diff --git a/src/backend/RomHelpers.hpp b/src/backend/RomHelpers.hpp index 6c9c0040..ebae39a2 100644 --- a/src/backend/RomHelpers.hpp +++ b/src/backend/RomHelpers.hpp @@ -8,7 +8,7 @@ namespace Util { #define V64 0x37800012 template -FORCE_INLINE void SwapN64Rom(size_t size, u8 *rom, u32 endianness) { +FORCE_INLINE void SwapN64Rom(std::vector &rom, u32 endianness) { u8 altByteShift = 0; if((endianness >> 24) != 0x80) { if((endianness & 0xFF) != 0x80) { @@ -28,17 +28,17 @@ FORCE_INLINE void SwapN64Rom(size_t size, u8 *rom, u32 endianness) { switch (endianness) { case V64: - SwapBuffer16(size, rom); + SwapBuffer16(rom); if constexpr(!toBE) - SwapBuffer32(size, rom); + SwapBuffer32(rom); break; case N64: if constexpr(toBE) - SwapBuffer32(size, rom); + SwapBuffer32(rom); break; case Z64: if constexpr(!toBE) - SwapBuffer32(size, rom); + SwapBuffer32(rom); break; default: panic("Unrecognized rom format! Make sure this is a valid Nintendo 64 ROM dump!"); diff --git a/src/backend/core/MMIO.cpp b/src/backend/core/MMIO.cpp index 3cb328fa..1f0ede02 100644 --- a/src/backend/core/MMIO.cpp +++ b/src/backend/core/MMIO.cpp @@ -71,7 +71,7 @@ std::vector MMIO::Serialize() { index += sizeof(DPC); memcpy(res.data() + index, rdp.cmd_buf, 0xFFFFF); index += 0xFFFFF; - memcpy(res.data() + index, rdp.rdram, RDRAM_SIZE); + std::copy(rdp.rdram.begin(), rdp.rdram.end(), res.begin() + index); index += RDRAM_SIZE; memcpy(res.data() + index, &mi, sizeof(MI)); index += sizeof(MI); @@ -102,7 +102,7 @@ void MMIO::Deserialize(const std::vector &data) { index += sizeof(DPC); memcpy(rdp.cmd_buf, data.data() + index, 0xFFFFF); index += 0xFFFFF; - memcpy(rdp.rdram, data.data() + index, RDRAM_SIZE); + std::copy(data.begin() + index, data.begin() + index + RDRAM_SIZE, rdp.rdram.begin()); index += RDRAM_SIZE; memcpy(&mi, data.data() + index, sizeof(MI)); index += sizeof(MI); diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index 5ba5c4bc..d8908bf7 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -19,11 +19,12 @@ Mem::Mem(Registers& regs) : flash(saveData), mmio(*this, regs) { writePages[i] = pointer; } - rom.cart = (u8*)calloc(CART_SIZE, 1); + rom.cart.resize(CART_SIZE); + std::fill(rom.cart.begin(), rom.cart.end(), 0); } void Mem::Reset() { - memset(rom.cart, 0, CART_SIZE); + std::fill(rom.cart.begin(), rom.cart.end(), 0); flash.Reset(); if (saveData.is_mapped()) { std::error_code error; @@ -46,9 +47,7 @@ void Mem::LoadSRAM(SaveType save_type, fs::path path) { FILE *f = fopen(sramPath.c_str(), "rb"); if (!f) { - f = fopen(sramPath.c_str(), "wb"); - u8* dummy = (u8*)calloc(SRAM_SIZE, 1); - fwrite(dummy, 1, SRAM_SIZE, f); + Util::panic("Could not open {}", sramPath); } fseek(f, 0, SEEK_END); @@ -60,7 +59,7 @@ void Mem::LoadSRAM(SaveType save_type, fs::path path) { fclose(f); saveData = mio::make_mmap_sink( sramPath, 0, mio::map_entire_file, error); - if (error) { Util::panic("Could not open {}", sramPath); } + if (error) { Util::panic("Could not mmap {}", sramPath); } } } @@ -99,13 +98,13 @@ std::vector Mem::OpenArchive(const std::string &path, size_t& sizeAdjusted) std::vector buf{}; - std::string rom_exts[] = {".n64",".z64",".v64",".N64",".Z64",".V64"}; + std::vector rom_exts{".n64",".z64",".v64",".N64",".Z64",".V64"}; while(ar_parse_entry(archive)) { auto filename = ar_entry_get_name(archive); auto extension = fs::path(filename).extension(); - if(std::any_of(std::begin(rom_exts), std::end(rom_exts), [&](auto x) { + if(std::any_of(rom_exts.begin(), rom_exts.end(), [&](auto x) { return extension == x; })) { auto size = ar_entry_get_size(archive); @@ -133,28 +132,24 @@ std::vector Mem::OpenROM(const std::string& filename, size_t& sizeAdjusted) void Mem::LoadROM(bool isArchive, const std::string& filename) { size_t sizeAdjusted; - u8* buf; - std::vector temp{}; - if(isArchive) { - temp = OpenArchive(filename, sizeAdjusted); - } else { - temp = OpenROM(filename, sizeAdjusted); + u32 endianness; + { + std::vector buf{}; + if (isArchive) { + buf = OpenArchive(filename, sizeAdjusted); + } else { + buf = OpenROM(filename, sizeAdjusted); + } + + endianness = be32toh(*reinterpret_cast(buf.data())); + Util::SwapN64Rom(buf, endianness); + + std::copy(buf.begin(), buf.end(), rom.cart.begin()); + rom.mask = sizeAdjusted - 1; + memcpy(&rom.header, buf.data(), sizeof(ROMHeader)); } - - buf = (u8*)calloc(sizeAdjusted, 1); - std::copy(temp.begin(), temp.end(), buf); - - u32 endianness = be32toh(*reinterpret_cast(buf)); - Util::SwapN64Rom(sizeAdjusted, buf, endianness); - - memcpy(rom.cart, buf, sizeAdjusted); - rom.size = sizeAdjusted; - rom.mask = sizeAdjusted - 1; - memcpy(&rom.header, buf, sizeof(ROMHeader)); memcpy(rom.gameNameCart, rom.header.imageName, sizeof(rom.header.imageName)); - free(buf); - rom.header.clockRate = be32toh(rom.header.clockRate); rom.header.programCounter = be32toh(rom.header.programCounter); rom.header.release = be32toh(rom.header.release); @@ -176,8 +171,8 @@ void Mem::LoadROM(bool isArchive, const std::string& filename) { u32 checksum = Util::crc32(0, &rom.cart[0x40], 0x9c0); SetROMCIC(checksum, rom); - endianness = be32toh(*reinterpret_cast(rom.cart)); - Util::SwapN64Rom(sizeAdjusted, rom.cart, endianness); + endianness = be32toh(*reinterpret_cast(rom.cart.data())); + Util::SwapN64Rom(rom.cart, endianness); rom.pal = IsROMPAL(); } @@ -194,13 +189,8 @@ template<> u8 Mem::Read(n64::Registers ®s, u32 paddr) { case RDRAM_REGION: return mmio.rdp.rdram[BYTE_ADDRESS(paddr)]; case RSP_MEM_REGION: { - u32 mirrAddr = paddr & 0x1FFF; - if(mirrAddr & 0x1000) { - mirrAddr -= 0x1000; - return mmio.rsp.imem[BYTE_ADDRESS(mirrAddr)]; - } else { - return mmio.rsp.dmem[BYTE_ADDRESS(mirrAddr)]; - } + auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + return src[BYTE_ADDRESS(paddr & 0xfff)]; } case REGION_CART: return mmio.pi.BusRead(*this, paddr); @@ -242,13 +232,8 @@ template<> u16 Mem::Read(n64::Registers ®s, u32 paddr) { case RDRAM_REGION: return Util::ReadAccess(mmio.rdp.rdram, HALF_ADDRESS(paddr)); case RSP_MEM_REGION: { - u32 mirrAddr = paddr & 0x1FFF; - if(mirrAddr & 0x1000) { - mirrAddr -= 0x1000; - return Util::ReadAccess(mmio.rsp.imem, HALF_ADDRESS(mirrAddr)); - } else { - return Util::ReadAccess(mmio.rsp.dmem, HALF_ADDRESS(mirrAddr)); - } + auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + return Util::ReadAccess(src, HALF_ADDRESS(paddr & 0xfff)); } case MMIO_REGION: return mmio.Read(paddr); @@ -282,13 +267,8 @@ template<> u32 Mem::Read(n64::Registers ®s, u32 paddr) { case RDRAM_REGION: return Util::ReadAccess(mmio.rdp.rdram, paddr); case RSP_MEM_REGION: { - u32 mirrAddr = paddr & 0x1FFF; - if(mirrAddr & 0x1000) { - mirrAddr -= 0x1000; - return Util::ReadAccess(mmio.rsp.imem, mirrAddr); - } else { - return Util::ReadAccess(mmio.rsp.dmem, mirrAddr); - } + auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + return Util::ReadAccess(src, paddr & 0xfff); } case MMIO_REGION: return mmio.Read(paddr); @@ -319,13 +299,8 @@ template<> u64 Mem::Read(n64::Registers ®s, u32 paddr) { case RDRAM_REGION: return Util::ReadAccess(mmio.rdp.rdram, paddr); case RSP_MEM_REGION: { - u32 mirrAddr = paddr & 0x1FFF; - if(mirrAddr & 0x1000) { - mirrAddr -= 0x1000; - return Util::ReadAccess(mmio.rsp.imem, mirrAddr); - } else { - return Util::ReadAccess(mmio.rsp.dmem, mirrAddr); - } + auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + return Util::ReadAccess(src, paddr & 0xfff); } case MMIO_REGION: return mmio.Read(paddr); @@ -360,14 +335,10 @@ template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { mmio.rdp.rdram[BYTE_ADDRESS(paddr)] = val; break; case RSP_MEM_REGION: { - u32 mirrAddr = paddr & 0x1FFF; - val = val << (8 * (3 - (mirrAddr & 3))); - mirrAddr = (mirrAddr & 0xFFF) & ~3; - if(mirrAddr & 0x1000) { - Util::WriteAccess(mmio.rsp.imem, mirrAddr, val); - } else { - Util::WriteAccess(mmio.rsp.dmem, mirrAddr, val); - } + val = val << (8 * (3 - (paddr & 3))); + auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + paddr = (paddr & 0xFFF) & ~3; + Util::WriteAccess(dest, paddr, val); } break; case REGION_CART: Util::trace("BusWrite @ {:08X} = {:02X}", paddr, val); @@ -409,14 +380,10 @@ template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { Util::WriteAccess(mmio.rdp.rdram, HALF_ADDRESS(paddr), val); break; case RSP_MEM_REGION: { - u32 mirrAddr = paddr & 0x1FFF; - val = val << (16 * !(mirrAddr & 2)); - mirrAddr = (mirrAddr & 0xFFF) & ~3; - if(mirrAddr & 0x1000) { - Util::WriteAccess(mmio.rsp.imem, mirrAddr, val); - } else { - Util::WriteAccess(mmio.rsp.dmem, mirrAddr, val); - } + val = val << (16 * !(paddr & 2)); + auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + paddr = (paddr & 0xFFF) & ~3; + Util::WriteAccess(dest, paddr, val); } break; case REGION_CART: Util::trace("BusWrite @ {:08X} = {:04X}", paddr, val); @@ -458,12 +425,8 @@ template<> void Mem::Write(Registers& regs, u32 paddr, u32 val) { Util::WriteAccess(mmio.rdp.rdram, paddr, val); break; case RSP_MEM_REGION: { - u32 mirrAddr = paddr & 0x1FFF; - if(mirrAddr & 0x1000) { - Util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); - } else { - Util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); - } + auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; + Util::WriteAccess(dest, paddr & 0xfff, val); } break; case REGION_CART: Util::trace("BusWrite @ {:08X} = {:08X}", paddr, val); @@ -501,13 +464,9 @@ void Mem::Write(Registers& regs, u32 paddr, u64 val) { Util::WriteAccess(mmio.rdp.rdram, paddr, val); break; case RSP_MEM_REGION: { - u32 mirrAddr = paddr & 0x1FFF; + auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem; val >>= 32; - if(mirrAddr & 0x1000) { - Util::WriteAccess(mmio.rsp.imem, paddr & IMEM_DSIZE, val); - } else { - Util::WriteAccess(mmio.rsp.dmem, paddr & DMEM_DSIZE, val); - } + Util::WriteAccess(dest, paddr & 0xfff, val); } break; case REGION_CART: Util::trace("BusWrite @ {:08X} = {:016X}", paddr, val); diff --git a/src/backend/core/Mem.hpp b/src/backend/core/Mem.hpp index d445b717..88c001c9 100644 --- a/src/backend/core/Mem.hpp +++ b/src/backend/core/Mem.hpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace n64 { struct ROMHeader { @@ -26,8 +27,7 @@ struct ROMHeader { }; struct ROM { - u8* cart; - size_t size; + std::vector cart; size_t mask; ROMHeader header; CICType cicType; @@ -50,7 +50,7 @@ struct Flash { u64 status{}; size_t eraseOffs{}; size_t writeOffs{}; - u8 writeBuf[128]{}; + std::array writeBuf{}; std::string flashPath{}; mio::mmap_sink& saveData; @@ -87,7 +87,11 @@ struct Mem { static std::vector OpenROM(const std::string&, size_t&); static std::vector OpenArchive(const std::string&, size_t&); void LoadROM(bool, const std::string&); - [[nodiscard]] auto GetRDRAM() const -> u8* { + [[nodiscard]] auto GetRDRAMPtr() -> u8* { + return mmio.rdp.rdram.data(); + } + + [[nodiscard]] auto GetRDRAM() -> std::vector& { return mmio.rdp.rdram; } @@ -108,33 +112,25 @@ struct Mem { MMIO mmio; FORCE_INLINE void DumpRDRAM() const { - FILE *fp = fopen("rdram.dump", "wb"); - u8 *temp = (u8*)calloc(RDRAM_SIZE, 1); - memcpy(temp, mmio.rdp.rdram, RDRAM_SIZE); - Util::SwapBuffer32(RDRAM_SIZE, temp); - fwrite(temp, 1, RDRAM_SIZE, fp); - free(temp); - fclose(fp); + std::vector temp{}; + temp.resize(RDRAM_SIZE); + std::copy(mmio.rdp.rdram.begin(), mmio.rdp.rdram.end(), temp.begin()); + Util::SwapBuffer32(temp); + Util::WriteFileBinary(temp, "rdram.bin"); } FORCE_INLINE void DumpIMEM() const { - FILE *fp = fopen("imem.bin", "wb"); - u8 *temp = (u8*)calloc(IMEM_SIZE, 1); - memcpy(temp, mmio.rsp.imem, IMEM_SIZE); - Util::SwapBuffer32(IMEM_SIZE, temp); - fwrite(temp, 1, IMEM_SIZE, fp); - free(temp); - fclose(fp); + std::array temp{}; + std::copy(mmio.rsp.imem.begin(), mmio.rsp.imem.end(), temp.begin()); + Util::SwapBuffer32(temp); + Util::WriteFileBinary(temp, "imem.bin"); } FORCE_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); + std::array temp{}; + std::copy(mmio.rsp.dmem.begin(), mmio.rsp.dmem.end(), temp.begin()); + Util::SwapBuffer32(temp); + Util::WriteFileBinary(temp, "dmem.bin"); } uintptr_t writePages[PAGE_COUNT]{}, readPages[PAGE_COUNT]{}; ROM rom; diff --git a/src/backend/core/RDP.cpp b/src/backend/core/RDP.cpp index 09a490ab..a2ca1888 100644 --- a/src/backend/core/RDP.cpp +++ b/src/backend/core/RDP.cpp @@ -6,14 +6,14 @@ namespace n64 { RDP::RDP() { - rdram = (u8*)calloc(RDRAM_SIZE, 1); + rdram.resize(RDRAM_SIZE); memset(cmd_buf, 0, 0x100000); dpc.status.raw = 0x80; } void RDP::Reset() { dpc.status.raw = 0x80; - memset(rdram, 0, RDRAM_SIZE); + rdram = {}; memset(cmd_buf, 0, 0x100000); } diff --git a/src/backend/core/RDP.hpp b/src/backend/core/RDP.hpp index 12b6681f..6bf0bec0 100644 --- a/src/backend/core/RDP.hpp +++ b/src/backend/core/RDP.hpp @@ -57,7 +57,7 @@ struct RDP { RDP(); void Reset(); - u8* rdram = nullptr; + 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/backend/core/RSP.cpp b/src/backend/core/RSP.cpp index 343e104c..9844e922 100644 --- a/src/backend/core/RSP.cpp +++ b/src/backend/core/RSP.cpp @@ -19,8 +19,8 @@ void RSP::Reset() { spDMASPAddr.raw = 0; spDMADRAMAddr.raw = 0; spDMALen.raw = 0; - memset(dmem, 0, DMEM_SIZE); - memset(imem, 0, IMEM_SIZE); + dmem = {}; + imem = {}; memset(vpr, 0, 32 * sizeof(VPR)); memset(gpr, 0, 32 * sizeof(u32)); memset(&vce, 0, sizeof(VPR)); @@ -116,11 +116,11 @@ void RSP::Write(Mem& mem, Registers& regs, u32 addr, u32 value) { case 0x04040004: spDMADRAMAddr.raw = value & 0xFFFFF8; break; case 0x04040008: { spDMALen.raw = value; - DMA(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank); + DMAtoRSP(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank); } break; case 0x0404000C: { spDMALen.raw = value; - DMA(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank); + DMAtoRDRAM(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank); } break; case 0x04040010: WriteStatus(mi, regs, value); break; case 0x0404001C: ReleaseSemaphore(); break; diff --git a/src/backend/core/RSP.hpp b/src/backend/core/RSP.hpp index e099d355..5ec1cb40 100644 --- a/src/backend/core/RSP.hpp +++ b/src/backend/core/RSP.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #define RSP_BYTE(addr) (dmem[BYTE_ADDRESS(addr) & 0xFFF]) #define GET_RSP_HALF(addr) ((RSP_BYTE(addr) << 8) | RSP_BYTE((addr) + 1)) @@ -134,7 +135,8 @@ struct RSP { SPDMASPAddr lastSuccessfulSPAddr{}; SPDMADRAMAddr lastSuccessfulDRAMAddr{}; SPDMALen spDMALen{}; - u8 dmem[DMEM_SIZE]{}, imem[IMEM_SIZE]{}; + std::array dmem{}; + std::array imem{}; VPR vpr[32]{}; s32 gpr[32]{}; VPR vce{}; @@ -356,31 +358,50 @@ struct RSP { void mfc2(u32 instr); void mtc2(u32 instr); - template - FORCE_INLINE void DMA(SPDMALen len, u8* rdram, RSP& rsp, bool bank) { + FORCE_INLINE void DMAtoRDRAM(SPDMALen len, std::vector& rdram, RSP& rsp, bool bank) { u32 length = len.len + 1; length = (length + 0x7) & ~0x7; - u8* dst, *src; - if constexpr (isDRAMdest) { - dst = rdram; - src = bank ? rsp.imem : rsp.dmem; - } else { - src = rdram; - dst = bank ? rsp.imem : rsp.dmem; - } + std::vector& dst = rdram; + std::array& src = bank ? rsp.imem : rsp.dmem; u32 mem_address = rsp.spDMASPAddr.address & 0xFF8; u32 dram_address = rsp.spDMADRAMAddr.address & 0xFFFFF8; for (u32 i = 0; i < len.count + 1; i++) { for(u32 j = 0; j < length; j++) { - if constexpr (isDRAMdest) { - dst[dram_address + j] = src[(mem_address + j) & 0xFFF]; - } else { - dst[(mem_address + j) & 0xFFF] = src[dram_address + j]; - } + dst[dram_address + j] = src[(mem_address + j) & 0xFFF]; + } + + int skip = i == len.count ? 0 : len.skip; + + dram_address += (length + skip); + dram_address &= 0xFFFFF8; + mem_address += length; + mem_address &= 0xFF8; + } + + rsp.lastSuccessfulSPAddr.address = mem_address; + rsp.lastSuccessfulSPAddr.bank = bank; + rsp.lastSuccessfulDRAMAddr.address = dram_address; + rsp.spDMALen.raw = 0xFF8 | (rsp.spDMALen.skip << 20); + } + + FORCE_INLINE void DMAtoRSP(SPDMALen len, std::vector& rdram, RSP& rsp, bool bank) { + u32 length = len.len + 1; + + length = (length + 0x7) & ~0x7; + + std::vector& src = rdram; + std::array& dst = bank ? rsp.imem : rsp.dmem; + + u32 mem_address = rsp.spDMASPAddr.address & 0xFF8; + u32 dram_address = rsp.spDMADRAMAddr.address & 0xFFFFF8; + + for (u32 i = 0; i < len.count + 1; i++) { + for(u32 j = 0; j < length; j++) { + dst[(mem_address + j) & 0xFFF] = src[dram_address + j]; } int skip = i == len.count ? 0 : len.skip; diff --git a/src/backend/core/mem/Flash.cpp b/src/backend/core/mem/Flash.cpp index 6d872b06..e7a0835b 100644 --- a/src/backend/core/mem/Flash.cpp +++ b/src/backend/core/mem/Flash.cpp @@ -117,7 +117,7 @@ std::vector Flash::Serialize() { index += sizeof(eraseOffs); memcpy(res.data() + index, &writeOffs, sizeof(writeOffs)); index += sizeof(writeOffs); - memcpy(res.data() + index, writeBuf, 128); + std::copy(writeBuf.begin(), writeBuf.end(), res.begin() + index); return res; } @@ -132,7 +132,7 @@ void Flash::Deserialize(const std::vector& data) { index += sizeof(eraseOffs); memcpy(&writeOffs, data.data() + index, sizeof(writeOffs)); index += sizeof(writeOffs); - memcpy(writeBuf, data.data() + index, 128); + std::copy(data.begin() + index, data.begin() + index + 128, writeBuf.begin()); } template <> void Flash::Write(u32 index, u32 val) { diff --git a/src/backend/core/mmio/PI.cpp b/src/backend/core/mmio/PI.cpp index 6d4e4d20..34dc7da2 100644 --- a/src/backend/core/mmio/PI.cpp +++ b/src/backend/core/mmio/PI.cpp @@ -62,8 +62,8 @@ template<> auto PI::BusRead(Mem& mem, u32 addr) -> u8 { case REGION_PI_ROM: { // round to nearest 4 byte boundary, keeping old LSB u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM; - if (index >= mem.rom.size) { - Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size); + if (index >= mem.rom.cart.size()) { + Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.cart.size(), mem.rom.cart.size()); return 0xFF; } return mem.rom.cart[index]; @@ -92,8 +92,8 @@ template<> auto PI::BusRead(Mem& mem, u32 addr) -> u8 { addr = (addr + 2) & ~2; // round to nearest 4 byte boundary, keeping old LSB u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM; - if (index >= mem.rom.size) { - Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.size, mem.rom.size); + if (index >= mem.rom.cart.size()) { + Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr, index, index, mem.rom.cart.size(), mem.rom.cart.size()); return 0xFF; } return mem.rom.cart[index]; @@ -154,7 +154,7 @@ template <> auto PI::BusRead(Mem& mem, u32 addr) -> u16 { case REGION_PI_ROM: { addr = (addr + 2) & ~3; u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM; - if (index > mem.rom.size - 1) { + if (index > mem.rom.cart.size() - 1) { Util::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index); } return Util::ReadAccess(mem.rom.cart, index); @@ -213,7 +213,7 @@ template <> auto PI::BusRead(Mem& mem, u32 addr) -> u32 { return mem.BackupRead(addr); case REGION_PI_ROM: { u32 index = addr - SREGION_PI_ROM; - if (index > mem.rom.size - 3) { // -3 because we're reading an entire word + if (index > mem.rom.cart.size() - 3) { // -3 because we're reading an entire word switch (addr) { case REGION_CART_ISVIEWER_BUFFER: return htobe32(Util::ReadAccess(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER)); @@ -313,7 +313,7 @@ template <> auto PI::BusRead(Mem& mem, u32 addr) -> u64 { Util::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr); case REGION_PI_ROM: { u32 index = addr - SREGION_PI_ROM; - if (index > mem.rom.size - 7) { // -7 because we're reading an entire dword + if (index > mem.rom.cart.size() - 7) { // -7 because we're reading an entire dword Util::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index); } return Util::ReadAccess(mem.rom.cart, index); diff --git a/src/backend/core/mmio/PIF.cpp b/src/backend/core/mmio/PIF.cpp index 31cdd629..60de423d 100644 --- a/src/backend/core/mmio/PIF.cpp +++ b/src/backend/core/mmio/PIF.cpp @@ -593,7 +593,7 @@ void PIF::HLE(bool pal, CICType cicType) { regs.gpr[22] = (cicSeeds[cicType] >> 8) & 0xFF; regs.cop0.Reset(); mem.Write(regs, 0x04300004, 0x01010101); - memcpy(mem.mmio.rsp.dmem, mem.rom.cart, 0x1000); + std::copy(mem.rom.cart.begin(), mem.rom.cart.begin() + 0x1000, mem.mmio.rsp.dmem.begin()); regs.SetPC32(s32(0xA4000040)); } diff --git a/src/backend/core/rsp/decode.cpp b/src/backend/core/rsp/decode.cpp index a2553df1..5c6a6253 100644 --- a/src/backend/core/rsp/decode.cpp +++ b/src/backend/core/rsp/decode.cpp @@ -221,13 +221,7 @@ void RSP::Exec(Registers ®s, Mem& mem, u32 instr) { case 0x32: lwc2(*this, instr); break; case 0x3A: swc2(*this, instr); break; default: - FILE *fp = fopen("imem.bin", "wb"); - u8 *temp = (u8*)calloc(IMEM_SIZE, 1); - memcpy(temp, imem, IMEM_SIZE); - Util::SwapBuffer32(IMEM_SIZE, temp); - fwrite(temp, 1, IMEM_SIZE, fp); - free(temp); - fclose(fp); + mem.DumpIMEM(); Util::panic("Unhandled RSP instruction ({:06b}, {:04X})", mask, oldPC); } } diff --git a/src/backend/core/rsp/instructions.cpp b/src/backend/core/rsp/instructions.cpp index d3059164..f34ae878 100644 --- a/src/backend/core/rsp/instructions.cpp +++ b/src/backend/core/rsp/instructions.cpp @@ -60,11 +60,11 @@ FORCE_INLINE void SetCop0Reg(Registers& regs, Mem& mem, u8 index, u32 val) { case 1: rsp.spDMADRAMAddr.raw = val; break; case 2: rsp.spDMALen.raw = val; - rsp.DMA(rsp.spDMALen, mem.GetRDRAM(), rsp, rsp.spDMASPAddr.bank); + rsp.DMAtoRSP(rsp.spDMALen, mem.GetRDRAM(), rsp, rsp.spDMASPAddr.bank); break; case 3: rsp.spDMALen.raw = val; - rsp.DMA(rsp.spDMALen, mem.GetRDRAM(), rsp, rsp.spDMASPAddr.bank); + rsp.DMAtoRDRAM(rsp.spDMALen, mem.GetRDRAM(), rsp, rsp.spDMASPAddr.bank); break; case 4: rsp.WriteStatus(mi, regs, val); break; case 7: diff --git a/src/frontend/EmuThread.cpp b/src/frontend/EmuThread.cpp index 6b03cb54..a338bb8f 100644 --- a/src/frontend/EmuThread.cpp +++ b/src/frontend/EmuThread.cpp @@ -8,7 +8,7 @@ EmuThread::EmuThread(std::unique_ptr&& instance, std::unique_ [[noreturn]] void EmuThread::run() noexcept { LoadWSIPlatform(instance.get(), std::move(wsiPlatform), std::move(windowInfo)); - LoadParallelRDP(core->cpu->mem.GetRDRAM()); + LoadParallelRDP(core->cpu->mem.GetRDRAMPtr()); while (true) { if (!core->pause) { diff --git a/src/utils/File.hpp b/src/utils/File.hpp index dd21ba54..63bca37a 100644 --- a/src/utils/File.hpp +++ b/src/utils/File.hpp @@ -8,6 +8,17 @@ FORCE_INLINE std::vector ReadFileBinary(const std::string& path) { return {std::istreambuf_iterator{file}, {}}; } +FORCE_INLINE void WriteFileBinary(const std::vector& data, const std::string& path) { + std::ofstream file(path, std::ios::binary); + std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file}); +} + +template +FORCE_INLINE void WriteFileBinary(const std::array& data, const std::string& path) { + std::ofstream file(path, std::ios::binary); + std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file}); +} + FORCE_INLINE size_t NextPow2(size_t num) { // Taken from "Bit Twiddling Hacks" by Sean Anderson: // https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 diff --git a/src/utils/MemoryHelpers.hpp b/src/utils/MemoryHelpers.hpp index a08221a2..75a589ca 100644 --- a/src/utils/MemoryHelpers.hpp +++ b/src/utils/MemoryHelpers.hpp @@ -6,7 +6,7 @@ namespace Util { template -static FORCE_INLINE T ReadAccess(const u8 *data, u32 index) { +static FORCE_INLINE T ReadAccess(const u8* data, u32 index) { if constexpr (sizeof(T) == 8) { u32 hi = *reinterpret_cast(&data[index + 0]); u32 lo = *reinterpret_cast(&data[index + 4]); @@ -17,6 +17,56 @@ static FORCE_INLINE T ReadAccess(const u8 *data, u32 index) { } } +template +static FORCE_INLINE T ReadAccess(const std::vector& data, u32 index) { + if constexpr (sizeof(T) == 8) { + u32 hi = *reinterpret_cast(&data[index + 0]); + u32 lo = *reinterpret_cast(&data[index + 4]); + T result = ((T)hi << 32) | (T)lo; + return result; + } else { + return *reinterpret_cast(&data[index]); + } +} + +template +static FORCE_INLINE T ReadAccess(const std::array& data, u32 index) { + if constexpr (sizeof(T) == 8) { + u32 hi = *reinterpret_cast(&data[index + 0]); + u32 lo = *reinterpret_cast(&data[index + 4]); + T result = ((T)hi << 32) | (T)lo; + return result; + } else { + return *reinterpret_cast(&data[index]); + } +} + +template +static FORCE_INLINE void WriteAccess(std::array& data, u32 index, T val) { + if constexpr (sizeof(T) == 8) { + u32 hi = val >> 32; + u32 lo = val; + + *reinterpret_cast(&data[index + 0]) = hi; + *reinterpret_cast(&data[index + 4]) = lo; + } else { + *reinterpret_cast(&data[index]) = val; + } +} + +template +static FORCE_INLINE void WriteAccess(std::vector& data, u32 index, T val) { + if constexpr (sizeof(T) == 8) { + u32 hi = val >> 32; + u32 lo = val; + + *reinterpret_cast(&data[index + 0]) = hi; + *reinterpret_cast(&data[index + 4]) = lo; + } else { + *reinterpret_cast(&data[index]) = val; + } +} + template static FORCE_INLINE void WriteAccess(u8 *data, u32 index, T val) { if constexpr (sizeof(T) == 8) { @@ -30,15 +80,31 @@ static FORCE_INLINE void WriteAccess(u8 *data, u32 index, T val) { } } -FORCE_INLINE void SwapBuffer32(size_t size, u8 *data) { - for (size_t i = 0; i < size; i += 4) { +FORCE_INLINE void SwapBuffer32(std::vector &data) { + for (size_t i = 0; i < data.size(); i += 4) { u32 original = *(u32 *) &data[i]; *(u32 *) &data[i] = bswap_32(original); } } -FORCE_INLINE void SwapBuffer16(size_t size, u8 *data) { - for (size_t i = 0; i < size; i += 2) { +FORCE_INLINE void SwapBuffer16(std::vector &data) { + for (size_t i = 0; i < data.size(); i += 2) { + u16 original = *(u16 *) &data[i]; + *(u16 *) &data[i] = bswap_16(original); + } +} + +template +FORCE_INLINE void SwapBuffer32(std::array &data) { + for (size_t i = 0; i < Size; i += 4) { + u32 original = *(u32 *) &data[i]; + *(u32 *) &data[i] = bswap_32(original); + } +} + +template +FORCE_INLINE void SwapBuffer16(std::array &data) { + for (size_t i = 0; i < Size; i += 2) { u16 original = *(u16 *) &data[i]; *(u16 *) &data[i] = bswap_16(original); }