src/gfxinit.c
branchcustombridgeheads
changeset 5643 3778051e8095
parent 5568 75f13d7bfaed
child 5645 72ebd9e4cd64
equal deleted inserted replaced
5642:bfa6074e2833 5643:3778051e8095
       
     1 /* $Id$ */
       
     2 
       
     3 #include "stdafx.h"
       
     4 #include "openttd.h"
       
     5 #include "debug.h"
       
     6 #include "functions.h"
       
     7 #include "gfx.h"
       
     8 #include "gfxinit.h"
       
     9 #include "spritecache.h"
       
    10 #include "table/sprites.h"
       
    11 #include "fileio.h"
       
    12 #include "string.h"
       
    13 #include "newgrf.h"
       
    14 #include "md5.h"
       
    15 #include "variables.h"
       
    16 #include "fontcache.h"
       
    17 #include <string.h>
       
    18 
       
    19 typedef struct MD5File {
       
    20 	const char * const filename;     // filename
       
    21 	const md5_byte_t hash[16]; // md5 sum of the file
       
    22 } MD5File;
       
    23 
       
    24 typedef struct FileList {
       
    25 	const MD5File basic[4];     // grf files that always have to be loaded
       
    26 	const MD5File landscape[3]; // landscape specific grf files
       
    27 } FileList;
       
    28 
       
    29 enum {
       
    30 	SKIP = 0xFFFE,
       
    31 	END  = 0xFFFF
       
    32 };
       
    33 
       
    34 #include "table/files.h"
       
    35 #include "table/landscape_sprite.h"
       
    36 
       
    37 static const SpriteID * const _landscape_spriteindexes[] = {
       
    38 	_landscape_spriteindexes_1,
       
    39 	_landscape_spriteindexes_2,
       
    40 	_landscape_spriteindexes_3,
       
    41 };
       
    42 
       
    43 static const SpriteID * const _slopes_spriteindexes[] = {
       
    44 	_slopes_spriteindexes_0,
       
    45 	_slopes_spriteindexes_1,
       
    46 	_slopes_spriteindexes_2,
       
    47 	_slopes_spriteindexes_3,
       
    48 };
       
    49 
       
    50 
       
    51 static uint LoadGrfFile(const char* filename, uint load_index, int file_index)
       
    52 {
       
    53 	uint load_index_org = load_index;
       
    54 
       
    55 	FioOpenFile(file_index, filename);
       
    56 
       
    57 	DEBUG(sprite, 2, "Reading grf-file '%s'", filename);
       
    58 
       
    59 	while (LoadNextSprite(load_index, file_index)) {
       
    60 		load_index++;
       
    61 		if (load_index >= MAX_SPRITES) {
       
    62 			error("Too many sprites. Recompile with higher MAX_SPRITES value or remove some custom GRF files.");
       
    63 		}
       
    64 	}
       
    65 	DEBUG(sprite, 2, "Currently %i sprites are loaded", load_index);
       
    66 
       
    67 	return load_index - load_index_org;
       
    68 }
       
    69 
       
    70 
       
    71 static void LoadGrfIndexed(const char* filename, const SpriteID* index_tbl, int file_index)
       
    72 {
       
    73 	uint start;
       
    74 
       
    75 	FioOpenFile(file_index, filename);
       
    76 
       
    77 	DEBUG(sprite, 2, "Reading indexed grf-file '%s'", filename);
       
    78 
       
    79 	while ((start = *index_tbl++) != END) {
       
    80 		uint end = *index_tbl++;
       
    81 
       
    82 		if (start == SKIP) { // skip sprites (amount in second var)
       
    83 			SkipSprites(end);
       
    84 		} else { // load sprites and use indexes from start to end
       
    85 			do {
       
    86 			#ifdef NDEBUG
       
    87 				LoadNextSprite(start, file_index);
       
    88 			#else
       
    89 				bool b = LoadNextSprite(start, file_index);
       
    90 				assert(b);
       
    91 			#endif
       
    92 			} while (++start <= end);
       
    93 		}
       
    94 	}
       
    95 }
       
    96 
       
    97 
       
    98 /* Check that the supplied MD5 hash matches that stored for the supplied filename */
       
    99 static bool CheckMD5Digest(const MD5File file, md5_byte_t *digest, bool warn)
       
   100 {
       
   101 	if (memcmp(file.hash, digest, sizeof(file.hash)) == 0) return true;
       
   102 	if (warn) fprintf(stderr, "MD5 of %s is ****INCORRECT**** - File Corrupt.\n", file.filename);
       
   103 	return false;
       
   104 }
       
   105 
       
   106 /* Calculate and check the MD5 hash of the supplied filename.
       
   107  * returns true if the checksum is correct */
       
   108 static bool FileMD5(const MD5File file, bool warn)
       
   109 {
       
   110 	FILE *f;
       
   111 	char buf[MAX_PATH];
       
   112 
       
   113 	// open file
       
   114 	snprintf(buf, lengthof(buf), "%s%s", _paths.data_dir, file.filename);
       
   115 	f = fopen(buf, "rb");
       
   116 
       
   117 #if !defined(WIN32)
       
   118 	if (f == NULL) {
       
   119 		strtolower(buf + strlen(_paths.data_dir) - 1);
       
   120 		f = fopen(buf, "rb");
       
   121 	}
       
   122 #endif
       
   123 
       
   124 	if (f != NULL) {
       
   125 		md5_state_t filemd5state;
       
   126 		md5_byte_t buffer[1024];
       
   127 		md5_byte_t digest[16];
       
   128 		size_t len;
       
   129 
       
   130 		md5_init(&filemd5state);
       
   131 		while ((len = fread(buffer, 1, sizeof(buffer), f)) != 0)
       
   132 			md5_append(&filemd5state, buffer, len);
       
   133 
       
   134 		if (ferror(f) && warn) fprintf(stderr, "Error Reading from %s \n", buf);
       
   135 		fclose(f);
       
   136 
       
   137 		md5_finish(&filemd5state, digest);
       
   138 		return CheckMD5Digest(file, digest, warn);
       
   139 	} else { // file not found
       
   140 		return false;
       
   141 	}
       
   142 }
       
   143 
       
   144 /* Checks, if either the Windows files exist (TRG1R.GRF) or the DOS files (TRG1.GRF)
       
   145  * by comparing the MD5 checksums of the files. _use_dos_palette is set accordingly.
       
   146  * If neither are found, Windows palette is assumed.
       
   147  *
       
   148  * (Note: Also checks sample.cat for corruption) */
       
   149 void CheckExternalFiles(void)
       
   150 {
       
   151 	uint i;
       
   152 	// count of files from this version
       
   153 	uint dos = 0;
       
   154 	uint win = 0;
       
   155 
       
   156 	for (i = 0; i < 2; i++) if (FileMD5(files_dos.basic[i], true)) dos++;
       
   157 	for (i = 0; i < 3; i++) if (FileMD5(files_dos.landscape[i], true)) dos++;
       
   158 
       
   159 	for (i = 0; i < 2; i++) if (FileMD5(files_win.basic[i], true)) win++;
       
   160 	for (i = 0; i < 3; i++) if (FileMD5(files_win.landscape[i], true)) win++;
       
   161 
       
   162 	if (!FileMD5(sample_cat_win, false) && !FileMD5(sample_cat_dos, false))
       
   163 		fprintf(stderr, "Your sample.cat file is corrupted or missing!\n");
       
   164 
       
   165 	for (i = 0; i < lengthof(files_openttd); i++) {
       
   166 		if (!FileMD5(files_openttd[i], false)) {
       
   167 			fprintf(stderr, "Your %s file is corrupted or missing!\n", files_openttd[i].filename);
       
   168 		}
       
   169 	}
       
   170 
       
   171 	/*
       
   172 	 * forced DOS palette via command line -> leave it that way
       
   173 	 * all Windows files present -> Windows palette
       
   174 	 * all DOS files present -> DOS palette
       
   175 	 * no Windows files present and any DOS file present -> DOS palette
       
   176 	 * otherwise -> Windows palette
       
   177 	 */
       
   178 	if (_use_dos_palette) {
       
   179 		return;
       
   180 	} else if (win == 5) {
       
   181 		_use_dos_palette = false;
       
   182 	} else if (dos == 5 || (win == 0 && dos > 0)) {
       
   183 		_use_dos_palette = true;
       
   184 	} else {
       
   185 		_use_dos_palette = false;
       
   186 	}
       
   187 }
       
   188 
       
   189 
       
   190 static const SpriteID trg1idx[] = {
       
   191 	   0,    1, // Mouse cursor, ZZZ
       
   192 /* Medium font */
       
   193 	   2,   92, // ' ' till 'z'
       
   194 	SKIP,   36,
       
   195 	 160,  160, // Move ¾ to the correct position
       
   196 	  98,   98, // Up arrow
       
   197 	 131,  133,
       
   198 	SKIP,    1, // skip currency sign
       
   199 	 135,  135,
       
   200 	SKIP,    1,
       
   201 	 137,  137,
       
   202 	SKIP,    1,
       
   203 	 139,  139,
       
   204 	 140,  140, // TODO Down arrow
       
   205 	 141,  141,
       
   206 	 142,  142, // TODO Check mark
       
   207 	 143,  143, // TODO Cross
       
   208 	 144,  144,
       
   209 	 145,  145, // TODO Right arrow
       
   210 	 146,  149,
       
   211 	 118,  122, // Transport markers
       
   212 	SKIP,    2,
       
   213 	 157,  157,
       
   214 	 114,  115, // Small up/down arrows
       
   215 	SKIP,    1,
       
   216 	 161,  225,
       
   217 /* Small font */
       
   218 	 226,  316, // ' ' till 'z'
       
   219 	SKIP,   36,
       
   220 	 384,  384, // Move ¾ to the correct position
       
   221 	 322,  322, // Up arrow
       
   222 	 355,  357,
       
   223 	SKIP,    1, // skip currency sign
       
   224 	 359,  359,
       
   225 	SKIP,    1,
       
   226 	 361,  361,
       
   227 	SKIP,    1,
       
   228 	 363,  363,
       
   229 	 364,  364, // TODO Down arrow
       
   230 	 365,  366,
       
   231 	SKIP,    1,
       
   232 	 368,  368,
       
   233 	 369,  369, // TODO Right arrow
       
   234 	 370,  373,
       
   235 	SKIP,    7,
       
   236 	 381,  381,
       
   237 	SKIP,    3,
       
   238 	 385,  449,
       
   239 /* Big font */
       
   240 	 450,  540, // ' ' till 'z'
       
   241 	SKIP,   36,
       
   242 	 608,  608, // Move ¾ to the correct position
       
   243 	SKIP,    1,
       
   244 	 579,  581,
       
   245 	SKIP,    1,
       
   246 	 583,  583,
       
   247 	SKIP,    5,
       
   248 	 589,  589,
       
   249 	SKIP,   15,
       
   250 	 605,  605,
       
   251 	SKIP,    3,
       
   252 	 609,  625,
       
   253 	SKIP,    1,
       
   254 	 627,  632,
       
   255 	SKIP,    1,
       
   256 	 634,  639,
       
   257 	SKIP,    1,
       
   258 	 641,  657,
       
   259 	SKIP,    1,
       
   260 	 659,  664,
       
   261 	SKIP,    2,
       
   262 	 667,  671,
       
   263 	SKIP,    1,
       
   264 	 673,  673,
       
   265 /* Graphics */
       
   266 	 674, 4792,
       
   267 	END
       
   268 };
       
   269 
       
   270 /* NOTE: When adding a normal sprite, increase OPENTTD_SPRITES_COUNT with the
       
   271  * amount of sprites and add them to the end of the list, with the index of
       
   272  * the old sprite-count offset from SPR_OPENTTD_BASE. With this there is no
       
   273  * correspondence of any kind with the ID's in the grf file, but results in
       
   274  * a maximum use of sprite slots. */
       
   275 static const SpriteID _openttd_grf_indexes[] = {
       
   276 	SPR_IMG_AUTORAIL, SPR_CURSOR_WAYPOINT, // icons etc
       
   277 	134, 134,  // euro symbol medium size
       
   278 	582, 582,  // euro symbol large size
       
   279 	358, 358,  // euro symbol tiny
       
   280 	SPR_CURSOR_CANAL, SPR_IMG_FASTFORWARD, // more icons
       
   281 	648, 648, // nordic char: æ
       
   282 	616, 616, // nordic char: Æ
       
   283 	666, 666, // nordic char: ø
       
   284 	634, 634, // nordic char: Ø
       
   285 	SPR_PIN_UP, SPR_CURSOR_CLONE_TRAIN, // more icons
       
   286 	382, 383, // ¼ ½ tiny
       
   287 	158, 159, // ¼ ½ medium
       
   288 	606, 607, // ¼ ½ large
       
   289 	360, 360, // ¦ tiny
       
   290 	362, 362, // ¨ tiny
       
   291 	136, 136, // ¦ medium
       
   292 	138, 138, // ¨ medium
       
   293 	584, 584, // ¦ large
       
   294 	586, 586, // ¨ large
       
   295 	626, 626, // Ð large
       
   296 	658, 658, // ð large
       
   297 	374, 374, // ´ tiny
       
   298 	378, 378, // ¸ tiny
       
   299 	150, 150, // ´ medium
       
   300 	154, 154, // ¸ medium
       
   301 	598, 598, // ´ large
       
   302 	602, 602, // ¸ large
       
   303 	640, 640, // Þ large
       
   304 	672, 672, // þ large
       
   305 	380, 380, // º tiny
       
   306 	156, 156, // º medium
       
   307 	604, 604, // º large
       
   308 	317, 320, // { | } ~ tiny
       
   309 	 93,  96, // { | } ~ medium
       
   310 	541, 544, // { | } ~ large
       
   311 	SPR_HOUSE_ICON, SPR_HOUSE_ICON,
       
   312 	585, 585, // § large
       
   313 	587, 587, // © large
       
   314 	592, 592, // ® large
       
   315 	594, 597, // ° ± ² ³ large
       
   316 	633, 633, // × large
       
   317 	665, 665, // ÷ large
       
   318 	SPR_SELL_TRAIN, SPR_SHARED_ORDERS_ICON,
       
   319 	377, 377, // · small
       
   320 	153, 153, // · medium
       
   321 	601, 601, // · large
       
   322 	END
       
   323 };
       
   324 
       
   325 
       
   326 static void LoadSpriteTables(void)
       
   327 {
       
   328 	const FileList* files = _use_dos_palette ? &files_dos : &files_win;
       
   329 	uint load_index;
       
   330 	uint i;
       
   331 
       
   332 	LoadGrfIndexed(files->basic[0].filename, trg1idx, 0);
       
   333 	DupSprite(  2, 130); // non-breaking space medium
       
   334 	DupSprite(226, 354); // non-breaking space tiny
       
   335 	DupSprite(450, 578); // non-breaking space large
       
   336 	load_index = 4793;
       
   337 
       
   338 	for (i = 1; files->basic[i].filename != NULL; i++) {
       
   339 		load_index += LoadGrfFile(files->basic[i].filename, load_index, i);
       
   340 	}
       
   341 
       
   342 	/* Load additional sprites for climates other than temperate */
       
   343 	if (_opt.landscape != LT_NORMAL) {
       
   344 		LoadGrfIndexed(
       
   345 			files->landscape[_opt.landscape - 1].filename,
       
   346 			_landscape_spriteindexes[_opt.landscape - 1],
       
   347 			i++
       
   348 		);
       
   349 	}
       
   350 
       
   351 	assert(load_index == SPR_SIGNALS_BASE);
       
   352 	load_index += LoadGrfFile("nsignalsw.grf", load_index, i++);
       
   353 
       
   354 	assert(load_index == SPR_CANALS_BASE);
       
   355 	load_index += LoadGrfFile("canalsw.grf", load_index, i++);
       
   356 
       
   357 	assert(load_index == SPR_SLOPES_BASE);
       
   358 	LoadGrfIndexed("trkfoundw.grf", _slopes_spriteindexes[_opt.landscape], i++);
       
   359 
       
   360 	load_index = SPR_AUTORAIL_BASE;
       
   361 	load_index += LoadGrfFile("autorail.grf", load_index, i++);
       
   362 
       
   363 	assert(load_index == SPR_ELRAIL_BASE);
       
   364 	load_index += LoadGrfFile("elrailsw.grf", load_index, i++);
       
   365 
       
   366 	assert(load_index == SPR_2CCMAP_BASE);
       
   367 	load_index += LoadGrfFile("2ccmap.grf", load_index, i++);
       
   368 
       
   369 	assert(load_index == SPR_OPENTTD_BASE);
       
   370 	LoadGrfIndexed("openttd.grf", _openttd_grf_indexes, i++);
       
   371 	load_index = SPR_OPENTTD_BASE + OPENTTD_SPRITES_COUNT;
       
   372 
       
   373 	assert(load_index == SPR_AIRPORTX_BASE);
       
   374 	load_index += LoadGrfFile("airports.grf", load_index, i++);
       
   375 
       
   376 	/* Initialize the unicode to sprite mapping table */
       
   377 	InitializeUnicodeGlyphMap();
       
   378 
       
   379 	LoadNewGRF(load_index, i);
       
   380 }
       
   381 
       
   382 
       
   383 void GfxLoadSprites(void)
       
   384 {
       
   385 	DEBUG(sprite, 2, "Loading sprite set %d", _opt.landscape);
       
   386 
       
   387 	GfxInitSpriteMem();
       
   388 	LoadSpriteTables();
       
   389 	GfxInitPalettes();
       
   390 }