forked from Lea/invadeez
input/output instructions
This commit is contained in:
parent
a97824b26e
commit
6955ca49ee
|
@ -39,6 +39,16 @@ fn tick<M: MemoryMapper>(state: &mut EmulatorState<M>) {
|
|||
0x00 => {} // NOP
|
||||
|
||||
/* Special */
|
||||
0xd3 => {
|
||||
// OUT
|
||||
let port = state.next_byte();
|
||||
state.write_io(port, state.a);
|
||||
}
|
||||
0xdb => {
|
||||
// IN
|
||||
let port = state.next_byte();
|
||||
state.a = state.read_io(port);
|
||||
}
|
||||
0xfb => state.ei = true, // EI
|
||||
0xf3 => state.ei = false, // DI
|
||||
0x76 => {
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
pub trait MemoryMapper {
|
||||
/// Read a byte at the specified address through the memory mapper
|
||||
fn read(&mut self, address: u16) -> u8;
|
||||
|
||||
/// Write a byte to the specified address through the memory mapper
|
||||
fn write(&mut self, address: u16, value: u8);
|
||||
|
||||
/// Receive a byte from a device on the I/O bus through the memory mapper
|
||||
#[allow(unused_variables)]
|
||||
fn read_io(&mut self, port: u8) -> u8 {
|
||||
0
|
||||
}
|
||||
|
||||
/// Send a byte to a device on the I/O bus through the memory mapper
|
||||
#[allow(unused_variables)]
|
||||
fn write_io(&mut self, port: u8, value: u8) {}
|
||||
}
|
||||
|
||||
//#[cfg(test)]
|
||||
|
|
|
@ -47,12 +47,20 @@ impl<M: MemoryMapper> EmulatorState<M> {
|
|||
}
|
||||
|
||||
/// Read a byte at a specific address
|
||||
///
|
||||
/// May return an indeterminate value if an invalid region is accessed.
|
||||
/// May cause internal mapper state (eg. interrupts, emulated shift
|
||||
/// registers) to be updated. Subsequent reads from the same address may
|
||||
/// yield different values.
|
||||
#[inline]
|
||||
pub fn read_byte(&mut self, address: u16) -> u8 {
|
||||
self.mapper.read(address)
|
||||
}
|
||||
|
||||
/// Write a byte at a specific address
|
||||
///
|
||||
/// May do nothing if an invalid region is accessed. Subsequent reads
|
||||
/// from the same address may yield different values.
|
||||
#[inline]
|
||||
pub fn write_byte(&mut self, address: u16, value: u8) {
|
||||
self.mapper.write(address, value);
|
||||
|
@ -67,6 +75,11 @@ impl<M: MemoryMapper> EmulatorState<M> {
|
|||
}
|
||||
|
||||
/// Read a 16-bit word at a specific address
|
||||
///
|
||||
/// May return an indeterminate value if an invalid region is accessed.
|
||||
/// May cause internal mapper state (eg. interrupts, emulated shift
|
||||
/// registers) to be updated. Subsequent reads from the same address may
|
||||
/// yield different values.
|
||||
#[inline]
|
||||
pub fn read_word(&mut self, address: u16) -> u16 {
|
||||
u16::from_le_bytes([
|
||||
|
@ -76,6 +89,9 @@ impl<M: MemoryMapper> EmulatorState<M> {
|
|||
}
|
||||
|
||||
/// Write a 16-bit word at a specific address
|
||||
///
|
||||
/// May do nothing if an invalid region is accessed. Subsequent reads
|
||||
/// from the same address may yield different values.
|
||||
#[inline]
|
||||
pub fn write_word(&mut self, address: u16, value: u16) {
|
||||
let [low, high] = u16::to_le_bytes(value);
|
||||
|
@ -90,6 +106,24 @@ impl<M: MemoryMapper> EmulatorState<M> {
|
|||
(self.pc, ..) = self.pc.overflowing_add(2);
|
||||
value
|
||||
}
|
||||
|
||||
/// Receive a byte from a device on the I/O bus
|
||||
///
|
||||
/// May return an indeterminate value if an invalid device is accessed.
|
||||
/// May (and usually will) cause internal mapper state (eg. interrupts)
|
||||
/// to be updated.
|
||||
#[inline]
|
||||
pub fn read_io(&mut self, port: u8) -> u8 {
|
||||
self.mapper.read_io(port)
|
||||
}
|
||||
|
||||
/// Send a byte to a device on the I/O bus
|
||||
///
|
||||
/// May do nothing if an invalid device is accessed.
|
||||
#[inline]
|
||||
pub fn write_io(&mut self, port: u8, value: u8) {
|
||||
self.mapper.write_io(port, value);
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: MemoryMapper + Default> Default for EmulatorState<M> {
|
||||
|
|
Loading…
Reference in a new issue