lemur/src/emulator/cart.rs

64 lines
1.6 KiB
Rust

use anyhow::Result;
use rand::Rng;
use std::{
fs::{self, File},
io::{Read, Seek as _, SeekFrom, Write as _},
path::{Path, PathBuf},
};
use crate::emulator::SimId;
pub struct Cart {
pub file_path: PathBuf,
pub rom: Vec<u8>,
sram_file: File,
pub sram: Vec<u8>,
}
impl Cart {
pub fn load(file_path: &Path, sim_id: SimId) -> Result<Self> {
let rom = fs::read(file_path)?;
let mut sram_file = File::options()
.read(true)
.write(true)
.create(true)
.truncate(false)
.open(sram_path(file_path, sim_id))?;
let sram = if sram_file.metadata()?.len() == 0 {
// new SRAM file, randomize the contents
let mut sram = vec![0; 8 * 1024];
let mut rng = rand::rng();
for dst in sram.iter_mut().step_by(2) {
*dst = rng.random();
}
sram
} else {
let mut sram = Vec::with_capacity(8 * 1024);
sram_file.read_to_end(&mut sram)?;
sram
};
Ok(Cart {
file_path: file_path.to_path_buf(),
rom,
sram_file,
sram,
})
}
pub fn save_sram(&mut self) -> Result<()> {
self.sram_file.seek(SeekFrom::Start(0))?;
self.sram_file.write_all(&self.sram)?;
Ok(())
}
}
fn sram_path(file_path: &Path, sim_id: SimId) -> PathBuf {
match sim_id {
SimId::Player1 => file_path.with_extension("p1.sram"),
SimId::Player2 => file_path.with_extension("p2.sram"),
}
}