2020-06-25 06:40:09 +00:00
|
|
|
// I used: http://devernay.free.fr/hacks/chip8/C8TECH10.HTM#00E0
|
|
|
|
// and https://en.wikipedia.org/wiki/CHIP-8#Opcode_table
|
|
|
|
// for information about how to implement a CHIP-8 Emulator
|
2020-06-25 18:13:09 +00:00
|
|
|
use chip8::emu::Chip8;
|
2020-06-25 06:40:09 +00:00
|
|
|
use std::path::Path;
|
2020-06-25 19:22:37 +00:00
|
|
|
|
2020-06-26 00:06:27 +00:00
|
|
|
use pixels::{wgpu::Surface, Pixels, SurfaceTexture};
|
2020-06-25 19:22:37 +00:00
|
|
|
use winit::dpi::LogicalSize;
|
|
|
|
use winit::event::{Event, VirtualKeyCode};
|
|
|
|
use winit::event_loop::{ControlFlow, EventLoop};
|
2020-06-26 00:06:27 +00:00
|
|
|
use winit::window::{Window, WindowBuilder};
|
2020-06-25 19:22:37 +00:00
|
|
|
use winit_input_helper::WinitInputHelper;
|
|
|
|
|
|
|
|
static WIDTH: u32 = 64;
|
|
|
|
static HEIGHT: u32 = 32;
|
|
|
|
|
2020-06-15 05:45:49 +00:00
|
|
|
fn main() {
|
2020-07-14 03:16:42 +00:00
|
|
|
let mut chip8: Chip8 = Default::default();
|
|
|
|
let mut input = WinitInputHelper::new();
|
2020-06-25 19:22:37 +00:00
|
|
|
let event_loop = EventLoop::new();
|
2020-06-26 00:06:27 +00:00
|
|
|
let window = init_window(&event_loop);
|
2020-07-14 03:16:42 +00:00
|
|
|
let mut pixels = init_pixels(&window);
|
2020-06-25 19:22:37 +00:00
|
|
|
|
2020-07-15 02:43:03 +00:00
|
|
|
let rom_path = Path::new("./games/test_opcode.ch8");
|
2020-07-14 03:16:42 +00:00
|
|
|
chip8.load_rom(rom_path).expect("Unable to load ROM");
|
2020-06-25 06:40:09 +00:00
|
|
|
|
2020-06-25 19:22:37 +00:00
|
|
|
event_loop.run(move |event, _, control_flow| {
|
2020-06-26 00:06:27 +00:00
|
|
|
if let Event::RedrawRequested(_) = event {
|
|
|
|
draw(&chip8.display.buf, pixels.get_frame());
|
|
|
|
if pixels
|
|
|
|
.render()
|
|
|
|
.map_err(|e| eprintln!("pixels.render() failed: {}", e))
|
|
|
|
.is_err()
|
|
|
|
{
|
|
|
|
*control_flow = ControlFlow::Exit;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2020-06-25 19:22:37 +00:00
|
|
|
|
|
|
|
if input.update(&event) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2020-06-26 00:06:27 +00:00
|
|
|
chip8.execute_cycle();
|
|
|
|
window.request_redraw();
|
|
|
|
}
|
2020-06-25 19:22:37 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-06-26 00:06:27 +00:00
|
|
|
fn init_pixels(window: &Window) -> Pixels {
|
|
|
|
let surface = Surface::create(window);
|
|
|
|
let texture = SurfaceTexture::new(WIDTH, HEIGHT, surface);
|
|
|
|
Pixels::new(WIDTH, HEIGHT, texture).unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn init_window(event_loop: &EventLoop<()>) -> Window {
|
2020-07-14 03:16:42 +00:00
|
|
|
const SCALE: u32 = 10;
|
|
|
|
let min_size = LogicalSize::new(WIDTH as f64, HEIGHT as f64);
|
|
|
|
let size = LogicalSize::new((WIDTH * SCALE) as f64, (HEIGHT * SCALE) as f64);
|
2020-06-26 00:06:27 +00:00
|
|
|
WindowBuilder::new()
|
|
|
|
.with_title("Chip8 Emulator")
|
|
|
|
.with_inner_size(size)
|
2020-07-14 03:16:42 +00:00
|
|
|
.with_min_inner_size(min_size)
|
2020-06-26 00:06:27 +00:00
|
|
|
.build(event_loop)
|
|
|
|
.unwrap()
|
|
|
|
}
|
|
|
|
|
2020-06-25 19:22:37 +00:00
|
|
|
fn draw(chip8_gfx: &[u8], frame: &mut [u8]) {
|
|
|
|
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
|
2020-07-13 20:28:41 +00:00
|
|
|
let rgba = if chip8_gfx[i] == 1 {
|
2020-07-14 04:04:58 +00:00
|
|
|
[0xFF; 4]
|
2020-06-25 19:22:37 +00:00
|
|
|
} else {
|
2020-07-14 04:04:58 +00:00
|
|
|
[0x00; 4]
|
2020-06-25 19:22:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
pixel.copy_from_slice(&rgba);
|
2020-06-25 06:40:09 +00:00
|
|
|
}
|
|
|
|
}
|