mirror of https://github.com/Ivsucram/ivsemu.git
Fixed chip-8 access modifiers
This commit is contained in:
parent
ab7ec2300a
commit
d6430f0a2e
|
@ -5,12 +5,10 @@ use std::io::Read;
|
|||
|
||||
pub fn run() {
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
'runner: loop {
|
||||
|
@ -25,57 +23,48 @@ pub fn run() {
|
|||
keycode: Some(sdl2::keyboard::Keycode::RightBracket),
|
||||
..
|
||||
} => {
|
||||
println!(
|
||||
"Increasing cpu clock from {:5} Hz to {:5} Hz",
|
||||
cpu.clock.clock_hz,
|
||||
cpu.clock.clock_hz + 10.
|
||||
);
|
||||
cpu.clock.clock_hz += 10.;
|
||||
cpu.increase_clock(true);
|
||||
}
|
||||
sdl2::event::Event::KeyDown {
|
||||
keycode: Some(sdl2::keyboard::Keycode::LeftBracket),
|
||||
..
|
||||
} => {
|
||||
println!(
|
||||
"Decreasing cpu clock from {:5} Hz to {:5} Hz",
|
||||
cpu.clock.clock_hz,
|
||||
cpu.clock.clock_hz - 10.
|
||||
);
|
||||
cpu.clock.clock_hz -= 10.;
|
||||
cpu.decrease_clock(true);
|
||||
}
|
||||
sdl2::event::Event::KeyDown {
|
||||
keycode: Some(sdl2::keyboard::Keycode::Backspace),
|
||||
..
|
||||
} => {
|
||||
cpu.pc.0 = 0x200;
|
||||
cpu.reset_rom();
|
||||
}
|
||||
sdl2::event::Event::KeyDown {
|
||||
keycode: Some(keycode),
|
||||
..
|
||||
} => {
|
||||
if let Some(key_index) = cpu.keypad.compute_keycode(keycode) {
|
||||
cpu.keypad.press(key_index);
|
||||
if let Some(key_index) = cpu.compute_keycode(keycode) {
|
||||
cpu.press_key(key_index);
|
||||
}
|
||||
}
|
||||
sdl2::event::Event::KeyUp {
|
||||
keycode: Some(keycode),
|
||||
..
|
||||
} => {
|
||||
if let Some(key_index) = cpu.keypad.compute_keycode(keycode) {
|
||||
cpu.keypad.release(key_index);
|
||||
if let Some(key_index) = cpu.compute_keycode(keycode) {
|
||||
cpu.release_key(key_index);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
cpu.dt.tick();
|
||||
cpu.st.tick();
|
||||
if cpu.clock.tick() {
|
||||
cpu.tick_delay_timer();
|
||||
cpu.tick_sound_timer();
|
||||
if cpu.tick() {
|
||||
cpu.fetch();
|
||||
cpu.decode();
|
||||
if cpu.decode_match("D???") {
|
||||
display.draw(&cpu.db.db)
|
||||
if cpu.should_redraw {
|
||||
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 mut buffer = vec![0; metadata.len() as usize];
|
||||
f.read(&mut buffer).expect("buffer overflow");
|
||||
cpu.ram.write_rom(&buffer);
|
||||
cpu.load_rom(&buffer);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,5 @@ mod clock;
|
|||
mod display_buffer;
|
||||
mod keypad;
|
||||
mod opcodes;
|
||||
mod program_counter;
|
||||
mod ram;
|
||||
mod registers;
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::time::SystemTime;
|
|||
|
||||
pub struct Clock {
|
||||
pub tick: u8,
|
||||
pub clock_hz: f64,
|
||||
clock_hz: f64,
|
||||
elapsed: SystemTime,
|
||||
}
|
||||
|
||||
|
@ -34,11 +34,35 @@ impl Clock {
|
|||
res
|
||||
}
|
||||
|
||||
pub fn reset_elapsed(&mut self) {
|
||||
fn reset_elapsed(&mut self) {
|
||||
self.elapsed = SystemTime::now();
|
||||
}
|
||||
|
||||
pub fn clock_hz_as_secs_f64(&self) -> f64 {
|
||||
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.;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,46 +2,48 @@ use super::clock::Clock;
|
|||
use super::display_buffer::{DisplayBuffer, DISPLAY_HEIGHT, DISPLAY_WIDTH};
|
||||
use super::keypad::Keypad;
|
||||
use super::opcodes::OpCodes;
|
||||
use super::program_counter::ProgramCounter;
|
||||
use super::ram::RAM;
|
||||
use super::registers::Registers;
|
||||
|
||||
use sdl2::keyboard::Keycode;
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
pub struct CPU {
|
||||
pub pc: ProgramCounter,
|
||||
pub i: usize,
|
||||
pub stack: Vec<usize>,
|
||||
pub dt: Clock,
|
||||
pub st: Clock,
|
||||
pub clock: Clock,
|
||||
pub registers: Registers,
|
||||
pub ram: RAM,
|
||||
pub keypad: Keypad,
|
||||
pub db: DisplayBuffer,
|
||||
pub op: OpCodes,
|
||||
stack: Vec<usize>, // Function Stack
|
||||
dt: Clock, // Delay Timer
|
||||
st: Clock, // Sound Timer
|
||||
clock: Clock, // CPU Clock
|
||||
regs: Registers, // Registers
|
||||
ram: RAM, // RAM
|
||||
keypad: Keypad, // Keypad
|
||||
db: DisplayBuffer, // Display Buffer
|
||||
op: OpCodes, // Operation Code,
|
||||
pub should_redraw: bool // Boolean indicating Display Buffer update
|
||||
}
|
||||
|
||||
impl CPU {
|
||||
pub fn new() -> CPU {
|
||||
let mut ram = RAM::new();
|
||||
ram.init_fonts();
|
||||
|
||||
CPU {
|
||||
pc: ProgramCounter::new(),
|
||||
i: 0,
|
||||
stack: vec![],
|
||||
dt: Clock::new(),
|
||||
st: Clock::new(),
|
||||
clock: Clock::new(),
|
||||
registers: Registers::new(),
|
||||
ram: RAM::new(),
|
||||
regs: Registers::new(),
|
||||
ram: ram,
|
||||
keypad: Keypad::new(),
|
||||
db: DisplayBuffer::new(10),
|
||||
op: OpCodes::new(0000),
|
||||
should_redraw: false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fetch(&mut self) {
|
||||
self.op = OpCodes::new(self.ram.read16(self.pc.0));
|
||||
self.pc.increment();
|
||||
self.op = OpCodes::new(self.ram.read16(self.regs.pc));
|
||||
self.regs.increment_pc();
|
||||
}
|
||||
|
||||
pub fn decode(&mut self) {
|
||||
|
@ -92,6 +94,7 @@ impl CPU {
|
|||
op_cxnn(self);
|
||||
} else if self.decode_match("D???") {
|
||||
op_dxyn(self);
|
||||
self.should_redraw = true;
|
||||
} else if self.decode_match("E?9E") {
|
||||
op_ex9e(self);
|
||||
} 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!(
|
||||
hex_code.len() == 4,
|
||||
"Instruction with wrong size. All chip-8 instructions have 16 bits"
|
||||
|
@ -155,6 +158,66 @@ impl CPU {
|
|||
_ => 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) {
|
||||
|
@ -162,133 +225,133 @@ fn op_00e0(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) {
|
||||
let value = cpu.stack.pop();
|
||||
match value {
|
||||
Some(value) => {
|
||||
cpu.pc.0 = value;
|
||||
cpu.regs.pc = value;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn op_2nnn(cpu: &mut CPU) {
|
||||
cpu.stack.push(cpu.pc.0);
|
||||
cpu.pc.0 = cpu.op.nnn;
|
||||
cpu.stack.push(cpu.regs.pc);
|
||||
cpu.regs.pc = cpu.op.nnn;
|
||||
}
|
||||
|
||||
fn op_3xnn(cpu: &mut CPU) {
|
||||
if cpu.registers.get(cpu.op.x) == cpu.op.nn {
|
||||
cpu.pc.increment();
|
||||
if cpu.regs.get(cpu.op.x) == cpu.op.nn {
|
||||
cpu.regs.increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
fn op_4xnn(cpu: &mut CPU) {
|
||||
if cpu.registers.get(cpu.op.x) != cpu.op.nn {
|
||||
cpu.pc.increment();
|
||||
if cpu.regs.get(cpu.op.x) != cpu.op.nn {
|
||||
cpu.regs.increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
fn op_5xy0(cpu: &mut CPU) {
|
||||
if cpu.registers.get(cpu.op.x) == cpu.registers.get(cpu.op.y) {
|
||||
cpu.pc.increment();
|
||||
if cpu.regs.get(cpu.op.x) == cpu.regs.get(cpu.op.y) {
|
||||
cpu.regs.increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
fn op_9xy0(cpu: &mut CPU) {
|
||||
if cpu.registers.get(cpu.op.x) != cpu.registers.get(cpu.op.y) {
|
||||
cpu.pc.increment();
|
||||
if cpu.regs.get(cpu.op.x) != cpu.regs.get(cpu.op.y) {
|
||||
cpu.regs.increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
cpu.registers.set(cpu.op.x, cpu.op.nn.wrapping_add(vx));
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
cpu.regs.set(cpu.op.x, cpu.op.nn.wrapping_add(vx));
|
||||
}
|
||||
|
||||
fn op_8xy0(cpu: &mut CPU) {
|
||||
let vy = cpu.registers.get(cpu.op.y);
|
||||
cpu.registers.set(cpu.op.x, vy);
|
||||
let vy = cpu.regs.get(cpu.op.y);
|
||||
cpu.regs.set(cpu.op.x, vy);
|
||||
}
|
||||
|
||||
fn op_8xy1(cpu: &mut CPU) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
let vy = cpu.registers.get(cpu.op.y);
|
||||
cpu.registers.set(cpu.op.x, vx | vy);
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
let vy = cpu.regs.get(cpu.op.y);
|
||||
cpu.regs.set(cpu.op.x, vx | vy);
|
||||
}
|
||||
|
||||
fn op_8xy2(cpu: &mut CPU) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
let vy = cpu.registers.get(cpu.op.y);
|
||||
cpu.registers.set(cpu.op.x, vx & vy);
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
let vy = cpu.regs.get(cpu.op.y);
|
||||
cpu.regs.set(cpu.op.x, vx & vy);
|
||||
}
|
||||
|
||||
fn op_8xy3(cpu: &mut CPU) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
let vy = cpu.registers.get(cpu.op.y);
|
||||
cpu.registers.set(cpu.op.x, vx ^ vy);
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
let vy = cpu.regs.get(cpu.op.y);
|
||||
cpu.regs.set(cpu.op.x, vx ^ vy);
|
||||
}
|
||||
|
||||
fn op_8xy4(cpu: &mut CPU) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
let vy = cpu.registers.get(cpu.op.y);
|
||||
cpu.registers.set(cpu.op.x, vx.wrapping_add(vy));
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
let vy = cpu.regs.get(cpu.op.y);
|
||||
cpu.regs.set(cpu.op.x, vx.wrapping_add(vy));
|
||||
}
|
||||
|
||||
fn op_8xy5(cpu: &mut CPU) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
let vy = cpu.registers.get(cpu.op.y);
|
||||
cpu.registers.set(cpu.op.x, vx.wrapping_sub(vy));
|
||||
cpu.registers.x_f = if vx > vy { 1 } else { 0 };
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
let vy = cpu.regs.get(cpu.op.y);
|
||||
cpu.regs.set(cpu.op.x, vx.wrapping_sub(vy));
|
||||
cpu.regs.set(0xF, if vx > vy { 1 } else { 0 });
|
||||
}
|
||||
|
||||
fn op_8xy6(cpu: &mut CPU) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
let vy = cpu.registers.get(cpu.op.y);
|
||||
cpu.registers.set(cpu.op.x, vy >> 1);
|
||||
cpu.registers.x_f = vx & 0x1;
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
let vy = cpu.regs.get(cpu.op.y);
|
||||
cpu.regs.set(cpu.op.x, vy >> 1);
|
||||
cpu.regs.set(0xF, vx & 0x1);
|
||||
}
|
||||
|
||||
fn op_8xy7(cpu: &mut CPU) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
let vy = cpu.registers.get(cpu.op.y);
|
||||
cpu.registers.set(cpu.op.x, vy.wrapping_sub(vx));
|
||||
cpu.registers.x_f = if vy > vx { 1 } else { 0 };
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
let vy = cpu.regs.get(cpu.op.y);
|
||||
cpu.regs.set(cpu.op.x, vy.wrapping_sub(vx));
|
||||
cpu.regs.set(0xF, if vy > vx { 1 } else { 0 });
|
||||
}
|
||||
|
||||
fn op_8xye(cpu: &mut CPU) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
let vy = cpu.registers.get(cpu.op.y);
|
||||
cpu.registers.set(cpu.op.x, vy << 1);
|
||||
cpu.registers.x_f = (vx & 0x80) >> 7;
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
let vy = cpu.regs.get(cpu.op.y);
|
||||
cpu.regs.set(cpu.op.x, vy << 1);
|
||||
cpu.regs.set(0xF, (vx & 0x80) >> 7);
|
||||
}
|
||||
|
||||
fn op_annn(cpu: &mut CPU) {
|
||||
cpu.i = cpu.op.nnn;
|
||||
cpu.regs.i = cpu.op.nnn;
|
||||
}
|
||||
|
||||
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) {
|
||||
let mut rng = rand::thread_rng();
|
||||
cpu.registers
|
||||
cpu.regs
|
||||
.set(cpu.op.x, rng.gen_range(0x0..0xFF) & cpu.op.nn);
|
||||
}
|
||||
|
||||
fn op_dxyn(cpu: &mut CPU) {
|
||||
let mut vf: bool = false;
|
||||
let value = cpu.op.n as usize;
|
||||
let ori_x = cpu.registers.get(cpu.op.x) as usize % DISPLAY_WIDTH;
|
||||
let ori_y = cpu.registers.get(cpu.op.y) as usize % DISPLAY_HEIGHT;
|
||||
let ori_x = cpu.regs.get(cpu.op.x) as usize % DISPLAY_WIDTH;
|
||||
let ori_y = cpu.regs.get(cpu.op.y) as usize % DISPLAY_HEIGHT;
|
||||
|
||||
for row in 0..value {
|
||||
let y = ori_y + row;
|
||||
|
@ -296,7 +359,7 @@ fn op_dxyn(cpu: &mut CPU) {
|
|||
break;
|
||||
}
|
||||
|
||||
let sprite = cpu.ram.read8(cpu.i + row);
|
||||
let sprite = cpu.ram.read8(cpu.regs.i + row);
|
||||
for pixel_position in 0..8 {
|
||||
let x = ori_x + pixel_position;
|
||||
if x >= DISPLAY_WIDTH {
|
||||
|
@ -309,70 +372,70 @@ fn op_dxyn(cpu: &mut CPU) {
|
|||
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) {
|
||||
if cpu.keypad.get(cpu.registers.get(cpu.op.x) as usize) {
|
||||
cpu.pc.increment();
|
||||
if cpu.keypad.get_status(cpu.regs.get(cpu.op.x) as usize) {
|
||||
cpu.regs.increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
fn op_exa1(cpu: &mut CPU) {
|
||||
if !cpu.keypad.get(cpu.registers.get(cpu.op.x) as usize) {
|
||||
cpu.pc.increment();
|
||||
if !cpu.keypad.get_status(cpu.regs.get(cpu.op.x) as usize) {
|
||||
cpu.regs.increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
match cpu.keypad.being_pressed() {
|
||||
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) {
|
||||
let char = (cpu.registers.get(cpu.op.x) & 0xF) as usize;
|
||||
cpu.i = cpu.ram.font_address + char * 5;
|
||||
let char = (cpu.regs.get(cpu.op.x) & 0xF) as usize;
|
||||
cpu.regs.i = cpu.ram.get_font_address() + char * 5;
|
||||
}
|
||||
|
||||
fn op_fx33(cpu: &mut CPU) {
|
||||
let vx = cpu.registers.get(cpu.op.x);
|
||||
cpu.ram.write(cpu.i, vx / 100);
|
||||
cpu.ram.write(cpu.i + 1, vx / 10 % 10);
|
||||
cpu.ram.write(cpu.i + 2, vx % 10);
|
||||
let vx = cpu.regs.get(cpu.op.x);
|
||||
cpu.ram.write8(cpu.regs.i, vx / 100);
|
||||
cpu.ram.write8(cpu.regs.i + 1, vx / 10 % 10);
|
||||
cpu.ram.write8(cpu.regs.i + 2, vx % 10);
|
||||
}
|
||||
|
||||
fn op_fx55(cpu: &mut CPU) {
|
||||
let i = cpu.i;
|
||||
let i = cpu.regs.i;
|
||||
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) {
|
||||
let i = cpu.i;
|
||||
let i = cpu.regs.i;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
pub struct RAM {
|
||||
ram: [u8; 4 * 1024],
|
||||
pub font_address: usize,
|
||||
font_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!(
|
||||
rom.len() <= self.ram.len() - 0x200,
|
||||
"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
|
||||
}
|
||||
|
||||
pub fn write(&mut self, addr: usize, value: u8) {
|
||||
pub fn write8(&mut self, addr: usize, value: u8) {
|
||||
assert!(
|
||||
addr < self.ram.len(),
|
||||
"addr = {}, self.0.len() = {}",
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
const INITIAL_PC: usize = 0x200;
|
||||
|
||||
pub struct Registers {
|
||||
pub x_0: u8,
|
||||
x_0: u8,
|
||||
x_1: u8,
|
||||
x_2: u8,
|
||||
x_3: u8,
|
||||
|
@ -14,7 +16,9 @@ pub struct Registers {
|
|||
x_c: u8,
|
||||
x_d: 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 {
|
||||
|
@ -36,6 +40,8 @@ impl Registers {
|
|||
x_d: 0,
|
||||
x_e: 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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue