Replaced serial single-byte NOPs with long NOPs

(the sequence is 5-byte long NOPs with trailing single-byte NOPs)
This commit is contained in:
NovaRain
2026-04-19 20:38:10 +08:00
parent e3a133e3aa
commit 3b836fdf73
6 changed files with 36 additions and 10 deletions
+2 -2
View File
@@ -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);
}
}
+1 -1
View File
@@ -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;
+4 -4
View File
@@ -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 {
+2 -2
View File
@@ -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);
+25 -1
View File
@@ -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);
}
}
+2
View File
@@ -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<DWORD> addrs);
void MakeCalls(void* func, std::initializer_list<DWORD> addrs);