diff --git a/src/machine.rs b/src/machine.rs new file mode 100644 index 0000000..ab5608c --- /dev/null +++ b/src/machine.rs @@ -0,0 +1,337 @@ +/* +* Chip8 emulator +* +* Copyright (C) 2022 rick G. +* +* This program is free software: you can redistribute it and/or modify it under +* the terms of the GNU General Public License as published by the Free Software +* Foundation, either version 3 of the License, or (at your option) any later +* version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see . +*/ + +const FONT: [u8; 80] = [ + 0xF0, 0x90, 0x90, 0x90, 0xF0, + 0x20, 0x60, 0x20, 0x20, 0x70, + 0xF0, 0x10, 0xF0, 0x80, 0xF0, + 0xF0, 0x10, 0xF0, 0x10, 0xF0, + 0x90, 0x90, 0xF0, 0x10, 0x10, + 0xF0, 0x80, 0xF0, 0x10, 0xF0, + 0xF0, 0x80, 0xF0, 0x90, 0xF0, + 0xF0, 0x10, 0x20, 0x40, 0x40, + 0xF0, 0x90, 0xF0, 0x90, 0xF0, + 0xF0, 0x90, 0xF0, 0x10, 0xF0, + 0xF0, 0x90, 0xF0, 0x90, 0x90, + 0xE0, 0x90, 0xE0, 0x90, 0xE0, + 0xF0, 0x80, 0x80, 0x80, 0xF0, + 0xE0, 0x90, 0x90, 0x90, 0xE0, + 0xF0, 0x80, 0xF0, 0x80, 0xF0, + 0xF0, 0x80, 0xF0, 0x80, 0x80 +]; + +pub const HEIGHT: usize = 32; +pub const WIDTH: usize = 64; + +extern crate sdl2; +extern crate rand; + +pub use sdl2::pixels::Color; +pub use sdl2::event::Event; +pub use sdl2::EventPump; +pub use sdl2::keyboard::Keycode; +pub use sdl2::video::Window; +pub use sdl2::rect::Point; +pub use sdl2::render::Canvas; + +pub use std::fs::File; +pub use std::path::Path; +pub use std::io; +pub use std::io::Read; + +pub struct Machine { + memory: [u8; 4096], + pub key_inputs: [u8; 16], + pub display_buffer: [[i32; WIDTH]; HEIGHT], + gpio: [u8; 16], + index: u16, + pc: usize, + stack: Vec, + dt: u8, + st: u8, +} + +impl Machine { + /// Initialise une machine en mettant tout à 0 (RAM, PC...) + pub fn new() -> Self { + Self { + memory: [0; 4096], + key_inputs: [0; 16], + display_buffer: [[0; WIDTH]; HEIGHT], + gpio: [0; 16], + index: 0, + pc: 0, + stack: Vec::new(), + dt: 0, + st: 0, + } + } + + pub fn init(&mut self) { + for i in 0..FONT.len() { + self.memory[i] = FONT[i]; + } + + self.pc = 0x200; + } + + /// charge une ROM en mémoire + pub fn load_rom(&mut self, p: &Path) -> io::Result<()> { + let mut buffer = Vec::new(); + let mut f = File::open(p)?; + f.read_to_end(&mut buffer)?; + + for i in 0..buffer.len() { + self.memory[i + 0x200] = buffer[i]; + } + + Ok(()) + } + + pub fn cycle(&mut self, screen: &mut Canvas, events: &mut EventPump) { + let opcode = ((self.memory[self.pc] as u16) << 8) + + (self.memory[self.pc + 1] as u16); + + let vx: usize = ((opcode & 0x0f00) >> 8) as usize; + let vy: usize = ((opcode & 0x00f0) >> 4) as usize; + let k: u8 = (opcode & 0x00ff) as u8; + + self.pc += 2; + + if self.dt > 0 { + self.dt -= 1; + } + + if self.st > 0 { + self.st -= 1; + if self.st == 0 { + println!("BUZZZ!!"); + } + } + + match (opcode & 0xf000) >> 12 { + 0 => match opcode { + 0x00E0 => { + self.display_buffer = [[0; 64]; 32]; + screen.set_draw_color(Color::RGB(0, 0, 0)); + screen.clear(); + screen.present(); + }, + 0x00EE => self.pc = self.stack.pop().unwrap() as usize, + _ => println!("SYS"), + } + 1 => self.pc = (opcode & 0x0fff) as usize, + 2 => { + self.stack.push(self.pc as u16); + self.pc = (opcode & 0x0fff) as usize + }, + 3 => if self.gpio[vx] == k as u8 { + self.pc += 2; + }, + 4 => if self.gpio[vx] != k as u8 { + self.pc += 2; + }, + 5 => if self.gpio[vx] == self.gpio[vy] { + self.pc += 2; + } + 6 => self.gpio[vx] = k, + 7 => self.gpio[vx] = self.gpio[vx].saturating_add(k), + 8 => { + match opcode & 0x000f { + 0 => self.gpio[vx] = self.gpio[vy], + 1 => self.gpio[vx] |= self.gpio[vy], + 2 => self.gpio[vx] &= self.gpio[vy], + 3 => self.gpio[vx] ^= self.gpio[vy], + 4 => { + self.gpio[vx] = self.gpio[vx].saturating_add(self.gpio[vy]); + let (_, overflow) = self.gpio[vx].overflowing_add(self.gpio[vy]); + if overflow { + self.gpio[0xf] = 1; + } + }, + 5 => { + if self.gpio[vx] > self.gpio[vy] { + self.gpio[0xf] = 1; + } else { + self.gpio[0xf] = 0; + } + + let (t, _) = self.gpio[vx].overflowing_sub(self.gpio[vy]); + self.gpio[vx] = t; + }, + 6 => { + if self.gpio[vx].trailing_ones() > 0 { + self.gpio[0xf] = 1; + } else { + self.gpio[0xf] = 0; + } + + self.gpio[vx] >>= 1; + }, + 7 => { + if self.gpio[vx] < self.gpio[vy] { + self.gpio[0xf] = 1; + } else { + self.gpio[0xf] = 0; + } + + self.gpio[vx] = self.gpio[vy] - self.gpio[vx]; + }, + 0xE => { + if self.gpio[vx].leading_ones() > 0 { + self.gpio[0xf] = 1; + } else { + self.gpio[0xf] = 0; + } + + self.gpio[vx] <<= 1; + }, + _ => println!("error 8") + } + } + 9 => if self.gpio[vx] != self.gpio[vy] { + self.pc += 2; + }, + 0xA => self.index = opcode & 0x0fff, + 0xB => self.pc = ((self.gpio[0]) as u16 + (opcode & 0x0fff)) as usize, + 0xC => self.gpio[vx] = rand::random::() & k, + 0xD => { + let x = self.gpio[vx] as u16; + let y = self.gpio[vy] as u16; + for i in 0..(opcode & 0x000f) { + //println!("{:?}", self.memory); + let mut sprite = self.memory[(self.index + i as u16) as usize]; + for j in 0..8 { + let mut case = 0; + if sprite.leading_ones() > 0 { case = 1; } + //println!("I :: {}", self.index + i); + //println!("D :: {} - {}", sprite, case); + sprite = sprite << 1; + + let ty: usize = (i + y) as usize % HEIGHT; + let tx: usize = (j + x) as usize % WIDTH; + + let tmp = self.display_buffer[ty][tx]; + self.display_buffer[ty][tx] ^= case; + if self.display_buffer[ty][tx] == 0 && tmp == 1 { + self.gpio[0xf] = 1; + } + } + } + }, + 0xE => { + match opcode & 0x00ff { + 0x9E => { + if self.key_inputs[self.gpio[vx] as usize] == 1 { + self.pc += 2; + } + }, + 0xA1 => { + if self.key_inputs[self.gpio[vx] as usize] == 0 { + self.pc += 2; + } + }, + _ => println!("error E") + } + } + 0xF => { + match opcode & 0x00ff { + 0x07 => self.gpio[vx] = self.dt, + 0x0A => self.check_touch(vx, events), + 0x15 => self.dt = self.gpio[vx], + 0x18 => self.st = self.gpio[vx], + 0x1E => self.index += self.gpio[vx] as u16, + 0x29 => self.index = (self.gpio[vx] as u16) * 5, + 0x33 => { + self.memory[self.index as usize] = self.gpio[vx] / 100 as u8; + self.memory[(self.index + 1) as usize] = (self.gpio[vx] % 100) /10 as u8; + self.memory[(self.index + 2) as usize] = self.gpio[vx] % 10 as u8; + }, + 0x55 => + { + for i in 0..(vx + 1) { + self.memory[(self.index as usize) + i] = self.gpio[i]; + } + }, + 0x65 => { + for i in 0..(vx + 1) { + self.gpio[i] = self.memory[(self.index as usize) + i]; + } + }, + _ => println!("error F") + } + } + _ => println!("error") + } + } + + fn check_touch(&mut self, vx: usize, events: &mut EventPump) { + let touch = events.wait_event(); + match touch { + Event::KeyDown { keycode: Some(Keycode::Num0), .. } => { + self.gpio[vx] = 0; + }, + Event::KeyDown { keycode: Some(Keycode::Num1), .. } => { + self.gpio[vx] = 1; + }, + Event::KeyDown { keycode: Some(Keycode::Num2), .. } => { + self.gpio[vx] = 2; + }, + Event::KeyDown { keycode: Some(Keycode::Num3), .. } => { + self.gpio[vx] = 3; + }, + Event::KeyDown { keycode: Some(Keycode::Num4), .. } => { + self.gpio[vx] = 4; + }, + Event::KeyDown { keycode: Some(Keycode::Num5), .. } => { + self.gpio[vx] = 5; + }, + Event::KeyDown { keycode: Some(Keycode::Num6), .. } => { + self.gpio[vx] = 6; + }, + Event::KeyDown { keycode: Some(Keycode::Num7), .. } => { + self.gpio[vx] = 7; + }, + Event::KeyDown { keycode: Some(Keycode::Num8), .. } => { + self.gpio[vx] = 8; + }, + Event::KeyDown { keycode: Some(Keycode::Num9), .. } => { + self.gpio[vx] = 9; + }, + Event::KeyDown { keycode: Some(Keycode::A), .. } => { + self.gpio[vx] = 0xa; + }, + Event::KeyDown { keycode: Some(Keycode::B), .. } => { + self.gpio[vx] = 0xb; + }, + Event::KeyDown { keycode: Some(Keycode::C), .. } => { + self.gpio[vx] = 0xc; + }, + Event::KeyDown { keycode: Some(Keycode::D), .. } => { + self.gpio[vx] = 0xd; + }, + Event::KeyDown { keycode: Some(Keycode::E), .. } => { + self.gpio[vx] = 0xe; + }, + Event::KeyDown { keycode: Some(Keycode::F), .. } => { + self.gpio[vx] = 0xf; + }, + _ => self.check_touch(vx, events), + } + } +} diff --git a/src/main.rs b/src/main.rs index 90a6112..4f61cc6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,407 +16,31 @@ * this program. If not, see . */ +mod machine; extern crate sdl2; -extern crate rand; use sdl2::pixels::Color; use sdl2::event::Event; -use sdl2::EventPump; use sdl2::keyboard::Keycode; -use sdl2::video::Window; use sdl2::rect::Point; -use sdl2::render::Canvas; + +use machine::HEIGHT; +use machine::WIDTH; +use machine::Machine; use std::fs::File; use std::path::Path; use std::io; use std::io::Read; - - -const FONT: [u8; 80] = [ - 0xF0, 0x90, 0x90, 0x90, 0xF0, - 0x20, 0x60, 0x20, 0x20, 0x70, - 0xF0, 0x10, 0xF0, 0x80, 0xF0, - 0xF0, 0x10, 0xF0, 0x10, 0xF0, - 0x90, 0x90, 0xF0, 0x10, 0x10, - 0xF0, 0x80, 0xF0, 0x10, 0xF0, - 0xF0, 0x80, 0xF0, 0x90, 0xF0, - 0xF0, 0x10, 0x20, 0x40, 0x40, - 0xF0, 0x90, 0xF0, 0x90, 0xF0, - 0xF0, 0x90, 0xF0, 0x10, 0xF0, - 0xF0, 0x90, 0xF0, 0x90, 0x90, - 0xE0, 0x90, 0xE0, 0x90, 0xE0, - 0xF0, 0x80, 0x80, 0x80, 0xF0, - 0xE0, 0x90, 0x90, 0x90, 0xE0, - 0xF0, 0x80, 0xF0, 0x80, 0xF0, - 0xF0, 0x80, 0xF0, 0x80, 0x80 -]; - -const HEIGHT: usize = 32; -const WIDTH: usize = 64; - -struct Machine { - memory: [u8; 4096], - key_inputs: [u8; 16], - display_buffer: [[i32; WIDTH]; HEIGHT], - gpio: [u8; 16], - index: u16, - pc: usize, - stack: Vec -} - -impl Machine { - /// Initialise une machine en mettant tout à 0 (RAM, PC...) - pub fn new() -> Self { - Self { - memory: [0; 4096], - key_inputs: [0; 16], - display_buffer: [[0; WIDTH]; HEIGHT], - gpio: [0; 16], - index: 0, - pc: 0, - stack: Vec::new(), - } - } - - pub fn init(&mut self) { - for i in 0..FONT.len() { - self.memory[i] = FONT[i]; - } - - self.pc = 0x200; - } - - /// charge une ROM en mémoire - pub fn load_rom(&mut self, p: &Path) -> io::Result<()> { - let mut buffer = Vec::new(); - let mut f = File::open(p)?; - f.read_to_end(&mut buffer)?; - - for i in 0..buffer.len() { - self.memory[i + 0x200] = buffer[i]; - } - - Ok(()) - } - - pub fn cycle(&mut self, screen: &mut Canvas, events: &mut EventPump) { - let opcode = ((self.memory[self.pc] as u16) << 8) - + (self.memory[self.pc + 1] as u16); - - let vx: usize = ((opcode & 0x0f00) >> 8) as usize; - let vy: usize = ((opcode & 0x00f0) >> 4) as usize; - let k: u8 = (opcode & 0x00ff) as u8; - - self.pc += 2; - - match (opcode & 0xf000) >> 12 { - 0 => match opcode { - 0x00E0 => { - self.display_buffer = [[0; 64]; 32]; - screen.set_draw_color(Color::RGB(0, 0, 0)); - screen.clear(); - screen.present(); - }, - 0x00EE => self.pc = self.stack.pop().unwrap() as usize, - _ => println!("SYS"), - } - 1 => self.pc = (opcode & 0x0fff) as usize, - 2 => { - self.stack.push(self.pc as u16); - self.pc = (opcode & 0x0fff) as usize - }, - 3 => if self.gpio[vx] == k as u8 { - self.pc += 2; - }, - 4 => if self.gpio[vx] != k as u8 { - self.pc += 2; - }, - 5 => if self.gpio[vx] == self.gpio[vy] { - self.pc += 2; - } - 6 => self.gpio[vx] = k, - 7 => self.gpio[vx] = self.gpio[vx].saturating_add(k), - 8 => { - match opcode & 0x000f { - 0 => self.gpio[vx] = self.gpio[vy], - 1 => self.gpio[vx] |= self.gpio[vy], - 2 => self.gpio[vx] &= self.gpio[vy], - 3 => self.gpio[vx] ^= self.gpio[vy], - 4 => { - self.gpio[vx] = self.gpio[vx].saturating_add(self.gpio[vy]); - let (_, overflow) = self.gpio[vx].overflowing_add(self.gpio[vy]); - if overflow { - self.gpio[0xf] = 1; - } - }, - 5 => { - if self.gpio[vx] > self.gpio[vy] { - self.gpio[0xf] = 1; - } else { - self.gpio[0xf] = 0; - } - - let (t, _) = self.gpio[vx].overflowing_sub(self.gpio[vy]); - self.gpio[vx] = t; - }, - 6 => { - if self.gpio[vx].trailing_ones() > 0 { - self.gpio[0xf] = 1; - } else { - self.gpio[0xf] = 0; - } - - self.gpio[vx] >>= 1; - }, - 7 => { - if self.gpio[vx] < self.gpio[vy] { - self.gpio[0xf] = 1; - } else { - self.gpio[0xf] = 0; - } - - self.gpio[vx] = self.gpio[vy] - self.gpio[vx]; - }, - 0xE => { - if self.gpio[vx].leading_ones() > 0 { - self.gpio[0xf] = 1; - } else { - self.gpio[0xf] = 0; - } - - self.gpio[vx] <<= 1; - }, - _ => println!("error 8") - } - } - 9 => if self.gpio[vx] != self.gpio[vy] { - self.pc += 2; - }, - 0xA => self.index = opcode & 0x0fff, - 0xB => self.pc = ((self.gpio[0]) as u16 + (opcode & 0x0fff)) as usize, - 0xC => self.gpio[vx] = rand::random::() & k, - 0xD => { - let x = self.gpio[vx] as u16; - let y = self.gpio[vy] as u16; - for i in 0..(opcode & 0x000f) { - //println!("{:?}", self.memory); - let mut sprite = self.memory[(self.index + i as u16) as usize]; - for j in 0..8 { - let mut case = 0; - if sprite.leading_ones() > 0 { case = 1; } - //println!("I :: {}", self.index + i); - //println!("D :: {} - {}", sprite, case); - sprite = sprite << 1; - - let ty: usize = (i + y) as usize % HEIGHT; - let tx: usize = (j + x) as usize % WIDTH; - - let tmp = self.display_buffer[ty][tx]; - self.display_buffer[ty][tx] ^= case; - if self.display_buffer[ty][tx] == 0 && tmp == 1 { - self.gpio[0xf] = 1; - } - } - } - }, - 0xE => { - match opcode & 0x00ff { - 0x9E => { - if self.key_inputs[self.gpio[vx] as usize] == 1 { - self.pc += 2; - } - }, - 0xA1 => { - if self.key_inputs[self.gpio[vx] as usize] == 0 { - self.pc += 2; - } - }, - _ => println!("error E") - } - } - 0xF => { - match opcode & 0x00ff { - 0x07 => println!("LD F 7"), - 0x0A => self.check_touch(vx, events), - 0x15 => println!("LD F 15"), - 0x18 => println!("LD F 18"), - 0x1E => self.index += self.gpio[vx] as u16, - 0x29 => self.index = (self.gpio[vx] as u16) * 5, - 0x33 => { - self.memory[self.index as usize] = self.gpio[vx] / 100 as u8; - self.memory[(self.index + 1) as usize] = (self.gpio[vx] % 100) /10 as u8; - self.memory[(self.index + 2) as usize] = self.gpio[vx] % 10 as u8; - }, - 0x55 => - { - for i in 0..(vx + 1) { - self.memory[(self.index as usize) + i] = self.gpio[i]; - } - }, - 0x65 => { - for i in 0..(vx + 1) { - self.gpio[i] = self.memory[(self.index as usize) + i]; - } - }, - _ => println!("error F") - } - } - _ => println!("error") - } - } - - fn check_touch(&mut self, vx: usize, events: &mut EventPump) { - let touch = events.wait_event(); - match touch { - Event::KeyDown { keycode: Some(Keycode::Num0), .. } => { - self.gpio[vx] = 0; - }, - Event::KeyDown { keycode: Some(Keycode::Num1), .. } => { - self.gpio[vx] = 1; - }, - Event::KeyDown { keycode: Some(Keycode::Num2), .. } => { - self.gpio[vx] = 2; - }, - Event::KeyDown { keycode: Some(Keycode::Num3), .. } => { - self.gpio[vx] = 3; - }, - Event::KeyDown { keycode: Some(Keycode::Num4), .. } => { - self.gpio[vx] = 4; - }, - Event::KeyDown { keycode: Some(Keycode::Num5), .. } => { - self.gpio[vx] = 5; - }, - Event::KeyDown { keycode: Some(Keycode::Num6), .. } => { - self.gpio[vx] = 6; - }, - Event::KeyDown { keycode: Some(Keycode::Num7), .. } => { - self.gpio[vx] = 7; - }, - Event::KeyDown { keycode: Some(Keycode::Num8), .. } => { - self.gpio[vx] = 8; - }, - Event::KeyDown { keycode: Some(Keycode::Num9), .. } => { - self.gpio[vx] = 9; - }, - Event::KeyDown { keycode: Some(Keycode::A), .. } => { - self.gpio[vx] = 0xa; - }, - Event::KeyDown { keycode: Some(Keycode::B), .. } => { - self.gpio[vx] = 0xb; - }, - Event::KeyDown { keycode: Some(Keycode::C), .. } => { - self.gpio[vx] = 0xc; - }, - Event::KeyDown { keycode: Some(Keycode::D), .. } => { - self.gpio[vx] = 0xd; - }, - Event::KeyDown { keycode: Some(Keycode::E), .. } => { - self.gpio[vx] = 0xe; - }, - Event::KeyDown { keycode: Some(Keycode::F), .. } => { - self.gpio[vx] = 0xf; - }, - _ => self.check_touch(vx, events), - } - } -} - -#[allow(dead_code, unused_variables)] -fn read_file(p: &Path) -> io::Result<()> { - let mut buffer = Vec::new(); - let mut f = File::open(p)?; - let mut mem = [0; 4096]; - f.read_to_end(&mut buffer)?; - - for i in 0..buffer.len() { - mem[i] = buffer[i]; - } - - println!("{:?}", mem); - - let mut i = 0; - while i < mem.len() { - let opcode = ((mem[i] as u16) << 8) - + (mem[i + 1] as u16); - - let vx: usize = ((opcode & 0x0f00) >> 8) as usize; - let vy: usize = ((opcode & 0x00f0) >> 4) as usize; - let k: u8 = (opcode & 0x00ff) as u8; - - i += 2; - - match (opcode & 0xf000) >> 12 { - 0 => match opcode { - 0x00E0 => println!("CLS"), - 0x00EE => println!("RET"), - _ => println!("SYS"), - } - 1 => println!("JP {}", opcode & 0x0fff), - 2 => println!("CALL {}", opcode & 0x0fff), - 3 => println!("3SE {} {}", vx, k), - 4 => println!("4SNE {} {}", vx, k), - 5 => println!("5SE {} {}", vx, vy), - 6 => println!("6LD {} {}", vx, k), - 7 => println!("7ADD {} {}", vx, k), - 8 => { - match opcode & 0x000f { - 0 => println!("8LD {} {}", vx, vy), - 1 => println!("8OR {} {}", vx, vy), - 2 => println!("8AND {} {}", vx, vy), - 3 => println!("8XOR {} {}", vx, vy), - 4 => println!("8ADD {} {}", vx, vy), - 5 => println!("8SUB {} {}", vx, vy), - 6 => println!("8SHR {} {}", vx, vy), - 7 => println!("8SUBN {} {}", vx, vy), - 0xE => println!("8SHL {} {}", vx, vy), - _ => println!("error 8") - } - } - 9 => println!("9SNE {} {}", vx, vy), - 0xA => println!("AADD I {}", opcode & 0x0fff), - 0xB => println!("BJP 0 {}", opcode & 0x0fff), - 0xC => println!("RND {} {}", vx, k), - 0xD => println!("DRW {} {} {}", vx, vy, opcode & 0x000f), - 0xE => { - let x = (opcode & 0x0f00) >> 8; - match opcode & 0x00ff { - 0x9E => println!("SKP {}", vx), - 0xA1 => println!("SKNP {}", vx), - _ => println!("error E") - } - } - 0xF => { - let x = (opcode & 0x0f00) >> 8; - match opcode & 0x00ff { - 0x07 => println!("FLD {} DT", vx), - 0x0A => println!("FLD {} K", vx), - 0x15 => println!("FLD DT {}", vx), - 0x18 => println!("FLD ST {}", vx), - 0x1E => println!("FADD I {}", vx), - 0x29 => println!("FLD F {}", vx), - 0x33 => println!("FLD B {}", vx), - 0x55 => println!("FLD [I] {}", vx), - 0x65 => println!("FLD {} [I]", vx), - _ => println!("error F") - } - } - _ => println!("error") - } - } - - Ok(()) -} +use std::env; fn main() { + let name_file = &env::args().collect::>()[1]; //read_file(Path::new("15PUZZLE")); //return; - let mut t : Machine = Machine::new(); + let mut t: Machine = Machine::new(); t.init(); - //t.load_rom(Path::new("15PUZZLE")); - t.load_rom(Path::new("BLINKY")).unwrap(); - //t.load_rom(Path::new("GUESS")); - //t.load_rom(Path::new("BLITZ")); + t.load_rom(Path::new(name_file)); let sdl_context = sdl2::init().unwrap(); let video_subsystem = sdl_context.video().unwrap(); @@ -553,3 +177,89 @@ fn main() { canvas.present(); } } + +#[allow(dead_code, unused_variables)] +fn read_file(p: &Path) -> io::Result<()> { + let mut buffer = Vec::new(); + let mut f = File::open(p)?; + let mut mem = [0; 4096]; + f.read_to_end(&mut buffer)?; + + for i in 0..buffer.len() { + mem[i] = buffer[i]; + } + + println!("{:?}", mem); + + let mut i = 0; + while i < mem.len() { + let opcode = ((mem[i] as u16) << 8) + + (mem[i + 1] as u16); + + let vx: usize = ((opcode & 0x0f00) >> 8) as usize; + let vy: usize = ((opcode & 0x00f0) >> 4) as usize; + let k: u8 = (opcode & 0x00ff) as u8; + + i += 2; + + match (opcode & 0xf000) >> 12 { + 0 => match opcode { + 0x00E0 => println!("CLS"), + 0x00EE => println!("RET"), + _ => println!("SYS"), + } + 1 => println!("JP {}", opcode & 0x0fff), + 2 => println!("CALL {}", opcode & 0x0fff), + 3 => println!("3SE {} {}", vx, k), + 4 => println!("4SNE {} {}", vx, k), + 5 => println!("5SE {} {}", vx, vy), + 6 => println!("6LD {} {}", vx, k), + 7 => println!("7ADD {} {}", vx, k), + 8 => { + match opcode & 0x000f { + 0 => println!("8LD {} {}", vx, vy), + 1 => println!("8OR {} {}", vx, vy), + 2 => println!("8AND {} {}", vx, vy), + 3 => println!("8XOR {} {}", vx, vy), + 4 => println!("8ADD {} {}", vx, vy), + 5 => println!("8SUB {} {}", vx, vy), + 6 => println!("8SHR {} {}", vx, vy), + 7 => println!("8SUBN {} {}", vx, vy), + 0xE => println!("8SHL {} {}", vx, vy), + _ => println!("error 8") + } + } + 9 => println!("9SNE {} {}", vx, vy), + 0xA => println!("AADD I {}", opcode & 0x0fff), + 0xB => println!("BJP 0 {}", opcode & 0x0fff), + 0xC => println!("RND {} {}", vx, k), + 0xD => println!("DRW {} {} {}", vx, vy, opcode & 0x000f), + 0xE => { + let x = (opcode & 0x0f00) >> 8; + match opcode & 0x00ff { + 0x9E => println!("SKP {}", vx), + 0xA1 => println!("SKNP {}", vx), + _ => println!("error E") + } + } + 0xF => { + let x = (opcode & 0x0f00) >> 8; + match opcode & 0x00ff { + 0x07 => println!("FLD {} DT", vx), + 0x0A => println!("FLD {} K", vx), + 0x15 => println!("FLD DT {}", vx), + 0x18 => println!("FLD ST {}", vx), + 0x1E => println!("FADD I {}", vx), + 0x29 => println!("FLD F {}", vx), + 0x33 => println!("FLD B {}", vx), + 0x55 => println!("FLD [I] {}", vx), + 0x65 => println!("FLD {} [I]", vx), + _ => println!("error F") + } + } + _ => println!("error") + } + } + + Ok(()) +}