diff --git a/ares/component/processor/arm7tdmi/arm7tdmi.hpp b/ares/component/processor/arm7tdmi/arm7tdmi.hpp index 36dcd852e..e13fae22a 100644 --- a/ares/component/processor/arm7tdmi/arm7tdmi.hpp +++ b/ares/component/processor/arm7tdmi/arm7tdmi.hpp @@ -22,6 +22,8 @@ struct ARM7TDMI { virtual auto get(u32 mode, n32 address) -> n32 = 0; virtual auto getDebugger(u32 mode, n32 address) -> n32 { return get(mode, address); } virtual auto set(u32 mode, n32 address, n32 word) -> void = 0; + virtual auto lock() -> void { return; } + virtual auto unlock() -> void { return; } //arm7tdmi.cpp ARM7TDMI(); diff --git a/ares/component/processor/arm7tdmi/instructions-arm.cpp b/ares/component/processor/arm7tdmi/instructions-arm.cpp index 0eec6fb7d..f6f095ef7 100644 --- a/ares/component/processor/arm7tdmi/instructions-arm.cpp +++ b/ares/component/processor/arm7tdmi/instructions-arm.cpp @@ -131,9 +131,11 @@ auto ARM7TDMI::armInstructionLoadRegister auto ARM7TDMI::armInstructionMemorySwap (n4 m, n4 d, n4 n, n1 byte) -> void { + lock(); n32 word = load((byte ? Byte : Word) | Nonsequential, r(n)); store((byte ? Byte : Word) | Nonsequential, r(n), r(m)); r(d) = word; + unlock(); } auto ARM7TDMI::armInstructionMoveHalfImmediate diff --git a/ares/gba/cpu/bus.cpp b/ares/gba/cpu/bus.cpp index b7d7b2818..a75d45db5 100644 --- a/ares/gba/cpu/bus.cpp +++ b/ares/gba/cpu/bus.cpp @@ -80,6 +80,15 @@ auto CPU::set(u32 mode, n32 address, n32 word) -> void { openBus.set(mode, address, word); } +auto CPU::lock() -> void { + dmaRun(); + context.busLocked = true; +} + +auto CPU::unlock() -> void { + context.busLocked = false; +} + auto CPU::_wait(u32 mode, n32 address) -> u32 { if(address >= 0x1000'0000) return 1; //unmapped if(address < 0x0200'0000) return 1; diff --git a/ares/gba/cpu/cpu.cpp b/ares/gba/cpu/cpu.cpp index e118d0505..80eaead89 100644 --- a/ares/gba/cpu/cpu.cpp +++ b/ares/gba/cpu/cpu.cpp @@ -56,7 +56,7 @@ auto CPU::main() -> void { } auto CPU::dmaRun() -> void { - if(!context.dmaActive) { + if(!context.dmaActive && !context.busLocked) { context.dmaActive = true; while(dma[0].run() | dma[1].run() | dma[2].run() | dma[3].run()); if(context.dmaRan) { diff --git a/ares/gba/cpu/cpu.hpp b/ares/gba/cpu/cpu.hpp index 8de209ace..0b03e10d7 100644 --- a/ares/gba/cpu/cpu.hpp +++ b/ares/gba/cpu/cpu.hpp @@ -64,6 +64,8 @@ struct CPU : ARM7TDMI, Thread, IO { auto get(u32 mode, n32 address) -> n32 override; auto getDebugger(u32 mode, n32 address) -> n32 override; auto set(u32 mode, n32 address, n32 word) -> void override; + auto lock() -> void override; + auto unlock() -> void override; auto _wait(u32 mode, n32 address) -> u32; //io.cpp @@ -255,6 +257,7 @@ struct CPU : ARM7TDMI, Thread, IO { n1 dmaRomAccess; n1 dmaActive; n1 timerLatched; + n1 busLocked; } context; }; diff --git a/ares/gba/cpu/serialization.cpp b/ares/gba/cpu/serialization.cpp index 8e39635b6..6f2716a0d 100644 --- a/ares/gba/cpu/serialization.cpp +++ b/ares/gba/cpu/serialization.cpp @@ -117,4 +117,5 @@ auto CPU::serialize(serializer& s) -> void { s(context.dmaRomAccess); s(context.dmaActive); s(context.timerLatched); + s(context.busLocked); } diff --git a/ares/gba/display/serialization.cpp b/ares/gba/display/serialization.cpp index aed59e8e0..7883c57aa 100644 --- a/ares/gba/display/serialization.cpp +++ b/ares/gba/display/serialization.cpp @@ -1,4 +1,6 @@ auto Display::serialize(serializer& s) -> void { + Thread::serialize(s); + s(io.vblank); s(io.hblank); s(io.vcoincidence); diff --git a/ares/gba/system/serialization.cpp b/ares/gba/system/serialization.cpp index e95bb09ec..0ccc58468 100644 --- a/ares/gba/system/serialization.cpp +++ b/ares/gba/system/serialization.cpp @@ -1,4 +1,4 @@ -static const string SerializerVersion = "v141.4"; +static const string SerializerVersion = "v141.5"; auto System::serialize(bool synchronize) -> serializer { if(synchronize) scheduler.enter(Scheduler::Mode::Synchronize);