gfxinit.cpp

Go to the documentation of this file.
00001 /* $Id: gfxinit.cpp 12002 2008-01-28 17:51:45Z peter1138 $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "debug.h"
00008 #include "gfxinit.h"
00009 #include "spritecache.h"
00010 #include "fileio.h"
00011 #include "fios.h"
00012 #include "newgrf.h"
00013 #include "md5.h"
00014 #include "variables.h"
00015 #include "fontcache.h"
00016 #include "gfx_func.h"
00017 #include "core/alloc_func.hpp"
00018 #include "core/bitmath_func.hpp"
00019 #include <string.h>
00020 #include "settings_type.h"
00021 
00022 #include "table/sprites.h"
00023 
00024 struct MD5File {
00025   const char * filename;     
00026   uint8 hash[16];            
00027 };
00028 
00029 struct FileList {
00030   MD5File basic[2];     
00031   MD5File landscape[3]; 
00032   MD5File sound;        
00033   MD5File openttd;      
00034 };
00035 
00036 #include "table/files.h"
00037 #include "table/landscape_sprite.h"
00038 
00039 static const SpriteID * const _landscape_spriteindexes[] = {
00040   _landscape_spriteindexes_1,
00041   _landscape_spriteindexes_2,
00042   _landscape_spriteindexes_3,
00043 };
00044 
00045 static uint LoadGrfFile(const char *filename, uint load_index, int file_index)
00046 {
00047   uint load_index_org = load_index;
00048   uint sprite_id = 0;
00049 
00050   FioOpenFile(file_index, filename);
00051 
00052   DEBUG(sprite, 2, "Reading grf-file '%s'", filename);
00053 
00054   while (LoadNextSprite(load_index, file_index, sprite_id)) {
00055     load_index++;
00056     sprite_id++;
00057     if (load_index >= MAX_SPRITES) {
00058       error("Too many sprites. Recompile with higher MAX_SPRITES value or remove some custom GRF files.");
00059     }
00060   }
00061   DEBUG(sprite, 2, "Currently %i sprites are loaded", load_index);
00062 
00063   return load_index - load_index_org;
00064 }
00065 
00066 
00067 void LoadSpritesIndexed(int file_index, uint *sprite_id, const SpriteID *index_tbl)
00068 {
00069   uint start;
00070   while ((start = *index_tbl++) != END) {
00071     uint end = *index_tbl++;
00072 
00073     do {
00074     #ifdef NDEBUG
00075       LoadNextSprite(start, file_index, *sprite_id);
00076     #else
00077       bool b = LoadNextSprite(start, file_index, *sprite_id);
00078       assert(b);
00079     #endif
00080       (*sprite_id)++;
00081     } while (++start <= end);
00082   }
00083 }
00084 
00085 static void LoadGrfIndexed(const char* filename, const SpriteID* index_tbl, int file_index)
00086 {
00087   uint sprite_id = 0;
00088 
00089   FioOpenFile(file_index, filename);
00090 
00091   DEBUG(sprite, 2, "Reading indexed grf-file '%s'", filename);
00092 
00093   LoadSpritesIndexed(file_index, &sprite_id, index_tbl);
00094 }
00095 
00096 
00102 static bool FileMD5(const MD5File file)
00103 {
00104   size_t size;
00105   FILE *f = FioFOpenFile(file.filename, "rb", DATA_DIR, &size);
00106 
00107   if (f != NULL) {
00108     Md5 checksum;
00109     uint8 buffer[1024];
00110     uint8 digest[16];
00111     size_t len;
00112 
00113     while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) {
00114       size -= len;
00115       checksum.Append(buffer, len);
00116     }
00117 
00118     FioFCloseFile(f);
00119 
00120     checksum.Finish(digest);
00121     return memcmp(file.hash, digest, sizeof(file.hash)) == 0;
00122   } else { // file not found
00123     return false;
00124   }
00125 }
00126 
00135 static void DeterminePalette()
00136 {
00137   if (_use_dos_palette) return;
00138 
00139   /* Count of files from the different versions. */
00140   uint dos = 0;
00141   uint win = 0;
00142 
00143   for (uint i = 0; i < lengthof(files_dos.basic); i++) if (FioCheckFileExists(files_dos.basic[i].filename)) dos++;
00144   for (uint i = 0; i < lengthof(files_dos.landscape); i++) if (FioCheckFileExists(files_dos.landscape[i].filename)) dos++;
00145 
00146   for (uint i = 0; i < lengthof(files_win.basic); i++) if (FioCheckFileExists(files_win.basic[i].filename)) win++;
00147   for (uint i = 0; i < lengthof(files_win.landscape); i++) if (FioCheckFileExists(files_win.landscape[i].filename)) win++;
00148 
00149   if (win == 5) {
00150     _use_dos_palette = false;
00151   } else if (dos == 5 || (win == 0 && dos > 0)) {
00152     _use_dos_palette = true;
00153   } else {
00154     _use_dos_palette = false;
00155   }
00156 }
00157 
00163 void CheckExternalFiles()
00164 {
00165   DeterminePalette();
00166 
00167   static const size_t ERROR_MESSAGE_LENGTH = 128;
00168   const FileList *files = _use_dos_palette ? &files_dos : &files_win;
00169   char error_msg[ERROR_MESSAGE_LENGTH * (lengthof(files->basic) + lengthof(files->landscape) + 3)];
00170   error_msg[0] = '\0';
00171   char *add_pos = error_msg;
00172 
00173   for (uint i = 0; i < lengthof(files->basic); i++) {
00174     if (!FileMD5(files->basic[i])) {
00175       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);
00176     }
00177   }
00178 
00179   for (uint i = 0; i < lengthof(files->landscape); i++) {
00180     if (!FileMD5(files->landscape[i])) {
00181       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);
00182     }
00183   }
00184 
00185   if (!FileMD5(files_win.sound) && !FileMD5(files_dos.sound)) {
00186     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");
00187   }
00188 
00189   if (!FileMD5(files->openttd)) {
00190     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);
00191   }
00192 
00193   if (add_pos != error_msg) ShowInfoF(error_msg);
00194 }
00195 
00196 
00197 static void LoadSpriteTables()
00198 {
00199   const FileList *files = _use_dos_palette ? &files_dos : &files_win;
00200   uint i = FIRST_GRF_SLOT;
00201 
00202   LoadGrfFile(files->basic[0].filename, 0, i++);
00203 
00204   /*
00205    * The second basic file always starts at the given location and does
00206    * contain a different amount of sprites depending on the "type"; DOS
00207    * has a few sprites less. However, we do not care about those missing
00208    * sprites as they are not shown anyway (logos in intro game).
00209    */
00210   LoadGrfFile(files->basic[1].filename, 4793, i++);
00211 
00212   /*
00213    * Load additional sprites for climates other than temperate.
00214    * This overwrites some of the temperate sprites, such as foundations
00215    * and the ground sprites.
00216    */
00217   if (_opt.landscape != LT_TEMPERATE) {
00218     LoadGrfIndexed(
00219       files->landscape[_opt.landscape - 1].filename,
00220       _landscape_spriteindexes[_opt.landscape - 1],
00221       i++
00222     );
00223   }
00224 
00225   /* Initialize the unicode to sprite mapping table */
00226   InitializeUnicodeGlyphMap();
00227 
00228   /*
00229    * Load the base NewGRF with OTTD required graphics as first NewGRF.
00230    * However, we do not want it to show up in the list of used NewGRFs,
00231    * so we have to manually add it, and then remove it later.
00232    */
00233   GRFConfig *top = _grfconfig;
00234   GRFConfig *master = CallocT<GRFConfig>(1);
00235   master->filename = strdup(files->openttd.filename);
00236   FillGRFDetails(master, false);
00237   ClrBit(master->flags, GCF_INIT_ONLY);
00238   master->next = top;
00239   _grfconfig = master;
00240 
00241   LoadNewGRF(SPR_NEWGRFS_BASE, i);
00242 
00243   /* Free and remove the top element. */
00244   ClearGRFConfig(&master);
00245   _grfconfig = top;
00246 }
00247 
00248 
00249 void GfxLoadSprites()
00250 {
00251   DEBUG(sprite, 2, "Loading sprite set %d", _opt.landscape);
00252 
00253   GfxInitSpriteMem();
00254   LoadSpriteTables();
00255   GfxInitPalettes();
00256 }

Generated on Mon Sep 22 20:34:15 2008 for openttd by  doxygen 1.5.6