first files: code skeleton
This commit is contained in:
commit
e565a98e6d
2 changed files with 208 additions and 0 deletions
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "chip8-emulator"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
sdl2 = "0.35.1"
|
198
src/main.rs
Normal file
198
src/main.rs
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
extern crate sdl2;
|
||||||
|
|
||||||
|
use sdl2::pixels::Color;
|
||||||
|
use sdl2::event::Event;
|
||||||
|
use sdl2::keyboard::Keycode;
|
||||||
|
use sdl2::video::Window;
|
||||||
|
|
||||||
|
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
|
||||||
|
];
|
||||||
|
|
||||||
|
struct Machine {
|
||||||
|
memory: [u8; 4096],
|
||||||
|
key_inputs: [i32; 16],
|
||||||
|
display_buffer: [[i32; 64]; 32],
|
||||||
|
gpio: [i8; 16],
|
||||||
|
index: i16,
|
||||||
|
opcode: u16,
|
||||||
|
pc: usize,
|
||||||
|
stack: Vec<i32>
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decodeOp(op1: u8, op2: u8) -> u16 {
|
||||||
|
let ret: u16 = u16::from(op1) << 2;
|
||||||
|
ret + u16::from(op2) >> 2
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Machine {
|
||||||
|
/// Initialise une machine en mettant tout à 0 (RAM, PC...)
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Machine {
|
||||||
|
memory: [0; 4096],
|
||||||
|
key_inputs: [0; 16],
|
||||||
|
display_buffer: [[0; 64]; 32],
|
||||||
|
gpio: [0; 16],
|
||||||
|
index: 0,
|
||||||
|
opcode: 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 loadRom(&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 sdl2::render::Canvas<Window>) {
|
||||||
|
self.opcode = ((self.memory[self.pc] as u16) << 8)
|
||||||
|
+ (self.memory[self.pc + 1] as u16);
|
||||||
|
|
||||||
|
self.pc += 2;
|
||||||
|
//let o = self.opcode & 0xf000;
|
||||||
|
|
||||||
|
match (self.opcode & 0xf000) >> 12 {
|
||||||
|
0 => match self.opcode {
|
||||||
|
0x00E0 => screen.clear(),
|
||||||
|
0x00EE => println!("RET"),
|
||||||
|
_ => println!("SYS"),
|
||||||
|
}
|
||||||
|
1 => println!("JP"),
|
||||||
|
2 => println!("CALL"),
|
||||||
|
3 => println!("SE"),
|
||||||
|
4 => println!("SNE"),
|
||||||
|
5 => println!("SE 5"),
|
||||||
|
6 => println!("LD"),
|
||||||
|
7 => println!("ADD"),
|
||||||
|
8 => {
|
||||||
|
let x = (self.opcode & 0x0f00) >> 8;
|
||||||
|
let y = (self.opcode & 0x00f0) >> 4;
|
||||||
|
match self.opcode & 0x000f {
|
||||||
|
0 => println!("LD 8"),
|
||||||
|
1 => println!("OR"),
|
||||||
|
2 => println!("AND"),
|
||||||
|
3 => println!("XOR"),
|
||||||
|
4 => println!("ADD"),
|
||||||
|
5 => println!("SUB"),
|
||||||
|
6 => println!("SHR"),
|
||||||
|
7 => println!("SUBN"),
|
||||||
|
0xE => println!("SHL"),
|
||||||
|
_ => println!("error 8")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
9 => println!("SNE 9"),
|
||||||
|
0xA => println!("LD A"),
|
||||||
|
0xB => println!("JP B"),
|
||||||
|
0xC => println!("RND "),
|
||||||
|
0xD => println!("DRW"),
|
||||||
|
0xE => {
|
||||||
|
let x = (self.opcode & 0x0f00) >> 8;
|
||||||
|
match self.opcode & 0x00ff {
|
||||||
|
0x9E => println!("SKP"),
|
||||||
|
0xA1 => println!("SKNP"),
|
||||||
|
_ => println!("error E")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0xF => {
|
||||||
|
let x = (self.opcode & 0x0f00) >> 8;
|
||||||
|
match self.opcode & 0x00ff {
|
||||||
|
0x07 => println!("LD F 7"),
|
||||||
|
0x0A => println!("LD F A"),
|
||||||
|
0x15 => println!("LD F 15"),
|
||||||
|
0x18 => println!("LD F 18"),
|
||||||
|
0x1E => println!("ADD F 1E"),
|
||||||
|
0x29 => println!("LD F 2"), // self.index = self.gpio[x] * 5) & 0x0fff
|
||||||
|
0x33 => println!("LD F 3"),
|
||||||
|
0x55 => println!("LD F 5"),
|
||||||
|
0x65 => println!("LD F 6"),
|
||||||
|
_ => println!("error F")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => println!("error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut t : Machine = Machine::new();
|
||||||
|
println!("{:?}", t.memory);
|
||||||
|
t.init();
|
||||||
|
t.loadRom(Path::new("15PUZZLE"));
|
||||||
|
println!("\n\n{:?}", t.memory);
|
||||||
|
//t.cycle();
|
||||||
|
|
||||||
|
let sdl_context = sdl2::init().unwrap();
|
||||||
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
|
let window = video_subsystem.window("Chip8 Emulator", 900, 700)
|
||||||
|
.position_centered()
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut canvas = window.into_canvas().build().unwrap();
|
||||||
|
canvas.set_draw_color(Color::RGB(0, 255, 255));
|
||||||
|
canvas.clear();
|
||||||
|
canvas.present();
|
||||||
|
|
||||||
|
let mut event_pump = sdl_context.event_pump().unwrap();
|
||||||
|
let mut i = 0;
|
||||||
|
|
||||||
|
'running: loop {
|
||||||
|
/*
|
||||||
|
i = (i + 1) % 255;
|
||||||
|
canvas.set_draw_color(Color::RGB(i, 64, 255 - i));
|
||||||
|
canvas.clear();
|
||||||
|
*/
|
||||||
|
t.cycle(&mut canvas);
|
||||||
|
|
||||||
|
/*
|
||||||
|
for event in event_pump.poll_iter() {
|
||||||
|
match event {
|
||||||
|
Event::KeyDown { keycode: Some(Keycode::Escape), ..} => {
|
||||||
|
break 'running
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
canvas.present();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue