Refactor many other things

This commit is contained in:
SimoneN64
2024-05-13 20:54:53 +02:00
committed by Simone
parent 5148a836a1
commit 059f884ca7
23 changed files with 150 additions and 141 deletions

View File

@@ -3,18 +3,6 @@
#include <ParallelRDPWrapper.hpp> #include <ParallelRDPWrapper.hpp>
namespace n64 { 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<Interpreter>()) {} Core::Core() : cpu(std::make_unique<Interpreter>()) {}
void Core::Stop() { void Core::Stop() {
@@ -71,7 +59,7 @@ void Core::Run(float volumeL, float volumeR) {
for(; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) { for(; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
u32 taken = cpu->Step(); u32 taken = cpu->Step();
taken += PopStalledCycles(); taken += regs.PopStalledCycles();
static u32 cpuSteps = 0; static u32 cpuSteps = 0;
cpuSteps += taken; cpuSteps += taken;
if(mmio.rsp.spStatus.halt) { if(mmio.rsp.spStatus.halt) {
@@ -91,7 +79,7 @@ void Core::Run(float volumeL, float volumeR) {
cycles += taken; cycles += taken;
frameCycles += taken; frameCycles += taken;
scheduler.Tick(taken, mem, regs); scheduler.Tick(taken, mem);
} }
cycles -= mmio.vi.cyclesPerHalfline; cycles -= mmio.vi.cyclesPerHalfline;
@@ -101,8 +89,8 @@ void Core::Run(float volumeL, float volumeR) {
mmio.mi.InterruptRaise(MI::Interrupt::VI); mmio.mi.InterruptRaise(MI::Interrupt::VI);
} }
mmio.ai.Step(cpu->mem, regs, frameCycles, volumeL, volumeR); mmio.ai.Step(frameCycles, volumeL, volumeR);
scheduler.Tick(frameCycles, mem, regs); scheduler.Tick(frameCycles, mem);
} }
} }

View File

@@ -30,8 +30,4 @@ struct Core {
size_t memSize{}, cpuSize{}, verSize{}; size_t memSize{}, cpuSize{}, verSize{};
int slot = 0; int slot = 0;
}; };
extern u32 extraCycles;
void CpuStall(u32 cycles);
u32 PopStalledCycles();
} }

View File

