summaryrefslogtreecommitdiff
path: root/spritecache.c
diff options
context:
space:
mode:
authordominik <dominik@openttd.org>2005-01-10 01:14:26 +0000
committerdominik <dominik@openttd.org>2005-01-10 01:14:26 +0000
commitaa261049f4d3c0977555e413ab7d9807c70eef02 (patch)
treefe347108b7efcb5f55d1b2ad4f319e3710006c27 /spritecache.c
parentc77e9231efe6f362f3ddd8d059ee3a5e4d340cc5 (diff)
downloadopenttd-aa261049f4d3c0977555e413ab7d9807c70eef02.tar.xz
(svn r1453) Feature: MD5 hash check for TTD files
The original TTD files are now checked with a MD5 sum to determine which version of the grf files is used and to warn about possible file corruptions. (Thanks to ledow for the original patch)
Diffstat (limited to 'spritecache.c')
-rw-r--r--spritecache.c147
1 files changed, 103 insertions, 44 deletions
diff --git a/spritecache.c b/spritecache.c
index 8ea8b0411..758f09b4e 100644
--- a/spritecache.c
+++ b/spritecache.c
@@ -3,6 +3,7 @@
#include "gfx.h"
#include "fileio.h"
#include "newgrf.h"
+#include "md5.h"
#include <ctype.h>
#define SPRITECACHE_ID 0xF00F0006
@@ -55,31 +56,17 @@ static byte *_spritecache_ptr;
static uint32 _spritecache_size;
static int _compact_cache_counter;
+typedef struct MD5File {
+ const char * const filename; // filename
+ const md5_byte_t const hash[16]; // md5 sum of the file
+} MD5File;
+
typedef struct FileList {
- const char * const basic[4]; // grf files that always have to be loaded
- const char * const landscape[3]; // landscape specific grf files
+ const MD5File basic[4]; // grf files that always have to be loaded
+ const MD5File landscape[3]; // landscape specific grf files
} FileList;
-FileList files_dos = {
- { "TRG1.GRF",
- "TRGI.GRF",
- "signalsw.grf", //0x1320 - 0x1405 inclusive
- NULL },
- { "TRGC.GRF",
- "TRGH.GRF",
- "TRGT.GRF" },
-};
-
-FileList files_win = {
- { "TRG1R.GRF",
- "TRGIR.GRF",
- "signalsw.grf", //0x1320 - 0x1405 inclusive
- NULL },
- { "TRGCR.GRF",
- "TRGHR.GRF",
- "TRGTR.GRF" },
-};
-
+#include "table/files.h"
#include "table/landscape_sprite.h"
static const uint16 * const _landscape_spriteindexes[] = {
@@ -758,28 +745,103 @@ static const uint16 _openttd_grf_indexes[] = {
0xffff,
};
+/* FUNCTIONS FOR CHECKING MD5 SUMS OF GRF FILES */
+
+/* Check that the supplied MD5 hash matches that stored for the supplied filename */
+static bool CheckMD5Digest(const MD5File file, md5_byte_t *digest, bool warn)
+{
+ int i, matching_bytes=0;
+
+ /* Loop through each byte of the file MD5 and the stored MD5... */
+ for (i = 0; i < 16; i++)
+ {
+ if (file.hash[i] == digest[i])
+ matching_bytes++;
+ };
-/* Checks, if either the Windows files exist (TRG1R.GRF) or the DOS files (TRG1.GRF).
- * _use_dos_palette is set accordingly
- * WARNING! This is case-sensitive, therefore the file has to be uppercase for correct
- * detection. If neither are found, Windows palette is assumed. */
-static void CheckGrfFile()
+ /* If all bytes of the MD5's match (i.e. the MD5's match)... */
+ if (matching_bytes == 16) {
+ return true;
+ } else {
+ if (warn) printf("MD5 of %s is ****INCORRECT**** - File Corrupt.\n", file.filename);
+ return false;
+ };
+}
+
+/* Calculate and check the MD5 hash of the supplied filename.
+ * returns true if the checksum is correct */
+static bool FileMD5(const MD5File file, bool warn)
{
FILE *f;
+ char buf[MAX_PATH];
byte *s;
- s = str_fmt("%s%s", _path.data_dir, files_win.basic[0]);
- f = fopen(s, "r");
- if (f != NULL) {
- _use_dos_palette = false;
- return;
+ md5_state_t filemd5state;
+ int len=0;
+ md5_byte_t buffer[1024], digest[16];
+
+ // open file
+ sprintf(buf, "%s%s", _path.data_dir, file.filename);
+ f = fopen(buf, "rb");
+
+#if !defined(WIN32)
+ if (f == NULL) {
+ // make lower case and check again
+ for (s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
+ *s = tolower(*s);
+ f = fopen(buf, "rb");
}
+#endif
- s = str_fmt("%s%s", _path.data_dir, files_dos.basic[0]);
- f = fopen(s, "r");
if (f != NULL) {
+ md5_init(&filemd5state);
+ while ( (len = fread (buffer, 1, 1024, f)) )
+ md5_append(&filemd5state, buffer, len);
+
+ if (ferror(f))
+ if (warn) printf ("Error Reading from %s \n", buf);
+ fclose(f);
+
+ md5_finish(&filemd5state, digest);
+ return CheckMD5Digest(file, digest, warn);
+ } else { // file not found
+ return false;
+ }
+}
+
+/* Checks, if either the Windows files exist (TRG1R.GRF) or the DOS files (TRG1.GRF)
+ * by comparing the MD5 checksums of the files. _use_dos_palette is set accordingly.
+ * If neither are found, Windows palette is assumed.
+ *
+ * (Note: Also checks sample.cat for corruption) */
+void CheckExternalFiles()
+{
+ int i;
+ int dos=0, win=0; // count of files from this version
+
+ for (i=0; i<2; i++)
+ if ( FileMD5(files_dos.basic[i], true) )
+ dos++;
+ for (i=0; i<3; i++)
+ if ( FileMD5(files_dos.landscape[i], true) )
+ dos++;
+
+ for (i=0; i<2; i++)
+ if ( FileMD5(files_win.basic[i], true) )
+ win++;
+ for (i=0; i<3; i++)
+ if ( FileMD5(files_win.landscape[i], true) )
+ win++;
+
+ if ( !FileMD5(sample_cat_win, false) && !FileMD5(sample_cat_dos, false) )
+ printf("Your sample.cat file is corrupted or missing!");
+
+ if (win == 5) { // always use the Windows palette if all Windows files are present
+ _use_dos_palette = false;
+ } else if (dos == 5) { // else use the DOS palette if all DOS files are present
_use_dos_palette = true;
- return;
+ } else { // some files are missing, regardless of palette. Use Windows
+ _use_dos_palette = false;
}
}
@@ -801,9 +863,6 @@ static void LoadSpriteTables()
* invest that further. --octo
*/
- // Check if we have the DOS or Windows version of the GRF files
- CheckGrfFile();
-
files = _use_dos_palette?(&files_dos):(&files_win);
// Try to load the sprites from cache
@@ -813,14 +872,14 @@ static void LoadSpriteTables()
int load_index = 0;
- for(i=0; files->basic[i] != NULL; i++) {
- load_index += LoadGrfFile(files->basic[i], load_index, (byte)i);
+ for(i=0; files->basic[i].filename != NULL; i++) {
+ load_index += LoadGrfFile(files->basic[i].filename, load_index, (byte)i);
}
LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++);
if (_sprite_page_to_load != 0)
- LoadGrfIndexed(files->landscape[_sprite_page_to_load-1], _landscape_spriteindexes[_sprite_page_to_load-1], i++);
+ LoadGrfIndexed(files->landscape[_sprite_page_to_load-1].filename, _landscape_spriteindexes[_sprite_page_to_load-1], i++);
LoadGrfIndexed("trkfoundw.grf", _slopes_spriteindexes[_opt.landscape], i++);
@@ -858,13 +917,13 @@ static void LoadSpriteTables()
//
// NOTE: the order of the files must be identical as in the section above!!
- for(i = 0; files->basic[i] != NULL; i++)
- FioOpenFile(i,files->basic[i]);
+ for(i = 0; files->basic[i].filename != NULL; i++)
+ FioOpenFile(i,files->basic[i].filename);
FioOpenFile(i++, "openttd.grf");
if (_sprite_page_to_load != 0)
- FioOpenFile(i++, files->landscape[_sprite_page_to_load-1]);
+ FioOpenFile(i++, files->landscape[_sprite_page_to_load-1].filename);
FioOpenFile(i++, "trkfoundw.grf");
FioOpenFile(i++, "canalsw.grf");