diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c33c147..f5911f01 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,8 +53,6 @@ target_include_directories(gadolinium PRIVATE ${SDL2_INCLUDE_DIR} ) -set_target_properties(gadolinium PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) - file(COPY ${PROJECT_SOURCE_DIR}/../resources/ DESTINATION ${PROJECT_BINARY_DIR}/resources/) file(REMOVE ${PROJECT_BINARY_DIR}/resources/mario.png @@ -66,4 +64,21 @@ if(WIN32) add_compile_options(/EHa) endif() +if(${CMAKE_BUILD_TYPE} MATCHES Release) + set_property(TARGET gadolinium PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + if(WIN32) + add_compile_options(/O2) + else() + add_compile_options(-O3) + endif() +else() + if(WIN32) + add_compile_options(/Od) + else() + add_compile_options(-fsanitize=address) + add_link_options(-fsanitize=address) + add_compile_options(-g) + endif() +endif() + target_link_libraries(gadolinium PRIVATE discord-rpc SDL2::SDL2main SDL2::SDL2 capstone-static nfd parallel-rdp fmt::fmt imgui nlohmann_json::nlohmann_json) \ No newline at end of file diff --git a/src/frontend/imgui/Window.hpp b/src/frontend/imgui/Window.hpp index 3d2c2074..33807e98 100644 --- a/src/frontend/imgui/Window.hpp +++ b/src/frontend/imgui/Window.hpp @@ -15,7 +15,7 @@ struct Window { [[nodiscard]] bool gotClosed(SDL_Event event); ImFont *uiFont{}, *codeFont{}; u32 windowID{}; - float volumeL = 0.01, volumeR = 0.01; + float volumeL = 0.0, volumeR = 0.0; void LoadROM(n64::Core& core, const std::string& path); private: bool lockVolume = true; diff --git a/src/n64/core/Mem.cpp b/src/n64/core/Mem.cpp index ea9959e6..873f285b 100644 --- a/src/n64/core/Mem.cpp +++ b/src/n64/core/Mem.cpp @@ -16,21 +16,16 @@ void Mem::Reset() { std::fill(writePages.begin(), writePages.end(), 0); for(int i = 0; i < 2048; i++) { - const auto pointer = (uintptr_t) &mmio.rdp.dram[(i * PAGE_SIZE) & RDRAM_DSIZE]; - readPages[i + 0x80000] = pointer; - readPages[i + 0xA0000] = pointer; - writePages[i + 0x80000] = pointer; - writePages[i + 0xA0000] = pointer; + const auto addr = (i * PAGE_SIZE) & RDRAM_DSIZE; + const auto pointer = (uintptr_t) &mmio.rdp.rdram[addr]; + readPages[i] = pointer; + writePages[i] = pointer; } - readPages[0x84000] = (uintptr_t) &mmio.rsp.dmem[0]; - readPages[0xA4000] = (uintptr_t) &mmio.rsp.dmem[0]; - readPages[0x84001] = (uintptr_t) &mmio.rsp.imem[0]; - readPages[0xA4001] = (uintptr_t) &mmio.rsp.imem[0]; - writePages[0x84000] = (uintptr_t) &mmio.rsp.dmem[0]; - writePages[0xA4000] = (uintptr_t) &mmio.rsp.dmem[0]; - writePages[0x84001] = (uintptr_t) &mmio.rsp.imem[0]; - writePages[0xA4001] = (uintptr_t) &mmio.rsp.imem[0]; + readPages[0x4000] = (uintptr_t) &mmio.rsp.dmem[0]; + readPages[0x4001] = (uintptr_t) &mmio.rsp.imem[0]; + writePages[0x4000] = (uintptr_t) &mmio.rsp.dmem[0]; + writePages[0x4001] = (uintptr_t) &mmio.rsp.imem[0]; sram.resize(SRAM_SIZE); std::fill(sram.begin(), sram.end(), 0); @@ -94,22 +89,22 @@ template bool MapVAddr(Registers& regs, TLBAccessType accessType, u64 vad template u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) { - const auto page = (vaddr & 0xFFFFFFFF) >> 12; - const auto offset = vaddr & 0xFFF; + u32 paddr = vaddr; + if (!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); + } + + const auto page = paddr >> 12; + const auto offset = paddr & 0xFFF; const auto pointer = readPages[page]; if(pointer) { return ((u8*)pointer)[BYTE_ADDRESS(offset)]; } else { - u32 paddr = vaddr; - if (!MapVAddr(regs, LOAD, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); - } - switch (paddr) { case 0x00000000 ... 0x007FFFFF: - return mmio.rdp.dram[BYTE_ADDRESS(paddr)]; + return mmio.rdp.rdram[BYTE_ADDRESS(paddr)]; case 0x04000000 ... 0x0403FFFF: if ((paddr >> 12) & 1) return mmio.rsp.imem[BYTE_ADDRESS(paddr) & IMEM_DSIZE]; @@ -145,22 +140,22 @@ u8 Mem::Read8(n64::Registers ®s, u64 vaddr, s64 pc) { template u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) { - const auto page = (vaddr & 0xFFFFFFFF) >> 12; - const auto offset = vaddr & 0xFFF; + u32 paddr = vaddr; + if (!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); + } + + const auto page = paddr >> 12; + const auto offset = paddr & 0xFFF; const auto pointer = readPages[page]; if(pointer) { return util::ReadAccess((u8*)pointer, HALF_ADDRESS(offset)); } else { - u32 paddr = vaddr; - if (!MapVAddr(regs, LOAD, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); - } - switch (paddr) { case 0x00000000 ... 0x007FFFFF: - return util::ReadAccess(mmio.rdp.dram.data(), HALF_ADDRESS(paddr)); + return util::ReadAccess(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr)); case 0x04000000 ... 0x0403FFFF: if ((paddr >> 12) & 1) return util::ReadAccess(mmio.rsp.imem, HALF_ADDRESS(paddr) & IMEM_DSIZE); @@ -191,22 +186,22 @@ u16 Mem::Read16(n64::Registers ®s, u64 vaddr, s64 pc) { template u32 Mem::Read32(n64::Registers ®s, u64 vaddr, s64 pc) { - const auto page = (vaddr & 0xFFFFFFFF) >> 12; - const auto offset = vaddr & 0xFFF; + u32 paddr = vaddr; + if (!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); + } + + const auto page = paddr >> 12; + const auto offset = paddr & 0xFFF; const auto pointer = readPages[page]; if(pointer) { return util::ReadAccess((u8*)pointer, offset); } else { - u32 paddr = vaddr; - if(!MapVAddr(regs, LOAD, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); - } - switch(paddr) { case 0x00000000 ... 0x007FFFFF: - return util::ReadAccess(mmio.rdp.dram.data(), paddr); + return util::ReadAccess(mmio.rdp.rdram.data(), paddr); case 0x04000000 ... 0x0403FFFF: if((paddr >> 12) & 1) return util::ReadAccess(mmio.rsp.imem, paddr & IMEM_DSIZE); @@ -231,22 +226,22 @@ u32 Mem::Read32(n64::Registers ®s, u64 vaddr, s64 pc) { template u64 Mem::Read64(n64::Registers ®s, u64 vaddr, s64 pc) { - const auto page = (vaddr & 0xFFFFFFFF) >> 12; - const auto offset = vaddr & 0xFFF; + u32 paddr = vaddr; + if (!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); + } + + const auto page = paddr >> 12; + const auto offset = paddr & 0xFFF; const auto pointer = readPages[page]; if(pointer) { return util::ReadAccess((u8*)pointer, offset); } else { - u32 paddr = vaddr; - if (!MapVAddr(regs, LOAD, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); - } - switch (paddr) { case 0x00000000 ... 0x007FFFFF: - return util::ReadAccess(mmio.rdp.dram.data(), paddr); + return util::ReadAccess(mmio.rdp.rdram.data(), paddr); case 0x04000000 ... 0x0403FFFF: if ((paddr >> 12) & 1) return util::ReadAccess(mmio.rsp.imem, paddr & IMEM_DSIZE); @@ -285,22 +280,27 @@ template u64 Mem::Read64(n64::Registers ®s, u64 vaddr, s64 pc); template void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) { - const auto page = (vaddr & 0xFFFFFFFF) >> 12; - const auto offset = vaddr & 0xFFF; - const auto pointer = writePages[page]; + u32 paddr = vaddr; + if (!MapVAddr(regs, LOAD, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, pc); + } + + const auto page = paddr >> 12; + auto offset = paddr & 0xFFF; + const auto pointer = readPages[page]; if(pointer) { - ((u8*)pointer)[BYTE_ADDRESS(offset)] = val; - } else { - u32 paddr = vaddr; - if (!MapVAddr(regs, STORE, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); + if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) { + val = val << (8 * (3 - (paddr & 3))); + offset = (offset & DMEM_DSIZE) & ~3; } + ((u8*)pointer)[BYTE_ADDRESS(offset)] = val; + } else { switch (paddr) { case 0x00000000 ... 0x007FFFFF: - mmio.rdp.dram[BYTE_ADDRESS(paddr)] = val; + mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val; break; case 0x04000000 ... 0x0403FFFF: val = val << (8 * (3 - (paddr & 3))); @@ -339,22 +339,27 @@ void Mem::Write8(Registers& regs, u64 vaddr, u32 val, s64 pc) { template void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) { - const auto page = (vaddr & 0xFFFFFFFF) >> 12; - const auto offset = vaddr & 0xFFF; - const auto pointer = writePages[page]; + u32 paddr = vaddr; + if (!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); + } + + const auto page = paddr >> 12; + auto offset = paddr & 0xFFF; + const auto pointer = readPages[page]; if(pointer) { - util::WriteAccess((u8*)pointer, HALF_ADDRESS(offset), val); - } else { - u32 paddr = vaddr; - if (!MapVAddr(regs, STORE, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); + if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) { + val = val << (16 * !(paddr & 2)); + offset &= ~3; } + util::WriteAccess((u8*)pointer, HALF_ADDRESS(offset), val); + } else { switch (paddr) { case 0x00000000 ... 0x007FFFFF: - util::WriteAccess(mmio.rdp.dram.data(), HALF_ADDRESS(paddr), val); + util::WriteAccess(mmio.rdp.rdram.data(), HALF_ADDRESS(paddr), val); break; case 0x04000000 ... 0x0403FFFF: val = val << (16 * !(paddr & 2)); @@ -393,22 +398,22 @@ void Mem::Write16(Registers& regs, u64 vaddr, u32 val, s64 pc) { template void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) { - const auto page = (vaddr & 0xFFFFFFFF) >> 12; - const auto offset = vaddr & 0xFFF; - const auto pointer = writePages[page]; + u32 paddr = vaddr; + if(!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); + } + + const auto page = paddr >> 12; + auto offset = paddr & 0xFFF; + const auto pointer = readPages[page]; if(pointer) { util::WriteAccess((u8*)pointer, offset, val); } else { - u32 paddr = vaddr; - if(!MapVAddr(regs, STORE, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); - } - switch(paddr) { case 0x00000000 ... 0x007FFFFF: - util::WriteAccess(mmio.rdp.dram.data(), paddr, val); + util::WriteAccess(mmio.rdp.rdram.data(), paddr, val); break; case 0x04000000 ... 0x0403FFFF: if(paddr & 0x1000) @@ -444,22 +449,25 @@ void Mem::Write32(Registers& regs, u64 vaddr, u32 val, s64 pc) { template void Mem::Write64(Registers& regs, u64 vaddr, u64 val, s64 pc) { - const auto page = (vaddr & 0xFFFFFFFF) >> 12; - const auto offset = vaddr & 0xFFF; - const auto pointer = writePages[page]; + u32 paddr = vaddr; + if(!MapVAddr(regs, STORE, vaddr, paddr)) { + HandleTLBException(regs, vaddr); + FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); + } + + const auto page = paddr >> 12; + auto offset = paddr & 0xFFF; + const auto pointer = readPages[page]; if(pointer) { + if(paddr >= 0x04000000 && paddr <= 0x0403FFFF) { + val >>= 32; + } util::WriteAccess((u8*)pointer, offset, val); } else { - u32 paddr = vaddr; - if (!MapVAddr(regs, STORE, vaddr, paddr)) { - HandleTLBException(regs, vaddr); - FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, STORE), 0, pc); - } - switch (paddr) { case 0x00000000 ... 0x007FFFFF: - util::WriteAccess(mmio.rdp.dram.data(), paddr, val); + util::WriteAccess(mmio.rdp.rdram.data(), paddr, val); break; case 0x04000000 ... 0x0403FFFF: val >>= 32; diff --git a/src/n64/core/Mem.hpp b/src/n64/core/Mem.hpp index 8dbe3a28..13953ead 100644 --- a/src/n64/core/Mem.hpp +++ b/src/n64/core/Mem.hpp @@ -20,7 +20,7 @@ struct Mem { void Reset(); CartInfo LoadROM(const std::string&); [[nodiscard]] auto GetRDRAM() -> u8* { - return mmio.rdp.dram.data(); + return mmio.rdp.rdram.data(); } template @@ -46,7 +46,7 @@ struct Mem { inline void DumpRDRAM() const { FILE *fp = fopen("rdram.dump", "wb"); u8 *temp = (u8*)calloc(RDRAM_SIZE, 1); - memcpy(temp, mmio.rdp.dram.data(), RDRAM_SIZE); + memcpy(temp, mmio.rdp.rdram.data(), RDRAM_SIZE); util::SwapBuffer32(RDRAM_SIZE, temp); fwrite(temp, 1, RDRAM_SIZE, fp); free(temp); @@ -72,6 +72,7 @@ struct Mem { free(temp); fclose(fp); } + std::vector writePages, readPages; private: friend struct SI; friend struct PI; @@ -82,7 +83,6 @@ private: std::vector cart, sram; u8 pifBootrom[PIF_BOOTROM_SIZE]{}; u8 isviewer[ISVIEWER_SIZE]{}; - std::vector writePages, readPages; size_t romMask; void SetCICType(u32& cicType, u32 checksum) { diff --git a/src/n64/core/RDP.cpp b/src/n64/core/RDP.cpp index 98b23fbd..6707017d 100644 --- a/src/n64/core/RDP.cpp +++ b/src/n64/core/RDP.cpp @@ -11,8 +11,8 @@ RDP::RDP() { void RDP::Reset() { dpc.status.raw = 0x80; - dram.resize(RDRAM_SIZE); - std::fill(dram.begin(), dram.end(), 0); + rdram.resize(RDRAM_SIZE); + std::fill(rdram.begin(), rdram.end(), 0); memset(cmd_buf, 0, 0x100000); } @@ -144,7 +144,7 @@ void RDP::RunCommand(MI& mi, Registers& regs, RSP& rsp) { return; } for (int i = 0; i < len; i += 4) { - u32 cmd = util::ReadAccess(dram.data(), current + i); + u32 cmd = util::ReadAccess(rdram.data(), current + i); cmd_buf[remaining_cmds + (i >> 2)] = cmd; } } diff --git a/src/n64/core/RDP.hpp b/src/n64/core/RDP.hpp index 11e0a8d9..c84a5c63 100644 --- a/src/n64/core/RDP.hpp +++ b/src/n64/core/RDP.hpp @@ -57,7 +57,7 @@ struct RDP { RDP(); void Reset(); - std::vector dram; + std::vector rdram; [[nodiscard]] auto Read(u32 addr) const -> u32; void Write(MI& mi, Registers& regs, RSP& rsp, u32 addr, u32 val); void WriteStatus(MI& mi, Registers& regs, RSP& rsp, u32 val); diff --git a/src/n64/core/mmio/AI.cpp b/src/n64/core/mmio/AI.cpp index b3f5dde3..6f77f766 100644 --- a/src/n64/core/mmio/AI.cpp +++ b/src/n64/core/mmio/AI.cpp @@ -81,17 +81,19 @@ void AI::Step(Mem& mem, Registers& regs, int cpuCycles, float volumeL, float vol } if(dmaLen[0] && dmaEnable) { - u32 addrHi = ((dmaAddr[0] >> 13) + dmaAddrCarry) & 0x7FF; - dmaAddr[0] = (addrHi << 13) | (dmaAddr[0] & 0x1FFF); - u32 data = util::ReadAccess(mem.mmio.rdp.dram.data(), dmaAddr[0] & RDRAM_DSIZE); - s16 l = s16(data >> 16); - s16 r = s16(data); + if(volumeR > 0 && volumeL > 0) { + u32 addrHi = ((dmaAddr[0] >> 13) + dmaAddrCarry) & 0x7FF; + dmaAddr[0] = (addrHi << 13) | (dmaAddr[0] & 0x1FFF); + u32 data = util::ReadAccess(mem.mmio.rdp.rdram.data(), dmaAddr[0] & RDRAM_DSIZE); + s16 l = s16(data >> 16); + s16 r = s16(data); - PushSample((float)l / INT16_MAX, volumeL, (float)r / INT16_MAX, volumeR); + PushSample((float) l / INT16_MAX, volumeL, (float) r / INT16_MAX, volumeR); - u32 addrLo = (dmaAddr[0] + 4) & 0x1FFF; - dmaAddr[0] = (dmaAddr[0] & ~0x1FFF) | addrLo; - dmaAddrCarry = addrLo == 0; + u32 addrLo = (dmaAddr[0] + 4) & 0x1FFF; + dmaAddr[0] = (dmaAddr[0] & ~0x1FFF) | addrLo; + dmaAddrCarry = addrLo == 0; + } dmaLen[0] -= 4; } diff --git a/src/n64/core/mmio/PI.cpp b/src/n64/core/mmio/PI.cpp index cc1a07d1..c62f3204 100644 --- a/src/n64/core/mmio/PI.cpp +++ b/src/n64/core/mmio/PI.cpp @@ -52,7 +52,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { } rdLen = len; for(int i = 0; i < len; i++) { - mem.cart[BYTE_ADDRESS(cart_addr + i) & mem.romMask] = mem.mmio.rdp.dram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE]; + mem.cart[BYTE_ADDRESS(cart_addr + i) & mem.romMask] = mem.mmio.rdp.rdram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE]; } dramAddr = dram_addr + len; cartAddr = cart_addr + len; @@ -68,7 +68,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) { } wrLen = len; for(int i = 0; i < len; i++) { - mem.mmio.rdp.dram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE] = mem.cart[BYTE_ADDRESS(cart_addr + i) & mem.romMask]; + mem.mmio.rdp.rdram[BYTE_ADDRESS(dram_addr + i) & RDRAM_DSIZE] = mem.cart[BYTE_ADDRESS(cart_addr + i) & mem.romMask]; } dramAddr = dram_addr + len; cartAddr = cart_addr + len; diff --git a/src/n64/core/mmio/SI.cpp b/src/n64/core/mmio/SI.cpp index 4244cd86..44db4dc3 100644 --- a/src/n64/core/mmio/SI.cpp +++ b/src/n64/core/mmio/SI.cpp @@ -39,11 +39,11 @@ void DMA(Mem& mem, Registers& regs) { if(si.toDram) { ProcessPIFCommands(mem.pifRam, si.controller, mem); for(int i = 0; i < 64; i++) { - mem.mmio.rdp.dram[BYTE_ADDRESS(si.dramAddr + i)] = mem.pifRam[i]; + mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)] = mem.pifRam[i]; } } else { for(int i = 0; i < 64; i++) { - mem.pifRam[i] = mem.mmio.rdp.dram[BYTE_ADDRESS(si.dramAddr + i)]; + mem.pifRam[i] = mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)]; } util::logdebug("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})\n", si.pifAddr, si.dramAddr); ProcessPIFCommands(mem.pifRam, si.controller, mem);