diff --git a/src/core/cheats.cpp b/src/core/cheats.cpp index bf83b5386..63cdb624e 100644 --- a/src/core/cheats.cpp +++ b/src/core/cheats.cpp @@ -1213,6 +1213,98 @@ void CheatCode::Apply() const index += 2; } break; + + case InstructionCode::ExtFindAndReplace: + { + + if ((index + 4) >= instructions.size()) + { + Log_ErrorPrintf("Incomplete find/replace instruction"); + return; + } + const Instruction& inst2 = instructions[index + 1]; + const Instruction& inst3 = instructions[index + 2]; + const Instruction& inst4 = instructions[index + 3]; + const Instruction& inst5 = instructions[index + 4]; + + const u32 offset = Truncate16(inst.value32 & 0x0000FFFFu) << 1; + const u8 wildcard = Truncate8((inst.value32 & 0x00FF0000u) >> 16); + const u32 minaddress = inst.address - offset; + const u32 maxaddress = inst.address + offset; + const u8 f1 = Truncate8((inst2.first & 0xFF000000u) >> 24); + const u8 f2 = Truncate8((inst2.first & 0x00FF0000u) >> 16); + const u8 f3 = Truncate8((inst2.first & 0x0000FF00u) >> 8); + const u8 f4 = Truncate8 (inst2.first & 0x000000FFu); + const u8 f5 = Truncate8((inst2.value32 & 0xFF000000u) >> 24); + const u8 f6 = Truncate8((inst2.value32 & 0x00FF0000u) >> 16); + const u8 f7 = Truncate8((inst2.value32 & 0x0000FF00u) >> 8); + const u8 f8 = Truncate8 (inst2.value32 & 0x000000FFu); + const u8 f9 = Truncate8((inst3.first & 0xFF000000u) >> 24); + const u8 f10 = Truncate8((inst3.first & 0x00FF0000u) >> 16); + const u8 f11 = Truncate8((inst3.first & 0x0000FF00u) >> 8); + const u8 f12 = Truncate8 (inst3.first & 0x000000FFu); + const u8 f13 = Truncate8((inst3.value32 & 0xFF000000u) >> 24); + const u8 f14 = Truncate8((inst3.value32 & 0x00FF0000u) >> 16); + const u8 f15 = Truncate8((inst3.value32 & 0x0000FF00u) >> 8); + const u8 f16 = Truncate8 (inst3.value32 & 0x000000FFu); + const u8 r1 = Truncate8((inst4.first & 0xFF000000u) >> 24); + const u8 r2 = Truncate8((inst4.first & 0x00FF0000u) >> 16); + const u8 r3 = Truncate8((inst4.first & 0x0000FF00u) >> 8); + const u8 r4 = Truncate8 (inst4.first & 0x000000FFu); + const u8 r5 = Truncate8((inst4.value32 & 0xFF000000u) >> 24); + const u8 r6 = Truncate8((inst4.value32 & 0x00FF0000u) >> 16); + const u8 r7 = Truncate8((inst4.value32 & 0x0000FF00u) >> 8); + const u8 r8 = Truncate8 (inst4.value32 & 0x000000FFu); + const u8 r9 = Truncate8((inst5.first & 0xFF000000u) >> 24); + const u8 r10 = Truncate8((inst5.first & 0x00FF0000u) >> 16); + const u8 r11 = Truncate8((inst5.first & 0x0000FF00u) >> 8); + const u8 r12 = Truncate8 (inst5.first & 0x000000FFu); + const u8 r13 = Truncate8((inst5.value32 & 0xFF000000u) >> 24); + const u8 r14 = Truncate8((inst5.value32 & 0x00FF0000u) >> 16); + const u8 r15 = Truncate8((inst5.value32 & 0x0000FF00u) >> 8); + const u8 r16 = Truncate8 (inst5.value32 & 0x000000FFu); + + for (u32 address = minaddress;address<=maxaddress;address+=2) + { + if ((DoMemoryRead(address )==f1 || f1 == wildcard) && + (DoMemoryRead(address+1 )==f2 || f2 == wildcard) && + (DoMemoryRead(address+2 )==f3 || f3 == wildcard) && + (DoMemoryRead(address+3 )==f4 || f4 == wildcard) && + (DoMemoryRead(address+4 )==f5 || f5 == wildcard) && + (DoMemoryRead(address+5 )==f6 || f6 == wildcard) && + (DoMemoryRead(address+6 )==f7 || f7 == wildcard) && + (DoMemoryRead(address+7 )==f8 || f8 == wildcard) && + (DoMemoryRead(address+8 )==f9 || f9 == wildcard) && + (DoMemoryRead(address+9 )==f10|| f10 == wildcard) && + (DoMemoryRead(address+10)==f11|| f11 == wildcard) && + (DoMemoryRead(address+11)==f12|| f12 == wildcard) && + (DoMemoryRead(address+12)==f13|| f13 == wildcard) && + (DoMemoryRead(address+13)==f14|| f14 == wildcard) && + (DoMemoryRead(address+14)==f15|| f15 == wildcard) && + (DoMemoryRead(address+15)==f16|| f16 == wildcard)) + { + if (r1 != wildcard) DoMemoryWrite(address , r1 ); + if (r2 != wildcard) DoMemoryWrite(address+1 , r2 ); + if (r3 != wildcard) DoMemoryWrite(address+2 , r3 ); + if (r4 != wildcard) DoMemoryWrite(address+3 , r4 ); + if (r5 != wildcard) DoMemoryWrite(address+4 , r5 ); + if (r6 != wildcard) DoMemoryWrite(address+5 , r6 ); + if (r7 != wildcard) DoMemoryWrite(address+6 , r7 ); + if (r8 != wildcard) DoMemoryWrite(address+7 , r8 ); + if (r9 != wildcard) DoMemoryWrite(address+8 , r9 ); + if (r10 != wildcard) DoMemoryWrite(address+9 , r10); + if (r11 != wildcard) DoMemoryWrite(address+10, r11); + if (r12 != wildcard) DoMemoryWrite(address+11, r12); + if (r13 != wildcard) DoMemoryWrite(address+12, r13); + if (r14 != wildcard) DoMemoryWrite(address+13, r14); + if (r15 != wildcard) DoMemoryWrite(address+14, r15); + if (r16 != wildcard) DoMemoryWrite(address+15, r16); + address=address+15; + } + } + index += 5; + } + break; case InstructionCode::CompareEqual16: { @@ -1479,7 +1571,9 @@ void CheatCode::ApplyOnDisable() const case InstructionCode::MemoryCopy: index += 2; break; - + case InstructionCode::ExtFindAndReplace: + index += 5; + break; // for conditionals, we don't want to skip over in case it changed at some point case InstructionCode::ExtCompareEqual32: case InstructionCode::ExtCompareNotEqual32: diff --git a/src/core/cheats.h b/src/core/cheats.h index e3e11012f..805a155d2 100644 --- a/src/core/cheats.h +++ b/src/core/cheats.h @@ -62,6 +62,7 @@ struct CheatCode ExtConstantForceRangeLimits16 = 0xF1, ExtConstantForceRangeRollRound16 = 0xF2, ExtConstantForceRange16 = 0xF3, + ExtFindAndReplace = 0xF4, ExtConstantBitSet8 = 0x31, ExtConstantBitClear8 = 0x32, ExtConstantBitSet16 = 0x81,