diff --git a/librecomp/include/librecomp/mods.hpp b/librecomp/include/librecomp/mods.hpp index ca53a44..aad1385 100644 --- a/librecomp/include/librecomp/mods.hpp +++ b/librecomp/include/librecomp/mods.hpp @@ -332,6 +332,7 @@ namespace recomp { std::vector get_mod_details(const std::string& mod_game_id); void set_mod_index(const std::string &mod_game_id, const std::string &mod_id, size_t index); const ConfigSchema &get_mod_config_schema(const std::string &mod_id) const; + const std::vector &get_mod_thumbnail(const std::string &mod_id) const; void set_mod_config_value(const std::string &mod_id, const std::string &option_id, const ConfigValueVariant &value); ConfigValueVariant get_mod_config_value(const std::string &mod_id, const std::string &option_id); void set_mods_config_path(const std::filesystem::path &path); @@ -347,7 +348,7 @@ namespace recomp { CodeModLoadError init_mod_code(uint8_t* rdram, const std::unordered_map& section_vrom_map, ModHandle& mod, int32_t load_address, bool hooks_available, uint32_t& ram_used, std::string& error_param); CodeModLoadError load_mod_code(uint8_t* rdram, ModHandle& mod, uint32_t base_event_index, std::string& error_param); CodeModLoadError resolve_code_dependencies(ModHandle& mod, const std::unordered_map& base_patched_funcs, std::string& error_param); - void add_opened_mod(ModManifest&& manifest, ConfigStorage&& config_storage, std::vector&& game_indices, std::vector&& detected_content_types); + void add_opened_mod(ModManifest&& manifest, ConfigStorage&& config_storage, std::vector&& game_indices, std::vector&& detected_content_types, std::vector&& thumbnail); void close_mods(); std::vector regenerate_with_hooks( const std::vector>& sorted_unprocessed_hooks, @@ -386,6 +387,7 @@ namespace recomp { // to add hooks to any functions that weren't already replaced by a mod. std::vector processed_hook_slots; ConfigSchema empty_schema; + std::vector empty_bytes; size_t num_events = 0; ModContentTypeId code_content_type_id; size_t active_game = (size_t)-1; @@ -414,8 +416,9 @@ namespace recomp { std::vector section_load_addresses; // Content types present in this mod. std::vector content_types; + std::vector thumbnail; - ModHandle(const ModContext& context, ModManifest&& manifest, ConfigStorage&& config_storage, std::vector&& game_indices, std::vector&& content_types); + ModHandle(const ModContext& context, ModManifest&& manifest, ConfigStorage&& config_storage, std::vector&& game_indices, std::vector&& content_types, std::vector&& thumbnail); ModHandle(const ModHandle& rhs) = delete; ModHandle& operator=(const ModHandle& rhs) = delete; ModHandle(ModHandle&& rhs); @@ -552,6 +555,7 @@ namespace recomp { bool is_mod_enabled(const std::string& mod_id); bool is_mod_auto_enabled(const std::string& mod_id); const ConfigSchema &get_mod_config_schema(const std::string &mod_id); + const std::vector &get_mod_thumbnail(const std::string &mod_id); void set_mod_config_value(const std::string &mod_id, const std::string &option_id, const ConfigValueVariant &value); ConfigValueVariant get_mod_config_value(const std::string &mod_id, const std::string &option_id); ModContentTypeId register_mod_content_type(const ModContentType& type); diff --git a/librecomp/src/mod_manifest.cpp b/librecomp/src/mod_manifest.cpp index c7a8d96..e3791a4 100644 --- a/librecomp/src/mod_manifest.cpp +++ b/librecomp/src/mod_manifest.cpp @@ -842,9 +842,18 @@ recomp::mods::ModOpenError recomp::mods::ModContext::open_mod(const std::filesys std::filesystem::path config_path = mod_config_directory / (manifest.mod_id + ".json"); parse_mod_config_storage(config_path, manifest.mod_id, config_storage, manifest.config_schema); + // Read the mod thumbnail if it exists. + static const std::string thumbnail_dds_name = "thumb.dds"; + static const std::string thumbnail_png_name = "thumb.png"; + bool exists = false; + std::vector thumbnail_data = manifest.file_handle->read_file(thumbnail_dds_name, exists); + if (!exists) { + thumbnail_data = manifest.file_handle->read_file(thumbnail_png_name, exists); + } + // Store the loaded mod manifest in a new mod handle. manifest.mod_root_path = mod_path; - add_opened_mod(std::move(manifest), std::move(config_storage), std::move(game_indices), std::move(detected_content_types)); + add_opened_mod(std::move(manifest), std::move(config_storage), std::move(game_indices), std::move(detected_content_types), std::move(thumbnail_data)); return ModOpenError::Good; } diff --git a/librecomp/src/mods.cpp b/librecomp/src/mods.cpp index b0febf8..0728241 100644 --- a/librecomp/src/mods.cpp +++ b/librecomp/src/mods.cpp @@ -266,13 +266,14 @@ recomp::mods::CodeModLoadError recomp::mods::validate_api_version(uint32_t api_v } } -recomp::mods::ModHandle::ModHandle(const ModContext& context, ModManifest&& manifest, ConfigStorage&& config_storage, std::vector&& game_indices, std::vector&& content_types) : +recomp::mods::ModHandle::ModHandle(const ModContext& context, ModManifest&& manifest, ConfigStorage&& config_storage, std::vector&& game_indices, std::vector&& content_types, std::vector&& thumbnail) : manifest(std::move(manifest)), config_storage(std::move(config_storage)), code_handle(), recompiler_context{std::make_unique()}, content_types{std::move(content_types)}, - game_indices{std::move(game_indices)} + game_indices{std::move(game_indices)}, + thumbnail{std::move(thumbnail)} { runtime_toggleable = true; for (ModContentTypeId type : this->content_types) { @@ -593,11 +594,11 @@ void unpatch_func(void* target_func, const recomp::mods::PatchData& data) { protect(target_func, old_flags); } -void recomp::mods::ModContext::add_opened_mod(ModManifest&& manifest, ConfigStorage&& config_storage, std::vector&& game_indices, std::vector&& detected_content_types) { +void recomp::mods::ModContext::add_opened_mod(ModManifest&& manifest, ConfigStorage&& config_storage, std::vector&& game_indices, std::vector&& detected_content_types, std::vector&& thumbnail) { std::unique_lock lock(opened_mods_mutex); size_t mod_index = opened_mods.size(); opened_mods_by_id.emplace(manifest.mod_id, mod_index); - opened_mods.emplace_back(*this, std::move(manifest), std::move(config_storage), std::move(game_indices), std::move(detected_content_types)); + opened_mods.emplace_back(*this, std::move(manifest), std::move(config_storage), std::move(game_indices), std::move(detected_content_types), std::move(thumbnail)); opened_mods_order.emplace_back(mod_index); } @@ -1195,6 +1196,17 @@ const recomp::mods::ConfigSchema &recomp::mods::ModContext::get_mod_config_schem return mod.manifest.config_schema; } +const std::vector &recomp::mods::ModContext::get_mod_thumbnail(const std::string &mod_id) const { + // Check that the mod exists. + auto find_it = opened_mods_by_id.find(mod_id); + if (find_it == opened_mods_by_id.end()) { + return empty_bytes; + } + + const ModHandle &mod = opened_mods[find_it->second]; + return mod.thumbnail; +} + void recomp::mods::ModContext::set_mod_config_value(const std::string &mod_id, const std::string &option_id, const ConfigValueVariant &value) { // Check that the mod exists. auto find_it = opened_mods_by_id.find(mod_id); diff --git a/librecomp/src/recomp.cpp b/librecomp/src/recomp.cpp index 9844844..3e6c077 100644 --- a/librecomp/src/recomp.cpp +++ b/librecomp/src/recomp.cpp @@ -525,6 +525,11 @@ const recomp::mods::ConfigSchema &recomp::mods::get_mod_config_schema(const std: return mod_context->get_mod_config_schema(mod_id); } +const std::vector &recomp::mods::get_mod_thumbnail(const std::string &mod_id) { + std::lock_guard lock{ mod_context_mutex }; + return mod_context->get_mod_thumbnail(mod_id); +} + void recomp::mods::set_mod_config_value(const std::string &mod_id, const std::string &option_id, const ConfigValueVariant &value) { std::lock_guard lock{ mod_context_mutex }; return mod_context->set_mod_config_value(mod_id, option_id, value);