arnaucube
arnaucube/chip8-rsPublic Self-hosted repository
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}