104 lines
4.8 KiB
Rust
104 lines
4.8 KiB
Rust
use crate::device;
|
|
use crate::ui;
|
|
|
|
pub const MEMPAK_SIZE: usize = 0x8000;
|
|
const MPK_PAGE_SIZE: usize = 256;
|
|
|
|
pub fn format_mempak(device: &mut device::Device) {
|
|
if device.ui.storage.saves.mempak.data.len() < MEMPAK_SIZE * 4 {
|
|
device
|
|
.ui
|
|
.storage
|
|
.saves
|
|
.mempak
|
|
.data
|
|
.resize(MEMPAK_SIZE * 4, 0);
|
|
|
|
let page_0: [u8; MPK_PAGE_SIZE] = [
|
|
/* Label area */
|
|
0x81, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
|
|
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
|
|
0x1c, 0x1d, 0x1e, 0x1f, /* Main ID area */
|
|
0xff, 0xff, 0xff, 0xff, 0x05, 0x1a, 0x5f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff,
|
|
0x66, 0x25, 0x99, 0xcd, /* Unused */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, /* ID area backup #1 */
|
|
0xff, 0xff, 0xff, 0xff, 0x05, 0x1a, 0x5f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff,
|
|
0x66, 0x25, 0x99, 0xcd, /* ID area backup #2 */
|
|
0xff, 0xff, 0xff, 0xff, 0x05, 0x1a, 0x5f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff,
|
|
0x66, 0x25, 0x99, 0xcd, /* Unused */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, /* ID area backup #3 */
|
|
0xff, 0xff, 0xff, 0xff, 0x05, 0x1a, 0x5f, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff,
|
|
0x66, 0x25, 0x99, 0xcd, /* Unused */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00,
|
|
];
|
|
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]
|
|
.copy_from_slice(&page_0);
|
|
|
|
/* Fill INODE page 1 and update it's checkum */
|
|
let start_page = 5;
|
|
for i in MPK_PAGE_SIZE..2 * start_page {
|
|
device.ui.storage.saves.mempak.data[offset + i] = 0;
|
|
}
|
|
for i in (MPK_PAGE_SIZE + 2 * start_page..2 * MPK_PAGE_SIZE).step_by(2) {
|
|
device.ui.storage.saves.mempak.data[offset + i] = 0x00;
|
|
device.ui.storage.saves.mempak.data[offset + i + 1] = 0x03;
|
|
}
|
|
device.ui.storage.saves.mempak.data[offset + (MPK_PAGE_SIZE + 1)] = 0x71;
|
|
|
|
/* Page 2 is identical to page 1 */
|
|
let page1 = offset + MPK_PAGE_SIZE;
|
|
let page2 = offset + 2 * MPK_PAGE_SIZE;
|
|
let page1data =
|
|
device.ui.storage.saves.mempak.data[page1..page1 + MPK_PAGE_SIZE].to_vec();
|
|
device.ui.storage.saves.mempak.data[page2..page2 + MPK_PAGE_SIZE]
|
|
.copy_from_slice(&page1data);
|
|
|
|
/* Remaining pages DIR+DATA (3...) are initialized with 0x00 */
|
|
for i in 3 * MPK_PAGE_SIZE..MEMPAK_SIZE - 3 * MPK_PAGE_SIZE {
|
|
device.ui.storage.saves.mempak.data[offset + i] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn read(device: &mut device::Device, channel: usize, address: u16, data: usize, size: usize) {
|
|
if (address as usize) < MEMPAK_SIZE {
|
|
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])
|
|
} else {
|
|
for i in 0..size {
|
|
device.pif.ram[data + i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn write(device: &mut device::Device, channel: usize, address: u16, data: usize, size: usize) {
|
|
if (address as usize) < MEMPAK_SIZE {
|
|
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]);
|
|
|
|
ui::storage::schedule_save(device, ui::storage::SaveTypes::Mempak);
|
|
}
|
|
}
|