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("rust-sdl2 demo", (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, 0x07);
 49        vkeys.insert(Keycode::A, 0x08);
 50        vkeys.insert(Keycode::S, 0x09);
 51        vkeys.insert(Keycode::D, 0x0E);
 52        vkeys.insert(Keycode::F, 0x0A);
 53        vkeys.insert(Keycode::Z, 0x00);
 54        vkeys.insert(Keycode::X, 0x0B);
 55        vkeys.insert(Keycode::V, 0x0F);
 56
 57        SdlEmulator {
 58            w,
 59            h,
 60            zoom,
 61            sdl_context,
 62            canvas,
 63            vkeys,
 64            chip8: c,
 65        }
 66    }
 67    fn draw_graphics(&mut self) {
 68        self.canvas.set_draw_color(Color::RGB(0, 0, 0));
 69        self.canvas.clear();
 70        self.canvas.set_draw_color(Color::RGB(255, 255, 255));
 71        for y in 0..self.h {
 72            for x in 0..self.w {
 73                let pixel = self.chip8.gfx[y * self.w + x];
 74                if pixel != 0 {
 75                    self.canvas.fill_rect(Rect::new(
 76                        (x * self.zoom) as i32,
 77                        (y * self.zoom) as i32,
 78                        (self.zoom) as u32,
 79                        (self.zoom) as u32,
 80                    ));
 81                }
 82            }
 83        }
 84
 85        self.canvas.present();
 86        self.chip8.draw_flag = false;
 87    }
 88    fn set_keys(&mut self) -> Result<(), String> {
 89        let mut events = self.sdl_context.event_pump()?;
 90        for event in events.poll_iter() {
 91            match event {
 92                Event::Quit { .. } => {
 93                    println!("Quit");
 94                    std::process::exit(0);
 95                }
 96                Event::KeyDown {
 97                    keycode: Some(keycode),
 98                    ..
 99                } => {
100                    println!("k {:?}", keycode);
101                    if self.vkeys.contains_key(&keycode) {
102                        let k_hex = self.vkeys.get(&keycode).unwrap();
103                        self.chip8.key[*k_hex as usize] = 1;
104                    }
105                }
106                Event::KeyUp {
107                    keycode: Some(keycode),
108                    ..
109                } => {
110                    println!("k {:?}", keycode);
111                    if self.vkeys.contains_key(&keycode) {
112                        let k_hex = self.vkeys.get(&keycode).unwrap();
113                        self.chip8.key[*k_hex as usize] = 0;
114                    }
115                    if keycode == Keycode::Escape {
116                        println!("EXIT");
117                        std::process::exit(0);
118                    }
119                }
120                _ => {}
121            }
122        }
123        Ok(())
124    }
125}
126
127fn main() {
128    let matches = App::new("chip8-rs")
129        .version("0.0.1")
130        .about("chip8 emulator")
131        .arg(
132            Arg::with_name("file")
133                .short("f")
134                .long("file")
135                .takes_value(true)
136                .help("File path of the rom to load"),
137        )
138        .get_matches();
139    let file = matches.value_of("file");
140    let file = match file {
141        Some(file) => file,
142        _ => panic!("Please specify file path of the rom to load"),
143    };
144    println!("{:?}", file);
145
146    let mut e = SdlEmulator::new(64, 32, 8);
147    e.chip8.load_game(file);
148
149    loop {
150        e.chip8.emulate_cycle();
151        if e.chip8.draw_flag {
152            e.draw_graphics();
153        }
154        e.set_keys();
155        std::thread::sleep(time::Duration::from_millis(1000 / 60));
156    }
157}