diff --git a/include/zelda_render.h b/include/zelda_render.h index e09cdc9..9fa0ce2 100644 --- a/include/zelda_render.h +++ b/include/zelda_render.h @@ -1,7 +1,7 @@ #ifndef __ZELDA_RENDER_H__ #define __ZELDA_RENDER_H__ -#include +#include #include #include "common/rt64_user_configuration.h" @@ -30,9 +30,11 @@ namespace zelda64 { uint32_t get_display_framerate() const override; float get_resolution_scale() const override; - protected: + private: std::unique_ptr app; - std::set enabled_texture_packs; + std::unordered_set enabled_texture_packs; + + void check_texture_pack_actions(); }; std::unique_ptr create_render_context(uint8_t *rdram, ultramodern::renderer::WindowHandle window_handle, bool developer_mode); @@ -41,6 +43,7 @@ namespace zelda64 { bool RT64SamplePositionsSupported(); bool RT64HighPrecisionFBEnabled(); + void trigger_texture_pack_update(); void enable_texture_pack(const recomp::mods::ModHandle& mod); void disable_texture_pack(const recomp::mods::ModHandle& mod); } diff --git a/lib/N64ModernRuntime b/lib/N64ModernRuntime index 8506c1b..af07562 160000 --- a/lib/N64ModernRuntime +++ b/lib/N64ModernRuntime @@ -1 +1 @@ -Subproject commit 8506c1b588a31c8a3f064621edec44abb6a09e43 +Subproject commit af075623dc4da25dc235fc2bebb5eec4dc70c2ab diff --git a/src/main/main.cpp b/src/main/main.cpp index 99b95af..a820c3f 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -544,16 +544,18 @@ void release_preload(PreloadContext& context) { #endif -void enable_texture_pack(recomp::mods::ModContext& context, const recomp::mods::ModHandle& mod) { - (void)context; +void enable_texture_pack(recomp::mods::ModContext&, const recomp::mods::ModHandle& mod) { zelda64::renderer::enable_texture_pack(mod); } -void disable_texture_pack(recomp::mods::ModContext& context, const recomp::mods::ModHandle& mod) { - (void)context; +void disable_texture_pack(recomp::mods::ModContext&, const recomp::mods::ModHandle& mod) { zelda64::renderer::disable_texture_pack(mod); } +void reorder_texture_pack(recomp::mods::ModContext&) { + zelda64::renderer::trigger_texture_pack_update(); +} + #define REGISTER_FUNC(name) recomp::overlays::register_base_export(#name, name) int main(int argc, char** argv) { @@ -682,6 +684,7 @@ int main(int argc, char** argv) { .allow_runtime_toggle = true, .on_enabled = enable_texture_pack, .on_disabled = disable_texture_pack, + .on_reordered = reorder_texture_pack, }; auto texture_pack_content_type_id = recomp::mods::register_mod_content_type(texture_pack_content_type); diff --git a/src/main/rt64_render_context.cpp b/src/main/rt64_render_context.cpp index e12ddbb..ae652c3 100644 --- a/src/main/rt64_render_context.cpp +++ b/src/main/rt64_render_context.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #define HLSL_CPU #include "hle/rt64_application.h" @@ -27,14 +28,17 @@ static uint8_t DMEM[0x1000]; static uint8_t IMEM[0x1000]; struct TexturePackEnableAction { - std::filesystem::path path; + std::string mod_id; }; struct TexturePackDisableAction { - std::filesystem::path path; + std::string mod_id; }; -using TexturePackAction = std::variant; +struct TexturePackUpdateAction { +}; + +using TexturePackAction = std::variant; static moodycamel::ConcurrentQueue texture_pack_action_queue; @@ -325,32 +329,7 @@ zelda64::renderer::RT64Context::RT64Context(uint8_t* rdram, ultramodern::rendere zelda64::renderer::RT64Context::~RT64Context() = default; void zelda64::renderer::RT64Context::send_dl(const OSTask* task) { - bool packs_disabled = false; - TexturePackAction cur_action; - while (texture_pack_action_queue.try_dequeue(cur_action)) { - std::visit(overloaded{ - [&](TexturePackDisableAction& to_disable) { - enabled_texture_packs.erase(to_disable.path); - packs_disabled = true; - }, - [&](TexturePackEnableAction& to_enable) { - enabled_texture_packs.insert(to_enable.path); - // Load the pack now if no packs have been disabled. - if (!packs_disabled) { - app->textureCache->loadReplacementDirectory(to_enable.path); - } - } - }, cur_action); - } - - // If any packs were disabled, unload all packs and load all the active ones. - if (packs_disabled) { - app->textureCache->clearReplacementDirectories(); - for (const std::filesystem::path& cur_pack_path : enabled_texture_packs) { - app->textureCache->loadReplacementDirectory(cur_pack_path); - } - } - + check_texture_pack_actions(); app->state->rsp->reset(); app->interpreter->loadUCodeGBI(task->t.ucode & 0x3FFFFFF, task->t.ucode_data & 0x3FFFFFF, true); app->processDisplayLists(app->core.RDRAM, task->t.data_ptr & 0x3FFFFFF, 0, true); @@ -416,6 +395,52 @@ float zelda64::renderer::RT64Context::get_resolution_scale() const { } } +void zelda64::renderer::RT64Context::check_texture_pack_actions() { + bool packs_changed = false; + TexturePackAction cur_action; + while (texture_pack_action_queue.try_dequeue(cur_action)) { + std::visit(overloaded{ + [&](TexturePackDisableAction &to_disable) { + enabled_texture_packs.erase(to_disable.mod_id); + packs_changed = true; + }, + [&](TexturePackEnableAction &to_enable) { + enabled_texture_packs.insert(to_enable.mod_id); + packs_changed = true; + }, + [&](TexturePackUpdateAction &) { + packs_changed = true; + } + }, cur_action); + } + + // If any packs were disabled, unload all packs and load all the active ones. + if (packs_changed) { + if (!enabled_texture_packs.empty()) { + // Sort the enabled texture packs in reverse order so that earlier ones override later ones. + std::vector sorted_texture_packs{}; + sorted_texture_packs.assign(enabled_texture_packs.begin(), enabled_texture_packs.end()); + std::sort(sorted_texture_packs.begin(), sorted_texture_packs.end(), + [](const std::string& lhs, const std::string& rhs) { + return recomp::mods::get_mod_order_index(lhs) > recomp::mods::get_mod_order_index(rhs); + } + ); + + // Build the path list from the sorted mod list. + std::vector replacement_directories; + replacement_directories.reserve(enabled_texture_packs.size()); + for (const std::string &mod_id : sorted_texture_packs) { + replacement_directories.emplace_back(RT64::ReplacementDirectory(recomp::mods::get_mod_filename(mod_id))); + } + + app->textureCache->loadReplacementDirectories(replacement_directories); + } + else { + app->textureCache->clearReplacementDirectories(); + } + } +} + RT64::UserConfiguration::Antialiasing zelda64::renderer::RT64MaxMSAA() { return device_max_msaa; } @@ -432,10 +457,14 @@ bool zelda64::renderer::RT64HighPrecisionFBEnabled() { return high_precision_fb_enabled; } +void zelda64::renderer::trigger_texture_pack_update() { + texture_pack_action_queue.enqueue(TexturePackUpdateAction{}); +} + void zelda64::renderer::enable_texture_pack(const recomp::mods::ModHandle& mod) { - texture_pack_action_queue.enqueue(TexturePackEnableAction{mod.manifest.mod_root_path}); + texture_pack_action_queue.enqueue(TexturePackEnableAction{mod.manifest.mod_id}); } void zelda64::renderer::disable_texture_pack(const recomp::mods::ModHandle& mod) { - texture_pack_action_queue.enqueue(TexturePackDisableAction{mod.manifest.mod_root_path}); + texture_pack_action_queue.enqueue(TexturePackDisableAction{mod.manifest.mod_id}); }