Add pixels-rs and winit as dependencies
This commit is contained in:
parent
be4be99c92
commit
4acffdfb6b
|
@ -1,2 +1,3 @@
|
|||
/target
|
||||
/games
|
||||
/games
|
||||
/.vscode
|
File diff suppressed because it is too large
Load Diff
|
@ -8,3 +8,6 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
rand = "0.7.3"
|
||||
pixels = "0.0.4"
|
||||
winit = "0.22.2"
|
||||
winit_input_helper = "0.7.0"
|
||||
|
|
54
src/emu.rs
54
src/emu.rs
|
@ -15,12 +15,12 @@ pub struct Chip8 {
|
|||
memory: [u8; 4096],
|
||||
delay: Timer,
|
||||
sound: Timer,
|
||||
display: Display,
|
||||
pub display: Display,
|
||||
}
|
||||
|
||||
impl Default for Chip8 {
|
||||
fn default() -> Self {
|
||||
Chip8 {
|
||||
let mut chip8 = Chip8 {
|
||||
opcode: 0,
|
||||
i: 0,
|
||||
pc: 0x200, // Progrm counter starts at 0x200
|
||||
|
@ -32,11 +32,33 @@ impl Default for Chip8 {
|
|||
delay: Default::default(),
|
||||
sound: Default::default(),
|
||||
display: Display::default(),
|
||||
}
|
||||
};
|
||||
|
||||
chip8.load_font_set();
|
||||
chip8
|
||||
}
|
||||
}
|
||||
|
||||
impl Chip8 {
|
||||
const FONT_SET: [u8; 80] = [
|
||||
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
|
||||
];
|
||||
|
||||
pub fn execute_cycle(&mut self) {
|
||||
self.opcode = self.get_opcode();
|
||||
println!("{:#x}", self.opcode);
|
||||
|
@ -46,6 +68,12 @@ impl Chip8 {
|
|||
self.sound.tick();
|
||||
}
|
||||
|
||||
pub fn load_font_set(&mut self) {
|
||||
for (i, byte) in Self::FONT_SET.iter().enumerate() {
|
||||
self.memory[i] = *byte;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_rom<P: AsRef<Path>>(&mut self, path: P) -> Result<(), io::Error> {
|
||||
let mut file = File::open(path.as_ref())?;
|
||||
let mut rom_buf: Vec<u8> = vec![];
|
||||
|
@ -157,6 +185,7 @@ impl Chip8 {
|
|||
fn jmp_addr(&mut self, n_1: u16, n_2: u16, n_3: u16) {
|
||||
// sets the program counter to addr (nnn)
|
||||
self.pc = Self::convert_to_addr(n_1, n_2, n_3);
|
||||
println!("{:#x}", self.pc);
|
||||
}
|
||||
|
||||
fn ret(&mut self) {
|
||||
|
@ -203,7 +232,7 @@ impl Chip8 {
|
|||
fn add_vx_byte(&mut self, x: u16, k_1: u16, k_2: u16) {
|
||||
// calculate Vx + kk, then store it in Vx
|
||||
let x = x as usize;
|
||||
self.v[x] = self.v[x] + Self::convert_to_byte(k_1, k_2);
|
||||
self.v[x] = self.v[x].wrapping_add(Self::convert_to_byte(k_1, k_2));
|
||||
}
|
||||
|
||||
fn ld_vx_vy(&mut self, x: u16, y: u16) {
|
||||
|
@ -247,7 +276,7 @@ impl Chip8 {
|
|||
let vy = self.v[y as usize];
|
||||
|
||||
self.v[0xF as usize] = if vx > vy { 1 } else { 0 };
|
||||
self.v[x as usize] = vx - vy;
|
||||
self.v[x as usize] = vx.wrapping_sub(vy);
|
||||
}
|
||||
|
||||
fn shr_vx(&mut self, x: u16) {
|
||||
|
@ -390,8 +419,9 @@ impl Chip8 {
|
|||
self.i = self.i + self.v[x as usize] as u16;
|
||||
}
|
||||
|
||||
fn ld_f_vx(&mut self, _x: u16) {
|
||||
todo!("Implement 0xF_29");
|
||||
fn ld_f_vx(&mut self, x: u16) {
|
||||
// set I to location of hex sprite related to Vx
|
||||
self.i = self.v[x as usize] as u16 * 5;
|
||||
}
|
||||
|
||||
fn ld_b_vx(&mut self, x: u16) {
|
||||
|
@ -399,15 +429,15 @@ impl Chip8 {
|
|||
// take tens digit and place it at I + 1
|
||||
// take ones digit and place it at I + 2
|
||||
let i = self.i as usize;
|
||||
let mut iter = Self::digits(self.v[x as usize]);
|
||||
let mut iter = Self::digits(self.v[x as usize] as usize);
|
||||
|
||||
let ones = iter.next().unwrap(); // Ther has to at least be a ones lol
|
||||
let tens = iter.next().unwrap_or(0);
|
||||
let hundreds = iter.next().unwrap_or(0);
|
||||
|
||||
self.memory[i] = hundreds;
|
||||
self.memory[i + 1] = tens;
|
||||
self.memory[i + 2] = ones;
|
||||
self.memory[i] = hundreds as u8;
|
||||
self.memory[i + 1] = tens as u8;
|
||||
self.memory[i + 2] = ones as u8;
|
||||
}
|
||||
|
||||
fn ld_i_vx(&mut self, x: u16) {
|
||||
|
@ -436,7 +466,7 @@ impl Chip8 {
|
|||
}
|
||||
|
||||
// https://stackoverflow.com/questions/41536479/how-do-i-split-an-integer-into-individual-digits
|
||||
fn digits(mut num: u8) -> impl Iterator<Item = u8> {
|
||||
fn digits(mut num: usize) -> impl Iterator<Item = usize> {
|
||||
let mut divisor = 1;
|
||||
while num >= divisor * 10 {
|
||||
divisor *= 10;
|
||||
|
|
68
src/main.rs
68
src/main.rs
|
@ -4,16 +4,78 @@
|
|||
use chip8::emu::Chip8;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
|
||||
use pixels::{wgpu::Surface, Error, Pixels, SurfaceTexture};
|
||||
use winit::dpi::LogicalSize;
|
||||
use winit::event::{Event, VirtualKeyCode};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::WindowBuilder;
|
||||
use winit_input_helper::WinitInputHelper;
|
||||
|
||||
static WIDTH: u32 = 64;
|
||||
static HEIGHT: u32 = 32;
|
||||
|
||||
fn main() {
|
||||
let event_loop = EventLoop::new();
|
||||
let mut input = WinitInputHelper::new();
|
||||
let window = {
|
||||
let size = LogicalSize::new(WIDTH as f64, HEIGHT as f64);
|
||||
WindowBuilder::new()
|
||||
.with_title("Chip8 Emulator")
|
||||
.with_inner_size(size)
|
||||
.with_min_inner_size(size)
|
||||
.build(&event_loop)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let mut hidpi_factor = window.scale_factor();
|
||||
|
||||
let mut pixels = {
|
||||
let surface = Surface::create(&window);
|
||||
let surface_texture = SurfaceTexture::new(WIDTH, HEIGHT, surface);
|
||||
Pixels::new(WIDTH, HEIGHT, surface_texture).unwrap()
|
||||
};
|
||||
|
||||
let mut chip8: Chip8 = Default::default();
|
||||
|
||||
chip8
|
||||
.load_rom(Path::new("./games/c8games/TICTAC"))
|
||||
.load_rom(Path::new("./games/test_opcode.ch8"))
|
||||
.expect("Unable to load ROM");
|
||||
|
||||
loop {
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
chip8.execute_cycle();
|
||||
|
||||
std::thread::sleep(Duration::from_millis(300));
|
||||
draw(&chip8.display.buf, pixels.get_frame());
|
||||
pixels.render().unwrap();
|
||||
window.request_redraw();
|
||||
|
||||
if input.update(&event) {
|
||||
if let Some(factor) = input.scale_factor_changed() {
|
||||
hidpi_factor = factor;
|
||||
};
|
||||
|
||||
if input.key_pressed(VirtualKeyCode::Escape) || input.quit() {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(size) = input.window_resized() {
|
||||
pixels.resize(size.width, size.height);
|
||||
}
|
||||
}
|
||||
|
||||
// std::thread::sleep(Duration::from_millis(1000));
|
||||
});
|
||||
}
|
||||
|
||||
fn draw(chip8_gfx: &[u8], frame: &mut [u8]) {
|
||||
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
|
||||
let rgba = if chip8_gfx[i] != 0 {
|
||||
[0xFF, 0xFF, 0xFF, 0xFF]
|
||||
} else {
|
||||
[0x00, 0x00, 0x00, 0xFF]
|
||||
};
|
||||
|
||||
pixel.copy_from_slice(&rgba);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue