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.
# Faster, but consumes more memory.
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::timer::Timers;
use super::{AudioInterface, InputInterface, VideoInterface};
use super::{AudioInterface, InputInterface};
#[cfg(not(feature = "no_video_interface"))]
use super::VideoInterface;
pub struct GameBoyAdvance {
pub sysbus: Box<SysBus>,
pub cpu: arm7tdmi::Core,
#[cfg(not(feature = "no_video_interface"))]
pub video_device: Rc<RefCell<dyn VideoInterface>>,
pub audio_device: Rc<RefCell<dyn AudioInterface>>,
pub input_device: Rc<RefCell<dyn InputInterface>>,
@ -55,6 +58,7 @@ impl GameBoyAdvance {
pub fn new(
bios_rom: Box<[u8]>,
gamepak: Cartridge,
#[cfg(not(feature = "no_video_interface"))]
video_device: Rc<RefCell<dyn VideoInterface>>,
audio_device: Rc<RefCell<dyn AudioInterface>>,
input_device: Rc<RefCell<dyn InputInterface>>,
@ -83,6 +87,7 @@ impl GameBoyAdvance {
cpu: cpu,
sysbus: sysbus,
#[cfg(not(feature = "no_video_interface"))]
video_device: video_device,
audio_device: audio_device,
input_device: input_device,
@ -99,6 +104,7 @@ impl GameBoyAdvance {
pub fn from_saved_state(
savestate: &[u8],
#[cfg(not(feature = "no_video_interface"))]
video_device: Rc<RefCell<dyn VideoInterface>>,
audio_device: Rc<RefCell<dyn AudioInterface>>,
input_device: Rc<RefCell<dyn InputInterface>>,
@ -117,6 +123,7 @@ impl GameBoyAdvance {
interrupt_flags: interrupts,
#[cfg(not(feature = "no_video_interface"))]
video_device: video_device,
audio_device: audio_device,
input_device: input_device,
@ -258,6 +265,7 @@ impl GameBoyAdvance {
cycles,
&mut cycles_to_next_event,
self.sysbus.as_mut(),
#[cfg(not(feature = "no_video_interface"))]
&self.video_device,
);
io.sound
@ -292,6 +300,7 @@ impl GameBoyAdvance {
cycles,
&mut _ignored,
self.sysbus.as_mut(),
#[cfg(not(feature = "no_video_interface"))]
&self.video_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::fmt;
#[cfg(not(feature = "no_video_interface"))]
use std::rc::Rc;
use serde::{Deserialize, Serialize};
@ -9,6 +11,7 @@ use super::dma::{DmaNotifer, TIMING_HBLANK, TIMING_VBLANK};
use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags};
pub use super::sysbus::consts::*;
use super::util::BoxedMemory;
#[cfg(not(feature = "no_video_interface"))]
use super::VideoInterface;
use crate::bitfield::Bit;
@ -172,6 +175,7 @@ impl Default for ObjBufferEntry {
}
}
#[cfg(not(feature = "no_video_interface"))]
type VideoDeviceRcRefCell = Rc<RefCell<dyn VideoInterface>>;
#[derive(Serialize, Deserialize, Clone, DebugStub)]
@ -414,7 +418,7 @@ impl Gpu {
&mut self,
completed: GpuState,
dma_notifier: &mut D,
video_device: &VideoDeviceRcRefCell,
#[cfg(not(feature = "no_video_interface"))] video_device: &VideoDeviceRcRefCell,
) where
D: DmaNotifer,
{
@ -470,7 +474,10 @@ impl Gpu {
};
dma_notifier.notify(TIMING_VBLANK);
#[cfg(not(feature = "no_video_interface"))]
video_device.borrow_mut().render(&self.frame_buffer);
self.obj_buffer_reset();
self.cycles_left_for_current_state = CYCLES_HDRAW;
self.state = VBlankHDraw;
@ -508,14 +515,19 @@ impl Gpu {
mut cycles: usize,
cycles_to_next_event: &mut usize,
dma_notifier: &mut D,
video_device: &VideoDeviceRcRefCell,
#[cfg(not(feature = "no_video_interface"))] video_device: &VideoDeviceRcRefCell,
) where
D: DmaNotifer,
{
loop {
if self.cycles_left_for_current_state <= cycles {
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 {
self.cycles_left_for_current_state -= cycles;
break;
@ -638,6 +650,7 @@ mod tests {
$cycles,
&mut cycles_to_next_event,
&mut dma_notifier,
#[cfg(not(feature = "no_video_interface"))]
&video_clone,
);
total_cycles += $cycles;

View file

@ -59,6 +59,7 @@ pub mod gdb;
#[cfg(feature = "debugger")]
pub mod debugger;
#[cfg(not(feature = "no_video_interface"))]
pub trait VideoInterface {
#[allow(unused_variables)]
fn render(&mut self, buffer: &[u32]) {}
@ -133,6 +134,8 @@ pub mod prelude {
pub use super::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH};
pub use super::util::{read_bin_file, write_bin_file};
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};
}