diff --git a/src/base_media_base.h b/src/base_media_base.h index 4378c4673b..cd77cef4df 100644 --- a/src/base_media_base.h +++ b/src/base_media_base.h @@ -58,21 +58,18 @@ struct BaseSet { /** BaseSet type name. */ static constexpr std::string_view SET_TYPE = BaseSetTraits::set_type; - /** Internal names of the files in this set. */ - static const char * const *file_names; - std::string name; ///< The name of the base set std::string url; ///< URL for information about the base set TranslatedStrings description; ///< Description of the base set - uint32_t shortname; ///< Four letter short variant of the name - uint32_t version; ///< The version of this base set - bool fallback; ///< This set is a fallback set, i.e. it should be used only as last resort + uint32_t shortname = 0; ///< Four letter short variant of the name + uint32_t version = 0; ///< The version of this base set + bool fallback = false; ///< This set is a fallback set, i.e. it should be used only as last resort - MD5File files[BaseSet::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 + std::array::NUM_FILES> files{}; ///< All files part of this set + uint found_files = 0; ///< Number of the files that could be found + uint valid_files = 0; ///< Number of the files that could be found and are valid - T *next; ///< The next base set in this list + T *next = nullptr; ///< The next base set in this list /** Free everything we allocated */ ~BaseSet() @@ -154,6 +151,12 @@ struct BaseSet { } return std::nullopt; } + + /** + * Get the internal names of the files in this set. + * @return the internal filenames + */ + static std::span GetFilenames(); }; /** @@ -163,9 +166,9 @@ struct BaseSet { template class BaseMedia : FileScanner { protected: - static Tbase_set *available_sets; ///< All available sets - static Tbase_set *duplicate_sets; ///< All sets that aren't available, but needed for not downloading base sets when a newer version than the one on BaNaNaS is loaded. - static const Tbase_set *used_set; ///< The currently used set + static inline Tbase_set *available_sets = nullptr; ///< All available sets + static inline Tbase_set *duplicate_sets = nullptr; ///< All sets that aren't available, but needed for not downloading base sets when a newer version than the one on BaNaNaS is loaded. + static inline const Tbase_set *used_set = nullptr; ///< The currently used set bool AddFile(const std::string &filename, size_t basepath_length, const std::string &tar_filename) override; @@ -211,10 +214,6 @@ public: static bool HasSet(const ContentInfo *ci, bool md5sum); }; -template /* static */ const Tbase_set *BaseMedia::used_set; -template /* static */ Tbase_set *BaseMedia::available_sets; -template /* static */ Tbase_set *BaseMedia::duplicate_sets; - /** * Check whether there's a base set matching some information. * @param ci The content info to compare it to. diff --git a/src/base_media_func.h b/src/base_media_func.h index 204ccfa818..4e32a12e94 100644 --- a/src/base_media_func.h +++ b/src/base_media_func.h @@ -79,12 +79,14 @@ bool BaseSet::FillSetDetails(const IniFile &ini, const std::string &path, con const IniGroup *files = ini.GetGroup("files"); const IniGroup *md5s = ini.GetGroup("md5s"); const IniGroup *origin = ini.GetGroup("origin"); + auto file_names = BaseSet::GetFilenames(); + for (uint i = 0; i < BaseSet::NUM_FILES; i++) { MD5File *file = &this->files[i]; /* Find the filename first. */ - item = files != nullptr ? files->GetItem(BaseSet::file_names[i]) : nullptr; + item = files != nullptr ? files->GetItem(file_names[i]) : nullptr; if (item == nullptr || (!item->value.has_value() && !allow_empty_filename)) { - Debug(grf, 0, "No {} file for: {} (in {})", BaseSet::SET_TYPE, BaseSet::file_names[i], full_filename); + Debug(grf, 0, "No {} file for: {} (in {})", BaseSet::SET_TYPE, file_names[i], full_filename); return false; } @@ -406,25 +408,3 @@ template { return BaseMedia::available_sets; } - -/** - * Force instantiation of methods so we don't get linker errors. - * @param repl_type the type of the BaseMedia to instantiate - * @param set_type the type of the BaseSet to instantiate - */ -#define INSTANTIATE_BASE_MEDIA_METHODS(repl_type, set_type) \ - template const char *repl_type::GetExtension(); \ - template bool repl_type::AddFile(const std::string &filename, size_t pathlength, const std::string &tar_filename); \ - template bool repl_type::HasSet(const struct ContentInfo *ci, bool md5sum); \ - template bool repl_type::SetSet(const set_type *set); \ - template bool repl_type::SetSetByName(const std::string &name); \ - template bool repl_type::SetSetByShortname(uint32_t shortname); \ - template void repl_type::GetSetsList(std::back_insert_iterator &output_iterator); \ - template int repl_type::GetNumSets(); \ - template int repl_type::GetIndexOfUsedSet(); \ - template const set_type *repl_type::GetSet(int index); \ - template const set_type *repl_type::GetUsedSet(); \ - template bool repl_type::DetermineBestSet(); \ - template set_type *repl_type::GetAvailableSets(); \ - template const char *TryGetBaseSetFile(const ContentInfo *ci, bool md5sum, const set_type *s); - diff --git a/src/base_media_graphics.h b/src/base_media_graphics.h index 72f2ca36e5..7340cc1ee9 100644 --- a/src/base_media_graphics.h +++ b/src/base_media_graphics.h @@ -40,7 +40,7 @@ template <> struct BaseSetTraits { /** All data of a graphics set. */ struct GraphicsSet : BaseSet { private: - mutable std::unique_ptr extra_cfg = nullptr; ///< Parameters for extra GRF + mutable std::unique_ptr extra_cfg; ///< Parameters for extra GRF public: PaletteType palette{}; ///< Palette of this graphics set BlitterType blitter{}; ///< Blitter of this graphics set diff --git a/src/bootstrap_gui.cpp b/src/bootstrap_gui.cpp index 41f4d88d91..b5d03fb506 100644 --- a/src/bootstrap_gui.cpp +++ b/src/bootstrap_gui.cpp @@ -407,7 +407,7 @@ bool HandleBootstrap() if (_exit_game) return false; /* Try to probe the graphics. Should work this time. */ - if (!BaseGraphics::SetSet({})) goto failure; + if (!BaseGraphics::SetSet(nullptr)) goto failure; /* Finally we can continue heading for the menu. */ _game_mode = GM_MENU; diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 7e4ebd196b..6c3badadb7 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -137,7 +137,7 @@ void CheckExternalFiles() static_assert(SoundsSet::NUM_FILES == 1); /* No need to loop each file, as long as there is only a single * sound file. */ - fmt::format_to(output_iterator, "\t{} is {} ({})\n", sounds_set->files->filename, SoundsSet::CheckMD5(sounds_set->files, BASESET_DIR) == MD5File::CR_MISMATCH ? "corrupt" : "missing", sounds_set->files->missing_warning); + fmt::format_to(output_iterator, "\t{} is {} ({})\n", sounds_set->files[0].filename, SoundsSet::CheckMD5(&sounds_set->files[0], BASESET_DIR) == MD5File::CR_MISMATCH ? "corrupt" : "missing", sounds_set->files[0].missing_warning); } if (!error_msg.empty()) ShowInfoI(error_msg); @@ -346,15 +346,11 @@ void GfxLoadSprites() UpdateCursorSize(); } -GraphicsSet::GraphicsSet() -{ - // instantiate here, because unique_ptr needs a complete type -} +// instantiate here, because unique_ptr needs a complete type +GraphicsSet::GraphicsSet() = default; -GraphicsSet::~GraphicsSet() -{ - // instantiate here, because unique_ptr needs a complete type -} +// instantiate here, because unique_ptr needs a complete type +GraphicsSet::~GraphicsSet() = default; bool GraphicsSet::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename) { @@ -467,18 +463,21 @@ MD5File::ChecksumResult MD5File::CheckMD5(Subdirectory subdir, size_t max_size) } /** Names corresponding to the GraphicsFileType */ -static const char * const _graphics_file_names[] = { "base", "logos", "arctic", "tropical", "toyland", "extra" }; +static const std::string_view _graphics_file_names[] = { "base", "logos", "arctic", "tropical", "toyland", "extra" }; /** Implementation */ -template -/* static */ const char * const *BaseSet::file_names = _graphics_file_names; - -template -/* static */ bool BaseMedia::DetermineBestSet() +template <> +/* static */ std::span BaseSet::GetFilenames() { - if (BaseMedia::used_set != nullptr) return true; + return _graphics_file_names; +} - const Tbase_set *best = nullptr; +template <> +/* static */ bool BaseMedia::DetermineBestSet() +{ + if (BaseMedia::used_set != nullptr) return true; + + const GraphicsSet *best = nullptr; auto IsBetter = [&best] (const auto *current) { /* Nothing chosen yet. */ @@ -495,21 +494,21 @@ template return best->palette != PAL_DOS && current->palette == PAL_DOS; }; - for (const Tbase_set *c = BaseMedia::available_sets; c != nullptr; c = c->next) { + for (const GraphicsSet *c = BaseMedia::available_sets; c != nullptr; c = c->next) { /* Skip unusable sets */ if (c->GetNumMissing() != 0) continue; if (IsBetter(c)) best = c; } - BaseMedia::used_set = best; - return BaseMedia::used_set != nullptr; + BaseMedia::used_set = best; + return BaseMedia::used_set != nullptr; } -template -/* static */ const char *BaseMedia::GetExtension() +template <> +/* static */ const char *BaseMedia::GetExtension() { return ".obg"; // OpenTTD Base Graphics } -INSTANTIATE_BASE_MEDIA_METHODS(BaseMedia, GraphicsSet) +template class BaseMedia; diff --git a/src/music.cpp b/src/music.cpp index f713fdc991..a8bf2ee1ac 100644 --- a/src/music.cpp +++ b/src/music.cpp @@ -66,10 +66,8 @@ std::optional> GetMusicCatEntryData(const std::string &file return data; } -INSTANTIATE_BASE_MEDIA_METHODS(BaseMedia, MusicSet) - /** Names corresponding to the music set's files */ -static const char * const _music_file_names[] = { +static const std::string_view _music_file_names[] = { "theme", "old_0", "old_1", "old_2", "old_3", "old_4", "old_5", "old_6", "old_7", "old_8", "old_9", "new_0", "new_1", "new_2", "new_3", "new_4", "new_5", "new_6", "new_7", "new_8", "new_9", @@ -78,22 +76,25 @@ static const char * const _music_file_names[] = { /** Make sure we aren't messing things up. */ static_assert(lengthof(_music_file_names) == NUM_SONGS_AVAILABLE); -template -/* static */ const char * const *BaseSet::file_names = _music_file_names; +template <> +/* static */ std::span BaseSet::GetFilenames() +{ + return _music_file_names; +} -template -/* static */ const char *BaseMedia::GetExtension() +template <> +/* static */ const char *BaseMedia::GetExtension() { return ".obm"; // OpenTTD Base Music } -template -/* static */ bool BaseMedia::DetermineBestSet() +template <> +/* static */ bool BaseMedia::DetermineBestSet() { - if (BaseMedia::used_set != nullptr) return true; + if (BaseMedia::used_set != nullptr) return true; - const Tbase_set *best = nullptr; - for (const Tbase_set *c = BaseMedia::available_sets; c != nullptr; c = c->next) { + const MusicSet *best = nullptr; + for (const MusicSet *c = BaseMedia::available_sets; c != nullptr; c = c->next) { if (c->GetNumMissing() != 0) continue; if (best == nullptr || @@ -105,10 +106,12 @@ template } } - BaseMedia::used_set = best; - return BaseMedia::used_set != nullptr; + BaseMedia::used_set = best; + return BaseMedia::used_set != nullptr; } +template class BaseMedia; + bool MusicSet::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename) { bool ret = this->BaseSet::FillSetDetails(ini, path, full_filename); diff --git a/src/sound.cpp b/src/sound.cpp index 94e67bc720..ff0d9b2704 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -90,7 +90,7 @@ static bool SetBankSource(MixerChannel *mc, SoundEntry *sound, SoundID sound_id) void InitializeSound() { Debug(misc, 1, "Loading sound effects..."); - OpenBankFile(BaseSounds::GetUsedSet()->files->filename); + OpenBankFile(BaseSounds::GetUsedSet()->files[0].filename); } @@ -247,28 +247,28 @@ void SndPlayFx(SoundID sound) StartSound(sound, 0.5, UINT8_MAX); } -INSTANTIATE_BASE_MEDIA_METHODS(BaseMedia, SoundsSet) - /** Names corresponding to the sound set's files */ -static const char * const _sound_file_names[] = { "samples" }; +static const std::string_view _sound_file_names[] = { "samples" }; +template <> +/* static */ std::span BaseSet::GetFilenames() +{ + return _sound_file_names; +} -template -/* static */ const char * const *BaseSet::file_names = _sound_file_names; - -template -/* static */ const char *BaseMedia::GetExtension() +template <> +/* static */ const char *BaseMedia::GetExtension() { return ".obs"; // OpenTTD Base Sounds } -template -/* static */ bool BaseMedia::DetermineBestSet() +template <> +/* static */ bool BaseMedia::DetermineBestSet() { - if (BaseMedia::used_set != nullptr) return true; + if (BaseMedia::used_set != nullptr) return true; - const Tbase_set *best = nullptr; - for (const Tbase_set *c = BaseMedia::available_sets; c != nullptr; c = c->next) { + const SoundsSet *best = nullptr; + for (const SoundsSet *c = BaseMedia::available_sets; c != nullptr; c = c->next) { /* Skip unusable sets */ if (c->GetNumMissing() != 0) continue; @@ -281,7 +281,8 @@ template } } - BaseMedia::used_set = best; - return BaseMedia::used_set != nullptr; + BaseMedia::used_set = best; + return BaseMedia::used_set != nullptr; } +template class BaseMedia;