From a857af008dbb9cd0d55ce0f3132c50cc6a9a5c4c Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Fri, 9 Jan 2026 17:07:09 -0500 Subject: [PATCH] Add functionality needed for HFR launcher --- ultramodern/include/ultramodern/config.hpp | 5 +++++ .../include/ultramodern/renderer_context.hpp | 1 + ultramodern/src/events.cpp | 17 +++++++++++------ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/ultramodern/include/ultramodern/config.hpp b/ultramodern/include/ultramodern/config.hpp index a8cd8e0..2f22456 100644 --- a/ultramodern/include/ultramodern/config.hpp +++ b/ultramodern/include/ultramodern/config.hpp @@ -57,6 +57,11 @@ namespace ultramodern { Off, OptionCount }; + enum class PresentationMode { + Console, + SkipBuffering, + PresentEarly + }; class GraphicsConfig { public: diff --git a/ultramodern/include/ultramodern/renderer_context.hpp b/ultramodern/include/ultramodern/renderer_context.hpp index 43032ea..d60c4ec 100644 --- a/ultramodern/include/ultramodern/renderer_context.hpp +++ b/ultramodern/include/ultramodern/renderer_context.hpp @@ -84,6 +84,7 @@ namespace ultramodern { virtual void enable_instant_present() = 0; virtual void send_dl(const OSTask* task) = 0; + virtual void send_dummy_workload(uint32_t fb_address) = 0; virtual void update_screen() = 0; virtual void shutdown() = 0; virtual uint32_t get_display_framerate() const = 0; diff --git a/ultramodern/src/events.cpp b/ultramodern/src/events.cpp index 1cd7907..090cc42 100644 --- a/ultramodern/src/events.cpp +++ b/ultramodern/src/events.cpp @@ -35,7 +35,11 @@ struct ScreenUpdateAction { struct UpdateConfigAction { }; -using Action = std::variant; +struct DummyWorkloadAction { + int32_t fb_address; +}; + +using Action = std::variant; struct ViState { const OSViMode* mode; @@ -214,6 +218,8 @@ void vi_thread_func() { static bool odd = false; set_dummy_vi(odd); odd = !odd; + + events_context.action_queue.enqueue(DummyWorkloadAction{events_context.vi.get_next_state()->framebuffer}); } // Queue a screen update for the graphics thread with the current VI register state. @@ -353,11 +359,6 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re if (events_context.action_queue.wait_dequeue_timed(action, 1ms)) { // Determine the action type and act on it if (const auto* task_action = std::get_if(&action)) { - // Turn on instant present if the game has been started and it hasn't been turned on yet. - if (ultramodern::is_game_started() && !enabled_instant_present) { - renderer_context->enable_instant_present(); - enabled_instant_present = true; - } // Tell the game that the RSP completed instantly. This will allow it to queue other task types, but it won't // start another graphics task until the RDP is also complete. Games usually preserve the RSP inputs until the RDP // is finished as well, so sending this early shouldn't be an issue in most cases. @@ -391,6 +392,9 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re old_config = new_config; } } + else if (const auto* dummy_workload_action = std::get_if(&action)) { + renderer_context->send_dummy_workload(dummy_workload_action->fb_address); + } } } @@ -442,6 +446,7 @@ static const OSViMode dummy_mode = []() { void set_dummy_vi(bool odd) { ViState* next_state = events_context.vi.get_next_state(); next_state->mode = &dummy_mode; + next_state->control = next_state->mode->comRegs.ctrl; // Set up a dummy framebuffer. next_state->framebuffer = 0x80700000; if (odd) {