Skip to main content

myriad/devices/
mod.rs

1use alloc::{boxed::Box, string::String, vec::Vec};
2pub mod system;
3pub mod console;
4
5pub use system::{SystemDevice, SYSTEM_ID};
6pub use console::{Console, BufferConsole, CONSOLE_ID, SharedBuf};
7use polka::Value;
8use crate::memory::Heap;
9
10pub trait Device {
11    /// Read a port. Returns (value, is_handle). For non-handle ports the tag
12    /// is `false`. For state-style ports that store cell handles, the device
13    /// returns the stored handle bits with `is_handle = true`; the runtime
14    /// gives the cart a fresh observer (rc_inc) on return.
15    fn read(&mut self, port: u8) -> Result<(Value, bool), String>;
16
17    /// Write a port. `is_handle` reflects the source register's tag. For
18    /// handle writes the runtime has already rc_inc'd the value, so the
19    /// device receives a fresh observer to either store (consuming the rc)
20    /// or discard (releasing rc via `heap.rc_dec`). State devices that
21    /// overwrite a previously-stored handle must rc_dec the old one through
22    /// `heap`.
23    fn write(&mut self, port: u8, val: Value, is_handle: bool, heap: &mut Heap)
24        -> Result<(), String>;
25
26    // Bulk byte write — host-side optimization path for stream-oriented devices
27    // (console, file, network). Default forwards to per-byte `write`; override
28    // to issue a single syscall. Not exposed via DEI/DEO.
29    fn write_bytes(&mut self, port: u8, bytes: &[u8], heap: &mut Heap) -> Result<(), String> {
30        for &b in bytes {
31            self.write(port, Value::from_int(b as i64), false, heap)?;
32        }
33        Ok(())
34    }
35}
36
37pub struct DeviceTable {
38    slots: Vec<Option<Box<dyn Device>>>,
39}
40
41impl DeviceTable {
42    pub fn new() -> Self {
43        let mut slots: Vec<Option<Box<dyn Device>>> = Vec::with_capacity(256);
44        for _ in 0..256 { slots.push(None); }
45        Self { slots }
46    }
47
48    pub fn install(&mut self, id: u8, dev: Box<dyn Device>) {
49        self.slots[id as usize] = Some(dev);
50    }
51
52    pub fn get_mut(&mut self, id: u8) -> Option<&mut Box<dyn Device>> {
53        self.slots[id as usize].as_mut()
54    }
55
56    pub fn take(&mut self, id: u8) -> Option<Box<dyn Device>> {
57        self.slots[id as usize].take()
58    }
59}