Fixed chip-8 access modifiers

This commit is contained in:
Marcus Vinicius de Carvalho 2021-07-28 12:54:24 +08:00
parent ab7ec2300a
commit d6430f0a2e
8 changed files with 224 additions and 142 deletions

View File

@ -5,12 +5,10 @@ use std::io::Read;
pub fn run() { pub fn run() {
let mut cpu = CPU::new(); let mut cpu = CPU::new();
cpu.ram.init_fonts(); //TODO: load in the RAM
cpu.clock.clock_hz = 60.;
load_rom("src/chip_8/roms/CAVE.ch8", &mut cpu); load_rom("src/chip_8/roms/CAVE.ch8", &mut cpu);
let sdl_context = sdl2::init().unwrap(); let sdl_context = sdl2::init().unwrap();
let mut display = Display::init(&sdl_context, cpu.db.scale); let mut display = Display::init(&sdl_context, cpu.get_display_scale());
let mut event_listener = sdl_context.event_pump().unwrap(); let mut event_listener = sdl_context.event_pump().unwrap();
'runner: loop { 'runner: loop {
@ -25,57 +23,48 @@ pub fn run() {
keycode: Some(sdl2::keyboard::Keycode::RightBracket), keycode: Some(sdl2::keyboard::Keycode::RightBracket),
.. ..
} => { } => {
println!( cpu.increase_clock(true);
"Increasing cpu clock from {:5} Hz to {:5} Hz",
cpu.clock.clock_hz,
cpu.clock.clock_hz + 10.
);
cpu.clock.clock_hz += 10.;
} }
sdl2::event::Event::KeyDown { sdl2::event::Event::KeyDown {
keycode: Some(sdl2::keyboard::Keycode::LeftBracket), keycode: Some(sdl2::keyboard::Keycode::LeftBracket),
.. ..
} => { } => {
println!( cpu.decrease_clock(true);
"Decreasing cpu clock from {:5} Hz to {:5} Hz",
cpu.clock.clock_hz,
cpu.clock.clock_hz - 10.
);
cpu.clock.clock_hz -= 10.;
} }
sdl2::event::Event::KeyDown { sdl2::event::Event::KeyDown {
keycode: Some(sdl2::keyboard::Keycode::Backspace), keycode: Some(sdl2::keyboard::Keycode::Backspace),
.. ..
} => { } => {
cpu.pc.0 = 0x200; cpu.reset_rom();
} }
sdl2::event::Event::KeyDown { sdl2::event::Event::KeyDown {
keycode: Some(keycode), keycode: Some(keycode),
.. ..
} => { } => {
if let Some(key_index) = cpu.keypad.compute_keycode(keycode) { if let Some(key_index) = cpu.compute_keycode(keycode) {
cpu.keypad.press(key_index); cpu.press_key(key_index);
} }
} }
sdl2::event::Event::KeyUp { sdl2::event::Event::KeyUp {
keycode: Some(keycode), keycode: Some(keycode),
.. ..
} => { } => {
if let Some(key_index) = cpu.keypad.compute_keycode(keycode) { if let Some(key_index) = cpu.compute_keycode(keycode) {
cpu.keypad.release(key_index); cpu.release_key(key_index);
} }
} }
_ => {} _ => {}
} }
} }
cpu.dt.tick(); cpu.tick_delay_timer();
cpu.st.tick(); cpu.tick_sound_timer();
if cpu.clock.tick() { if cpu.tick() {
cpu.fetch(); cpu.fetch();
cpu.decode(); cpu.decode();
if cpu.decode_match("D???") { if cpu.should_redraw {
display.draw(&cpu.db.db) display.draw(&cpu.get_display_buffer());
cpu.should_redraw = false;
} }
} }
} }
@ -86,5 +75,5 @@ fn load_rom(filename: &str, cpu: &mut CPU) {
let metadata = std::fs::metadata(&filename).expect("unable to read metadata"); let metadata = std::fs::metadata(&filename).expect("unable to read metadata");
let mut buffer = vec![0; metadata.len() as usize]; let mut buffer = vec![0; metadata.len() as usize];
f.read(&mut buffer).expect("buffer overflow"); f.read(&mut buffer).expect("buffer overflow");
cpu.ram.write_rom(&buffer); cpu.load_rom(&buffer);
} }

View File

@ -4,6 +4,5 @@ mod clock;
mod display_buffer; mod display_buffer;
mod keypad; mod keypad;
mod opcodes; mod opcodes;
mod program_counter;
mod ram; mod ram;
mod registers; mod registers;

