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