diff --git a/sfall/HRP/Inventory.cpp b/sfall/HRP/Inventory.cpp index da3d977c..61c38fb1 100644 --- a/sfall/HRP/Inventory.cpp +++ b/sfall/HRP/Inventory.cpp @@ -78,8 +78,8 @@ void Inventory::init() { }); // setup_inventory_ - sf::SafeMemSet(0x46ED23, sf::CodeType::Nop, 6); - sf::SafeMemSet(0x46ED31, sf::CodeType::Nop, 6); + sf::BlockCall(0x46ED23, 6); + sf::BlockCall(0x46ED31, 6); } } diff --git a/sfall/Modules/MiscPatches.cpp b/sfall/Modules/MiscPatches.cpp index 9ed86fdf..cb1f3c0c 100644 --- a/sfall/Modules/MiscPatches.cpp +++ b/sfall/Modules/MiscPatches.cpp @@ -877,7 +877,7 @@ static void EngineOptimizationPatches() { // Remove redundant/duplicate code BlockCall(0x45EBBF); // intface_redraw_ BlockCall(0x4A4859); // exec_script_proc_ - SafeMemSet(0x455189, CodeType::Nop, 11); // op_create_object_sid_ + BlockCall(0x455189, 11); // op_create_object_sid_ // Improve performance of the data conversion of script interpreter // mov eax, [edx+eax]; bswap eax; ret; diff --git a/sfall/Modules/Scripting/Handlers/Objects.cpp b/sfall/Modules/Scripting/Handlers/Objects.cpp index bf4d5753..0c4a1104 100644 --- a/sfall/Modules/Scripting/Handlers/Objects.cpp +++ b/sfall/Modules/Scripting/Handlers/Objects.cpp @@ -54,10 +54,10 @@ static void __cdecl IncNPCLevel(const char* fmt, const char* name) { SafeWrite32(0x495C50, 0x01FB840F); // Want to keep this check intact. (restore) - SafeMemSet(0x495C77, CodeType::Nop, 6); // Check that the player is high enough for the npc to consider this level - //SafeMemSet(0x495C8C, CodeType::Nop, 6); // Check that the npc isn't already at its maximum level - SafeMemSet(0x495CE3, CodeType::Nop, 5); // Check if npc had "early" level up before the next scheduled one, resets the "early" flag - SafeMemSet(0x495CEC, CodeType::Nop, 6); // Related to above + BlockCall(0x495C77, 6); // Check that the player is high enough for the npc to consider this level + //BlockCall(0x495C8C, 6); // Check that the npc isn't already at its maximum level + BlockCall(0x495CE3); // Check if npc had "early" level up before the next scheduled one, resets the "early" flag + BlockCall(0x495CEC, 6); // Related to above SafeWrite8(0x495CFB, CodeType::JumpShort); // Skip random roll for early level up __asm mov dword ptr [ebp + 0x150 - 0x28 + 16], 255; // set counter for exit loop } else { diff --git a/sfall/Modules/Worldmap.cpp b/sfall/Modules/Worldmap.cpp index c29a9665..bb38e14b 100644 --- a/sfall/Modules/Worldmap.cpp +++ b/sfall/Modules/Worldmap.cpp @@ -416,8 +416,8 @@ static void TimeLimitPatch() { 0x4A34EF, // inc_game_time_ 0x4A3547 // inc_game_time_in_seconds_ }); - SafeMemSet(0x4A34F4, CodeType::Nop, 16); - SafeMemSet(0x4A354C, CodeType::Nop, 16); + BlockCall(0x4A34F4, 16); + BlockCall(0x4A354C, 16); } else { SafeWrite8(0x4A34EC, limit); SafeWrite8(0x4A3544, limit); diff --git a/sfall/SafeWrite.cpp b/sfall/SafeWrite.cpp index 81dc8db4..7e947ef5 100644 --- a/sfall/SafeWrite.cpp +++ b/sfall/SafeWrite.cpp @@ -137,10 +137,34 @@ void BlockCall(DWORD addr) { DWORD oldProtect; VirtualProtect((void*)addr, 4, PAGE_EXECUTE_READWRITE, &oldProtect); - *((DWORD*)addr) = 0x00441F0F; // long NOP (0F1F4400-XX) + *((DWORD*)addr) = 0x00441F0F; // 5-byte long NOP (0F1F4400-XX) VirtualProtect((void*)addr, 4, oldProtect, &oldProtect); CheckConflict(addr, 5); } +static __declspec(noinline) void __stdcall SafeWriteNops(DWORD addr, size_t len) { + DWORD oldProtect; + + VirtualProtect((void*)addr, len, PAGE_EXECUTE_READWRITE, &oldProtect); + DWORD cur = addr, remaining = len; + while (remaining >= 5) { + *((DWORD*)cur) = 0x00441F0F; // 5-byte long NOP (0F1F4400-XX) + cur += 5; + remaining -= 5; + } + // Fill the remaining bytes (1-4 bytes) with single-byte NOPs + while (remaining > 0) { + *((BYTE*)cur++) = CodeType::Nop; + remaining--; + } + VirtualProtect((void*)addr, len, oldProtect, &oldProtect); + + CheckConflict(addr, len); +} + +void BlockCall(DWORD addr, size_t len) { + SafeWriteNops(addr, len); +} + } diff --git a/sfall/SafeWrite.h b/sfall/SafeWrite.h index fb34f8e1..0a539d4b 100644 --- a/sfall/SafeWrite.h +++ b/sfall/SafeWrite.h @@ -62,6 +62,8 @@ void MakeCall(DWORD addr, void* func, size_t len); void MakeJump(DWORD addr, void* func); void MakeJump(DWORD addr, void* func, size_t len); void BlockCall(DWORD addr); +// Should be used for patching out 6+ bytes (use single-byte NOPs for 1-4 bytes) +void BlockCall(DWORD addr, size_t len); void HookCalls(void* func, std::initializer_list addrs); void MakeCalls(void* func, std::initializer_list addrs);