View File

@ -2,7 +2,7 @@ use std::time::SystemTime;
pub struct Clock { pub struct Clock {
pub tick: u8, pub tick: u8,
pub clock_hz: f64, clock_hz: f64,
elapsed: SystemTime, elapsed: SystemTime,
} }
@ -34,11 +34,35 @@ impl Clock {
res res
} }
pub fn reset_elapsed(&mut self) { fn reset_elapsed(&mut self) {
self.elapsed = SystemTime::now(); self.elapsed = SystemTime::now();
} }
pub fn clock_hz_as_secs_f64(&self) -> f64 { pub fn clock_hz_as_secs_f64(&self) -> f64 {
1. / self.clock_hz 1. / self.clock_hz
} }
pub fn increase_clock(&mut self, is_printing: bool) {
if is_printing {
println!(
"Increasing cpu clock from {:5} Hz to {:5} Hz",
self.clock_hz,
self.clock_hz + 10.
);
}
self.clock_hz += 10.;
}
pub fn decrease_clock(&mut self, is_printing: bool) {
if self.clock_hz > 10. {
if is_printing {
println!(
"Decreasing cpu clock from {:5} Hz to {:5} Hz",
self.clock_hz,
self.clock_hz - 10.
);
}
self.clock_hz -= 10.;
}
}
} }

View File

