Small RDP accuracy improvement

This commit is contained in:
irisz64
2025-07-26 00:26:40 +02:00
parent ef05bcfac6
commit 9dec9c03b4
5 changed files with 40 additions and 23 deletions

View File

@@ -80,7 +80,7 @@ std::vector<u8> MMIO::Serialize() {
index += sizeof(RSP); index += sizeof(RSP);
memcpy(res.data() + index, &rdp.dpc, sizeof(DPC)); memcpy(res.data() + index, &rdp.dpc, sizeof(DPC));
index += sizeof(DPC); index += sizeof(DPC);
memcpy(res.data() + index, rdp.cmd_buf, 0xFFFFF); memcpy(res.data() + index, rdp.cmd_buf.data(), RDP::COMMAND_BUFFER_SIZE);
index += 0xFFFFF; index += 0xFFFFF;
std::ranges::copy(rdp.rdram, res.begin() + index); std::ranges::copy(rdp.rdram, res.begin() + index);
index += RDRAM_SIZE; index += RDRAM_SIZE;
@@ -127,7 +127,7 @@ void MMIO::Deserialize(const std::vector<u8> &data) {
index += sizeof(RSP); index += sizeof(RSP);
memcpy(&rdp.dpc, data.data() + index, sizeof(DPC)); memcpy(&rdp.dpc, data.data() + index, sizeof(DPC));
index += sizeof(DPC); index += sizeof(DPC);
memcpy(rdp.cmd_buf, data.data() + index, 0xFFFFF); memcpy(rdp.cmd_buf.data(), data.data() + index, RDP::COMMAND_BUFFER_SIZE);
index += 0xFFFFF; index += 0xFFFFF;
std::copy_n(data.begin() + index, RDRAM_SIZE, rdp.rdram.begin()); std::copy_n(data.begin() + index, RDRAM_SIZE, rdp.rdram.begin());
index += RDRAM_SIZE; index += RDRAM_SIZE;

View File

@@ -8,7 +8,7 @@ namespace n64 {
RDP::RDP(Mem &mem, ParallelRDP &parallel) : mem(mem), parallel(parallel) { RDP::RDP(Mem &mem, ParallelRDP &parallel) : mem(mem), parallel(parallel) {
rdram.resize(RDRAM_SIZE); rdram.resize(RDRAM_SIZE);
std::ranges::fill(rdram, 0); std::ranges::fill(rdram, 0);
memset(cmd_buf, 0, 0x100000); std::ranges::fill(cmd_buf, 0);
dpc.status.raw = 0x80; dpc.status.raw = 0x80;
} }
@@ -16,7 +16,7 @@ void RDP::Reset() {
dpc = {}; dpc = {};
dpc.status.raw = 0x80; dpc.status.raw = 0x80;
std::ranges::fill(rdram, 0); std::ranges::fill(rdram, 0);
memset(cmd_buf, 0, 0x100000); std::ranges::fill(cmd_buf, 0);
} }
template <> template <>
@@ -124,26 +124,37 @@ void RDP::Write(const u32 addr, const u32 val) {
} }
} }
void RDP::WriteStatus(const u32 val) { void RDP::WriteStatus(const u32 val) {
DPCStatusWrite temp{}; DPCStatusWrite temp{};
temp.raw = val; temp.raw = val;
bool unfrozen = false;
#define CLEAR_SET(val, clear, set) \
do { \
if ((clear)) \
(val) = 0; \
if ((set)) \
(val) = 1; \
} \
while (0)
CLEAR_SET(dpc.status.xbusDmemDma, temp.clearXbusDmemDma, temp.setXbusDmemDma); CLEAR_SET(dpc.status.xbusDmemDma, temp.clearXbusDmemDma, temp.setXbusDmemDma);
if (temp.clearFreeze) { if (temp.clearFreeze) {
dpc.status.freeze = false; dpc.status.freeze = false;
unfrozen = true;
} }
if (temp.setFreeze) { if (temp.setFreeze) {
dpc.status.freeze = true; dpc.status.freeze = true;
} }
CLEAR_SET(dpc.status.flush, temp.clearFlush, temp.setFlush); CLEAR_SET(dpc.status.flush, temp.clearFlush, temp.setFlush);
CLEAR_SET(dpc.status.cmdBusy, temp.clearCmd, false);
if (temp.clearClock)
dpc.clock = 0;
CLEAR_SET(dpc.status.pipeBusy, temp.clearPipe, false);
CLEAR_SET(dpc.status.tmemBusy, temp.clearTmem, false); CLEAR_SET(dpc.status.tmemBusy, temp.clearTmem, false);
CLEAR_SET(dpc.status.pipeBusy, temp.clearPipe, false);
CLEAR_SET(dpc.status.cmdBusy, temp.clearCmd, false);
CLEAR_SET(dpc.clock, temp.clearClock, false);
if (!dpc.status.freeze) { if (!unfrozen) {
RunCommand(); RunCommand();
} }
} }
@@ -207,14 +218,14 @@ void RDP::RunCommand() {
if (len <= 0) if (len <= 0)
return; return;
if (len + remaining_cmds * 4 > 0xFFFFF) { if (len + remaining_cmds * 4 > COMMAND_BUFFER_SIZE) {
panic("Too many RDP commands"); panic("Too many RDP commands");
return; return;
} }
if (dpc.status.xbusDmemDma) { if (dpc.status.xbusDmemDma) {
for (int i = 0; i < len; i += 4) { for (int i = 0; i < len; i += 4) {
const u32 cmd = Util::ReadAccess<u32>(mem.mmio.rsp.dmem, (current + i) & 0xFFF); const 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 {
@@ -234,10 +245,10 @@ void RDP::RunCommand() {
bool processed_all = true; bool processed_all = true;
while (buf_index < word_len) { while (buf_index < word_len) {
const u8 cmd = (cmd_buf[buf_index] >> 24) & 0x3F; const u8 cmd = cmd_buf[buf_index] >> 24 & 0x3F;
const int cmd_len = cmd_lens[cmd]; const int cmd_len = cmd_lens[cmd];
if ((buf_index + cmd_len) * 4 > len + (remaining_cmds * 4)) { if ((buf_index + cmd_len) * 4 > len + remaining_cmds * 4) {
remaining_cmds = word_len - buf_index; remaining_cmds = word_len - buf_index;
u32 tmp[remaining_cmds]; u32 tmp[remaining_cmds];

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <common.hpp> #include <array>
#include <vector> #include <vector>
#include <common.hpp>
class ParallelRDP; class ParallelRDP;
@@ -53,8 +54,10 @@ struct DPC {
}; };
struct RDP { struct RDP {
static constexpr auto COMMAND_BUFFER_SIZE = 0xFFFFF;
DPC dpc{}; DPC dpc{};
u32 cmd_buf[0xFFFFF]{}; std::array<u32, COMMAND_BUFFER_SIZE> cmd_buf{};
RDP(Mem &, ParallelRDP &); RDP(Mem &, ParallelRDP &);
void Reset(); void Reset();

View File

@@ -105,6 +105,16 @@ void RSP::WriteStatus(const u32 value) {
mi.InterruptLower(MI::Interrupt::SP); mi.InterruptLower(MI::Interrupt::SP);
if (write.setIntr && !write.clearIntr) if (write.setIntr && !write.clearIntr)
mi.InterruptRaise(MI::Interrupt::SP); mi.InterruptRaise(MI::Interrupt::SP);
#define CLEAR_SET(val, clear, set) \
do { \
if ((clear) && !(set)) \
(val) = 0; \
if ((set) && !(clear)) \
(val) = 1; \
} \
while (0)
CLEAR_SET(spStatus.singleStep, write.clearSstep, write.setSstep); CLEAR_SET(spStatus.singleStep, write.clearSstep, write.setSstep);
CLEAR_SET(spStatus.interruptOnBreak, write.clearIntrOnBreak, write.setIntrOnBreak); CLEAR_SET(spStatus.interruptOnBreak, write.clearIntrOnBreak, write.setIntrOnBreak);
CLEAR_SET(spStatus.signal0, write.clearSignal0, write.setSignal0); CLEAR_SET(spStatus.signal0, write.clearSignal0, write.setSignal0);
@@ -115,6 +125,7 @@ void RSP::WriteStatus(const u32 value) {
CLEAR_SET(spStatus.signal5, write.clearSignal5, write.setSignal5); CLEAR_SET(spStatus.signal5, write.clearSignal5, write.setSignal5);
CLEAR_SET(spStatus.signal6, write.clearSignal6, write.setSignal6); CLEAR_SET(spStatus.signal6, write.clearSignal6, write.setSignal6);
CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7); CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7);
#undef CLEAR_SET
} }
template <> template <>

View File

@@ -116,14 +116,6 @@ struct Mem;
struct Registers; struct Registers;
#define DE(x) (((x) >> 11) & 0x1F) #define DE(x) (((x) >> 11) & 0x1F)
#define CLEAR_SET(val, clear, set) \
do { \
if ((clear) && !(set)) \
(val) = 0; \
if ((set) && !(clear)) \
(val) = 1; \
} \
while (0)
struct RSP { struct RSP {
RSP(Mem &, Registers &); RSP(Mem &, Registers &);