Refactor Memory
This commit is contained in:
@@ -8,7 +8,7 @@ namespace Util {
|
||||
#define V64 0x37800012
|
||||
|
||||
template <bool toBE = false>
|
||||
FORCE_INLINE void SwapN64Rom(size_t size, u8 *rom, u32 endianness) {
|
||||
FORCE_INLINE void SwapN64Rom(std::vector<u8> &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!");
|
||||
|
||||
@@ -71,7 +71,7 @@ std::vector<u8> 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<u8> &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);
|
||||
|
||||
@@ -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<u8> Mem::OpenArchive(const std::string &path, size_t& sizeAdjusted)
|
||||
|
||||
std::vector<u8> buf{};
|
||||
|
||||
std::string rom_exts[] = {".n64",".z64",".v64",".N64",".Z64",".V64"};
|
||||
std::vector<std::string> 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<u8> 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<u8> temp{};
|
||||
if(isArchive) {
|
||||
temp = OpenArchive(filename, sizeAdjusted);
|
||||
} else {
|
||||
temp = OpenROM(filename, sizeAdjusted);
|
||||
u32 endianness;
|
||||
{
|
||||
std::vector<u8> buf{};
|
||||
if (isArchive) {
|
||||
buf = OpenArchive(filename, sizeAdjusted);
|
||||
} else {
|
||||
buf = OpenROM(filename, sizeAdjusted);
|
||||
}
|
||||
|
||||
endianness = be32toh(*reinterpret_cast<u32*>(buf.data()));
|
||||
Util::SwapN64Rom<true>(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<u32*>(buf));
|
||||
Util::SwapN64Rom<true>(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<u32*>(rom.cart));
|
||||
Util::SwapN64Rom(sizeAdjusted, rom.cart, endianness);
|
||||
endianness = be32toh(*reinterpret_cast<u32*>(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<u8, false>(*this, paddr);
|
||||
@@ -242,13 +232,8 @@ template<> u16 Mem::Read(n64::Registers ®s, u32 paddr) {
|
||||
case RDRAM_REGION:
|
||||
return Util::ReadAccess<u16>(mmio.rdp.rdram, HALF_ADDRESS(paddr));
|
||||
case RSP_MEM_REGION: {
|
||||
u32 mirrAddr = paddr & 0x1FFF;
|
||||
if(mirrAddr & 0x1000) {
|
||||
mirrAddr -= 0x1000;
|
||||
return Util::ReadAccess<u16>(mmio.rsp.imem, HALF_ADDRESS(mirrAddr));
|
||||
} else {
|
||||
return Util::ReadAccess<u16>(mmio.rsp.dmem, HALF_ADDRESS(mirrAddr));
|
||||
}
|
||||
auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
|
||||
return Util::ReadAccess<u16>(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<u32>(mmio.rdp.rdram, paddr);
|
||||
case RSP_MEM_REGION: {
|
||||
u32 mirrAddr = paddr & 0x1FFF;
|
||||
if(mirrAddr & 0x1000) {
|
||||
mirrAddr -= 0x1000;
|
||||
return Util::ReadAccess<u32>(mmio.rsp.imem, mirrAddr);
|
||||
} else {
|
||||
return Util::ReadAccess<u32>(mmio.rsp.dmem, mirrAddr);
|
||||
}
|
||||
auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
|
||||
return Util::ReadAccess<u32>(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<u64>(mmio.rdp.rdram, paddr);
|
||||
case RSP_MEM_REGION: {
|
||||
u32 mirrAddr = paddr & 0x1FFF;
|
||||
if(mirrAddr & 0x1000) {
|
||||
mirrAddr -= 0x1000;
|
||||
return Util::ReadAccess<u64>(mmio.rsp.imem, mirrAddr);
|
||||
} else {
|
||||
return Util::ReadAccess<u64>(mmio.rsp.dmem, mirrAddr);
|
||||
}
|
||||
auto& src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
|
||||
return Util::ReadAccess<u64>(src, paddr & 0xfff);
|
||||
}
|
||||
case MMIO_REGION:
|
||||
return mmio.Read(paddr);
|
||||
@@ -360,14 +335,10 @@ template<> void Mem::Write<u8>(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<u32>(mmio.rsp.imem, mirrAddr, val);
|
||||
} else {
|
||||
Util::WriteAccess<u32>(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<u32>(dest, paddr, val);
|
||||
} break;
|
||||
case REGION_CART:
|
||||
Util::trace("BusWrite<u8> @ {:08X} = {:02X}", paddr, val);
|
||||
@@ -409,14 +380,10 @@ template<> void Mem::Write<u16>(Registers& regs, u32 paddr, u32 val) {
|
||||
Util::WriteAccess<u16>(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<u32>(mmio.rsp.imem, mirrAddr, val);
|
||||
} else {
|
||||
Util::WriteAccess<u32>(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<u32>(dest, paddr, val);
|
||||
} break;
|
||||
case REGION_CART:
|
||||
Util::trace("BusWrite<u8> @ {:08X} = {:04X}", paddr, val);
|
||||
@@ -458,12 +425,8 @@ template<> void Mem::Write<u32>(Registers& regs, u32 paddr, u32 val) {
|
||||
Util::WriteAccess<u32>(mmio.rdp.rdram, paddr, val);
|
||||
break;
|
||||
case RSP_MEM_REGION: {
|
||||
u32 mirrAddr = paddr & 0x1FFF;
|
||||
if(mirrAddr & 0x1000) {
|
||||
Util::WriteAccess<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||
} else {
|
||||
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
||||
}
|
||||
auto& dest = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
|
||||
Util::WriteAccess<u32>(dest, paddr & 0xfff, val);
|
||||
} break;
|
||||
case REGION_CART:
|
||||
Util::trace("BusWrite<u8> @ {:08X} = {:08X}", paddr, val);
|
||||
@@ -501,13 +464,9 @@ void Mem::Write(Registers& regs, u32 paddr, u64 val) {
|
||||
Util::WriteAccess<u64>(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<u32>(mmio.rsp.imem, paddr & IMEM_DSIZE, val);
|
||||
} else {
|
||||
Util::WriteAccess<u32>(mmio.rsp.dmem, paddr & DMEM_DSIZE, val);
|
||||
}
|
||||
Util::WriteAccess<u32>(dest, paddr & 0xfff, val);
|
||||
} break;
|
||||
case REGION_CART:
|
||||
Util::trace("BusWrite<u8> @ {:08X} = {:016X}", paddr, val);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <Registers.hpp>
|
||||
#include <algorithm>
|
||||
#include <GameDB.hpp>
|
||||
#include <File.hpp>
|
||||
|
||||
namespace n64 {
|
||||
struct ROMHeader {
|
||||
@@ -26,8 +27,7 @@ struct ROMHeader {
|
||||
};
|
||||
|
||||
struct ROM {
|
||||
u8* cart;
|
||||
size_t size;
|
||||
std::vector<u8> 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<u8, 128> writeBuf{};
|
||||
std::string flashPath{};
|
||||
mio::mmap_sink& saveData;
|
||||
|
||||
@@ -87,7 +87,11 @@ struct Mem {
|
||||
static std::vector<u8> OpenROM(const std::string&, size_t&);
|
||||
static std::vector<u8> 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<u8>& {
|
||||
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<u8> 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<u8, IMEM_SIZE> 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<u8, DMEM_SIZE> 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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ struct RDP {
|
||||
RDP();
|
||||
void Reset();
|
||||
|
||||
u8* rdram = nullptr;
|
||||
std::vector<u8> 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);
|
||||
|
||||
@@ -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<false>(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank);
|
||||
DMAtoRSP(spDMALen, mem.GetRDRAM(), *this, spDMASPAddr.bank);
|
||||
} break;
|
||||
case 0x0404000C: {
|
||||
spDMALen.raw = value;
|
||||
DMA<true>(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;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <MemoryRegions.hpp>
|
||||
#include <MemoryHelpers.hpp>
|
||||
#include <Interrupt.hpp>
|
||||
#include <array>
|
||||
|
||||
#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<u8, DMEM_SIZE> dmem{};
|
||||
std::array<u8, IMEM_SIZE> imem{};
|
||||
VPR vpr[32]{};
|
||||
s32 gpr[32]{};
|
||||
VPR vce{};
|
||||
@@ -356,31 +358,50 @@ struct RSP {
|
||||
void mfc2(u32 instr);
|
||||
void mtc2(u32 instr);
|
||||
|
||||
template <bool isDRAMdest>
|
||||
FORCE_INLINE void DMA(SPDMALen len, u8* rdram, RSP& rsp, bool bank) {
|
||||
FORCE_INLINE void DMAtoRDRAM(SPDMALen len, std::vector<u8>& 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<u8>& dst = rdram;
|
||||
std::array<u8, DMEM_SIZE>& 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<u8>& rdram, RSP& rsp, bool bank) {
|
||||
u32 length = len.len + 1;
|
||||
|
||||
length = (length + 0x7) & ~0x7;
|
||||
|
||||
std::vector<u8>& src = rdram;
|
||||
std::array<u8, DMEM_SIZE>& 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;
|
||||
|
||||
@@ -117,7 +117,7 @@ std::vector<u8> 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<u8>& 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>(u32 index, u32 val) {
|
||||
|
||||
@@ -62,8 +62,8 @@ template<> auto PI::BusRead<u8, true>(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<u8, false>(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<u16, false>(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<u16>(mem.rom.cart, index);
|
||||
@@ -213,7 +213,7 @@ template <> auto PI::BusRead<u32, false>(Mem& mem, u32 addr) -> u32 {
|
||||
return mem.BackupRead<u32>(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<u32>(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER));
|
||||
@@ -313,7 +313,7 @@ template <> auto PI::BusRead<u64, false>(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<u64>(mem.rom.cart, index);
|
||||
|
||||
@@ -593,7 +593,7 @@ void PIF::HLE(bool pal, CICType cicType) {
|
||||
regs.gpr[22] = (cicSeeds[cicType] >> 8) & 0xFF;
|
||||
regs.cop0.Reset();
|
||||
mem.Write<u32>(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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<false>(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<true>(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:
|
||||
|
||||
Reference in New Issue
Block a user