diff --git a/.gitignore b/.gitignore index d68b69c..641f274 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,9 @@ *.dSYM /.vs/ /packages/ -/saves/ +/saves/* +!/saves/SAV_TESTS/ +!/saves/testyourmine's/ *.o /sm /build/ diff --git a/saves/SAV_TESTS/001-controller-inputs.sav b/saves/SAV_TESTS/001-controller-inputs.sav new file mode 100644 index 0000000..b3a6bbb Binary files /dev/null and b/saves/SAV_TESTS/001-controller-inputs.sav differ diff --git a/saves/SAV_TESTS/002-intro.sav b/saves/SAV_TESTS/002-intro.sav new file mode 100644 index 0000000..d302777 Binary files /dev/null and b/saves/SAV_TESTS/002-intro.sav differ diff --git a/saves/SAV_TESTS/101-shine-spark.sav b/saves/SAV_TESTS/101-shine-spark.sav new file mode 100644 index 0000000..1bbc645 Binary files /dev/null and b/saves/SAV_TESTS/101-shine-spark.sav differ diff --git a/saves/SAV_TESTS/102-moon-fall.sav b/saves/SAV_TESTS/102-moon-fall.sav new file mode 100644 index 0000000..ce060f4 Binary files /dev/null and b/saves/SAV_TESTS/102-moon-fall.sav differ diff --git a/saves/SAV_TESTS/103-mock-ball.sav b/saves/SAV_TESTS/103-mock-ball.sav new file mode 100644 index 0000000..30d611e Binary files /dev/null and b/saves/SAV_TESTS/103-mock-ball.sav differ diff --git a/saves/SAV_TESTS/104-crystal-flash.sav b/saves/SAV_TESTS/104-crystal-flash.sav new file mode 100644 index 0000000..b56a9f3 Binary files /dev/null and b/saves/SAV_TESTS/104-crystal-flash.sav differ diff --git a/saves/SAV_TESTS/201-alcatraz-escape.sav b/saves/SAV_TESTS/201-alcatraz-escape.sav new file mode 100644 index 0000000..cf82b3b Binary files /dev/null and b/saves/SAV_TESTS/201-alcatraz-escape.sav differ diff --git a/saves/SAV_TESTS/202-green-gate-glitch.sav b/saves/SAV_TESTS/202-green-gate-glitch.sav new file mode 100644 index 0000000..9bd095e Binary files /dev/null and b/saves/SAV_TESTS/202-green-gate-glitch.sav differ diff --git a/saves/SAV_TESTS/999-black-out.sav b/saves/SAV_TESTS/999-black-out.sav new file mode 100644 index 0000000..990fc11 Binary files /dev/null and b/saves/SAV_TESTS/999-black-out.sav differ diff --git a/saves/testyourmine's/100 Percent.sav b/saves/testyourmine's/100 Percent.sav new file mode 100644 index 0000000..9544428 Binary files /dev/null and b/saves/testyourmine's/100 Percent.sav differ diff --git a/saves/testyourmine's/Baby Metroid.sav b/saves/testyourmine's/Baby Metroid.sav new file mode 100644 index 0000000..25e60a1 Binary files /dev/null and b/saves/testyourmine's/Baby Metroid.sav differ diff --git a/saves/testyourmine's/Bluesuit.sav b/saves/testyourmine's/Bluesuit.sav new file mode 100644 index 0000000..20a8ecf Binary files /dev/null and b/saves/testyourmine's/Bluesuit.sav differ diff --git a/saves/testyourmine's/Bomb Torizo.sav b/saves/testyourmine's/Bomb Torizo.sav new file mode 100644 index 0000000..c959177 Binary files /dev/null and b/saves/testyourmine's/Bomb Torizo.sav differ diff --git a/saves/testyourmine's/Botwoon.sav b/saves/testyourmine's/Botwoon.sav new file mode 100644 index 0000000..0215f5f Binary files /dev/null and b/saves/testyourmine's/Botwoon.sav differ diff --git a/saves/testyourmine's/Brinstar Pirates Appear.sav b/saves/testyourmine's/Brinstar Pirates Appear.sav new file mode 100644 index 0000000..0b9898b Binary files /dev/null and b/saves/testyourmine's/Brinstar Pirates Appear.sav differ diff --git a/saves/testyourmine's/Crocomire.sav b/saves/testyourmine's/Crocomire.sav new file mode 100644 index 0000000..1b0458b Binary files /dev/null and b/saves/testyourmine's/Crocomire.sav differ diff --git a/saves/testyourmine's/Draygon.sav b/saves/testyourmine's/Draygon.sav new file mode 100644 index 0000000..2764d54 Binary files /dev/null and b/saves/testyourmine's/Draygon.sav differ diff --git a/saves/testyourmine's/Golden Torizo.sav b/saves/testyourmine's/Golden Torizo.sav new file mode 100644 index 0000000..335d12c Binary files /dev/null and b/saves/testyourmine's/Golden Torizo.sav differ diff --git a/saves/testyourmine's/Gravity Suit.sav b/saves/testyourmine's/Gravity Suit.sav new file mode 100644 index 0000000..3b7776e Binary files /dev/null and b/saves/testyourmine's/Gravity Suit.sav differ diff --git a/saves/testyourmine's/Green Brinstar.sav b/saves/testyourmine's/Green Brinstar.sav new file mode 100644 index 0000000..d42f3c3 Binary files /dev/null and b/saves/testyourmine's/Green Brinstar.sav differ diff --git a/saves/testyourmine's/Kraid's Lair.sav b/saves/testyourmine's/Kraid's Lair.sav new file mode 100644 index 0000000..ccb749f Binary files /dev/null and b/saves/testyourmine's/Kraid's Lair.sav differ diff --git a/saves/testyourmine's/Kraid.sav b/saves/testyourmine's/Kraid.sav new file mode 100644 index 0000000..3d27030 Binary files /dev/null and b/saves/testyourmine's/Kraid.sav differ diff --git a/saves/testyourmine's/Lower Maridia.sav b/saves/testyourmine's/Lower Maridia.sav new file mode 100644 index 0000000..0534bc9 Binary files /dev/null and b/saves/testyourmine's/Lower Maridia.sav differ diff --git a/saves/testyourmine's/Lower Norfair.sav b/saves/testyourmine's/Lower Norfair.sav new file mode 100644 index 0000000..de3c15e Binary files /dev/null and b/saves/testyourmine's/Lower Norfair.sav differ diff --git a/saves/testyourmine's/Mother Brain Phase 1.sav b/saves/testyourmine's/Mother Brain Phase 1.sav new file mode 100644 index 0000000..ff0b2f8 Binary files /dev/null and b/saves/testyourmine's/Mother Brain Phase 1.sav differ diff --git a/saves/testyourmine's/Mother Brain Phase 2.sav b/saves/testyourmine's/Mother Brain Phase 2.sav new file mode 100644 index 0000000..2bd9319 Binary files /dev/null and b/saves/testyourmine's/Mother Brain Phase 2.sav differ diff --git a/saves/testyourmine's/Mother Brain Phase 3.sav b/saves/testyourmine's/Mother Brain Phase 3.sav new file mode 100644 index 0000000..890ecaa Binary files /dev/null and b/saves/testyourmine's/Mother Brain Phase 3.sav differ diff --git a/saves/testyourmine's/Norfair Enter.sav b/saves/testyourmine's/Norfair Enter.sav new file mode 100644 index 0000000..6a0576a Binary files /dev/null and b/saves/testyourmine's/Norfair Enter.sav differ diff --git a/saves/testyourmine's/Phantoon.sav b/saves/testyourmine's/Phantoon.sav new file mode 100644 index 0000000..3096926 Binary files /dev/null and b/saves/testyourmine's/Phantoon.sav differ diff --git a/saves/testyourmine's/Red Brinstar Enter.sav b/saves/testyourmine's/Red Brinstar Enter.sav new file mode 100644 index 0000000..8a54897 Binary files /dev/null and b/saves/testyourmine's/Red Brinstar Enter.sav differ diff --git a/saves/testyourmine's/Red Brinstar Escape.sav b/saves/testyourmine's/Red Brinstar Escape.sav new file mode 100644 index 0000000..bfa5a4c Binary files /dev/null and b/saves/testyourmine's/Red Brinstar Escape.sav differ diff --git a/saves/testyourmine's/Ridley.sav b/saves/testyourmine's/Ridley.sav new file mode 100644 index 0000000..3cfb087 Binary files /dev/null and b/saves/testyourmine's/Ridley.sav differ diff --git a/saves/testyourmine's/Spore Spawn Defeat.sav b/saves/testyourmine's/Spore Spawn Defeat.sav new file mode 100644 index 0000000..b60681b Binary files /dev/null and b/saves/testyourmine's/Spore Spawn Defeat.sav differ diff --git a/saves/testyourmine's/Spore Spawn.sav b/saves/testyourmine's/Spore Spawn.sav new file mode 100644 index 0000000..2de71ef Binary files /dev/null and b/saves/testyourmine's/Spore Spawn.sav differ diff --git a/saves/testyourmine's/Tourian.sav b/saves/testyourmine's/Tourian.sav new file mode 100644 index 0000000..7d3bf9a Binary files /dev/null and b/saves/testyourmine's/Tourian.sav differ diff --git a/saves/testyourmine's/Wrecked Ship.sav b/saves/testyourmine's/Wrecked Ship.sav new file mode 100644 index 0000000..635e8af Binary files /dev/null and b/saves/testyourmine's/Wrecked Ship.sav differ diff --git a/saves/testyourmine's/Zebes Escape.sav b/saves/testyourmine's/Zebes Escape.sav new file mode 100644 index 0000000..883f690 Binary files /dev/null and b/saves/testyourmine's/Zebes Escape.sav differ diff --git a/saves/testyourmine's/Zebes Landing.sav b/saves/testyourmine's/Zebes Landing.sav new file mode 100644 index 0000000..3d296d0 Binary files /dev/null and b/saves/testyourmine's/Zebes Landing.sav differ diff --git a/saves/testyourmine's/sm.srm b/saves/testyourmine's/sm.srm new file mode 100644 index 0000000..78eddc3 Binary files /dev/null and b/saves/testyourmine's/sm.srm differ diff --git a/saves/testyourmine's/sm.srm.bak b/saves/testyourmine's/sm.srm.bak new file mode 100644 index 0000000..400c63a Binary files /dev/null and b/saves/testyourmine's/sm.srm.bak differ diff --git a/sm.ini b/sm.ini index 3b2fae5..de27fad 100644 --- a/sm.ini +++ b/sm.ini @@ -93,6 +93,8 @@ Replay= Ctrl+F1,Ctrl+F2,Ctrl+F3,Ctrl+F4,Ctrl+F5,Ctrl+F6,Ctrl+F7,Ctrl+F8,Ctrl+F9, LoadRef = 1,2,3,4,5,6,7,8,9,0,-,=,Backspace ReplayRef = Ctrl+1,Ctrl+2,Ctrl+3,Ctrl+4,Ctrl+5,Ctrl+6,Ctrl+7,Ctrl+8,Ctrl+9,Ctrl+0,Ctrl+-,Ctrl+=,Ctrl+Backspace +SavTests = Shift+Ctrl+a + [GamepadMap] # Any keys used in KeyMap can be used also in this section. # The shoulder button is called L1/Lb and L2, and the thumbstick button is called L3 diff --git a/src/config.c b/src/config.c index e819119..66a70a8 100644 --- a/src/config.c +++ b/src/config.c @@ -61,6 +61,7 @@ static const KeyNameId kKeyNameId[] = { S(CheatLife), S(CheatJump), S(ToggleWhichFrame), S(ClearKeyLog), S(StopReplay), S(Fullscreen), S(Reset), S(Pause), S(PauseDimmed), S(Turbo), S(ReplayTurbo), S(WindowBigger), S(WindowSmaller), S(VolumeUp), S(VolumeDown), S(DisplayPerf), S(ToggleRenderer), + S(SavTests) }; #undef S #undef M diff --git a/src/config.h b/src/config.h index 724965e..4cce8db 100644 --- a/src/config.h +++ b/src/config.h @@ -34,6 +34,7 @@ enum { kKeys_VolumeUp, kKeys_VolumeDown, kKeys_Total, + kKeys_SavTests }; enum { diff --git a/src/main.c b/src/main.c index 85e5853..50c18b1 100644 --- a/src/main.c +++ b/src/main.c @@ -21,6 +21,7 @@ #include "config.h" #include "util.h" #include "spc_player.h" +#include "rtk2/rtk2_sav_test.h" #ifdef __SWITCH__ #include "switch_impl.h" @@ -451,6 +452,8 @@ int main(int argc, char** argv) { bool has_bug_in_title = false; while (running) { + Rtk2_Rtl_Rtk2SaveTestRunner_StateMachine_Run(); + SDL_Event event; while (SDL_PollEvent(&event)) { @@ -645,6 +648,7 @@ static void HandleCommand(uint32 j, bool pressed) { RtlSaveLoad(kSaveLoad_Replay, 256 + j - kKeys_ReplayRef); } else { switch (j) { + case kKeys_SavTests: Rtk2SavTestRunner_Start(&g_sav_test_runner); break; case kKeys_CheatLife: RtlCheat('w'); break; case kKeys_CheatJump: RtlCheat('q'); break; case kKeys_ToggleWhichFrame: diff --git a/src/rtk2/rtk2_globals.c b/src/rtk2/rtk2_globals.c new file mode 100644 index 0000000..14f84b9 --- /dev/null +++ b/src/rtk2/rtk2_globals.c @@ -0,0 +1 @@ +#include "rtk2_globals.h" \ No newline at end of file diff --git a/src/rtk2/rtk2_globals.h b/src/rtk2/rtk2_globals.h new file mode 100644 index 0000000..97187b9 --- /dev/null +++ b/src/rtk2/rtk2_globals.h @@ -0,0 +1,3 @@ +#pragma once + +#define log(fmt, ...) printf(fmt "\n", ##__VA_ARGS__) \ No newline at end of file diff --git a/src/rtk2/rtk2_sav_test.c b/src/rtk2/rtk2_sav_test.c new file mode 100644 index 0000000..ee9787b --- /dev/null +++ b/src/rtk2/rtk2_sav_test.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include "rtk2_sav_test.h" +#include "rtk2_globals.h" +#include "src/sm_rtl.h" + +static Rtk2SaveTest SavTests[] = { + {001, "SAV_TESTS/001-controller-inputs"}, + {002, "SAV_TESTS/002-intro"}, + {101, "SAV_TESTS/101-shine-spark"}, + {102, "SAV_TESTS/102-moon-fall"}, + {103, "SAV_TESTS/103-mock-ball"}, + {104, "SAV_TESTS/104-crystal-flash"}, + {201, "SAV_TESTS/201-alcatraz-escape"}, + {202, "SAV_TESTS/202-green-gate-glitch"}, + {999, NULL} +}; + +Rtk2SaveTestRunner g_sav_test_runner = { + .state = kSavTestState_NONE, + .now_test_idx = 0, + .tests = SavTests +}; + + +#define now_test(x) x->tests[x->now_test_idx] + +void Rtk2SavTestRunner_ResolveSnapshotFail(Rtk2SaveTestRunner* x, bool has_failed) +{ + if (x->state == kSavTestState_NONE) return; + if (!has_failed) return; + now_test(x).has_failed = has_failed; +} + +void Rtk2SavTestRunner_Start(Rtk2SaveTestRunner* x) +{ + x->state = kSavTestState_STARTING; +} + +void Rtk2SavTestRunner_StateMachine_Run(Rtk2SaveTestRunner* x, bool is_replay) +{ + switch (x->state) + { + case kSavTestState_STARTING: + x->state = kSavTestState_RUNNING; + x->now_test_idx = -1; + log("[SAV_TESTS] - tests stated"); + break; + case kSavTestState_RUNNING: + if (is_replay) return; + x->now_test_idx++; + if (now_test(x).name != NULL) + { + Rtk2_RtlSaveLoad_ByName(kSaveLoad_Replay, now_test(x).name); + } + else + { + Rtk2_RtlSaveLoad_ByName(kSaveLoad_Replay, "SAV_TESTS/999-black-out"); + x->state = kSavTestState_FINISHING; + log("[SAV_TESTS] - tests ended"); + } + break; + case kSavTestState_FINISHING: + log("\n*** SAV TESTS RESULTS ******************"); + for (struct Rtk2SavTest* test = x->tests; test && test->name != NULL; test++) + { + log("TEST #%03d | %s | %s", test->id, test->has_failed ? "FAIL" : "PASS", test->name); + } + log("****************************************"); + x->state = kSavTestState_NONE; + break; + default: + break; + } +} diff --git a/src/rtk2/rtk2_sav_test.h b/src/rtk2/rtk2_sav_test.h new file mode 100644 index 0000000..4561745 --- /dev/null +++ b/src/rtk2/rtk2_sav_test.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include "src/types.h" + +typedef struct Rtk2SavTest { + int id; + const char* name; + bool has_failed; +} Rtk2SaveTest; + +typedef enum +{ + kSavTestState_NONE, + kSavTestState_STARTING, + kSavTestState_RUNNING, + kSavTestState_FINISHING +} SavTestStates; + +typedef struct Rtk2SaveTestRunner { + SavTestStates state; + int8 now_test_idx; + struct Rtk2SavTest* tests; +} Rtk2SaveTestRunner; + +extern Rtk2SaveTestRunner g_sav_test_runner; + +void Rtk2SavTestRunner_Start(Rtk2SaveTestRunner* x); +void Rtk2SavTestRunner_StateMachine_Run(Rtk2SaveTestRunner* x, bool is_replay); +void Rtk2SavTestRunner_ResolveSnapshotFail(Rtk2SaveTestRunner* x, bool has_failed); \ No newline at end of file diff --git a/src/sm.vcxproj b/src/sm.vcxproj index c8840d7..715a2d1 100644 --- a/src/sm.vcxproj +++ b/src/sm.vcxproj @@ -152,6 +152,8 @@ + + @@ -239,6 +241,8 @@ + + diff --git a/src/sm_82.c b/src/sm_82.c index 514d311..7cb86a0 100644 --- a/src/sm_82.c +++ b/src/sm_82.c @@ -5029,28 +5029,26 @@ void OptionsMenuFunc6_DrawControllerBindings(void) { } } + void OptionsMenuControllerFunc_SetBinding(void) { // 0x82F6B9 - uint16 v0 = 12; - while ((kControllerInputMasks[v0 >> 1] & joypad1_newkeys) == 0) { - v0 -= 2; - if ((v0 & 0x8000) != 0) - return; - } - uint16 r18 = v0 >> 1; - uint16 v1 = 2 * menu_option_index + 2; - if (!sign16(2 * menu_option_index - 12)) - v1 = 0; - uint16 v2 = v1; - for (int i = 5; i >= 0; --i) { - if (eproj_F[(v2 >> 1) + 13] == r18) - break; - v2 += 2; - if ((int16)(v2 - 14) >= 0) - v2 = 0; - } - int v4 = menu_option_index; - uint16 r20 = eproj_F[v4 + 13]; - eproj_F[v4 + 13] = r18; - eproj_F[(v2 >> 1) + 13] = r20; - OptionsMenuFunc6_DrawControllerBindings(); -} + // Get the new button pressed, excluding the left and right dpad + + const int16 MAX_INPUT_MASK_INDEX = 6; + int16 mask_index = MAX_INPUT_MASK_INDEX; + while ((kControllerInputMasks[mask_index] & joypad1_newkeys) == 0) { + --mask_index; + if (mask_index < 0) return; + } + + uint16 new_binding = mask_index; + uint16 next_option_down = (menu_option_index + 1) % 7; + + for (int i = 5; i >= 0; --i) { + if (optionsmenu_input_bindings[next_option_down] == new_binding) break; + next_option_down = (next_option_down + 1) % 7; + } + + optionsmenu_input_bindings[next_option_down] = optionsmenu_input_bindings[menu_option_index]; + optionsmenu_input_bindings[menu_option_index] = new_binding; + OptionsMenuFunc6_DrawControllerBindings(); +} \ No newline at end of file diff --git a/src/sm_cpu_infra.c b/src/sm_cpu_infra.c index ec1e34a..8acd0b3 100644 --- a/src/sm_cpu_infra.c +++ b/src/sm_cpu_infra.c @@ -11,6 +11,8 @@ #include "enemy_types.h" #include +#include "rtk2/rtk2_sav_test.h" + void RtlRunFrameCompare(uint16 input, int run_what); enum RunMode { RM_BOTH, RM_MINE, RM_THEIRS }; @@ -991,6 +993,8 @@ void RunOneFrameOfGame_Both(void) { // Compare both snapshots VerifySnapshotsEq(&g_snapshot_mine, &g_snapshot_theirs, &g_snapshot_before); + Rtk2SavTestRunner_ResolveSnapshotFail(&g_sav_test_runner, g_fail); + if (g_fail) { g_fail = false; diff --git a/src/sm_rtl.c b/src/sm_rtl.c index 6cabc43..31c4a75 100644 --- a/src/sm_rtl.c +++ b/src/sm_rtl.c @@ -6,6 +6,7 @@ #include "funcs.h" #include "spc_player.h" #include "util.h" +#include "rtk2/rtk2_sav_test.h" struct StateRecorder; @@ -490,6 +491,52 @@ void RtlSaveLoad(int cmd, int slot) { } } +void Rtk2_Rtl_Rtk2SaveTestRunner_StateMachine_Run() +{ + // added bcuz state_recorder is private + Rtk2SavTestRunner_StateMachine_Run(&g_sav_test_runner, state_recorder.replay_mode); +} + +void Rtk2_RtlSaveLoad_ByName(int cmd, const char* filename) { + //carbon copy of RtlSaveLoad... I'm just to scared to refactor them at this point :D + char name[128]; + sprintf(name, "saves/%s.sav", filename); + + printf("*** %s filename %s\n", cmd == kSaveLoad_Save ? "Saving" : cmd == kSaveLoad_Load ? "Loading" : "Replaying", filename); + if (cmd != kSaveLoad_Save) { + + FILE* f = fopen(name, "rb"); + if (f == NULL) { + printf("Failed fopen: %s\n", name); + return; + } + RtlApuLock(); + StateRecorder_Load(&state_recorder, f, cmd == kSaveLoad_Replay); + ppu_copy(g_snes->my_ppu, g_snes->ppu); + RtlApuUnlock(); + RtlSynchronizeWholeState(); + fclose(f); + + if (coroutine_state_0 | coroutine_state_1 | coroutine_state_2 | coroutine_state_3 | coroutine_state_4) { + printf("Coroutine state: %d, %d, %d, %d, %d\n", + coroutine_state_0, coroutine_state_1, coroutine_state_2, coroutine_state_3, coroutine_state_4); + } + + // Earlier versions used coroutine_state_0 differently + if (coroutine_state_0 == 4) + coroutine_state_0 = 10 + game_state; + + // bug_fix_counter_BAD didn't actually belong to free ram... + if (bug_fix_counter == 0) + bug_fix_counter = bug_fix_counter_BAD; + + } + else { + RtlSaveSnapshot(name, false); + } +} + + /** * @brief Copies size bytes from the source to the destination * @param *dst Pointer to destination diff --git a/src/sm_rtl.h b/src/sm_rtl.h index 624ba99..3a833f8 100644 --- a/src/sm_rtl.h +++ b/src/sm_rtl.h @@ -108,6 +108,9 @@ enum { }; void RtlSaveLoad(int cmd, int slot); + +void Rtk2_Rtl_Rtk2SaveTestRunner_StateMachine_Run(); +void Rtk2_RtlSaveLoad_ByName(int cmd, const char* filename); void RtlCheat(char c); void RtlApuLock(); void RtlApuUnlock();