Skip to content

Commit

Permalink
fix: updated patch.cpp & dev container (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
kipcode66 authored Sep 27, 2022
1 parent 7cb19e3 commit 5bdbc88
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 21 deletions.
14 changes: 7 additions & 7 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
66 changes: 52 additions & 14 deletions common/rels/include/patch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -20,14 +21,22 @@ void writeBranchMain(void* ptr, void* destination, uint32_t branch);
* @return A pointer to the allocated trampoline.
*/
template <typename Func, typename Dest>
Func hookFunction(Func function, Dest destination) {
Func hookFunction(Func function, Dest destination, bool absoluteBranch) {
uint32_t* instructions = reinterpret_cast<uint32_t*>(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];
Expand All @@ -40,36 +49,65 @@ Func hookFunction(Func function, Dest destination) {
// Write actual hook
writeBranch(&instructions[0], reinterpret_cast<void*>(static_cast<Func>(destination)));

// Branch to original function past hook
if (absoluteBranch) {
writeAbsoluteBranch(&trampoline[1], &instructions[1]);
} else {
writeBranch(&trampoline[1], &instructions[1]);
}

return reinterpret_cast<Func>(trampoline);
}

template <typename Func, typename Dest>
Func hookFunction(Func function, Dest destination) {
return hookFunction(function, destination, false);
}

template <typename Func, typename Dest>
Func hookFunctionAbsolute(Func function, Dest destination) {
return hookFunction(function, destination, true);
}

template <typename Func>
Func unhookFunction(Func trampoline) {
if (!trampoline) {
return nullptr;
}

uint32_t* instructions = reinterpret_cast<uint32_t*>(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<uint32_t*>(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<uint32_t>(&instructions[1]);
address = reinterpret_cast<uint32_t*>(instructionAddress + branchLength);
}

uint32_t instructionAddress = reinterpret_cast<uint32_t>(&instructions[1]);
uint32_t* address = reinterpret_cast<uint32_t*>(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;
Expand Down
13 changes: 13 additions & 0 deletions common/rels/src/patch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint32_t>(destination);
uint32_t* code = reinterpret_cast<uint32_t*>(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);
}

0 comments on commit 5bdbc88

Please sign in to comment.