diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index 9df946cc..ee45b11e 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -3,18 +3,6 @@ #include namespace n64 { -u32 extraCycles = 0; - -void CpuStall(u32 cycles) { - extraCycles += cycles; -} - -u32 PopStalledCycles() { - u32 ret = extraCycles; - extraCycles = 0; - return ret; -} - Core::Core() : cpu(std::make_unique()) {} void Core::Stop() { @@ -71,7 +59,7 @@ void Core::Run(float volumeL, float volumeR) { for(; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) { u32 taken = cpu->Step(); - taken += PopStalledCycles(); + taken += regs.PopStalledCycles(); static u32 cpuSteps = 0; cpuSteps += taken; if(mmio.rsp.spStatus.halt) { @@ -91,7 +79,7 @@ void Core::Run(float volumeL, float volumeR) { cycles += taken; frameCycles += taken; - scheduler.Tick(taken, mem, regs); + scheduler.Tick(taken, mem); } cycles -= mmio.vi.cyclesPerHalfline; @@ -101,8 +89,8 @@ void Core::Run(float volumeL, float volumeR) { mmio.mi.InterruptRaise(MI::Interrupt::VI); } - mmio.ai.Step(cpu->mem, regs, frameCycles, volumeL, volumeR); - scheduler.Tick(frameCycles, mem, regs); + mmio.ai.Step(frameCycles, volumeL, volumeR); + scheduler.Tick(frameCycles, mem); } } diff --git a/src/backend/Core.hpp b/src/backend/Core.hpp index f6968135..b0639aa9 100644 --- a/src/backend/Core.hpp +++ b/src/backend/Core.hpp @@ -30,8 +30,4 @@ struct Core { size_t memSize{}, cpuSize{}, verSize{}; int slot = 0; }; - -extern u32 extraCycles; -void CpuStall(u32 cycles); -u32 PopStalledCycles(); } diff --git a/src/backend/Scheduler.cpp b/src/backend/Scheduler.cpp index 13f09424..f9664ff1 100644 --- a/src/backend/Scheduler.cpp +++ b/src/backend/Scheduler.cpp @@ -25,7 +25,7 @@ u64 Scheduler::Remove(EventType type) { return 0; } -void Scheduler::Tick(u64 t, n64::Mem& mem, n64::Registers& regs) { +void Scheduler::Tick(u64 t, n64::Mem& mem) { ticks += t; n64::MI& mi = mem.mmio.mi; n64::SI& si = mem.mmio.si; @@ -34,7 +34,7 @@ void Scheduler::Tick(u64 t, n64::Mem& mem, n64::Registers& regs) { while(ticks >= events.top().time) { switch(auto type = events.top().type) { case SI_DMA: - si.DMA(mem, regs); + si.DMA(); break; case PI_DMA_COMPLETE: mi.InterruptRaise(n64::MI::Interrupt::PI); diff --git a/src/backend/Scheduler.hpp b/src/backend/Scheduler.hpp index 4dc4c840..d0565d4d 100644 --- a/src/backend/Scheduler.hpp +++ b/src/backend/Scheduler.hpp @@ -53,7 +53,7 @@ struct Scheduler { void EnqueueRelative(u64, EventType); void EnqueueAbsolute(u64, EventType); u64 Remove(EventType); - void Tick(u64 t, n64::Mem&, n64::Registers&); + void Tick(u64 t, n64::Mem&); IterableEvents events; u64 ticks = 0; diff --git a/src/backend/core/MMIO.cpp b/src/backend/core/MMIO.cpp index aacf8974..31fa7a28 100644 --- a/src/backend/core/MMIO.cpp +++ b/src/backend/core/MMIO.cpp @@ -1,7 +1,5 @@ #include -#include #include -#include namespace n64 { void MMIO::Reset() { @@ -22,24 +20,24 @@ u32 MMIO::Read(u32 addr) { case MI_REGION: return mi.Read(addr); case VI_REGION: return vi.Read(addr); case AI_REGION: return ai.Read(addr); - case PI_REGION: return pi.Read(mi, addr); + case PI_REGION: return pi.Read(addr); case RI_REGION: return ri.Read(addr); - case SI_REGION: return si.Read(mi, addr); + case SI_REGION: return si.Read(addr); default: Util::panic("Unhandled mmio read at addr {:08X}", addr); } } -void MMIO::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { +void MMIO::Write(u32 addr, u32 val) { switch (addr) { case RSP_REGION: rsp.Write(addr, val); break; - case RDP_REGION: rdp.Write(mi, regs, rsp, addr, val); break; - case MI_REGION: mi.Write(regs, addr, val); break; - case VI_REGION: vi.Write(mi, regs, addr, val); break; - case AI_REGION: ai.Write(mem, regs, addr, val); break; - case PI_REGION: pi.Write(mem, regs, addr, val); break; + case RDP_REGION: rdp.Write(addr, val); break; + case MI_REGION: mi.Write(addr, val); break; + case VI_REGION: vi.Write(addr, val); break; + case AI_REGION: ai.Write(addr, val); break; + case PI_REGION: pi.Write(addr, val); break; case RI_REGION: ri.Write(addr, val); break; - case SI_REGION: si.Write(mem, regs, addr, val); break; + case SI_REGION: si.Write(addr, val); break; default: Util::panic("Unhandled mmio write at addr {:08X} with val {:08X}", addr, val); } diff --git a/src/backend/core/MMIO.hpp b/src/backend/core/MMIO.hpp index f9ce0c94..880802ac 100644 --- a/src/backend/core/MMIO.hpp +++ b/src/backend/core/MMIO.hpp @@ -13,7 +13,7 @@ struct Mem; struct Registers; struct MMIO { - MMIO(Mem& mem, Registers& regs) : mi(regs), si(mem, regs), rsp(mem, regs) {} + MMIO(Mem& mem, Registers& regs) : vi(mem, regs), mi(regs), ai(mem, regs), pi(mem, regs), si(mem, regs), rsp(mem, regs), rdp(mem, regs) {} void Reset(); VI vi; @@ -26,7 +26,7 @@ struct MMIO { RDP rdp; u32 Read(u32); - void Write(Mem&, Registers&, u32, u32); + void Write(u32, u32); std::vector Serialize(); void Deserialize(const std::vector&); }; diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index d8908bf7..51293c90 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -193,7 +193,7 @@ template<> u8 Mem::Read(n64::Registers ®s, u32 paddr) { return src[BYTE_ADDRESS(paddr & 0xfff)]; } case REGION_CART: - return mmio.pi.BusRead(*this, paddr); + return mmio.pi.BusRead(paddr); case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: case 0x04600000 ... 0x048FFFFF: @@ -238,7 +238,7 @@ template<> u16 Mem::Read(n64::Registers ®s, u32 paddr) { case MMIO_REGION: return mmio.Read(paddr); case REGION_CART: - return mmio.pi.BusRead(*this, paddr); + return mmio.pi.BusRead(paddr); case PIF_ROM_REGION: return Util::ReadAccess(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START); case PIF_RAM_REGION: @@ -273,7 +273,7 @@ template<> u32 Mem::Read(n64::Registers ®s, u32 paddr) { case MMIO_REGION: return mmio.Read(paddr); case REGION_CART: - return mmio.pi.BusRead(*this, paddr); + return mmio.pi.BusRead(paddr); case PIF_ROM_REGION: return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); case PIF_RAM_REGION: @@ -305,7 +305,7 @@ template<> u64 Mem::Read(n64::Registers ®s, u32 paddr) { case MMIO_REGION: return mmio.Read(paddr); case REGION_CART: - return mmio.pi.BusRead(*this, paddr); + return mmio.pi.BusRead(paddr); case PIF_ROM_REGION: return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); case PIF_RAM_REGION: @@ -342,7 +342,7 @@ template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { } break; case REGION_CART: Util::trace("BusWrite @ {:08X} = {:02X}", paddr, val); - mmio.pi.BusWrite(*this, paddr, val); + mmio.pi.BusWrite(paddr, val); break; case MMIO_REGION: Util::panic("MMIO Write!"); @@ -387,7 +387,7 @@ template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { } break; case REGION_CART: Util::trace("BusWrite @ {:08X} = {:04X}", paddr, val); - mmio.pi.BusWrite(*this, paddr, val); + mmio.pi.BusWrite(paddr, val); break; case MMIO_REGION: Util::panic("MMIO Write!"); @@ -430,10 +430,10 @@ template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { } break; case REGION_CART: Util::trace("BusWrite @ {:08X} = {:08X}", paddr, val); - mmio.pi.BusWrite(*this, paddr, val); + mmio.pi.BusWrite(paddr, val); break; case MMIO_REGION: - mmio.Write(*this, regs, paddr, val); + mmio.Write(paddr, val); break; case PIF_RAM_REGION: Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val)); @@ -470,7 +470,7 @@ void Mem::Write(Registers& regs, u32 paddr, u64 val) { } break; case REGION_CART: Util::trace("BusWrite @ {:08X} = {:016X}", paddr, val); - mmio.pi.BusWrite(*this, paddr, val); + mmio.pi.BusWrite(paddr, val); break; case MMIO_REGION: Util::panic("MMIO Write!"); diff --git a/src/backend/core/RDP.cpp b/src/backend/core/RDP.cpp index a2ca1888..16dfd8be 100644 --- a/src/backend/core/RDP.cpp +++ b/src/backend/core/RDP.cpp @@ -5,7 +5,7 @@ #include namespace n64 { -RDP::RDP() { +RDP::RDP(Mem& mem, Registers& regs) : mem(mem), regs(regs) { rdram.resize(RDRAM_SIZE); memset(cmd_buf, 0, 0x100000); dpc.status.raw = 0x80; @@ -40,17 +40,17 @@ auto RDP::Read(u32 addr) const -> u32 { } } -void RDP::Write(MI& mi, Registers& regs, RSP& rsp, u32 addr, u32 val) { +void RDP::Write(u32 addr, u32 val) { switch(addr) { case 0x04100000: WriteStart(val); break; - case 0x04100004: WriteEnd(mi, regs, rsp, val); break; - case 0x0410000C: WriteStatus(mi, regs, rsp, val); break; + case 0x04100004: WriteEnd(val); break; + case 0x0410000C: WriteStatus(val); break; default: Util::panic("Unhandled DP Command Registers write (addr: {:08X}, val: {:08X})", addr, val); } } -void RDP::WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val) { +void RDP::WriteStatus(u32 val) { DPCStatusWrite temp{}; temp.raw = val; @@ -69,7 +69,7 @@ void RDP::WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val) { CLEAR_SET(dpc.status.tmemBusy, temp.clearTmem, false); if(!dpc.status.freeze) { - RunCommand(mi, regs, rsp); + RunCommand(); } } /* @@ -114,7 +114,7 @@ FORCE_INLINE void logCommand(u8 cmd) { } */ -void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) { +void RDP::RunCommand() { if (dpc.status.freeze) { return; } @@ -138,7 +138,7 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) { if (dpc.status.xbusDmemDma) { for (int i = 0; i < len; i += 4) { - u32 cmd = Util::ReadAccess(rsp.dmem, (current + i) & 0xFFF); + u32 cmd = Util::ReadAccess(mem.mmio.rsp.dmem, (current + i) & 0xFFF); cmd_buf[remaining_cmds + (i >> 2)] = cmd; } } else { @@ -181,7 +181,7 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) { } if (cmd == 0x29) { - OnFullSync(mi, regs); + OnFullSync(); } buf_index += cmd_len; @@ -198,12 +198,12 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) { dpc.status.cbufReady = true; } -void RDP::OnFullSync(MI& mi, Registers& regs) { +void RDP::OnFullSync() { ParallelRdpOnFullSync(); dpc.status.pipeBusy = false; dpc.status.startGclk = false; dpc.status.cbufReady = false; - mi.InterruptRaise(MI::Interrupt::DP); + mem.mmio.mi.InterruptRaise(MI::Interrupt::DP); } } diff --git a/src/backend/core/RDP.hpp b/src/backend/core/RDP.hpp index 6bf0bec0..7bc78a82 100644 --- a/src/backend/core/RDP.hpp +++ b/src/backend/core/RDP.hpp @@ -5,7 +5,7 @@ namespace n64 { struct RSP; -struct MI; +struct Mem; struct Registers; union DPCStatusWrite { @@ -54,15 +54,15 @@ struct RDP { DPC dpc{}; u32 cmd_buf[0xFFFFF]{}; - RDP(); + RDP(Mem&, Registers&); void Reset(); std::vector rdram{}; [[nodiscard]] auto Read(u32 addr) const -> u32; - void Write(MI& mi, Registers& regs, RSP& rsp, u32 addr, u32 val); - void WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val); - void RunCommand(MI& mi, Registers& regs, RSP& rsp); - void OnFullSync(MI& mi, Registers& regs); + void Write(u32 addr, u32 val); + void WriteStatus(u32 val); + void RunCommand(); + void OnFullSync(); FORCE_INLINE void WriteStart(u32 val) { if(!dpc.status.startValid) { @@ -71,13 +71,16 @@ struct RDP { dpc.status.startValid = true; } - FORCE_INLINE void WriteEnd(MI& mi, Registers& regs, RSP& rsp, u32 val) { + FORCE_INLINE void WriteEnd(u32 val) { dpc.end = val & 0xFFFFF8; if(dpc.status.startValid) { dpc.current = dpc.start; dpc.status.startValid = false; } - RunCommand(mi, regs, rsp); + RunCommand(); } +private: + Mem& mem; + Registers& regs; }; } // backend diff --git a/src/backend/core/RSP.cpp b/src/backend/core/RSP.cpp index 55015874..cc454e77 100644 --- a/src/backend/core/RSP.cpp +++ b/src/backend/core/RSP.cpp @@ -110,26 +110,26 @@ void RSP::WriteStatus(u32 value) { CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7); } -void RSP::Write(u32 addr, u32 value) { +void RSP::Write(u32 addr, u32 val) { switch (addr) { - case 0x04040000: spDMASPAddr.raw = value & 0x1FF8; break; - case 0x04040004: spDMADRAMAddr.raw = value & 0xFFFFF8; break; + case 0x04040000: spDMASPAddr.raw = val & 0x1FF8; break; + case 0x04040004: spDMADRAMAddr.raw = val & 0xFFFFF8; break; case 0x04040008: { - spDMALen.raw = value; + spDMALen.raw = val; DMAtoRSP(mem.GetRDRAM()); } break; case 0x0404000C: { - spDMALen.raw = value; + spDMALen.raw = val; DMAtoRDRAM(mem.GetRDRAM()); } break; - case 0x04040010: WriteStatus(value); break; + case 0x04040010: WriteStatus(val); break; case 0x0404001C: ReleaseSemaphore(); break; case 0x04080000: if(spStatus.halt) { - SetPC(value); + SetPC(val); } break; default: - Util::panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, value); + Util::panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, val); } } diff --git a/src/backend/core/RSP.hpp b/src/backend/core/RSP.hpp index 223737cf..1c4c9e46 100644 --- a/src/backend/core/RSP.hpp +++ b/src/backend/core/RSP.hpp @@ -126,7 +126,7 @@ struct RSP { Exec(instr); } auto Read(u32 addr) -> u32; - void Write(u32 addr, u32 value); + void Write(u32 addr, u32 val); void Exec(u32 instr); SPStatus spStatus{}; u16 oldPC{}, pc{}, nextPC{}; diff --git a/src/backend/core/mmio/AI.cpp b/src/backend/core/mmio/AI.cpp index 86a31094..86a6c445 100644 --- a/src/backend/core/mmio/AI.cpp +++ b/src/backend/core/mmio/AI.cpp @@ -4,6 +4,8 @@ #include namespace n64 { +AI::AI(Mem &mem, Registers ®s) : mem(mem), regs(regs) { } + void AI::Reset() { dmaEnable = false; dacRate = 0; @@ -33,7 +35,7 @@ auto AI::Read(u32 addr) const -> u32 { return dmaLen[0]; } -void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { +void AI::Write(u32 addr, u32 val) { switch(addr) { case 0x04500000: if(dmaCount < 2) { @@ -72,7 +74,7 @@ void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { } } -void AI::Step(Mem& mem, Registers& regs, u32 cpuCycles, float volumeL, float volumeR) { +void AI::Step(u32 cpuCycles, float volumeL, float volumeR) { cycles += cpuCycles; while(cycles > dac.period) { if (dmaCount == 0) { diff --git a/src/backend/core/mmio/AI.hpp b/src/backend/core/mmio/AI.hpp index d633d24b..3f522216 100644 --- a/src/backend/core/mmio/AI.hpp +++ b/src/backend/core/mmio/AI.hpp @@ -8,11 +8,11 @@ struct Mem; struct Registers; struct AI { - AI() = default; + AI(Mem&, Registers& regs); void Reset(); auto Read(u32) const -> u32; - void Write(Mem&, Registers&, u32, u32); - void Step(Mem&, Registers&, u32, float, float); + void Write(u32, u32); + void Step(u32, float, float); bool dmaEnable{}; u16 dacRate{}; u8 bitrate{}; @@ -28,5 +28,8 @@ struct AI { u32 period{N64_CPU_FREQ / freq}; u32 precision{16}; } dac; +private: + Mem& mem; + Registers& regs; }; } \ No newline at end of file diff --git a/src/backend/core/mmio/MI.cpp b/src/backend/core/mmio/MI.cpp index 9c818629..4fb85ff9 100644 --- a/src/backend/core/mmio/MI.cpp +++ b/src/backend/core/mmio/MI.cpp @@ -27,7 +27,7 @@ auto MI::Read(u32 paddr) const -> u32 { } } -void MI::Write(Registers& regs, u32 paddr, u32 val) { +void MI::Write(u32 paddr, u32 val) { switch(paddr & 0xF) { case 0x0: miMode &= 0xFFFFFF80; diff --git a/src/backend/core/mmio/MI.hpp b/src/backend/core/mmio/MI.hpp index 73d67ae1..cc6f398d 100644 --- a/src/backend/core/mmio/MI.hpp +++ b/src/backend/core/mmio/MI.hpp @@ -26,7 +26,7 @@ struct MI { MI(Registers&); void Reset(); [[nodiscard]] auto Read(u32) const -> u32; - void Write(Registers& regs, u32, u32); + void Write(u32, u32); void InterruptRaise(Interrupt intr); void InterruptLower(Interrupt intr); void UpdateInterrupt(); diff --git a/src/backend/core/mmio/PI.cpp b/src/backend/core/mmio/PI.cpp index 34dc7da2..33aabf8e 100644 --- a/src/backend/core/mmio/PI.cpp +++ b/src/backend/core/mmio/PI.cpp @@ -4,7 +4,7 @@ #include namespace n64 { -PI::PI() { +PI::PI(Mem& mem, Registers& regs) : mem(mem), regs(regs) { Reset(); } @@ -42,13 +42,13 @@ bool PI::WriteLatch(u32 value) { bool PI::ReadLatch() { if (ioBusy) [[unlikely]] { ioBusy = false; - CpuStall(scheduler.Remove(PI_BUS_WRITE_COMPLETE)); + regs.CpuStall(scheduler.Remove(PI_BUS_WRITE_COMPLETE)); return false; } return true; } -template<> auto PI::BusRead(Mem& mem, u32 addr) -> u8 { +template<> auto PI::BusRead(u32 addr) -> u8 { switch (addr) { case REGION_PI_UNKNOWN: Util::panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr); @@ -73,7 +73,7 @@ template<> auto PI::BusRead(Mem& mem, u32 addr) -> u8 { } } -template<> auto PI::BusRead(Mem& mem, u32 addr) -> u8 { +template<> auto PI::BusRead(u32 addr) -> u8 { if (!ReadLatch()) [[unlikely]] { return latch >> 24; } @@ -103,7 +103,7 @@ template<> auto PI::BusRead(Mem& mem, u32 addr) -> u8 { } } -template<> void PI::BusWrite(Mem& mem, u32 addr, u32 val) { +template<> void PI::BusWrite(u32 addr, u32 val) { switch (addr) { case REGION_PI_UNKNOWN: Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); @@ -127,17 +127,17 @@ template<> void PI::BusWrite(Mem& mem, u32 addr, u32 val) { } } -template<> void PI::BusWrite(Mem& mem, u32 addr, u32 val) { +template<> void PI::BusWrite(u32 addr, u32 val) { u8 latch_shift = 24 - (addr & 1) * 8; if (!WriteLatch(val << latch_shift) && addr != 0x05000020) [[unlikely]] { return; } - BusWrite(mem, addr, val); + BusWrite(addr, val); } -template <> auto PI::BusRead(Mem& mem, u32 addr) -> u16 { +template <> auto PI::BusRead(u32 addr) -> u16 { if (!ReadLatch()) [[unlikely]] { return latch >> 16; } @@ -164,11 +164,11 @@ template <> auto PI::BusRead(Mem& mem, u32 addr) -> u16 { } } -template <> auto PI::BusRead(Mem& mem, u32 addr) -> u16 { - return BusRead(mem, addr); +template <> auto PI::BusRead(u32 addr) -> u16 { + return BusRead(addr); } -template <> void PI::BusWrite(Mem&, u32 addr, u32 val) { +template <> void PI::BusWrite(u32 addr, u32 val) { if (!WriteLatch(val << 16)) [[unlikely]] { return; } @@ -190,11 +190,11 @@ template <> void PI::BusWrite(Mem&, u32 addr, u32 val) { } } -template <> void PI::BusWrite(Mem& mem, u32 addr, u32 val) { - BusWrite(mem, addr, val); +template <> void PI::BusWrite(u32 addr, u32 val) { + BusWrite(addr, val); } -template <> auto PI::BusRead(Mem& mem, u32 addr) -> u32 { +template <> auto PI::BusRead(u32 addr) -> u32 { if (!ReadLatch()) [[unlikely]] { return latch; } @@ -232,11 +232,11 @@ template <> auto PI::BusRead(Mem& mem, u32 addr) -> u32 { } } -template <> auto PI::BusRead(Mem& mem, u32 addr) -> u32 { - return BusRead(mem, addr); +template <> auto PI::BusRead(u32 addr) -> u32 { + return BusRead(addr); } -template <> void PI::BusWrite(Mem& mem, u32 addr, u32 val) { +template <> void PI::BusWrite(u32 addr, u32 val) { switch (addr) { case REGION_PI_UNKNOWN: if (!WriteLatch(val)) [[unlikely]] { @@ -293,11 +293,11 @@ template <> void PI::BusWrite(Mem& mem, u32 addr, u32 val) { } template <> -void PI::BusWrite(Mem& mem, u32 addr, u32 val) { - BusWrite(mem, addr, val); +void PI::BusWrite(u32 addr, u32 val) { + BusWrite(addr, val); } -template <> auto PI::BusRead(Mem& mem, u32 addr) -> u64 { +template <> auto PI::BusRead(u32 addr) -> u64 { if (!ReadLatch()) [[unlikely]] { return (u64)latch << 32; } @@ -323,11 +323,11 @@ template <> auto PI::BusRead(Mem& mem, u32 addr) -> u64 { } } -template <> auto PI::BusRead(Mem& mem, u32 addr) -> u64 { - return BusRead(mem, addr); +template <> auto PI::BusRead(u32 addr) -> u64 { + return BusRead(addr); } -template <> void PI::BusWrite(Mem&, u32 addr, u64 val) { +template <> void PI::BusWrite(u32 addr, u64 val) { if (!WriteLatch(val >> 32)) [[unlikely]] { return; } @@ -349,11 +349,11 @@ template <> void PI::BusWrite(Mem&, u32 addr, u64 val) { } } -template <> void PI::BusWrite(Mem& mem, u32 addr, u64 val) { - BusWrite(mem, addr, val); +template <> void PI::BusWrite(u32 addr, u64 val) { + BusWrite(addr, val); } -auto PI::Read(MI& mi, u32 addr) const -> u32 { +auto PI::Read(u32 addr) const -> u32 { switch(addr) { case 0x04600000: return dramAddr; case 0x04600004: return cartAddr; @@ -364,7 +364,7 @@ auto PI::Read(MI& mi, u32 addr) const -> u32 { value |= (dmaBusy << 0); // Is PI DMA active? No, because it's instant value |= (ioBusy << 1); // Is PI IO busy? No, because it's instant value |= (0 << 2); // PI IO error? - value |= (mi.miIntr.pi << 3); // PI interrupt? + value |= (mem.mmio.mi.miIntr.pi << 3); // PI interrupt? return value; } case 0x04600014: return piBsdDom1Lat; @@ -427,7 +427,7 @@ u32 PI::AccessTiming(u8 domain, u32 length) const { return cycles * 1.5; // Converting RCP clock speed to CPU clock speed } -void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { +void PI::Write(u32 addr, u32 val) { MI& mi = mem.mmio.mi; switch(addr) { case 0x04600000: dramAddr = val & 0xFFFFFF; break; @@ -444,7 +444,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { Util::panic("PI DMA RDRAM->CART ADDRESS TOO HIGH"); } for (int i = 0; i < len; i++) { - BusWrite(mem, cartAddrInternal + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE]); + BusWrite(cartAddrInternal + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE]); } Util::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr); dmaBusy = true; @@ -465,7 +465,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { } for(u32 i = 0; i < len; i++) { - mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE] = BusRead(mem, cartAddrInternal + i); + mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE] = BusRead(cartAddrInternal + i); } dmaBusy = true; Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr); diff --git a/src/backend/core/mmio/PI.hpp b/src/backend/core/mmio/PI.hpp index 1d31b381..d1132cb0 100644 --- a/src/backend/core/mmio/PI.hpp +++ b/src/backend/core/mmio/PI.hpp @@ -8,18 +8,18 @@ struct Mem; struct Registers; struct PI { - PI(); + PI(Mem&, Registers&); void Reset(); - auto Read(MI&, u32) const -> u32; - void Write(Mem&, Registers&, u32, u32); + auto Read(u32) const -> u32; + void Write(u32, u32); template - void BusWrite(Mem&, u32, u32); + void BusWrite(u32, u32); template - void BusWrite(Mem&, u32, u64); + void BusWrite(u32, u64); template - auto BusRead(Mem&, u32) -> T; + auto BusRead(u32) -> T; bool ReadLatch(); bool WriteLatch(u32 val); @@ -34,5 +34,8 @@ struct PI { u32 piBsdDom1Pwd{}, piBsdDom2Pwd{}; u32 piBsdDom1Pgs{}, piBsdDom2Pgs{}; u32 piBsdDom1Rls{}, piBsdDom2Rls{}; +private: + Mem& mem; + Registers& regs; }; } \ No newline at end of file diff --git a/src/backend/core/mmio/SI.cpp b/src/backend/core/mmio/SI.cpp index 157e66da..db8d9a15 100644 --- a/src/backend/core/mmio/SI.cpp +++ b/src/backend/core/mmio/SI.cpp @@ -3,7 +3,7 @@ #include namespace n64 { -SI::SI(Mem& mem, Registers& regs) : pif(mem, regs) { +SI::SI(Mem& mem, Registers& regs) : mem(mem), regs(regs), pif(mem, regs) { Reset(); } @@ -14,7 +14,7 @@ void SI::Reset() { pif.Reset(); } -auto SI::Read(MI& mi, u32 addr) const -> u32 { +auto SI::Read(u32 addr) const -> u32 { switch(addr) { case 0x04800000: return dramAddr; case 0x04800004: case 0x04800010: return pifAddr; @@ -24,7 +24,7 @@ auto SI::Read(MI& mi, u32 addr) const -> u32 { val |= status.dmaBusy; val |= (0 << 1); val |= (0 << 3); - val |= (mi.miIntr.si << 12); + val |= (mem.mmio.mi.miIntr.si << 12); return val; } default: @@ -32,26 +32,25 @@ auto SI::Read(MI& mi, u32 addr) const -> u32 { } } -void SI::DMA(Mem& mem, Registers& regs) const { - SI& si = mem.mmio.si; - si.status.dmaBusy = false; +void SI::DMA() { + status.dmaBusy = false; if (toDram) { - si.pif.ProcessCommands(mem); + pif.ProcessCommands(mem); for(int i = 0; i < 64; i++) { - mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)] = si.pif.Read(si.pifAddr + i); + mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddr + i)] = pif.Read(pifAddr + i); } - Util::trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", si.pifAddr, si.dramAddr); + Util::trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr); } else { for(int i = 0; i < 64; i++) { - si.pif.Write(si.pifAddr + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)]); + pif.Write(pifAddr + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddr + i)]); } - Util::trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", si.dramAddr, si.pifAddr); - si.pif.ProcessCommands(mem); + Util::trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr); + pif.ProcessCommands(mem); } mem.mmio.mi.InterruptRaise(MI::Interrupt::SI); } -void SI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { +void SI::Write(u32 addr, u32 val) { switch(addr) { case 0x04800000: dramAddr = val & RDRAM_DSIZE; diff --git a/src/backend/core/mmio/SI.hpp b/src/backend/core/mmio/SI.hpp index 9f1cfbd2..e58f25bb 100644 --- a/src/backend/core/mmio/SI.hpp +++ b/src/backend/core/mmio/SI.hpp @@ -28,10 +28,13 @@ struct SI { u32 pifAddr{}; bool toDram = false; - auto Read(MI&, u32) const -> u32; - void Write(Mem&, Registers&, u32, u32); - void DMA(Mem&, Registers&) const; + auto Read(u32) const -> u32; + void Write(u32, u32); + void DMA(); PIF pif; +private: + Mem& mem; + Registers& regs; }; #define SI_DMA_DELAY (65536 * 2) diff --git a/src/backend/core/mmio/VI.cpp b/src/backend/core/mmio/VI.cpp index 0995602b..f1230ac2 100644 --- a/src/backend/core/mmio/VI.cpp +++ b/src/backend/core/mmio/VI.cpp @@ -1,11 +1,11 @@ #include #include #include -#include +#include #include namespace n64 { -VI::VI () { +VI::VI (Mem& mem, Registers& regs) : mem(mem), regs(regs) { Reset(); } @@ -43,7 +43,7 @@ u32 VI::Read(u32 paddr) const { } } -void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) { +void VI::Write(u32 paddr, u32 val) { switch(paddr) { case 0x04400000: status.raw = val; @@ -63,7 +63,7 @@ void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) { intr = val & 0x3FF; } break; case 0x04400010: - mi.InterruptLower(MI::Interrupt::VI); + mem.mmio.mi.InterruptLower(MI::Interrupt::VI); break; case 0x04400014: burst.raw = val; break; case 0x04400018: { diff --git a/src/backend/core/mmio/VI.hpp b/src/backend/core/mmio/VI.hpp index d7a71691..c08170a1 100644 --- a/src/backend/core/mmio/VI.hpp +++ b/src/backend/core/mmio/VI.hpp @@ -72,14 +72,14 @@ union AxisStart { }; }; -struct MI; +struct Mem; struct Registers; struct VI { - VI(); + VI(Mem&, Registers&); void Reset(); [[nodiscard]] u32 Read(u32) const; - void Write(MI&, Registers&, u32, u32); + void Write(u32, u32); AxisScale xscale{}, yscale{}; VIHsyncLeap hsyncLeap{}; VIStatus status{}; @@ -93,5 +93,8 @@ struct VI { int numHalflines{}; int numFields{}; int cyclesPerHalfline{}; +private: + Mem& mem; + Registers& regs; }; } // backend diff --git a/src/backend/core/registers/Registers.hpp b/src/backend/core/registers/Registers.hpp index 71da4539..71e2220e 100644 --- a/src/backend/core/registers/Registers.hpp +++ b/src/backend/core/registers/Registers.hpp @@ -14,5 +14,16 @@ struct Registers { s64 hi{}, lo{}; bool prevDelaySlot{}, delaySlot{}; int steps = 0; + u32 extraCycles = 0; + + void CpuStall(u32 cycles) { + extraCycles += cycles; + } + + u32 PopStalledCycles() { + u32 ret = extraCycles; + extraCycles = 0; + return ret; + } }; } diff --git a/src/backend/core/rsp/instructions.cpp b/src/backend/core/rsp/instructions.cpp index 69a06559..7f95fe85 100644 --- a/src/backend/core/rsp/instructions.cpp +++ b/src/backend/core/rsp/instructions.cpp @@ -75,8 +75,8 @@ FORCE_INLINE void SetCop0Reg(Registers& regs, Mem& mem, u8 index, u32 val) { } break; case 8: rdp.WriteStart(val); break; - case 9: rdp.WriteEnd(mi, regs, rsp, val); break; - case 11: rdp.WriteStatus(mi, regs, rsp, val); break; + case 9: rdp.WriteEnd(val); break; + case 11: rdp.WriteStatus(val); break; default: Util::panic("Unhandled RSP COP0 register write at index {}", index); } }