From 5bdbc882f1bc3cd11adb9ef13729212468198481 Mon Sep 17 00:00:00 2001 From: kipcode66 Date: Mon, 26 Sep 2022 21:32:40 -0400 Subject: [PATCH] fix: updated patch.cpp & dev container (#72) --- .devcontainer/Dockerfile | 14 ++++---- common/rels/include/patch.h | 66 +++++++++++++++++++++++++++++-------- common/rels/src/patch.cpp | 13 ++++++++ 3 files changed, 72 insertions(+), 21 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 2888e895..51d31f8f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -33,10 +33,10 @@ WORKDIR /etc RUN sudo ln -sf /proc/self/mounts mtab RUN sudo dkp-pacman -S --noconfirm gamecube-dev wii-dev -# Install the patchers -WORKDIR /workspaces/romhack/wii -RUN curl -L https://github.com/zsrtp/romhack-compiler/releases/download/v0.1.1-r2/romhack-v0.1.1-r2-linux-x64-musl.zip | bsdtar -xvf - -RUN chmod +x romhack -WORKDIR /workspaces/romhack/gc -RUN curl -L https://github.com/zsrtp/romhack-compiler/releases/download/v0.1.1-r2/romhack-v0.1.1-r2-linux-x64-musl-gc.zip | bsdtar -xvf - -RUN chmod +x romhack +# # Install the patchers +# WORKDIR /workspaces/romhack/wii +# RUN curl -L https://github.com/zsrtp/romhack-compiler/releases/download/v0.1.1-r2/romhack-v0.1.1-r2-linux-x64-musl.zip | bsdtar -xvf - +# RUN chmod +x romhack +# WORKDIR /workspaces/romhack/gc +# RUN curl -L https://github.com/zsrtp/romhack-compiler/releases/download/v0.1.1-r2/romhack-v0.1.1-r2-linux-x64-musl-gc.zip | bsdtar -xvf - +# RUN chmod +x romhack diff --git a/common/rels/include/patch.h b/common/rels/include/patch.h index 83f59a83..113a48b2 100644 --- a/common/rels/include/patch.h +++ b/common/rels/include/patch.h @@ -9,6 +9,7 @@ void writeBranch(void* ptr, void* destination); void writeBranchLR(void* ptr, void* destination); void writeBranchBL(void* ptr, void* destination); void writeBranchMain(void* ptr, void* destination, uint32_t branch); +void writeAbsoluteBranch(void* ptr, void* destination); /** * @brief Hooks a function to execute the provided one instead. @@ -20,14 +21,22 @@ void writeBranchMain(void* ptr, void* destination, uint32_t branch); * @return A pointer to the allocated trampoline. */ template -Func hookFunction(Func function, Dest destination) { +Func hookFunction(Func function, Dest destination, bool absoluteBranch) { uint32_t* instructions = reinterpret_cast(function); + uint32_t instructionCount; + uint32_t* trampoline; + if (absoluteBranch) { + instructionCount = 5; + trampoline = new (sizeof(uint32_t)) uint32_t[instructionCount]; + } else { + instructionCount = 2; #ifdef PLATFORM_WII - uint32_t* trampoline = new (0x4, HEAP_ZELDA) uint32_t[2]; + trampoline = new (sizeof(uint32_t), HEAP_ZELDA) uint32_t[instructionCount]; #else - uint32_t* trampoline = new (0x4) uint32_t[2]; + trampoline = new (sizeof(uint32_t)) uint32_t[instructionCount]; #endif + } // Original instruction trampoline[0] = instructions[0]; @@ -40,9 +49,26 @@ Func hookFunction(Func function, Dest destination) { // Write actual hook writeBranch(&instructions[0], reinterpret_cast(static_cast(destination))); + // Branch to original function past hook + if (absoluteBranch) { + writeAbsoluteBranch(&trampoline[1], &instructions[1]); + } else { + writeBranch(&trampoline[1], &instructions[1]); + } + return reinterpret_cast(trampoline); } +template +Func hookFunction(Func function, Dest destination) { + return hookFunction(function, destination, false); +} + +template +Func hookFunctionAbsolute(Func function, Dest destination) { + return hookFunction(function, destination, true); +} + template Func unhookFunction(Func trampoline) { if (!trampoline) { @@ -50,26 +76,38 @@ Func unhookFunction(Func trampoline) { } uint32_t* instructions = reinterpret_cast(trampoline); + uint32_t instructionCount; + uint32_t* address; + + uint32_t firstInstruction = instructions[1]; + if ((firstInstruction >> 16) == 0x3D80) { // lis r12 + // Absolute branch + instructionCount = 5; + uint32_t instructionAddress = (firstInstruction & 0xFFFF) << 16; // Upper 16 bits + instructionAddress |= (instructions[2] & 0xFFFF); // Lower 16 bits + address = reinterpret_cast(instructionAddress - 0x4); + } else { + // Standard branchinstructionCount = 2; + int32_t branchLength = firstInstruction & 0x03FFFFFC; - // Restore the original instruction - int32_t branchLength = instructions[1] & 0x03FFFFFC; + // Check if this is a negative branch + if (branchLength > 0x01FFFFFC) { + const int32_t Width = 26; + const int32_t Mask = (1 << (Width - 1)); + branchLength = (branchLength ^ Mask) - Mask - 0x4; + } - // Check if this is a negative branch - if (branchLength > 0x01FFFFFC) { - const int32_t Width = 26; - const int32_t Mask = (1 << (Width - 1)); - branchLength = (branchLength ^ Mask) - Mask - 0x4; + uint32_t instructionAddress = reinterpret_cast(&instructions[1]); + address = reinterpret_cast(instructionAddress + branchLength); } - uint32_t instructionAddress = reinterpret_cast(&instructions[1]); - uint32_t* address = reinterpret_cast(instructionAddress + branchLength); *address = instructions[0]; // Clear the cache for both the address and where the instructions were stored DCFlushRange(address, sizeof(uint32_t)); ICInvalidateRange(address, sizeof(uint32_t)); - DCFlushRange(instructions, sizeof(uint32_t)); - ICInvalidateRange(instructions, sizeof(uint32_t)); + DCFlushRange(instructions, sizeof(uint32_t) * instructionCount); + ICInvalidateRange(instructions, sizeof(uint32_t) * instructionCount); // Free the memory used by the trampoline delete[] instructions; diff --git a/common/rels/src/patch.cpp b/common/rels/src/patch.cpp index 60b94508..e5dcbbd1 100644 --- a/common/rels/src/patch.cpp +++ b/common/rels/src/patch.cpp @@ -29,3 +29,16 @@ void writeBranchMain(void* ptr, void* destination, uint32_t branch) { DCFlushRange(ptr, sizeof(uint32_t)); ICInvalidateRange(ptr, sizeof(uint32_t)); } + +void writeAbsoluteBranch(void* ptr, void* destination) { + uint32_t dstRaw = reinterpret_cast(destination); + uint32_t* code = reinterpret_cast(ptr); + + code[0] = 0x3D800000 | (dstRaw >> 16); // lis r12,dstRaw@h + code[1] = 0x618C0000 | (dstRaw & 0xFFFF); // ori r12,r12,dstRaw@l + code[2] = 0x7D8903A6; // mtctr r12 + code[3] = 0x4E800420; // bctr + + DCFlushRange(ptr, sizeof(uint32_t) * 4); + ICInvalidateRange(ptr, sizeof(uint32_t) * 4); +}