diff --git a/src/core/gba.rs b/src/core/gba.rs index 0d69eb6..7e15737 100644 --- a/src/core/gba.rs +++ b/src/core/gba.rs @@ -1,4 +1,7 @@ /// Struct containing everything +use std::cell::RefCell; +use std::rc::Rc; + use super::arm7tdmi::Core; use super::cartridge::Cartridge; use super::gpu::*; @@ -10,28 +13,53 @@ use super::SyncedIoDevice; use super::super::{AudioInterface, InputInterface, VideoInterface}; -pub struct GameBoyAdvance { - pub cpu: Core, +pub struct GameBoyAdvance +where + V: VideoInterface, + A: AudioInterface, + I: InputInterface, +{ pub sysbus: Box, + pub cpu: Core, + video_device: Rc>, + audio_device: Rc>, + input_device: Rc>, } -impl GameBoyAdvance { - pub fn new(cpu: Core, bios_rom: Vec, gamepak: Cartridge) -> GameBoyAdvance { +impl GameBoyAdvance +where + V: VideoInterface, + A: AudioInterface, + I: InputInterface, +{ + pub fn new( + cpu: Core, + bios_rom: Vec, + gamepak: Cartridge, + video_device: Rc>, + audio_device: Rc>, + input_device: Rc>, + ) -> GameBoyAdvance { let io = IoDevices::new(); GameBoyAdvance { cpu: cpu, sysbus: Box::new(SysBus::new(io, bios_rom, gamepak)), + video_device: video_device, + audio_device: audio_device, + input_device: input_device, } } - pub fn frame(&mut self, video: &mut VideoInterface, input: &mut InputInterface) { - self.sysbus.io.keyinput = input.poll(); + pub fn frame(&mut self) { + self.sysbus.io.keyinput = self.input_device.borrow_mut().poll(); while self.sysbus.io.gpu.state != GpuState::VBlank { - self.step_new(); + self.step(); } - video.render(self.sysbus.io.gpu.get_framebuffer()); + self.video_device + .borrow_mut() + .render(self.sysbus.io.gpu.get_framebuffer()); while self.sysbus.io.gpu.state == GpuState::VBlank { - self.step_new(); + self.step(); } } @@ -56,7 +84,7 @@ impl GameBoyAdvance { None } - pub fn step_new(&mut self) { + pub fn step(&mut self) { let mut irqs = IrqBitmask(0); let previous_cycles = self.cpu.cycles; diff --git a/src/debugger/command.rs b/src/debugger/command.rs index 0bcca39..346fe6a 100644 --- a/src/debugger/command.rs +++ b/src/debugger/command.rs @@ -8,6 +8,7 @@ use crate::core::arm7tdmi::thumb::ThumbInstruction; use crate::core::arm7tdmi::{Addr, CpuState}; use crate::core::GBAError; use crate::disass::Disassembler; +use crate::{AudioInterface, InputInterface, VideoInterface}; use super::palette_view::create_palette_view; // use super::tile_view::create_tile_view; @@ -61,7 +62,12 @@ pub enum Command { TraceToggle(TraceFlags), } -impl Debugger { +impl Debugger +where + V: VideoInterface, + A: AudioInterface, + I: InputInterface, +{ pub fn run_command(&mut self, command: Command) { use Command::*; match command { @@ -78,9 +84,9 @@ impl Debugger { if !self.ctrlc_flag.load(Ordering::SeqCst) { break; } - self.gba.step_new(); + self.gba.step(); while self.gba.cpu.last_executed.is_none() { - self.gba.step_new(); + self.gba.step(); } let last_executed = self.gba.cpu.last_executed.unwrap(); print!( @@ -113,7 +119,7 @@ impl Debugger { // break; // } // _ => { - // self.gba.step_new(); + // self.gba.step(); // } // } // } diff --git a/src/debugger/mod.rs b/src/debugger/mod.rs index 54d978e..79f144f 100644 --- a/src/debugger/mod.rs +++ b/src/debugger/mod.rs @@ -12,6 +12,8 @@ use colored::*; use super::core::arm7tdmi::{Addr, Bus, CpuError}; use super::core::GameBoyAdvance; +use super::{AudioInterface, InputInterface, VideoInterface}; + mod parser; use parser::{parse_expr, DerefType, Expr, Value}; @@ -46,15 +48,25 @@ impl From<::std::io::Error> for DebuggerError { type DebuggerResult = Result; -pub struct Debugger { - pub gba: GameBoyAdvance, +pub struct Debugger +where + V: VideoInterface, + A: AudioInterface, + I: InputInterface, +{ + pub gba: GameBoyAdvance, running: bool, pub ctrlc_flag: Arc, pub previous_command: Option, } -impl Debugger { - pub fn new(gba: GameBoyAdvance) -> Debugger { +impl Debugger +where + V: VideoInterface, + A: AudioInterface, + I: InputInterface, +{ + pub fn new(gba: GameBoyAdvance) -> Debugger { let ctrlc_flag = Arc::new(AtomicBool::new(true)); let r = ctrlc_flag.clone(); ctrlc::set_handler(move || { diff --git a/src/plat/sdl2/keyboard.rs b/src/plat/sdl2/keyboard.rs index c65ae56..34b00c2 100644 --- a/src/plat/sdl2/keyboard.rs +++ b/src/plat/sdl2/keyboard.rs @@ -7,12 +7,12 @@ use rustboyadvance_ng::InputInterface; extern crate bit; use bit::BitIndex; -pub struct Sdl2Keyboard { +pub struct Sdl2Input { event_pump: EventPump, keyinput: u16, } -impl InputInterface for Sdl2Keyboard { +impl InputInterface for Sdl2Input { fn poll(&mut self) -> u16 { for event in self.event_pump.poll_iter() { match event { @@ -56,8 +56,8 @@ fn keycode_to_keypad(keycode: Keycode) -> Option { } } -pub fn create_keyboard(sdl: &sdl2::Sdl) -> Sdl2Keyboard { - Sdl2Keyboard { +pub fn create_keyboard(sdl: &sdl2::Sdl) -> Sdl2Input { + Sdl2Input { event_pump: sdl.event_pump().unwrap(), keyinput: gba_keypad::KEYINPUT_ALL_RELEASED, } diff --git a/src/plat/sdl2/main.rs b/src/plat/sdl2/main.rs index 607ddc5..bfa9776 100644 --- a/src/plat/sdl2/main.rs +++ b/src/plat/sdl2/main.rs @@ -1,5 +1,7 @@ extern crate sdl2; -use sdl2::Sdl; + +use std::cell::RefCell; +use std::rc::Rc; use std::path::Path; use std::time; @@ -11,9 +13,9 @@ mod audio; mod keyboard; mod video; -use keyboard::create_keyboard; -use video::create_video_interface; -use audio::create_audio_player; +use audio::{create_audio_player, Sdl2AudioPlayer}; +use keyboard::{create_keyboard, Sdl2Input}; +use video::{create_video_interface, Sdl2Video}; #[macro_use] extern crate rustboyadvance_ng; @@ -41,12 +43,13 @@ fn main() { let cpu = cpu; let sdl_context = sdl2::init().unwrap(); - let mut video = create_video_interface(&sdl_context); - let mut audio = create_audio_player(&sdl_context); - let mut keyboard = create_keyboard(&sdl_context); + let video = Rc::new(RefCell::new(create_video_interface(&sdl_context))); + let audio = Rc::new(RefCell::new(create_audio_player(&sdl_context))); + let keyboard = Rc::new(RefCell::new(create_keyboard(&sdl_context))); let mut fps_counter = FpsCounter::default(); - let mut gba = GameBoyAdvance::new(cpu, bios_bin, cart); + let mut gba: GameBoyAdvance = + GameBoyAdvance::new(cpu, bios_bin, cart, video.clone(), audio.clone(), keyboard.clone()); if debug { gba.cpu.set_verbose(true); @@ -59,10 +62,11 @@ fn main() { loop { let start_time = time::Instant::now(); - gba.frame(&mut video, &mut keyboard); + gba.frame(); + if let Some(fps) = fps_counter.tick() { let title = format!("{} ({} fps)", rom_name, fps); - video.set_window_title(&title); + video.borrow_mut().set_window_title(&title); } if !no_framerate_limit { diff --git a/src/plat/sdl2/video.rs b/src/plat/sdl2/video.rs index 71e6805..fe13564 100644 --- a/src/plat/sdl2/video.rs +++ b/src/plat/sdl2/video.rs @@ -12,19 +12,19 @@ const SCREEN_WIDTH: u32 = DISPLAY_WIDTH as u32; const SCREEN_HEIGHT: u32 = DISPLAY_HEIGHT as u32; const SCALE: u32 = 3; // TODO control via CLI & support window resize -pub struct Sdl2VideoInterface { +pub struct Sdl2Video { tc: TextureCreator, canvas: WindowCanvas, fps_counter: FpsCounter, } -impl Sdl2VideoInterface { +impl Sdl2Video { pub fn set_window_title(&mut self, title: &str) { self.canvas.window_mut().set_title(&title); } } -impl VideoInterface for Sdl2VideoInterface { +impl VideoInterface for Sdl2Video { fn render(&mut self, buffer: &[u32]) { let mut texture = self .tc @@ -53,7 +53,7 @@ impl VideoInterface for Sdl2VideoInterface { } } -pub fn create_video_interface(sdl: &Sdl) -> Sdl2VideoInterface { +pub fn create_video_interface(sdl: &Sdl) -> Sdl2Video { let video_subsystem = sdl.video().unwrap(); let window = video_subsystem .window( @@ -69,7 +69,7 @@ pub fn create_video_interface(sdl: &Sdl) -> Sdl2VideoInterface { canvas.set_draw_color(Color::RGB(0, 0, 0)); canvas.clear(); let tc = canvas.texture_creator(); - Sdl2VideoInterface { + Sdl2Video { tc: tc, canvas: canvas, fps_counter: Default::default(),