From ccbe394e7d4bc5f5596544813d887da161af3ca6 Mon Sep 17 00:00:00 2001 From: Morilli <35152647+Morilli@users.noreply.github.com> Date: Fri, 1 Mar 2024 13:03:04 +0100 Subject: [PATCH] wdc65816: emulate (direct,X) wraparound bug in emulation mode Manually cherry-picked ares commit https://github.com/ares-emulator/ares/commit/be8fa76e7dc31b8cd7255f227932afd903501553 Co-Authored-By: Adrian Siekierka --- bsnes/processor/wdc65816/instructions-read.cpp | 8 ++++---- bsnes/processor/wdc65816/instructions-write.cpp | 8 ++++---- bsnes/processor/wdc65816/memory.cpp | 7 +++++++ bsnes/processor/wdc65816/wdc65816.hpp | 1 + 4 files changed, 16 insertions(+), 8 deletions(-) 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;