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
|
0x00 => {} // NOP
|
||||||
|
|
||||||
/* Special */
|
/* 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
|
0xfb => state.ei = true, // EI
|
||||||
0xf3 => state.ei = false, // DI
|
0xf3 => state.ei = false, // DI
|
||||||
0x76 => {
|
0x76 => {
|
||||||
|
|
|
@ -1,6 +1,19 @@
|
||||||
pub trait MemoryMapper {
|
pub trait MemoryMapper {
|
||||||
|
/// Read a byte at the specified address through the memory mapper
|
||||||
fn read(&mut self, address: u16) -> u8;
|
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);
|
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)]
|
//#[cfg(test)]
|
||||||
|
|
|
@ -47,12 +47,20 @@ impl<M: MemoryMapper> EmulatorState<M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a byte at a specific address
|
/// 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]
|
#[inline]
|
||||||
pub fn read_byte(&mut self, address: u16) -> u8 {
|
pub fn read_byte(&mut self, address: u16) -> u8 {
|
||||||
self.mapper.read(address)
|
self.mapper.read(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a byte at a specific 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]
|
#[inline]
|
||||||
pub fn write_byte(&mut self, address: u16, value: u8) {
|
pub fn write_byte(&mut self, address: u16, value: u8) {
|
||||||
self.mapper.write(address, value);
|
self.mapper.write(address, value);
|
||||||
|
@ -67,6 +75,11 @@ impl<M: MemoryMapper> EmulatorState<M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read a 16-bit word at a specific address
|
/// 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]
|
#[inline]
|
||||||
pub fn read_word(&mut self, address: u16) -> u16 {
|
pub fn read_word(&mut self, address: u16) -> u16 {
|
||||||
u16::from_le_bytes([
|
u16::from_le_bytes([
|
||||||
|
@ -76,6 +89,9 @@ impl<M: MemoryMapper> EmulatorState<M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a 16-bit word at a specific address
|
/// 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]
|
#[inline]
|
||||||
pub fn write_word(&mut self, address: u16, value: u16) {
|
pub fn write_word(&mut self, address: u16, value: u16) {
|
||||||
let [low, high] = u16::to_le_bytes(value);
|
let [low, high] = u16::to_le_bytes(value);
|
||||||
|
@ -90,6 +106,24 @@ impl<M: MemoryMapper> EmulatorState<M> {
|
||||||
(self.pc, ..) = self.pc.overflowing_add(2);
|
(self.pc, ..) = self.pc.overflowing_add(2);
|
||||||
value
|
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> {
|
impl<M: MemoryMapper + Default> Default for EmulatorState<M> {
|
||||||
|
|
Loading…
Reference in a new issue