From 4e6a3f21099cb56046809a02ed45308f64eee1a3 Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Sun, 5 Nov 2023 18:27:01 +0100 Subject: [PATCH] Improve cartridge regions handling --- src/backend/MemoryRegions.hpp | 29 ++++- src/backend/core/Mem.cpp | 220 ++++++++++++++++--------------- src/backend/core/Mem.hpp | 5 + src/backend/core/mmio/PI.cpp | 236 +++++++++++++++++++++++++++++++++- src/backend/core/mmio/PI.hpp | 8 ++ 5 files changed, 381 insertions(+), 117 deletions(-) diff --git a/src/backend/MemoryRegions.hpp b/src/backend/MemoryRegions.hpp index 25f09e07..47bf8702 100644 --- a/src/backend/MemoryRegions.hpp +++ b/src/backend/MemoryRegions.hpp @@ -51,10 +51,7 @@ #define PI_REGION 0x04600000 ... 0x046FFFFF #define RI_REGION 0x04700000 ... 0x047FFFFF #define SI_REGION 0x04800000 ... 0x048FFFFF -#define CART_REGION_1_1 (CART_REGION_START_1_1) ... (CART_REGION_END_1_1) -#define CART_REGION_1_2 (CART_REGION_START_1_2) ... (CART_REGION_END_1_2) -#define CART_REGION_2_1 (CART_REGION_START_2_1) ... (CART_REGION_END_2_1) -#define CART_REGION_2_2 (CART_REGION_START_2_2) ... (CART_REGION_END_2_2) +#define REGION_CART CART_REGION_START_2_1 ... CART_REGION_END_1_2 #define PIF_ROM_REGION PIF_ROM_REGION_START ... PIF_ROM_REGION_END #define PIF_RAM_REGION PIF_RAM_REGION_START ... PIF_RAM_REGION_END @@ -90,6 +87,30 @@ #define VREGION_CKSSEG 0xFFFFFFFFC0000000 ... 0xFFFFFFFFDFFFFFFF #define VREGION_CKSEG3 0xFFFFFFFFE0000000 ... 0xFFFFFFFFFFFFFFFF +#define SREGION_PI_UNKNOWN 0x00000000 +#define SREGION_PI_64DD_REG 0x05000000 +#define SREGION_PI_64DD_ROM 0x06000000 +#define SREGION_PI_SRAM 0x08000000 +#define SREGION_PI_ROM 0x10000000 + +#define EREGION_PI_UNKNOWN 0x04FFFFFF +#define EREGION_PI_64DD_REG 0x05FFFFFF +#define EREGION_PI_64DD_ROM 0x07FFFFFF +#define EREGION_PI_SRAM 0x0FFFFFFF +#define EREGION_PI_ROM 0xFFFFFFFF + +#define REGION_PI_UNKNOWN SREGION_PI_UNKNOWN ... EREGION_PI_UNKNOWN +#define REGION_PI_64DD_REG SREGION_PI_64DD_REG ... EREGION_PI_64DD_REG +#define REGION_PI_64DD_ROM SREGION_PI_64DD_ROM ... EREGION_PI_64DD_ROM +#define REGION_PI_SRAM SREGION_PI_SRAM ... EREGION_PI_SRAM +#define REGION_PI_ROM SREGION_PI_ROM ... EREGION_PI_ROM + +#define CART_ISVIEWER_FLUSH 0x13FF0014 +#define SREGION_CART_ISVIEWER_BUFFER 0x13FF0020 +#define EREGION_CART_ISVIEWER_BUFFER 0x13FFFFFF +#define CART_ISVIEWER_SIZE (EREGION_CART_ISVIEWER_BUFFER - SREGION_CART_ISVIEWER_BUFFER) +#define REGION_CART_ISVIEWER_BUFFER SREGION_CART_ISVIEWER_BUFFER ... EREGION_CART_ISVIEWER_BUFFER + constexpr u64 operator""_kb(unsigned long long int x) { return 1024ULL * x; } diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index f169e7a8..940bb082 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -195,6 +195,8 @@ u8 Mem::Read8(n64::Registers ®s, u32 paddr) { return mmio.rsp.dmem[BYTE_ADDRESS(mirrAddr)]; } } + case REGION_CART: + return mmio.pi.BusRead8(*this, paddr); case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: case 0x04600000 ... 0x048FFFFF: @@ -205,39 +207,15 @@ u8 Mem::Read8(n64::Registers ®s, u32 paddr) { int offs = 3 - (paddr & 3); return (w >> (offs * 8)) & 0xff; } - case CART_REGION_1_2: - paddr = (paddr + 2) & ~2; - return rom.cart[BYTE_ADDRESS(paddr) & rom.mask]; case PIF_ROM_REGION: return si.pif.bootrom[BYTE_ADDRESS(paddr) - PIF_ROM_REGION_START]; case PIF_RAM_REGION: return si.pif.ram[paddr - PIF_RAM_REGION_START]; case 0x00800000 ... 0x03FFFFFF: // unused case 0x04200000 ... 0x042FFFFF: // unused - case 0x04900000 ... 0x07FFFFFF: // unused + case 0x04900000 ... 0x04FFFFFF: // unused case 0x1FC00800 ... 0xFFFFFFFF: // unused return 0; - case CART_REGION_2_2: - switch (saveType) { - case SAVE_NONE: - Util::panic("Accessing cartridge backup with save type SAVE_NONE"); - break; - case SAVE_EEPROM_4k: - case SAVE_EEPROM_16k: - Util::panic("Accessing cartridge backup with save type SAVE_EEPROM"); - break; - case SAVE_FLASH_1m: - if(flash.flash.is_open()) { - return flash.Read8(paddr - CART_REGION_START_2_2); - } else { - Util::panic("Invalid backup Write8 if save data is not initialized"); - } - case SAVE_SRAM_256k: - if(sram.is_open()) { - return sram[paddr - CART_REGION_START_2_2]; - } - } - break; default: Util::panic("Unimplemented 8-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc); } @@ -267,16 +245,15 @@ u16 Mem::Read16(n64::Registers ®s, u32 paddr) { } case MMIO_REGION: return mmio.Read(paddr); - case CART_REGION_1_2: - paddr = (paddr + 2) & ~3; - return Util::ReadAccess(rom.cart, HALF_ADDRESS(paddr) & rom.mask); + case REGION_CART: + return mmio.pi.BusRead16(*this, paddr); case PIF_ROM_REGION: return Util::ReadAccess(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START); case PIF_RAM_REGION: return be16toh(Util::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x0FFFFFFF: + case 0x04900000 ... 0x04FFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0; default: @@ -308,24 +285,14 @@ u32 Mem::Read32(n64::Registers ®s, u32 paddr) { } case MMIO_REGION: return mmio.Read(paddr); - case CART_REGION_1_2: - return Util::ReadAccess(rom.cart, paddr & rom.mask); - case CART_REGION_2_2: - if(saveType == SAVE_NONE) { - return 0; - } else if (saveType == SAVE_SRAM_256k) { - return 0xffff'ffff; - } else if (saveType == SAVE_FLASH_1m) { - return flash.Read32(paddr - CART_REGION_START_2_2); - } else { - Util::panic("Cartridge backup Read32 with unknown save type!"); - } + case REGION_CART: + return mmio.pi.BusRead32(*this, paddr); case PIF_ROM_REGION: return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); case PIF_RAM_REGION: return be32toh(Util::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x07FFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0; + case 0x04900000 ... 0x04FFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0; default: Util::panic("Unimplemented 32-bit read at address {:08X} (PC = {:016X})", paddr, (u64) regs.pc); } @@ -355,15 +322,15 @@ u64 Mem::Read64(n64::Registers ®s, u32 paddr) { } case MMIO_REGION: return mmio.Read(paddr); - case CART_REGION_1_2: - return Util::ReadAccess(rom.cart, paddr & rom.mask); + case REGION_CART: + return mmio.pi.BusRead64(*this, paddr); case PIF_ROM_REGION: return Util::ReadAccess(si.pif.bootrom, paddr - PIF_ROM_REGION_START); case PIF_RAM_REGION: return be64toh(Util::ReadAccess(si.pif.ram, paddr - PIF_RAM_REGION_START)); case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x0FFFFFFF: + case 0x04900000 ... 0x04FFFFFF: case 0x1FC00800 ... 0xFFFFFFFF: return 0; default: @@ -397,7 +364,8 @@ void Mem::Write8(Registers& regs, u32 paddr, u32 val) { } break; case MMIO_REGION: Util::panic("MMIO Write8!"); - case CART_REGION_1_2: + case REGION_CART: + mmio.pi.BusWrite8(*this, paddr, val); break; case PIF_RAM_REGION: val = val << (8 * (3 - (paddr & 3))); @@ -405,32 +373,9 @@ void Mem::Write8(Registers& regs, u32 paddr, u32 val) { Util::WriteAccess(si.pif.ram, paddr, htobe32(val)); si.pif.ProcessCommands(*this); break; - case CART_REGION_2_2: - switch (saveType) { - case SAVE_NONE: - Util::panic("Accessing cartridge backup with save type SAVE_NONE"); - break; - case SAVE_EEPROM_4k: - case SAVE_EEPROM_16k: - Util::panic("Accessing cartridge backup with save type SAVE_EEPROM"); - break; - case SAVE_FLASH_1m: - if(flash.flash.is_open()) { - flash.Write8(paddr - CART_REGION_START_2_2, val); - } else { - Util::panic("Invalid backup Write8 if save data is not initialized"); - } - break; - case SAVE_SRAM_256k: - if(sram.is_open()) { - sram[paddr - CART_REGION_START_2_2] = val; - } - break; - } - break; case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x07FFFFFF: + case 0x04900000 ... 0x04FFFFFF: case PIF_ROM_REGION: case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: @@ -467,19 +412,18 @@ void Mem::Write16(Registers& regs, u32 paddr, u32 val) { } break; case MMIO_REGION: Util::panic("MMIO Write16!"); - case CART_REGION_1_2: - break; case PIF_RAM_REGION: val = val << (16 * !(paddr & 2)); paddr &= ~3; Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val)); si.pif.ProcessCommands(*this); break; - case CART_REGION_2_2: - Util::panic("Backup Write16!"); + case REGION_CART: + mmio.pi.BusWrite16(*this, paddr, val); + break; case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x07FFFFFF: + case 0x04900000 ... 0x04FFFFFF: case PIF_ROM_REGION: case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: @@ -515,42 +459,18 @@ void Mem::Write32(Registers& regs, u32 paddr, u32 val) { case MMIO_REGION: mmio.Write(*this, regs, paddr, val); break; - case 0x10000000 ... 0x13FF0013: break; - case 0x13FF0014: { - if(val < ISVIEWER_SIZE) { - char* message = (char*)calloc(val + 1, 1); - memcpy(message, isviewer, val); - fmt::print("{}", message); - free(message); - } - } break; - case 0x13FF0020 ... 0x13FFFFFF: - Util::WriteAccess(isviewer, paddr - 0x13FF0020, htobe32(val)); - break; - case 0x14000000 ... 0x1FBFFFFF: break; case PIF_RAM_REGION: Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe32(val)); si.pif.ProcessCommands(*this); break; case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x07FFFFFF: + case 0x04900000 ... 0x04FFFFFF: case PIF_ROM_REGION: case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break; - case CART_REGION_2_2: - if (saveType == SAVE_FLASH_1m) { - if(flash.flash.is_open()) { - flash.Write32(paddr - CART_REGION_START_2_2, val); - } else { - Util::panic("Invalid write to cartridge backup if save data is not initialized!"); - } - } else if (saveType == SAVE_SRAM_256k) { - break; - } else { - Util::panic("Invalid cartridge backup Write32 with save type {} (addr {:08X})", static_cast(saveType), - paddr); - } + case REGION_CART: + mmio.pi.BusWrite32(*this, paddr, val); break; default: Util::panic("Unimplemented 32-bit write at address {:08X} with value {:0X} (PC = {:016X})", paddr, val, (u64)regs.pc); } @@ -581,20 +501,19 @@ void Mem::Write64(Registers& regs, u32 paddr, u64 val) { } break; case MMIO_REGION: Util::panic("MMIO Write64!"); - case CART_REGION_1_2: - break; case PIF_RAM_REGION: Util::WriteAccess(si.pif.ram, paddr - PIF_RAM_REGION_START, htobe64(val)); si.pif.ProcessCommands(*this); break; + case REGION_CART: + mmio.pi.BusWrite64(*this, paddr, val); + break; case 0x00800000 ... 0x03FFFFFF: case 0x04200000 ... 0x042FFFFF: - case 0x04900000 ... 0x07FFFFFF: + case 0x04900000 ... 0x04FFFFFF: case 0x1FC00000 ... 0x1FC007BF: case 0x1FC00800 ... 0x7FFFFFFF: case 0x80000000 ... 0xFFFFFFFF: break; - case CART_REGION_2_2: - Util::panic("Backup Write64!"); default: Util::panic("Unimplemented 64-bit write at address {:08X} with value {:0X} (PC = {:016X})", paddr, val, (u64) regs.pc); @@ -602,6 +521,93 @@ void Mem::Write64(Registers& regs, u32 paddr, u64 val) { } } +u32 Mem::BackupRead32(u32 addr) { + switch(saveType) { + case SAVE_NONE: return 0; + case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: + Util::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); + return 0; + case SAVE_FLASH_1m: + if(flash.flash.is_open()) { + return flash.Read32(addr); + } else { + Util::panic("Invalid backup Read32 if save data is not initialized"); + } + case SAVE_SRAM_256k: + return 0xFFFFFFFF; + default: + Util::panic("Backup read word with unknown save type"); + } +} + +void Mem::BackupWrite32(u32 addr, u32 val) { + switch(saveType) { + case SAVE_NONE: + Util::panic("Accessing cartridge with save type SAVE_NONE in write word"); + case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: + Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); + case SAVE_FLASH_1m: + if(flash.flash.is_open()) { + flash.Write32(addr, val); + } else { + Util::panic("Invalid backup Write32 if save data is not initialized"); + } + break; + case SAVE_SRAM_256k: + break; + default: + Util::panic("Backup read word with unknown save type"); + } +} + +u8 Mem::BackupRead8(u32 addr) { + switch(saveType) { + case SAVE_NONE: return 0; + case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: + Util::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read"); + return 0; + case SAVE_FLASH_1m: + if(flash.flash.is_open()) { + return flash.Read8(addr); + } else { + Util::panic("Invalid backup Read8 if save data is not initialized"); + } + case SAVE_SRAM_256k: + if(sram.is_open()) { + return sram[addr & 0x8000]; + } else { + Util::panic("Invalid backup Read8 if save data is not initialized"); + } + default: + Util::panic("Backup read word with unknown save type"); + } +} + +void Mem::BackupWrite8(u32 addr, u8 val) { + switch(saveType) { + case SAVE_NONE: + Util::panic("Accessing cartridge with save type SAVE_NONE in write word"); + case SAVE_EEPROM_4k: case SAVE_EEPROM_16k: + Util::panic("Accessing cartridge with save type SAVE_EEPROM in write word"); + case SAVE_FLASH_1m: + if(flash.flash.is_open()) { + flash.Write8(addr, val); + } else { + Util::panic("Invalid backup Write8 if save data is not initialized"); + } + break; + case SAVE_SRAM_256k: + if(sram.is_open()) { + sram[addr & 0x8000] = val; + } else { + Util::panic("Invalid backup Write8 if save data is not initialized"); + } + break; + default: + Util::panic("Backup read word with unknown save type"); + } +} + std::vector Mem::Serialize() { std::vector res{}; diff --git a/src/backend/core/Mem.hpp b/src/backend/core/Mem.hpp index 5bd4543c..146e7624 100644 --- a/src/backend/core/Mem.hpp +++ b/src/backend/core/Mem.hpp @@ -192,6 +192,11 @@ struct Mem { void Write32(Registers&, u32, u32); void Write64(Registers&, u32, u64); + u32 BackupRead32(u32); + void BackupWrite32(u32, u32); + u8 BackupRead8(u32); + void BackupWrite8(u32, u8); + MMIO mmio; FORCE_INLINE void DumpRDRAM() const { diff --git a/src/backend/core/mmio/PI.cpp b/src/backend/core/mmio/PI.cpp index 383e5ee3..5d260e5a 100644 --- a/src/backend/core/mmio/PI.cpp +++ b/src/backend/core/mmio/PI.cpp @@ -16,6 +16,230 @@ void PI::Reset() { wrLen = 0; } +auto PI::BusRead8(Mem& mem, u32 addr) const -> u8 { + // TODO: Latch with CPU stall + switch (addr) { + case REGION_PI_UNKNOWN: + Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_64DD_REG: + Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_64DD_ROM: + Util::warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_SRAM: + return mem.BackupRead8(addr - SREGION_PI_SRAM); + case REGION_PI_ROM: { + // round to nearest 4 byte boundary, keeping old LSB + addr = (addr + 2) & ~2; + 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); + return 0xFF; + } + return mem.rom.cart[index]; + } + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +void PI::BusWrite8(Mem& mem, u32 addr, u32 val) { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + return; + case REGION_PI_64DD_REG: + if (addr == 0x05000020) { + fprintf(stderr, "%c", val); + } else { + Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr); + } + return; + case REGION_PI_64DD_ROM: + Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + return; + case REGION_PI_SRAM: + mem.BackupWrite8(addr - SREGION_PI_SRAM, val); + return; + case REGION_PI_ROM: + Util::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + return; + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +auto PI::BusRead16(Mem& mem, u32 addr) const -> u16 { + // TODO: Latch with CPU stall + switch (addr) { + case REGION_PI_UNKNOWN: + Util::warn("Reading half from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_64DD_REG: + Util::warn("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_64DD_ROM: + Util::warn("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_SRAM: + Util::panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr); + case REGION_PI_ROM: { + // round to nearest 4 byte boundary, keeping old LSB + addr = (addr + 2) & ~3; + u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM; + if (index > mem.rom.size - 1) { + 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); + return 0xFFFF; + } + return Util::ReadAccess(mem.rom.cart, index); + } + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +void PI::BusWrite16(Mem& mem, u32 addr, u16 val) { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + return; + case REGION_PI_64DD_REG: + Util::warn("Writing half 0x{:04X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr); + return; + case REGION_PI_64DD_ROM: + Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + return; + case REGION_PI_SRAM: + Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr); + return; + case REGION_PI_ROM: + Util::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + return; + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +auto PI::BusRead32(Mem& mem, u32 addr) const -> u32 { + // TODO: Latch with CPU stall + switch (addr) { + case REGION_PI_UNKNOWN: + Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_64DD_REG: + Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_64DD_ROM: + Util::warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, returning FF because it is not emulated", addr); + return 0xFF; + case REGION_PI_SRAM: + return mem.BackupRead32(addr - SREGION_PI_SRAM); + case REGION_PI_ROM: { + u32 index = addr - SREGION_PI_ROM; + if (index > mem.rom.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)); + case CART_ISVIEWER_FLUSH: + Util::panic("Read from ISViewer flush!"); + } + Util::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index); + return 0; + } else { + return Util::ReadAccess(mem.rom.cart, index); + } + } + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +void PI::BusWrite32(Mem& mem, u32 addr, u32 val) { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + return; + case REGION_PI_64DD_REG: + Util::warn("Writing word 0x{:08X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val, addr); + return; + case REGION_PI_64DD_ROM: + Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + return; + case REGION_PI_SRAM: + mem.BackupWrite32(addr - SREGION_PI_SRAM, val); + return; + case REGION_PI_ROM: + switch (addr) { + case REGION_CART_ISVIEWER_BUFFER: + Util::WriteAccess(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER, be32toh(val)); + break; + case CART_ISVIEWER_FLUSH: { + if (val < CART_ISVIEWER_SIZE) { + char* message = (char*)malloc(val + 1); + memcpy(message, mem.isviewer, val); + message[val] = '\0'; + printf("%s", message); + free(message); + } else { + Util::panic("ISViewer buffer size is emulated at {} bytes, but received a flush command for {} bytes!", CART_ISVIEWER_SIZE, val); + } + break; + } + default: + Util::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + } + return; + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +auto PI::BusRead64(Mem& mem, u32 addr) const -> u64 { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", addr); + return 0xFFFFFFFFFFFFFFFF; + case REGION_PI_64DD_REG: + Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", addr); + return 0xFFFFFFFFFFFFFFFF; + case REGION_PI_64DD_ROM: + Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", addr); + return 0xFFFFFFFFFFFFFFFF; + case REGION_PI_SRAM: + Util::warn("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr); + return 0xFFFFFFFFFFFFFFFF; + case REGION_PI_ROM: { + u32 index = addr - SREGION_PI_ROM; + if (index > mem.rom.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); + } + default: + Util::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr); + } +} + +void PI::BusWrite64(Mem& mem, u32 addr, u64 val) { + switch (addr) { + case REGION_PI_UNKNOWN: + Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr); + case REGION_PI_64DD_REG: + Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", val, addr); + case REGION_PI_64DD_ROM: + Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr); + case REGION_PI_SRAM: + Util::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr); + case REGION_PI_ROM: + Util::warn("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr); + break; + default: + Util::panic("Should never end up here! Access to address %08X which did not match any PI bus regions!", addr); + } +} + auto PI::Read(MI& mi, u32 addr) const -> u32 { switch(addr) { case 0x04600000: return dramAddr; @@ -45,12 +269,12 @@ auto PI::Read(MI& mi, u32 addr) const -> u32 { FORCE_INLINE u8 PIGetDomain(u32 address) { switch (address) { - case 0x00000000 ... 0x04FFFFFF: - case CART_REGION_1_1: - case 0x10000000 ... 0xFFFFFFFF: + case REGION_PI_UNKNOWN: + case REGION_PI_64DD_ROM: + case REGION_PI_ROM: return 1; - case CART_REGION_2_1: - case CART_REGION_2_2: + case REGION_PI_64DD_REG: + case REGION_PI_SRAM: return 2; default: Util::panic("Unknown PI domain for address {:08X}!", address); @@ -79,7 +303,7 @@ FORCE_INLINE u32 PIAccessTiming(PI& pi, u8 domain, u32 length) { page_size = std::pow(2, (pi.pi_bsd_dom2_pgs + 2)); break; default: - Util::panic("Unknown PI domain: %d\n", domain); + Util::panic("Unknown PI domain: {}\n", domain); } pages = ceil((double)length / page_size); diff --git a/src/backend/core/mmio/PI.hpp b/src/backend/core/mmio/PI.hpp index 69f66830..0e034406 100644 --- a/src/backend/core/mmio/PI.hpp +++ b/src/backend/core/mmio/PI.hpp @@ -12,6 +12,14 @@ struct PI { void Reset(); auto Read(MI&, u32) const -> u32; void Write(Mem&, Registers&, u32, u32); + auto BusRead8(Mem&, u32) const -> u8; + void BusWrite8(Mem&, u32, u32); + auto BusRead16(Mem&, u32) const -> u16; + void BusWrite16(Mem&, u32, u16); + auto BusRead32(Mem&, u32) const -> u32; + void BusWrite32(Mem&, u32, u32); + auto BusRead64(Mem&, u32) const -> u64; + void BusWrite64(Mem&, u32, u64); bool dmaBusy{}, ioBusy{}; u32 dramAddr{}, cartAddr{}, dramAddrInternal{}, cartAddrInternal{}; u32 rdLen{}, wrLen{};