From 9980302d3747413edbfaee0dd9a7716dbfb2301c Mon Sep 17 00:00:00 2001 From: Logan McNaughton <848146+loganmc10@users.noreply.github.com> Date: Sun, 23 Feb 2025 13:10:50 +0100 Subject: [PATCH] more tpak code (#276) * more tpak code * more --- src/device/controller/gbcart.rs | 109 ++++++++++++++++----------- src/device/controller/transferpak.rs | 36 +++++---- src/savestates.rs | 4 +- 3 files changed, 85 insertions(+), 64 deletions(-) diff --git a/src/device/controller/gbcart.rs b/src/device/controller/gbcart.rs index aedc483..29297e7 100644 --- a/src/device/controller/gbcart.rs +++ b/src/device/controller/gbcart.rs @@ -1,5 +1,17 @@ use crate::device; +#[derive(Default, serde::Serialize, serde::Deserialize)] +pub struct GbCart { + pub enabled: bool, + #[serde(skip)] + pub rom: Vec, + pub ram: Vec, + pub cart_type: device::controller::gbcart::CartType, + pub ram_enabled: bool, + pub ram_bank: u16, + pub rom_bank: u16, +} + #[derive(Default, Copy, Clone, serde::Serialize, serde::Deserialize)] pub enum CartType { #[default] @@ -11,36 +23,36 @@ pub enum CartType { fn write_mbc3( pif_ram: &mut [u8], - pak: &mut device::controller::transferpak::TransferPak, + cart: &mut device::controller::gbcart::GbCart, address: u16, data: usize, size: usize, ) { let value = pif_ram[data + size - 1]; if address < 0x2000 { - pak.ram_enabled = value & 0xf == 0xa; + cart.ram_enabled = value & 0xf == 0xa; } else if address < 0x4000 { let bank = value & 0x7f; if bank == 0 { - pak.bank = 1; + cart.rom_bank = 1; } else { - pak.bank = bank as u16; + cart.rom_bank = bank as u16; } } else if address < 0x6000 { - pak.ram_bank = value as u16; + cart.ram_bank = value as u16; } else if address < 0x8000 { println!("MBC3 RTC latch") } else if (0xa000..0xc000).contains(&address) { - if !pak.ram_enabled { + if !cart.ram_enabled { return; } - if pak.ram_bank < 0x8 { - let banked_address = (pak.ram_bank << 13) | (address & 0x1FFF); + if cart.ram_bank < 0x8 { + let banked_address = (cart.ram_bank << 13) | (address & 0x1FFF); for i in 0..size { - pak.ram[banked_address as usize + i] = pif_ram[data + i]; + cart.ram[banked_address as usize + i] = pif_ram[data + i]; } } else { - panic!("Unsupported ram bank {:x}", pak.ram_bank); + panic!("Unsupported ram bank {:x}", cart.ram_bank); } } else { panic!("Unsupported write address {:x}", address); @@ -49,34 +61,34 @@ fn write_mbc3( fn read_mbc3( pif_ram: &mut [u8], - pak: &mut device::controller::transferpak::TransferPak, + cart: &mut device::controller::gbcart::GbCart, address: u16, data: usize, size: usize, ) { if address < 0x4000 { for i in 0..size { - pif_ram[data + i] = pak.rom[address as usize + i]; + pif_ram[data + i] = cart.rom[address as usize + i]; } } else if address < 0x8000 { - let banked_address = (pak.bank << 14) | (address & 0x3FFF); + let banked_address = (cart.rom_bank << 14) | (address & 0x3FFF); for i in 0..size { - pif_ram[data + i] = pak.rom[banked_address as usize + i]; + pif_ram[data + i] = cart.rom[banked_address as usize + i]; } } else if address < 0xc000 { - if !pak.ram_enabled { + if !cart.ram_enabled { for i in 0..size { pif_ram[data + i] = 0xff; } return; } - if pak.ram_bank < 0x8 { - let banked_address = (pak.ram_bank << 13) | (address & 0x1FFF); + if cart.ram_bank < 0x8 { + let banked_address = (cart.ram_bank << 13) | (address & 0x1FFF); for i in 0..size { - pif_ram[data + i] = pak.ram[banked_address as usize + i]; + pif_ram[data + i] = cart.ram[banked_address as usize + i]; } } else { - panic!("Unsupported ram bank {:x}", pak.ram_bank); + panic!("Unsupported ram bank {:x}", cart.ram_bank); } } else { panic!("Unsupported read address {:x}", address); @@ -85,26 +97,28 @@ fn read_mbc3( fn write_mbc5( pif_ram: &mut [u8], - pak: &mut device::controller::transferpak::TransferPak, + cart: &mut device::controller::gbcart::GbCart, address: u16, data: usize, size: usize, ) { let value = pif_ram[data + size - 1]; if address < 0x2000 { - pak.ram_enabled = value & 0xf == 0xa; + cart.ram_enabled = value & 0xf == 0xa; + } else if address < 0x4000 { + println!("Unknown MBC5 write address {:x}", address); } else if address < 0x6000 { - pak.ram_bank = (value & 0xf) as u16; + cart.ram_bank = (value & 0xf) as u16; } else if address < 0xa000 { println!("Unknown MBC5 write address {:x}", address); } else if (0xa000..0xc000).contains(&address) { - if !pak.ram_enabled { + if !cart.ram_enabled { return; } - let banked_address = (pak.ram_bank << 13) | (address & 0x1FFF); + let banked_address = (cart.ram_bank << 13) | (address & 0x1FFF); for i in 0..size { - pak.ram[banked_address as usize + i] = pif_ram[data + i]; + cart.ram[banked_address as usize + i] = pif_ram[data + i]; } } else { panic!("Unsupported write address {:x}", address); @@ -113,31 +127,31 @@ fn write_mbc5( fn read_mbc5( pif_ram: &mut [u8], - pak: &mut device::controller::transferpak::TransferPak, + cart: &mut device::controller::gbcart::GbCart, address: u16, data: usize, size: usize, ) { if address < 0x4000 { for i in 0..size { - pif_ram[data + i] = pak.rom[address as usize + i]; + pif_ram[data + i] = cart.rom[address as usize + i]; } } else if address < 0x8000 { - let banked_address = (pak.bank << 14) | (address & 0x3FFF); + let banked_address = (cart.rom_bank << 14) | (address & 0x3FFF); for i in 0..size { - pif_ram[data + i] = pak.rom[banked_address as usize + i]; + pif_ram[data + i] = cart.rom[banked_address as usize + i]; } - } else if address < 0xc000 { - if !pak.ram_enabled { + } else if (0xa000..0xc000).contains(&address) { + if !cart.ram_enabled { for i in 0..size { pif_ram[data + i] = 0xff; } return; } - let banked_address = (pak.ram_bank << 13) | (address & 0x1FFF); + let banked_address = (cart.ram_bank << 13) | (address & 0x1FFF); for i in 0..size { - pif_ram[data + i] = pak.ram[banked_address as usize + i]; + pif_ram[data + i] = cart.ram[banked_address as usize + i]; } } else { panic!("Unsupported read address {:x}", address); @@ -146,30 +160,39 @@ fn read_mbc5( pub fn read( pif_ram: &mut [u8], - pak: &mut device::controller::transferpak::TransferPak, + cart: &mut device::controller::gbcart::GbCart, address: u16, data: usize, size: usize, ) { - match pak.cart_type { - CartType::MBC3RamBatt => read_mbc3(pif_ram, pak, address, data, size), - CartType::MBC3RamBattRtc => read_mbc3(pif_ram, pak, address, data, size), - CartType::MBC5RamBatt => read_mbc5(pif_ram, pak, address, data, size), + if !cart.enabled { + for i in 0..size { + pif_ram[data + i] = 0x00; + } + return; + } + match cart.cart_type { + CartType::MBC3RamBatt => read_mbc3(pif_ram, cart, address, data, size), + CartType::MBC3RamBattRtc => read_mbc3(pif_ram, cart, address, data, size), + CartType::MBC5RamBatt => read_mbc5(pif_ram, cart, address, data, size), _ => panic!("Unsupported cart type"), } } pub fn write( pif_ram: &mut [u8], - pak: &mut device::controller::transferpak::TransferPak, + cart: &mut device::controller::gbcart::GbCart, address: u16, data: usize, size: usize, ) { - match pak.cart_type { - CartType::MBC3RamBatt => write_mbc3(pif_ram, pak, address, data, size), - CartType::MBC3RamBattRtc => write_mbc3(pif_ram, pak, address, data, size), - CartType::MBC5RamBatt => write_mbc5(pif_ram, pak, address, data, size), + if !cart.enabled { + return; + } + match cart.cart_type { + CartType::MBC3RamBatt => write_mbc3(pif_ram, cart, address, data, size), + CartType::MBC3RamBattRtc => write_mbc3(pif_ram, cart, address, data, size), + CartType::MBC5RamBatt => write_mbc5(pif_ram, cart, address, data, size), _ => panic!("Unsupported cart type"), } } diff --git a/src/device/controller/transferpak.rs b/src/device/controller/transferpak.rs index 08fcb70..7b1512f 100644 --- a/src/device/controller/transferpak.rs +++ b/src/device/controller/transferpak.rs @@ -3,15 +3,9 @@ use crate::device; #[derive(Default, serde::Serialize, serde::Deserialize)] pub struct TransferPak { pub enabled: bool, - pub cart_enabled: bool, pub reset_state: u8, pub bank: u16, - #[serde(skip)] - pub rom: Vec, - pub ram: Vec, - pub cart_type: device::controller::gbcart::CartType, - pub ram_enabled: bool, - pub ram_bank: u16, + pub cart: device::controller::gbcart::GbCart, } pub fn read(device: &mut device::Device, channel: usize, address: u16, data: usize, size: usize) { @@ -38,7 +32,7 @@ pub fn read(device: &mut device::Device, channel: usize, address: u16, data: usi match address >> 12 { 0xB => { let mut value = 0; - if pak.cart_enabled { + if pak.cart.enabled { value |= 1 << 0; } value |= (pak.reset_state & 3) << 2; @@ -46,11 +40,11 @@ pub fn read(device: &mut device::Device, channel: usize, address: u16, data: usi value |= 1 << 7; } - if pak.cart_enabled && pak.reset_state == 3 { + if pak.cart.enabled && pak.reset_state == 3 { pak.reset_state = 2 - } else if !pak.cart_enabled && pak.reset_state == 2 { + } else if !pak.cart.enabled && pak.reset_state == 2 { pak.reset_state = 1 - } else if !pak.cart_enabled && pak.reset_state == 1 { + } else if !pak.cart.enabled && pak.reset_state == 1 { pak.reset_state = 0 } for i in 0..size { @@ -60,7 +54,7 @@ pub fn read(device: &mut device::Device, channel: usize, address: u16, data: usi 0xC..=0xF => { device::controller::gbcart::read( &mut device.pif.ram, - pak, + &mut pak.cart, (address & 0x3fff) | ((pak.bank & 0x3) * 0x4000), data, size, @@ -84,8 +78,8 @@ pub fn write(device: &mut device::Device, channel: usize, address: u16, data: us } 0x84 => { if !pak.enabled { - pak.bank = 0; - pak.cart_enabled = false; + pak.bank = 3; + pak.cart.enabled = false; pak.reset_state = 0; } pak.enabled = true; @@ -110,19 +104,23 @@ pub fn write(device: &mut device::Device, channel: usize, address: u16, data: us } 0xB => { if value & 1 != 0 { - if !pak.cart_enabled { + if !pak.cart.enabled { pak.reset_state = 3; - pak.cart_type = device::controller::gbcart::get_cart_type(pak.rom[0x147]); + pak.cart.rom_bank = 1; + pak.cart.ram_bank = 0; + pak.cart.ram_enabled = false; + pak.cart.cart_type = + device::controller::gbcart::get_cart_type(pak.cart.rom[0x147]); } - pak.cart_enabled = true; + pak.cart.enabled = true; } else { - pak.cart_enabled = false; + pak.cart.enabled = false; } } 0xC..=0xF => { device::controller::gbcart::write( &mut device.pif.ram, - pak, + &mut pak.cart, (address & 0x3fff) | ((pak.bank & 0x3) * 0x4000), data, size, diff --git a/src/savestates.rs b/src/savestates.rs index 16943cf..3f9215c 100644 --- a/src/savestates.rs +++ b/src/savestates.rs @@ -110,11 +110,11 @@ pub fn load_savestate(device: &mut device::Device) { let mut tpak_rom = [vec![], vec![], vec![], vec![]]; for (i, item) in tpak_rom.iter_mut().enumerate() { - *item = device.transferpaks[i].rom.clone(); + *item = device.transferpaks[i].cart.rom.clone(); } device.transferpaks = state.transferpaks; for (i, item) in tpak_rom.iter().enumerate() { - device.transferpaks[i].rom = item.clone(); + device.transferpaks[i].cart.rom = item.clone(); } device::memory::init(device);