# 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 }