shithub: zelda3

Download patch

ref: fda3f90cf516fa5a1172f9c4773f85864ca324e9
parent: aa6b257fd20b9ed3f1a1c2755253249ee510f249
author: Snesrev <snesrev@protonmail.com>
date: Wed Sep 28 08:54:16 EDT 2022

Hold tab for ~16x turbo mode

--- a/README.md
+++ b/README.md
@@ -110,6 +110,7 @@
 
 | Key | Action                |
 | --- | --------------------- |
+| Tab | Turbo mode |
 | W   | Fill health/magic     |
 | Shift+W   | Fill rupees/bombs/arrows     |
 | Ctrl+E | Reset            |
@@ -117,7 +118,7 @@
 | Shift+P   | Pause (without dim)                |
 | Ctrl+Up   | Increase window size                |
 | Ctrl+Down   | Decrease window size                |
-| T   | Toggle replay turbo   |
+| T   | Toggle replay turbo mode  |
 | O   | Set dungeon key to 1  |
 | K   | Clear all input history from the joypad log  |
 | L   | Stop replaying a shapshot  |
--- a/config.c
+++ b/config.c
@@ -33,8 +33,8 @@
   _(SDLK_1), _(SDLK_2), _(SDLK_3), _(SDLK_4), _(SDLK_5), _(SDLK_6), _(SDLK_7), _(SDLK_8), _(SDLK_9), _(SDLK_0), _(SDLK_MINUS), _(SDLK_EQUALS), _(SDLK_BACKSPACE), N, N, N, N, N, N, N,
   // Replay Ref State
   C(SDLK_1), C(SDLK_2), C(SDLK_3), C(SDLK_4), C(SDLK_5), C(SDLK_6), C(SDLK_7), C(SDLK_8), C(SDLK_9), C(SDLK_0), C(SDLK_MINUS), C(SDLK_EQUALS), C(SDLK_BACKSPACE), N, N, N, N, N, N, N,
-  // CheatLife, CheatKeys, CheatEquipment, ClearKeyLog, StopReplay, Fullscreen, Reset, Pause, PauseDimmed, Turbo, WindowBigger, WindowSmaller, DisplayPerf, ToggleRenderer
-  _(SDLK_w), _(SDLK_o), S(SDLK_w), _(SDLK_k), _(SDLK_l), A(SDLK_RETURN), _(SDLK_e), S(SDLK_p), _(SDLK_p), _(SDLK_t), N, N, _(SDLK_f), _(SDLK_r),
+  // CheatLife, CheatKeys, CheatEquipment, ClearKeyLog, StopReplay, Fullscreen, Reset, Pause, PauseDimmed, Turbo, ReplayTurbo, WindowBigger, WindowSmaller, DisplayPerf, ToggleRenderer
+  _(SDLK_w), _(SDLK_o), S(SDLK_w), _(SDLK_k), _(SDLK_l), A(SDLK_RETURN), _(SDLK_e), S(SDLK_p), _(SDLK_p), _(SDLK_TAB), _(SDLK_t), N, N, _(SDLK_f), _(SDLK_r),
 };
 #undef _
 #undef A
@@ -52,7 +52,7 @@
 static const KeyNameId kKeyNameId[] = {
   M(Controls), M(Load), M(Save), M(Replay), M(LoadRef), M(ReplayRef),
   S(CheatLife), S(CheatKeys), S(CheatEquipment), S(ClearKeyLog), S(StopReplay), S(Fullscreen), S(Reset),
-  S(Pause), S(PauseDimmed), S(Turbo), S(WindowBigger), S(WindowSmaller), S(DisplayPerf), S(ToggleRenderer),
+  S(Pause), S(PauseDimmed), S(Turbo), S(ReplayTurbo), S(WindowBigger), S(WindowSmaller), S(DisplayPerf), S(ToggleRenderer),
 };
 #undef S
 #undef M
--- a/config.h
+++ b/config.h
@@ -25,6 +25,7 @@
   kKeys_Pause,
   kKeys_PauseDimmed,
   kKeys_Turbo,
+  kKeys_ReplayTurbo,
   kKeys_WindowBigger,
   kKeys_WindowSmaller,
   kKeys_DisplayPerf,