@@ -25,7 +25,7 @@ u64 Scheduler::Remove(EventType type) {
return 0; return 0;
} }
void Scheduler::Tick(u64 t, n64::Mem& mem, n64::Registers& regs) { void Scheduler::Tick(u64 t, n64::Mem& mem) {
ticks += t; ticks += t;
n64::MI& mi = mem.mmio.mi; n64::MI& mi = mem.mmio.mi;
n64::SI& si = mem.mmio.si; 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) { while(ticks >= events.top().time) {
switch(auto type = events.top().type) { switch(auto type = events.top().type) {
case SI_DMA: case SI_DMA:
si.DMA(mem, regs); si.DMA();
break; break;
case PI_DMA_COMPLETE: case PI_DMA_COMPLETE:
mi.InterruptRaise(n64::MI::Interrupt::PI); mi.InterruptRaise(n64::MI::Interrupt::PI);

View File

@@ -53,7 +53,7 @@ struct Scheduler {
void EnqueueRelative(u64, EventType); void EnqueueRelative(u64, EventType);
void EnqueueAbsolute(u64, EventType); void EnqueueAbsolute(u64, EventType);
u64 Remove(EventType); u64 Remove(EventType);
void Tick(u64 t, n64::Mem&, n64::Registers&); void Tick(u64 t, n64::Mem&);
IterableEvents events; IterableEvents events;
u64 ticks = 0; u64 ticks = 0;

View File

@@ -1,7 +1,5 @@
#include <core/MMIO.hpp> #include <core/MMIO.hpp>
#include <log.hpp>
#include <core/Mem.hpp> #include <core/Mem.hpp>
#include <core/registers/Registers.hpp>
namespace n64 { namespace n64 {
void MMIO::Reset() { void MMIO::Reset() {
@@ -22,24 +20,24 @@ u32 MMIO::Read(u32 addr) {
case MI_REGION: return mi.Read(addr); case MI_REGION: return mi.Read(addr);
case VI_REGION: return vi.Read(addr); case VI_REGION: return vi.Read(addr);
case AI_REGION: return ai.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 RI_REGION: return ri.Read(addr);
case SI_REGION: return si.Read(mi, addr); case SI_REGION: return si.Read(addr);
default: default:
Util::panic("Unhandled mmio read at addr {:08X}", addr); 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) { switch (addr) {
case RSP_REGION: rsp.Write(addr, val); break; case RSP_REGION: rsp.Write(addr, val); break;
case RDP_REGION: rdp.Write(mi, regs, rsp, addr, val); break; case RDP_REGION: rdp.Write(addr, val); break;
case MI_REGION: mi.Write(regs, addr, val); break; case MI_REGION: mi.Write(addr, val); break;
case VI_REGION: vi.Write(mi, regs, addr, val); break; case VI_REGION: vi.Write(addr, val); break;
case AI_REGION: ai.Write(mem, regs, addr, val); break; case AI_REGION: ai.Write(addr, val); break;
case PI_REGION: pi.Write(mem, regs, addr, val); break; case PI_REGION: pi.Write(addr, val); break;
case RI_REGION: ri.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: default:
Util::panic("Unhandled mmio write at addr {:08X} with val {:08X}", addr, val); Util::panic("Unhandled mmio write at addr {:08X} with val {:08X}", addr, val);
} }

View File

@@ -13,7 +13,7 @@ struct Mem;
struct Registers; struct Registers;
struct MMIO { 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(); void Reset();
VI vi; VI vi;
@@ -26,7 +26,7 @@ struct MMIO {
RDP rdp; RDP rdp;
u32 Read(u32); u32 Read(u32);
void Write(Mem&, Registers&, u32, u32); void Write(u32, u32);
std::vector<u8> Serialize(); std::vector<u8> Serialize();
void Deserialize(const std::vector<u8>&); void Deserialize(const std::vector<u8>&);
}; };

View File

@@ -193,7 +193,7 @@ template<> u8 Mem::Read(n64::Registers &regs, u32 paddr) {
return src[BYTE_ADDRESS(paddr & 0xfff)]; return src[BYTE_ADDRESS(paddr & 0xfff)];
} }
case REGION_CART: case REGION_CART:
return mmio.pi.BusRead<u8, false>(*this, paddr); return mmio.pi.BusRead<u8, false>(paddr);
case 0x04040000 ... 0x040FFFFF: case 0x04040000 ... 0x040FFFFF:
case 0x04100000 ... 0x041FFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x04600000 ... 0x048FFFFF: case 0x04600000 ... 0x048FFFFF:
@@ -238,7 +238,7 @@ template<> u16 Mem::Read(n64::Registers &regs, u32 paddr) {
case MMIO_REGION: case MMIO_REGION:
return mmio.Read(paddr); return mmio.Read(paddr);
case REGION_CART: case REGION_CART:
return mmio.pi.BusRead<u16, false>(*this, paddr); return mmio.pi.BusRead<u16, false>(paddr);
case PIF_ROM_REGION: case PIF_ROM_REGION:
return Util::ReadAccess<u16>(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START); return Util::ReadAccess<u16>(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START);
case PIF_RAM_REGION: case PIF_RAM_REGION:
@@ -273,7 +273,7 @@ template<> u32 Mem::Read(n64::Registers &regs, u32 paddr) {
case MMIO_REGION: case MMIO_REGION:
return mmio.Read(paddr); return mmio.Read(paddr);
case REGION_CART: case REGION_CART:
return mmio.pi.BusRead<u32, false>(*this, paddr); return mmio.pi.BusRead<u32, false>(paddr);
case PIF_ROM_REGION: case PIF_ROM_REGION:
return Util::ReadAccess<u32>(si.pif.bootrom, paddr - PIF_ROM_REGION_START); return Util::ReadAccess<u32>(si.pif.bootrom, paddr - PIF_ROM_REGION_START);
case PIF_RAM_REGION: case PIF_RAM_REGION:
@@ -305,7 +305,7 @@ template<> u64 Mem::Read(n64::Registers &regs, u32 paddr) {
case MMIO_REGION: case MMIO_REGION:
return mmio.Read(paddr); return mmio.Read(paddr);
case REGION_CART: case REGION_CART:
return mmio.pi.BusRead<u64, false>(*this, paddr); return mmio.pi.BusRead<u64, false>(paddr);
case PIF_ROM_REGION: case PIF_ROM_REGION:
return Util::ReadAccess<u64>(si.pif.bootrom, paddr - PIF_ROM_REGION_START); return Util::ReadAccess<u64>(si.pif.bootrom, paddr - PIF_ROM_REGION_START);
case PIF_RAM_REGION: case PIF_RAM_REGION:
@@ -342,7 +342,7 @@ template<> void Mem::Write<u8>(Registers& regs, u32 paddr, u32 val) {
} break; } break;
case REGION_CART: case REGION_CART:
Util::trace("BusWrite<u8> @ {:08X} = {:02X}", paddr, val); Util::trace("BusWrite<u8> @ {:08X} = {:02X}", paddr, val);
mmio.pi.BusWrite<u8, false>(*this, paddr, val); mmio.pi.BusWrite<u8, false>(paddr, val);
break; break;
case MMIO_REGION: case MMIO_REGION:
Util::panic("MMIO Write<u8>!"); Util::panic("MMIO Write<u8>!");
@@ -387,7 +387,7 @@ template<> void Mem::Write<u16>(Registers& regs, u32 paddr, u32 val) {
} break; } break;
case REGION_CART: case REGION_CART:
Util::trace("BusWrite<u8> @ {:08X} = {:04X}", paddr, val); Util::trace("BusWrite<u8> @ {:08X} = {:04X}", paddr, val);
mmio.pi.BusWrite<u16, false>(*this, paddr, val); mmio.pi.BusWrite<u16, false>(paddr, val);
break; break;
case MMIO_REGION: case MMIO_REGION:
Util::panic("MMIO Write<u16>!"); Util::panic("MMIO Write<u16>!");
@@ -430,10 +430,10 @@ template<> void Mem::Write<u32>(Registers& regs, u32 paddr, u32 val) {
} break; } break;
case REGION_CART: case REGION_CART:
Util::trace("BusWrite<u8> @ {:08X} = {:08X}", paddr, val); Util::trace("BusWrite<u8> @ {:08X} = {:08X}", paddr, val);
mmio.pi.BusWrite<u32, false>(*this, paddr, val); mmio.pi.BusWrite<u32, false>(paddr, val);
break; break;
case MMIO_REGION: case MMIO_REGION:
mmio.Write(*this, regs, paddr, val); mmio.Write(paddr, val);
break; break;
case PIF_RAM_REGION: case PIF_RAM_REGION:
Util::WriteAccess<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val)); Util::WriteAccess<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val));
@@ -470,7 +470,7 @@ void Mem::Write(Registers& regs, u32 paddr, u64 val) {
} break; } break;
case REGION_CART: case REGION_CART:
Util::trace("BusWrite<u8> @ {:08X} = {:016X}", paddr, val); Util::trace("BusWrite<u8> @ {:08X} = {:016X}", paddr, val);
mmio.pi.BusWrite<false>(*this, paddr, val); mmio.pi.BusWrite<false>(paddr, val);
break; break;
case MMIO_REGION: case MMIO_REGION:
Util::panic("MMIO Write!"); Util::panic("MMIO Write!");

View File

@@ -5,7 +5,7 @@
#include <core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
namespace n64 { namespace n64 {
RDP::RDP() { RDP::RDP(Mem& mem, Registers& regs) : mem(mem), regs(regs) {
rdram.resize(RDRAM_SIZE); rdram.resize(RDRAM_SIZE);
memset(cmd_buf, 0, 0x100000); memset(cmd_buf, 0, 0x100000);
dpc.status.raw = 0x80; 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) { switch(addr) {
case 0x04100000: WriteStart(val); break; case 0x04100000: WriteStart(val); break;
case 0x04100004: WriteEnd(mi, regs, rsp, val); break; case 0x04100004: WriteEnd(val); break;
case 0x0410000C: WriteStatus(mi, regs, rsp, val); break; case 0x0410000C: WriteStatus(val); break;
default: default:
Util::panic("Unhandled DP Command Registers write (addr: {:08X}, val: {:08X})", addr, val); 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{}; DPCStatusWrite temp{};
temp.raw = val; 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); CLEAR_SET(dpc.status.tmemBusy, temp.clearTmem, false);
if(!dpc.status.freeze) { 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) { if (dpc.status.freeze) {
return; return;
} }
@@ -138,7 +138,7 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) {
if (dpc.status.xbusDmemDma) { if (dpc.status.xbusDmemDma) {
for (int i = 0; i < len; i += 4) { for (int i = 0; i < len; i += 4) {
u32 cmd = Util::ReadAccess<u32>(rsp.dmem, (current + i) & 0xFFF); u32 cmd = Util::ReadAccess<u32>(mem.mmio.rsp.dmem, (current + i) & 0xFFF);
cmd_buf[remaining_cmds + (i >> 2)] = cmd; cmd_buf[remaining_cmds + (i >> 2)] = cmd;
} }
} else { } else {
@@ -181,7 +181,7 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) {
} }
if (cmd == 0x29) { if (cmd == 0x29) {
OnFullSync(mi, regs); OnFullSync();
} }
buf_index += cmd_len; buf_index += cmd_len;
@@ -198,12 +198,12 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) {
dpc.status.cbufReady = true; dpc.status.cbufReady = true;
} }
void RDP::OnFullSync(MI& mi, Registers& regs) { void RDP::OnFullSync() {
ParallelRdpOnFullSync(); ParallelRdpOnFullSync();
dpc.status.pipeBusy = false; dpc.status.pipeBusy = false;
dpc.status.startGclk = false; dpc.status.startGclk = false;
dpc.status.cbufReady = false; dpc.status.cbufReady = false;
mi.InterruptRaise(MI::Interrupt::DP); mem.mmio.mi.InterruptRaise(MI::Interrupt::DP);
} }
} }

View File

@@ -5,7 +5,7 @@
namespace n64 { namespace n64 {
struct RSP; struct RSP;
struct MI; struct Mem;
struct Registers; struct Registers;
union DPCStatusWrite { union DPCStatusWrite {
@@ -54,15 +54,15 @@ struct RDP {
DPC dpc{}; DPC dpc{};
u32 cmd_buf[0xFFFFF]{}; u32 cmd_buf[0xFFFFF]{};
RDP(); RDP(Mem&, Registers&);
void Reset(); void Reset();
std::vector<u8> rdram{}; std::vector<u8> rdram{};
[[nodiscard]] auto Read(u32 addr) const -> u32; [[nodiscard]] auto Read(u32 addr) const -> u32;
void Write(MI& mi, Registers& regs, RSP& rsp, u32 addr, u32 val); void Write(u32 addr, u32 val);
void WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val); void WriteStatus(u32 val);
void RunCommand(MI& mi, Registers& regs, RSP& rsp); void RunCommand();
void OnFullSync(MI& mi, Registers& regs); void OnFullSync();
FORCE_INLINE void WriteStart(u32 val) { FORCE_INLINE void WriteStart(u32 val) {
if(!dpc.status.startValid) { if(!dpc.status.startValid) {
@@ -71,13 +71,16 @@ struct RDP {
dpc.status.startValid = true; 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; dpc.end = val & 0xFFFFF8;
if(dpc.status.startValid) { if(dpc.status.startValid) {
dpc.current = dpc.start; dpc.current = dpc.start;
dpc.status.startValid = false; dpc.status.startValid = false;
} }
RunCommand(mi, regs, rsp); RunCommand();
} }
private:
Mem& mem;
Registers& regs;
}; };
} // backend } // backend

View File

@@ -110,26 +110,26 @@ void RSP::WriteStatus(u32 value) {
CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7); CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7);
} }
void RSP::Write(u32 addr, u32 value) { void RSP::Write(u32 addr, u32 val) {
switch (addr) { switch (addr) {
case 0x04040000: spDMASPAddr.raw = value & 0x1FF8; break; case 0x04040000: spDMASPAddr.raw = val & 0x1FF8; break;
case 0x04040004: spDMADRAMAddr.raw = value & 0xFFFFF8; break; case 0x04040004: spDMADRAMAddr.raw = val & 0xFFFFF8; break;
case 0x04040008: { case 0x04040008: {
spDMALen.raw = value; spDMALen.raw = val;
DMAtoRSP(mem.GetRDRAM()); DMAtoRSP(mem.GetRDRAM());
} break; } break;
case 0x0404000C: { case 0x0404000C: {
spDMALen.raw = value; spDMALen.raw = val;
DMAtoRDRAM(mem.GetRDRAM()); DMAtoRDRAM(mem.GetRDRAM());
} break; } break;
case 0x04040010: WriteStatus(value); break; case 0x04040010: WriteStatus(val); break;
case 0x0404001C: ReleaseSemaphore(); break; case 0x0404001C: ReleaseSemaphore(); break;
case 0x04080000: case 0x04080000:
if(spStatus.halt) { if(spStatus.halt) {
SetPC(value); SetPC(val);
} break; } break;
default: default:
Util::panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, value); Util::panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, val);
} }
} }

View File

@@ -126,7 +126,7 @@ struct RSP {
Exec(instr); Exec(instr);
} }
auto Read(u32 addr) -> u32; auto Read(u32 addr) -> u32;
void Write(u32 addr, u32 value); void Write(u32 addr, u32 val);
void Exec(u32 instr); void Exec(u32 instr);
SPStatus spStatus{}; SPStatus spStatus{};
u16 oldPC{}, pc{}, nextPC{}; u16 oldPC{}, pc{}, nextPC{};

View File

@@ -4,6 +4,8 @@
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
namespace n64 { namespace n64 {
AI::AI(Mem &mem, Registers &regs) : mem(mem), regs(regs) { }
void AI::Reset() { void AI::Reset() {
dmaEnable = false; dmaEnable = false;
dacRate = 0; dacRate = 0;
@@ -33,7 +35,7 @@ auto AI::Read(u32 addr) const -> u32 {
return dmaLen[0]; return dmaLen[0];
} }
void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { void AI::Write(u32 addr, u32 val) {
switch(addr) { switch(addr) {
case 0x04500000: case 0x04500000:
if(dmaCount < 2) { 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; cycles += cpuCycles;
while(cycles > dac.period) { while(cycles > dac.period) {
if (dmaCount == 0) { if (dmaCount == 0) {

View File

@@ -8,11 +8,11 @@ struct Mem;
struct Registers; struct Registers;
struct AI { struct AI {
AI() = default; AI(Mem&, Registers& regs);
void Reset(); void Reset();
auto Read(u32) const -> u32; auto Read(u32) const -> u32;
void Write(Mem&, Registers&, u32, u32); void Write(u32, u32);
void Step(Mem&, Registers&, u32, float, float); void Step(u32, float, float);
bool dmaEnable{}; bool dmaEnable{};
u16 dacRate{}; u16 dacRate{};
u8 bitrate{}; u8 bitrate{};
@@ -28,5 +28,8 @@ struct AI {
u32 period{N64_CPU_FREQ / freq}; u32 period{N64_CPU_FREQ / freq};
u32 precision{16}; u32 precision{16};
} dac; } dac;
private:
Mem& mem;
Registers& regs;
}; };
} }

View File

@@ -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) { switch(paddr & 0xF) {
case 0x0: case 0x0:
miMode &= 0xFFFFFF80; miMode &= 0xFFFFFF80;

View File

@@ -26,7 +26,7 @@ struct MI {
MI(Registers&); MI(Registers&);
void Reset(); void Reset();
[[nodiscard]] auto Read(u32) const -> u32; [[nodiscard]] auto Read(u32) const -> u32;
void Write(Registers& regs, u32, u32); void Write(u32, u32);
void InterruptRaise(Interrupt intr); void InterruptRaise(Interrupt intr);
void InterruptLower(Interrupt intr); void InterruptLower(Interrupt intr);
void UpdateInterrupt(); void UpdateInterrupt();

View File

@@ -4,7 +4,7 @@
#include <Scheduler.hpp> #include <Scheduler.hpp>
namespace n64 { namespace n64 {
PI::PI() { PI::PI(Mem& mem, Registers& regs) : mem(mem), regs(regs) {
Reset(); Reset();
} }
@@ -42,13 +42,13 @@ bool PI::WriteLatch(u32 value) {
bool PI::ReadLatch() { bool PI::ReadLatch() {
if (ioBusy) [[unlikely]] { if (ioBusy) [[unlikely]] {
ioBusy = false; ioBusy = false;
CpuStall(scheduler.Remove(PI_BUS_WRITE_COMPLETE)); regs.CpuStall(scheduler.Remove(PI_BUS_WRITE_COMPLETE));
return false; return false;
} }
return true; return true;
} }
template<> auto PI::BusRead<u8, true>(Mem& mem, u32 addr) -> u8 { template<> auto PI::BusRead<u8, true>(u32 addr) -> u8 {
switch (addr) { switch (addr) {
case REGION_PI_UNKNOWN: 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); 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<u8, true>(Mem& mem, u32 addr) -> u8 {
} }
} }
template<> auto PI::BusRead<u8, false>(Mem& mem, u32 addr) -> u8 { template<> auto PI::BusRead<u8, false>(u32 addr) -> u8 {
if (!ReadLatch()) [[unlikely]] { if (!ReadLatch()) [[unlikely]] {
return latch >> 24; return latch >> 24;
} }
@@ -103,7 +103,7 @@ template<> auto PI::BusRead<u8, false>(Mem& mem, u32 addr) -> u8 {
} }
} }
template<> void PI::BusWrite<u8, true>(Mem& mem, u32 addr, u32 val) { template<> void PI::BusWrite<u8, true>(u32 addr, u32 val) {
switch (addr) { switch (addr) {
case REGION_PI_UNKNOWN: case REGION_PI_UNKNOWN:
Util::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); 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<u8, true>(Mem& mem, u32 addr, u32 val) {
} }
} }
template<> void PI::BusWrite<u8, false>(Mem& mem, u32 addr, u32 val) { template<> void PI::BusWrite<u8, false>(u32 addr, u32 val) {
u8 latch_shift = 24 - (addr & 1) * 8; u8 latch_shift = 24 - (addr & 1) * 8;
if (!WriteLatch(val << latch_shift) && addr != 0x05000020) [[unlikely]] { if (!WriteLatch(val << latch_shift) && addr != 0x05000020) [[unlikely]] {
return; return;
} }
BusWrite<u8, true>(mem, addr, val); BusWrite<u8, true>(addr, val);
} }
template <> auto PI::BusRead<u16, false>(Mem& mem, u32 addr) -> u16 { template <> auto PI::BusRead<u16, false>(u32 addr) -> u16 {
if (!ReadLatch()) [[unlikely]] { if (!ReadLatch()) [[unlikely]] {
return latch >> 16; return latch >> 16;
} }
@@ -164,11 +164,11 @@ template <> auto PI::BusRead<u16, false>(Mem& mem, u32 addr) -> u16 {
} }
} }
template <> auto PI::BusRead<u16, true>(Mem& mem, u32 addr) -> u16 { template <> auto PI::BusRead<u16, true>(u32 addr) -> u16 {
return BusRead<u16, false>(mem, addr); return BusRead<u16, false>(addr);
} }
template <> void PI::BusWrite<u16, false>(Mem&, u32 addr, u32 val) { template <> void PI::BusWrite<u16, false>(u32 addr, u32 val) {
if (!WriteLatch(val << 16)) [[unlikely]] { if (!WriteLatch(val << 16)) [[unlikely]] {
return; return;
} }
@@ -190,11 +190,11 @@ template <> void PI::BusWrite<u16, false>(Mem&, u32 addr, u32 val) {
} }
} }
template <> void PI::BusWrite<u16, true>(Mem& mem, u32 addr, u32 val) { template <> void PI::BusWrite<u16, true>(u32 addr, u32 val) {
BusWrite<u16, false>(mem, addr, val); BusWrite<u16, false>(addr, val);
} }
template <> auto PI::BusRead<u32, false>(Mem& mem, u32 addr) -> u32 { template <> auto PI::BusRead<u32, false>(u32 addr) -> u32 {
if (!ReadLatch()) [[unlikely]] { if (!ReadLatch()) [[unlikely]] {
return latch; return latch;
} }
@@ -232,11 +232,11 @@ template <> auto PI::BusRead<u32, false>(Mem& mem, u32 addr) -> u32 {
} }
} }
template <> auto PI::BusRead<u32, true>(Mem& mem, u32 addr) -> u32 { template <> auto PI::BusRead<u32, true>(u32 addr) -> u32 {
return BusRead<u32, false>(mem, addr); return BusRead<u32, false>(addr);
} }
template <> void PI::BusWrite<u32, false>(Mem& mem, u32 addr, u32 val) { template <> void PI::BusWrite<u32, false>(u32 addr, u32 val) {
switch (addr) { switch (addr) {
case REGION_PI_UNKNOWN: case REGION_PI_UNKNOWN:
if (!WriteLatch(val)) [[unlikely]] { if (!WriteLatch(val)) [[unlikely]] {
@@ -293,11 +293,11 @@ template <> void PI::BusWrite<u32, false>(Mem& mem, u32 addr, u32 val) {
} }
template <> template <>
void PI::BusWrite<u32, true>(Mem& mem, u32 addr, u32 val) { void PI::BusWrite<u32, true>(u32 addr, u32 val) {
BusWrite<u32, false>(mem, addr, val); BusWrite<u32, false>(addr, val);
} }
template <> auto PI::BusRead<u64, false>(Mem& mem, u32 addr) -> u64 { template <> auto PI::BusRead<u64, false>(u32 addr) -> u64 {
if (!ReadLatch()) [[unlikely]] { if (!ReadLatch()) [[unlikely]] {
return (u64)latch << 32; return (u64)latch << 32;
} }
@@ -323,11 +323,11 @@ template <> auto PI::BusRead<u64, false>(Mem& mem, u32 addr) -> u64 {
} }
} }
template <> auto PI::BusRead<u64, true>(Mem& mem, u32 addr) -> u64 { template <> auto PI::BusRead<u64, true>(u32 addr) -> u64 {
return BusRead<u64, false>(mem, addr); return BusRead<u64, false>(addr);
} }
template <> void PI::BusWrite<false>(Mem&, u32 addr, u64 val) { template <> void PI::BusWrite<false>(u32 addr, u64 val) {
if (!WriteLatch(val >> 32)) [[unlikely]] { if (!WriteLatch(val >> 32)) [[unlikely]] {
return; return;
} }
@@ -349,11 +349,11 @@ template <> void PI::BusWrite<false>(Mem&, u32 addr, u64 val) {
} }
} }
template <> void PI::BusWrite<true>(Mem& mem, u32 addr, u64 val) { template <> void PI::BusWrite<true>(u32 addr, u64 val) {
BusWrite<false>(mem, addr, val); BusWrite<false>(addr, val);
} }
auto PI::Read(MI& mi, u32 addr) const -> u32 { auto PI::Read(u32 addr) const -> u32 {
switch(addr) { switch(addr) {
case 0x04600000: return dramAddr; case 0x04600000: return dramAddr;
case 0x04600004: return cartAddr; 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 |= (dmaBusy << 0); // Is PI DMA active? No, because it's instant
value |= (ioBusy << 1); // Is PI IO busy? No, because it's instant value |= (ioBusy << 1); // Is PI IO busy? No, because it's instant
value |= (0 << 2); // PI IO error? value |= (0 << 2); // PI IO error?
value |= (mi.miIntr.pi << 3); // PI interrupt? value |= (mem.mmio.mi.miIntr.pi << 3); // PI interrupt?
return value; return value;
} }
case 0x04600014: return piBsdDom1Lat; 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 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; MI& mi = mem.mmio.mi;
switch(addr) { switch(addr) {
case 0x04600000: dramAddr = val & 0xFFFFFF; break; 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"); Util::panic("PI DMA RDRAM->CART ADDRESS TOO HIGH");
} }
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
BusWrite<u8, true>(mem, cartAddrInternal + i, mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE]); BusWrite<u8, true>(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); Util::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
dmaBusy = true; dmaBusy = true;
@@ -465,7 +465,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
} }
for(u32 i = 0; i < len; i++) { for(u32 i = 0; i < len; i++) {
mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE] = BusRead<u8, true>(mem, cartAddrInternal + i); mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE] = BusRead<u8, true>(cartAddrInternal + i);
} }
dmaBusy = true; dmaBusy = true;
Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr); Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);

View File

@@ -8,18 +8,18 @@ struct Mem;
struct Registers; struct Registers;
struct PI { struct PI {
PI(); PI(Mem&, Registers&);
void Reset(); void Reset();
auto Read(MI&, u32) const -> u32; auto Read(u32) const -> u32;
void Write(Mem&, Registers&, u32, u32); void Write(u32, u32);
template<typename T, bool isDma> template<typename T, bool isDma>
void BusWrite(Mem&, u32, u32); void BusWrite(u32, u32);
template<bool isDma> template<bool isDma>
void BusWrite(Mem&, u32, u64); void BusWrite(u32, u64);
template<typename T, bool isDma> template<typename T, bool isDma>
auto BusRead(Mem&, u32) -> T; auto BusRead(u32) -> T;
bool ReadLatch(); bool ReadLatch();
bool WriteLatch(u32 val); bool WriteLatch(u32 val);
@@ -34,5 +34,8 @@ struct PI {
u32 piBsdDom1Pwd{}, piBsdDom2Pwd{}; u32 piBsdDom1Pwd{}, piBsdDom2Pwd{};
u32 piBsdDom1Pgs{}, piBsdDom2Pgs{}; u32 piBsdDom1Pgs{}, piBsdDom2Pgs{};
u32 piBsdDom1Rls{}, piBsdDom2Rls{}; u32 piBsdDom1Rls{}, piBsdDom2Rls{};
private:
Mem& mem;
Registers& regs;
}; };
} }

View File

@@ -3,7 +3,7 @@
#include <Scheduler.hpp> #include <Scheduler.hpp>
namespace n64 { 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(); Reset();
} }
@@ -14,7 +14,7 @@ void SI::Reset() {
pif.Reset(); pif.Reset();
} }
auto SI::Read(MI& mi, u32 addr) const -> u32 { auto SI::Read(u32 addr) const -> u32 {
switch(addr) { switch(addr) {
case 0x04800000: return dramAddr; case 0x04800000: return dramAddr;
case 0x04800004: case 0x04800010: return pifAddr; case 0x04800004: case 0x04800010: return pifAddr;
@@ -24,7 +24,7 @@ auto SI::Read(MI& mi, u32 addr) const -> u32 {
val |= status.dmaBusy; val |= status.dmaBusy;
val |= (0 << 1); val |= (0 << 1);
val |= (0 << 3); val |= (0 << 3);
val |= (mi.miIntr.si << 12); val |= (mem.mmio.mi.miIntr.si << 12);
return val; return val;
} }
default: default:
@@ -32,26 +32,25 @@ auto SI::Read(MI& mi, u32 addr) const -> u32 {
} }
} }
void SI::DMA(Mem& mem, Registers& regs) const { void SI::DMA() {
SI& si = mem.mmio.si; status.dmaBusy = false;
si.status.dmaBusy = false;
if (toDram) { if (toDram) {
si.pif.ProcessCommands(mem); pif.ProcessCommands(mem);
for(int i = 0; i < 64; i++) { 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 { } else {
for(int i = 0; i < 64; i++) { 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); Util::trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr);
si.pif.ProcessCommands(mem); pif.ProcessCommands(mem);
} }
mem.mmio.mi.InterruptRaise(MI::Interrupt::SI); 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) { switch(addr) {
case 0x04800000: case 0x04800000:
dramAddr = val & RDRAM_DSIZE; dramAddr = val & RDRAM_DSIZE;

View File

@@ -28,10 +28,13 @@ struct SI {
u32 pifAddr{}; u32 pifAddr{};
bool toDram = false; bool toDram = false;
auto Read(MI&, u32) const -> u32; auto Read(u32) const -> u32;
void Write(Mem&, Registers&, u32, u32); void Write(u32, u32);
void DMA(Mem&, Registers&) const; void DMA();
PIF pif; PIF pif;
private:
Mem& mem;
Registers& regs;
}; };
#define SI_DMA_DELAY (65536 * 2) #define SI_DMA_DELAY (65536 * 2)

View File

@@ -1,11 +1,11 @@
#include <core/mmio/VI.hpp> #include <core/mmio/VI.hpp>
#include <log.hpp> #include <log.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <core/mmio/MI.hpp> #include <core/Mem.hpp>
#include <core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
namespace n64 { namespace n64 {
VI::VI () { VI::VI (Mem& mem, Registers& regs) : mem(mem), regs(regs) {
Reset(); 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) { switch(paddr) {
case 0x04400000: case 0x04400000:
status.raw = val; status.raw = val;
@@ -63,7 +63,7 @@ void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) {
intr = val & 0x3FF; intr = val & 0x3FF;
} break; } break;
case 0x04400010: case 0x04400010:
mi.InterruptLower(MI::Interrupt::VI); mem.mmio.mi.InterruptLower(MI::Interrupt::VI);
break; break;
case 0x04400014: burst.raw = val; break; case 0x04400014: burst.raw = val; break;
case 0x04400018: { case 0x04400018: {

View File

@@ -72,14 +72,14 @@ union AxisStart {
}; };
}; };
struct MI; struct Mem;
struct Registers; struct Registers;
struct VI { struct VI {
VI(); VI(Mem&, Registers&);
void Reset(); void Reset();
[[nodiscard]] u32 Read(u32) const; [[nodiscard]] u32 Read(u32) const;
void Write(MI&, Registers&, u32, u32); void Write(u32, u32);
AxisScale xscale{}, yscale{}; AxisScale xscale{}, yscale{};
VIHsyncLeap hsyncLeap{}; VIHsyncLeap hsyncLeap{};
VIStatus status{}; VIStatus status{};
@@ -93,5 +93,8 @@ struct VI {
int numHalflines{}; int numHalflines{};
int numFields{}; int numFields{};
int cyclesPerHalfline{}; int cyclesPerHalfline{};
private:
Mem& mem;
Registers& regs;
}; };
} // backend } // backend

View File

@@ -14,5 +14,16 @@ struct Registers {
s64 hi{}, lo{}; s64 hi{}, lo{};
bool prevDelaySlot{}, delaySlot{}; bool prevDelaySlot{}, delaySlot{};
int steps = 0; int steps = 0;
u32 extraCycles = 0;
void CpuStall(u32 cycles) {
extraCycles += cycles;
}
u32 PopStalledCycles() {
u32 ret = extraCycles;
extraCycles = 0;
return ret;
}
}; };
} }

View File

@@ -75,8 +75,8 @@ FORCE_INLINE void SetCop0Reg(Registers& regs, Mem& mem, u8 index, u32 val) {
} }
break; break;
case 8: rdp.WriteStart(val); break; case 8: rdp.WriteStart(val); break;
case 9: rdp.WriteEnd(mi, regs, rsp, val); break; case 9: rdp.WriteEnd(val); break;
case 11: rdp.WriteStatus(mi, regs, rsp, val); break; case 11: rdp.WriteStatus(val); break;
default: Util::panic("Unhandled RSP COP0 register write at index {}", index); default: Util::panic("Unhandled RSP COP0 register write at index {}", index);
} }
} }