spritecache.c
changeset 961 26fdd7e62075
parent 884 9750c41c5860
child 962 c1de16d93e46
equal deleted inserted replaced
960:5dad48857cd2 961:26fdd7e62075
     1 #include "stdafx.h"
     1 #include "stdafx.h"
     2 #include "ttd.h"
     2 #include "ttd.h"
     3 #include "gfx.h"
     3 #include "gfx.h"
     4 #include "fileio.h"
     4 #include "fileio.h"
     5 #include "newgrf.h"
     5 #include "newgrf.h"
       
     6 #include "md5.h"
     6 #include <ctype.h>
     7 #include <ctype.h>
     7 
     8 
     8 #define SPRITECACHE_ID 0xF00F0006
     9 #define SPRITECACHE_ID 0xF00F0006
     9 #define SPRITE_CACHE_SIZE 1024*1024
    10 #define SPRITE_CACHE_SIZE 1024*1024
    10 
    11 
    53 static uint _sprite_lru_counter;
    54 static uint _sprite_lru_counter;
    54 static byte *_spritecache_ptr;
    55 static byte *_spritecache_ptr;
    55 static uint32 _spritecache_size;
    56 static uint32 _spritecache_size;
    56 static int _compact_cache_counter;
    57 static int _compact_cache_counter;
    57 
    58 
       
    59 typedef struct MD5File {
       
    60 	const char * const filename;     // filename
       
    61 	const md5_byte_t const hash[16]; // md5 sum of the file
       
    62 } MD5File;
       
    63 
    58 typedef struct FileList {
    64 typedef struct FileList {
    59 	const char * const basic[4];     // grf files that always have to be loaded
    65 	const MD5File basic[4];     // grf files that always have to be loaded
    60 	const char * const landscape[3]; // landscape specific grf files
    66 	const MD5File landscape[3]; // landscape specific grf files
    61 } FileList;
    67 } FileList;
    62 
    68 
    63 FileList files_dos = {
    69 #include "table/files.h"
    64 	{	"TRG1.GRF",
       
    65 		"TRGI.GRF",
       
    66 		"signalsw.grf", //0x1320 - 0x1405 inclusive
       
    67 		NULL },
       
    68 	{	"TRGC.GRF",
       
    69 		"TRGH.GRF",
       
    70 		"TRGT.GRF" },
       
    71 };
       
    72 
       
    73 FileList files_win = {
       
    74 	{	"TRG1R.GRF",
       
    75 		"TRGIR.GRF",
       
    76 		"signalsw.grf", //0x1320 - 0x1405 inclusive
       
    77 		NULL },
       
    78 	{	"TRGCR.GRF",
       
    79 		"TRGHR.GRF",
       
    80 		"TRGTR.GRF" },
       
    81 };
       
    82 
       
    83 #include "table/landscape_sprite.h"
    70 #include "table/landscape_sprite.h"
    84 
    71 
    85 static const uint16 * const _landscape_spriteindexes[] = {
    72 static const uint16 * const _landscape_spriteindexes[] = {
    86 	_landscape_spriteindexes_1,
    73 	_landscape_spriteindexes_1,
    87 	_landscape_spriteindexes_2,
    74 	_landscape_spriteindexes_2,
   756 	634, 634, // nordic char: Ø
   743 	634, 634, // nordic char: Ø
   757 	SPR_OPENTTD_BASE+62, SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT, // more icons
   744 	SPR_OPENTTD_BASE+62, SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT, // more icons
   758 	0xffff,
   745 	0xffff,
   759 };
   746 };
   760 
   747 
   761 
   748 /* FUNCTIONS FOR CHECKING MD5 SUMS OF GRF FILES */
   762 /* Checks, if either the Windows files exist (TRG1R.GRF) or the DOS files (TRG1.GRF).
   749 
   763  * _use_dos_palette is set accordingly
   750 /* Check that the supplied MD5 hash matches that stored for the supplied filename */
   764  * WARNING! This is case-sensitive, therefore the file has to be uppercase for correct
   751 static bool CheckMD5Digest(const MD5File file, md5_byte_t *digest, bool warn)
   765  * detection. If neither are found, Windows palette is assumed. */
   752 {
   766 static void CheckGrfFile()
   753 	int i, matching_bytes=0;
       
   754 
       
   755 	/* Loop through each byte of the file MD5 and the stored MD5... */
       
   756 	for (i = 0; i < 16; i++)
       
   757 	{
       
   758 		if (file.hash[i] == digest[i])
       
   759 			matching_bytes++;
       
   760 	};
       
   761 
       
   762 		/* If all bytes of the MD5's match (i.e. the MD5's match)... */
       
   763 	if (matching_bytes == 16) {
       
   764 		return true;
       
   765 	} else {
       
   766 		if (warn) printf("MD5 of %s is ****INCORRECT**** - File Corrupt.\n", file.filename);
       
   767 		return false;
       
   768 	};
       
   769 }
       
   770 
       
   771 /* Calculate and check the MD5 hash of the supplied filename. 
       
   772  * returns true if the checksum is correct */
       
   773 static bool FileMD5(const MD5File file, bool warn)
   767 {
   774 {
   768 	FILE *f;
   775 	FILE *f;
       
   776 	char buf[MAX_PATH];
   769 	byte *s;
   777 	byte *s;
   770 
   778 
   771 	s = str_fmt("%s%s", _path.data_dir, files_win.basic[0]);
   779 	md5_state_t filemd5state;
   772 	f = fopen(s, "r");
   780 	int len=0;
       
   781 	md5_byte_t buffer[1024], digest[16];
       
   782 
       
   783 	// open file
       
   784 	sprintf(buf, "%s%s", _path.data_dir, file.filename);
       
   785 	f = fopen(buf, "rb");
       
   786 
       
   787 #if !defined(WIN32)
       
   788 	if (f == NULL) {
       
   789 	// make lower case and check again
       
   790 		for (s=buf + strlen(_path.data_dir) - 1; *s != 0; s++)
       
   791 			*s = tolower(*s);
       
   792 		f = fopen(buf, "rb");
       
   793 	}
       
   794 #endif
       
   795 
   773 	if (f != NULL) {
   796 	if (f != NULL) {
       
   797 		md5_init(&filemd5state);
       
   798 		while ( (len = fread (buffer, 1, 1024, f)) )
       
   799 			md5_append(&filemd5state, buffer, len);
       
   800 
       
   801 		if (ferror(f))
       
   802 			if (warn) printf ("Error Reading from %s \n", buf);
       
   803 		fclose(f);
       
   804   
       
   805 		md5_finish(&filemd5state, digest);
       
   806 	  return CheckMD5Digest(file, digest, warn);
       
   807 	} else { // file not found
       
   808 		return false;
       
   809 	}	
       
   810 }
       
   811 
       
   812 /* Checks, if either the Windows files exist (TRG1R.GRF) or the DOS files (TRG1.GRF)
       
   813  * by comparing the MD5 checksums of the files. _use_dos_palette is set accordingly.
       
   814  * If neither are found, Windows palette is assumed. 
       
   815  *
       
   816  * (Note: Also checks sample.cat for corruption) */
       
   817 void CheckExternalFiles()
       
   818 {
       
   819 	int i;
       
   820 	int dos=0, win=0; // count of files from this version
       
   821 
       
   822 	for (i=0; i<2; i++)
       
   823 	  if ( FileMD5(files_dos.basic[i], true) )
       
   824 			dos++;
       
   825 	for (i=0; i<3; i++)
       
   826 	  if ( FileMD5(files_dos.landscape[i], true) )
       
   827 			dos++;
       
   828 
       
   829 	for (i=0; i<2; i++)
       
   830 	  if ( FileMD5(files_win.basic[i], true) )
       
   831 			win++;
       
   832 	for (i=0; i<3; i++)
       
   833 	  if ( FileMD5(files_win.landscape[i], true) )
       
   834 			win++;
       
   835 
       
   836 	if ( !FileMD5(sample_cat_win, false) && !FileMD5(sample_cat_dos, false) )
       
   837 		printf("Your sample.cat file is corrupted or missing!");
       
   838 
       
   839 	if (win == 5) {       // always use the Windows palette if all Windows files are present
   774 		_use_dos_palette = false;
   840 		_use_dos_palette = false;
   775 		return;
   841 	} else if (dos == 5) { // else use the DOS palette if all DOS files are present
   776 	}
       
   777 
       
   778 	s = str_fmt("%s%s", _path.data_dir, files_dos.basic[0]);
       
   779 	f = fopen(s, "r");
       
   780 	if (f != NULL) {
       
   781 		_use_dos_palette = true;
   842 		_use_dos_palette = true;
   782 		return;
   843 	} else {							// some files are missing, regardless of palette. Use Windows
       
   844 		_use_dos_palette = false;
   783 	}
   845 	}
   784 }
   846 }
   785 
   847 
   786 static void LoadSpriteTables()
   848 static void LoadSpriteTables()
   787 {
   849 {
   799 	 * TODO:
   861 	 * TODO:
   800 	 *   I think we can live entirely without Indexed GRFs, but I have to
   862 	 *   I think we can live entirely without Indexed GRFs, but I have to
   801 	 *   invest that further. --octo
   863 	 *   invest that further. --octo
   802 	 */
   864 	 */
   803 
   865 
   804 	// Check if we have the DOS or Windows version of the GRF files
       
   805 	CheckGrfFile();
       
   806 
       
   807 	files = _use_dos_palette?(&files_dos):(&files_win);
   866 	files = _use_dos_palette?(&files_dos):(&files_win);
   808 
   867 
   809 	// Try to load the sprites from cache
   868 	// Try to load the sprites from cache
   810 	if (!HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], true)) {
   869 	if (!HandleCachedSpriteHeaders(_cached_filenames[_opt.landscape], true)) {
   811 		// We do not have the sprites in cache yet, or cache is disabled
   870 		// We do not have the sprites in cache yet, or cache is disabled
   812 		// So just load all files from disk..
   871 		// So just load all files from disk..
   813 
   872 
   814 		int load_index = 0;
   873 		int load_index = 0;
   815 
   874 
   816 		for(i=0; files->basic[i] != NULL; i++) {
   875 		for(i=0; files->basic[i].filename != NULL; i++) {
   817 			load_index += LoadGrfFile(files->basic[i], load_index, (byte)i);
   876 			load_index += LoadGrfFile(files->basic[i].filename, load_index, (byte)i);
   818 		}
   877 		}
   819 
   878 
   820 		LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++);
   879 		LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++);
   821 
   880 
   822 		if (_sprite_page_to_load != 0)
   881 		if (_sprite_page_to_load != 0)
   823 			LoadGrfIndexed(files->landscape[_sprite_page_to_load-1], _landscape_spriteindexes[_sprite_page_to_load-1], i++);
   882 			LoadGrfIndexed(files->landscape[_sprite_page_to_load-1].filename, _landscape_spriteindexes[_sprite_page_to_load-1], i++);
   824 
   883 
   825 		LoadGrfIndexed("trkfoundw.grf", _slopes_spriteindexes[_opt.landscape], i++);
   884 		LoadGrfIndexed("trkfoundw.grf", _slopes_spriteindexes[_opt.landscape], i++);
   826 
   885 
   827 		load_index = SPR_CANALS_BASE;
   886 		load_index = SPR_CANALS_BASE;
   828 		load_index += LoadGrfFile("canalsw.grf", load_index, i++);
   887 		load_index += LoadGrfFile("canalsw.grf", load_index, i++);
   856 		//  open it can not read. So all files that are in the 'if'-section
   915 		//  open it can not read. So all files that are in the 'if'-section
   857 		//  above should also be in this 'else'-section.
   916 		//  above should also be in this 'else'-section.
   858 		//
   917 		//
   859 		// NOTE: the order of the files must be identical as in the section above!!
   918 		// NOTE: the order of the files must be identical as in the section above!!
   860 
   919 
   861 		for(i = 0; files->basic[i] != NULL; i++)
   920 		for(i = 0; files->basic[i].filename != NULL; i++)
   862 			FioOpenFile(i,files->basic[i]);
   921 			FioOpenFile(i,files->basic[i].filename);
   863 
   922 
   864 		FioOpenFile(i++, "openttd.grf");
   923 		FioOpenFile(i++, "openttd.grf");
   865 
   924 
   866 		if (_sprite_page_to_load != 0)
   925 		if (_sprite_page_to_load != 0)
   867 			FioOpenFile(i++, files->landscape[_sprite_page_to_load-1]);
   926 			FioOpenFile(i++, files->landscape[_sprite_page_to_load-1].filename);
   868 
   927 
   869 		FioOpenFile(i++, "trkfoundw.grf");
   928 		FioOpenFile(i++, "trkfoundw.grf");
   870 		FioOpenFile(i++, "canalsw.grf");
   929 		FioOpenFile(i++, "canalsw.grf");
   871 
   930 
   872 		// FIXME: if a user changes his newgrf's, the cached-sprites gets
   931 		// FIXME: if a user changes his newgrf's, the cached-sprites gets