diff options
-rw-r--r-- | src/gfxinit.cpp | 166 | ||||
-rw-r--r-- | src/gfxinit.h | 4 | ||||
-rw-r--r-- | src/openttd.cpp | 27 | ||||
-rw-r--r-- | src/table/files.h | 32 |
4 files changed, 175 insertions, 54 deletions
diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index a13ec21a4..cf6cc8757 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -18,6 +18,7 @@ #include "core/bitmath_func.hpp" #include <string.h> #include "settings_type.h" +#include "string_func.h" #include "table/sprites.h" @@ -28,13 +29,24 @@ struct MD5File { uint8 hash[16]; ///< md5 sum of the file }; -struct FileList { - 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 +/** + * Information about a single graphics set. + */ +struct GraphicsSet { + const char *name; ///< The name of the graphics set + const char *description; ///< Description of the graphics set + Palette palette; ///< Palette of this graphics set + MD5File basic[2]; ///< GRF files that always have to be loaded + MD5File landscape[3]; ///< Landscape specific grf files + const char *base_missing; ///< Warning when one of the base GRF files is missing + MD5File extra; ///< NewGRF File with extra graphics loaded using Action 05 + const char *extra_missing; ///< Warning when the extra (NewGRF) file is missing + uint found_grfs; ///< Number of the GRFs that could be found }; +static const uint GRAPHICS_SET_GRF_COUNT = 6; +static int _use_graphics_set = -1; + #include "table/files.h" #include "table/landscape_sprite.h" @@ -123,34 +135,31 @@ static bool FileMD5(const MD5File file) } /** - * 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 + * Determine the graphics pack that has to be used. + * The one with the most correct files wins. */ -static void DeterminePalette() +static void DetermineGraphicsPack() { - if (_use_palette < MAX_PAL) return; + if (_use_graphics_set >= 0) return; - /* Count of files from the different versions. */ - uint dos = 0; - uint win = 0; + uint max_index = 0; + for (uint j = 1; j < lengthof(_graphics_sets); j++) { + if (_graphics_sets[max_index].found_grfs < _graphics_sets[j].found_grfs) max_index = j; + } - 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++; + _use_graphics_set = max_index; +} - 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++; +/** + * Determine the palette that has to be used. + * - forced palette via command line -> leave it that way + * - otherwise -> palette based on the graphics pack + */ +static void DeterminePalette() +{ + if (_use_palette < MAX_PAL) return; - if (win == 5) { - _use_palette = PAL_WINDOWS; - } else if (dos == 5 || (win == 0 && dos > 0)) { - _use_palette = PAL_DOS; - } else { - _use_palette = PAL_WINDOWS; - } + _use_palette = _graphics_sets[_use_graphics_set].palette; } /** @@ -160,32 +169,38 @@ static void DeterminePalette() */ void CheckExternalFiles() { + DetermineGraphicsPack(); DeterminePalette(); static const size_t ERROR_MESSAGE_LENGTH = 128; - const FileList *files = (_use_palette == PAL_DOS) ? &files_dos : &files_win; - char error_msg[ERROR_MESSAGE_LENGTH * (lengthof(files->basic) + lengthof(files->landscape) + 3)]; + const GraphicsSet *graphics = &_graphics_sets[_use_graphics_set]; + char error_msg[ERROR_MESSAGE_LENGTH * (GRAPHICS_SET_GRF_COUNT + 1)]; 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(graphics->basic); i++) { + if (!FileMD5(graphics->basic[i])) { + add_pos += snprintf(add_pos, ERROR_MESSAGE_LENGTH, "Your '%s' file is corrupted or missing! %s.\n", graphics->basic[i].filename, graphics->base_missing); } } - 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); + for (uint i = 0; i < lengthof(graphics->landscape); i++) { + if (!FileMD5(graphics->landscape[i])) { + add_pos += snprintf(add_pos, ERROR_MESSAGE_LENGTH, "Your '%s' file is corrupted or missing! %s\n", graphics->landscape[i].filename, graphics->base_missing); } } - if (!FileMD5(files_win.sound) && !FileMD5(files_dos.sound)) { + bool sound = false; + for (uint i = 0; !sound && i < lengthof(_sound_sets); i++) { + sound = FileMD5(_sound_sets[i]); + } + + if (!sound) { 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"); } - 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); + if (!FileMD5(graphics->extra)) { + add_pos += snprintf(add_pos, ERROR_MESSAGE_LENGTH, "Your '%s' file is corrupted or missing! %s\n", graphics->extra.filename, graphics->extra_missing); } if (add_pos != error_msg) ShowInfoF(error_msg); @@ -194,10 +209,10 @@ void CheckExternalFiles() static void LoadSpriteTables() { - const FileList *files = (_use_palette == PAL_DOS) ? &files_dos : &files_win; + const GraphicsSet *graphics = &_graphics_sets[_use_graphics_set]; uint i = FIRST_GRF_SLOT; - LoadGrfFile(files->basic[0].filename, 0, i++); + LoadGrfFile(graphics->basic[0].filename, 0, i++); /* * The second basic file always starts at the given location and does @@ -205,7 +220,7 @@ static void LoadSpriteTables() * 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++); + LoadGrfFile(graphics->basic[1].filename, 4793, i++); /* * Load additional sprites for climates other than temperate. @@ -214,7 +229,7 @@ static void LoadSpriteTables() */ if (_settings_game.game_creation.landscape != LT_TEMPERATE) { LoadGrfIndexed( - files->landscape[_settings_game.game_creation.landscape - 1].filename, + graphics->landscape[_settings_game.game_creation.landscape - 1].filename, _landscape_spriteindexes[_settings_game.game_creation.landscape - 1], i++ ); @@ -230,7 +245,7 @@ static void LoadSpriteTables() */ GRFConfig *top = _grfconfig; GRFConfig *master = CallocT<GRFConfig>(1); - master->filename = strdup(files->openttd.filename); + master->filename = strdup(graphics->extra.filename); FillGRFDetails(master, false); ClrBit(master->flags, GCF_INIT_ONLY); master->next = top; @@ -252,3 +267,68 @@ void GfxLoadSprites() LoadSpriteTables(); GfxInitPalettes(); } + +/** + * Find all graphics sets and populate their data. + */ +void FindGraphicsSets() +{ + for (uint j = 0; j < lengthof(_graphics_sets); j++) { + _graphics_sets[j].found_grfs = 0; + for (uint i = 0; i < lengthof(_graphics_sets[j].basic); i++) { + if (FioCheckFileExists(_graphics_sets[j].basic[i].filename)) _graphics_sets[j].found_grfs++; + } + for (uint i = 0; i < lengthof(_graphics_sets[j].landscape); i++) { + if (FioCheckFileExists(_graphics_sets[j].landscape[i].filename)) _graphics_sets[j].found_grfs++; + } + if (FioCheckFileExists(_graphics_sets[j].extra.filename)) _graphics_sets[j].found_grfs++; + } +} + +/** + * Set the graphics set to be used. + * @param name of the graphics set to use + * @return true if it could be loaded + */ +bool SetGraphicsSet(const char *name) +{ + if (StrEmpty(name)) { + DetermineGraphicsPack(); + CheckExternalFiles(); + return true; + } + + for (uint i = 0; i < lengthof(_graphics_sets); i++) { + if (strcmp(name, _graphics_sets[i].name) == 0) { + _use_graphics_set = i; + CheckExternalFiles(); + return true; + } + } + return false; +} + +/** + * Returns a list with the graphics sets. + * @param p where to print to + * @param last the last character to print to + * @return the last printed character + */ +char *GetGraphicsSetsList(char *p, const char *last) +{ + p += snprintf(p, last - p, "List of graphics sets:\n"); + for (uint i = 0; i < lengthof(_graphics_sets); i++) { + if (_graphics_sets[i].found_grfs <= 1) continue; + + p += snprintf(p, last - p, "%18s: %s", _graphics_sets[i].name, _graphics_sets[i].description); + int difference = GRAPHICS_SET_GRF_COUNT - _graphics_sets[i].found_grfs; + if (difference != 0) { + p += snprintf(p, last - p, " (missing %i file%s)\n", difference, difference == 1 ? "" : "s"); + } else { + p += snprintf(p, last - p, "\n"); + } + } + p += snprintf(p, last - p, "\n"); + + return p; +} diff --git a/src/gfxinit.h b/src/gfxinit.h index 37def4598..d75e99378 100644 --- a/src/gfxinit.h +++ b/src/gfxinit.h @@ -11,4 +11,8 @@ void CheckExternalFiles(); void GfxLoadSprites(); void LoadSpritesIndexed(int file_index, uint *sprite_id, const SpriteID *index_tbl); +void FindGraphicsSets(); +bool SetGraphicsSet(const char *name); +char *GetGraphicsSetsList(char *p, const char *last); + #endif /* GFXINIT_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index b28ef672e..131ad9a0c 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -191,11 +191,16 @@ static void ShowHelp() #endif /* ENABLE_NETWORK */ " -i = Force to use the DOS (0) or Windows (1) palette\n" " (use this if you see a lot of pink)\n" + " -I graphics_set = Force the graphics set (see below)\n" " -c config_file = Use 'config_file' instead of 'openttd.cfg'\n" - " -x = Do not automatically save to config file on exit\n", + " -x = Do not automatically save to config file on exit\n" + "\n", lastof(buf) ); + /* List the graphics packs */ + p = GetGraphicsSetsList(p, lastof(buf)); + /* List the drivers */ p = VideoDriverFactoryBase::GetDriversInfo(p, lastof(buf)); @@ -380,7 +385,7 @@ int ttd_main(int argc, char *argv[]) { int i; const char *optformat; - char musicdriver[32], sounddriver[32], videodriver[32], blitter[32]; + char musicdriver[32], sounddriver[32], videodriver[32], blitter[32], graphics_set[32]; Dimension resolution = {0, 0}; Year startyear = INVALID_YEAR; uint generation_seed = GENERATE_NEW_SEED; @@ -394,7 +399,7 @@ int ttd_main(int argc, char *argv[]) uint16 dedicated_port = 0; #endif /* ENABLE_NETWORK */ - musicdriver[0] = sounddriver[0] = videodriver[0] = blitter[0] = '\0'; + musicdriver[0] = sounddriver[0] = videodriver[0] = blitter[0] = graphics_set[0] = '\0'; _game_mode = GM_MENU; _switch_mode = SM_MENU; @@ -406,7 +411,7 @@ int ttd_main(int argc, char *argv[]) * a letter means: it accepts that param (e.g.: -h) * a ':' behind it means: it need a param (e.g.: -m<driver>) * a '::' behind it means: it can optional have a param (e.g.: -d<debug>) */ - optformat = "m:s:v:b:hD::n::ei::t:d::r:g::G:c:xl:" + optformat = "m:s:v:b:hD::n::ei::I:t:d::r:g::G:c:xl:" #if !defined(__MORPHOS__) && !defined(__AMIGA__) && !defined(WIN32) "f" #endif @@ -416,6 +421,7 @@ int ttd_main(int argc, char *argv[]) while ((i = MyGetOpt(&mgo)) != -1) { switch (i) { + case 'I': ttd_strlcpy(graphics_set, mgo.opt, sizeof(graphics_set)); break; case 'm': ttd_strlcpy(musicdriver, mgo.opt, sizeof(musicdriver)); break; case 's': ttd_strlcpy(sounddriver, mgo.opt, sizeof(sounddriver)); break; case 'v': ttd_strlcpy(videodriver, mgo.opt, sizeof(videodriver)); break; @@ -481,6 +487,11 @@ int ttd_main(int argc, char *argv[]) case 'x': save_config = false; break; case -2: case 'h': + /* The next two functions are needed to list the graphics sets. + * We can't do them earlier because then we can't show it on + * the debug console as that hasn't been configured yet. */ + DeterminePaths(argv[0]); + FindGraphicsSets(); ShowHelp(); return 0; } @@ -492,7 +503,7 @@ int ttd_main(int argc, char *argv[]) #endif DeterminePaths(argv[0]); - CheckExternalFiles(); + FindGraphicsSets(); #if defined(UNIX) && !defined(__MORPHOS__) /* We must fork here, or we'll end up without some resources we need (like sockets) */ @@ -547,6 +558,12 @@ int ttd_main(int argc, char *argv[]) /* This must be done early, since functions use the InvalidateWindow* calls */ InitWindowSystem(); + if (!SetGraphicsSet(graphics_set)) { + StrEmpty(graphics_set) ? + usererror("Failed to find a graphics set. Please acquire a graphics set for OpenTTD.") : + usererror("Failed to select requested graphics set '%s'", graphics_set); + } + /* Initialize game palette */ GfxInitPalettes(); diff --git a/src/table/files.h b/src/table/files.h index abc139c67..702ffe621 100644 --- a/src/table/files.h +++ b/src/table/files.h @@ -25,7 +25,12 @@ */ -static FileList files_dos = { +static GraphicsSet _graphics_sets[] = { +/** Filenames and MD5 checksums of the original DOS graphics */ +{ + "original_dos", + "Original Transport Tycoon Deluxe DOS edition graphics", + PAL_DOS, { { "TRG1.GRF", {0x93, 0x11, 0x67, 0x62, 0x80, 0xe5, 0xb1, 0x40, 0x77, 0xa8, 0xee, 0x41, 0xc1, 0xb4, 0x21, 0x92} }, // 0 - 4792 inclusive { "TRGI.GRF", {0xda, 0x6a, 0x6c, 0x9d, 0xcc, 0x45, 0x1e, 0xec, 0x88, 0xd7, 0x92, 0x11, 0x43, 0x7b, 0x76, 0xa8} } // 4793 - 4889 inclusive @@ -34,12 +39,18 @@ static FileList files_dos = { { "TRGH.GRF", {0xee, 0x66, 0x16, 0xfb, 0x0e, 0x6e, 0xf6, 0xb2, 0x48, 0x92, 0xc5, 0x8c, 0x93, 0xd8, 0x6f, 0xc9} }, { "TRGT.GRF", {0xfc, 0xde, 0x1d, 0x7e, 0x8a, 0x74, 0x19, 0x7d, 0x72, 0xa6, 0x26, 0x95, 0x88, 0x4b, 0x90, 0x9e} } }, - { "SAMPLE.CAT", {0x42, 0x2e, 0xa3, 0xdd, 0x07, 0x4d, 0x28, 0x59, 0xbb, 0x51, 0x63, 0x9a, 0x6e, 0x0e, 0x85, 0xda} }, - { "OPENTTDD.GRF", {0xf8, 0x29, 0xf6, 0x2c, 0x13, 0x7d, 0x6d, 0x7c, 0x6e, 0x27, 0x2c, 0x48, 0x1b, 0x79, 0x6d, 0xd5} } -}; + "You can find it on your Transport Tycoon Deluxe CD-ROM.", + { "OPENTTDD.GRF", {0xf8, 0x29, 0xf6, 0x2c, 0x13, 0x7d, 0x6d, 0x7c, 0x6e, 0x27, 0x2c, 0x48, 0x1b, 0x79, 0x6d, 0xd5} }, + "This file was part of your installation.", + 0 +}, -static FileList files_win = { +/** Filenames and MD5 checksums of the original Windows graphics */ +{ + "original_windows", + "Original Transport Tycoon Deluxe Windows edition graphics", + PAL_WINDOWS, { { "TRG1R.GRF", {0xb0, 0x4c, 0xe5, 0x93, 0xd8, 0xc5, 0x01, 0x6e, 0x07, 0x47, 0x3a, 0x74, 0x3d, 0x7d, 0x33, 0x58} }, // 0 - 4792 inclusive { "TRGIR.GRF", {0x0c, 0x24, 0x84, 0xff, 0x6b, 0xe4, 0x9f, 0xc6, 0x3a, 0x83, 0xbe, 0x6a, 0xb5, 0xc3, 0x8f, 0x32} } // 4793 - 4895 inclusive @@ -48,6 +59,15 @@ static FileList files_win = { { "TRGHR.GRF", {0x06, 0xbf, 0x2b, 0x7a, 0x31, 0x76, 0x6f, 0x04, 0x8b, 0xaa, 0xc2, 0xeb, 0xe4, 0x34, 0x57, 0xb1} }, { "TRGTR.GRF", {0xde, 0x53, 0x65, 0x05, 0x17, 0xfe, 0x66, 0x1c, 0xea, 0xa3, 0x13, 0x8c, 0x6e, 0xdb, 0x0e, 0xb8} } }, + "You can find it on your Transport Tycoon Deluxe CD-ROM", + + { "OPENTTDW.GRF", {0x89, 0x4f, 0xa4, 0xb0, 0x4d, 0xc1, 0x6d, 0xc4, 0x39, 0x21, 0x49, 0x3f, 0xd8, 0x3d, 0x80, 0x9e} }, + "This file was part of your installation.", + 0 +} +}; + +static MD5File _sound_sets[] = { + { "SAMPLE.CAT", {0x42, 0x2e, 0xa3, 0xdd, 0x07, 0x4d, 0x28, 0x59, 0xbb, 0x51, 0x63, 0x9a, 0x6e, 0x0e, 0x85, 0xda} }, { "SAMPLE.CAT", {0x92, 0x12, 0xe8, 0x1e, 0x72, 0xba, 0xdd, 0x4b, 0xbe, 0x1e, 0xae, 0xae, 0x66, 0x45, 0x8e, 0x10} }, - { "OPENTTDW.GRF", {0x89, 0x4f, 0xa4, 0xb0, 0x4d, 0xc1, 0x6d, 0xc4, 0x39, 0x21, 0x49, 0x3f, 0xd8, 0x3d, 0x80, 0x9e} } }; |