From df8d7d9ff0c43b7bb13e962733b91715bbba4104 Mon Sep 17 00:00:00 2001 From: Logan McNaughton <848146+loganmc10@users.noreply.github.com> Date: Fri, 1 May 2026 21:32:08 +0200 Subject: [PATCH] allow single controller mpk files (#820) --- src/device.rs | 1 + src/device/cart.rs | 4 ---- src/device/cart/sc64.rs | 4 ---- src/device/cart/sram.rs | 16 ++-------------- src/device/controller/mempak.rs | 11 ++++++----- src/ui/storage.rs | 7 +++++++ 6 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/device.rs b/src/device.rs index 7b00360..fad89f5 100644 --- a/src/device.rs +++ b/src/device.rs @@ -82,6 +82,7 @@ pub fn run_game(device: &mut Device, rom_contents: &[u8], game_settings: ui::Gam ui::storage::init(&mut device.ui, &device.cart.rom); ui::storage::load_saves(&mut device.ui, &mut device.netplay); + ui::storage::format_saves(device); if !retroachievements::get_hardcore() { cheats::init(device, game_settings.cheats); diff --git a/src/device/cart.rs b/src/device/cart.rs index b6bb0f2..2933309 100644 --- a/src/device/cart.rs +++ b/src/device/cart.rs @@ -130,8 +130,6 @@ pub fn format_eeprom(device: &mut device::Device) { fn eeprom_read_block(device: &mut device::Device, block: usize, offset: usize) { let address = device.pif.ram[block] as usize * EEPROM_BLOCK_SIZE; - format_eeprom(device); - device.pif.ram[offset..offset + EEPROM_BLOCK_SIZE].copy_from_slice( &device.ui.storage.saves.eeprom.data[address..address + EEPROM_BLOCK_SIZE], ); @@ -140,8 +138,6 @@ fn eeprom_read_block(device: &mut device::Device, block: usize, offset: usize) { fn eeprom_write_block(device: &mut device::Device, block: usize, offset: usize, status: usize) { let address = device.pif.ram[block] as usize * EEPROM_BLOCK_SIZE; - format_eeprom(device); - device.ui.storage.saves.eeprom.data[address..address + EEPROM_BLOCK_SIZE] .copy_from_slice(&device.pif.ram[offset..offset + EEPROM_BLOCK_SIZE]); diff --git a/src/device/cart/sc64.rs b/src/device/cart/sc64.rs index e19f2c0..32b78ce 100644 --- a/src/device/cart/sc64.rs +++ b/src/device/cart/sc64.rs @@ -376,7 +376,6 @@ pub fn read_mem( _access_size: device::memory::AccessSize, ) -> u32 { if address & 0x2000 != 0 { - device::cart::format_eeprom(device); let masked_address = address as usize & SC64_EEPROM_MASK; u32::from_be_bytes( device.ui.storage.saves.eeprom.data[masked_address..masked_address + 4] @@ -395,7 +394,6 @@ pub fn read_mem( pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u32) { if address & 0x2000 != 0 { - device::cart::format_eeprom(device); let masked_address = address as usize & SC64_EEPROM_MASK; let mut data = u32::from_be_bytes( device.ui.storage.saves.eeprom.data[masked_address..masked_address + 4] @@ -427,7 +425,6 @@ pub fn dma_read( ) -> u64 { dram_addr &= device::rdram::RDRAM_MASK as u32; let buffer = if cart_addr & 0x2000 != 0 { - device::cart::format_eeprom(device); cart_addr &= SC64_EEPROM_MASK as u32; ui::storage::schedule_save(device, ui::storage::SaveTypes::Eeprom4k); &mut device.ui.storage.saves.eeprom.data @@ -459,7 +456,6 @@ pub fn dma_write( ) -> u64 { dram_addr &= device::rdram::RDRAM_MASK as u32; let buffer = if cart_addr & 0x2000 != 0 { - device::cart::format_eeprom(device); cart_addr &= SC64_EEPROM_MASK as u32; &device.ui.storage.saves.eeprom.data } else { diff --git a/src/device/cart/sram.rs b/src/device/cart/sram.rs index ef17f8c..4e82bec 100644 --- a/src/device/cart/sram.rs +++ b/src/device/cart/sram.rs @@ -28,13 +28,13 @@ pub struct Flashram { pub silicon_id: [u32; 2], } -fn format_sram(device: &mut device::Device) { +pub fn format_sram(device: &mut device::Device) { if device.ui.storage.saves.sram.data.len() < SRAM_SIZE { device.ui.storage.saves.sram.data.resize(SRAM_SIZE, 0xFF) } } -fn format_flash(device: &mut device::Device) { +pub fn format_flash(device: &mut device::Device) { if device.ui.storage.saves.flash.data.len() < FLASHRAM_SIZE { device .ui @@ -49,8 +49,6 @@ fn format_flash(device: &mut device::Device) { fn read_mem_sram(device: &mut device::Device, address: u64) -> u32 { let masked_address = address as usize & SRAM_MASK; - format_sram(device); - u32::from_be_bytes( device.ui.storage.saves.sram.data[masked_address..masked_address + 4] .try_into() @@ -96,8 +94,6 @@ pub fn read_mem( fn write_mem_sram(device: &mut device::Device, address: u64, value: u32, mask: u32) { let masked_address = address as usize & SRAM_MASK; - format_sram(device); - let mut data = u32::from_be_bytes( device.ui.storage.saves.sram.data[masked_address..masked_address + 4] .try_into() @@ -116,7 +112,6 @@ fn write_mem_flash(device: &mut device::Device, address: u64, value: u32, mask: device.cart.flashram.status = (value & mask) & 0xff; } else if (address & 0x1ffff) == 0x10000 { /* set command */ - format_flash(device); flashram_command(device, value & mask); } else { /* other accesses are not implemented */ @@ -148,8 +143,6 @@ fn dma_read_sram(device: &mut device::Device, mut cart_addr: u32, mut dram_addr: let mut i = dram_addr; let mut j = cart_addr; - format_sram(device); - while i < dram_addr + length { *device .ui @@ -171,8 +164,6 @@ fn dma_read_sram(device: &mut device::Device, mut cart_addr: u32, mut dram_addr: } fn dma_read_flash(device: &mut device::Device, cart_addr: u32, dram_addr: u32, length: u32) { - format_flash(device); - if (cart_addr & 0x1ffff) == 0x00000 && length == 128 && device.cart.flashram.mode == FlashramMode::PageProgram @@ -217,8 +208,6 @@ fn dma_write_sram( let mut i = dram_addr; let mut j = cart_addr; - format_sram(device); - while i < dram_addr + length { *device .rdram @@ -266,7 +255,6 @@ fn dma_write_flash( } else if (cart_addr & 0x1ffff) < 0x10000 && device.cart.flashram.mode == FlashramMode::ReadArray { - format_flash(device); /* adjust flashram address before starting DMA. */ if device.cart.flashram.silicon_id[1] == MX29L1100_ID || device.cart.flashram.silicon_id[1] == MX29L0000_ID diff --git a/src/device/controller/mempak.rs b/src/device/controller/mempak.rs index 55eab6d..75e920e 100644 --- a/src/device/controller/mempak.rs +++ b/src/device/controller/mempak.rs @@ -4,7 +4,7 @@ use crate::ui; pub const MEMPAK_SIZE: usize = 0x8000; const MPK_PAGE_SIZE: usize = 256; -fn format_mempak(device: &mut device::Device) { +pub fn format_mempak(device: &mut device::Device) { if device.ui.storage.saves.mempak.data.len() < MEMPAK_SIZE * 4 { device .ui @@ -43,6 +43,11 @@ fn format_mempak(device: &mut device::Device) { ]; for i in 0..4 { let offset = i * MEMPAK_SIZE; + if device.ui.storage.saves.mempak.data[offset..offset + MEMPAK_SIZE] != [0; MEMPAK_SIZE] + { + // don't overwrite existing data + continue; + } /* Fill Page 0 with pre-initialized content */ device.ui.storage.saves.mempak.data[offset..offset + MPK_PAGE_SIZE] @@ -77,8 +82,6 @@ fn format_mempak(device: &mut device::Device) { pub fn read(device: &mut device::Device, channel: usize, address: u16, data: usize, size: usize) { if (address as usize) < MEMPAK_SIZE { - format_mempak(device); - let offset = (channel * MEMPAK_SIZE) + address as usize; device.pif.ram[data..data + size] .copy_from_slice(&device.ui.storage.saves.mempak.data[offset..offset + size]) @@ -91,8 +94,6 @@ pub fn read(device: &mut device::Device, channel: usize, address: u16, data: usi pub fn write(device: &mut device::Device, channel: usize, address: u16, data: usize, size: usize) { if (address as usize) < MEMPAK_SIZE { - format_mempak(device); - let offset = (channel * MEMPAK_SIZE) + address as usize; device.ui.storage.saves.mempak.data[offset..offset + size] .copy_from_slice(&device.pif.ram[data..data + size]); diff --git a/src/ui/storage.rs b/src/ui/storage.rs index 470b077..ed65e8f 100644 --- a/src/ui/storage.rs +++ b/src/ui/storage.rs @@ -322,6 +322,13 @@ pub fn load_saves(ui: &mut ui::Ui, netplay: &mut Option) { } } +pub fn format_saves(device: &mut device::Device) { + device::cart::format_eeprom(device); + device::cart::sram::format_sram(device); + device::cart::sram::format_flash(device); + device::controller::mempak::format_mempak(device); +} + pub fn decompress_file(input: &[u8], name: &str) -> Vec { let mut decompressed_file = Vec::new(); {