2022-12-19 07:34:35 +00:00
|
|
|
use crate::device::Device;
|
|
|
|
use crate::vm::Uxn;
|
|
|
|
|
2022-12-19 07:29:30 +00:00
|
|
|
/**
|
|
|
|
* The system device
|
|
|
|
*/
|
|
|
|
#[derive(Debug)]
|
2022-12-19 07:34:35 +00:00
|
|
|
pub struct SystemDevice {
|
2022-12-19 07:29:30 +00:00
|
|
|
buffer: [u8; 0xF],
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SystemDevice {
|
2022-12-19 07:34:35 +00:00
|
|
|
pub fn new() -> SystemDevice {
|
2022-12-19 07:29:30 +00:00
|
|
|
SystemDevice { buffer: [0; 0xF] }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Device for SystemDevice {
|
|
|
|
fn dei1(&mut self, vm: &mut Uxn, port: u8) -> u8 {
|
|
|
|
let slot = port & 0xF;
|
|
|
|
match slot {
|
|
|
|
0x2 => vm.wst.idx,
|
|
|
|
0x3 => vm.rst.idx,
|
|
|
|
x => self.buffer[x as usize],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn dei2(&mut self, vm: &mut Uxn, port: u8) -> u16 {
|
|
|
|
return ((self.dei1(vm, port) as u16) << 8) + self.dei1(vm, port + 1) as u16;
|
|
|
|
}
|
|
|
|
fn deo1(&mut self, vm: &mut Uxn, port: u8, val: u8) {
|
|
|
|
let slot = port & 0xF;
|
|
|
|
match slot {
|
|
|
|
// Note: This VM does not support mutating the stack pointers.
|
|
|
|
// This operation is not well defined upstream
|
|
|
|
0x2 => panic!("Invoked unsupported mutation of the data stack pointer"),
|
|
|
|
0x3 => panic!("Invoked unsupported mutation of the return stack pointer"),
|
|
|
|
x => self.buffer[x as usize] = val,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn deo2(&mut self, vm: &mut Uxn, port: u8, val: u16) {
|
|
|
|
let slot = port & 0xF;
|
|
|
|
assert!(slot < 0xF, "Double-write beyond the end of the device");
|
|
|
|
match slot {
|
|
|
|
0x2 => panic!("The data stack is single-width, panic on spurious double-write"),
|
|
|
|
0x3 => panic!("The return stack is single-width, panic on spurious double-write"),
|
|
|
|
x => {
|
|
|
|
let [high, low] = val.to_be_bytes();
|
|
|
|
self.deo1(vm, x, high);
|
|
|
|
self.deo1(vm, x + 1, low)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|