chip8-rs/src/main.rs
src/main.rsRaw
1use std::collections::HashMap;
2use std::{thread, time};
3extern crate sdl2;
4
5use sdl2::event::Event;
6use sdl2::keyboard::Keycode;
7use sdl2::pixels::Color;
8use sdl2::rect::Rect;
9use sdl2::render::Canvas;
10
11use clap::{App, Arg};
12
13use chip8::Chip8;
14
15struct SdlEmulator {
16 w: usize,
17 h: usize,
18 zoom: usize,
19 sdl_context: sdl2::Sdl,
20 canvas: Canvas<sdl2::video::Window>,
21 vkeys: HashMap<Keycode, u8>,
22 chip8: Chip8,
23}
24
25impl SdlEmulator {
26 fn new(w: usize, h: usize, zoom: usize) -> SdlEmulator {
27 let mut c = Chip8::new();
28
29 let sdl_context = sdl2::init().unwrap();
30 let video_subsystem = sdl_context.video().unwrap();
31
32 let window = video_subsystem
33 .window("chip8-rs", (w * zoom) as u32, (h * zoom) as u32)
34 .position_centered()
35 .build()
36 .unwrap();
37
38 let mut canvas = window.into_canvas().build().unwrap();
39
40 let mut vkeys: HashMap<Keycode, u8> = HashMap::new();
41 vkeys.insert(Keycode::Num1, 0x01);
42 vkeys.insert(Keycode::Num2, 0x02);
43 vkeys.insert(Keycode::Num3, 0x03);
44 vkeys.insert(Keycode::Num4, 0x0c);
45 vkeys.insert(Keycode::Q, 0x04);
46 vkeys.insert(Keycode::W, 0x05);
47 vkeys.insert(Keycode::E, 0x06);
48 vkeys.insert(Keycode::R, 0x0d);
49 vkeys.insert(Keycode::A, 0x07);
50 vkeys.insert(Keycode::S, 0x08);
51 vkeys.insert(Keycode::D, 0x09);
52 vkeys.insert(Keycode::F, 0x0e);
53 vkeys.insert(Keycode::Z, 0x0a);
54 vkeys.insert(Keycode::X, 0x00);
55 vkeys.insert(Keycode::C, 0x0b);
56 vkeys.insert(Keycode::V, 0x0f);
57
58 SdlEmulator {
59 w,
60 h,
61 zoom,
62 sdl_context,
63 canvas,
64 vkeys,
65 chip8: c,
66 }
67 }
68 fn draw_graphics(&mut self) {
69 self.canvas.set_draw_color(Color::RGB(0, 0, 0));
70 self.canvas.clear();
71 self.canvas.set_draw_color(Color::RGB(255, 255, 255));
72 for y in 0..self.h {
73 for x in 0..self.w {
74 let pixel = self.chip8.gfx[y * self.w + x];
75 if pixel != 0 {
76 self.canvas.fill_rect(Rect::new(
77 (x * self.zoom) as i32,
78 (y * self.zoom) as i32,
79 (self.zoom) as u32,
80 (self.zoom) as u32,
81 ));
82 }
83 }
84 }
85
86 self.canvas.present();
87 self.chip8.draw_flag = false;
88 }
89 fn set_keys(&mut self) -> Result<(), String> {
90 let mut events = self.sdl_context.event_pump()?;
91 for event in events.poll_iter() {
92 match event {
93 Event::Quit { .. } => {
94 println!("Quit");
95 std::process::exit(0);
96 }
97 Event::KeyDown {
98 keycode: Some(keycode),
99 ..
100 } => {
101 println!("k {:?}", keycode);
102 if self.vkeys.contains_key(&keycode) {
103 let k_hex = self.vkeys.get(&keycode).unwrap();
104 self.chip8.key[*k_hex as usize] = 1;
105 }
106 }
107 Event::KeyUp {
108 keycode: Some(keycode),
109 ..
110 } => {
111 println!("k {:?}", keycode);
112 if self.vkeys.contains_key(&keycode) {
113 let k_hex = self.vkeys.get(&keycode).unwrap();
114 self.chip8.key[*k_hex as usize] = 0;
115 }
116 if keycode == Keycode::Escape {
117 println!("EXIT");
118 std::process::exit(0);
119 }
120 }
121 _ => {}
122 }
123 }
124 Ok(())
125 }
126}
127
128fn main() {
129 let matches = App::new("chip8-rs")
130 .version("0.0.1")
131 .about("chip8 emulator")
132 .arg(
133 Arg::with_name("file")
134 .short("f")
135 .long("file")
136 .takes_value(true)
137 .help("File path of the rom to load"),
138 )
139 .get_matches();
140 let file = matches.value_of("file");
141 let file = match file {
142 Some(file) => file,
143 _ => panic!("Please specify file path of the rom to load"),
144 };
145 println!("{:?}", file);
146
147 let mut e = SdlEmulator::new(64, 32, 8);
148 e.chip8.load_game(file);
149
150 loop {
151 e.chip8.emulate_cycle();
152 if e.chip8.draw_flag {
153 e.draw_graphics();
154 }
155 e.set_keys();
156 std::thread::sleep(time::Duration::from_millis(200 / 60));
157 }
158}