2005-08-14 18:10:18 +00:00
/* $Id$ */
2007-03-01 01:24:44 +00:00
/** @file gfxinit.cpp */
2005-08-14 18:10:18 +00:00
# include "stdafx.h"
# include "openttd.h"
# include "debug.h"
# include "functions.h"
# include "gfx.h"
# include "gfxinit.h"
# include "spritecache.h"
# include "table/sprites.h"
# include "fileio.h"
2007-10-29 23:02:31 +00:00
# include "fios.h"
2006-07-31 22:11:34 +00:00
# include "string.h"
2005-08-14 18:10:18 +00:00
# include "newgrf.h"
# include "md5.h"
# include "variables.h"
2006-11-24 20:47:29 +00:00
# include "fontcache.h"
2006-08-31 07:52:20 +00:00
# include <string.h>
2005-08-14 18:10:18 +00:00
2007-03-07 12:11:48 +00:00
struct MD5File {
2007-03-01 01:24:44 +00:00
const char * filename ; ///< filename
md5_byte_t hash [ 16 ] ; ///< md5 sum of the file
2007-03-07 12:11:48 +00:00
} ;
2005-08-14 18:10:18 +00:00
2007-03-07 12:11:48 +00:00
struct FileList {
2007-11-15 07:42:25 +00:00
MD5File basic [ 2 ] ; ///< GRF files that always have to be loaded
MD5File landscape [ 3 ] ; ///< Landscape specific grf files
MD5File sound ; ///< Sound samples
MD5File chars ; ///< GRF File with character replacements
MD5File openttd ; ///< GRF File with OTTD specific graphics
2007-03-07 12:11:48 +00:00
} ;
2005-08-14 18:10:18 +00:00
# include "table/files.h"
# include "table/landscape_sprite.h"
static const SpriteID * const _landscape_spriteindexes [ ] = {
_landscape_spriteindexes_1 ,
_landscape_spriteindexes_2 ,
_landscape_spriteindexes_3 ,
} ;
2007-11-07 23:29:43 +00:00
static uint LoadGrfFile ( const char * filename , uint load_index , int file_index )
2005-08-14 18:10:18 +00:00
{
2005-08-15 11:39:13 +00:00
uint load_index_org = load_index ;
2007-06-14 14:31:48 +00:00
uint sprite_id = 0 ;
2005-08-14 18:10:18 +00:00
FioOpenFile ( file_index , filename ) ;
2006-12-26 17:36:18 +00:00
DEBUG ( sprite , 2 , " Reading grf-file '%s' " , filename ) ;
2005-08-14 18:10:18 +00:00
2007-06-14 14:31:48 +00:00
while ( LoadNextSprite ( load_index , file_index , sprite_id ) ) {
2005-08-14 18:10:18 +00:00
load_index + + ;
2007-06-14 14:31:48 +00:00
sprite_id + + ;
2005-08-14 18:10:18 +00:00
if ( load_index > = MAX_SPRITES ) {
error ( " Too many sprites. Recompile with higher MAX_SPRITES value or remove some custom GRF files. " ) ;
}
}
2006-12-26 17:36:18 +00:00
DEBUG ( sprite , 2 , " Currently %i sprites are loaded " , load_index ) ;
2005-08-14 18:10:18 +00:00
return load_index - load_index_org ;
}
2007-10-20 21:39:50 +00:00
void LoadSpritesIndexed ( int file_index , uint * sprite_id , const SpriteID * index_tbl )
2005-08-14 18:10:18 +00:00
{
2005-08-15 11:39:13 +00:00
uint start ;
2005-11-03 15:25:45 +00:00
while ( ( start = * index_tbl + + ) ! = END ) {
2005-08-15 11:39:13 +00:00
uint end = * index_tbl + + ;
2005-11-03 15:25:45 +00:00
if ( start = = SKIP ) { // skip sprites (amount in second var)
2005-08-14 18:10:18 +00:00
SkipSprites ( end ) ;
2007-10-20 21:39:50 +00:00
( * sprite_id ) + = end ;
2005-08-14 18:10:18 +00:00
} else { // load sprites and use indexes from start to end
do {
# ifdef NDEBUG
2007-10-20 21:39:50 +00:00
LoadNextSprite ( start , file_index , * sprite_id ) ;
2005-08-14 18:10:18 +00:00
# else
2007-10-20 21:39:50 +00:00
bool b = LoadNextSprite ( start , file_index , * sprite_id ) ;
2005-08-14 18:10:18 +00:00
assert ( b ) ;
# endif
2007-10-20 21:39:50 +00:00
( * sprite_id ) + + ;
2005-08-14 18:10:18 +00:00
} while ( + + start < = end ) ;
}
}
}
2007-10-20 21:39:50 +00:00
static void LoadGrfIndexed ( const char * filename , const SpriteID * index_tbl , int file_index )
{
uint sprite_id = 0 ;
FioOpenFile ( file_index , filename ) ;
DEBUG ( sprite , 2 , " Reading indexed grf-file '%s' " , filename ) ;
LoadSpritesIndexed ( file_index , & sprite_id , index_tbl ) ;
}
2005-08-14 18:10:18 +00:00
2007-11-07 23:29:43 +00:00
/**
* Calculate and check the MD5 hash of the supplied filename .
* @ param file filename and expected MD5 hash for the given filename .
* @ return true if the checksum is correct .
*/
static bool FileMD5 ( const MD5File file )
2005-08-14 18:10:18 +00:00
{
2007-09-13 18:46:29 +00:00
size_t size ;
FILE * f = FioFOpenFile ( file . filename , " rb " , DATA_DIR , & size ) ;
2007-01-02 20:39:07 +00:00
2005-08-14 18:10:18 +00:00
if ( f ! = NULL ) {
md5_state_t filemd5state ;
md5_byte_t buffer [ 1024 ] ;
md5_byte_t digest [ 16 ] ;
size_t len ;
md5_init ( & filemd5state ) ;
2007-09-13 18:46:29 +00:00
while ( ( len = fread ( buffer , 1 , ( size > sizeof ( buffer ) ) ? sizeof ( buffer ) : size , f ) ) ! = 0 & & size ! = 0 ) {
size - = len ;
2005-08-14 18:10:18 +00:00
md5_append ( & filemd5state , buffer , len ) ;
2007-09-13 18:46:29 +00:00
}
2005-08-14 18:10:18 +00:00
2007-09-16 18:10:52 +00:00
FioFCloseFile ( f ) ;
2005-08-14 18:10:18 +00:00
md5_finish ( & filemd5state , digest ) ;
2007-11-07 23:29:43 +00:00
return memcmp ( file . hash , digest , sizeof ( file . hash ) ) = = 0 ;
2005-08-14 18:10:18 +00:00
} else { // file not found
return false ;
}
}
2007-11-07 23:29:43 +00:00
/**
* Determine the palette that has to be used .
* - forced DOS palette via command line - > leave it that way
* - all Windows files present - > Windows palette
* - all DOS files present - > DOS palette
* - no Windows files present and any DOS file present - > DOS palette
* - otherwise - > Windows palette
*/
static void DeterminePalette ( )
2005-08-14 18:10:18 +00:00
{
2007-11-07 23:29:43 +00:00
if ( _use_dos_palette ) return ;
/* Count of files from the different versions. */
2005-08-14 18:10:18 +00:00
uint dos = 0 ;
uint win = 0 ;
2007-11-07 23:29:43 +00:00
for ( uint i = 0 ; i < lengthof ( files_dos . basic ) ; i + + ) if ( FioCheckFileExists ( files_dos . basic [ i ] . filename ) ) dos + + ;
for ( uint i = 0 ; i < lengthof ( files_dos . landscape ) ; i + + ) if ( FioCheckFileExists ( files_dos . landscape [ i ] . filename ) ) dos + + ;
2005-08-14 18:10:18 +00:00
2007-11-07 23:29:43 +00:00
for ( uint i = 0 ; i < lengthof ( files_win . basic ) ; i + + ) if ( FioCheckFileExists ( files_win . basic [ i ] . filename ) ) win + + ;
for ( uint i = 0 ; i < lengthof ( files_win . landscape ) ; i + + ) if ( FioCheckFileExists ( files_win . landscape [ i ] . filename ) ) win + + ;
2006-10-24 10:15:56 +00:00
2007-11-07 23:29:43 +00:00
if ( win = = 5 ) {
2005-08-14 18:10:18 +00:00
_use_dos_palette = false ;
} else if ( dos = = 5 | | ( win = = 0 & & dos > 0 ) ) {
_use_dos_palette = true ;
} else {
_use_dos_palette = false ;
}
}
2007-11-07 23:29:43 +00:00
/**
* Checks whether the MD5 checksums of the files are correct .
*
* @ note Also checks sample . cat and other required non - NewGRF GRFs for corruption .
*/
void CheckExternalFiles ( )
{
DeterminePalette ( ) ;
static const size_t ERROR_MESSAGE_LENGTH = 128 ;
const FileList * files = _use_dos_palette ? & files_dos : & files_win ;
2007-11-15 07:42:25 +00:00
char error_msg [ ERROR_MESSAGE_LENGTH * ( lengthof ( files - > basic ) + lengthof ( files - > landscape ) + 3 ) ] ;
2007-11-07 23:29:43 +00:00
error_msg [ 0 ] = ' \0 ' ;
char * add_pos = error_msg ;
for ( uint i = 0 ; i < lengthof ( files - > basic ) ; i + + ) {
if ( ! FileMD5 ( files - > basic [ i ] ) ) {
add_pos + = snprintf ( add_pos , ERROR_MESSAGE_LENGTH , " Your '%s' file is corrupted or missing! You can find '%s' on your Transport Tycoon Deluxe CD-ROM. \n " , files - > basic [ i ] . filename , files - > basic [ i ] . filename ) ;
}
}
for ( uint i = 0 ; i < lengthof ( files - > landscape ) ; i + + ) {
if ( ! FileMD5 ( files - > landscape [ i ] ) ) {
add_pos + = snprintf ( add_pos , ERROR_MESSAGE_LENGTH , " Your '%s' file is corrupted or missing! You can find '%s' on your Transport Tycoon Deluxe CD-ROM. \n " , files - > landscape [ i ] . filename , files - > landscape [ i ] . filename ) ;
}
}
2007-11-15 07:42:25 +00:00
if ( ! FileMD5 ( files_win . sound ) & & ! FileMD5 ( files_dos . sound ) ) {
2007-11-07 23:29:43 +00:00
add_pos + = snprintf ( add_pos , ERROR_MESSAGE_LENGTH , " Your 'sample.cat' file is corrupted or missing! You can find 'sample.cat' on your Transport Tycoon Deluxe CD-ROM. \n " ) ;
}
2007-11-15 07:42:25 +00:00
if ( ! FileMD5 ( files - > chars ) ) {
add_pos + = snprintf ( add_pos , ERROR_MESSAGE_LENGTH , " Your '%s' file is corrupted or missing! The file was part of your installation. \n " , files - > chars . filename ) ;
}
if ( ! FileMD5 ( files - > openttd ) ) {
add_pos + = snprintf ( add_pos , ERROR_MESSAGE_LENGTH , " Your '%s' file is corrupted or missing! The file was part of your installation. \n " , files - > openttd . filename ) ;
2007-11-07 23:29:43 +00:00
}
if ( add_pos ! = error_msg ) ShowInfoF ( error_msg ) ;
}
2005-08-15 11:39:13 +00:00
2005-08-20 18:14:32 +00:00
static const SpriteID trg1idx [ ] = {
2007-03-01 01:24:44 +00:00
0 , 1 , ///< Mouse cursor, ZZZ
2005-08-20 18:14:32 +00:00
/* Medium font */
2007-03-01 01:24:44 +00:00
2 , 92 , ///< ' ' till 'z'
2005-11-03 15:25:45 +00:00
SKIP , 36 ,
2007-05-28 04:15:32 +00:00
160 , 160 , ///< Move Ÿ to the correct position
2007-03-01 01:24:44 +00:00
98 , 98 , ///< Up arrow
2005-11-03 15:25:45 +00:00
131 , 133 ,
2007-03-01 01:24:44 +00:00
SKIP , 1 , ///< skip currency sign
2005-11-03 15:25:45 +00:00
135 , 135 ,
SKIP , 1 ,
137 , 137 ,
SKIP , 1 ,
139 , 139 ,
2007-03-01 01:24:44 +00:00
140 , 140 , ///< @todo Down arrow
2005-11-03 15:25:45 +00:00
141 , 141 ,
2007-03-01 01:24:44 +00:00
142 , 142 , ///< @todo Check mark
143 , 143 , ///< @todo Cross
2005-11-03 15:25:45 +00:00
144 , 144 ,
2007-03-01 01:24:44 +00:00
145 , 145 , ///< @todo Right arrow
2005-11-03 15:25:45 +00:00
146 , 149 ,
2007-03-01 01:24:44 +00:00
118 , 122 , ///< Transport markers
2005-11-03 15:25:45 +00:00
SKIP , 2 ,
157 , 157 ,
2007-03-01 01:24:44 +00:00
114 , 115 , ///< Small up/down arrows
2005-11-03 15:25:45 +00:00
SKIP , 1 ,
161 , 225 ,
2005-08-20 18:14:32 +00:00
/* Small font */
2007-03-01 01:24:44 +00:00
226 , 316 , ///< ' ' till 'z'
2005-11-03 15:25:45 +00:00
SKIP , 36 ,
2007-05-28 04:15:32 +00:00
384 , 384 , ///< Move Ÿ to the correct position
2007-03-01 01:24:44 +00:00
322 , 322 , ///< Up arrow
2005-11-03 15:25:45 +00:00
355 , 357 ,
2007-03-01 01:24:44 +00:00
SKIP , 1 , ///< skip currency sign
2005-11-03 15:25:45 +00:00
359 , 359 ,
SKIP , 1 ,
361 , 361 ,
SKIP , 1 ,
363 , 363 ,
2007-03-01 01:24:44 +00:00
364 , 364 , ////< @todo Down arrow
2005-11-03 15:25:45 +00:00
365 , 366 ,
SKIP , 1 ,
368 , 368 ,
2007-03-01 01:24:44 +00:00
369 , 369 , ///< @todo Right arrow
2005-11-03 15:25:45 +00:00
370 , 373 ,
SKIP , 7 ,
381 , 381 ,
SKIP , 3 ,
385 , 449 ,
2005-08-20 18:14:32 +00:00
/* Big font */
2007-03-01 01:24:44 +00:00
450 , 540 , ///< ' ' till 'z'
2005-11-03 15:25:45 +00:00
SKIP , 36 ,
2007-05-28 04:15:32 +00:00
608 , 608 , ///< Move Ÿ to the correct position
2005-11-03 15:25:45 +00:00
SKIP , 1 ,
579 , 581 ,
SKIP , 1 ,
583 , 583 ,
SKIP , 5 ,
589 , 589 ,
SKIP , 15 ,
605 , 605 ,
SKIP , 3 ,
609 , 625 ,
SKIP , 1 ,
627 , 632 ,
SKIP , 1 ,
634 , 639 ,
SKIP , 1 ,
641 , 657 ,
SKIP , 1 ,
659 , 664 ,
SKIP , 2 ,
667 , 671 ,
SKIP , 1 ,
673 , 673 ,
2005-08-20 18:14:32 +00:00
/* Graphics */
2005-11-03 15:25:45 +00:00
674 , 4792 ,
END
2005-08-20 18:14:32 +00:00
} ;
2007-11-15 07:42:25 +00:00
/** Replace some letter sprites with some other letters */
static const SpriteID _chars_grf_indexes [ ] = {
134 , 134 , ///< euro symbol medium size
582 , 582 , ///< euro symbol large size
358 , 358 , ///< euro symbol tiny
2007-05-28 04:15:32 +00:00
648 , 648 , ///< nordic char: æ
616 , 616 , ///< nordic char: Æ
666 , 666 , ///< nordic char: ø
634 , 634 , ///< nordic char: Ø
382 , 383 , ///< Œ œ tiny
158 , 159 , ///< Œ œ medium
606 , 607 , ///< Œ œ large
360 , 360 , ///< Š tiny
362 , 362 , ///< š tiny
136 , 136 , ///< Š medium
138 , 138 , ///< š medium
584 , 584 , ///< Š large
586 , 586 , ///< š large
626 , 626 , ///< Ð large
658 , 658 , ///< ð large
374 , 374 , ///< Ž tiny
378 , 378 , ///< ž tiny
150 , 150 , ///< Ž medium
154 , 154 , ///< ž medium
598 , 598 , ///< Ž large
602 , 602 , ///< ž large
640 , 640 , ///< Þ large
672 , 672 , ///< þ large
380 , 380 , ///< º tiny
156 , 156 , ///< º medium
604 , 604 , ///< º large
2007-03-01 01:24:44 +00:00
317 , 320 , ///< { | } ~ tiny
93 , 96 , ///< { | } ~ medium
541 , 544 , ///< { | } ~ large
2007-05-28 04:15:32 +00:00
585 , 585 , ///< § large
587 , 587 , ///< © large
592 , 592 , ///< ® large
594 , 597 , ///< ° ± ² ³ large
633 , 633 , ///< × large
665 , 665 , ///< ÷ large
377 , 377 , ///< · small
153 , 153 , ///< · medium
601 , 601 , ///< · large
2005-11-03 15:25:45 +00:00
END
2005-08-20 18:14:32 +00:00
} ;
2005-08-15 11:39:13 +00:00
2007-03-07 11:47:46 +00:00
static void LoadSpriteTables ( )
2005-08-14 18:10:18 +00:00
{
2007-11-07 23:29:43 +00:00
const FileList * files = _use_dos_palette ? & files_dos : & files_win ;
2007-10-29 23:02:31 +00:00
uint i = FIRST_GRF_SLOT ;
2005-08-14 18:10:18 +00:00
2007-10-29 23:02:31 +00:00
LoadGrfIndexed ( files - > basic [ 0 ] . filename , trg1idx , i + + ) ;
2005-09-10 08:17:30 +00:00
DupSprite ( 2 , 130 ) ; // non-breaking space medium
DupSprite ( 226 , 354 ) ; // non-breaking space tiny
DupSprite ( 450 , 578 ) ; // non-breaking space large
2005-08-20 18:14:32 +00:00
2007-11-07 23:29:43 +00:00
/*
* The second basic file always starts at the given location and does
* contain a different amount of sprites depending on the " type " ; DOS
* has a few sprites less . However , we do not care about those missing
* sprites as they are not shown anyway ( logos in intro game ) .
*/
LoadGrfFile ( files - > basic [ 1 ] . filename , 4793 , i + + ) ;
2005-08-14 18:10:18 +00:00
2007-11-07 23:29:43 +00:00
/*
* Load additional sprites for climates other than temperate .
* This overwrites some of the temperate sprites , such as foundations
* and the ground sprites .
*/
2007-03-22 03:42:43 +00:00
if ( _opt . landscape ! = LT_TEMPERATE ) {
2005-08-14 18:10:18 +00:00
LoadGrfIndexed (
2006-11-24 12:39:13 +00:00
files - > landscape [ _opt . landscape - 1 ] . filename ,
_landscape_spriteindexes [ _opt . landscape - 1 ] ,
2005-08-14 18:10:18 +00:00
i + +
) ;
}
2007-11-15 07:42:25 +00:00
LoadGrfIndexed ( files - > chars . filename , _chars_grf_indexes , i + + ) ;
2007-06-01 23:06:01 +00:00
2006-11-24 20:47:29 +00:00
/* Initialize the unicode to sprite mapping table */
InitializeUnicodeGlyphMap ( ) ;
2007-11-15 07:42:25 +00:00
/*
* Load the base NewGRF with OTTD required graphics as first NewGRF .
* However , we do not want it to show up in the list of used NewGRFs ,
* so we have to manually add it , and then remove it later .
*/
GRFConfig * top = _grfconfig ;
GRFConfig * master = CallocT < GRFConfig > ( 1 ) ;
master - > filename = strdup ( files - > openttd . filename ) ;
FillGRFDetails ( master , false ) ;
2007-11-19 21:32:20 +00:00
ClrBit ( master - > flags , GCF_INIT_ONLY ) ;
2007-11-15 07:42:25 +00:00
master - > next = top ;
_grfconfig = master ;
LoadNewGRF ( SPR_NEWGRFS_BASE , i ) ;
/* Free and remove the top element. */
ClearGRFConfig ( & master ) ;
_grfconfig = top ;
2005-08-14 18:10:18 +00:00
}
2007-03-07 11:47:46 +00:00
void GfxLoadSprites ( )
2005-08-14 18:10:18 +00:00
{
2006-12-26 17:36:18 +00:00
DEBUG ( sprite , 2 , " Loading sprite set %d " , _opt . landscape ) ;
2005-08-14 18:10:18 +00:00
2006-11-24 12:39:13 +00:00
GfxInitSpriteMem ( ) ;
LoadSpriteTables ( ) ;
GfxInitPalettes ( ) ;
2005-08-14 18:10:18 +00:00
}