cpu: fix renaming mistake "screen" -> "mem"

This commit is contained in:
John 2023-04-29 18:34:24 -05:00
parent ea357be477
commit 57c2ac681c
4 changed files with 45 additions and 52 deletions

View File

@ -43,7 +43,7 @@ pub struct CPU {
/// chip-8. Includes [Quirks], target IPF, etc. /// chip-8. Includes [Quirks], target IPF, etc.
pub flags: Flags, pub flags: Flags,
// memory map info // memory map info
screen: Bus, mem: Bus,
font: Adr, font: Adr,
// memory // memory
stack: Vec<Adr>, stack: Vec<Adr>,
@ -108,11 +108,26 @@ impl CPU {
/// Loads bytes into the CPU's program space /// Loads bytes into the CPU's program space
pub fn load_program_bytes(&mut self, rom: &[u8]) -> Result<&mut Self> { pub fn load_program_bytes(&mut self, rom: &[u8]) -> Result<&mut Self> {
self.screen.clear_region(Program); self.mem.clear_region(Program);
self.screen.load_region(Program, rom)?; self.mem.load_region(Program, rom)?;
Ok(self) Ok(self)
} }
/// Pokes a value into memory
pub fn poke(&mut self, addr: Adr, data: u8) {
self.mem.write(addr, data)
}
/// Peeks a value from memory
pub fn peek(&mut self, addr: Adr) -> u8 {
self.mem.read(addr)
}
/// Grabs a reference to the [CPU]'s memory
pub fn introspect(&mut self) -> &Bus {
&self.mem
}
/// Presses a key, and reports whether the key's state changed. /// Presses a key, and reports whether the key's state changed.
/// If key does not exist, returns [Error::InvalidKey]. /// If key does not exist, returns [Error::InvalidKey].
/// ///
@ -453,12 +468,12 @@ impl CPU {
/// # cpu.flags.debug = true; // enable live disassembly /// # cpu.flags.debug = true; // enable live disassembly
/// # cpu.flags.monotonic = true; // enable monotonic/test timing /// # cpu.flags.monotonic = true; // enable monotonic/test timing
/// let mut bus = bus!{ /// let mut bus = bus!{
/// Program [0x0200..0x0f00] = &[
/// 0xff, 0xff, // invalid!
/// 0x22, 0x02, // jump 0x202 (pc)
/// ],
/// Screen [0x0f00..0x1000], /// Screen [0x0f00..0x1000],
/// }; /// };
/// cpu.load_program_bytes(&[
/// 0xff, 0xff, // invalid!
/// 0x22, 0x02, // jump 0x202
/// ]);
/// dbg!(cpu.tick(&mut bus)) /// dbg!(cpu.tick(&mut bus))
/// .expect_err("Should return Error::InvalidInstruction { 0xffff }"); /// .expect_err("Should return Error::InvalidInstruction { 0xffff }");
/// ``` /// ```
@ -472,23 +487,13 @@ impl CPU {
return Ok(self); return Ok(self);
} }
self.cycle += 1; self.cycle += 1;
// Fetch slice of memory starting at pc, for var-width opcode 0xf000_iiii
let opchunk = self let opchunk = self
.screen .mem
.get(self.pc as usize..) .get(self.pc as usize..)
.ok_or(Error::InvalidAddressRange { .ok_or(Error::InvalidAddressRange {
range: (self.pc as usize..).into(), range: (self.pc as usize..).into(),
})?; })?;
// fetch opcode
let opcode: &[u8; 2] =
if let Some(slice) = self.screen.get(self.pc as usize..self.pc as usize + 2) {
slice
.try_into()
.expect("`slice` should be exactly 4 bytes.")
} else {
return Err(Error::InvalidAddressRange {
range: (self.pc as usize..self.pc as usize + 4).into(),
});
};
// Print opcode disassembly: // Print opcode disassembly:
if self.flags.debug { if self.flags.debug {
@ -496,7 +501,7 @@ impl CPU {
"{:3} {:03x}: {:<36}", "{:3} {:03x}: {:<36}",
self.cycle.bright_black(), self.cycle.bright_black(),
self.pc, self.pc,
self.disassembler.once(u16::from_be_bytes(*opcode)) self.disassembler.once(self.mem.read(self.pc))
); );
} }
@ -506,7 +511,7 @@ impl CPU {
self.execute(screen, insn); self.execute(screen, insn);
} else { } else {
return Err(Error::UnimplementedInstruction { return Err(Error::UnimplementedInstruction {
word: u16::from_be_bytes(*opcode), word: self.mem.read(self.pc),
}); });
} }
@ -515,7 +520,7 @@ impl CPU {
self.flags.pause = true; self.flags.pause = true;
return Err(Error::BreakpointHit { return Err(Error::BreakpointHit {
addr: self.pc, addr: self.pc,
next: self.screen.read(self.pc), next: self.mem.read(self.pc),
}); });
} }
Ok(self) Ok(self)
@ -600,7 +605,7 @@ impl Default for CPU {
fn default() -> Self { fn default() -> Self {
CPU { CPU {
stack: vec![], stack: vec![],
screen: bus! { mem: bus! {
Charset [0x0050..0x00a0] = include_bytes!("mem/charset.bin"), Charset [0x0050..0x00a0] = include_bytes!("mem/charset.bin"),
Program [0x0200..0x1000], Program [0x0200..0x1000],
}, },

View File

@ -407,10 +407,7 @@ impl CPU {
pub(super) fn draw_sprite(&mut self, x: u16, y: u16, n: Nib, w: u16, h: u16, screen: &mut Bus) { pub(super) fn draw_sprite(&mut self, x: u16, y: u16, n: Nib, w: u16, h: u16, screen: &mut Bus) {
let w_bytes = w / 8; let w_bytes = w / 8;
self.v[0xf] = 0; self.v[0xf] = 0;
if let Some(sprite) = self if let Some(sprite) = self.mem.get(self.i as usize..(self.i + n as u16) as usize) {
.screen
.get(self.i as usize..(self.i + n as u16) as usize)
{
for (line, &sprite) in sprite.iter().enumerate() { for (line, &sprite) in sprite.iter().enumerate() {
let line = line as u16; let line = line as u16;
let sprite = ((sprite as u16) << (8 - (x % 8))).to_be_bytes(); let sprite = ((sprite as u16) << (8 - (x % 8))).to_be_bytes();
@ -460,7 +457,7 @@ impl CPU {
pub(super) fn draw_schip_sprite(&mut self, x: u16, y: u16, w: u16, screen: &mut Bus) { pub(super) fn draw_schip_sprite(&mut self, x: u16, y: u16, w: u16, screen: &mut Bus) {
self.v[0xf] = 0; self.v[0xf] = 0;
let w_bytes = w / 8; let w_bytes = w / 8;
if let Some(sprite) = self.screen.get(self.i as usize..(self.i + 32) as usize) { if let Some(sprite) = self.mem.get(self.i as usize..(self.i + 32) as usize) {
let sprite = sprite.to_owned(); let sprite = sprite.to_owned();
for (line, sprite) in sprite.chunks_exact(2).enumerate() { for (line, sprite) in sprite.chunks_exact(2).enumerate() {
let sprite = u16::from_be_bytes( let sprite = u16::from_be_bytes(
@ -572,9 +569,9 @@ impl CPU {
#[inline(always)] #[inline(always)]
pub(super) fn bcd_convert(&mut self, x: Reg) { pub(super) fn bcd_convert(&mut self, x: Reg) {
let x = self.v[x]; let x = self.v[x];
self.screen.write(self.i.wrapping_add(2), x % 10); self.mem.write(self.i.wrapping_add(2), x % 10);
self.screen.write(self.i.wrapping_add(1), x / 10 % 10); self.mem.write(self.i.wrapping_add(1), x / 10 % 10);
self.screen.write(self.i, x / 100 % 10); self.mem.write(self.i, x / 100 % 10);
} }
/// |`Fx55`| DMA Stor from I to registers 0..=X /// |`Fx55`| DMA Stor from I to registers 0..=X
/// ///
@ -585,7 +582,7 @@ impl CPU {
pub(super) fn store_dma(&mut self, x: Reg) { pub(super) fn store_dma(&mut self, x: Reg) {
let i = self.i as usize; let i = self.i as usize;
for (reg, value) in self for (reg, value) in self
.screen .mem
.get_mut(i..=i + x) .get_mut(i..=i + x)
.unwrap_or_default() .unwrap_or_default()
.iter_mut() .iter_mut()
@ -606,7 +603,7 @@ impl CPU {
pub(super) fn load_dma(&mut self, x: Reg) { pub(super) fn load_dma(&mut self, x: Reg) {
let i = self.i as usize; let i = self.i as usize;
for (reg, value) in self for (reg, value) in self
.screen .mem
.get(i..=i + x) .get(i..=i + x)
.unwrap_or_default() .unwrap_or_default()
.iter() .iter()
@ -642,7 +639,7 @@ impl CPU {
pub(super) fn store_flags(&mut self, x: Reg) { pub(super) fn store_flags(&mut self, x: Reg) {
// TODO: Save these, maybe // TODO: Save these, maybe
for (reg, value) in self for (reg, value) in self
.screen .mem
.get_mut(0..=x) .get_mut(0..=x)
.unwrap_or_default() .unwrap_or_default()
.iter_mut() .iter_mut()
@ -656,13 +653,7 @@ impl CPU {
/// I just chuck it in 0x0..0xf. Screw it. /// I just chuck it in 0x0..0xf. Screw it.
#[inline(always)] #[inline(always)]
pub(super) fn load_flags(&mut self, x: Reg) { pub(super) fn load_flags(&mut self, x: Reg) {
for (reg, value) in self for (reg, value) in self.mem.get(0..=x).unwrap_or_default().iter().enumerate() {
.screen
.get(0..=x)
.unwrap_or_default()
.iter()
.enumerate()
{
self.v[reg] = *value; self.v[reg] = *value;
} }
} }

View File

@ -33,7 +33,7 @@ fn setup_environment() -> (CPU, Bus) {
}, },
bus! { bus! {
// Create a screen // Create a screen
Screen [0x0F00..0x1000] = include_bytes!("../../chip8Archive/roms/1dcell.ch8"), Screen [0x000..0x100] = include_bytes!("../../chip8Archive/roms/1dcell.ch8"),
}, },
); );
ch8.0 ch8.0
@ -755,7 +755,7 @@ mod io {
// Debug mode is 5x slower // Debug mode is 5x slower
cpu.flags.debug = false; cpu.flags.debug = false;
// Load the test program // Load the test program
cpu.screen.load_region(Program, test.program).unwrap(); cpu.mem.load_region(Program, test.program).unwrap();
// Run the test program for the specified number of steps // Run the test program for the specified number of steps
while cpu.cycle() < test.steps { while cpu.cycle() < test.steps {
cpu.multistep(&mut bus, 10.min(test.steps - cpu.cycle())) cpu.multistep(&mut bus, 10.min(test.steps - cpu.cycle()))
@ -958,7 +958,7 @@ mod io {
let addr = cpu.i as usize; let addr = cpu.i as usize;
assert_eq!( assert_eq!(
cpu.screen cpu.mem
.get(addr..addr.wrapping_add(5)) .get(addr..addr.wrapping_add(5))
.expect("Region at addr should exist!"), .expect("Region at addr should exist!"),
test.output, test.output,
@ -1004,10 +1004,7 @@ mod io {
cpu.bcd_convert(5); cpu.bcd_convert(5);
assert_eq!( assert_eq!(cpu.mem.get(addr..addr.saturating_add(3)), Some(test.output))
cpu.screen.get(addr..addr.saturating_add(3)),
Some(test.output)
)
} }
} }
} }
@ -1030,7 +1027,7 @@ mod io {
cpu.store_dma(len); cpu.store_dma(len);
// Check that bus grabbed the correct data // Check that bus grabbed the correct data
let bus = cpu let bus = cpu
.screen .mem
.get_mut(addr..addr + DATA.len()) .get_mut(addr..addr + DATA.len())
.expect("Getting a mutable slice at addr 0x0456 should not fail"); .expect("Getting a mutable slice at addr 0x0456 should not fail");
assert_eq!(bus[0..=len], DATA[0..=len]); assert_eq!(bus[0..=len], DATA[0..=len]);
@ -1048,7 +1045,7 @@ mod io {
const DATA: &[u8] = b"ABCDEFGHIJKLMNOP"; const DATA: &[u8] = b"ABCDEFGHIJKLMNOP";
// Load some test data into memory // Load some test data into memory
let addr = 0x456; let addr = 0x456;
cpu.screen cpu.mem
.get_mut(addr..addr + DATA.len()) .get_mut(addr..addr + DATA.len())
.expect("Getting a mutable slice at addr 0x0456..0x0466 should not fail") .expect("Getting a mutable slice at addr 0x0456..0x0466 should not fail")
.write_all(DATA) .write_all(DATA)
@ -1088,8 +1085,8 @@ mod behavior {
#[test] #[test]
fn sound() { fn sound() {
let (mut cpu, mut bus) = setup_environment(); let (mut cpu, mut bus) = setup_environment();
cpu.flags.monotonic = None; // disable monotonic timing
cpu.sound = 10.0; cpu.sound = 10.0;
cpu.flags.monotonic = false; // disable monotonic timing
for _ in 0..2 { for _ in 0..2 {
cpu.multistep(&mut bus, 8) cpu.multistep(&mut bus, 8)
.expect("Running valid instructions should always succeed"); .expect("Running valid instructions should always succeed");

View File

@ -15,7 +15,7 @@ fn run_single_op(op: &[u8]) -> CPU {
Screen[0x0..0x1000], Screen[0x0..0x1000],
}, },
); );
cpu.screen cpu.mem
.load_region(Program, op).unwrap(); .load_region(Program, op).unwrap();
cpu.v = *INDX; cpu.v = *INDX;
cpu.flags.quirks = Quirks::from(false); cpu.flags.quirks = Quirks::from(false);