use eframe::egui::{DragValue, Ui}; use rand::RngCore; use serde::{Deserialize, Serialize}; use crate::{ card::{Card, SettingsUi}, register, }; #[derive(Serialize, Deserialize)] pub struct RamCardSettings { size: u16, start_addr: u16, } pub struct RamCard { ram: Vec, start_addr: u16, } impl Card for RamCard { fn new(settings: ron::Value) -> Result { let settings: RamCardSettings = settings.into_rust().unwrap(); let mut ram = vec![0; settings.size as usize]; rand::thread_rng().fill_bytes(&mut ram); Ok(Self { ram, start_addr: settings.start_addr, }) } fn read_mem(&mut self, address: u16) -> Option { if address < self.start_addr { return None; } let offset = (address - self.start_addr) as usize; if offset >= self.ram.len() { return None; } Some(self.ram[offset]) } fn write_mem(&mut self, address: u16, data: u8) -> Option<()> { if address < self.start_addr { return None; } let offset = (address - self.start_addr) as usize; if offset >= self.ram.len() { return None; } self.ram[offset] = data; Some(()) } fn default_settings() -> String { ron::to_string(&RamCardSettings { size: 4096, start_addr: 0, }) .unwrap() } fn get_settings(&self) -> String { ron::to_string(&RamCardSettings { size: self.ram.len() as u16, start_addr: self.start_addr, }).unwrap() } fn settings_ui(settings: ron::Value) -> anyhow::Result where Self: Sized, { Ok(RamCardSettingsUi { settings: settings.into_rust().unwrap(), }) } } pub struct RamCardSettingsUi { settings: RamCardSettings, } impl SettingsUi for RamCardSettingsUi { fn draw_ui(&mut self, ui: &mut Ui) { ui.horizontal(|ui| { ui.label("Size"); ui.add(DragValue::new(&mut self.settings.size).hexadecimal(4, false, true)); }); ui.horizontal(|ui| { ui.label("Start address"); ui.add(DragValue::new(&mut self.settings.start_addr).hexadecimal(4, false, true)); }); } fn serialize_settings(&self) -> String { ron::to_string(&self.settings).unwrap() } } register!(RamCard, "RAM card");