#pragma once #include #include #include namespace n64 { union DPCStatusWrite { u32 raw; struct { unsigned clearXbusDmemDma : 1; unsigned setXbusDmemDma : 1; unsigned clearFreeze : 1; unsigned setFreeze : 1; unsigned clearFlush : 1; unsigned setFlush : 1; unsigned clearTmem : 1; unsigned clearPipe : 1; unsigned clearCmd : 1; unsigned clearClock : 1; }; }; union DPCStatus { struct { unsigned xbusDmemDma : 1; unsigned freeze : 1; unsigned flush : 1; unsigned startGclk : 1; unsigned tmemBusy : 1; unsigned pipeBusy : 1; unsigned cmdBusy : 1; unsigned cbufReady : 1; unsigned dmaBusy : 1; unsigned endValid : 1; unsigned startValid : 1; }; u32 raw; }; struct DPC { DPCStatus status; u32 start; u32 current; u32 end; u32 clock; u32 tmem; }; struct RDP { static constexpr auto COMMAND_BUFFER_SIZE = 0xFFFFF; RDP(); void Reset(); [[nodiscard]] auto Read(u32 addr) const -> u32; void Write(u32 addr, u32 val); void WriteStatus(u32 val); void RunCommand(); void OnFullSync(); FORCE_INLINE void WriteStart(u32 val) { if (!dpc.status.startValid) { dpc.start = val & 0xFFFFF8; } dpc.status.startValid = true; } FORCE_INLINE void WriteEnd(u32 val) { dpc.end = val & 0xFFFFF8; if (dpc.status.startValid) { dpc.current = dpc.start; dpc.status.startValid = false; } RunCommand(); } template void WriteRDRAM(size_t, T); template T ReadRDRAM(size_t); private: friend struct Mem; friend struct MMIO; std::vector rdram{}; public: DPC dpc{}; std::array cmd_buf{}; }; } // namespace n64