From d6080984d1dc52bd81cb538513119ac9e874cf14 Mon Sep 17 00:00:00 2001 From: Mow <32942550+taxicat1@users.noreply.github.com> Date: Wed, 31 Dec 2025 01:51:40 -0500 Subject: [PATCH] Add overlay patch for hombrew AP in Rabbids Go Homeh (#82) --- arm9/source/Arm9Patcher.cpp | 8 +++++ .../RabbidsGoHome/RabbidsGoHomePatch.cpp | 31 +++++++++++++++++ .../RabbidsGoHome/RabbidsGoHomePatch.h | 17 ++++++++++ .../RabbidsGoHome/RabbidsGoHomePatchAsm.h | 10 ++++++ .../RabbidsGoHome/RabbidsGoHomePatchAsm.s | 34 +++++++++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.cpp create mode 100644 arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.h create mode 100644 arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatchAsm.h create mode 100644 arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatchAsm.s diff --git a/arm9/source/Arm9Patcher.cpp b/arm9/source/Arm9Patcher.cpp index 55a4809..9c54189 100644 --- a/arm9/source/Arm9Patcher.cpp +++ b/arm9/source/Arm9Patcher.cpp @@ -22,6 +22,7 @@ #include "patches/arm9/OverlayPatches/DSProtectPatches/DSProtectPuyoPuyo7Patch.h" #include "patches/arm9/OverlayPatches/PokemonIr/PokemonIrApPatch.h" #include "patches/arm9/OverlayPatches/KirbySuperStarUltra/KirbySuperStarUltraPatch.h" +#include "patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.h" #include "patches/arm9/OverlayPatches/GoldenSunDarkDawn/GoldenSunDarkDawnOverlayHookPatch.h" #include "SecureSysCallsUnusedSpaceLocator.h" #include "fastSearch.h" @@ -405,6 +406,13 @@ void Arm9Patcher::AddGameSpecificPatches( patchCollection.AddPatch(new NintendoDSGuideNandSavePatch()); break; } + // Rabbids Go Home + case GAMECODE("VRGE"): + case GAMECODE("VRGV"): + { + overlayHookPatch->AddOverlayPatch(new RabbidsGoHomePatch()); + break; + } // Kirby Super Star Ultra case GAMECODE("YKWE"): case GAMECODE("YKWJ"): diff --git a/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.cpp b/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.cpp new file mode 100644 index 0000000..ee96d0b --- /dev/null +++ b/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.cpp @@ -0,0 +1,31 @@ +#include "common.h" +#include "gameCode.h" +#include "patches/PatchContext.h" +#include "RabbidsGoHomePatchAsm.h" +#include "RabbidsGoHomePatch.h" + +const void* RabbidsGoHomePatch::InsertPatch(PatchContext& patchContext) +{ + rabbidspatch_nextAddress = next ? (const void*)next->InsertPatch(patchContext) : nullptr; + + switch (patchContext.GetGameCode()) + { + case GAMECODE("VRGE"): + { + rabbidspatch_offset = 0x1465C + 0x1C; + break; + } + case GAMECODE("VRGV"): + { + rabbidspatch_offset = 0x146A4 + 0x1C; + break; + } + } + + u32 patchSize = SECTION_SIZE(rabbidspatch); + void* patchAddress = patchContext.GetPatchHeap().Alloc(patchSize); + u32 entryAddress = (u32)&rabbidspatch_entry - (u32)SECTION_START(rabbidspatch) + (u32)patchAddress; + memcpy(patchAddress, SECTION_START(rabbidspatch), patchSize); + + return (const void*)entryAddress; +} diff --git a/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.h b/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.h new file mode 100644 index 0000000..cf4b26e --- /dev/null +++ b/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatch.h @@ -0,0 +1,17 @@ +#pragma once +#include "../OverlayPatch.h" + +/// @brief Arm9 overlay patch for Rabbids Go Home. +/// @details +/// This game has a homebrew AP method based on ROM read timings. Specifically, it will +/// run 100 ROM reads of 0x4000 bytes each, or 32 0x200-byte pages, and use ticks to time how +/// long it takes. It must take between 0x80000 and 0x88000 ticks, or 1.001 to 1.063 seconds, +/// or the game will hang prior to the title screen (after the publisher splash and language selection). +/// The actual contents of the ROM reads are not checked, and they are obtained using TWL SDK CARD_ReadRom. +/// +/// To bypass this, most of the function that runs the AP check is skipped, as it has no other side effects. +class RabbidsGoHomePatch : public OverlayPatch +{ +public: + const void* InsertPatch(PatchContext& patchContext) override; +}; diff --git a/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatchAsm.h b/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatchAsm.h new file mode 100644 index 0000000..7fd1deb --- /dev/null +++ b/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatchAsm.h @@ -0,0 +1,10 @@ +#pragma once +#include "sections.h" + +DEFINE_SECTION_SYMBOLS(rabbidspatch); + +extern "C" void rabbidspatch_entry(); + +extern u32 rabbidspatch_offset; + +extern const void* rabbidspatch_nextAddress; // Next patch address diff --git a/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatchAsm.s b/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatchAsm.s new file mode 100644 index 0000000..6674394 --- /dev/null +++ b/arm9/source/patches/arm9/OverlayPatches/RabbidsGoHome/RabbidsGoHomePatchAsm.s @@ -0,0 +1,34 @@ +.cpu arm946e-s +.syntax unified +.section "rabbidspatch", "ax" +.thumb + +.global rabbidspatch_entry +.type rabbidspatch_entry, %function +rabbidspatch_entry: + push {r5,lr} + ldm r5!, {r0, r1} // ovy_id, ram_start + cmp r0, #1 + bne continue_to_next + + ldr r2, rabbidspatch_offset + ldr r0, =0xE3A00001 // mov r0, #1 + str r0, [r1, r2] + +continue_to_next: + ldr r0, rabbidspatch_nextAddress + pop {r5,pc} + +.balign 4 + +.global rabbidspatch_offset +rabbidspatch_offset: + .word 0 + +.global rabbidspatch_nextAddress +rabbidspatch_nextAddress: + .word 0 + +.pool + +.end