Skip to content

Commit

Permalink
fix and improve olmec patch
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr-Auto committed Sep 23, 2023
1 parent a47fa49 commit e3b4394
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 52 deletions.
110 changes: 62 additions & 48 deletions src/game_api/game_patches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,73 +69,41 @@ bool check_if_ent_type_exists(ENT_TYPE type, int mask)
return false;
}

size_t g_olmec_patch_size;
size_t g_olmec_patch_addr;
void patch_olmec_kill_crash()
{
/*
* The idea: do what's necessary xd
*/
static bool once = false;
if (once)
return;

// [patch ... whatever this code does]

const auto offset = get_address("olmec_lookup_crash");
constexpr auto code_to_move = 7;
auto memory = Memory::get();
size_t return_addr;
{
// find address to escape to

auto rva = offset - memory.exe_ptr;
// there are two jump that performe long jump, at the end, of it, the is 'mov rax,qword ptr ds:[rdi]', then find jump that's jumps over that code and create sound meta call
// this is actually unique pattern
auto jump_out_lookup = find_inst(memory.exe(), "\x48\x8B\x45\x50\x48\x83\x78\x60\x00"sv, rva, std::nullopt, "patch_olmec_kill_crash");
size_t rva = offset - memory.exe_ptr;
// below the patched code there are two jumps that performe long jump, at the end of it there is 'mov rax,qword ptr ds:[rdi]',
// from this point find jump that's jumps over sond meta and fmod stuff, the jump ends up on code `mov eax,dword ptr ss:[rbp+10]`, that's our target for return_addr
auto jump_out_lookup = find_inst(memory.exe(), "\x48\xC7\x40\x60\x00\x00\x00\x00"sv, rva, rva + 0x69D, "patch_olmec_kill_crash");
if (jump_out_lookup == 0)
return;

// could probably just make static offset from this stuff
auto jump_offset_offset = memory.at_exe(jump_out_lookup + 10); // 4 (lookup instruction size) + 1 (jump instruction)
auto jump_offset = memory_read<int8_t>(jump_offset_offset);
return_addr = jump_offset_offset + 1 + jump_offset; // +1 to get address after the jump
}
{
// patch the cutscene

const auto function_offset = get_virtual_function_address(VTABLE_OFFSET::THEME_OLMEC, 24); // spawn_effects
const auto jump_out_lookup = get_address("olmec_lookup_in_theme");
if (jump_out_lookup == 0)
return;

// find first jump (skips the whole funciton)
auto end_function_jump = find_inst(memory.exe(), "\x0F\x84"sv, function_offset, function_offset + 0xC3, "patch_olmec_kill_crash");
if (end_function_jump == 0)
return;

auto jump_addr = memory.at_exe(end_function_jump);
auto addr_to_jump_to = jump_addr + 6 + memory_read<int32_t>(jump_addr + 2);
std::string clear_ic8_code = fmt::format(
"\x48\xb8{}" // movabs RAX, &clear_cutscene_behavior
"\xff\xd0"sv // call RAX
);

/* The idea:
* replace end of the loop jump with jump to the new code
* call our own function to clear all the cutscene behaviors
* jump to the end of the function
* hopefully there isn't something important that we're skipping
*/

patch_and_redirect(jump_out_lookup, 5, clear_ic8_code, true, addr_to_jump_to);
return_addr = memory.at_exe(jump_out_lookup + 8); // 8 - pattern size
}

/* The idea:
* if it's not the end of the array it's looking for olmec, jump back to the oryginal code via jump in `new_code`
* if it's end of the array (no olmec found) jump to return_addr
* the place for return_addr was kind of choosen by feel, as the code is complicated
* the whole point of the patched code is to find olmec and check it's faze, maybe for the music? no idea
* the whole point of the patched code is to find olmec and check it's faze, maybe for the music? no idea, it's a big function
*/

std::string_view new_code{
"\x0f\x85\x00\x00\x00\x00"sv}; // jne (offset needs to be updated after we know the address)
"\x0f\x85\x00\x00\x00\x00"sv}; // jne (offset needs to be updated after we know the address)

auto new_code_addr = patch_and_redirect(offset, code_to_move, new_code, false, return_addr);
if (new_code_addr == 0)
Expand All @@ -144,12 +112,53 @@ void patch_olmec_kill_crash()
new_code_addr += code_to_move;
int32_t rel = static_cast<int32_t>(offset + code_to_move - (new_code_addr + 6)); // +6 after the jump
write_mem_prot(new_code_addr + 2, rel, true);

// [patch the cutscene]

const auto patch_addr = get_address("olmec_lookup_in_theme");
if (patch_addr == 0)
return;

