Couple RDP fixes and some other stuff i forgor 💀

This commit is contained in:
CocoSimone
2022-10-16 21:37:48 +02:00
parent fc6642554c
commit 932275ab32
12 changed files with 131 additions and 102 deletions

View File

@@ -138,6 +138,7 @@ void Window::InitImgui(const n64::Core& core) {
memoryEditor.ReadFn = readHandler; memoryEditor.ReadFn = readHandler;
memoryEditor.WriteFn = writeHandler; memoryEditor.WriteFn = writeHandler;
memoryEditor.Cols = 32;
} }
Window::~Window() { Window::~Window() {
@@ -194,8 +195,13 @@ void Window::Render(n64::Core& core) {
windowTitle = shadowWindowTitle; windowTitle = shadowWindowTitle;
} }
static bool showSettings = false; static bool showSettings = false;
static bool showMemEditor = false;
bool showMainMenuBar = windowID == SDL_GetWindowID(SDL_GetMouseFocus()); bool showMainMenuBar = windowID == SDL_GetWindowID(SDL_GetMouseFocus());
memoryEditor.DrawWindow("Memory viewer", &core, 0x80000000); if(showMemEditor) {
ImGui::PushFont(codeFont);
memoryEditor.DrawWindow("Memory viewer", &core, 0x80000000);
ImGui::PopFont();
}
if(showMainMenuBar) { if(showMainMenuBar) {
ImGui::BeginMainMenuBar(); ImGui::BeginMainMenuBar();
if (ImGui::BeginMenu("File")) { if (ImGui::BeginMenu("File")) {
@@ -214,6 +220,9 @@ void Window::Render(n64::Core& core) {
if (ImGui::MenuItem("Dump IMEM")) { if (ImGui::MenuItem("Dump IMEM")) {
core.mem.DumpIMEM(); core.mem.DumpIMEM();
} }
if (ImGui::MenuItem("Dump DMEM")) {
core.mem.DumpDMEM();
}
if (ImGui::MenuItem("Exit")) { if (ImGui::MenuItem("Exit")) {
core.done = true; core.done = true;
} }
@@ -241,6 +250,7 @@ void Window::Render(n64::Core& core) {
if (ImGui::MenuItem("Settings")) { if (ImGui::MenuItem("Settings")) {
showSettings = true; showSettings = true;
} }
ImGui::Checkbox("Show memory editor", &showMemEditor);
ImGui::EndMenu(); ImGui::EndMenu();
} }
ImGui::EndMainMenuBar(); ImGui::EndMainMenuBar();

View File

@@ -28,9 +28,7 @@ inline void CheckCompareInterrupt(MI& mi, Registers& regs) {
} }
inline void HandleInterrupt(Registers& regs) { inline void HandleInterrupt(Registers& regs) {
if(ShouldServiceInterrupt(regs)) {
FireException(regs, ExceptionCode::Interrupt, 0, regs.pc);
}
} }
inline void Cpu::disassembly(u32 instr) { inline void Cpu::disassembly(u32 instr) {
@@ -57,19 +55,21 @@ void Cpu::Step(Mem& mem) {
regs.gpr[0] = 0; regs.gpr[0] = 0;
CheckCompareInterrupt(mem.mmio.mi, regs); CheckCompareInterrupt(mem.mmio.mi, regs);
HandleInterrupt(regs);
regs.prevDelaySlot = regs.delaySlot;
regs.delaySlot = false;
u32 instruction = mem.Read32(regs, regs.pc, regs.pc); u32 instruction = mem.Read32(regs, regs.pc, regs.pc);
//disassembly(instruction); if(ShouldServiceInterrupt(regs)) {
FireException(regs, ExceptionCode::Interrupt, 0, regs.pc);
return;
}
regs.oldPC = regs.pc; regs.oldPC = regs.pc;
regs.pc = regs.nextPC; regs.pc = regs.nextPC;
regs.nextPC += 4; regs.nextPC += 4;
Exec(mem, instruction); Exec(mem, instruction);
regs.prevDelaySlot = regs.delaySlot;
regs.delaySlot = false;
} }
} }

View File

@@ -80,7 +80,7 @@ u8 Mem::Read8(n64::Registers &regs, u64 vaddr, s64 pc) {
switch(paddr) { switch(paddr) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
return mmio.rdp.dram[BYTE_ADDRESS(paddr) & RDRAM_DSIZE]; return mmio.rdp.dram[BYTE_ADDRESS(paddr)];
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if((paddr >> 12) & 1) if((paddr >> 12) & 1)
return mmio.rsp.imem[BYTE_ADDRESS(paddr) & IMEM_DSIZE]; return mmio.rsp.imem[BYTE_ADDRESS(paddr) & IMEM_DSIZE];
@@ -116,7 +116,7 @@ u16 Mem::Read16(n64::Registers &regs, u64 vaddr, s64 pc) {
switch(paddr) { switch(paddr) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
return util::ReadAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr) & RDRAM_DSIZE); return util::ReadAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr));
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if((paddr >> 12) & 1) if((paddr >> 12) & 1)
return util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE); return util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE);
@@ -148,7 +148,7 @@ u32 Mem::Read32(n64::Registers &regs, u64 vaddr, s64 pc) {
switch(paddr) { switch(paddr) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
return util::ReadAccess<u32>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE); return util::ReadAccess<u32>(mmio.rdp.dram.data(), paddr);
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if((paddr >> 12) & 1) if((paddr >> 12) & 1)
return util::ReadAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE); return util::ReadAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE);
@@ -180,7 +180,7 @@ u64 Mem::Read64(n64::Registers &regs, u64 vaddr, s64 pc) {
switch(paddr) { switch(paddr) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
return util::ReadAccess<u64>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE); return util::ReadAccess<u64>(mmio.rdp.dram.data(), paddr);
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if((paddr >> 12) & 1) if((paddr >> 12) & 1)
return util::ReadAccess<u64>(mmio.rsp.imem, paddr & IMEM_DSIZE); return util::ReadAccess<u64>(mmio.rsp.imem, paddr & IMEM_DSIZE);
@@ -222,7 +222,7 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) {
switch(paddr) { switch(paddr) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
mmio.rdp.dram[BYTE_ADDRESS(paddr) & RDRAM_DSIZE] = val; mmio.rdp.dram[BYTE_ADDRESS(paddr)] = val;
break; break;
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
val = val << (8 * (3 - (paddr & 3))); val = val << (8 * (3 - (paddr & 3)));
@@ -261,7 +261,7 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) {
switch(paddr) { switch(paddr) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
util::WriteAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr) & RDRAM_DSIZE, val); util::WriteAccess<u16>(mmio.rdp.dram.data(), HALF_ADDRESS(paddr), val);
break; break;
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
val = val << (16 * !(paddr & 2)); val = val << (16 * !(paddr & 2));
@@ -297,7 +297,7 @@ void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) {
switch(paddr) { switch(paddr) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
util::WriteAccess<u32>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE, val); util::WriteAccess<u32>(mmio.rdp.dram.data(), paddr, val);
break; break;
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
if((paddr >> 12) & 1) if((paddr >> 12) & 1)
@@ -340,7 +340,7 @@ void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) {
switch(paddr) { switch(paddr) {
case 0x00000000 ... 0x007FFFFF: case 0x00000000 ... 0x007FFFFF:
util::WriteAccess<u64>(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE, val); util::WriteAccess<u64>(mmio.rdp.dram.data(), paddr, val);
break; break;
case 0x04000000 ... 0x0403FFFF: case 0x04000000 ... 0x0403FFFF:
val >>= 32; val >>= 32;

View File

@@ -62,6 +62,16 @@ struct Mem {
free(temp); free(temp);
fclose(fp); fclose(fp);
} }
inline void DumpDMEM() const {
FILE *fp = fopen("dmem.dump", "wb");
u8 *temp = (u8*)calloc(DMEM_SIZE, 1);
memcpy(temp, mmio.rsp.dmem, DMEM_SIZE);
util::SwapBuffer32(DMEM_SIZE, temp);
fwrite(temp, 1, DMEM_SIZE, fp);
free(temp);
fclose(fp);
}
private: private:
friend struct SI; friend struct SI;
friend struct PI; friend struct PI;

View File

@@ -24,12 +24,13 @@ static const int cmd_lens[64] = {
}; };
template <bool crashOnUnimplemented> template <bool crashOnUnimplemented>
auto RDP::Read(u32 addr) const -> u32{ auto RDP::Read(u32 addr) const -> u32 {
switch(addr) { switch(addr) {
case 0x04100000: return dpc.start; case 0x04100000: return dpc.start;
case 0x04100004: return dpc.end; case 0x04100004: return dpc.end;
case 0x04100008: return dpc.current; case 0x04100008: return dpc.current;
case 0x0410000C: return dpc.status.raw; case 0x0410000C:
return dpc.status.raw;
case 0x04100010: return dpc.clock; case 0x04100010: return dpc.clock;
case 0x04100014: return dpc.status.cmdBusy; case 0x04100014: return dpc.status.cmdBusy;
case 0x04100018: return dpc.status.pipeBusy; case 0x04100018: return dpc.status.pipeBusy;
@@ -62,15 +63,12 @@ template void RDP::Write<true>(MI&, Registers&, RSP&, u32, u32);
template void RDP::Write<false>(MI&, Registers&, RSP&, u32, u32); template void RDP::Write<false>(MI&, Registers&, RSP&, u32, u32);
void RDP::WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val) { void RDP::WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val) {
bool rdpUnfrozen = false;
DPCStatusWrite temp{}; DPCStatusWrite temp{};
temp.raw = val; temp.raw = val;
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;
rdpUnfrozen = true;
} }
if(temp.setFreeze) { if(temp.setFreeze) {
@@ -82,7 +80,7 @@ void RDP::WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val) {
CLEAR_SET(dpc.status.pipeBusy, temp.clearPipe, false); CLEAR_SET(dpc.status.pipeBusy, temp.clearPipe, false);
CLEAR_SET(dpc.status.tmemBusy, temp.clearTmem, false); CLEAR_SET(dpc.status.tmemBusy, temp.clearTmem, false);
if(rdpUnfrozen) { if(!dpc.status.freeze) {
RunCommand(mi, regs, rsp); RunCommand(mi, regs, rsp);
} }
} }
@@ -128,85 +126,89 @@ inline void logCommand(u8 cmd) {
} }
void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) { void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) {
//if (dpc.status.freeze) { if (dpc.status.freeze) {
// return;
//}
dpc.status.pipeBusy = true;
dpc.status.startGclk = true;
dpc.status.freeze = true;
static int remaining_cmds = 0;
const u32 current = dpc.current & 0xFFFFF8;
const u32 end = dpc.end & 0xFFFFF8;
int len = end - current;
if(len <= 0) return;
if(len + (remaining_cmds * 4) > 0xFFFFF) {
return; return;
} }
dpc.status.pipeBusy = true;
dpc.status.startGclk = true;
if(dpc.end > dpc.current) {
dpc.status.freeze = true;
if(dpc.status.xbusDmemDma) { static int remaining_cmds = 0;
for(int i = 0; i < len; i += 4) {
u32 cmd = util::ReadAccess<u32>(rsp.dmem, (current + i) & 0xFFF); const u32 current = dpc.current & 0xFFFFF8;
cmd_buf[remaining_cmds + (i >> 2)] = cmd; const u32 end = dpc.end & 0xFFFFF8;
}
} else { int len = end - current;
if(end > RDRAM_DSIZE || current > RDRAM_DSIZE) { if (len <= 0) return;
if (len + (remaining_cmds * 4) > 0xFFFFF) {
util::panic("Too many RDP commands\n");
return; return;
} }
for(int i = 0; i < len; i += 4) {
u32 cmd = util::ReadAccess<u32>(dram.data(), current + i); if (dpc.status.xbusDmemDma) {
cmd_buf[remaining_cmds + (i >> 2)] = cmd; for (int i = 0; i < len; i += 4) {
u32 cmd = util::ReadAccess<u32>(rsp.dmem, (current + i) & 0xFFF);
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
}
} else {
if (end > 0x7FFFFFF || current > 0x7FFFFFF) {
util::panic("Not running RDP commands past end of RDRAM\n");
return;
}
for (int i = 0; i < len; i += 4) {
u32 cmd = util::ReadAccess<u32>(dram.data(), current + i);
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
}
} }
}
int word_len = (len >> 2) + remaining_cmds; int word_len = (len >> 2) + remaining_cmds;
int buf_index = 0; int buf_index = 0;
bool processed_all = true; bool processed_all = true;
while(buf_index < word_len) { while (buf_index < word_len) {
u8 cmd = (cmd_buf[buf_index] >> 24) & 0x3F; u8 cmd = (cmd_buf[buf_index] >> 24) & 0x3F;
// logCommand(cmd); logCommand(cmd);
int cmd_len = cmd_lens[cmd]; 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];
for(int i = 0; i < remaining_cmds; i++) { for (int i = 0; i < remaining_cmds; i++) {
tmp[i] = cmd_buf[buf_index + i]; tmp[i] = cmd_buf[buf_index + i];
}
for (int i = 0; i < remaining_cmds; i++) {
cmd_buf[i] = tmp[i];
}
processed_all = false;
break;
} }
for(int i = 0; i < remaining_cmds; i++) { if (cmd >= 8) {
cmd_buf[buf_index + i] = tmp[i]; ParallelRdpEnqueueCommand(cmd_len, &cmd_buf[buf_index]);
} }
processed_all = false; if (cmd == 0x29) {
break; OnFullSync(mi, regs);
}
buf_index += cmd_len;
} }
if(cmd >= 8) { if (processed_all) {
ParallelRdpEnqueueCommand(cmd_len, &cmd_buf[buf_index]); remaining_cmds = 0;
} }
if (cmd == 0x29) { dpc.current = end;
OnFullSync(mi, regs); dpc.end = end;
} dpc.status.freeze = false;
buf_index += cmd_len;
} }
if(processed_all) {
remaining_cmds = 0;
}
dpc.current = end;
dpc.end = end;
dpc.status.cbufReady = true; dpc.status.cbufReady = true;
dpc.status.freeze = false;
} }
void RDP::OnFullSync(MI& mi, Registers& regs) { void RDP::OnFullSync(MI& mi, Registers& regs) {

View File

@@ -56,11 +56,9 @@ inline void logRSP(const RSP& rsp, const u32 instr) {
for (int e = 0; e < 8; e++) { for (int e = 0; e < 8; e++) {
util::print("{:04X}", rsp.acc.l.element[e]); util::print("{:04X}", rsp.acc.l.element[e]);
} }
util::print(" ");
util::print("{:04X} {:04X} {:02X}", rsp.GetVCC(), rsp.GetVCO(), rsp.GetVCE()); util::print(" {:04X} {:04X} {:02X}\n", rsp.GetVCC(), rsp.GetVCO(), rsp.GetVCE());
util::print("DMEM: {:02X}{:02X}\n", rsp.dmem[0x3c4], rsp.dmem[0x3c5]);
util::print("\n");
} }
void RSP::Step(Registers& regs, Mem& mem) { void RSP::Step(Registers& regs, Mem& mem) {
@@ -69,12 +67,10 @@ void RSP::Step(Registers& regs, Mem& mem) {
oldPC = pc & 0xFFC; oldPC = pc & 0xFFC;
pc = nextPC & 0xFFC; pc = nextPC & 0xFFC;
nextPC += 4; nextPC += 4;
if(oldPC == 0x00E4 && gpr[1] == 0x18) {
printf("\n");
}
Exec(regs, mem, instr); Exec(regs, mem, instr);
// logRSP(*this, instr); //logRSP(*this, instr);
} }
template <bool crashOnUnimplemented> template <bool crashOnUnimplemented>
@@ -87,7 +83,11 @@ auto RSP::Read(u32 addr) -> u32{
case 0x04040010: return spStatus.raw; case 0x04040010: return spStatus.raw;
case 0x04040014: return spStatus.dmaFull; case 0x04040014: return spStatus.dmaFull;
case 0x04040018: return 0; case 0x04040018: return 0;
case 0x0404001C: return AcquireSemaphore(); case 0x0404001C:
if constexpr (crashOnUnimplemented) {
return semaphore;
}
return AcquireSemaphore();
case 0x04080000: return pc & 0xFFC; case 0x04080000: return pc & 0xFFC;
default: default:
if constexpr (crashOnUnimplemented) { if constexpr (crashOnUnimplemented) {

View File

@@ -390,13 +390,15 @@ struct RSP {
int skip = i == len.count ? 0 : len.skip; int skip = i == len.count ? 0 : len.skip;
dram_address += (length + skip) & 0xFFFFF8; dram_address += (length + skip);
dram_address &= 0xFFFFF8;
mem_address += length; mem_address += length;
mem_address &= 0xFF8;
} }
rsp.lastSuccessfulSPAddr.address = mem_address & 0xFF8; rsp.lastSuccessfulSPAddr.address = mem_address;
rsp.lastSuccessfulSPAddr.bank = bank; rsp.lastSuccessfulSPAddr.bank = bank;
rsp.lastSuccessfulDRAMAddr.address = dram_address & 0xFFFFF8; rsp.lastSuccessfulDRAMAddr.address = dram_address;
rsp.spDMALen.raw = 0xFF8 | (rsp.spDMALen.skip << 20); rsp.spDMALen.raw = 0xFF8 | (rsp.spDMALen.skip << 20);
} }
private: private:

View File

@@ -15,6 +15,7 @@ void Registers::Reset() {
} }
void Registers::SetPC(s64 val) { void Registers::SetPC(s64 val) {
oldPC = pc;
pc = val; pc = val;
nextPC = pc + 4; nextPC = pc + 4;
} }

View File

@@ -173,17 +173,19 @@ u64 getVPN(u64 addr, u64 pageMask) {
TLBEntry* TLBTryMatch(Registers& regs, u64 vaddr, int* match) { TLBEntry* TLBTryMatch(Registers& regs, u64 vaddr, int* match) {
for(int i = 0; i < 32; i++) { for(int i = 0; i < 32; i++) {
TLBEntry *entry = &regs.cop0.tlb[i]; TLBEntry *entry = &regs.cop0.tlb[i];
u64 entry_vpn = getVPN(entry->entryHi.raw, entry->pageMask.raw); if(entry->initialized) {
u64 vaddr_vpn = getVPN(vaddr, entry->pageMask.raw); u64 entry_vpn = getVPN(entry->entryHi.raw, entry->pageMask.raw);
u64 vaddr_vpn = getVPN(vaddr, entry->pageMask.raw);
bool vpn_match = entry_vpn == vaddr_vpn; bool vpn_match = entry_vpn == vaddr_vpn;
bool asid_match = entry->global || (regs.cop0.entryHi.asid == entry->entryHi.asid); bool asid_match = entry->global || (regs.cop0.entryHi.asid == entry->entryHi.asid);
if(vpn_match && asid_match) { if (vpn_match && asid_match) {
if(match) { if (match) {
*match = i; *match = i;
}
return entry;
} }
return entry;
} }
} }

View File

@@ -132,6 +132,7 @@ union PageMask {
}; };
struct TLBEntry { struct TLBEntry {
bool initialized;
union { union {
u32 raw; u32 raw;
struct { struct {

View File

@@ -67,6 +67,7 @@ void Cop0::tlbwi(Registers& regs) {
tlb[Index].pageMask.raw = page_mask.raw; tlb[Index].pageMask.raw = page_mask.raw;
tlb[Index].global = entryLo0.g && entryLo1.g; tlb[Index].global = entryLo0.g && entryLo1.g;
tlb[Index].initialized = true;
} }
void Cop0::tlbp(Registers& regs) { void Cop0::tlbp(Registers& regs) {

View File

@@ -253,7 +253,7 @@ inline auto ReadFileBinary(const std::string& path, u32** buf) {
std::ifstream file(path, std::ios::binary); std::ifstream file(path, std::ios::binary);
file.unsetf(std::ios::skipws); file.unsetf(std::ios::skipws);
if(!file.is_open()) { if(!file.is_open()) {
panic("Could not load file!\n"); panic("Could not load file '{}'!\n", path);
} }
file.seekg(0, std::ios::end); file.seekg(0, std::ios::end);