diff --git a/src/main.rs b/src/main.rs index fb18bd1..08f0583 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod option_window; mod ram; mod state; mod window; +mod twosio; use std::collections::HashMap; diff --git a/src/twosio.rs b/src/twosio.rs new file mode 100644 index 0000000..154aa52 --- /dev/null +++ b/src/twosio.rs @@ -0,0 +1,108 @@ +use bitflags::bitflags; +use eframe::egui::{Ui, ComboBox}; +use serde::{Deserialize, Serialize}; + +use crate::{ + card::{Card, SettingsUi}, + register, +}; + +bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + struct Status: u8 { + const RDRF = 0b0000_0001; + const TDRE = 0b0000_0010; + const DCD = 0b0000_0100; + const CTS = 0b0000_1000; + const FE = 0b0001_0000; + const OVRN = 0b0010_0000; + const PE = 0b0100_0000; + const IRQ = 0b1000_0000; + } +} + +#[derive(Serialize, Deserialize)] +pub struct TwoSioSettings { + start_addr: u8, +} + +pub struct TwoSio { + start_addr: u8, + port1_status: Status, + port1_recv_data: u8, + port2_status: Status, + port2_recv_data: u8, +} + +impl Card for TwoSio { + fn new(settings: ron::Value) -> Result { + let settings: TwoSioSettings = settings.into_rust().unwrap(); + Ok(Self { + start_addr: settings.start_addr, + port1_status: Status::TDRE, + port1_recv_data: 0, + port2_status: Status::TDRE, + port2_recv_data: 0, + }) + } + + fn default_settings() -> String { + ron::to_string(&TwoSioSettings { + start_addr: 0, + }) + .unwrap() + } + + fn get_settings(&self) -> String { + ron::to_string(&TwoSioSettings { + start_addr: self.start_addr, + }).unwrap() + } + + fn settings_ui(settings: ron::Value) -> anyhow::Result + where + Self: Sized, + { + Ok(TwoSioSettingsUi { + settings: settings.into_rust().unwrap(), + }) + } + + fn read_io(&mut self, address: u8) -> Option { + if address & 0xF8 == self.start_addr { + match address & 0x2 { + 0 => Some(self.port1_status.bits()), + 1 => Some(self.port1_recv_data), + 2 => Some(self.port2_status.bits()), + 3 => Some(self.port2_recv_data), + _ => unreachable!(), + } + } else { + None + } + } +} + +pub struct TwoSioSettingsUi { + settings: TwoSioSettings, +} + +impl SettingsUi for TwoSioSettingsUi { + fn draw_ui(&mut self, ui: &mut Ui) { + ui.horizontal(|ui| { + ui.label("Base address"); + ComboBox::from_id_source("2sio_base").selected_text(format!("{:#x}", self.settings.start_addr)).show_ui(ui, |ui| { + for i in 0..64 { + let start_addr = (i as u8) * 4; + ui.selectable_value(&mut self.settings.start_addr, start_addr, format!("{:#x}", start_addr)); + } + }); + }); + } + + fn serialize_settings(&self) -> String { + ron::to_string(&self.settings).unwrap() + } +} + +register!(TwoSio, "88-2SIO");