00001
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 {
00123 return false;
00124 }
00125 }
00126
00135 static void DeterminePalette()
00136 {
00137 if (_use_dos_palette) return;
00138
00139
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
00206
00207
00208
00209
00210 LoadGrfFile(files->basic[1].filename, 4793, i++);
00211
00212
00213
00214
00215
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
00226 InitializeUnicodeGlyphMap();
00227
00228
00229
00230
00231
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
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 }