Use Rc<RefCell<T>> to have the GameboyAdvance struct hold references to platform video,audio,input combo

Former-commit-id: bfe233a333790fe1bad1038bd553a3fe244e57fa
This commit is contained in:
Michel Heily 2019-12-09 23:37:46 +02:00
parent aee86d85c8
commit 385016f24a
6 changed files with 87 additions and 37 deletions

View file

@ -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<V, A, I>
where
V: VideoInterface,
A: AudioInterface,
I: InputInterface,
{
pub sysbus: Box<SysBus>,
pub cpu: Core,
video_device: Rc<RefCell<V>>,
audio_device: Rc<RefCell<A>>,
input_device: Rc<RefCell<I>>,
}
impl GameBoyAdvance {
pub fn new(cpu: Core, bios_rom: Vec<u8>, gamepak: Cartridge) -> GameBoyAdvance {
impl<V, A, I> GameBoyAdvance<V, A, I>
where
V: VideoInterface,
A: AudioInterface,
I: InputInterface,
{
pub fn new(
cpu: Core,
bios_rom: Vec<u8>,
gamepak: Cartridge,
video_device: Rc<RefCell<V>>,
audio_device: Rc<RefCell<A>>,
input_device: Rc<RefCell<I>>,
) -> GameBoyAdvance<V, A, I> {
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;

View file

@ -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<V, A, I> Debugger<V, A, I>
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();
// }
// }
// }

View file

@ -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<T> = Result<T, DebuggerError>;
pub struct Debugger {
pub gba: GameBoyAdvance,
pub struct Debugger<V, A, I>
where
V: VideoInterface,
A: AudioInterface,
I: InputInterface,
{
pub gba: GameBoyAdvance<V, A, I>,
running: bool,
pub ctrlc_flag: Arc<AtomicBool>,
pub previous_command: Option<Command>,
}
impl Debugger {
pub fn new(gba: GameBoyAdvance) -> Debugger {
impl<V, A, I> Debugger<V, A, I>
where
V: VideoInterface,
A: AudioInterface,
I: InputInterface,
{
pub fn new(gba: GameBoyAdvance<V, A, I>) -> Debugger<V, A, I> {
let ctrlc_flag = Arc::new(AtomicBool::new(true));
let r = ctrlc_flag.clone();
ctrlc::set_handler(move || {

View file

@ -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<gba_keypad::Keys> {
}
}
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,
}

View file

@ -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<Sdl2Video, Sdl2AudioPlayer, Sdl2Input> =
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 {

View file

@ -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<WindowContext>,
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(),