This repository has been archived on 2026-08-27. You can view files and clone it, but cannot push or open issues or pull requests.
gopher64-netplay/src/device/memory.rs
2025-03-16 10:10:16 +01:00

178 lines
7.8 KiB
Rust

use crate::{device, savestates};
const MM_RDRAM_DRAM: usize = 0x00000000;
const MM_RDRAM_REGS: usize = 0x03f00000;
const MM_RSP_MEM: usize = 0x04000000;
const MM_RSP_REGS: usize = 0x04040000;
const MM_RSP_REGS_PC: usize = 0x04080000;
const MM_DPC_REGS: usize = 0x04100000;
const MM_DPS_REGS: usize = 0x04200000;
const MM_MI_REGS: usize = 0x04300000;
const MM_VI_REGS: usize = 0x04400000;
const MM_AI_REGS: usize = 0x04500000;
const MM_PI_REGS: usize = 0x04600000;
const MM_RI_REGS: usize = 0x04700000;
const MM_SI_REGS: usize = 0x04800000;
//const MM_DOM2_ADDR1: usize = 0x05000000;
pub const MM_DOM2_ADDR2: usize = 0x08000000;
pub const MM_CART_ROM: usize = 0x10000000;
pub const MM_PIF_MEM: usize = 0x1fc00000;
//const MM_DOM1_ADDR3: usize = 0x1fd00000;
const MM_IS_VIEWER: usize = 0x13ff0000;
pub const MM_SC64_BUFFER: usize = 0x1ffe0000;
const MM_SC64_REGS: usize = 0x1fff0000;
#[derive(PartialEq)]
pub enum AccessType {
Write,
Read,
}
#[derive(Copy, Clone, Default)]
pub enum AccessSize {
#[default]
None = 0,
Word = 4,
Dword = 8,
Dcache = 16,
Icache = 32,
}
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Memory {
#[serde(skip, default = "savestates::default_memory_read_fast")]
pub fast_read: [fn(&device::Device, u64, AccessSize) -> u32; 0x2000], // fast_read is used for lookups that try to detect idle loops
#[serde(skip, default = "savestates::default_memory_read")]
pub memory_map_read: [fn(&mut device::Device, u64, AccessSize) -> u32; 0x2000],
#[serde(skip, default = "savestates::default_memory_write")]
pub memory_map_write: [fn(&mut device::Device, u64, u32, u32); 0x2000],
#[serde(with = "serde_big_array::BigArray")]
pub icache: [device::cache::ICache; 512],
#[serde(with = "serde_big_array::BigArray")]
pub dcache: [device::cache::DCache; 512],
}
pub fn masked_write_32(dst: &mut u32, value: u32, mask: u32) {
*dst = (*dst & !mask) | (value & mask);
}
pub fn masked_write_64(dst: &mut u64, value: u64, mask: u64) {
*dst = (*dst & !mask) | (value & mask);
}
pub fn translate_address(
device: &mut device::Device,
address: u64,
access_type: AccessType,
) -> (u64, bool, bool) {
if (address & 0xc0000000) != 0x80000000 {
return device::tlb::get_physical_address(device, address, access_type);
}
(address & 0x1FFFFFFF, address & 0x20000000 == 0, false)
}
pub fn data_read(
device: &mut device::Device,
phys_address: u64,
access_size: AccessSize,
cached: bool,
) -> u32 {
if cached {
device::cache::dcache_read(device, phys_address)
} else {
device.memory.memory_map_read[(phys_address >> 16) as usize](
device,
phys_address,
access_size,
)
}
}
pub fn data_write(
device: &mut device::Device,
phys_address: u64,
value: u32,
mask: u32,
cached: bool,
) {
if cached {
device::cache::dcache_write(device, phys_address, value, mask)
} else {
device.memory.memory_map_write[(phys_address >> 16) as usize](
device,
phys_address,
value,
mask,
)
}
}
pub fn init(device: &mut device::Device) {
for i in 0..0x2000 {
if (MM_RDRAM_DRAM >> 16..=(MM_RDRAM_DRAM + 0x03EFFFFF) >> 16).contains(&i) {
device.memory.fast_read[i] = device::rdram::read_mem_fast;
device.memory.memory_map_read[i] = device::rdram::read_mem;
device.memory.memory_map_write[i] = device::rdram::write_mem;
} else if (MM_RDRAM_REGS >> 16..=(MM_RDRAM_REGS + 0xFFFFF) >> 16).contains(&i) {
device.memory.memory_map_read[i] = device::rdram::read_regs;
device.memory.memory_map_write[i] = device::rdram::write_regs;
} else if (MM_RSP_MEM >> 16..=(MM_RSP_MEM + 0x3FFFF) >> 16).contains(&i) {
device.memory.fast_read[i] = device::rsp_interface::read_mem_fast;
device.memory.memory_map_read[i] = device::rsp_interface::read_mem;
device.memory.memory_map_write[i] = device::rsp_interface::write_mem;
} else if i >= MM_RSP_REGS >> 16 && i <= (MM_RSP_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::rsp_interface::read_regs;
device.memory.memory_map_write[i] = device::rsp_interface::write_regs;
} else if i >= MM_RSP_REGS_PC >> 16 && i <= (MM_RSP_REGS_PC + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::rsp_interface::read_regs2;
device.memory.memory_map_write[i] = device::rsp_interface::write_regs2;
} else if i >= MM_DPC_REGS >> 16 && i <= (MM_DPC_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::rdp::read_regs_dpc;
device.memory.memory_map_write[i] = device::rdp::write_regs_dpc;
} else if i >= MM_DPS_REGS >> 16 && i <= (MM_DPS_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::rdp::read_regs_dps;
device.memory.memory_map_write[i] = device::rdp::write_regs_dps;
} else if i >= MM_MI_REGS >> 16 && i <= (MM_MI_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::mi::read_regs;
device.memory.memory_map_write[i] = device::mi::write_regs;
} else if i >= MM_VI_REGS >> 16 && i <= (MM_VI_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::vi::read_regs;
device.memory.memory_map_write[i] = device::vi::write_regs;
} else if i >= MM_AI_REGS >> 16 && i <= (MM_AI_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::ai::read_regs;
device.memory.memory_map_write[i] = device::ai::write_regs;
} else if i >= MM_PI_REGS >> 16 && i <= (MM_PI_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::pi::read_regs;
device.memory.memory_map_write[i] = device::pi::write_regs;
} else if i >= MM_RI_REGS >> 16 && i <= (MM_RI_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::ri::read_regs;
device.memory.memory_map_write[i] = device::ri::write_regs;
} else if i >= MM_SI_REGS >> 16 && i <= (MM_SI_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::si::read_regs;
device.memory.memory_map_write[i] = device::si::write_regs;
} else if (MM_DOM2_ADDR2 >> 16..=(MM_DOM2_ADDR2 + 0x1FFFF) >> 16).contains(&i) {
device.memory.memory_map_read[i] = device::cart::sram::read_mem;
device.memory.memory_map_write[i] = device::cart::sram::write_mem;
} else if device.cart.rom.len() <= MM_IS_VIEWER - MM_CART_ROM
&& i >= MM_IS_VIEWER >> 16
&& i <= (MM_IS_VIEWER + 0xFFFF) >> 16
{
device.memory.memory_map_read[i] = device::is_viewer::read_mem;
device.memory.memory_map_write[i] = device::is_viewer::write_mem;
} else if (MM_CART_ROM >> 16..=(MM_CART_ROM + 0x0FBFFFFF) >> 16).contains(&i) {
device.memory.fast_read[i] = device::cart::rom::read_mem_fast;
device.memory.memory_map_read[i] = device::cart::rom::read_mem;
device.memory.memory_map_write[i] = device::cart::rom::write_mem;
} else if i >= MM_PIF_MEM >> 16 && i <= (MM_PIF_MEM + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::pif::read_mem;
device.memory.memory_map_write[i] = device::pif::write_mem;
} else if i >= MM_SC64_BUFFER >> 16 && i <= (MM_SC64_BUFFER + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::cart::sc64::read_mem;
device.memory.memory_map_write[i] = device::cart::sc64::write_mem;
} else if i >= MM_SC64_REGS >> 16 && i <= (MM_SC64_REGS + 0xFFFF) >> 16 {
device.memory.memory_map_read[i] = device::cart::sc64::read_regs;
device.memory.memory_map_write[i] = device::cart::sc64::write_regs;
}
}
}