--- a/spritecache.c Sun Jan 09 21:39:49 2005 +0000
+++ b/spritecache.c Mon Jan 10 01:14:26 2005 +0000
@@ -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 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 @@
0xffff,
};
+/* FUNCTIONS FOR CHECKING MD5 SUMS OF GRF FILES */
-/* 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()
+/* 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++;
+ };
+
+ /* 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 @@
* 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 @@
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 @@
//
// 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");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/table/files.h Mon Jan 10 01:14:26 2005 +0000
@@ -0,0 +1,51 @@
+/*
+ MD5 sums of graphics files
+
+ DOS -
+
+ TRG1.GRF 9311676280e5b14077a8ee41c1b42192
+ TRGC.GRF ed446637e034104c5559b32c18afe78d
+ TRGH.GRF ee6616fb0e6ef6b24892c58c93d86fc9
+ TRGI.GRF da6a6c9dcc451eec88d79211437b76a8
+ TRGT.GRF fcde1d7e8a74197d72a62695884b909e
+ SAMPLE.CAT 422ea3dd074d2859bb51639a6e0e85da
+
+ WINDOWS -
+
+ TRG1R.GRF b04ce593d8c5016e07473a743d7d3358
+ TRGCR.GRF 3668f410c761a050b5e7095a2b14879b
+ TRGHR.GRF 06bf2b7a31766f048baac2ebe43457b1
+ TRGIR.GRF 0c2484ff6be49fc63a83be6ab5c38f32
+ TRGTR.GRF de53650517fe661ceaa3138c6edb0eb8
+ SAMPLE.CAT 9212e81e72badd4bbe1eaeae66458e10
+*/
+
+
+FileList files_dos = {
+ {
+ { "TRG1.GRF", {0x93,0x11,0x67,0x62,0x80,0xe5,0xb1,0x40,0x77,0xa8,0xee,0x41,0xc1,0xb4,0x21,0x92} },
+ { "TRGI.GRF", {0xda,0x6a,0x6c,0x9d,0xcc,0x45,0x1e,0xec,0x88,0xd7,0x92,0x11,0x43,0x7b,0x76,0xa8} },
+ { "signalsw.grf", {0x76,0x1b,0x42,0x25,0x44,0x0d,0x21,0xc7,0xe0,0xb4,0x25,0xd8,0x2f,0xc8,0x52,0x38} }, //0x1320 - 0x1405 inclusive
+ { NULL }
+ },
+ { { "TRGC.GRF", {0xed,0x44,0x66,0x37,0xe0,0x34,0x10,0x4c,0x55,0x59,0xb3,0x2c,0x18,0xaf,0xe7,0x8d} },
+ { "TRGH.GRF", {0xee,0x66,0x16,0xfb,0x0e,0x6e,0xf6,0xb2,0x48,0x92,0xc5,0x8c,0x93,0xd8,0x6f,0xc9} },
+ { "TRGT.GRF", {0xfc,0xde,0x1d,0x7e,0x8a,0x74,0x19,0x7d,0x72,0xa6,0x26,0x95,0x88,0x4b,0x90,0x9e} }
+ }
+};
+
+FileList files_win = {
+ {
+ { "TRG1R.GRF", {0xb0,0x4c,0xe5,0x93,0xd8,0xc5,0x01,0x6e,0x07,0x47,0x3a,0x74,0x3d,0x7d,0x33,0x58} },
+ { "TRGIR.GRF", {0x0c,0x24,0x84,0xff,0x6b,0xe4,0x9f,0xc6,0x3a,0x83,0xbe,0x6a,0xb5,0xc3,0x8f,0x32} },
+ { "signalsw.grf", {0x76,0x1b,0x42,0x25,0x44,0x0d,0x21,0xc7,0xe0,0xb4,0x25,0xd8,0x2f,0xc8,0x52,0x38} }, //0x1320 - 0x1405 inclusive
+ { NULL }
+ },
+ { { "TRGCR.GRF", {0x36,0x68,0xf4,0x10,0xc7,0x61,0xa0,0x50,0xb5,0xe7,0x09,0x5a,0x2b,0x14,0x87,0x9b} },
+ { "TRGHR.GRF", {0x06,0xbf,0x2b,0x7a,0x31,0x76,0x6f,0x04,0x8b,0xaa,0xc2,0xeb,0xe4,0x34,0x57,0xb1} },
+ { "TRGTR.GRF", {0xde,0x53,0x65,0x05,0x17,0xfe,0x66,0x1c,0xea,0xa3,0x13,0x8c,0x6e,0xdb,0x0e,0xb8} }
+ }
+};
+
+static MD5File sample_cat_win = { "SAMPLE.CAT", {0x92,0x12,0xe8,0x1e,0x72,0xba,0xdd,0x4b,0xbe,0x1e,0xae,0xae,0x66,0x45,0x8e,0x10} };
+static MD5File sample_cat_dos = { "SAMPLE.CAT", {0x42,0x2e,0xa3,0xdd,0x07,0x4d,0x28,0x59,0xbb,0x51,0x63,0x9a,0x6e,0x0e,0x85,0xda} };