diff --git a/arm7tdmi/src/simple_memory.rs b/arm7tdmi/src/simple_memory.rs
index df0e561..4d5d986 100644
--- a/arm7tdmi/src/simple_memory.rs
+++ b/arm7tdmi/src/simple_memory.rs
@@ -69,13 +69,16 @@ impl DebugRead for SimpleMemory {
impl MemoryGdbInterface for SimpleMemory {
fn memory_map_xml(&self, offset: u64, length: usize, buf: &mut [u8]) -> usize {
- let memory_map = format!(r#"
+ let memory_map = format!(
+ r#"
- "#, self.data.len());
+ "#,
+ self.data.len()
+ );
copy_range_to_buf(memory_map.trim().as_bytes(), offset, length, buf)
}
}
diff --git a/core/BENCHMARK.md b/core/BENCHMARK.md
index edad29b..401d0c2 100644
--- a/core/BENCHMARK.md
+++ b/core/BENCHMARK.md
@@ -2,5 +2,5 @@
rustboyadvance-core crate provides a simple yet effective performance benchmark.
-to run it use `cargo bench --manifest-path ./core/Cargo.toml --features no_video_interface` from the repository root
+to run it use `cargo bench --manifest-path ./core/Cargo.toml` from the repository root
diff --git a/core/Cargo.toml b/core/Cargo.toml
index e6c65d7..300c713 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -54,6 +54,4 @@ harness = false
default = []
elf_support = []
debugger = ["nom", "rustyline", "fuzzy-matcher", "elf_support"]
-gdb = ["gdbstub"]
-# For use for ports where VideoInterface is not needed like wasm & jni
-no_video_interface = []
+gdb = ["gdbstub"]
\ No newline at end of file
diff --git a/core/src/cartridge/loader.rs b/core/src/cartridge/loader.rs
index e55589e..99ce52d 100644
--- a/core/src/cartridge/loader.rs
+++ b/core/src/cartridge/loader.rs
@@ -11,7 +11,6 @@ use rustboyadvance_utils::elf::{load_elf, GoblinError};
use rustboyadvance_utils::read_bin_file;
use zip::ZipArchive;
-
pub enum LoadRom {
#[cfg(feature = "elf_support")]
Elf {
diff --git a/core/src/gba.rs b/core/src/gba.rs
index 6e8b2b9..4bf0bcc 100644
--- a/core/src/gba.rs
+++ b/core/src/gba.rs
@@ -16,8 +16,6 @@ use super::sysbus::SysBus;
use super::timer::Timers;
use super::AudioInterface;
-#[cfg(not(feature = "no_video_interface"))]
-use super::VideoInterface;
use arm7tdmi::{self, Arm7tdmiCore};
use rustboyadvance_utils::Shared;
@@ -28,8 +26,6 @@ pub struct GameBoyAdvance {
pub io_devs: Shared,
pub scheduler: SharedScheduler,
interrupt_flags: SharedInterruptFlags,
- #[cfg(not(feature = "no_video_interface"))]
- pub video_device: Rc>,
pub audio_device: Rc>,
}
@@ -67,7 +63,6 @@ impl GameBoyAdvance {
pub fn new(
bios_rom: Box<[u8]>,
gamepak: Cartridge,
- #[cfg(not(feature = "no_video_interface"))] video_device: Rc>,
audio_device: Rc>,
) -> GameBoyAdvance {
// Warn the user if the bios is not the real one
@@ -108,8 +103,6 @@ impl GameBoyAdvance {
cpu,
sysbus,
io_devs,
- #[cfg(not(feature = "no_video_interface"))]
- video_device,
audio_device,
scheduler,
interrupt_flags,
@@ -124,7 +117,6 @@ impl GameBoyAdvance {
savestate: &[u8],
bios: Box<[u8]>,
rom: Box<[u8]>,
- #[cfg(not(feature = "no_video_interface"))] video_device: Rc>,
audio_device: Rc>,
) -> bincode::Result {
let decoded: Box = bincode::deserialize_from(savestate)?;
@@ -156,8 +148,6 @@ impl GameBoyAdvance {
sysbus,
io_devs,
interrupt_flags: interrupts,
- #[cfg(not(feature = "no_video_interface"))]
- video_device,
audio_device,
scheduler,
})
@@ -308,12 +298,7 @@ impl GameBoyAdvance {
let apu = &mut io.sound;
Some(timers.handle_overflow_event(channel_id, event_time, apu, dmac))
}
- EventType::Gpu(gpu_event) => Some(io.gpu.on_event(
- gpu_event,
- &mut *self.sysbus,
- #[cfg(not(feature = "no_video_interface"))]
- &self.video_device,
- )),
+ EventType::Gpu(gpu_event) => Some(io.gpu.on_event(gpu_event, &mut *self.sysbus)),
EventType::Apu(event) => Some(io.sound.on_event(event, &self.audio_device)),
};
if let Some((new_event, when)) = new_event {
@@ -380,8 +365,6 @@ impl GameBoyAdvance {
breakpoint
}
- /// Query the emulator for the recently drawn framebuffer.
- /// for use with implementations where the VideoInterface is not a viable option.
pub fn get_frame_buffer(&self) -> &[u32] {
self.sysbus.io.gpu.get_frame_buffer()
}
@@ -401,17 +384,15 @@ mod tests {
use crate::cartridge::GamepakBuilder;
use arm7tdmi::memory::BusIO;
- struct DummyInterface {}
+ struct DummyAudio {}
- impl DummyInterface {
- fn new() -> DummyInterface {
- DummyInterface {}
+ impl DummyAudio {
+ fn new() -> DummyAudio {
+ DummyAudio {}
}
}
- #[cfg(not(feature = "no_video_interface"))]
- impl VideoInterface for DummyInterface {}
- impl AudioInterface for DummyInterface {}
+ impl AudioInterface for DummyAudio {}
fn make_mock_gba(rom: &[u8]) -> GameBoyAdvance {
let bios = vec![0; 0x4000].into_boxed_slice();
@@ -421,14 +402,8 @@ mod tests {
.without_backup_to_file()
.build()
.unwrap();
- let dummy = Rc::new(RefCell::new(DummyInterface::new()));
- let mut gba = GameBoyAdvance::new(
- bios,
- cartridge,
- #[cfg(not(feature = "no_video_interface"))]
- dummy.clone(),
- dummy.clone(),
- );
+ let dummy = Rc::new(RefCell::new(DummyAudio::new()));
+ let mut gba = GameBoyAdvance::new(bios, cartridge, dummy.clone());
gba.skip_bios();
gba
diff --git a/core/src/gpu/mod.rs b/core/src/gpu/mod.rs
index 8ad8ac6..078704d 100644
--- a/core/src/gpu/mod.rs
+++ b/core/src/gpu/mod.rs
@@ -1,8 +1,3 @@
-#[cfg(not(feature = "no_video_interface"))]
-use std::cell::RefCell;
-#[cfg(not(feature = "no_video_interface"))]
-use std::rc::Rc;
-
use num::FromPrimitive;
use serde::{Deserialize, Serialize};
@@ -13,8 +8,6 @@ use super::dma::{DmaNotifer, TIMING_HBLANK, TIMING_VBLANK};
use super::interrupt::{self, Interrupt, InterruptConnect, SharedInterruptFlags};
use super::sched::{EventType, FutureEvent, GpuEvent, Scheduler};
pub use super::sysbus::consts::*;
-#[cfg(not(feature = "no_video_interface"))]
-use super::VideoInterface;
mod render;
@@ -107,9 +100,6 @@ impl Default for ObjBufferEntry {
}
}
-#[cfg(not(feature = "no_video_interface"))]
-type VideoDeviceRcRefCell = Rc>;
-
#[derive(Serialize, Deserialize, Clone, DebugStub)]
pub struct Gpu {
interrupt_flags: SharedInterruptFlags,
@@ -369,11 +359,7 @@ impl Gpu {
(GpuEvent::HBlank, CYCLES_HBLANK)
}
- fn handle_hblank_end(
- &mut self,
- dma_notifier: &mut D,
- #[cfg(not(feature = "no_video_interface"))] video_device: &VideoDeviceRcRefCell,
- ) -> FutureGpuEvent {
+ fn handle_hblank_end(&mut self, dma_notifier: &mut D) -> FutureGpuEvent {
self.update_vcount(self.vcount + 1);
if self.vcount < DISPLAY_HEIGHT {
@@ -401,9 +387,6 @@ 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();
(GpuEvent::VBlankHDraw, CYCLES_HDRAW)
@@ -432,22 +415,13 @@ impl Gpu {
}
}
- pub fn on_event(
- &mut self,
- event: GpuEvent,
- dma_notifier: &mut D,
- #[cfg(not(feature = "no_video_interface"))] video_device: &VideoDeviceRcRefCell,
- ) -> FutureEvent
+ pub fn on_event(&mut self, event: GpuEvent, dma_notifier: &mut D) -> FutureEvent
where
D: DmaNotifer,
{
let (event, when) = match event {
GpuEvent::HDraw => self.handle_hdraw_end(dma_notifier),
- GpuEvent::HBlank => self.handle_hblank_end(
- dma_notifier,
- #[cfg(not(feature = "no_video_interface"))]
- video_device,
- ),
+ GpuEvent::HBlank => self.handle_hblank_end(dma_notifier),
GpuEvent::VBlankHDraw => self.handle_vblank_hdraw_end(),
GpuEvent::VBlankHBlank => self.handle_vblank_hblank_end(),
};
@@ -549,26 +523,10 @@ mod tests {
fn notify(&mut self, _timing: u16) {}
}
- #[derive(Default)]
- struct TestVideoInterface {
- frame_counter: usize,
- }
-
- #[cfg(not(feature = "no_video_interface"))]
- impl VideoInterface for TestVideoInterface {
- fn render(&mut self, _buffer: &[u32]) {
- self.frame_counter += 1;
- }
- }
-
#[test]
fn test_gpu_state_machine() {
let mut sched = Scheduler::new();
let mut gpu = Gpu::new(&mut sched, Rc::new(Cell::new(Default::default())));
- #[cfg(not(feature = "no_video_interface"))]
- let video = Rc::new(RefCell::new(TestVideoInterface::default()));
- #[cfg(not(feature = "no_video_interface"))]
- let video_clone: VideoDeviceRcRefCell = video.clone();
let mut dma_notifier = NopDmaNotifer;
gpu.dispstat.vcount_setting = 0;
@@ -580,12 +538,7 @@ mod tests {
let (event, event_time) = sched.pop_pending_event().unwrap();
assert_eq!(event_time, sched.timestamp());
let next_event = match event {
- EventType::Gpu(event) => gpu.on_event(
- event,
- &mut dma_notifier,
- #[cfg(not(feature = "no_video_interface"))]
- &video_clone,
- ),
+ EventType::Gpu(event) => gpu.on_event(event, &mut dma_notifier),
_ => panic!("Found unexpected event in queue!"),
};
sched.schedule(next_event);
@@ -594,8 +547,6 @@ mod tests {
for line in 0..160 {
println!("line = {}", line);
- #[cfg(not(feature = "no_video_interface"))]
- assert_eq!(video.borrow().frame_counter, 0);
assert_eq!(gpu.vcount, line);
assert_eq!(sched.peek_next(), Some(EventType::Gpu(GpuEvent::HDraw)));
assert_eq!(gpu.dispstat.hblank_flag, false);
@@ -613,9 +564,6 @@ mod tests {
assert_eq!(gpu.interrupt_flags.get().LCD_VCounterMatch(), false);
}
- #[cfg(not(feature = "no_video_interface"))]
- assert_eq!(video.borrow().frame_counter, 1);
-
for line in 0..68 {
println!("line = {}", 160 + line);
assert_eq!(gpu.dispstat.hblank_flag, false);
@@ -638,8 +586,6 @@ mod tests {
update!(CYCLES_HBLANK);
}
- #[cfg(not(feature = "no_video_interface"))]
- assert_eq!(video.borrow().frame_counter, 1);
assert_eq!(sched.timestamp(), CYCLES_FULL_REFRESH);
assert_eq!(gpu.interrupt_flags.get().LCD_VCounterMatch(), true);
diff --git a/core/src/lib.rs b/core/src/lib.rs
index 471606c..fbe1f7f 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -55,12 +55,6 @@ pub(crate) mod overrides;
#[cfg(feature = "debugger")]
pub mod debugger;
-#[cfg(not(feature = "no_video_interface"))]
-pub trait VideoInterface {
- #[allow(unused_variables)]
- fn render(&mut self, buffer: &[u32]) {}
-}
-
pub type StereoSample = [T; 2];
pub trait AudioInterface {
@@ -129,8 +123,6 @@ pub mod prelude {
pub use super::debugger::Debugger;
pub use super::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH};
pub use super::Bus;
- #[cfg(not(feature = "no_video_interface"))]
- pub use super::VideoInterface;
pub use super::{AudioInterface, StereoSample};
pub use super::{GBAError, GBAResult, GameBoyAdvance};
pub use rustboyadvance_utils::{read_bin_file, write_bin_file};
diff --git a/fps_bench/src/main.rs b/fps_bench/src/main.rs
index 16f292b..4a36b6a 100644
--- a/fps_bench/src/main.rs
+++ b/fps_bench/src/main.rs
@@ -6,16 +6,15 @@ use std::rc::Rc;
use rustboyadvance_core::prelude::*;
use rustboyadvance_core::util::FpsCounter;
-struct BenchmarkHardware {}
+struct DummyAudio {}
-impl BenchmarkHardware {
- fn new() -> BenchmarkHardware {
- BenchmarkHardware {}
+impl DummyAudio {
+ fn new() -> DummyAudio {
+ DummyAudio {}
}
}
-impl VideoInterface for BenchmarkHardware {}
-impl AudioInterface for BenchmarkHardware {}
+impl AudioInterface for DummyAudio {}
fn main() {
if env::args().count() < 3 {
@@ -36,14 +35,9 @@ fn main() {
.build()
.unwrap();
- let dummy = Rc::new(RefCell::new(BenchmarkHardware::new()));
+ let dummy = Rc::new(RefCell::new(DummyAudio::new()));
- let mut gba = GameBoyAdvance::new(
- bios.into_boxed_slice(),
- gamepak,
- dummy.clone(),
- dummy.clone(),
- );
+ let mut gba = GameBoyAdvance::new(bios.into_boxed_slice(), gamepak, dummy.clone());
gba.skip_bios();
let mut fps_counter = FpsCounter::default();
diff --git a/platform/rustboyadvance-jni/Cargo.toml b/platform/rustboyadvance-jni/Cargo.toml
index 824e1d1..c4fe42b 100644
--- a/platform/rustboyadvance-jni/Cargo.toml
+++ b/platform/rustboyadvance-jni/Cargo.toml
@@ -10,8 +10,8 @@ publish = false
crate-type = ["staticlib", "cdylib"]
[dependencies]
-rustboyadvance-core = {path = "../../core/", features = ["no_video_interface"]}
-rustboyadvance-utils = {path = "../../utils/" }
+rustboyadvance-core = { path = "../../core/" }
+rustboyadvance-utils = { path = "../../utils/" }
jni = "0.17.0"
log = {version = "0.4.8", features = ["release_max_level_info", "max_level_debug"]}
diff --git a/platform/rustboyadvance-jni/src/emulator.rs b/platform/rustboyadvance-jni/src/emulator.rs
index 4d0d242..8e7646c 100644
--- a/platform/rustboyadvance-jni/src/emulator.rs
+++ b/platform/rustboyadvance-jni/src/emulator.rs
@@ -15,12 +15,12 @@ use jni::JNIEnv;
use crate::audio::{self, connector::AudioJNIConnector, thread::AudioThreadCommand};
-struct Hardware {
+struct AudioDevice {
sample_rate: i32,
audio_producer: Option>,
}
-impl AudioInterface for Hardware {
+impl AudioInterface for AudioDevice {
fn push_sample(&mut self, samples: &[i16]) {
if let Some(prod) = &mut self.audio_producer {
for s in samples.iter() {
@@ -146,7 +146,7 @@ impl Default for EmulationState {
}
pub struct EmulatorContext {
- hwif: Rc>,
+ audio_device: Rc>,
renderer: Renderer,
audio_player_ref: GlobalRef,
keypad: Keypad,
@@ -188,11 +188,11 @@ impl EmulatorContext {
let renderer = Renderer::new(env, renderer_obj)?;
info!("Creating GBA Instance");
- let hw = Rc::new(RefCell::new(Hardware {
+ let audio = Rc::new(RefCell::new(AudioDevice {
sample_rate: audio::util::get_sample_rate(env, audio_player),
audio_producer: None,
}));
- let mut gba = GameBoyAdvance::new(bios, gamepak, hw.clone());
+ let mut gba = GameBoyAdvance::new(bios, gamepak, audio.clone());
if skip_bios != 0 {
info!("skipping bios");
gba.skip_bios();
@@ -209,7 +209,7 @@ impl EmulatorContext {
renderer,
audio_player_ref,
emustate: Mutex::new(EmulationState::default()),
- hwif: hw.clone(),
+ audio_device: audio.clone(),
};
Ok(context)
}
@@ -237,17 +237,18 @@ impl EmulatorContext {
let renderer = Renderer::new(env, renderer_obj)?;
- let hw = Rc::new(RefCell::new(Hardware {
+ let audio = Rc::new(RefCell::new(AudioDevice {
sample_rate: audio::util::get_sample_rate(env, audio_player),
audio_producer: None,
}));
- let gba = GameBoyAdvance::from_saved_state(&savestate, bios, rom, hw.clone())
- .map_err(|e| {
- format!(
- "failed to create GameBoyAdvance from saved savestate, error {:?}",
- e
- )
- })?;
+ let gba = GameBoyAdvance::from_saved_state(&savestate, bios, rom, audio.clone()).map_err(
+ |e| {
+ format!(
+ "failed to create GameBoyAdvance from saved savestate, error {:?}",
+ e
+ )
+ },
+ )?;
let keypad = Keypad::new(env, keypad_obj);
@@ -258,7 +259,7 @@ impl EmulatorContext {
renderer,
audio_player_ref,
emustate: Mutex::new(EmulationState::default()),
- hwif: hw.clone(),
+ audio_device: audio.clone(),
})
}
@@ -288,7 +289,7 @@ impl EmulatorContext {
let (prod, cons) = AudioRingBuffer::new_with_capacity(audio_connector.sample_count).split();
// Store the ringbuffer producer in the emulator
- self.hwif.borrow_mut().audio_producer = Some(prod);
+ self.audio_device.borrow_mut().audio_producer = Some(prod);
// Spawn the audio worker thread, give it the audio connector, jvm and ringbuffer consumer
let (audio_thread_handle, audio_thread_tx) =
@@ -354,7 +355,7 @@ impl EmulatorContext {
audio_connector.pause(env);
- self.hwif.borrow_mut().audio_producer = None;
+ self.audio_device.borrow_mut().audio_producer = None;
*self.emustate.lock().unwrap() = EmulationState::Stopped;
diff --git a/platform/rustboyadvance-libretro/Cargo.toml b/platform/rustboyadvance-libretro/Cargo.toml
index 68e1002..9d151fc 100644
--- a/platform/rustboyadvance-libretro/Cargo.toml
+++ b/platform/rustboyadvance-libretro/Cargo.toml
@@ -10,7 +10,7 @@ crate-type = ["cdylib"]
[dependencies]
-rustboyadvance-core = { path = "../../core/", features = ["no_video_interface"] }
+rustboyadvance-core = { path = "../../core/" }
rustboyadvance-utils = { path = "../../utils" }
log = "0.4.8"
libc = "0.2"
diff --git a/platform/rustboyadvance-libretro/src/lib.rs b/platform/rustboyadvance-libretro/src/lib.rs
index 2dba8e8..d1fd5a3 100644
--- a/platform/rustboyadvance-libretro/src/lib.rs
+++ b/platform/rustboyadvance-libretro/src/lib.rs
@@ -49,7 +49,7 @@ struct GbaButton(_GbaButton);
impl Deref for GbaButton {
type Target = _GbaButton;
fn deref(&self) -> &Self::Target {
- return &self.0
+ return &self.0;
}
}
diff --git a/platform/rustboyadvance-sdl2/src/main.rs b/platform/rustboyadvance-sdl2/src/main.rs
index 801a84e..3664650 100644
--- a/platform/rustboyadvance-sdl2/src/main.rs
+++ b/platform/rustboyadvance-sdl2/src/main.rs
@@ -1,4 +1,3 @@
-use sdl2;
use sdl2::controller::Button;
use sdl2::event::{Event, WindowEvent};
use sdl2::image::{InitFlag, LoadSurface, LoadTexture};
@@ -7,6 +6,7 @@ use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::WindowCanvas;
use sdl2::surface::Surface;
+use sdl2::{self};
use sdl2::EventPump;
@@ -37,7 +37,7 @@ mod input;
mod video;
use audio::{create_audio_player, create_dummy_player};
-use video::{create_video_interface, SCREEN_HEIGHT, SCREEN_WIDTH};
+use video::{SCREEN_HEIGHT, SCREEN_WIDTH};
use rustboyadvance_core::cartridge::BackupType;
use rustboyadvance_core::prelude::*;
@@ -182,7 +182,7 @@ fn main() -> Result<(), Box> {
}
};
- let video = Rc::new(RefCell::new(create_video_interface(canvas)));
+ let mut renderer = video::Renderer::from_canvas(canvas);
let audio: Rc> = if silent {
Rc::new(RefCell::new(create_dummy_player()))
} else {
@@ -205,12 +205,7 @@ fn main() -> Result<(), Box> {
let gamepak = builder.build()?;
- let mut gba = GameBoyAdvance::new(
- bios_bin.clone(),
- gamepak,
- video.clone(),
- audio.clone(),
- );
+ let mut gba = GameBoyAdvance::new(bios_bin.clone(), gamepak, audio.clone());
if skip_bios {
gba.skip_bios();
@@ -331,12 +326,7 @@ fn main() -> Result<(), Box> {
let bios_bin = read_bin_file(bios_path).unwrap();
// create a new emulator - TODO, export to a function
- gba = GameBoyAdvance::new(
- bios_bin.into_boxed_slice(),
- gamepak,
- video.clone(),
- audio.clone(),
- );
+ gba = GameBoyAdvance::new(bios_bin.into_boxed_slice(), gamepak, audio.clone());
gba.skip_bios();
}
_ => {}
@@ -344,10 +334,11 @@ fn main() -> Result<(), Box> {
}
gba.frame();
+ renderer.render(gba.get_frame_buffer());
if let Some(fps) = fps_counter.tick() {
let title = format!("{} ({} fps)", rom_name, fps);
- video.borrow_mut().set_window_title(&title);
+ renderer.set_window_title(&title);
}
if frame_limiter {
diff --git a/platform/rustboyadvance-sdl2/src/video.rs b/platform/rustboyadvance-sdl2/src/video.rs
index 91370bd..45ca50f 100644
--- a/platform/rustboyadvance-sdl2/src/video.rs
+++ b/platform/rustboyadvance-sdl2/src/video.rs
@@ -4,25 +4,37 @@ use sdl2::render::{Texture, TextureCreator, WindowCanvas};
use sdl2::video::WindowContext;
use rustboyadvance_core::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH};
-use rustboyadvance_core::VideoInterface;
pub const SCREEN_WIDTH: u32 = DISPLAY_WIDTH as u32;
pub const SCREEN_HEIGHT: u32 = DISPLAY_HEIGHT as u32;
-pub struct Sdl2Video<'a> {
+pub struct Renderer<'a> {
_tc: TextureCreator, // only kept alive because of the texture
texture: Texture<'a>, // TODO - what happens if _tc is destroyed first ?
canvas: WindowCanvas,
}
-impl<'a> Sdl2Video<'a> {
+impl<'a> Renderer<'a> {
+ pub fn from_canvas(canvas: WindowCanvas) -> Renderer<'a> {
+ let mut tc = canvas.texture_creator();
+ let texture = unsafe {
+ let tc_ptr = &mut tc as *mut TextureCreator;
+ (*tc_ptr)
+ .create_texture_streaming(PixelFormatEnum::BGRA32, SCREEN_WIDTH, SCREEN_HEIGHT)
+ .unwrap()
+ };
+ Renderer {
+ _tc: tc,
+ texture,
+ canvas,
+ }
+ }
+
pub fn set_window_title(&mut self, title: &str) {
self.canvas.window_mut().set_title(&title).unwrap();
}
-}
-impl<'a> VideoInterface for Sdl2Video<'a> {
- fn render(&mut self, buffer: &[u32]) {
+ pub fn render(&mut self, buffer: &[u32]) {
self.texture
.update(
None,
@@ -42,18 +54,3 @@ impl<'a> VideoInterface for Sdl2Video<'a> {
self.canvas.present();
}
}
-
-pub fn create_video_interface<'a>(canvas: WindowCanvas) -> Sdl2Video<'a> {
- let mut tc = canvas.texture_creator();
- let texture = unsafe {
- let tc_ptr = &mut tc as *mut TextureCreator;
- (*tc_ptr)
- .create_texture_streaming(PixelFormatEnum::BGRA32, SCREEN_WIDTH, SCREEN_HEIGHT)
- .unwrap()
- };
- Sdl2Video {
- _tc: tc,
- texture: texture,
- canvas: canvas,
- }
-}
diff --git a/platform/rustboyadvance-wasm/src/emulator.rs b/platform/rustboyadvance-wasm/src/emulator.rs
index 48ba0aa..70f3508 100644
--- a/platform/rustboyadvance-wasm/src/emulator.rs
+++ b/platform/rustboyadvance-wasm/src/emulator.rs
@@ -19,10 +19,21 @@ use bit::BitIndex;
pub struct Emulator {
gba: GameBoyAdvance,
interface: Rc>,
+ frame: Option>,
+}
+
+fn translate_frame_to_u8(input_fb: &[u32], out_fb: &mut [u8]) {
+ // TODO optimize
+ for i in 0..input_fb.len() {
+ let color = input_fb[i];
+ out_fb[4 * i + 0] = ((color >> 16) & 0xff) as u8;
+ out_fb[4 * i + 1] = ((color >> 8) & 0xff) as u8;
+ out_fb[4 * i + 2] = (color & 0xff) as u8;
+ out_fb[4 * i + 3] = 255;
+ }
}
struct Interface {
- frame: Vec,
sample_rate: i32,
audio_ctx: AudioContext,
audio_ring_buffer: AudioRingBuffer,
@@ -37,7 +48,6 @@ impl Drop for Interface {
impl Interface {
fn new(audio_ctx: AudioContext) -> Result {
Ok(Interface {
- frame: vec![0; 240 * 160 * 4],
sample_rate: audio_ctx.sample_rate() as i32,
audio_ctx: audio_ctx,
audio_ring_buffer: Default::default(),
@@ -45,19 +55,6 @@ impl Interface {
}
}
-impl VideoInterface for Interface {
- fn render(&mut self, buffer: &[u32]) {
- // TODO optimize
- for i in 0..buffer.len() {
- let color = buffer[i];
- self.frame[4 * i + 0] = ((color >> 16) & 0xff) as u8;
- self.frame[4 * i + 1] = ((color >> 8) & 0xff) as u8;
- self.frame[4 * i + 2] = (color & 0xff) as u8;
- self.frame[4 * i + 3] = 255;
- }
- }
-}
-
fn convert_sample(s: i16) -> f32 {
(s as f32) / 32767_f32
}
@@ -88,15 +85,13 @@ impl Emulator {
.build()
.unwrap();
- let gba = GameBoyAdvance::new(
- bios.to_vec().into_boxed_slice(),
- gamepak,
- interface.clone(),
- interface.clone(),
- interface.clone(),
- );
+ let gba = GameBoyAdvance::new(bios.to_vec().into_boxed_slice(), gamepak, interface.clone());
- Ok(Emulator { gba, interface })
+ Ok(Emulator {
+ gba,
+ interface,
+ frame: Some(vec![0; 240 * 160 * 4].into_boxed_slice()),
+ })
}
pub fn skip_bios(&mut self) {
@@ -105,13 +100,11 @@ impl Emulator {
pub fn run_frame(&mut self, ctx: &CanvasRenderingContext2d) -> Result<(), JsValue> {
self.gba.frame();
- let mut frame_buffer = &mut self.interface.borrow_mut().frame;
- let data = web_sys::ImageData::new_with_u8_clamped_array_and_sh(
- Clamped(&mut frame_buffer),
- 240,
- 160,
- )
- .unwrap();
+ let mut frame = self.frame.take().unwrap();
+ translate_frame_to_u8(self.gba.get_frame_buffer(), &mut frame);
+ let data =
+ web_sys::ImageData::new_with_u8_clamped_array_and_sh(Clamped(&mut frame), 240, 160)?;
+ self.frame.replace(frame);
ctx.put_image_data(&data, 0.0, 0.0)
}
@@ -134,14 +127,14 @@ impl Emulator {
pub fn key_down(&mut self, event_key: &str) {
debug!("Key down: {}", event_key);
if let Some(key) = Emulator::map_key(event_key) {
- self.gba.get_key_state().set_bit(key as usize, false);
+ self.gba.get_key_state_mut().set_bit(key as usize, false);
}
}
pub fn key_up(&mut self, event_key: &str) {
debug!("Key up: {}", event_key);
if let Some(key) = Emulator::map_key(event_key) {
- self.gba.get_key_state().set_bit(key as usize, true);
+ self.gba.get_key_state_mut().set_bit(key as usize, true);
}
}