From 9932dabc4ce6295dc2fffbb0ecd3484cbb389a2b Mon Sep 17 00:00:00 2001 From: Matthew Stanley <1379tech@gmail.com> Date: Fri, 19 Jun 2026 10:34:01 -0700 Subject: [PATCH] launcher: add Turbo loads toggle (Settings, default off) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exposes turbo-through-loads as a launcher Settings option instead of a game.toml-only knob. Turbo runs the guest unpaced + mutes audio while the CD data stream is active (faster loads, but a brief audio cut/fade). Now defaults OFF so loads play at natural 60fps with continuous audio (disc_speed=instant already keeps data delivery fast); users opt into turbo via the launcher. Wired through the full settings chain, mirroring auto_skip_fmv: UserSettings turbo_loads/has_turbo_loads, settings.toml read+write, runtime override/seed/ apply over game.toml [runtime] turbo_loads, launcher data-model + toggle event, and the RML row. Runtime/launcher only — no regen, codegen unaffected. Co-Authored-By: Claude Opus 4.8 --- recompiler/src/config_loader.cpp | 5 +++++ recompiler/src/config_loader.h | 5 +++++ runtime/launcher/assets/launcher.rml | 3 +++ runtime/launcher/launcher.cpp | 9 +++++++++ runtime/src/main.cpp | 3 +++ 5 files changed, 25 insertions(+) diff --git a/recompiler/src/config_loader.cpp b/recompiler/src/config_loader.cpp index d1d78b01..55ca7d45 100644 --- a/recompiler/src/config_loader.cpp +++ b/recompiler/src/config_loader.cpp @@ -757,6 +757,9 @@ UserSettings load_user_settings(const fs::path& path) { if (v.contains("auto_skip_fmv")) try_get([&]{ s.auto_skip_fmv = toml::find(v, "auto_skip_fmv"); s.has_auto_skip_fmv = true; }); + if (v.contains("turbo_loads")) try_get([&]{ + s.turbo_loads = toml::find(v, "turbo_loads"); s.has_turbo_loads = true; + }); if (v.contains("low_latency_input")) try_get([&]{ s.low_latency_input = toml::find(v, "low_latency_input"); s.has_low_latency_input = true; @@ -900,6 +903,8 @@ bool save_user_settings(const fs::path& path, const UserSettings& s) { } if (s.has_auto_skip_fmv) f << "auto_skip_fmv = " << (s.auto_skip_fmv ? "true" : "false") << "\n"; + if (s.has_turbo_loads) + f << "turbo_loads = " << (s.turbo_loads ? "true" : "false") << "\n"; if (s.has_low_latency_input) f << "low_latency_input = " << (s.low_latency_input ? "true" : "false") << "\n"; if (s.has_vsync) diff --git a/recompiler/src/config_loader.h b/recompiler/src/config_loader.h index ba26b2dd..a675d29c 100644 --- a/recompiler/src/config_loader.h +++ b/recompiler/src/config_loader.h @@ -381,6 +381,11 @@ struct UserSettings { bool has_texture_filter = false; int texture_filter = 0; // 0=nearest,1=bilinear bool has_screen_kind = false; int screen_kind = 0; // 0..3 (ScreenKind) bool has_auto_skip_fmv = false; bool auto_skip_fmv = false; // skip FMVs + // Turbo through in-game load screens: run the guest unpaced (host speed) + + // mute audio while the CD data stream is active. Faster loads, but the audio + // briefly cuts/fades. Ships OFF (default) so loads play at natural speed with + // continuous audio (disc_speed=instant already keeps the data delivery fast). + bool has_turbo_loads = false; bool turbo_loads = false; // Low-latency present knobs. low_latency_input re-samples the pad after the // wall-clock pacer (just before present) so the next CPU frame reads fresh // input instead of input ~one frame stale (the dominant input->photon cost diff --git a/runtime/launcher/assets/launcher.rml b/runtime/launcher/assets/launcher.rml index 5340db64..b9ecb4ec 100644 --- a/runtime/launcher/assets/launcher.rml +++ b/runtime/launcher/assets/launcher.rml @@ -340,6 +340,9 @@ button:hover { background-color: #232d3c; }
Skip FMVs
+
Turbo loads + + faster loading, briefly mutes audio
Widescreen EXPERIMENTAL 16:9 native field-of-view
diff --git a/runtime/launcher/launcher.cpp b/runtime/launcher/launcher.cpp index be7204d1..703caaaa 100644 --- a/runtime/launcher/launcher.cpp +++ b/runtime/launcher/launcher.cpp @@ -99,6 +99,7 @@ struct LauncherModel { int texture_filter = 0; // 0=nearest, 1=bilinear int crt = 0; // 0=raw,1=crt,2=composite,3=trinitron bool auto_skip_fmv = false; // skip FMVs via the game's own skip + bool turbo_loads = false; // speed through load screens (mutes audio); default off bool spu_hq = false; int aspect_index = 0; // index into kAspects (0 = 4:3 native) int window_width = 1280; // window size (height = width*den/num per aspect) @@ -647,6 +648,7 @@ Result run(SDL_Window* window, void* gl_context, m.texture_filter = io.texture_filter; m.crt = io.screen_kind; m.auto_skip_fmv = io.auto_skip_fmv; + m.turbo_loads = io.turbo_loads; m.spu_hq = io.spu_hq; m.aspect_index = io.has_aspect_ratio ? aspect_index_for(io.aspect_num, io.aspect_den) : 0; m.window_width = kWinWidths[winsize_index(io.has_window_width ? io.window_width : 1280)]; @@ -691,6 +693,7 @@ Result run(SDL_Window* window, void* gl_context, c.Bind("supersampling", &m.supersampling); c.Bind("antialiasing", &m.antialiasing); c.Bind("auto_skip_fmv", &m.auto_skip_fmv); + c.Bind("turbo_loads", &m.turbo_loads); c.Bind("spu_hq", &m.spu_hq); c.Bind("renderer_label", &m.renderer_label); c.Bind("crt_label", &m.crt_label); @@ -804,6 +807,11 @@ Result run(SDL_Window* window, void* gl_context, m.auto_skip_fmv = !m.auto_skip_fmv; handle.DirtyVariable("auto_skip_fmv"); }); + c.BindEventCallback("toggle_turbo_loads", + [&m, handle](Rml::DataModelHandle, Rml::Event&, const Rml::VariantList&) mutable { + m.turbo_loads = !m.turbo_loads; + handle.DirtyVariable("turbo_loads"); + }); c.BindEventCallback("browse_bios", [&m, window, handle](Rml::DataModelHandle, Rml::Event&, const Rml::VariantList&) mutable { std::string p = win_pick_file(window, "Select PlayStation BIOS", @@ -990,6 +998,7 @@ Result run(SDL_Window* window, void* gl_context, io.texture_filter = m.texture_filter; io.has_texture_filter = true; io.screen_kind = m.crt; io.has_screen_kind = true; io.auto_skip_fmv = m.auto_skip_fmv; io.has_auto_skip_fmv = true; + io.turbo_loads = m.turbo_loads; io.has_turbo_loads = true; io.spu_hq = m.spu_hq; io.has_spu_hq = true; io.aspect_num = kAspects[m.aspect_index][0]; io.aspect_den = kAspects[m.aspect_index][1]; diff --git a/runtime/src/main.cpp b/runtime/src/main.cpp index 3cb730a0..232f75b7 100644 --- a/runtime/src/main.cpp +++ b/runtime/src/main.cpp @@ -1936,6 +1936,7 @@ int main(int argc, char** argv) { if (us.has_texture_filter) g_video_texfilter = us.texture_filter; if (us.has_screen_kind) g_video_screen = us.screen_kind; if (us.has_auto_skip_fmv) g_auto_skip_fmv = us.auto_skip_fmv ? 1 : 0; + if (us.has_turbo_loads) g_turbo_loads_enabled = us.turbo_loads ? 1 : 0; if (us.has_aspect_ratio) { g_video_aspect_num = us.aspect_num; g_video_aspect_den = us.aspect_den; @@ -2032,6 +2033,7 @@ int main(int argc, char** argv) { seed.texture_filter = g_video_texfilter; seed.has_texture_filter = true; seed.screen_kind = g_video_screen; seed.has_screen_kind = true; seed.auto_skip_fmv = (g_auto_skip_fmv != 0); seed.has_auto_skip_fmv = true; + seed.turbo_loads = (g_turbo_loads_enabled != 0); seed.has_turbo_loads = true; seed.aspect_num = g_video_aspect_num; seed.aspect_den = g_video_aspect_den; seed.has_aspect_ratio = true; seed.spu_hq = g_audio_spu_hq; seed.has_spu_hq = true; @@ -2099,6 +2101,7 @@ int main(int argc, char** argv) { g_video_texfilter = seed.texture_filter; g_video_screen = seed.screen_kind; g_auto_skip_fmv = seed.auto_skip_fmv ? 1 : 0; + g_turbo_loads_enabled = seed.turbo_loads ? 1 : 0; g_video_aspect_num = seed.aspect_num; g_video_aspect_den = seed.aspect_den; g_audio_spu_hq = seed.spu_hq;