@ -2,46 +2,48 @@ use super::clock::Clock;
use super::display_buffer::{DisplayBuffer, DISPLAY_HEIGHT, DISPLAY_WIDTH}; use super::display_buffer::{DisplayBuffer, DISPLAY_HEIGHT, DISPLAY_WIDTH};
use super::keypad::Keypad; use super::keypad::Keypad;
use super::opcodes::OpCodes; use super::opcodes::OpCodes;
use super::program_counter::ProgramCounter;
use super::ram::RAM; use super::ram::RAM;
use super::registers::Registers; use super::registers::Registers;
use sdl2::keyboard::Keycode;
use rand::Rng; use rand::Rng;
pub struct CPU { pub struct CPU {
pub pc: ProgramCounter, stack: Vec<usize>, // Function Stack
pub i: usize, dt: Clock, // Delay Timer
pub stack: Vec<usize>, st: Clock, // Sound Timer
pub dt: Clock, clock: Clock, // CPU Clock
pub st: Clock, regs: Registers, // Registers
pub clock: Clock, ram: RAM, // RAM
pub registers: Registers, keypad: Keypad, // Keypad
pub ram: RAM, db: DisplayBuffer, // Display Buffer
pub keypad: Keypad, op: OpCodes, // Operation Code,
pub db: DisplayBuffer, pub should_redraw: bool // Boolean indicating Display Buffer update
pub op: OpCodes,
} }
impl CPU { impl CPU {
pub fn new() -> CPU { pub fn new() -> CPU {
let mut ram = RAM::new();
ram.init_fonts();
CPU { CPU {
pc: ProgramCounter::new(),
i: 0,
stack: vec![], stack: vec![],
dt: Clock::new(), dt: Clock::new(),
st: Clock::new(), st: Clock::new(),
clock: Clock::new(), clock: Clock::new(),
registers: Registers::new(), regs: Registers::new(),
ram: RAM::new(), ram: ram,
keypad: Keypad::new(), keypad: Keypad::new(),
db: DisplayBuffer::new(10), db: DisplayBuffer::new(10),
op: OpCodes::new(0000), op: OpCodes::new(0000),
should_redraw: false
} }
} }
pub fn fetch(&mut self) { pub fn fetch(&mut self) {
self.op = OpCodes::new(self.ram.read16(self.pc.0)); self.op = OpCodes::new(self.ram.read16(self.regs.pc));
self.pc.increment(); self.regs.increment_pc();
} }
pub fn decode(&mut self) { pub fn decode(&mut self) {
@ -92,6 +94,7 @@ impl CPU {
op_cxnn(self); op_cxnn(self);
} else if self.decode_match("D???") { } else if self.decode_match("D???") {
op_dxyn(self); op_dxyn(self);
self.should_redraw = true;
} else if self.decode_match("E?9E") { } else if self.decode_match("E?9E") {
op_ex9e(self); op_ex9e(self);
} else if self.decode_match("E?A1") { } else if self.decode_match("E?A1") {
@ -119,7 +122,7 @@ impl CPU {
} }
} }
pub fn decode_match(&self, hex_code: &str) -> bool { fn decode_match(&self, hex_code: &str) -> bool {
assert!( assert!(
hex_code.len() == 4, hex_code.len() == 4,
"Instruction with wrong size. All chip-8 instructions have 16 bits" "Instruction with wrong size. All chip-8 instructions have 16 bits"
@ -155,6 +158,66 @@ impl CPU {
_ => false, _ => false,
} }
} }
pub fn reset_rom(&mut self) {
self.regs.reset_pc();
}
pub fn increase_clock(&mut self, is_printing: bool) {
self.clock.increase_clock(is_printing);
}
pub fn decrease_clock(&mut self, is_printing: bool) {
self.clock.decrease_clock(is_printing);
}
pub fn compute_keycode(&mut self, keycode: Keycode) -> Option<usize> {
self.keypad.compute_keycode(keycode)
}
pub fn press_key(&mut self, key_index: usize) {
self.keypad.press(key_index);
}
pub fn release_key(&mut self, key_index: usize) {
self.keypad.release(key_index);
}
pub fn get_delay_timer(&self) -> u8 {
self.dt.tick
}
pub fn set_delay_timer(&mut self, tick: u8) {
self.dt.tick = tick;
}
pub fn set_sound_timer(&mut self, tick: u8) {
self.st.tick = tick;
}
pub fn tick_delay_timer(&mut self) -> bool {
self.dt.tick()
}
pub fn tick_sound_timer(&mut self) -> bool {
self.st.tick()
}
pub fn tick(&mut self) -> bool {
self.clock.tick()
}
pub fn load_rom(&mut self, rom: &[u8]) {
self.ram.load_rom(rom);
}
pub fn get_display_scale(&self) -> u32 {
self.db.scale
}
pub fn get_display_buffer(&self) -> [[bool; DISPLAY_HEIGHT]; DISPLAY_WIDTH] {
self.db.db
}
} }
fn op_00e0(cpu: &mut CPU) { fn op_00e0(cpu: &mut CPU) {
@ -162,133 +225,133 @@ fn op_00e0(cpu: &mut CPU) {
} }
fn op_1nnn(cpu: &mut CPU) { fn op_1nnn(cpu: &mut CPU) {
cpu.pc.0 = cpu.op.nnn; cpu.regs.pc = cpu.op.nnn;
} }
fn op_00ee(cpu: &mut CPU) { fn op_00ee(cpu: &mut CPU) {
let value = cpu.stack.pop(); let value = cpu.stack.pop();
match value { match value {
Some(value) => { Some(value) => {
cpu.pc.0 = value; cpu.regs.pc = value;
} }
_ => {} _ => {}
} }
} }
fn op_2nnn(cpu: &mut CPU) { fn op_2nnn(cpu: &mut CPU) {
cpu.stack.push(cpu.pc.0); cpu.stack.push(cpu.regs.pc);
cpu.pc.0 = cpu.op.nnn; cpu.regs.pc = cpu.op.nnn;
} }
fn op_3xnn(cpu: &mut CPU) { fn op_3xnn(cpu: &mut CPU) {
if cpu.registers.get(cpu.op.x) == cpu.op.nn { if cpu.regs.get(cpu.op.x) == cpu.op.nn {
cpu.pc.increment(); cpu.regs.increment_pc();
} }
} }
fn op_4xnn(cpu: &mut CPU) { fn op_4xnn(cpu: &mut CPU) {
if cpu.registers.get(cpu.op.x) != cpu.op.nn { if cpu.regs.get(cpu.op.x) != cpu.op.nn {
cpu.pc.increment(); cpu.regs.increment_pc();
} }
} }
fn op_5xy0(cpu: &mut CPU) { fn op_5xy0(cpu: &mut CPU) {
if cpu.registers.get(cpu.op.x) == cpu.registers.get(cpu.op.y) { if cpu.regs.get(cpu.op.x) == cpu.regs.get(cpu.op.y) {
cpu.pc.increment(); cpu.regs.increment_pc();
} }
} }
fn op_9xy0(cpu: &mut CPU) { fn op_9xy0(cpu: &mut CPU) {
if cpu.registers.get(cpu.op.x) != cpu.registers.get(cpu.op.y) { if cpu.regs.get(cpu.op.x) != cpu.regs.get(cpu.op.y) {
cpu.pc.increment(); cpu.regs.increment_pc();
} }
} }
fn op_6xnn(cpu: &mut CPU) { fn op_6xnn(cpu: &mut CPU) {
cpu.registers.set(cpu.op.x, cpu.op.nn); cpu.regs.set(cpu.op.x, cpu.op.nn);
} }
fn op_7xnn(cpu: &mut CPU) { fn op_7xnn(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
cpu.registers.set(cpu.op.x, cpu.op.nn.wrapping_add(vx)); cpu.regs.set(cpu.op.x, cpu.op.nn.wrapping_add(vx));
} }
fn op_8xy0(cpu: &mut CPU) { fn op_8xy0(cpu: &mut CPU) {
let vy = cpu.registers.get(cpu.op.y); let vy = cpu.regs.get(cpu.op.y);
cpu.registers.set(cpu.op.x, vy); cpu.regs.set(cpu.op.x, vy);
} }
fn op_8xy1(cpu: &mut CPU) { fn op_8xy1(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
let vy = cpu.registers.get(cpu.op.y); let vy = cpu.regs.get(cpu.op.y);
cpu.registers.set(cpu.op.x, vx | vy); cpu.regs.set(cpu.op.x, vx | vy);
} }
fn op_8xy2(cpu: &mut CPU) { fn op_8xy2(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
let vy = cpu.registers.get(cpu.op.y); let vy = cpu.regs.get(cpu.op.y);
cpu.registers.set(cpu.op.x, vx & vy); cpu.regs.set(cpu.op.x, vx & vy);
} }
fn op_8xy3(cpu: &mut CPU) { fn op_8xy3(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
let vy = cpu.registers.get(cpu.op.y); let vy = cpu.regs.get(cpu.op.y);
cpu.registers.set(cpu.op.x, vx ^ vy); cpu.regs.set(cpu.op.x, vx ^ vy);
} }
fn op_8xy4(cpu: &mut CPU) { fn op_8xy4(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
let vy = cpu.registers.get(cpu.op.y); let vy = cpu.regs.get(cpu.op.y);
cpu.registers.set(cpu.op.x, vx.wrapping_add(vy)); cpu.regs.set(cpu.op.x, vx.wrapping_add(vy));
} }
fn op_8xy5(cpu: &mut CPU) { fn op_8xy5(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
let vy = cpu.registers.get(cpu.op.y); let vy = cpu.regs.get(cpu.op.y);
cpu.registers.set(cpu.op.x, vx.wrapping_sub(vy)); cpu.regs.set(cpu.op.x, vx.wrapping_sub(vy));
cpu.registers.x_f = if vx > vy { 1 } else { 0 }; cpu.regs.set(0xF, if vx > vy { 1 } else { 0 });
} }
fn op_8xy6(cpu: &mut CPU) { fn op_8xy6(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
let vy = cpu.registers.get(cpu.op.y); let vy = cpu.regs.get(cpu.op.y);
cpu.registers.set(cpu.op.x, vy >> 1); cpu.regs.set(cpu.op.x, vy >> 1);
cpu.registers.x_f = vx & 0x1; cpu.regs.set(0xF, vx & 0x1);
} }
fn op_8xy7(cpu: &mut CPU) { fn op_8xy7(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
let vy = cpu.registers.get(cpu.op.y); let vy = cpu.regs.get(cpu.op.y);
cpu.registers.set(cpu.op.x, vy.wrapping_sub(vx)); cpu.regs.set(cpu.op.x, vy.wrapping_sub(vx));
cpu.registers.x_f = if vy > vx { 1 } else { 0 }; cpu.regs.set(0xF, if vy > vx { 1 } else { 0 });
} }
fn op_8xye(cpu: &mut CPU) { fn op_8xye(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
let vy = cpu.registers.get(cpu.op.y); let vy = cpu.regs.get(cpu.op.y);
cpu.registers.set(cpu.op.x, vy << 1); cpu.regs.set(cpu.op.x, vy << 1);
cpu.registers.x_f = (vx & 0x80) >> 7; cpu.regs.set(0xF, (vx & 0x80) >> 7);
} }
fn op_annn(cpu: &mut CPU) { fn op_annn(cpu: &mut CPU) {
cpu.i = cpu.op.nnn; cpu.regs.i = cpu.op.nnn;
} }
fn op_bnnn(cpu: &mut CPU) { fn op_bnnn(cpu: &mut CPU) {
cpu.pc.0 = cpu.op.nnn + cpu.registers.x_0 as usize; cpu.regs.pc = cpu.op.nnn + cpu.regs.get(0x0) as usize;
} }
fn op_cxnn(cpu: &mut CPU) { fn op_cxnn(cpu: &mut CPU) {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
cpu.registers cpu.regs
.set(cpu.op.x, rng.gen_range(0x0..0xFF) & cpu.op.nn); .set(cpu.op.x, rng.gen_range(0x0..0xFF) & cpu.op.nn);
} }
fn op_dxyn(cpu: &mut CPU) { fn op_dxyn(cpu: &mut CPU) {
let mut vf: bool = false; let mut vf: bool = false;
let value = cpu.op.n as usize; let value = cpu.op.n as usize;
let ori_x = cpu.registers.get(cpu.op.x) as usize % DISPLAY_WIDTH; let ori_x = cpu.regs.get(cpu.op.x) as usize % DISPLAY_WIDTH;
let ori_y = cpu.registers.get(cpu.op.y) as usize % DISPLAY_HEIGHT; let ori_y = cpu.regs.get(cpu.op.y) as usize % DISPLAY_HEIGHT;
for row in 0..value { for row in 0..value {
let y = ori_y + row; let y = ori_y + row;
@ -296,7 +359,7 @@ fn op_dxyn(cpu: &mut CPU) {
break; break;
} }
let sprite = cpu.ram.read8(cpu.i + row); let sprite = cpu.ram.read8(cpu.regs.i + row);
for pixel_position in 0..8 { for pixel_position in 0..8 {
let x = ori_x + pixel_position; let x = ori_x + pixel_position;
if x >= DISPLAY_WIDTH { if x >= DISPLAY_WIDTH {
@ -309,70 +372,70 @@ fn op_dxyn(cpu: &mut CPU) {
vf = (memory_pixel && display_pixel) || vf; vf = (memory_pixel && display_pixel) || vf;
} }
} }
cpu.registers.x_f = if vf { 1 } else { 0 }; cpu.regs.set(0xF, if vf { 1 } else { 0 });
} }
fn op_ex9e(cpu: &mut CPU) { fn op_ex9e(cpu: &mut CPU) {
if cpu.keypad.get(cpu.registers.get(cpu.op.x) as usize) { if cpu.keypad.get_status(cpu.regs.get(cpu.op.x) as usize) {
cpu.pc.increment(); cpu.regs.increment_pc();
} }
} }
fn op_exa1(cpu: &mut CPU) { fn op_exa1(cpu: &mut CPU) {
if !cpu.keypad.get(cpu.registers.get(cpu.op.x) as usize) { if !cpu.keypad.get_status(cpu.regs.get(cpu.op.x) as usize) {
cpu.pc.increment(); cpu.regs.increment_pc();
} }
} }
fn op_fx07(cpu: &mut CPU) { fn op_fx07(cpu: &mut CPU) {
cpu.registers.set(cpu.op.x, cpu.dt.tick); cpu.regs.set(cpu.op.x, cpu.get_delay_timer());
} }
fn op_fx15(cpu: &mut CPU) { fn op_fx15(cpu: &mut CPU) {
cpu.dt.tick = cpu.registers.get(cpu.op.x); cpu.set_delay_timer(cpu.regs.get(cpu.op.x));
} }
fn op_fx18(cpu: &mut CPU) { fn op_fx18(cpu: &mut CPU) {
cpu.st.tick = cpu.registers.get(cpu.op.x); cpu.set_sound_timer(cpu.regs.get(cpu.op.x));
} }
fn op_fx1e(cpu: &mut CPU) { fn op_fx1e(cpu: &mut CPU) {
cpu.i += cpu.registers.get(cpu.op.x) as usize; cpu.regs.i += cpu.regs.get(cpu.op.x) as usize;
} }
fn op_fx0a(cpu: &mut CPU) { fn op_fx0a(cpu: &mut CPU) {
match cpu.keypad.being_pressed() { match cpu.keypad.being_pressed() {
Some(key) => { Some(key) => {
cpu.registers.set(cpu.op.x, key); cpu.regs.set(cpu.op.x, key);
} }
_ => { _ => {
cpu.pc.decrement(); cpu.regs.decrement_pc();
} }
} }
} }
fn op_fx29(cpu: &mut CPU) { fn op_fx29(cpu: &mut CPU) {
let char = (cpu.registers.get(cpu.op.x) & 0xF) as usize; let char = (cpu.regs.get(cpu.op.x) & 0xF) as usize;
cpu.i = cpu.ram.font_address + char * 5; cpu.regs.i = cpu.ram.get_font_address() + char * 5;
} }
fn op_fx33(cpu: &mut CPU) { fn op_fx33(cpu: &mut CPU) {
let vx = cpu.registers.get(cpu.op.x); let vx = cpu.regs.get(cpu.op.x);
cpu.ram.write(cpu.i, vx / 100); cpu.ram.write8(cpu.regs.i, vx / 100);
cpu.ram.write(cpu.i + 1, vx / 10 % 10); cpu.ram.write8(cpu.regs.i + 1, vx / 10 % 10);
cpu.ram.write(cpu.i + 2, vx % 10); cpu.ram.write8(cpu.regs.i + 2, vx % 10);
} }
fn op_fx55(cpu: &mut CPU) { fn op_fx55(cpu: &mut CPU) {
let i = cpu.i; let i = cpu.regs.i;
for regs in 0x0..(cpu.op.x + 1) { for regs in 0x0..(cpu.op.x + 1) {
cpu.ram.write(i + regs, cpu.registers.get(regs)); cpu.ram.write8(i + regs, cpu.regs.get(regs));
} }
} }
fn op_fx65(cpu: &mut CPU) { fn op_fx65(cpu: &mut CPU) {
let i = cpu.i; let i = cpu.regs.i;
for regs in 0x0..(cpu.op.x + 1) { for regs in 0x0..(cpu.op.x + 1) {
cpu.registers.set(regs, cpu.ram.read8(i + regs)); cpu.regs.set(regs, cpu.ram.read8(i + regs));
} }
} }

View File

@ -41,7 +41,7 @@ impl Keypad {
} }
} }
pub fn get(&mut self, pos: usize) -> bool { pub fn get_status(&mut self, pos: usize) -> bool {
self.key_status[pos] self.key_status[pos]
} }

View File

@ -1,15 +0,0 @@
pub struct ProgramCounter(pub usize);
impl ProgramCounter {
pub fn new() -> ProgramCounter {
ProgramCounter { 0: 0x200 }
}
pub fn increment(&mut self) {
self.0 += 2;
}
pub fn decrement(&mut self) {
self.0 -= 2;
}
}

View File

@ -1,6 +1,6 @@
pub struct RAM { pub struct RAM {
ram: [u8; 4 * 1024], ram: [u8; 4 * 1024],
pub font_address: usize, font_address: usize,
rom_address: usize, rom_address: usize,
} }
@ -37,7 +37,11 @@ impl RAM {
} }
} }
pub fn write_rom(&mut self, rom: &[u8]) { pub fn get_font_address(&self) -> usize {
self.font_address
}
pub fn load_rom(&mut self, rom: &[u8]) {
assert!( assert!(
rom.len() <= self.ram.len() - 0x200, rom.len() <= self.ram.len() - 0x200,
"ROM is bigger than Chip-8 RAM" "ROM is bigger than Chip-8 RAM"
@ -67,7 +71,7 @@ impl RAM {
(self.ram[addr] as u16) << 8 | self.ram[addr + 1] as u16 (self.ram[addr] as u16) << 8 | self.ram[addr + 1] as u16
} }
pub fn write(&mut self, addr: usize, value: u8) { pub fn write8(&mut self, addr: usize, value: u8) {
assert!( assert!(
addr < self.ram.len(), addr < self.ram.len(),
"addr = {}, self.0.len() = {}", "addr = {}, self.0.len() = {}",

View File

@ -1,5 +1,7 @@
const INITIAL_PC: usize = 0x200;
pub struct Registers { pub struct Registers {
pub x_0: u8, x_0: u8,
x_1: u8, x_1: u8,
x_2: u8, x_2: u8,
x_3: u8, x_3: u8,
@ -14,7 +16,9 @@ pub struct Registers {
x_c: u8, x_c: u8,
x_d: u8, x_d: u8,
x_e: u8, x_e: u8,
pub x_f: u8, x_f: u8, // Flag register
pub pc: usize, // Program Counter
pub i: usize // Index register
} }
impl Registers { impl Registers {
@ -36,6 +40,8 @@ impl Registers {
x_d: 0, x_d: 0,
x_e: 0, x_e: 0,
x_f: 0, x_f: 0,
pc: INITIAL_PC,
i: 0,
} }
} }
@ -84,4 +90,16 @@ impl Registers {
_ => {} _ => {}
} }
} }
pub fn increment_pc(&mut self) {
self.pc += 2;
}
pub fn decrement_pc(&mut self) {
self.pc -= 2;
}
pub fn reset_pc(&mut self) {
self.pc = INITIAL_PC;
}
} }