use sdl2::keyboard::Keycode; use sdl2::rect::Rect; use std::io; use std::io::prelude::*; use std::fs::File; pub const WIDTH : u32 = 32; pub const HEIGHT : u32 = 64; pub const SCALE : u32 = 20; //length for the array of display "pixels" where pixels are the rectangles being rendered const DISPLAY_LENGTH : usize = (WIDTH * HEIGHT) as usize; //Basic struct to represent the Chip-8 interpreter structure pub struct Chip { mem : [u8; 4096], //4kb of memory registers: [u8; 16], //16 8-bit registers index: u16, //16-bit index pointer pc: u16, //Program counter stack: [u16; 16], //16 level stack sp: u8, //stack pointer delay_timer: u8, //delay timer sound_timer: u8, //sound timer keys : [Keycode; 16], //mapping keys to chip-8 input keys fonts : [u8; 80], //all the 16 chars that can be rendered 16 * 5 display: [Rect; DISPLAY_LENGTH as usize] //the display array } impl Chip { //return a new Chip, with memory 0-initialized pub fn new() -> Self { Chip { mem : [0; 4096], registers: [0; 16], index: 0, pc: 0, stack: [0; 16], sp: 0, delay_timer: 0, sound_timer: 0, keys: [Keycode::Num1, Keycode::Num2, Keycode::Num3, Keycode::Num4, Keycode::Q, Keycode::W, Keycode::E, Keycode::R, Keycode::A, Keycode::S, Keycode::D, Keycode::F, Keycode::Z, Keycode::X, Keycode::C, Keycode::V], fonts: [ 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 0x20, 0x60, 0x20, 0x20, 0x70, // 1 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3 0x90, 0x90, 0xF0, 0x10, 0x10, // 4 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6 0xF0, 0x10, 0x20, 0x40, 0x40, // 7 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9 0xF0, 0x90, 0xF0, 0x90, 0x90, // A 0xE0, 0x90, 0xE0, 0x90, 0xE0, // B 0xF0, 0x80, 0x80, 0x80, 0xF0, // C 0xE0, 0x90, 0x90, 0x90, 0xE0, // D 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E 0xF0, 0x80, 0xF0, 0x80, 0x80 // F ], display: [Rect::new(0, 0, SCALE - 1, SCALE - 1); DISPLAY_LENGTH], } } //initialize memory with all the starting values pub fn init(&mut self) { for i in 0..80 { self.mem[0x50 + i] = self.fonts[i]; } } pub fn read_rom(&mut self, rom : &str) { let mut buf = Vec::new(); let mut rom = File::open(rom).unwrap_or_else(|_err| panic!("Valid ROM needed")); rom.read_to_end(&mut buf).unwrap_or_else(|_err| panic!("Error reading ROM")); let mut start = 0x200; for i in buf { self.mem[start] = i; start += 1; } println!("{:?}", self.mem); } pub fn fetch(&mut self) { let instr = (self.mem[self.pc as usize] << 8) | self.mem[self.pc + 1 as usize]; self.pc += 2; } //render the current grid of pixels accounting for scale pub fn render(&mut self) -> &[Rect] { for idx in 0..DISPLAY_LENGTH { let (mut x_coord, mut y_coord) : (i32, i32) =((idx as i32 % WIDTH as i32), (idx as i32 / WIDTH as i32)); x_coord *= SCALE as i32; y_coord *= SCALE as i32; self.display[idx].set_x(x_coord); self.display[idx].set_y(y_coord); } &self.display } }