/ src / device.rs
device.rs
  1  use crate::display::Display;
  2  use crate::rom::Ch8Rom;
  3  use crate::vm::VM;
  4  use anyhow::Result;
  5  use sdl2::event::Event;
  6  use sdl2::keyboard::Keycode;
  7  use sdl2::pixels::Color;
  8  use sdl2::video::Window;
  9  use sdl2::{rect::Rect, render::Canvas};
 10  
 11  pub struct Device {
 12      pub vm: VM,
 13  }
 14  
 15  impl Device {
 16      pub fn new(rom: Ch8Rom) -> Result<Self> {
 17          Ok(Device { vm: VM::new(rom)? })
 18      }
 19  
 20      pub fn initialize(&mut self) -> Result<()> {
 21          self.vm.initialize()?;
 22  
 23          Ok(())
 24      }
 25  
 26      pub fn run(&mut self) -> Result<()> {
 27          // SDL2 Setup
 28          let sdl_context = sdl2::init().map_err(anyhow::Error::msg)?;
 29          let video_subsys = sdl_context.video().map_err(anyhow::Error::msg)?;
 30          let window = video_subsys
 31              .window("Chip8 Emulator", Display::WIDTH * Display::SCALE, Display::HEIGHT * Display::SCALE)
 32              .position_centered()
 33              .opengl()
 34              .build()?;
 35  
 36          let mut canvas = window.into_canvas().present_vsync().build()?;
 37  
 38          canvas.clear();
 39          canvas.present();
 40  
 41          let mut event_pump = sdl_context.event_pump().map_err(anyhow::Error::msg)?;
 42          'vmevloop: loop {
 43              for evt in event_pump.poll_iter() {
 44                  match evt {
 45                      Event::Quit { .. }
 46                          | Event::KeyDown {
 47                          keycode: Some(Keycode::Escape),
 48                          ..
 49                      } => break 'vmevloop,
 50                      Event::KeyDown {
 51                          keycode: Some(key), ..
 52                      } => match key {
 53                              Keycode::Num1 => self.vm.keyboard[0] = true,
 54                              Keycode::Num2 => self.vm.keyboard[1] = true,
 55                              Keycode::Num3 => self.vm.keyboard[2] = true,
 56                              Keycode::Num4 => self.vm.keyboard[3] = true,
 57                              Keycode::Q => self.vm.keyboard[4] = true,
 58                              Keycode::W => self.vm.keyboard[5] = true,
 59                              Keycode::E => self.vm.keyboard[6] = true,
 60                              Keycode::R => self.vm.keyboard[7] = true,
 61                              Keycode::A => self.vm.keyboard[8] = true,
 62                              Keycode::S => self.vm.keyboard[9] = true,
 63                              Keycode::D => self.vm.keyboard[10] = true,
 64                              Keycode::F => self.vm.keyboard[11] = true,
 65                              Keycode::Z => self.vm.keyboard[12] = true,
 66                              Keycode::X => self.vm.keyboard[13] = true,
 67                              Keycode::C => self.vm.keyboard[14] = true,
 68                              Keycode::V => self.vm.keyboard[15] = true,
 69                              _ => (),
 70                          },
 71                      Event::KeyUp {
 72                          keycode: Some(key), ..
 73                      } => match key {
 74                              Keycode::Num1 => self.vm.keyboard[0] = false,
 75                              Keycode::Num2 => self.vm.keyboard[1] = false,
 76                              Keycode::Num3 => self.vm.keyboard[2] = false,
 77                              Keycode::Num4 => self.vm.keyboard[3] = false,
 78                              Keycode::Q => self.vm.keyboard[4] = false,
 79                              Keycode::W => self.vm.keyboard[5] = false,
 80                              Keycode::E => self.vm.keyboard[6] = false,
 81                              Keycode::R => self.vm.keyboard[7] = false,
 82                              Keycode::A => self.vm.keyboard[8] = false,
 83                              Keycode::S => self.vm.keyboard[9] = false,
 84                              Keycode::D => self.vm.keyboard[10] = false,
 85                              Keycode::F => self.vm.keyboard[11] = false,
 86                              Keycode::Z => self.vm.keyboard[12] = false,
 87                              Keycode::X => self.vm.keyboard[13] = false,
 88                              Keycode::C => self.vm.keyboard[14] = false,
 89                              Keycode::V => self.vm.keyboard[15] = false,
 90                              _ => (),
 91                          },
 92                      _ => (),
 93                  }
 94              }
 95  
 96              for _ in 0..Display::TICKS_PER_FRAME {
 97                  self.vm.tick()?;
 98              }
 99  
100              self.draw_screen(&mut canvas)?;
101          }
102  
103          Ok(())
104      }
105  
106  
107      fn draw_screen(&self, canvas: &mut Canvas<Window>) -> Result<()> {
108          for (y, row) in self.vm.vram.iter().enumerate() {
109              for (x, &col) in row.iter().enumerate() {
110                  let x = (x as u32) * Display::SCALE;
111                  let y = (y as u32) * Display::SCALE;
112                  if col == 0 {
113                      canvas.set_draw_color(Color::RGB(0, 0, 0));
114                  } else {
115                      canvas.set_draw_color(Color::RGB(255, 255, 255));
116                  }
117  
118                  let _ = canvas
119                      .fill_rect(Rect::new(x as i32, y as i32, Display::SCALE, Display::SCALE));
120              }
121          }
122          canvas.present();
123  
124          Ok(())
125      }
126  }