mirror of https://github.com/OpenTTD/OpenTTD
(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)release/0.4.5
parent
c77e9231ef
commit
aa261049f4
|
@ -24,7 +24,7 @@ On BeOS, run ./configure and then use jam. There are a variaty of options you ca
|
|||
On Windows, insert your "Transport Tycoon Deluxe for Windows 95" disk. You can use a DOS version, but your graphics will be purple. NB: Even if your version of Transport Tycoon Deluxe ran on Windows 95, it may still be the DOS version. Then run the OpenTTD installer.
|
||||
|
||||
On UNIX platforms; decompress your OpenTTD archive, or otherwise run the installer. You should be left with an OpenTTD directory on your system. In this directory, make a subdirectory called 'data', and into this place the sample.cat file and all the .grf files from the install CD of 'Transport Tycoon Deluxe for Windows 95".
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. Those filenames have to be uppercase to be detected correctly. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
If you want MIDI music, copy the 'gm' folder from the original game directory/CD to the OpenTTD folder.
|
||||
|
||||
|
|
|
@ -19,6 +19,6 @@ trghr.grf
|
|||
trgir.grf
|
||||
trgtr.grf
|
||||
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. Those filenames have to be uppercase to be detected correctly. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
You should also use the data folder to add any custom grf files if you like
|
|
@ -39,7 +39,7 @@ Copy the following files from Transport Tycoon Deluxe to openttd/data/
|
|||
trgir.grf
|
||||
trgtr.grf
|
||||
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. Those filenames have to be uppercase to be detected correctly. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
|
||||
|
||||
|
||||
4.) Compiling and running:
|
||||
|
|
|
@ -92,10 +92,9 @@ trgir.grf
|
|||
trgtr.grf
|
||||
|
||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF,
|
||||
TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. Those filenames have to be uppercase
|
||||
to be detected correctly. A few minor graphical glitches with the DOS
|
||||
graphics remain. E.g. the autorail button in the rail toolbar doesn't look
|
||||
as nice as with the Windows graphics.)
|
||||
TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with
|
||||
the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't
|
||||
look as nice as with the Windows graphics.)
|
||||
|
||||
If you want music you need to copy the gm/ folder from Windows TTD into your
|
||||
OpenTTD folder, not your data folder.
|
||||
|
|
149
spritecache.c
149
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 */
|
||||
|
||||
/* 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 @@ 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");
|
||||
|
|
|
@ -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} };
|
2
ttd.c
2
ttd.c
|
@ -545,6 +545,7 @@ void LoadIntroGame()
|
|||
}
|
||||
|
||||
extern void DedicatedFork(void);
|
||||
extern void CheckExternalFiles();
|
||||
|
||||
int ttd_main(int argc, char* argv[])
|
||||
{
|
||||
|
@ -638,6 +639,7 @@ int ttd_main(int argc, char* argv[])
|
|||
}
|
||||
|
||||
DeterminePaths();
|
||||
CheckExternalFiles();
|
||||
|
||||
#ifdef UNIX
|
||||
// We must fork here, or we'll end up without some resources we need (like sockets)
|
||||
|
|
Loading…
Reference in New Issue