2024-02-03 22:22:39 -06:00
|
|
|
use eframe::egui::{DragValue, Ui};
|
2024-02-08 11:01:15 -06:00
|
|
|
use rand::RngCore;
|
2023-10-12 13:11:38 -05:00
|
|
|
use serde::{Deserialize, Serialize};
|
2023-08-10 13:58:34 -05:00
|
|
|
|
2024-02-07 11:18:38 -06:00
|
|
|
use crate::{
|
|
|
|
card::{Card, SettingsUi},
|
|
|
|
register,
|
|
|
|
};
|
2023-08-10 13:58:34 -05:00
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
pub struct RamCardSettings {
|
|
|
|
size: u16,
|
|
|
|
start_addr: u16,
|
|
|
|
}
|
2024-02-03 22:22:39 -06:00
|
|
|
|
2023-08-10 13:58:34 -05:00
|
|
|
pub struct RamCard {
|
|
|
|
ram: Vec<u8>,
|
|
|
|
start_addr: u16,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Card for RamCard {
|
2024-02-03 22:22:39 -06:00
|
|
|
fn new(settings: ron::Value) -> Result<RamCard, anyhow::Error> {
|
2023-08-10 13:58:34 -05:00
|
|
|
let settings: RamCardSettings = settings.into_rust().unwrap();
|
2024-02-08 11:01:15 -06:00
|
|
|
let mut ram = vec![0; settings.size as usize];
|
|
|
|
rand::thread_rng().fill_bytes(&mut ram);
|
2024-02-03 22:22:39 -06:00
|
|
|
Ok(Self {
|
2023-08-10 13:58:34 -05:00
|
|
|
ram,
|
2023-10-12 13:11:38 -05:00
|
|
|
start_addr: settings.start_addr,
|
2023-08-10 13:58:34 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-02-03 22:22:39 -06:00
|
|
|
fn read_mem(&mut self, address: u16) -> Option<u8> {
|
|
|
|
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(())
|
|
|
|
}
|
|
|
|
|
2024-02-07 11:18:38 -06:00
|
|
|
fn default_settings() -> String {
|
|
|
|
ron::to_string(&RamCardSettings {
|
|
|
|
size: 4096,
|
|
|
|
start_addr: 0,
|
|
|
|
})
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
2024-02-08 08:40:24 -06:00
|
|
|
fn get_settings(&self) -> String {
|
|
|
|
ron::to_string(&RamCardSettings {
|
|
|
|
size: self.ram.len() as u16,
|
|
|
|
start_addr: self.start_addr,
|
|
|
|
}).unwrap()
|
|
|
|
}
|
|
|
|
|
2024-02-03 22:22:39 -06:00
|
|
|
fn settings_ui(settings: ron::Value) -> anyhow::Result<impl SettingsUi>
|
|
|
|
where
|
|
|
|
Self: Sized,
|
|
|
|
{
|
|
|
|
Ok(RamCardSettingsUi {
|
|
|
|
settings: settings.into_rust().unwrap(),
|
2023-10-12 13:11:38 -05:00
|
|
|
})
|
2023-08-10 13:58:34 -05:00
|
|
|
}
|
|
|
|
}
|
2024-02-03 22:22:39 -06:00
|
|
|
|
|
|
|
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");
|