summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/base_media_base.h38
-rw-r--r--src/base_media_func.h37
-rw-r--r--src/gfxinit.cpp57
-rw-r--r--src/settings_gui.cpp8
-rw-r--r--src/sound.cpp10
5 files changed, 85 insertions, 65 deletions
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;
}