Add ROM loading and basic opcode support
This commit is contained in:
parent
408480a4ef
commit
b105e8ca1e
|
@ -1,13 +1,13 @@
|
|||
use crate::chip8::audio::Speaker;
|
||||
use crate::chip8::display::Screen;
|
||||
use crate::chip8::keyboard::Keyboard;
|
||||
use crate::chip8::memory::Memory;
|
||||
use crate::chip8::memory::{Memory, MEMORY_SIZE, PROGRAM_LOAD_ADDRESS};
|
||||
use crate::chip8::registers::{Register, Registers};
|
||||
use crate::chip8::stack::Stack;
|
||||
|
||||
use sdl2::AudioSubsystem;
|
||||
|
||||
use std::{thread, time::Duration};
|
||||
use std::{fs, thread, time::Duration};
|
||||
|
||||
pub struct Chip8 {
|
||||
pub memory: Memory,
|
||||
|
@ -30,11 +30,6 @@ impl Chip8 {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn handle_timers(&mut self) -> () {
|
||||
self.handle_delay_timer();
|
||||
self.handle_sound_timer();
|
||||
}
|
||||
|
||||
pub fn handle_delay_timer(&mut self) -> () {
|
||||
let delay_timer = self.registers.get(Register::DT);
|
||||
if delay_timer > 0 {
|
||||
|
@ -52,4 +47,26 @@ impl Chip8 {
|
|||
self.registers.set(Register::ST, sound_timer - 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_rom(&mut self, file: &str) -> usize {
|
||||
let rom = fs::read(file).expect("Cannot read ROM");
|
||||
let rom_length = rom.len();
|
||||
|
||||
if rom_length > MEMORY_SIZE - PROGRAM_LOAD_ADDRESS {
|
||||
panic!("ROM too big, aborting")
|
||||
}
|
||||
|
||||
for (i, byte) in rom.iter().enumerate() {
|
||||
self.memory.set(PROGRAM_LOAD_ADDRESS + i, *byte);
|
||||
}
|
||||
|
||||
rom_length
|
||||
}
|
||||
|
||||
pub fn exec(&mut self) {
|
||||
let pc = self.registers.get(Register::PC);
|
||||
let opcode = self.memory.read_opcode(pc as usize);
|
||||
println!("{}", opcode);
|
||||
self.registers.set(Register::PC, pc + 2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const MEMORY_SIZE: usize = 4096;
|
||||
pub const MEMORY_SIZE: usize = 4096;
|
||||
pub const PROGRAM_LOAD_ADDRESS: usize = 0x200;
|
||||
|
||||
const DEFAULT_CHARACTER_SET_START: usize = 0;
|
||||
|
||||
|
@ -53,6 +54,11 @@ impl Memory {
|
|||
pub fn read(&self, start: usize, bytes: u8) -> &[u8] {
|
||||
&self.memory[start..start + bytes as usize]
|
||||
}
|
||||
|
||||
pub fn read_opcode(&self, start: usize) -> u16 {
|
||||
let bytes = self.read(start, 2);
|
||||
(bytes[0] as u16) << 8 | bytes[1] as u16
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use super::memory::PROGRAM_LOAD_ADDRESS;
|
||||
|
||||
const DATA_REGISTERS: usize = 16;
|
||||
|
||||
pub enum Register {
|
||||
|
@ -62,7 +64,7 @@ impl Registers {
|
|||
i: 0,
|
||||
delay_timer: 0,
|
||||
sound_timer: 0,
|
||||
pc: 0,
|
||||
pc: PROGRAM_LOAD_ADDRESS as u16,
|
||||
sp: 0,
|
||||
}
|
||||
}
|
||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -8,18 +8,37 @@ use sdl2::keyboard::Keycode;
|
|||
use sdl2::pixels::Color;
|
||||
use sdl2::rect::Rect;
|
||||
|
||||
use std::env;
|
||||
|
||||
const EMULATOR_WINDOW_TITLE: &str = "Rust CHIP-8";
|
||||
|
||||
fn main() -> Result<(), String> {
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() < 2 {
|
||||
println!("USAGE: {} <path to ROM>", &args[0]);
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
std::process::exit(match run(&args[1]) {
|
||||
Ok(_) => 0,
|
||||
Err(err) => {
|
||||
eprintln!("ERROR: {:?}", err);
|
||||
1
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn run(rom: &str) -> Result<(), String> {
|
||||
print!("Initializing SDL: ");
|
||||
let sdl_context = sdl2::init()?;
|
||||
let video_subsystem = sdl_context.video()?;
|
||||
let audio_subsystem = sdl_context.audio()?;
|
||||
println!("Done");
|
||||
|
||||
let mut chip8 = Chip8::new(&audio_subsystem);
|
||||
chip8.screen.draw_sprite(24, 13, chip8.memory.read(20, 5));
|
||||
chip8.screen.draw_sprite(29, 13, chip8.memory.read(10, 5));
|
||||
chip8.screen.draw_sprite(34, 13, chip8.memory.read(40, 5));
|
||||
chip8.registers.set(chip8::registers::Register::ST, 5);
|
||||
print!("Loading ROM: {}: ", &rom);
|
||||
let bytes = chip8.load_rom(rom);
|
||||
println!("Done ({} bytes)", bytes);
|
||||
|
||||
let window = video_subsystem
|
||||
.window(
|
||||
|
@ -89,6 +108,8 @@ fn main() -> Result<(), String> {
|
|||
canvas.present();
|
||||
chip8.handle_delay_timer();
|
||||
chip8.handle_sound_timer();
|
||||
|
||||
chip8.exec();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in New Issue