core: add "no_video_interface" feature

Former-commit-id: 0b1462e3ef1ab65c37e2c0fce54bc7f5c2f9f2b5
Former-commit-id: 7b837be4dcb477b048f0118c4ab30f97eb445363
This commit is contained in:
Michel Heily 2020-09-30 00:10:47 +03:00
parent e25268f4d8
commit 08a7cd966a
4 changed files with 32 additions and 5 deletions

View file

@ -58,3 +58,5 @@ elf_support = ["goblin"]
# Uses lookup tables when executing instructions instead of `match` statements. # Uses lookup tables when executing instructions instead of `match` statements.
# Faster, but consumes more memory. # Faster, but consumes more memory.
arm7tdmi_dispatch_table = [] arm7tdmi_dispatch_table = []
# For use for ports where VideoInterface is not needed like wasm & jni
no_video_interface = []

View file

@ -15,12 +15,15 @@ use super::sound::SoundController;
use super::sysbus::SysBus; use super::sysbus::SysBus;
use super::timer::Timers; use super::timer::Timers;
use super::{AudioInterface, InputInterface, VideoInterface}; use super::{AudioInterface, InputInterface};
#[cfg(not(feature = "no_video_interface"))]
use super::VideoInterface;
pub struct GameBoyAdvance { pub struct GameBoyAdvance {
pub sysbus: Box<SysBus>, pub sysbus: Box<SysBus>,
pub cpu: arm7tdmi::Core, pub cpu: arm7tdmi::Core,
#[cfg(not(feature = "no_video_interface"))]
pub video_device: Rc<RefCell<dyn VideoInterface>>, pub video_device: Rc<RefCell<dyn VideoInterface>>,
pub audio_device: Rc<RefCell<dyn AudioInterface>>, pub audio_device: Rc<RefCell<dyn AudioInterface>>,
pub input_device: Rc<RefCell<dyn InputInterface>>, pub input_device: Rc<RefCell<dyn InputInterface>>,
@ -55,6 +58,7 @@ impl GameBoyAdvance {
pub fn new( pub fn new(
bios_rom: Box<[u8]>, bios_rom: Box<[u8]>,
gamepak: Cartridge, gamepak: Cartridge,
#[cfg(not(feature = "no_video_interface"))]
video_device: Rc<RefCell<dyn VideoInterface>>, video_device: Rc<RefCell<dyn VideoInterface>>,
audio_device: Rc<RefCell<dyn AudioInterface>>, audio_device: Rc<RefCell<dyn AudioInterface>>,
input_device: Rc<RefCell<dyn InputInterface>>, input_device: Rc<RefCell<dyn InputInterface>>,
@ -83,6 +87,7 @@ impl GameBoyAdvance {
cpu: cpu, cpu: cpu,
sysbus: sysbus, sysbus: sysbus,
#[cfg(not(feature = "no_video_interface"))]
video_device: video_device, video_device: video_device,
audio_device: audio_device, audio_device: audio_device,
input_device: input_device, input_device: input_device,
@ -99,6 +104,7 @@ impl GameBoyAdvance {
pub fn from_saved_state( pub fn from_saved_state(
savestate: &[u8], savestate: &[u8],
#[cfg(not(feature = "no_video_interface"))]
video_device: Rc<RefCell<dyn VideoInterface>>, video_device: Rc<RefCell<dyn VideoInterface>>,
audio_device: Rc<RefCell<dyn AudioInterface>>, audio_device: Rc<RefCell<dyn AudioInterface>>,
input_device: Rc<RefCell<dyn InputInterface>>, input_device: Rc<RefCell<dyn InputInterface>>,
@ -117,6 +123,7 @@ impl GameBoyAdvance {
interrupt_flags: interrupts, interrupt_flags: interrupts,
#[cfg(not(feature = "no_video_interface"))]
video_device: video_device, video_device: video_device,
audio_device: audio_device, audio_device: audio_device,
input_device: input_device, input_device: input_device,
@ -258,6 +265,7 @@ impl GameBoyAdvance {
cycles, cycles,
&mut cycles_to_next_event, &mut cycles_to_next_event,
self.sysbus.as_mut(), self.sysbus.as_mut(),
#[cfg(not(feature = "no_video_interface"))]
&self.video_device, &self.video_device,
); );
io.sound io.sound
@ -292,6 +300,7 @@ impl GameBoyAdvance {
cycles, cycles,
&mut _ignored, &mut _ignored,
self.sysbus.as_mut(), self.sysbus.as_mut(),
#[cfg(not(feature = "no_video_interface"))]
&self.video_device, &self.video_device,
); );
io.sound.update(cycles, &mut _ignored, &self.audio_device); io.sound.update(cycles, &mut _ignored, &self.audio_device);

View file

@ -1,5 +1,7 @@
#[cfg(not(feature = "no_video_interface"))]
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt; use std::fmt;
#[cfg(not(feature = "no_video_interface"))]
use std::rc::Rc; use std::rc::Rc;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -9,6 +11,7 @@ use super::dma::{DmaNotifer, TIMING_HBLANK, TIMING_VBLANK};
use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags}; use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags};
pub use super::sysbus::consts::*; pub use super::sysbus::consts::*;
use super::util::BoxedMemory; use super::util::BoxedMemory;
#[cfg(not(feature = "no_video_interface"))]
use super::VideoInterface; use super::VideoInterface;
use crate::bitfield::Bit; use crate::bitfield::Bit;
@ -172,6 +175,7 @@ impl Default for ObjBufferEntry {
} }
} }
#[cfg(not(feature = "no_video_interface"))]
type VideoDeviceRcRefCell = Rc<RefCell<dyn VideoInterface>>; type VideoDeviceRcRefCell = Rc<RefCell<dyn VideoInterface>>;
#[derive(Serialize, Deserialize, Clone, DebugStub)] #[derive(Serialize, Deserialize, Clone, DebugStub)]
@ -414,7 +418,7 @@ impl Gpu {
&mut self, &mut self,
completed: GpuState, completed: GpuState,
dma_notifier: &mut D, dma_notifier: &mut D,
video_device: &VideoDeviceRcRefCell, #[cfg(not(feature = "no_video_interface"))] video_device: &VideoDeviceRcRefCell,
) where ) where
D: DmaNotifer, D: DmaNotifer,
{ {
@ -470,7 +474,10 @@ impl Gpu {
}; };
dma_notifier.notify(TIMING_VBLANK); dma_notifier.notify(TIMING_VBLANK);
#[cfg(not(feature = "no_video_interface"))]
video_device.borrow_mut().render(&self.frame_buffer); video_device.borrow_mut().render(&self.frame_buffer);
self.obj_buffer_reset(); self.obj_buffer_reset();
self.cycles_left_for_current_state = CYCLES_HDRAW; self.cycles_left_for_current_state = CYCLES_HDRAW;
self.state = VBlankHDraw; self.state = VBlankHDraw;
@ -508,14 +515,19 @@ impl Gpu {
mut cycles: usize, mut cycles: usize,
cycles_to_next_event: &mut usize, cycles_to_next_event: &mut usize,
dma_notifier: &mut D, dma_notifier: &mut D,
video_device: &VideoDeviceRcRefCell, #[cfg(not(feature = "no_video_interface"))] video_device: &VideoDeviceRcRefCell,
) where ) where
D: DmaNotifer, D: DmaNotifer,
{ {
loop { loop {
if self.cycles_left_for_current_state <= cycles { if self.cycles_left_for_current_state <= cycles {
cycles -= self.cycles_left_for_current_state; cycles -= self.cycles_left_for_current_state;
self.on_state_completed(self.state, dma_notifier, video_device); self.on_state_completed(
self.state,
dma_notifier,
#[cfg(not(feature = "no_video_interface"))]
video_device,
);
} else { } else {
self.cycles_left_for_current_state -= cycles; self.cycles_left_for_current_state -= cycles;
break; break;
@ -638,6 +650,7 @@ mod tests {
$cycles, $cycles,
&mut cycles_to_next_event, &mut cycles_to_next_event,
&mut dma_notifier, &mut dma_notifier,
#[cfg(not(feature = "no_video_interface"))]
&video_clone, &video_clone,
); );
total_cycles += $cycles; total_cycles += $cycles;

View file

@ -59,6 +59,7 @@ pub mod gdb;
#[cfg(feature = "debugger")] #[cfg(feature = "debugger")]
pub mod debugger; pub mod debugger;
#[cfg(not(feature = "no_video_interface"))]
pub trait VideoInterface { pub trait VideoInterface {
#[allow(unused_variables)] #[allow(unused_variables)]
fn render(&mut self, buffer: &[u32]) {} fn render(&mut self, buffer: &[u32]) {}
@ -133,6 +134,8 @@ pub mod prelude {
pub use super::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH}; pub use super::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH};
pub use super::util::{read_bin_file, write_bin_file}; pub use super::util::{read_bin_file, write_bin_file};
pub use super::Bus; pub use super::Bus;
pub use super::{AudioInterface, InputInterface, StereoSample, VideoInterface}; pub use super::{AudioInterface, InputInterface, StereoSample};
#[cfg(not(feature = "no_video_interface"))]
pub use super::VideoInterface;
pub use super::{GBAError, GBAResult, GameBoyAdvance}; pub use super::{GBAError, GBAResult, GameBoyAdvance};
} }