diff --git a/Cargo.lock b/Cargo.lock index ff22e7c..ec0b028 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -577,12 +577,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" -[[package]] -name = "iz80" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e13cd358184c4b647f19a858246b82e3327ed29c2893d232f01ed016ac5d3c" - [[package]] name = "jni" version = "0.19.0" @@ -744,6 +738,7 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-host", "nix 0.25.1", ] @@ -770,15 +765,23 @@ version = "0.1.0" dependencies = [ "femtos", "log", + "moa-host", + "thiserror", ] [[package]] -name = "moa-iz80" +name = "moa-debugger" +version = "0.1.0" +dependencies = [ + "moa-core", +] + +[[package]] +name = "moa-host" version = "0.1.0" dependencies = [ "femtos", - "iz80", - "moa-core", + "thiserror", ] [[package]] @@ -789,6 +792,7 @@ dependencies = [ "log", "moa-core", "moa-parsing", + "thiserror", ] [[package]] @@ -801,6 +805,8 @@ dependencies = [ "minifb", "moa-common", "moa-core", + "moa-debugger", + "moa-host", "moa-peripherals-yamaha", "moa-systems-computie", "moa-systems-genesis", @@ -832,6 +838,7 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-signals", ] [[package]] @@ -841,6 +848,7 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-host", ] [[package]] @@ -852,6 +860,7 @@ dependencies = [ "log", "moa-audio", "moa-core", + "moa-host", ] [[package]] @@ -863,6 +872,13 @@ dependencies = [ "moa-core", ] +[[package]] +name = "moa-signals" +version = "0.1.0" +dependencies = [ + "femtos", +] + [[package]] name = "moa-systems-computie" version = "0.1.0" @@ -870,6 +886,7 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-host", "moa-m68k", "moa-peripherals-generic", "moa-peripherals-motorola", @@ -882,8 +899,10 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-host", "moa-m68k", "moa-peripherals-yamaha", + "moa-signals", "moa-z80", ] @@ -894,9 +913,11 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-host", "moa-m68k", "moa-peripherals-mos", "moa-peripherals-zilog", + "moa-signals", ] [[package]] @@ -906,6 +927,7 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-host", "moa-z80", ] @@ -916,6 +938,7 @@ dependencies = [ "femtos", "log", "moa-core", + "moa-signals", ] [[package]] diff --git a/emulator/core/Cargo.toml b/emulator/core/Cargo.toml index 05674cf..8460ec6 100644 --- a/emulator/core/Cargo.toml +++ b/emulator/core/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" [dependencies] log = "0.4" femtos = "0.1" - +thiserror = "1.0" +moa-host = { path = "../libraries/host" } diff --git a/emulator/core/src/error.rs b/emulator/core/src/error.rs index 6b6c28b..cdc5ea8 100644 --- a/emulator/core/src/error.rs +++ b/emulator/core/src/error.rs @@ -1,16 +1,21 @@ +use std::fmt; +use std::error::{Error as StdError}; +use moa_host::HostError; + #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum EmulatorErrorKind { Misc, MemoryAlignment, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, thiserror::Error)] pub enum Error { Assertion(String), Breakpoint(String), Emulator(EmulatorErrorKind, String), Processor(u32), + Other(String), } impl Error { @@ -50,9 +55,28 @@ impl Error { match self { Error::Assertion(msg) | Error::Breakpoint(msg) | + Error::Other(msg) | Error::Emulator(_, msg) => msg.as_str(), Error::Processor(_) => "native exception", } } } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Error::Assertion(msg) | + Error::Breakpoint(msg) | + Error::Other(msg) | + Error::Emulator(_, msg) => write!(f, "{}", msg), + Error::Processor(_) => write!(f, "native exception"), + } + } +} + +impl From> for Error { + fn from(err: HostError) -> Self { + Self::Other(format!("other")) + } +} + diff --git a/emulator/core/src/host/mod.rs b/emulator/core/src/host/mod.rs deleted file mode 100644 index 6749e17..0000000 --- a/emulator/core/src/host/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ - -mod audio; -mod controllers; -mod gfx; -mod input; -mod keys; -mod mouse; -mod traits; - -pub use self::audio::{Sample, AudioFrame}; -pub use self::gfx::{Pixel, PixelEncoding, Frame, FrameSender, FrameReceiver, frame_queue}; -pub use self::keys::{Key, KeyEvent}; -pub use self::mouse::{MouseButton, MouseEventType, MouseEvent, MouseState}; -pub use self::controllers::{ControllerDevice, ControllerInput, ControllerEvent}; -pub use self::input::{EventSender, EventReceiver, event_queue}; -pub use self::traits::{Host, Tty, Audio, ClockedQueue, DummyAudio}; - diff --git a/emulator/core/src/lib.rs b/emulator/core/src/lib.rs index f1badcd..f718345 100644 --- a/emulator/core/src/lib.rs +++ b/emulator/core/src/lib.rs @@ -2,21 +2,15 @@ #[macro_use] mod error; -mod debugger; mod devices; mod interrupts; mod memory; -mod signals; mod system; -pub mod host; - -pub use crate::debugger::{DebugControl, Debugger}; pub use crate::devices::{Address, Addressable, Steppable, Interruptable, Debuggable, Inspectable, Transmutable, TransmutableBox, Device}; pub use crate::devices::{read_beu16, read_beu32, read_leu16, read_leu32, write_beu16, write_beu32, write_leu16, write_leu32, wrap_transmutable}; pub use crate::error::Error; pub use crate::interrupts::InterruptController; pub use crate::memory::{MemoryBlock, AddressTranslator, AddressRepeater, Bus, BusPort, dump_slice}; -pub use crate::signals::{Observable, Signal, EdgeSignal, ObservableSignal, ObservableEdgeSignal}; pub use crate::system::System; diff --git a/emulator/core/src/system.rs b/emulator/core/src/system.rs index 599636f..f6113f7 100644 --- a/emulator/core/src/system.rs +++ b/emulator/core/src/system.rs @@ -4,7 +4,7 @@ use std::cell::{RefCell, RefMut}; use std::collections::HashMap; use femtos::{Instant, Duration}; -use crate::{Bus, EdgeSignal, Error, InterruptController, Address, Device}; +use crate::{Bus, Error, InterruptController, Address, Device}; pub struct System { @@ -17,8 +17,6 @@ pub struct System { pub bus: Rc>, pub buses: HashMap>>, pub interrupt_controller: RefCell, - - pub break_signal: Option, } impl Default for System { @@ -33,8 +31,6 @@ impl Default for System { bus: Rc::new(RefCell::new(Bus::default())), buses: HashMap::new(), interrupt_controller: RefCell::new(InterruptController::default()), - - break_signal: None, } } } diff --git a/emulator/cpus/m68k/Cargo.toml b/emulator/cpus/m68k/Cargo.toml index 980d14c..e6ae8d6 100644 --- a/emulator/cpus/m68k/Cargo.toml +++ b/emulator/cpus/m68k/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] log = "0.4" +thiserror = "1.0" femtos = "0.1" moa-core = { path = "../../core" } moa-parsing = { path = "../../libraries/parsing" } diff --git a/emulator/cpus/m68k/src/lib.rs b/emulator/cpus/m68k/src/lib.rs index 39e56ff..c70c624 100644 --- a/emulator/cpus/m68k/src/lib.rs +++ b/emulator/cpus/m68k/src/lib.rs @@ -9,5 +9,5 @@ pub mod memory; pub mod timing; pub mod tests; -pub use self::state::{M68k, M68kType}; +pub use self::state::{M68k, M68kType, M68kError}; diff --git a/emulator/cpus/z80/Cargo.toml b/emulator/cpus/z80/Cargo.toml index 2d872ad..d3e4a25 100644 --- a/emulator/cpus/z80/Cargo.toml +++ b/emulator/cpus/z80/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" log = "0.4" femtos = "0.1" moa-core = { path = "../../core" } +moa-signals = { path = "../../libraries/signals" } diff --git a/emulator/cpus/z80/src/state.rs b/emulator/cpus/z80/src/state.rs index deff808..c79a7b9 100644 --- a/emulator/cpus/z80/src/state.rs +++ b/emulator/cpus/z80/src/state.rs @@ -3,7 +3,8 @@ use std::rc::Rc; use std::cell::RefCell; use femtos::{Instant, Frequency}; -use moa_core::{Address, Bus, BusPort, Signal}; +use moa_core::{Address, Bus, BusPort}; +use moa_signals::Signal; use crate::decode::Z80Decoder; use crate::debugger::Z80Debugger; diff --git a/emulator/frontends/common/Cargo.toml b/emulator/frontends/common/Cargo.toml index 728495c..69722e6 100644 --- a/emulator/frontends/common/Cargo.toml +++ b/emulator/frontends/common/Cargo.toml @@ -11,6 +11,7 @@ audio = ["cpal"] log = "0.4" femtos = "0.1" moa-core = { path = "../../core" } +moa-host = { path = "../../libraries/host" } nix = { version = "0.25", optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/emulator/frontends/common/src/audio.rs b/emulator/frontends/common/src/audio.rs index 639135a..a15956a 100644 --- a/emulator/frontends/common/src/audio.rs +++ b/emulator/frontends/common/src/audio.rs @@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex, MutexGuard}; use femtos::{Instant, Duration}; -use moa_core::host::{Audio, Sample, AudioFrame, ClockedQueue}; +use moa_host::{Audio, Sample, AudioFrame, ClockedQueue}; pub const SAMPLE_RATE: usize = 48000; diff --git a/emulator/frontends/console/src/lib.rs b/emulator/frontends/console/src/lib.rs index 240d870..91d89b6 100644 --- a/emulator/frontends/console/src/lib.rs +++ b/emulator/frontends/console/src/lib.rs @@ -9,22 +9,24 @@ use moa_core::host::{Host, Tty, ControllerEvent, Audio, DummyAudio, FrameReceive pub struct ConsoleFrontend; impl Host for ConsoleFrontend { - fn add_pty(&self) -> Result, Error> { + type Error = Error; + + fn add_pty(&self) -> Result, HostError> { use moa_common::tty::SimplePty; Ok(Box::new(SimplePty::open()?)) } - fn add_video_source(&mut self, _receiver: FrameReceiver) -> Result<(), Error> { + fn add_video_source(&mut self, _receiver: FrameReceiver) -> Result<(), HostError> { println!("console: add_window() is not supported from the console; ignoring request..."); Ok(()) } - fn register_controllers(&mut self, _sender: EventSender) -> Result<(), Error> { + fn register_controllers(&mut self, _sender: EventSender) -> Result<(), HostError> { println!("console: register_controller() is not supported from the console; ignoring request..."); Ok(()) } - fn add_audio_source(&mut self) -> Result, Error> { + fn add_audio_source(&mut self) -> Result, HostError> { println!("console: create_audio_source() is not supported from the console; returning dummy device..."); Ok(Box::new(DummyAudio())) } diff --git a/emulator/frontends/minifb/Cargo.toml b/emulator/frontends/minifb/Cargo.toml index 5cc95c3..0b0db92 100644 --- a/emulator/frontends/minifb/Cargo.toml +++ b/emulator/frontends/minifb/Cargo.toml @@ -12,8 +12,10 @@ simple_logger = "^2" femtos = "0.1" moa-core = { path = "../../core" } +moa-host = { path = "../../libraries/host" } moa-common = { path = "../common", features = ["audio"] } +moa-debugger = { path = "../../libraries/debugger" } moa-systems-genesis = { path = "../../systems/genesis" } moa-systems-computie = { path = "../../systems/computie" } moa-systems-trs80 = { path = "../../systems/trs80" } diff --git a/emulator/frontends/minifb/src/bin/moa-synth.rs b/emulator/frontends/minifb/src/bin/moa-synth.rs index 69223ba..f3057f7 100644 --- a/emulator/frontends/minifb/src/bin/moa-synth.rs +++ b/emulator/frontends/minifb/src/bin/moa-synth.rs @@ -3,7 +3,7 @@ use femtos::{Instant, Duration, Frequency}; use moa_peripherals_yamaha::{Ym2612, Sn76489}; -use moa_core::host::{self, Host, Frame, FrameSender, PixelEncoding, Key, KeyEvent, EventReceiver}; +use moa_host::{self, Host, Frame, FrameSender, PixelEncoding, Key, KeyEvent, EventReceiver}; use moa_core::{System, Error, Address, Addressable, Steppable, Transmutable, Device}; const SCREEN_WIDTH: u32 = 384; @@ -85,8 +85,8 @@ fn main() { moa_minifb::run(matches, |host| { let mut system = System::default(); - let (frame_sender, frame_receiver) = host::frame_queue(SCREEN_WIDTH, SCREEN_HEIGHT); - let (key_sender, key_receiver) = host::event_queue(); + let (frame_sender, frame_receiver) = moa_host::frame_queue(SCREEN_WIDTH, SCREEN_HEIGHT); + let (key_sender, key_receiver) = moa_host::event_queue(); let control = Device::new(SynthControl::new(key_receiver, frame_sender)); system.add_device("control", control)?; diff --git a/emulator/frontends/minifb/src/controllers.rs b/emulator/frontends/minifb/src/controllers.rs index ce56b3f..d7f58d3 100644 --- a/emulator/frontends/minifb/src/controllers.rs +++ b/emulator/frontends/minifb/src/controllers.rs @@ -1,6 +1,6 @@ use minifb::Key as MiniKey; -use moa_core::host::ControllerInput; +use moa_host::ControllerInput; pub fn map_controller_a(key: MiniKey, state: bool) -> Option { match key { diff --git a/emulator/frontends/minifb/src/keys.rs b/emulator/frontends/minifb/src/keys.rs index 84bdafd..bd3b4a7 100644 --- a/emulator/frontends/minifb/src/keys.rs +++ b/emulator/frontends/minifb/src/keys.rs @@ -1,6 +1,6 @@ use minifb::Key as MiniKey; -use moa_core::host::Key; +use moa_host::Key; pub fn map_key(key: MiniKey) -> Key { match key { diff --git a/emulator/frontends/minifb/src/lib.rs b/emulator/frontends/minifb/src/lib.rs index a47c7c8..6c05bb3 100644 --- a/emulator/frontends/minifb/src/lib.rs +++ b/emulator/frontends/minifb/src/lib.rs @@ -8,8 +8,9 @@ use minifb::{self, Key, MouseMode, MouseButton}; use clap::{Command, Arg, ArgAction, ArgMatches}; use femtos::{Duration as FemtosDuration}; -use moa_core::{System, Error, Device, Debugger, DebugControl}; -use moa_core::host::{Host, Audio, KeyEvent, MouseEvent, MouseState, ControllerDevice, ControllerEvent, EventSender, PixelEncoding, Frame, FrameReceiver}; +use moa_core::{System, Error, Device}; +use moa_debugger::{Debugger, DebugControl}; +use moa_host::{Host, HostError, Audio, KeyEvent, MouseEvent, MouseState, ControllerDevice, ControllerEvent, EventSender, PixelEncoding, Frame, FrameReceiver}; use moa_common::{AudioMixer, AudioSource}; use moa_common::CpalAudioOutput; @@ -138,38 +139,40 @@ impl MiniFrontendBuilder { } impl Host for MiniFrontendBuilder { - fn add_video_source(&mut self, receiver: FrameReceiver) -> Result<(), Error> { + type Error = Error; + + fn add_video_source(&mut self, receiver: FrameReceiver) -> Result<(), HostError> { if self.video.is_some() { - return Err(Error::new("Only one video source can be registered with this frontend")); + return Err(HostError::Specific(Error::new("Only one video source can be registered with this frontend"))); } self.video = Some(receiver); Ok(()) } - fn add_audio_source(&mut self) -> Result, Error> { + fn add_audio_source(&mut self) -> Result, HostError> { let source = AudioSource::new(self.mixer.as_ref().unwrap().clone()); Ok(Box::new(source)) } - fn register_controllers(&mut self, sender: EventSender) -> Result<(), Error> { + fn register_controllers(&mut self, sender: EventSender) -> Result<(), HostError> { if self.controllers.is_some() { - return Err(Error::new("A controller updater has already been registered with the frontend")); + return Err(HostError::Specific(Error::new("A controller updater has already been registered with the frontend"))); } self.controllers = Some(sender); Ok(()) } - fn register_keyboard(&mut self, sender: EventSender) -> Result<(), Error> { + fn register_keyboard(&mut self, sender: EventSender) -> Result<(), HostError> { if self.keyboard.is_some() { - return Err(Error::new("A keyboard updater has already been registered with the frontend")); + return Err(HostError::Specific(Error::new("A keyboard updater has already been registered with the frontend"))); } self.keyboard = Some(sender); Ok(()) } - fn register_mouse(&mut self, sender: EventSender) -> Result<(), Error> { + fn register_mouse(&mut self, sender: EventSender) -> Result<(), HostError> { if self.mouse.is_some() { - return Err(Error::new("A mouse updater has already been registered with the frontend")); + return Err(HostError::Specific(Error::new("A mouse updater has already been registered with the frontend"))); } self.mouse = Some(sender); Ok(()) diff --git a/emulator/frontends/pixels/Cargo.toml b/emulator/frontends/pixels/Cargo.toml index 105667d..4157095 100644 --- a/emulator/frontends/pixels/Cargo.toml +++ b/emulator/frontends/pixels/Cargo.toml @@ -11,6 +11,7 @@ femtos = "0.1" moa-core = { path = "../../core" } moa-common = { path = "../common", features = ["audio"] } +moa-host = { path = "../../libraries/host" } moa-systems-genesis = { path = "../../systems/genesis" } diff --git a/emulator/frontends/pixels/src/frontend.rs b/emulator/frontends/pixels/src/frontend.rs index f35289f..b41df81 100644 --- a/emulator/frontends/pixels/src/frontend.rs +++ b/emulator/frontends/pixels/src/frontend.rs @@ -5,7 +5,7 @@ use winit::event::{Event, VirtualKeyCode, WindowEvent, ElementState}; use winit::event_loop::{ControlFlow, EventLoop}; use moa_core::{System, Error}; -use moa_core::host::{Host, PixelEncoding, Frame, ControllerDevice, ControllerInput, ControllerEvent, EventSender, Audio, DummyAudio, FrameReceiver}; +use moa_host::{Host, HostError, PixelEncoding, Frame, ControllerDevice, ControllerInput, ControllerEvent, EventSender, Audio, DummyAudio, FrameReceiver}; use moa_common::{AudioMixer, AudioSource, CpalAudioOutput}; use crate::settings; @@ -45,17 +45,19 @@ impl PixelsFrontend { } impl Host for PixelsFrontend { - fn add_video_source(&mut self, receiver: FrameReceiver) -> Result<(), Error> { + type Error = Error; + + fn add_video_source(&mut self, receiver: FrameReceiver) -> Result<(), HostError> { self.video = Some(receiver); Ok(()) } - fn register_controllers(&mut self, sender: EventSender) -> Result<(), Error> { + fn register_controllers(&mut self, sender: EventSender) -> Result<(), HostError> { self.controllers = Some(sender); Ok(()) } - fn add_audio_source(&mut self) -> Result, Error> { + fn add_audio_source(&mut self) -> Result, HostError> { let source = AudioSource::new(self.mixer.clone()); Ok(Box::new(source)) //Ok(Box::new(DummyAudio())) diff --git a/emulator/frontends/pixels/src/web.rs b/emulator/frontends/pixels/src/web.rs index bece1e5..c0e2242 100644 --- a/emulator/frontends/pixels/src/web.rs +++ b/emulator/frontends/pixels/src/web.rs @@ -14,7 +14,7 @@ use wasm_bindgen::closure::Closure; use femtos::{Duration as FemtosDuration}; use moa_core::{System, Device}; -use moa_core::host::{ControllerInput, ControllerDevice, ControllerEvent, EventSender}; +use moa_host::{ControllerInput, ControllerDevice, ControllerEvent, EventSender}; use crate::settings; use crate::frontend::{self, PixelsFrontend, LoadSystemFn}; diff --git a/emulator/libraries/debugger/Cargo.toml b/emulator/libraries/debugger/Cargo.toml new file mode 100644 index 0000000..b40efe9 --- /dev/null +++ b/emulator/libraries/debugger/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "moa-debugger" +version = "0.1.0" +edition = "2021" + +[dependencies] +moa-core = { path = "../../core" } diff --git a/emulator/core/src/debugger.rs b/emulator/libraries/debugger/src/lib.rs similarity index 99% rename from emulator/core/src/debugger.rs rename to emulator/libraries/debugger/src/lib.rs index 4720fcf..b559060 100644 --- a/emulator/core/src/debugger.rs +++ b/emulator/libraries/debugger/src/lib.rs @@ -1,5 +1,5 @@ -use crate::{Error, System, Address, Addressable}; +use moa_core::{Error, System, Address, Addressable}; #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/emulator/libraries/host/Cargo.toml b/emulator/libraries/host/Cargo.toml new file mode 100644 index 0000000..3557e5b --- /dev/null +++ b/emulator/libraries/host/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "moa-host" +version = "0.1.0" +edition = "2021" +rust-version = "1.60" +categories = ["emulators"] +keywords = ["emulators"] +description = "traits for abstracting the I/O of an emulated system to the host" +authors = ["transistor fet "] +license = "MIT OR Apache-2.0" +repository = "https://github.com/transistorfet/moa" +readme = "README.md" + +[dependencies] +femtos = "0.1" +thiserror = "1.0" diff --git a/emulator/core/src/host/audio.rs b/emulator/libraries/host/src/audio.rs similarity index 100% rename from emulator/core/src/host/audio.rs rename to emulator/libraries/host/src/audio.rs diff --git a/emulator/core/src/host/controllers.rs b/emulator/libraries/host/src/controllers.rs similarity index 100% rename from emulator/core/src/host/controllers.rs rename to emulator/libraries/host/src/controllers.rs diff --git a/emulator/core/src/host/gfx.rs b/emulator/libraries/host/src/gfx.rs similarity index 99% rename from emulator/core/src/host/gfx.rs rename to emulator/libraries/host/src/gfx.rs index ebb0603..b2b5b0f 100644 --- a/emulator/core/src/host/gfx.rs +++ b/emulator/libraries/host/src/gfx.rs @@ -1,7 +1,7 @@ use std::sync::{Arc, Mutex}; use femtos::Instant; -use crate::host::traits::ClockedQueue; +use crate::traits::ClockedQueue; pub const MASK_COLOUR: u32 = 0xFFFFFFFF; diff --git a/emulator/core/src/host/input.rs b/emulator/libraries/host/src/input.rs similarity index 100% rename from emulator/core/src/host/input.rs rename to emulator/libraries/host/src/input.rs diff --git a/emulator/core/src/host/keys.rs b/emulator/libraries/host/src/keys.rs similarity index 100% rename from emulator/core/src/host/keys.rs rename to emulator/libraries/host/src/keys.rs diff --git a/emulator/libraries/host/src/lib.rs b/emulator/libraries/host/src/lib.rs new file mode 100644 index 0000000..cb0d3f9 --- /dev/null +++ b/emulator/libraries/host/src/lib.rs @@ -0,0 +1,17 @@ + +mod audio; +mod controllers; +mod gfx; +mod input; +mod keys; +mod mouse; +mod traits; + +pub use crate::audio::{Sample, AudioFrame}; +pub use crate::gfx::{Pixel, PixelEncoding, Frame, FrameSender, FrameReceiver, frame_queue}; +pub use crate::keys::{Key, KeyEvent}; +pub use crate::mouse::{MouseButton, MouseEventType, MouseEvent, MouseState}; +pub use crate::controllers::{ControllerDevice, ControllerInput, ControllerEvent}; +pub use crate::input::{EventSender, EventReceiver, event_queue}; +pub use crate::traits::{Host, HostError, Tty, Audio, ClockedQueue, DummyAudio}; + diff --git a/emulator/core/src/host/mouse.rs b/emulator/libraries/host/src/mouse.rs similarity index 100% rename from emulator/core/src/host/mouse.rs rename to emulator/libraries/host/src/mouse.rs diff --git a/emulator/core/src/host/traits.rs b/emulator/libraries/host/src/traits.rs similarity index 50% rename from emulator/core/src/host/traits.rs rename to emulator/libraries/host/src/traits.rs index 42d382e..81154a4 100644 --- a/emulator/core/src/host/traits.rs +++ b/emulator/libraries/host/src/traits.rs @@ -1,40 +1,70 @@ +use std::fmt; +use std::error::Error; use std::collections::VecDeque; use std::sync::{Arc, Mutex}; use femtos::Instant; -use crate::Error; -use crate::host::gfx::FrameReceiver; -use crate::host::audio::Sample; -use crate::host::keys::KeyEvent; -use crate::host::controllers::ControllerEvent; -use crate::host::mouse::MouseEvent; -use crate::host::input::EventSender; +use crate::gfx::FrameReceiver; +use crate::audio::Sample; +use crate::keys::KeyEvent; +use crate::controllers::ControllerEvent; +use crate::mouse::MouseEvent; +use crate::input::EventSender; +#[derive(Clone, Debug, thiserror::Error)] +pub enum HostError { + TTYNotSupported, + VideoSourceNotSupported, + AudioSourceNotSupported, + ControllerNotSupported, + KeyboardNotSupported, + MouseNotSupported, + #[from(E)] + Specific(E), +} + +/* +impl fmt::Display for HostError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + HostError::TTYNotSupported => write!(f, "This frontend doesn't support PTYs"), + HostError::VideoSourceNotSupported => write!(f, "This frontend doesn't support windows"), + HostError::AudioSourceNotSupported => write!(f, "This frontend doesn't support the sound"), + HostError::ControllerNotSupported => write!(f, "This frontend doesn't support game controllers"), + HostError::KeyboardNotSupported => write!(f, "This frontend doesn't support the keyboard"), + HostError::MouseNotSupported => write!(f, "This frontend doesn't support the mouse"), + HostError::Specific(err) => write!(f, "{}", err), + } + } +} +*/ pub trait Host { - fn add_pty(&self) -> Result, Error> { - Err(Error::new("This frontend doesn't support PTYs")) + type Error: Error; + + fn add_pty(&self) -> Result, HostError> { + Err(HostError::TTYNotSupported) } - fn add_video_source(&mut self, _receiver: FrameReceiver) -> Result<(), Error> { - Err(Error::new("This frontend doesn't support windows")) + fn add_video_source(&mut self, _receiver: FrameReceiver) -> Result<(), HostError> { + Err(HostError::VideoSourceNotSupported) } - fn add_audio_source(&mut self) -> Result, Error> { - Err(Error::new("This frontend doesn't support the sound")) + fn add_audio_source(&mut self) -> Result, HostError> { + Err(HostError::AudioSourceNotSupported) } - fn register_controllers(&mut self, _sender: EventSender) -> Result<(), Error> { - Err(Error::new("This frontend doesn't support game controllers")) + fn register_controllers(&mut self, _sender: EventSender) -> Result<(), HostError> { + Err(HostError::ControllerNotSupported) } - fn register_keyboard(&mut self, _sender: EventSender) -> Result<(), Error> { - Err(Error::new("This frontend doesn't support the keyboard")) + fn register_keyboard(&mut self, _sender: EventSender) -> Result<(), HostError> { + Err(HostError::KeyboardNotSupported) } - fn register_mouse(&mut self, _sender: EventSender) -> Result<(), Error> { - Err(Error::new("This frontend doesn't support the mouse")) + fn register_mouse(&mut self, _sender: EventSender) -> Result<(), HostError> { + Err(HostError::MouseNotSupported) } } diff --git a/emulator/libraries/signals/Cargo.toml b/emulator/libraries/signals/Cargo.toml new file mode 100644 index 0000000..fe695b0 --- /dev/null +++ b/emulator/libraries/signals/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "moa-signals" +version = "0.1.0" +edition = "2021" + +[dependencies] +femtos = "0.1" diff --git a/emulator/core/src/signals.rs b/emulator/libraries/signals/src/lib.rs similarity index 100% rename from emulator/core/src/signals.rs rename to emulator/libraries/signals/src/lib.rs diff --git a/emulator/peripherals/mos/Cargo.toml b/emulator/peripherals/mos/Cargo.toml index ecefe41..f20199a 100644 --- a/emulator/peripherals/mos/Cargo.toml +++ b/emulator/peripherals/mos/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" log = "0.4" femtos = "0.1" moa-core = { path = "../../core" } +moa-signals = { path = "../../libraries/signals" } diff --git a/emulator/peripherals/mos/src/mos6522.rs b/emulator/peripherals/mos/src/mos6522.rs index b223337..1fb6245 100644 --- a/emulator/peripherals/mos/src/mos6522.rs +++ b/emulator/peripherals/mos/src/mos6522.rs @@ -1,8 +1,8 @@ use femtos::{Instant, Duration}; -use moa_core::{Error, System, Address, Addressable, Steppable, Transmutable, Signal, ObservableSignal, Observable}; - +use moa_core::{Error, System, Address, Addressable, Steppable, Transmutable}; +use moa_signals::{Signal, ObservableSignal, Observable}; const REG_OUTPUT_B: Address = 0x00; const REG_OUTPUT_A: Address = 0x01; diff --git a/emulator/peripherals/motorola/Cargo.toml b/emulator/peripherals/motorola/Cargo.toml index 4d12377..02c37cc 100644 --- a/emulator/peripherals/motorola/Cargo.toml +++ b/emulator/peripherals/motorola/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" log = "0.4" femtos = "0.1" moa-core = { path = "../../core" } +moa-host = { path = "../../libraries/host" } diff --git a/emulator/peripherals/motorola/src/mc68681.rs b/emulator/peripherals/motorola/src/mc68681.rs index 5cce965..42677fc 100644 --- a/emulator/peripherals/motorola/src/mc68681.rs +++ b/emulator/peripherals/motorola/src/mc68681.rs @@ -2,7 +2,7 @@ use femtos::{Instant, Duration, Frequency}; use moa_core::{System, Error, Address, Steppable, Addressable, Transmutable}; -use moa_core::host::Tty; +use moa_host::Tty; const REG_MR1A_MR2A: Address = 0x01; diff --git a/emulator/peripherals/yamaha/Cargo.toml b/emulator/peripherals/yamaha/Cargo.toml index dd8bcde..051a167 100644 --- a/emulator/peripherals/yamaha/Cargo.toml +++ b/emulator/peripherals/yamaha/Cargo.toml @@ -7,5 +7,6 @@ edition = "2021" log = "^0.4" femtos = "0.1" moa-core = { path = "../../core" } +moa-host = { path = "../../libraries/host" } moa-audio = { path = "../../libraries/audio" } lazy_static = "1.4.0" diff --git a/emulator/peripherals/yamaha/src/sn76489.rs b/emulator/peripherals/yamaha/src/sn76489.rs index 58e796a..f3b0d3e 100644 --- a/emulator/peripherals/yamaha/src/sn76489.rs +++ b/emulator/peripherals/yamaha/src/sn76489.rs @@ -2,7 +2,7 @@ use femtos::{Instant, Duration, Frequency}; use moa_core::{System, Error, Address, Addressable, Steppable, Transmutable}; -use moa_core::host::{Host, Audio, Sample}; +use moa_host::{Host, HostError, Audio, Sample}; use moa_audio::SquareWave; @@ -94,7 +94,10 @@ pub struct Sn76489 { } impl Sn76489 { - pub fn new(host: &mut H, _clock_frequency: Frequency) -> Result { + pub fn new(host: &mut H, _clock_frequency: Frequency) -> Result> + where + H: Host + { let source = host.add_audio_source()?; let sample_rate = source.samples_per_second(); diff --git a/emulator/peripherals/yamaha/src/ym2612.rs b/emulator/peripherals/yamaha/src/ym2612.rs index 71af736..10aceb4 100644 --- a/emulator/peripherals/yamaha/src/ym2612.rs +++ b/emulator/peripherals/yamaha/src/ym2612.rs @@ -21,7 +21,7 @@ use lazy_static::lazy_static; use femtos::{Instant, Duration, Frequency}; use moa_core::{System, Error, Address, Addressable, Steppable, Transmutable}; -use moa_core::host::{Host, Audio, Sample}; +use moa_host::{Host, HostError, Audio, Sample}; /// Table of shift values for each possible rate angle @@ -739,7 +739,10 @@ pub struct Ym2612 { } impl Ym2612 { - pub fn new(host: &mut H, clock_frequency: Frequency) -> Result { + pub fn new(host: &mut H, clock_frequency: Frequency) -> Result> + where + H: Host, + { let source = host.add_audio_source()?; let fm_clock = clock_frequency / (6 * 24); let fm_clock_period = fm_clock.period_duration(); diff --git a/emulator/systems/computie/Cargo.toml b/emulator/systems/computie/Cargo.toml index ece0f3a..6de726c 100644 --- a/emulator/systems/computie/Cargo.toml +++ b/emulator/systems/computie/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" log = "0.4" femtos = "0.1" moa-core = { path = "../../core" } +moa-host = { path = "../../libraries/host" } moa-m68k = { path = "../../cpus/m68k" } moa-peripherals-generic = { path = "../../peripherals/generic" } moa-peripherals-motorola = { path = "../../peripherals/motorola" } diff --git a/emulator/systems/computie/src/system.rs b/emulator/systems/computie/src/system.rs index e216482..55eeb78 100644 --- a/emulator/systems/computie/src/system.rs +++ b/emulator/systems/computie/src/system.rs @@ -2,7 +2,7 @@ use femtos::Frequency; use moa_core::{System, Error, Debuggable, MemoryBlock, Device}; -use moa_core::host::Host; +use moa_host::Host; use moa_m68k::{M68k, M68kType}; use moa_peripherals_generic::AtaDevice; diff --git a/emulator/systems/genesis/Cargo.toml b/emulator/systems/genesis/Cargo.toml index 7391cfd..64e016c 100644 --- a/emulator/systems/genesis/Cargo.toml +++ b/emulator/systems/genesis/Cargo.toml @@ -7,6 +7,8 @@ edition = "2021" log = "0.4" femtos = "0.1" moa-core = { path = "../../core" } +moa-signals = { path = "../../libraries/signals" } +moa-host = { path = "../../libraries/host" } moa-peripherals-yamaha = { path = "../../peripherals/yamaha" } moa-m68k = { path = "../../cpus/m68k" } moa-z80 = { path = "../../cpus/z80" } diff --git a/emulator/systems/genesis/src/peripherals/controllers.rs b/emulator/systems/genesis/src/peripherals/controllers.rs index 348c11a..3167917 100644 --- a/emulator/systems/genesis/src/peripherals/controllers.rs +++ b/emulator/systems/genesis/src/peripherals/controllers.rs @@ -1,9 +1,9 @@ use femtos::{Instant, Duration}; -use moa_core::{System, Error, Signal, Address, Addressable, Steppable, Transmutable}; -use moa_core::host::{self, Host, ControllerDevice, ControllerInput, ControllerEvent, EventReceiver}; - +use moa_core::{System, Error, Address, Addressable, Steppable, Transmutable}; +use moa_host::{self, Host, HostError, ControllerDevice, ControllerInput, ControllerEvent, EventReceiver}; +use moa_signals::{Signal}; const REG_VERSION: Address = 0x01; const REG_DATA1: Address = 0x03; @@ -97,8 +97,11 @@ pub struct GenesisControllers { } impl GenesisControllers { - pub fn new(host: &mut H) -> Result { - let (sender, receiver) = host::event_queue(); + pub fn new(host: &mut H) -> Result> + where + H: Host, + { + let (sender, receiver) = moa_host::event_queue(); host.register_controllers(sender)?; Ok(Self { diff --git a/emulator/systems/genesis/src/peripherals/coprocessor.rs b/emulator/systems/genesis/src/peripherals/coprocessor.rs index 2ca7f3f..d96ec5d 100644 --- a/emulator/systems/genesis/src/peripherals/coprocessor.rs +++ b/emulator/systems/genesis/src/peripherals/coprocessor.rs @@ -3,8 +3,8 @@ use std::rc::Rc; use std::cell::{Cell, RefCell}; use femtos::Instant; -use moa_core::{Bus, Signal, Error, Address, Addressable, Transmutable}; - +use moa_core::{Bus, Error, Address, Addressable, Transmutable}; +use moa_signals::Signal; const DEV_NAME: &str = "coprocessor"; diff --git a/emulator/systems/genesis/src/peripherals/ym7101.rs b/emulator/systems/genesis/src/peripherals/ym7101.rs index e9d934f..cd4becf 100644 --- a/emulator/systems/genesis/src/peripherals/ym7101.rs +++ b/emulator/systems/genesis/src/peripherals/ym7101.rs @@ -1,9 +1,9 @@ use femtos::{Instant, Duration, Frequency}; -use moa_core::{System, Error, EdgeSignal, Signal, Address, Addressable, Steppable, Inspectable, Transmutable, Device, read_beu16, dump_slice}; -use moa_core::host::{self, Host, Pixel, PixelEncoding, Frame, FrameSender}; - +use moa_core::{System, Error, Address, Addressable, Steppable, Inspectable, Transmutable, Device, read_beu16, dump_slice}; +use moa_host::{self, Host, HostError, Pixel, PixelEncoding, Frame, FrameSender}; +use moa_signals::{EdgeSignal, Signal}; const DEV_NAME: &str = "ym7101"; @@ -717,17 +717,20 @@ pub struct Ym7101 { } impl Ym7101 { - pub fn new(host: &mut H, external_interrupt: Signal, sn_sound: Device) -> Ym7101 { - let (sender, receiver) = host::frame_queue(320, 224); - host.add_video_source(receiver).unwrap(); + pub fn new(host: &mut H, external_interrupt: Signal, sn_sound: Device) -> Result> + where + H: Host, + { + let (sender, receiver) = moa_host::frame_queue(320, 224); + host.add_video_source(receiver)?; - Ym7101 { + Ok(Ym7101 { sender, state: Ym7101State::default(), sn_sound, external_interrupt, vsync_interrupt: EdgeSignal::default(), - } + }) } fn set_register(&mut self, word: u16) { diff --git a/emulator/systems/genesis/src/system.rs b/emulator/systems/genesis/src/system.rs index 7f68a86..e0a3de9 100644 --- a/emulator/systems/genesis/src/system.rs +++ b/emulator/systems/genesis/src/system.rs @@ -6,7 +6,7 @@ use std::cell::RefCell; use femtos::Frequency; use moa_core::{System, Error, MemoryBlock, Bus, Address, Addressable, Device}; -use moa_core::host::Host; +use moa_host::Host; use moa_m68k::{M68k, M68kType}; use moa_z80::{Z80, Z80Type}; @@ -45,13 +45,13 @@ pub fn build_genesis(host: &mut H, mut options: SegaGenesisOptions) -> let rom = MemoryBlock::new(rom_data); //rom.read_only(); let rom_end = rom.size(); - system.add_addressable_device(0x00000000, Device::new(rom)).unwrap(); + system.add_addressable_device(0x00000000, Device::new(rom))?; let cartridge_nvram = MemoryBlock::new(vec![0; 0x400000 - rom_end]); - system.add_addressable_device(rom_end as Address, Device::new(cartridge_nvram)).unwrap(); + system.add_addressable_device(rom_end as Address, Device::new(cartridge_nvram))?; let ram = MemoryBlock::new(vec![0; 0x00010000]); - system.add_addressable_device(0x00ff0000, Device::new(ram)).unwrap(); + system.add_addressable_device(0x00ff0000, Device::new(ram))?; // Build the Coprocessor's Bus @@ -86,16 +86,16 @@ pub fn build_genesis(host: &mut H, mut options: SegaGenesisOptions) -> let controllers = GenesisControllers::new(host)?; let interrupt = controllers.get_interrupt_signal(); - system.add_addressable_device(0x00a10000, Device::new(controllers)).unwrap(); + system.add_addressable_device(0x00a10000, Device::new(controllers))?; let coproc = CoprocessorCoordinator::new(reset, bus_request); - system.add_addressable_device(0x00a11000, Device::new(coproc)).unwrap(); + system.add_addressable_device(0x00a11000, Device::new(coproc))?; - let vdp = Ym7101::new(host, interrupt, coproc_sn_sound); - system.add_peripheral("vdp", 0x00c00000, Device::new(vdp)).unwrap(); + let vdp = Ym7101::new(host, interrupt, coproc_sn_sound)?; + system.add_peripheral("vdp", 0x00c00000, Device::new(vdp))?; let cpu = M68k::from_type(M68kType::MC68000, Frequency::from_hz(7_670_454), system.bus.clone(), 0); - system.add_interruptable_device("cpu", Device::new(cpu)).unwrap(); + system.add_interruptable_device("cpu", Device::new(cpu))?; Ok(system) } diff --git a/emulator/systems/macintosh/Cargo.toml b/emulator/systems/macintosh/Cargo.toml index ab788ed..f063851 100644 --- a/emulator/systems/macintosh/Cargo.toml +++ b/emulator/systems/macintosh/Cargo.toml @@ -7,6 +7,8 @@ edition = "2021" log = "0.4" femtos = "0.1" moa-core = { path = "../../core" } +moa-host = { path = "../../libraries/host" } +moa-signals = { path = "../../libraries/signals" } moa-m68k = { path = "../../cpus/m68k" } moa-peripherals-mos = { path = "../../peripherals/mos" } moa-peripherals-zilog = { path = "../../peripherals/zilog" } diff --git a/emulator/systems/macintosh/src/peripherals/mainboard.rs b/emulator/systems/macintosh/src/peripherals/mainboard.rs index 3e02a6b..0ccdcd6 100644 --- a/emulator/systems/macintosh/src/peripherals/mainboard.rs +++ b/emulator/systems/macintosh/src/peripherals/mainboard.rs @@ -3,7 +3,8 @@ use std::rc::Rc; use std::cell::RefCell; use femtos::{Instant, Duration}; -use moa_core::{System, Bus, Error, Observable, Address, Addressable, AddressRepeater, Steppable, Transmutable, Device}; +use moa_core::{System, Bus, Error, Address, Addressable, AddressRepeater, Steppable, Transmutable, Device}; +use moa_signals::Observable; use moa_peripherals_mos::Mos6522; use moa_peripherals_zilog::Z8530; diff --git a/emulator/systems/macintosh/src/peripherals/video.rs b/emulator/systems/macintosh/src/peripherals/video.rs index 596da9d..7854f8d 100644 --- a/emulator/systems/macintosh/src/peripherals/video.rs +++ b/emulator/systems/macintosh/src/peripherals/video.rs @@ -2,7 +2,7 @@ use femtos::Duration; use moa_core::{System, Error, Address, Addressable, Steppable, Transmutable}; -use moa_core::host::{self, Host, Frame, FrameSender, Pixel}; +use moa_host::{self, Host, HostError, Frame, FrameSender, Pixel}; const SCRN_BASE: u32 = 0x07A700; @@ -13,8 +13,11 @@ pub struct MacVideo { } impl MacVideo { - pub fn new(host: &mut H) -> Result { - let (frame_sender, frame_receiver) = host::frame_queue(SCRN_SIZE.0, SCRN_SIZE.1); + pub fn new(host: &mut H) -> Result> + where + H: Host, + { + let (frame_sender, frame_receiver) = moa_host::frame_queue(SCRN_SIZE.0, SCRN_SIZE.1); host.add_video_source(frame_receiver)?; diff --git a/emulator/systems/macintosh/src/system.rs b/emulator/systems/macintosh/src/system.rs index d96ecf0..1d74423 100644 --- a/emulator/systems/macintosh/src/system.rs +++ b/emulator/systems/macintosh/src/system.rs @@ -2,7 +2,7 @@ use femtos::Frequency; use moa_core::{System, Error, MemoryBlock, Debuggable, Device}; -use moa_core::host::Host; +use moa_host::Host; use moa_m68k::{M68k, M68kType}; diff --git a/emulator/systems/trs80/Cargo.toml b/emulator/systems/trs80/Cargo.toml index 3ec5c72..44e6c5a 100644 --- a/emulator/systems/trs80/Cargo.toml +++ b/emulator/systems/trs80/Cargo.toml @@ -7,5 +7,6 @@ edition = "2021" log = "0.4" femtos = "0.1" moa-core = { path = "../../core" } +moa-host = { path = "../../libraries/host" } moa-z80 = { path = "../../cpus/z80" } diff --git a/emulator/systems/trs80/src/peripherals/charset.rs b/emulator/systems/trs80/src/peripherals/charset.rs index bb2d663..d17b7a7 100644 --- a/emulator/systems/trs80/src/peripherals/charset.rs +++ b/emulator/systems/trs80/src/peripherals/charset.rs @@ -650,7 +650,7 @@ const CHARACTERS: [[u8; 8]; 64] = [ ]; -use moa_core::host::Pixel; +use moa_host::Pixel; pub struct CharacterGenerator { pub row: i8, diff --git a/emulator/systems/trs80/src/peripherals/keymap.rs b/emulator/systems/trs80/src/peripherals/keymap.rs index 13ba79d..b8d8db2 100644 --- a/emulator/systems/trs80/src/peripherals/keymap.rs +++ b/emulator/systems/trs80/src/peripherals/keymap.rs @@ -1,5 +1,5 @@ -use moa_core::host::Key; +use moa_host::Key; #[inline(always)] pub fn set_bit(data: &mut [u8; 8], index: usize, bit: u8, state: bool) { diff --git a/emulator/systems/trs80/src/peripherals/model1.rs b/emulator/systems/trs80/src/peripherals/model1.rs index 16f420f..577b465 100644 --- a/emulator/systems/trs80/src/peripherals/model1.rs +++ b/emulator/systems/trs80/src/peripherals/model1.rs @@ -2,7 +2,7 @@ use femtos::{Instant, Duration}; use moa_core::{System, Error, Address, Addressable, Steppable, Transmutable}; -use moa_core::host::{self, Host, Frame, FrameSender, KeyEvent, EventReceiver}; +use moa_host::{self, Host, HostError, Frame, FrameSender, KeyEvent, EventReceiver}; use super::keymap; use super::charset::CharacterGenerator; @@ -18,8 +18,11 @@ pub struct Model1Keyboard { } impl Model1Keyboard { - pub fn new(host: &mut H) -> Result { - let (sender, receiver) = host::event_queue(); + pub fn new(host: &mut H) -> Result> + where + H: Host, + { + let (sender, receiver) = moa_host::event_queue(); host.register_keyboard(sender)?; Ok(Self { @@ -86,8 +89,11 @@ pub struct Model1Video { } impl Model1Video { - pub fn new(host: &mut H) -> Result { - let (frame_sender, frame_receiver) = host::frame_queue(SCREEN_SIZE.0, SCREEN_SIZE.1); + pub fn new(host: &mut H) -> Result> + where + H: Host, + { + let (frame_sender, frame_receiver) = moa_host::frame_queue(SCREEN_SIZE.0, SCREEN_SIZE.1); host.add_video_source(frame_receiver)?; diff --git a/emulator/systems/trs80/src/system.rs b/emulator/systems/trs80/src/system.rs index e79de06..9767c50 100644 --- a/emulator/systems/trs80/src/system.rs +++ b/emulator/systems/trs80/src/system.rs @@ -2,7 +2,7 @@ use femtos::Frequency; use moa_core::{System, Error, MemoryBlock, Device}; -use moa_core::host::Host; +use moa_host::Host; use moa_z80::{Z80, Z80Type};