[NO TESTS] WIP
This commit is contained in:
parent
12d657097c
commit
e6faac5788
2 changed files with 76 additions and 39 deletions
64
src/lib.rs
64
src/lib.rs
|
@ -1,6 +1,7 @@
|
|||
pub mod memory;
|
||||
pub mod stack;
|
||||
|
||||
use std::cell::{Cell, RefCell, RefMut};
|
||||
use std::rc::Rc;
|
||||
use std::*;
|
||||
|
||||
|
@ -73,8 +74,10 @@ impl Device for SystemDevice {
|
|||
fn deo1(&mut self, vm: &mut Uxn, port: u8, val: u8) {
|
||||
let slot = port & 0xF;
|
||||
match slot {
|
||||
0x2 => vm.wst.idx = val,
|
||||
0x3 => vm.rst.idx = val,
|
||||
// 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,
|
||||
}
|
||||
}
|
||||
|
@ -95,9 +98,9 @@ impl Device for SystemDevice {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Uxn {
|
||||
memory: Box<TrivialMemory>,
|
||||
memory: Rc<RefCell<TrivialMemory>>,
|
||||
// Note: Using Rc so we can start with many NullDevs and replace them
|
||||
devices: [Box<dyn Device>; 16],
|
||||
devices: [Rc<RefCell<dyn Device>>; 16],
|
||||
pc: u16, // Program counter
|
||||
wst: Stack, // Data stack
|
||||
rst: Stack, // Return stack pointer
|
||||
|
@ -106,24 +109,24 @@ pub struct Uxn {
|
|||
impl Uxn {
|
||||
pub fn new() -> Uxn {
|
||||
Uxn {
|
||||
memory: Box::new(TrivialMemory::new()),
|
||||
memory: Rc::new(RefCell::new(TrivialMemory::new())),
|
||||
devices: [
|
||||
Box::new(SystemDevice::new()), // #00
|
||||
Box::new(NullDevice::new()), // #01
|
||||
Box::new(NullDevice::new()), // #02
|
||||
Box::new(NullDevice::new()), // #03
|
||||
Box::new(NullDevice::new()), // #04
|
||||
Box::new(NullDevice::new()), // #05
|
||||
Box::new(NullDevice::new()), // #06
|
||||
Box::new(NullDevice::new()), // #07
|
||||
Box::new(NullDevice::new()), // #08
|
||||
Box::new(NullDevice::new()), // #09
|
||||
Box::new(NullDevice::new()), // #0a
|
||||
Box::new(NullDevice::new()), // #0b
|
||||
Box::new(NullDevice::new()), // #0c
|
||||
Box::new(NullDevice::new()), // #0d
|
||||
Box::new(NullDevice::new()), // #0e
|
||||
Box::new(NullDevice::new()), // #0f
|
||||
Rc::new(RefCell::new(SystemDevice::new())), // #00
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #01
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #02
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #03
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #04
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #05
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #06
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #07
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #08
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #09
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #0a
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #0b
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #0c
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #0d
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #0e
|
||||
Rc::new(RefCell::new(NullDevice::new())), // #0f
|
||||
],
|
||||
pc: 0x0100,
|
||||
wst: Stack::new(),
|
||||
|
@ -132,27 +135,26 @@ impl Uxn {
|
|||
}
|
||||
|
||||
pub fn is_halted(&mut self) -> bool {
|
||||
let dev = self.devices[0].as_mut();
|
||||
dev.dei1(self, 0x0f) != 0
|
||||
self.dei1(0x0f) != 0
|
||||
}
|
||||
|
||||
fn device(&self, port: u8) -> Rc<RefCell<dyn Device>> {
|
||||
Rc::clone(&self.devices[(port & 0xF0 >> 4) as usize])
|
||||
}
|
||||
|
||||
pub fn dei1(&mut self, port: u8) -> u8 {
|
||||
let dev = self.devices[(port & 0xF0 >> 4) as usize];
|
||||
dev.dei1(self, port)
|
||||
self.device(port).borrow_mut().dei1(self, port)
|
||||
}
|
||||
|
||||
pub fn dei2(&mut self, port: u8) -> u16 {
|
||||
let dev = self.devices[(port & 0xF0 >> 4) as usize];
|
||||
dev.dei2(self, port)
|
||||
self.device(port).borrow_mut().dei2(self, port)
|
||||
}
|
||||
|
||||
pub fn deo1(&mut self, port: u8, val: u8) {
|
||||
let dev = self.devices[(port & 0xF0 >> 4) as usize].as_mut();
|
||||
dev.deo1(self, port, val)
|
||||
self.device(port).borrow_mut().deo1(self, port, val);
|
||||
}
|
||||
|
||||
pub fn deo2(&mut self, port: u8, val: u16) {
|
||||
let dev = self.devices[(port & 0xF0 >> 4) as usize].as_mut();
|
||||
dev.deo2(self, port, val)
|
||||
self.device(port).borrow_mut().deo2(self, port, val);
|
||||
}
|
||||
}
|
||||
|
|
49
src/stack.rs
49
src/stack.rs
|
@ -39,20 +39,55 @@ impl Stack {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pop1(&mut self) -> Result<u8, StackError> {
|
||||
pub fn get1(&self, idx: u8) -> Result<u8, StackError> {
|
||||
Ok(self.buff[idx as usize])
|
||||
}
|
||||
|
||||
pub fn peek1(&self) -> Result<u8, StackError> {
|
||||
if self.idx == 0 {
|
||||
Err(StackError::StackUnderflow)
|
||||
} else {
|
||||
Ok(self.get1(self.idx - 1)?)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop1(&mut self) -> Result<u8, StackError> {
|
||||
let val = self.peek1()?;
|
||||
self.idx -= 1;
|
||||
Ok(self.buff[self.idx as usize])
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
pub fn get2(&self, idx: u8) -> Result<u16, StackError> {
|
||||
if idx == 255 {
|
||||
Err(StackError::StackOverflow)
|
||||
} else {
|
||||
let high = self.buff[idx as usize] as u16;
|
||||
let low = self.buff[(idx + 1) as usize] as u16;
|
||||
Ok((high << 8) + low)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peek2(&mut self) -> Result<u16, StackError> {
|
||||
if self.idx < 2 {
|
||||
Err(StackError::StackUnderflow)
|
||||
} else {
|
||||
self.get2(self.idx - 2)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop2(&mut self) -> Result<u16, StackError> {
|
||||
if self.idx < 2 {
|
||||
Err(StackError::StackUnderflow)
|
||||
} else {
|
||||
Ok(((self.pop1()? as u16) << 8) + self.pop1()? as u16)
|
||||
}
|
||||
let val = self.peek2()?;
|
||||
self.idx -= 2;
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
pub fn move1(&mut self, other: &mut Stack) -> Result<(), StackError> {
|
||||
other.push1(self.pop1()?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn move2(&mut self, other: &mut Stack) -> Result<(), StackError> {
|
||||
other.push2(self.pop2()?)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue