Add functionality needed for HFR launcher

This commit is contained in:
Mr-Wiseguy 2026-01-09 17:07:09 -05:00
parent 8441e2252a
commit a857af008d
3 changed files with 17 additions and 6 deletions

View file

@ -57,6 +57,11 @@ namespace ultramodern {
Off,
OptionCount
};
enum class PresentationMode {
Console,
SkipBuffering,
PresentEarly
};
class GraphicsConfig {
public:

View file

@ -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;

View file

@ -35,7 +35,11 @@ struct ScreenUpdateAction {
struct UpdateConfigAction {
};
using Action = std::variant<SpTaskAction, ScreenUpdateAction, UpdateConfigAction>;
struct DummyWorkloadAction {
int32_t fb_address;
};
using Action = std::variant<SpTaskAction, ScreenUpdateAction, UpdateConfigAction, DummyWorkloadAction>;
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<SpTaskAction>(&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<DummyWorkloadAction>(&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) {