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 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".
|
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.
|
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
|
trgir.grf
|
||||||
trgtr.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
|
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
|
trgir.grf
|
||||||
trgtr.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:
|
4.) Compiling and running:
|
||||||
|
|
|
@ -92,10 +92,9 @@ trgir.grf
|
||||||
trgtr.grf
|
trgtr.grf
|
||||||
|
|
||||||
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.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
|
TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with
|
||||||
to be detected correctly. A few minor graphical glitches with the DOS
|
the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't
|
||||||
graphics remain. E.g. the autorail button in the rail toolbar doesn't look
|
look as nice as with the Windows graphics.)
|
||||||
as nice as with the Windows graphics.)
|
|
||||||
|
|
||||||
If you want music you need to copy the gm/ folder from Windows TTD into your
|
If you want music you need to copy the gm/ folder from Windows TTD into your
|
||||||
OpenTTD folder, not your data folder.
|
OpenTTD folder, not your data folder.
|
||||||
|
|
149
spritecache.c
149
spritecache.c
|
@ -3,6 +3,7 @@
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "newgrf.h"
|
#include "newgrf.h"
|
||||||
|
#include "md5.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#define SPRITECACHE_ID 0xF00F0006
|
#define SPRITECACHE_ID 0xF00F0006
|
||||||
|
@ -55,31 +56,17 @@ static byte *_spritecache_ptr;
|
||||||
static uint32 _spritecache_size;
|
static uint32 _spritecache_size;
|
||||||
static int _compact_cache_counter;
|
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 {
|
typedef struct FileList {
|
||||||
const char * const basic[4]; // grf files that always have to be loaded
|
const MD5File basic[4]; // grf files that always have to be loaded
|
||||||
const char * const landscape[3]; // landscape specific grf files
|
const MD5File landscape[3]; // landscape specific grf files
|
||||||
} FileList;
|
} FileList;
|
||||||
|
|
||||||
FileList files_dos = {
|
#include "table/files.h"
|
||||||
{ "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/landscape_sprite.h"
|
#include "table/landscape_sprite.h"
|
||||||
|
|
||||||
static const uint16 * const _landscape_spriteindexes[] = {
|
static const uint16 * const _landscape_spriteindexes[] = {
|
||||||
|
@ -758,28 +745,103 @@ static const uint16 _openttd_grf_indexes[] = {
|
||||||
0xffff,
|
0xffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* FUNCTIONS FOR CHECKING MD5 SUMS OF GRF FILES */
|
||||||
|
|
||||||
/* Checks, if either the Windows files exist (TRG1R.GRF) or the DOS files (TRG1.GRF).
|
/* Check that the supplied MD5 hash matches that stored for the supplied filename */
|
||||||
* _use_dos_palette is set accordingly
|
static bool CheckMD5Digest(const MD5File file, md5_byte_t *digest, bool warn)
|
||||||
* WARNING! This is case-sensitive, therefore the file has to be uppercase for correct
|
{
|
||||||
* detection. If neither are found, Windows palette is assumed. */
|
int i, matching_bytes=0;
|
||||||
static void CheckGrfFile()
|
|
||||||
|
/* 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;
|
FILE *f;
|
||||||
|
char buf[MAX_PATH];
|
||||||
byte *s;
|
byte *s;
|
||||||
|
|
||||||
s = str_fmt("%s%s", _path.data_dir, files_win.basic[0]);
|
md5_state_t filemd5state;
|
||||||
f = fopen(s, "r");
|
int len=0;
|
||||||
if (f != NULL) {
|
md5_byte_t buffer[1024], digest[16];
|
||||||
_use_dos_palette = false;
|
|
||||||
return;
|
// 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) {
|
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;
|
_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
|
* 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);
|
files = _use_dos_palette?(&files_dos):(&files_win);
|
||||||
|
|
||||||
// Try to load the sprites from cache
|
// Try to load the sprites from cache
|
||||||
|
@ -813,14 +872,14 @@ static void LoadSpriteTables()
|
||||||
|
|
||||||
int load_index = 0;
|
int load_index = 0;
|
||||||
|
|
||||||
for(i=0; files->basic[i] != NULL; i++) {
|
for(i=0; files->basic[i].filename != NULL; i++) {
|
||||||
load_index += LoadGrfFile(files->basic[i], load_index, (byte)i);
|
load_index += LoadGrfFile(files->basic[i].filename, load_index, (byte)i);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++);
|
LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++);
|
||||||
|
|
||||||
if (_sprite_page_to_load != 0)
|
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++);
|
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!!
|
// NOTE: the order of the files must be identical as in the section above!!
|
||||||
|
|
||||||
for(i = 0; files->basic[i] != NULL; i++)
|
for(i = 0; files->basic[i].filename != NULL; i++)
|
||||||
FioOpenFile(i,files->basic[i]);
|
FioOpenFile(i,files->basic[i].filename);
|
||||||
|
|
||||||
FioOpenFile(i++, "openttd.grf");
|
FioOpenFile(i++, "openttd.grf");
|
||||||
|
|
||||||
if (_sprite_page_to_load != 0)
|
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++, "trkfoundw.grf");
|
||||||
FioOpenFile(i++, "canalsw.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 DedicatedFork(void);
|
||||||
|
extern void CheckExternalFiles();
|
||||||
|
|
||||||
int ttd_main(int argc, char* argv[])
|
int ttd_main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
@ -638,6 +639,7 @@ int ttd_main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
DeterminePaths();
|
DeterminePaths();
|
||||||
|
CheckExternalFiles();
|
||||||
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
// We must fork here, or we'll end up without some resources we need (like sockets)
|
// We must fork here, or we'll end up without some resources we need (like sockets)
|
||||||
|
|
Loading…
Reference in New Issue