mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 22:25:41 +12:00
[AR] More opcodes
This commit is contained in:
parent
8e45b8c324
commit
08596c1a24
2 changed files with 102 additions and 6 deletions
|
@ -14,7 +14,7 @@ class ActionReplay {
|
|||
|
||||
// When an instruction does not specify which offset or data register to use, we use the "active" one
|
||||
// Which is by default #1 and may be changed by certain AR operations
|
||||
u32 *activeOffset, *activeData;
|
||||
u32 *activeOffset, *activeData, *activeStorage;
|
||||
|
||||
// Program counter
|
||||
u32 pc = 0;
|
||||
|
|
|
@ -6,6 +6,9 @@ void ActionReplay::reset() {
|
|||
// Default value of storage regs is 0
|
||||
storage1 = 0;
|
||||
storage2 = 0;
|
||||
|
||||
// TODO: Is the active storage persistent or not?
|
||||
activeStorage = &storage1;
|
||||
}
|
||||
|
||||
void ActionReplay::runCheat(const Cheat& cheat) {
|
||||
|
@ -33,15 +36,41 @@ u8 ActionReplay::read8(u32 addr) { return mem.read8(addr); }
|
|||
u16 ActionReplay::read16(u32 addr) { return mem.read16(addr); }
|
||||
u32 ActionReplay::read32(u32 addr) { return mem.read32(addr); }
|
||||
|
||||
void ActionReplay::write8(u32 addr, u8 value) { mem.write8(addr, value); }
|
||||
void ActionReplay::write16(u32 addr, u16 value) { mem.write16(addr, value); }
|
||||
void ActionReplay::write32(u32 addr, u32 value) { mem.write32(addr, value); }
|
||||
// Some AR cheats seem to want to write to unmapped memory or memory that straight up does not exist
|
||||
|
||||
#define MAKE_WRITE_HANDLER(size) \
|
||||
void ActionReplay::write##size(u32 addr, u##size value) { \
|
||||
auto pointerWrite = mem.getWritePointer(addr); \
|
||||
if (pointerWrite) { \
|
||||
*(u##size*)pointerWrite = value; \
|
||||
} else { \
|
||||
auto pointerRead = mem.getReadPointer(addr); \
|
||||
if (pointerRead) { \
|
||||
*(u##size*)pointerRead = value; \
|
||||
} else { \
|
||||
Helpers::warn("AR code tried to write to invalid address: %08X\n", addr); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
MAKE_WRITE_HANDLER(8)
|
||||
MAKE_WRITE_HANDLER(16)
|
||||
MAKE_WRITE_HANDLER(32)
|
||||
#undef MAKE_WRITE_HANDLER
|
||||
|
||||
void ActionReplay::runInstruction(const Cheat& cheat, u32 instruction) {
|
||||
// Top nibble determines the instruction type
|
||||
const u32 type = instruction >> 28;
|
||||
|
||||
switch (type) {
|
||||
// 32-bit write to [XXXXXXX + offset]
|
||||
case 0x0: {
|
||||
const u32 baseAddr = Helpers::getBits<0, 28>(instruction);
|
||||
const u32 value = cheat[pc++];
|
||||
write32(baseAddr + *activeOffset, value);
|
||||
break;
|
||||
}
|
||||
|
||||
// 16-bit write to [XXXXXXX + offset]
|
||||
case 0x1: {
|
||||
const u32 baseAddr = Helpers::getBits<0, 28>(instruction);
|
||||
|
@ -50,7 +79,6 @@ void ActionReplay::runInstruction(const Cheat& cheat, u32 instruction) {
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
// 8-bit write to [XXXXXXX + offset]
|
||||
case 0x2: {
|
||||
const u32 baseAddr = Helpers::getBits<0, 28>(instruction);
|
||||
|
@ -74,5 +102,73 @@ void ActionReplay::runInstruction(const Cheat& cheat, u32 instruction) {
|
|||
}
|
||||
|
||||
void ActionReplay::executeDType(const Cheat& cheat, u32 instruction) {
|
||||
Helpers::panic("ActionReplay: Unimplemented d-type opcode: %08X", instruction);
|
||||
switch (instruction) {
|
||||
case 0xD3000000: offset1 = cheat[pc++]; break;
|
||||
case 0xD3000001: offset2 = cheat[pc++]; break;
|
||||
case 0xDC000000: *activeOffset += cheat[pc++]; break;
|
||||
|
||||
// DD000000 XXXXXXXX - if KEYPAD has value XXXXXXXX execute next block
|
||||
case 0xDD000000: {
|
||||
const u32 mask = cheat[pc++];
|
||||
break;
|
||||
}
|
||||
|
||||
// Offset register ops
|
||||
case 0xDF000000: {
|
||||
const u32 subopcode = cheat[pc++];
|
||||
switch (subopcode) {
|
||||
case 0x00000000: activeOffset = &offset1; break;
|
||||
case 0x00000001: activeOffset = &offset2; break;
|
||||
case 0x00010000: offset2 = offset1; break;
|
||||
case 0x00010001: offset1 = offset2; break;
|
||||
case 0x00020000: data1 = offset1; break;
|
||||
case 0x00020001: data2 = offset2; break;
|
||||
default:
|
||||
Helpers::warn("Unknown ActionReplay offset operation");
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Data register operations
|
||||
case 0xDF000001: {
|
||||
const u32 subopcode = cheat[pc++];
|
||||
switch (subopcode) {
|
||||
case 0x00000000: activeData = &data1; break;
|
||||
case 0x00000001: activeData = &data2; break;
|
||||
|
||||
case 0x00010000: data2 = data1; break;
|
||||
case 0x00010001: data1 = data2; break;
|
||||
case 0x00020000: offset1 = data1; break;
|
||||
case 0x00020001: offset2 = data2; break;
|
||||
default:
|
||||
Helpers::warn("Unknown ActionReplay data operation");
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Storage register operations
|
||||
case 0xDF000002: {
|
||||
const u32 subopcode = cheat[pc++];
|
||||
switch (subopcode) {
|
||||
case 0x00000000: activeStorage = &storage1; break;
|
||||
case 0x00000001: activeStorage = &storage2; break;
|
||||
|
||||
case 0x00010000: data1 = storage1; break;
|
||||
case 0x00010001: data2 = storage2; break;
|
||||
case 0x00020000: storage1 = data1; break;
|
||||
case 0x00020001: storage2 = data2; break;
|
||||
default:
|
||||
Helpers::warn("Unknown ActionReplay data operation");
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: Helpers::panic("ActionReplay: Unimplemented d-type opcode: %08X", instruction); break;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue