diff --git a/bsnes/processor/wdc65816/instructions-read.cpp b/bsnes/processor/wdc65816/instructions-read.cpp index e364725b7..957223d24 100755 --- a/bsnes/processor/wdc65816/instructions-read.cpp +++ b/bsnes/processor/wdc65816/instructions-read.cpp @@ -113,8 +113,8 @@ auto WDC65816::instructionIndexedIndirectRead8(alu8 op) -> void { U.l = fetch(); idle2(); idle(); - V.l = readDirect(U.l + X.w + 0); - V.h = readDirect(U.l + X.w + 1); + V.l = readDirectX(U.l + X.w, 0); + V.h = readDirectX(U.l + X.w, 1); L W.l = readBank(V.w + 0); alu(W.l); } @@ -123,8 +123,8 @@ auto WDC65816::instructionIndexedIndirectRead16(alu16 op) -> void { U.l = fetch(); idle2(); idle(); - V.l = readDirect(U.l + X.w + 0); - V.h = readDirect(U.l + X.w + 1); + V.l = readDirectX(U.l + X.w, 0); + V.h = readDirectX(U.l + X.w, 1); W.l = readBank(V.w + 0); L W.h = readBank(V.w + 1); alu(W.w); diff --git a/bsnes/processor/wdc65816/instructions-write.cpp b/bsnes/processor/wdc65816/instructions-write.cpp index f2851ed68..a3042d862 100755 --- a/bsnes/processor/wdc65816/instructions-write.cpp +++ b/bsnes/processor/wdc65816/instructions-write.cpp @@ -90,8 +90,8 @@ auto WDC65816::instructionIndexedIndirectWrite8() -> void { U.l = fetch(); idle2(); idle(); - V.l = readDirect(U.l + X.w + 0); - V.h = readDirect(U.l + X.w + 1); + V.l = readDirectX(U.l + X.w, 0); + V.h = readDirectX(U.l + X.w, 1); L writeBank(V.w + 0, A.l); } @@ -99,8 +99,8 @@ auto WDC65816::instructionIndexedIndirectWrite16() -> void { U.l = fetch(); idle2(); idle(); - V.l = readDirect(U.l + X.w + 0); - V.h = readDirect(U.l + X.w + 1); + V.l = readDirectX(U.l + X.w, 0); + V.h = readDirectX(U.l + X.w, 1); writeBank(V.w + 0, A.l); L writeBank(V.w + 1, A.h); } diff --git a/bsnes/processor/wdc65816/memory.cpp b/bsnes/processor/wdc65816/memory.cpp index 4f6037407..7cfb2cc05 100644 --- a/bsnes/processor/wdc65816/memory.cpp +++ b/bsnes/processor/wdc65816/memory.cpp @@ -59,6 +59,13 @@ auto WDC65816::writeDirect(uint address, uint8 data) -> void { write(D.w + address & 0xffff, data); } +auto WDC65816::readDirectX(uint address, uint offset) -> uint8 { + // The (direct,X) addressing mode has a bug in which the high byte is + // wrapped within the page if E = 1 and D&0xFF != 0. + if(EF && D.l) return read(((D.w + address) & 0xffff00) | ((D.w + address + offset) & 0xff)); + else return readDirect(address + offset); +} + auto WDC65816::readDirectN(uint address) -> uint8 { return read(D.w + address & 0xffff); } diff --git a/bsnes/processor/wdc65816/wdc65816.hpp b/bsnes/processor/wdc65816/wdc65816.hpp index 3821794d0..102bd512b 100755 --- a/bsnes/processor/wdc65816/wdc65816.hpp +++ b/bsnes/processor/wdc65816/wdc65816.hpp @@ -58,6 +58,7 @@ struct WDC65816 { alwaysinline auto pushN(uint8 data) -> void; alwaysinline auto readDirect(uint address) -> uint8; alwaysinline auto writeDirect(uint address, uint8 data) -> void; + alwaysinline auto readDirectX(uint address, uint offset) -> uint8; alwaysinline auto readDirectN(uint address) -> uint8; alwaysinline auto readBank(uint address) -> uint8; alwaysinline auto writeBank(uint address, uint8 data) -> void;