2005-08-14 18:10:18 +00:00
/* $Id$ */
2008-05-06 15:11:33 +00:00
/** @file gfxinit.cpp Initializing of the (GRF) graphics. */
2007-03-01 01:24:44 +00:00
2005-08-14 18:10:18 +00:00
# include "stdafx.h"
# include "openttd.h"
# include "debug.h"
# include "gfxinit.h"
# include "spritecache.h"
# include "fileio.h"
2007-10-29 23:02:31 +00:00
# include "fios.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"
2007-12-23 10:56:02 +00:00
# include "gfx_func.h"
2008-01-07 14:02:26 +00:00
# include "core/alloc_func.hpp"
2008-01-09 21:05:03 +00:00
# include "core/bitmath_func.hpp"
2006-08-31 07:52:20 +00:00
# include <string.h>
2008-01-13 14:37:30 +00:00
# include "settings_type.h"
2005-08-14 18:10:18 +00:00
2008-01-13 01:21:35 +00:00
# include "table/sprites.h"
2007-03-07 12:11:48 +00:00
struct MD5File {
2007-03-01 01:24:44 +00:00
const char * filename ; ///< filename
2007-12-25 13:59:21 +00:00
uint8 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 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 ) {
2008-06-05 20:54:52 +00:00
usererror ( " Too many sprites. Recompile with higher MAX_SPRITES value or remove some custom GRF files. " ) ;
2005-08-14 18:10:18 +00:00
}
}
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 + + ;
2008-01-28 17:51:45 +00:00
do {
bool b = LoadNextSprite ( start , file_index , * sprite_id ) ;
assert ( b ) ;
( * sprite_id ) + + ;
} while ( + + start < = end ) ;
2005-08-14 18:10:18 +00:00
}
}
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 ) {
2007-12-25 13:59:21 +00:00
Md5 checksum ;
uint8 buffer [ 1024 ] ;
uint8 digest [ 16 ] ;
2005-08-14 18:10:18 +00:00
size_t len ;
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 ;
2007-12-25 13:59:21 +00:00
checksum . Append ( 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
2007-12-25 13:59:21 +00:00
checksum . Finish ( 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 - > 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
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
2008-01-25 13:48:39 +00:00
LoadGrfFile ( files - > basic [ 0 ] . filename , 0 , i + + ) ;
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 .
*/
2008-05-29 15:13:28 +00:00
if ( _settings_game . game_creation . landscape ! = LT_TEMPERATE ) {
2005-08-14 18:10:18 +00:00
LoadGrfIndexed (
2008-05-29 15:13:28 +00:00
files - > landscape [ _settings_game . game_creation . landscape - 1 ] . filename ,
_landscape_spriteindexes [ _settings_game . game_creation . landscape - 1 ] ,
2005-08-14 18:10:18 +00:00
i + +
) ;
}
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
{
2008-05-29 15:13:28 +00:00
DEBUG ( sprite , 2 , " Loading sprite set %d " , _settings_game . game_creation . 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
}