You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
4.6 KiB

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