--- a/main.c
+++ b/main.c
@@ -32,7 +32,7 @@
 void CopyStateAfterSnapshotRestore(bool is_reset);
 void SaveLoadSlot(int cmd, int which);
 void PatchCommand(char cmd);
-bool RunOneFrame(Snes *snes, int input_state, bool turbo);
+bool RunOneFrame(Snes *snes, int input_state);
 
 static bool LoadRom(const char *name, Snes *snes);
 static void PlayAudio(Snes *snes, SDL_AudioDeviceID device, int channels, int16 *audioBuffer);
@@ -57,7 +57,7 @@
 static uint32 g_win_flags = SDL_WINDOW_RESIZABLE;
 static SDL_Window *g_window;
 static SDL_Renderer *g_renderer;
-static uint8 g_paused, g_turbo = true, g_cursor = true;
+static uint8 g_paused, g_turbo, g_replay_turbo = true, g_cursor = true;
 static uint8 g_current_window_scale;
 static int g_samples_per_block;
 static uint8 g_gamepad_buttons;
@@ -373,9 +373,9 @@
     if ((inputs & 0x30) == 0x30) inputs ^= 0x30;
     if ((inputs & 0xc0) == 0xc0) inputs ^= 0xc0;
 
-    bool is_turbo = RunOneFrame(snes_run, inputs, (frameCtr++ & 0x7f) != 0 && g_turbo);
+    bool is_replay = RunOneFrame(snes_run, inputs);
 
-    if (is_turbo)
+    if ((g_turbo ^ (is_replay & g_replay_turbo)) && (frameCtr++ & (g_turbo ? 0xf : 0x7f)) != 0)
       continue;
 
 
@@ -550,6 +550,12 @@
     SetButtonState(kKbdRemap[j], pressed);
     return;
   }
+
+  if (j == kKeys_Turbo) {
+    g_turbo = pressed;
+    return;
+  }
+
   if (!pressed)
     return;
   if (j <= kKeys_Load_Last) {
@@ -590,7 +596,7 @@
         SDL_RenderPresent(g_renderer);
       }
       break;
-    case kKeys_Turbo: g_turbo = !g_turbo; break;
+    case kKeys_ReplayTurbo: g_replay_turbo = !g_replay_turbo; break;
     case kKeys_WindowBigger: ChangeWindowScale(1); break;
     case kKeys_WindowSmaller: ChangeWindowScale(-1); break;
     case kKeys_DisplayPerf: g_display_perf ^= 1; break;
--- a/zelda3.ini
+++ b/zelda3.ini
@@ -88,7 +88,8 @@
 Reset = Ctrl+e
 Pause = Shift+p
 PauseDimmed = p
-Turbo = t
+Turbo = Tab
+ReplayTurbo = t
 WindowBigger = Ctrl+Up
 WindowSmaller = Ctrl+Down
 
--- a/zelda_cpu_infra.c
+++ b/zelda_cpu_infra.c
@@ -697,16 +697,16 @@
 }
 #endif
 
-bool RunOneFrame(Snes *snes, int input_state, bool turbo) {
+bool RunOneFrame(Snes *snes, int input_state) {
+  bool is_replay = state_recorder.replay_mode;
   frame_ctr++;
 
   // Either copy state or apply state
-  if (state_recorder.replay_mode) {
+  if (is_replay) {
     input_state = StateRecorder_ReadNextReplayState(&state_recorder);
   } else {
     //    input_state = InputStateReadFromFile();
     StateRecorder_Record(&state_recorder, input_state);
-    turbo = false;
 
     // This is whether APUI00 is true or false, this is used by the ancilla code.
     uint8 apui00 = ZeldaIsMusicPlaying();
@@ -746,7 +746,7 @@
   if (snes == NULL || enhanced_features0 != 0) {
     // can't compare against real impl when running with extra features.
     ZeldaRunFrame(input_state, run_what);
-    return turbo;
+    return is_replay;
   }
 
   if (g_fail)
@@ -795,7 +795,7 @@
     }
   }
 
-  return turbo;
+  return is_replay;
 }
 
 void PatchRomBP(uint8_t *rom, uint32_t addr) {