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
|
||||
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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -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 || {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
|
|
Reference in a new issue