From 73d65c22462b2f0264992ed62f111c0fa513c164 Mon Sep 17 00:00:00 2001 From: CocoSimone Date: Thu, 6 Oct 2022 02:17:36 +0200 Subject: [PATCH] SSV and SLV switched, fix shift in SBV, implement "Dump RDRAM" and "Dump IMEM" buttons in GUI --- src/frontend/App.cpp | 9 +--- src/frontend/imgui/Window.cpp | 14 ++++++ src/n64/core/Mem.cpp | 16 +++---- src/n64/core/RSP.hpp | 19 +++++++- src/n64/core/rsp/decode.cpp | 17 ++++--- src/n64/core/rsp/instructions.cpp | 75 ++++++++++++++++++++----------- 6 files changed, 101 insertions(+), 49 deletions(-) diff --git a/src/frontend/App.cpp b/src/frontend/App.cpp index 0d6e0d88..31f8f240 100644 --- a/src/frontend/App.cpp +++ b/src/frontend/App.cpp @@ -13,14 +13,9 @@ void App::Run() { while (SDL_PollEvent(&event)) { ImGui_ImplSDL2_ProcessEvent(&event); switch(event.type) { - case SDL_QUIT: { + case SDL_QUIT: core.done = true; - FILE *fp = fopen("rdram.dump", "wb"); - u8 *temp = core.mem.GetRDRAM(); - util::SwapBuffer32(RDRAM_SIZE, temp); - fwrite(temp, 1, RDRAM_SIZE, fp); - fclose(fp); - } break; + break; case SDL_WINDOWEVENT: core.done = window.gotClosed(event); break; diff --git a/src/frontend/imgui/Window.cpp b/src/frontend/imgui/Window.cpp index 04759690..f5c58cba 100644 --- a/src/frontend/imgui/Window.cpp +++ b/src/frontend/imgui/Window.cpp @@ -182,6 +182,20 @@ void Window::Render(n64::Core& core) { NFD_FreePath(outpath); } } + if (ImGui::MenuItem("Dump RDRAM")) { + FILE *fp = fopen("rdram.dump", "wb"); + u8 *temp = core.mem.GetRDRAM(); + util::SwapBuffer32(RDRAM_SIZE, temp); + fwrite(temp, 1, RDRAM_SIZE, fp); + fclose(fp); + } + if (ImGui::MenuItem("Dump IMEM")) { + FILE *fp = fopen("imem.dump", "wb"); + u8 *temp = core.mem.mmio.rsp.imem; + util::SwapBuffer32(IMEM_SIZE, temp); + fwrite(temp, 1, IMEM_SIZE, fp); + fclose(fp); + } if (ImGui::MenuItem("Exit")) { core.done = true; } diff --git a/src/n64/core/Mem.cpp b/src/n64/core/Mem.cpp index 7e62fec6..b9258b8c 100644 --- a/src/n64/core/Mem.cpp +++ b/src/n64/core/Mem.cpp @@ -80,7 +80,7 @@ u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) { case 0x00000000 ... 0x007FFFFF: return mmio.rdp.dram[BYTE_ADDRESS(paddr) & RDRAM_DSIZE]; case 0x04000000 ... 0x0403FFFF: - if(paddr & 0x1000) + if((paddr >> 12) & 1) return mmio.rsp.imem[BYTE_ADDRESS(paddr) & IMEM_DSIZE]; else return mmio.rsp.dmem[BYTE_ADDRESS(paddr) & DMEM_DSIZE]; @@ -113,7 +113,7 @@ u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) { case 0x00000000 ... 0x007FFFFF: return util::ReadAccess(mmio.rdp.dram.data(), HALF_ADDRESS(paddr) & RDRAM_DSIZE); case 0x04000000 ... 0x0403FFFF: - if(paddr & 0x1000) + if((paddr >> 12) & 1) return util::ReadAccess(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE); else return util::ReadAccess(mmio.rsp.dmem, HALF_ADDRESS(paddr) & DMEM_DSIZE); @@ -146,7 +146,7 @@ u32 Mem::Read32(n64::Registers ®s, u64 vaddr, s64 pc) { case 0x00000000 ... 0x007FFFFF: return util::ReadAccess(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE); case 0x04000000 ... 0x0403FFFF: - if(paddr & 0x1000) + if((paddr >> 12) & 1) return util::ReadAccess(mmio.rsp.imem, paddr & IMEM_DSIZE); else return util::ReadAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE); @@ -178,7 +178,7 @@ u64 Mem::Read64(n64::Registers ®s, u64 vaddr, s64 pc) { case 0x00000000 ... 0x007FFFFF: return util::ReadAccess(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE); case 0x04000000 ... 0x0403FFFF: - if(paddr & 0x1000) + if((paddr >> 12) & 1) return util::ReadAccess(mmio.rsp.imem, paddr & IMEM_DSIZE); else return util::ReadAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE); @@ -222,7 +222,7 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) { case 0x04000000 ... 0x0403FFFF: val = val << (8 * (3 - (paddr & 3))); paddr = (paddr & DMEM_DSIZE) & ~3; - if(paddr & 0x1000) + if((paddr >> 12) & 1) util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); else util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); @@ -258,7 +258,7 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) { case 0x04000000 ... 0x0403FFFF: val = val << (16 * !(paddr & 2)); paddr &= ~3; - if(paddr & 0x1000) + if((paddr >> 12) & 1) util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); else util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); @@ -292,7 +292,7 @@ void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) { util::WriteAccess(mmio.rdp.dram.data(), paddr & RDRAM_DSIZE, val); break; case 0x04000000 ... 0x0403FFFF: - if(paddr & 0x1000) + if((paddr >> 12) & 1) util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); else util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); @@ -336,7 +336,7 @@ void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) { break; case 0x04000000 ... 0x0403FFFF: val >>= 32; - if(paddr & 0x1000) + if((paddr >> 12) & 1) util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); else util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); diff --git a/src/n64/core/RSP.hpp b/src/n64/core/RSP.hpp index 06e1056f..470f0f94 100644 --- a/src/n64/core/RSP.hpp +++ b/src/n64/core/RSP.hpp @@ -218,6 +218,7 @@ struct RSP { } inline u64 ReadDword(u32 addr, bool i) { + addr &= 0xfff; if (i) { return GET_RSP_DWORD(addr, imem); } else { @@ -226,6 +227,7 @@ struct RSP { } inline void WriteDword(u32 addr, u64 val, bool i) { + addr &= 0xfff; if (i) { SET_RSP_DWORD(addr, imem, val); } else { @@ -234,6 +236,7 @@ struct RSP { } inline u32 ReadWord(u32 addr, bool i) { + addr &= 0xfff; if (i) { return GET_RSP_WORD(addr, imem); } else { @@ -242,6 +245,7 @@ struct RSP { } inline void WriteWord(u32 addr, u32 val, bool i) { + addr &= 0xfff; if (i) { SET_RSP_WORD(addr, imem, val); } else { @@ -250,6 +254,7 @@ struct RSP { } inline u16 ReadHalf(u32 addr, bool i) { + addr &= 0xfff; if (i) { return GET_RSP_HALF(addr, imem); } else { @@ -258,6 +263,7 @@ struct RSP { } inline void WriteHalf(u32 addr, u16 val, bool i) { + addr &= 0xfff; if (i) { SET_RSP_HALF(addr, imem, val); } else { @@ -266,6 +272,7 @@ struct RSP { } inline u8 ReadByte(u32 addr, bool i) { + addr &= 0xfff; if (i) { return RSP_BYTE(addr, imem); } else { @@ -274,6 +281,7 @@ struct RSP { } inline void WriteByte(u32 addr, u8 val, bool i) { + addr &= 0xfff; if (i) { RSP_BYTE(addr, imem) = val; } else { @@ -282,34 +290,42 @@ struct RSP { } inline u64 ReadDword(u32 addr) { + addr &= 0xfff; return GET_RSP_DWORD(addr, dmem); } inline void WriteDword(u32 addr, u64 val) { + addr &= 0xfff; SET_RSP_DWORD(addr, dmem, val); } inline u32 ReadWord(u32 addr) { + addr &= 0xfff; return GET_RSP_WORD(addr, dmem); } inline void WriteWord(u32 addr, u32 val) { + addr &= 0xfff; SET_RSP_WORD(addr, dmem, val); } inline u16 ReadHalf(u32 addr) { + addr &= 0xfff; return GET_RSP_HALF(addr, dmem); } inline void WriteHalf(u32 addr, u16 val) { + addr &= 0xfff; SET_RSP_HALF(addr, dmem, val); } inline u8 ReadByte(u32 addr) { + addr &= 0xfff; return RSP_BYTE(addr, dmem); } inline void WriteByte(u32 addr, u8 val) { + addr &= 0xfff; RSP_BYTE(addr, dmem) = val; } @@ -411,7 +427,8 @@ struct RSP { void vsub(u32 instr); void vsubc(u32 instr); void vxor(u32 instr); - void vxnor(u32 instr); + void vnxor(u32 instr); + void vor(u32 instr); void vnor(u32 instr); void vzero(u32 instr); void mfc0(RDP& rdp, u32 instr); diff --git a/src/n64/core/rsp/decode.cpp b/src/n64/core/rsp/decode.cpp index ba2b977a..b8573d4d 100644 --- a/src/n64/core/rsp/decode.cpp +++ b/src/n64/core/rsp/decode.cpp @@ -77,8 +77,8 @@ inline void swc2(RSP& rsp, u32 instr) { //util::print("swc2 {:02X}\n", mask); switch(mask) { case 0x00: rsp.sbv(instr); break; - case 0x01: rsp.slv(instr); break; - case 0x02: rsp.ssv(instr); break; + case 0x01: rsp.ssv(instr); break; + case 0x02: rsp.slv(instr); break; case 0x03: rsp.sdv(instr); break; case 0x04: rsp.sqv(instr); break; case 0x06: rsp.spv(instr); break; @@ -100,8 +100,10 @@ inline void cop2(RSP& rsp, u32 instr) { case 0x02: rsp.cfc2(instr); break; case 0x04: rsp.mtc2(instr); break; case 0x06: rsp.ctc2(instr); break; - case 0x10: case 0x1C: case 0x1E: - case 0x1F: case 0x14: break; //rsp.vzero(instr); break; + case 0x10: case 0x14: + case 0x1C: case 0x1E: case 0x1F: + util::print("Invalid COP2 SUB {:05b} at PC: {:016X}\n", mask_sub, rsp.oldPC); + break; default: util::panic("Unhandled RSP COP2 sub ({:05b})\n", mask_sub); } break; @@ -130,9 +132,10 @@ inline void cop2(RSP& rsp, u32 instr) { case 0x27: rsp.vmrg(instr); break; case 0x28: rsp.vand(instr); break; case 0x29: rsp.vnand(instr); break; - case 0x2A: rsp.vnor(instr); break; + case 0x2A: rsp.vor(instr); break; + case 0x2B: rsp.vnor(instr); break; case 0x2C: rsp.vxor(instr); break; - case 0x2D: rsp.vxnor(instr); break; + case 0x2D: rsp.vnxor(instr); break; case 0x31: rsp.vrcpl(instr); break; case 0x35: rsp.vrsql(instr); break; case 0x32: case 0x36: @@ -141,6 +144,8 @@ inline void cop2(RSP& rsp, u32 instr) { case 0x30: rsp.vrcp(instr); break; case 0x33: rsp.vmov(instr); break; case 0x34: rsp.vrsq(instr); break; + case 0x37: break; + case 0x3F: break; default: util::panic("Unhandled RSP COP2 ({:06b})\n", mask); } } diff --git a/src/n64/core/rsp/instructions.cpp b/src/n64/core/rsp/instructions.cpp index fb678113..975e8a44 100644 --- a/src/n64/core/rsp/instructions.cpp +++ b/src/n64/core/rsp/instructions.cpp @@ -97,11 +97,23 @@ inline VPR GetVTE(VPR vt, u8 e) { VPR vte{}; switch(e & 0xf) { case 0 ... 1: return vt; - case 2 ... 3: - vte = Broadcast(vt, e - 2, e - 2, e, e, e + 2, e + 2, e + 4, e + 4); + case 2: + vte = Broadcast(vt, 0, 0, 2, 2, 4, 4, 6, 6); break; - case 4 ... 7: - vte = Broadcast(vt, e - 4, e - 4, e - 4, e - 4, e, e, e, e); + case 3: + vte = Broadcast(vt, 1, 1, 3, 3, 5, 5, 7, 7); + break; + case 4: + vte = Broadcast(vt, 0, 0, 0, 0, 4, 4, 4, 4); + break; + case 5: + vte = Broadcast(vt, 1, 1, 1, 1, 5, 5, 5, 5); + break; + case 6: + vte = Broadcast(vt, 2, 2, 2, 2, 6, 6, 6, 6); + break; + case 7: + vte = Broadcast(vt, 3, 3, 3, 3, 7, 7, 7, 7); break; case 8 ... 15: { int index = ELEMENT_INDEX(e - 8); @@ -289,7 +301,7 @@ void RSP::ldv(u32 instr) { } void RSP::lsv(u32 instr) { - int e = E1(instr); + u8 e = E1(instr); u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 1); u16 val = ReadHalf(addr); vpr[VT(instr)].byte[BYTE_INDEX(e)] = val >> 8; @@ -404,7 +416,7 @@ void RSP::spv(u32 instr) { void RSP::sbv(u32 instr) { int e = E1(instr); - u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 3); + u32 addr = gpr[BASE(instr)] + SignExt7bit(OFFSET(instr), 0); WriteByte(addr, vpr[VT(instr)].byte[BYTE_INDEX(e & 0xF)]); } @@ -583,7 +595,7 @@ void RSP::vaddc(u32 instr) { VPR vte = GetVTE(vpr[VT(instr)], E2(instr)); for(int i = 0; i < 8; i++) { - s32 result = vs.selement[i] + vte.selement[i]; + u32 result = vs.element[i] + vte.element[i]; acc.l.element[i] = result; vd.element[i] = result; vco.l.element[i] = (result >> 16) & 1 ? 0xffff : 0; @@ -663,17 +675,15 @@ void RSP::vcl(u32 instr) { VPR vte = GetVTE(vpr[VT(instr)], e); for(int i = 0; i < 8; i++) { - s16 vsElem = vs.selement[i]; - s16 vteElem = vte.selement[i]; + u16 vsElem = vs.element[i]; + u16 vteElem = vte.element[i]; + acc.l.element[i] = vcc.l.element[i] ? -vteElem : vsElem; if(vco.l.element[i]) { - if(vco.h.element[i]) { - acc.l.element[i] = vcc.l.element[i] ? -vteElem : vsElem; - } else { + if(!vco.h.element[i]) { u16 clampSum = vsElem + vteElem; bool overflow = (vsElem + vteElem) != clampSum; - acc.l.element[i] = vcc.l.element[i] ? -vteElem : vsElem; if(vce.element[i]) { vcc.l.element[i] = !clampSum || !overflow ? 0xffff : 0; } else { @@ -681,9 +691,8 @@ void RSP::vcl(u32 instr) { } } } else { - acc.l.element[i] = vcc.l.element[i] ? -vteElem : vsElem; if(!vco.h.element[i]) { - vcc.h.element[i] = s32(vsElem) - s32(vteElem) >= 0 ? 0xffff : 0; + vcc.h.element[i] = (s32(vsElem) - s32(vteElem) >= 0) ? 0xffff : 0; } } @@ -699,7 +708,7 @@ void RSP::vmov(u32 instr) { VPR& vd = vpr[VD(instr)]; VPR vte = GetVTE(vpr[VT(instr)], e); - u32 se; + /*u8 se; switch (e) { case 0 ... 1: @@ -716,11 +725,11 @@ void RSP::vmov(u32 instr) { break; default: util::panic("VMOV: This should be unreachable!\n"); - } + }*/ u8 de = VS(instr) & 7; - vd.element[ELEMENT_INDEX(de)] = vte.element[ELEMENT_INDEX(se)]; + vd.element[ELEMENT_INDEX(de)] = vte.element[ELEMENT_INDEX(de)]; for(int i = 0; i < 8; i++) { acc.l.element[i] = vte.element[i]; } @@ -950,7 +959,7 @@ void RSP::vge(u32 instr) { for(int i = 0; i < 8; i++) { bool eql = vs.element[i] == vte.element[i]; - bool neg = !(vco.h.element[i] & vco.l.element[i]) & eql; + bool neg = !(vco.h.element[i] && vco.l.element[i]) && eql; vcc.l.element[i] = (neg || (vs.element[i] > vte.element[i])) ? 0xffff : 0; acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; vd.element[i] = acc.l.element[i]; @@ -966,8 +975,8 @@ void RSP::vlt(u32 instr) { for(int i = 0; i < 8; i++) { bool eql = vs.element[i] == vte.element[i]; - bool neg = vco.h.element[i] & vco.l.element[i] & eql; - vcc.l.element[i] = (neg || (vs.element[i] < vte.element[i])) ? 0xffff : 0; + bool neg = vco.h.element[i] && vco.l.element[i] && eql; + vcc.l.element[i] = (neg || (vs.selement[i] < vte.selement[i])) ? 0xffff : 0; acc.l.element[i] = vcc.l.element[i] ? vs.element[i] : vte.element[i]; vd.element[i] = acc.l.element[i]; vcc.h.element[i] = vco.h.element[i] = vco.l.element[i] = 0; @@ -1105,11 +1114,11 @@ void RSP::vrsql(u32 instr) { } void RSP::vrcph(u32 instr) { - int e = E2(instr); - int de = DE(instr); + int e = E2(instr) & 7; + int de = DE(instr) & 7; VPR& vd = vpr[VD(instr)]; VPR& vt = vpr[VT(instr)]; - VPR vte = GetVTE(vpr[VT(instr)], e); + VPR vte = GetVTE(vpr[VT(instr)], E2(instr)); for(int i = 0; i < 8; i++) { acc.l.element[i] = vte.element[i]; @@ -1169,9 +1178,9 @@ void RSP::vsub(u32 instr) { VPR vte = GetVTE(vpr[VT(instr)], e); for(int i = 0; i < 8; i++) { - u32 result = vs.element[i] - vte.element[i] - vco.l.element[i]; + s32 result = vs.selement[i] - vte.selement[i] - (vco.l.element[i] != 0); acc.l.element[i] = result; - vd.element[i] = clamp_signed(s32(result) & 0x1FFFF); + vd.element[i] = clamp_signed(result); vco.l.element[i] = 0; vco.h.element[i] = 0; @@ -1202,7 +1211,7 @@ void RSP::vxor(u32 instr) { } } -void RSP::vxnor(u32 instr) { +void RSP::vnxor(u32 instr) { int e = E2(instr); VPR& vs = vpr[VS(instr)]; VPR& vd = vpr[VD(instr)]; @@ -1250,6 +1259,18 @@ void RSP::vnor(u32 instr) { } } +void RSP::vor(u32 instr) { + int e = E2(instr); + VPR& vs = vpr[VS(instr)]; + VPR& vd = vpr[VD(instr)]; + VPR vte = GetVTE(vpr[VT(instr)], e); + + for(int i = 0; i < 8; i++) { + acc.l.element[i] = vte.element[i] | vs.element[i]; + vd.element[i] = acc.l.element[i]; + } +} + void RSP::vzero(u32 instr) { VPR& vs = vpr[VS(instr)]; VPR& vd = vpr[VD(instr)];