size_t addr_to_jump_to;
{
// find end of the function that sets the camera and stuff
size_t rva = patch_addr - memory.exe_ptr;
size_t rva_jumpout_to = find_inst(memory.exe(), "\x48\x8B\x06"sv, rva, rva + 0xA50, "patch_olmec_kill_crash");
if (rva_jumpout_to == 0)
return;

addr_to_jump_to = memory.at_exe(rva_jumpout_to + 14); // +14 just offset to get what we want
}

std::string cutscene_new_code = fmt::format(
"\xb9{}"sv // mov ecx, ENT_TYPE
"\xba\x80\x00\x00\x00"sv // mov edx, 0x80 (MASK::ACTIVEFLOOR)
"\x48\xb8{}"sv // movabs RAX, &check_if_ent_type_exists
"\xff\xd0"sv // call RAX
"\x84\xc0"sv // test al, al
"\x0f\x85\x00\x00\x00\x00"sv, // jnz (offset needs to be updated after we know the address)
to_le_bytes(to_id("ENT_TYPE_ACTIVEFLOOR_OLMEC")),
to_le_bytes((size_t)&check_if_ent_type_exists));

/* The idea:
* same as tiamat
*/
constexpr auto cutscene_code_to_move = 7;
g_olmec_patch_size = cutscene_new_code.size() + cutscene_code_to_move; // without the final jump added by patch_and_redirect

g_olmec_patch_addr = patch_and_redirect(patch_addr, cutscene_code_to_move, cutscene_new_code, false, addr_to_jump_to);
if (g_olmec_patch_addr == 0)
return;

auto jump_addr = g_olmec_patch_addr + g_olmec_patch_size;
int32_t rel_off = static_cast<int32_t>(patch_addr + cutscene_code_to_move - jump_addr);
write_mem_prot(jump_addr - 4, rel_off, true); // update the jump offset

once = true;
}

size_t g_tiamat_patch_size;
size_t g_tiamat_patch_addr;

void patch_tiamat_kill_crash()
{
static bool once = false;
Expand Down Expand Up @@ -193,6 +202,8 @@ void patch_tiamat_kill_crash()
g_tiamat_patch_size = new_code.size() + copy_over_code_size; // without the final jump added by patch_and_redirect

g_tiamat_patch_addr = patch_and_redirect(patch_addr, copy_over_code_size, new_code, false, return_to_addr);
if (g_tiamat_patch_addr == 0)
return;

auto jump_addr = g_tiamat_patch_addr + g_tiamat_patch_size;
int32_t rel = static_cast<int32_t>(patch_addr + copy_over_code_size - jump_addr);
Expand Down Expand Up @@ -238,6 +249,9 @@ void patch_liquid_OOB()
"\x0f\x8C\x00\x00\x00\x00"sv}; // jl (same jump as before)

auto new_code_addr = patch_and_redirect(offset, code_to_move, new_code);
if (new_code_addr == 0)
return;

new_code_addr += code_to_move;

int32_t rel = static_cast<int32_t>(continue_addr - (new_code_addr + 10)); // +10 after the jump
Expand All @@ -249,12 +263,12 @@ void patch_liquid_OOB()

void set_skip_olmec_cutscene(bool skip)
{
static const auto jump_out_lookup = get_address("olmec_lookup_in_theme");
if (jump_out_lookup == 0)
return;
patch_olmec_kill_crash(); // just in case

// simple jump over the tiamat check, nop here just so there is no funny business
static const std::string code = fmt::format("\xEB{}\x90"sv, to_le_bytes(static_cast<int8_t>(g_olmec_patch_size - 2)));
if (skip)
write_mem_recoverable("set_skip_olmec_cutscene", jump_out_lookup - 2, "\x90\x90"sv, true);
write_mem_recoverable("set_skip_olmec_cutscene", g_olmec_patch_addr, code, true);
else
recover_mem("set_skip_olmec_cutscene");
}
Expand Down
6 changes: 3 additions & 3 deletions src/game_api/search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1986,11 +1986,11 @@ std::unordered_map<std::string_view, AddressRule> g_address_rules{
},
{
"olmec_lookup_in_theme"sv,
// find the jump out of olmec lookup loop
// find the first jump in the virtual that skips the whole function
PatternCommandBuffer{}
.get_virtual_function_address(VTABLE_OFFSET::THEME_OLMEC, (VIRT_FUNC)24) // spawn_effects
.find_after_inst("\x48\x03\x58\x28"sv)
.offset(0x5)
.find_after_inst("83 78 0C 0D"_gh)
.offset(0x6) // after the jump instruction
.at_exe(),
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/game_api/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ State& State::get()
// game patches
patch_tiamat_kill_crash();
patch_orbs_limit();
//patch_olmec_kill_crash();
patch_olmec_kill_crash();
patch_liquid_OOB();
}

Expand Down

0 comments on commit e3b4394

Please sign in to comment.