diff options
author | rubidium <rubidium@openttd.org> | 2009-08-20 17:02:44 +0000 |
---|---|---|
committer | rubidium <rubidium@openttd.org> | 2009-08-20 17:02:44 +0000 |
commit | 2fd1b000e5d179418cb831a13392545d77ea3b48 (patch) | |
tree | b8349df74006922d7b819989e9e2e141beaef5b0 | |
parent | 367ff2375af6a7eeac122186335a193361bf06f2 (diff) | |
download | openttd-2fd1b000e5d179418cb831a13392545d77ea3b48.tar.xz |
(svn r17241) -Change: make a distinction between missing and corrupted data files. If (at least) one data file is missing do not consider the set to be useable. Do also no autodetect sets with missing files.
-rw-r--r-- | bin/data/orig_dos.obs | 2 | ||||
-rw-r--r-- | bin/data/orig_win.obs | 2 | ||||
-rw-r--r-- | src/base_media_base.h | 38 | ||||
-rw-r--r-- | src/base_media_func.h | 37 | ||||
-rw-r--r-- | src/gfxinit.cpp | 57 | ||||
-rw-r--r-- | src/settings_gui.cpp | 8 | ||||
-rw-r--r-- | src/sound.cpp | 10 |
7 files changed, 87 insertions, 67 deletions
diff --git a/bin/data/orig_dos.obs b/bin/data/orig_dos.obs index ced0628a2..b342e314d 100644 --- a/bin/data/orig_dos.obs +++ b/bin/data/orig_dos.obs @@ -5,7 +5,7 @@ ; [metadata] name = original_dos -shortname = TTDD +shortname = TTDO version = 0 description = Original Transport Tycoon Deluxe DOS edition sounds diff --git a/bin/data/orig_win.obs b/bin/data/orig_win.obs index 5f5788034..71e329962 100644 --- a/bin/data/orig_win.obs +++ b/bin/data/orig_win.obs @@ -5,7 +5,7 @@ ; [metadata] name = original_windows -shortname = TTDW +shortname = TTDO version = 0 description = Original Transport Tycoon Deluxe Windows edition sounds diff --git a/src/base_media_base.h b/src/base_media_base.h index a13b77d58..0e52bbc7a 100644 --- a/src/base_media_base.h +++ b/src/base_media_base.h @@ -13,11 +13,18 @@ struct ContentInfo; /** Structure holding filename and MD5 information about a single file */ struct MD5File { + /** The result of a checksum check */ + enum ChecksumResult { + CR_MATCH, ///< The file did exist and the md5 checksum did match + CR_MISMATCH, ///< The file did exist, just the md5 checksum did not match + CR_NO_FILE, ///< The file did not exist + }; + const char *filename; ///< filename uint8 hash[16]; ///< md5 sum of the file const char *missing_warning; ///< warning when this file is missing - bool CheckMD5() const; + ChecksumResult CheckMD5() const; }; /** @@ -40,6 +47,7 @@ struct BaseSet { MD5File files[NUM_FILES]; ///< All files part of this set uint found_files; ///< Number of the files that could be found + uint valid_files; ///< Number of the files that could be found and are valid T *next; ///< The next base set in this list @@ -66,6 +74,16 @@ struct BaseSet { } /** + * Get the number of invalid files. + * @note a missing file is invalid too! + * @return the number + */ + int GetNumInvalid() const + { + return Tnum_files - this->valid_files; + } + + /** * Read the set information from a loaded ini. * @param ini the ini to read from * @param path the path to this ini file (for filenames) @@ -172,16 +190,6 @@ enum GraphicsFileType { struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT> { PaletteType palette; ///< Palette of this graphics set - /** - * Is this set useable? Are enough files found to think it exists. - * @return true if it's useable. - */ - bool IsUseable() const - { - /* Do not find 'only' openttd[dw].grf */ - return this->found_files > 1; - } - bool FillSetDetails(struct IniFile *ini, const char *path); }; @@ -196,14 +204,6 @@ public: /** All data of a sounds set. */ struct SoundsSet : BaseSet<SoundsSet, 1> { - /** - * Is this set useable? Are enough files found to think it exists. - * @return true if it's useable. - */ - bool IsUseable() const - { - return this->found_files > 0; - } }; /** All data/functions related with replacing the base sounds */ diff --git a/src/base_media_func.h b/src/base_media_func.h index ba0925952..ea3e41366 100644 --- a/src/base_media_func.h +++ b/src/base_media_func.h @@ -95,7 +95,17 @@ bool BaseSet<T, Tnum_files>::FillSetDetails(IniFile *ini, const char *path) file->missing_warning = strdup(item->value); } - if (file->CheckMD5()) this->found_files++; + switch (file->CheckMD5()) { + case MD5File::CR_MATCH: + this->valid_files++; + /* FALL THROUGH */ + case MD5File::CR_MISMATCH: + this->found_files++; + break; + + case MD5File::CR_NO_FILE: + break; + } } return true; @@ -129,8 +139,8 @@ bool BaseMedia<Tbase_set>::AddFile(const char *filename, size_t basepath_length) } if (duplicate != NULL) { /* The more complete set takes precedence over the version number. */ - if ((duplicate->found_files == set->found_files && duplicate->version >= set->version) || - duplicate->found_files > set->found_files) { + if ((duplicate->valid_files == set->valid_files && duplicate->version >= set->version) || + duplicate->valid_files > set->valid_files) { DEBUG(grf, 1, "Not adding %s (%i) as base " SET_TYPE " set (duplicate)", set->name, set->version); delete set; } else { @@ -191,12 +201,15 @@ template <class Tbase_set> { p += seprintf(p, last, "List of " SET_TYPE " sets:\n"); for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != NULL; s = s->next) { - if (!s->IsUseable()) continue; - p += seprintf(p, last, "%18s: %s", s->name, s->description); - int missing = s->GetNumMissing(); - if (missing != 0) { - p += seprintf(p, last, " (missing %i file%s)\n", missing, missing == 1 ? "" : "s"); + int invalid = s->GetNumInvalid(); + if (invalid != 0) { + int missing = s->GetNumMissing(); + if (missing == 0) { + p += seprintf(p, last, " (%i corrupt file%s)\n", invalid, invalid == 1 ? "" : "s"); + } else { + p += seprintf(p, last, " (unuseable: %i missing file%s)\n", missing, missing == 1 ? "" : "s"); + } } else { p += seprintf(p, last, "\n"); } @@ -213,7 +226,7 @@ template <class Tbase_set> /* static */ bool BaseMedia<Tbase_set>::HasSet(const ContentInfo *ci, bool md5sum) { for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != NULL; s = s->next) { - if (!s->IsUseable()) continue; + if (s->GetNumMissing() != 0) continue; if (s->shortname != ci->unique_id) continue; if (!md5sum) return true; @@ -246,7 +259,7 @@ template <class Tbase_set> { int n = 0; for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != NULL; s = s->next) { - if (s != BaseMedia<Tbase_set>::used_set && !s->IsUseable()) continue; + if (s != BaseMedia<Tbase_set>::used_set && s->GetNumMissing() != 0) continue; n++; } return n; @@ -258,7 +271,7 @@ template <class Tbase_set> int n = 0; for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != NULL; s = s->next) { if (s == BaseMedia<Tbase_set>::used_set) return n; - if (!s->IsUseable()) continue; + if (s->GetNumMissing() != 0) continue; n++; } return -1; @@ -268,7 +281,7 @@ template <class Tbase_set> /* static */ const Tbase_set *BaseMedia<Tbase_set>::GetSet(int index) { for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != NULL; s = s->next) { - if (s != BaseMedia<Tbase_set>::used_set && !s->IsUseable()) continue; + if (s != BaseMedia<Tbase_set>::used_set && s->GetNumMissing() != 0) continue; if (index == 0) return s; index--; } diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 4bf4c8fa3..1f8bf089f 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -85,7 +85,6 @@ static void LoadGrfIndexed(const char *filename, const SpriteID *index_tbl, int LoadSpritesIndexed(file_index, &sprite_id, index_tbl); } - /** * Checks whether the MD5 checksums of the files are correct. * @@ -111,25 +110,24 @@ void CheckExternalFiles() char *add_pos = error_msg; const char *last = lastof(error_msg); - if (used_set->GetNumMissing() != 0) { + if (used_set->GetNumInvalid() != 0) { /* Not all files were loaded succesfully, see which ones */ add_pos += seprintf(add_pos, last, "Trying to load graphics set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one.\n\nThe following files are corrupted or missing:\n", used_set->name); for (uint i = 0; i < GraphicsSet::NUM_FILES; i++) { - if (!used_set->files[i].CheckMD5()) { - add_pos += seprintf(add_pos, last, "\t%s (%s)\n", used_set->files[i].filename, used_set->files[i].missing_warning); - } + MD5File::ChecksumResult res = used_set->files[i].CheckMD5(); + if (res != MD5File::CR_MATCH) add_pos += seprintf(add_pos, last, "\t%s is %s (%s)\n", used_set->files[i].filename, res == MD5File::CR_MISMATCH ? "corrupt" : "missing", used_set->files[i].missing_warning); } add_pos += seprintf(add_pos, last, "\n"); } const SoundsSet *sounds_set = BaseSounds::GetUsedSet(); - if (sounds_set->GetNumMissing() != 0) { + if (sounds_set->GetNumInvalid() != 0) { add_pos += seprintf(add_pos, last, "Trying to load sound set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one.\n\nThe following files are corrupted or missing:\n", sounds_set->name); assert_compile(SoundsSet::NUM_FILES == 1); /* No need to loop each file, as long as there is only a single * sound file. */ - add_pos += seprintf(add_pos, last, "\t%s (%s)\n", sounds_set->files->filename, sounds_set->files->missing_warning); + add_pos += seprintf(add_pos, last, "\t%s is %s (%s)\n", sounds_set->files->filename, sounds_set->files->CheckMD5() == MD5File::CR_MISMATCH ? "corrupt" : "missing", sounds_set->files->missing_warning); } if (add_pos != error_msg) ShowInfoF("%s", error_msg); @@ -218,31 +216,32 @@ bool GraphicsSet::FillSetDetails(IniFile *ini, const char *path) /** * Calculate and check the MD5 hash of the supplied filename. - * @return true if the checksum is correct. + * @return + * CR_MATCH if the MD5 hash matches + * CR_MISMATCH if the MD5 does not match + * CR_NO_FILE if the file misses */ -bool MD5File::CheckMD5() const +MD5File::ChecksumResult MD5File::CheckMD5() const { size_t size; FILE *f = FioFOpenFile(this->filename, "rb", DATA_DIR, &size); - if (f != NULL) { - Md5 checksum; - uint8 buffer[1024]; - uint8 digest[16]; - size_t len; - - while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) { - size -= len; - checksum.Append(buffer, len); - } + if (f == NULL) return CR_NO_FILE; - FioFCloseFile(f); + Md5 checksum; + uint8 buffer[1024]; + uint8 digest[16]; + size_t len; - checksum.Finish(digest); - return memcmp(this->hash, digest, sizeof(this->hash)) == 0; - } else { // file not found - return false; + while ((len = fread(buffer, 1, (size > sizeof(buffer)) ? sizeof(buffer) : size, f)) != 0 && size != 0) { + size -= len; + checksum.Append(buffer, len); } + + FioFCloseFile(f); + + checksum.Finish(digest); + return memcmp(this->hash, digest, sizeof(this->hash)) == 0 ? CR_MATCH : CR_MISMATCH; } /** Names corresponding to the GraphicsFileType */ @@ -287,10 +286,14 @@ template <class Tbase_set> { if (BaseMedia<Tbase_set>::used_set != NULL) return true; - const Tbase_set *best = BaseMedia<Tbase_set>::available_sets; + const Tbase_set *best = NULL; for (const Tbase_set *c = BaseMedia<Tbase_set>::available_sets; c != NULL; c = c->next) { - if (best->found_files < c->found_files || - (best->found_files == c->found_files && ( + /* Skip unuseable sets */ + if (c->GetNumMissing() != 0) continue; + + if (best == NULL || + best->valid_files < c->valid_files || + (best->valid_files == c->valid_files && ( (best->shortname == c->shortname && best->version < c->version) || (best->palette != _use_palette && c->palette == _use_palette)))) { best = c; diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 18b06c575..e18c08ad1 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -199,7 +199,7 @@ struct GameOptionsWindow : Window { case GOW_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _num_resolutions ? STR_RES_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break; case GOW_SCREENSHOT_DROPDOWN: SetDParam(0, SPECSTR_SCREENSHOT_START + _cur_screenshot_format); break; case GOW_BASE_GRF_DROPDOWN: SetDParamStr(0, BaseGraphics::GetUsedSet()->name); break; - case GOW_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumMissing()); break; + case GOW_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break; case GOW_BASE_SFX_DROPDOWN: SetDParamStr(0, BaseSounds::GetUsedSet()->name); break; } } @@ -238,10 +238,10 @@ struct GameOptionsWindow : Window { case GOW_BASE_GRF_STATUS: /* Find the biggest description for the default size. */ for (int i = 0; i < BaseGraphics::GetNumSets(); i++) { - uint missing_files = BaseGraphics::GetSet(i)->GetNumMissing(); - if (missing_files == 0) continue; + uint invalid_files = BaseGraphics::GetSet(i)->GetNumInvalid(); + if (invalid_files == 0) continue; - SetDParam(0, missing_files); + SetDParam(0, invalid_files); *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_GRF_STATUS)); } break; diff --git a/src/sound.cpp b/src/sound.cpp index 130841154..7449225b8 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -281,10 +281,14 @@ template <class Tbase_set> { if (BaseMedia<Tbase_set>::used_set != NULL) return true; - const Tbase_set *best = BaseMedia<Tbase_set>::available_sets; + const Tbase_set *best = NULL; for (const Tbase_set *c = BaseMedia<Tbase_set>::available_sets; c != NULL; c = c->next) { - if (best->found_files < c->found_files || - (best->found_files == c->found_files && + /* Skip unuseable sets */ + if (c->GetNumMissing() != 0) continue; + + if (best == NULL || + best->valid_files < c->valid_files || + (best->valid_files == c->valid_files && (best->shortname == c->shortname && best->version < c->version))) { best = c; } |