Add minifb based binary, currently it has better performance than the SDL2.

SDL2 rendering is really bottlenecking currently..


Former-commit-id: 8e04b799f248209a138990b2389e740b0d1d9f0f
This commit is contained in:
Michel Heily 2019-12-20 16:31:26 +02:00
parent 385016f24a
commit 3c7a734270
3 changed files with 192 additions and 0 deletions

View file

@ -29,6 +29,11 @@ cpal="0.10.0"
name = "rba-sdl2" name = "rba-sdl2"
path = "src/plat/sdl2/main.rs" path = "src/plat/sdl2/main.rs"
[[bin]]
name = "rba-minifb"
path = "src/plat/minifb/main.rs"
[profile.dev] [profile.dev]
opt-level = 0 opt-level = 0
debug = true debug = true

32
src/plat/minifb/cli.yml Normal file
View file

@ -0,0 +1,32 @@
name: rba-sdl2
author: Michel Heily <michelheily@gmail.com>
about: RustBoyAdvance SDL2 port
args:
- bios:
help: Sets the bios file to use
short: b
required: false
default_value: gba_bios.bin
- game_rom:
long: game-rom
takes_value: true
help: Sets the game-rom file to use
required: true
index: 1
- skip_bios:
long: skip-bios
help: Skip running bios and start from the ROM instead
- no_framerate_limit:
long: no-framerate-limit
help: Run without frame limiter
- debug:
long: debug
help: Start with the debugger attached
- script_file:
long: script-file
short: f
takes_value: true
help: Text file with debugger commands to run
required: false
requires:
debug

155
src/plat/minifb/main.rs Normal file
View file

@ -0,0 +1,155 @@
extern crate sdl2;
use std::cell::RefCell;
use std::rc::Rc;
use std::path::Path;
use std::time;
#[macro_use]
extern crate clap;
#[macro_use]
extern crate rustboyadvance_ng;
use rustboyadvance_ng::prelude::*;
use rustboyadvance_ng::util::FpsCounter;
use rustboyadvance_ng::core::keypad;
extern crate bit;
use bit::BitIndex;
extern crate minifb;
use minifb::{Key, Window, WindowOptions};
struct MiniFb {
window: minifb::Window,
}
impl VideoInterface for MiniFb {
fn render(&mut self, buffer: &[u32]) {
self.window.update_with_buffer(buffer).unwrap();
}
}
impl InputInterface for MiniFb {
fn poll(&mut self) -> u16 {
let mut keyinput = keypad::KEYINPUT_ALL_RELEASED;
keyinput.set_bit(keypad::Keys::Up as usize, !self.window.is_key_down(Key::Up));
keyinput.set_bit(
keypad::Keys::Down as usize,
!self.window.is_key_down(Key::Down),
);
keyinput.set_bit(
keypad::Keys::Left as usize,
!self.window.is_key_down(Key::Left),
);
keyinput.set_bit(
keypad::Keys::Right as usize,
!self.window.is_key_down(Key::Right),
);
keyinput.set_bit(
keypad::Keys::ButtonB as usize,
!self.window.is_key_down(Key::Z),
);
keyinput.set_bit(
keypad::Keys::ButtonA as usize,
!self.window.is_key_down(Key::X),
);
keyinput.set_bit(
keypad::Keys::Start as usize,
!self.window.is_key_down(Key::Enter),
);
keyinput.set_bit(
keypad::Keys::Select as usize,
!self.window.is_key_down(Key::Space),
);
keyinput.set_bit(
keypad::Keys::ButtonL as usize,
!self.window.is_key_down(Key::A),
);
keyinput.set_bit(
keypad::Keys::ButtonR as usize,
!self.window.is_key_down(Key::S),
);
keyinput
}
}
impl AudioInterface for MiniFb {
fn get_sample_rate(&self) -> u32 {
0
}
}
fn main() {
let yaml = load_yaml!("cli.yml");
let matches = clap::App::from_yaml(yaml).get_matches();
let skip_bios = matches.occurrences_of("skip_bios") != 0;
let no_framerate_limit = matches.occurrences_of("no_framerate_limit") != 0;
let debug = matches.occurrences_of("debug") != 0;
let bios_path = Path::new(matches.value_of("bios").unwrap_or_default());
let rom_path = Path::new(matches.value_of("game_rom").unwrap());
let rom_name = rom_path.file_name().unwrap().to_str().unwrap();
let bios_bin = read_bin_file(bios_path).unwrap();
let cart = Cartridge::from_path(rom_path).unwrap();
let mut cpu = arm7tdmi::Core::new();
if skip_bios {
cpu.skip_bios();
}
let cpu = cpu;
let sdl_context = sdl2::init().unwrap();
let minifb = Rc::new(RefCell::new(MiniFb {
window: Window::new(
"rustboyadvance-ng",
240,
160,
WindowOptions {
borderless: true,
scale: minifb::Scale::X4,
..Default::default()
},
)
.unwrap(),
}));
let mut fps_counter = FpsCounter::default();
let mut gba: GameBoyAdvance<MiniFb, MiniFb, MiniFb> =
GameBoyAdvance::new(cpu, bios_bin, cart, minifb.clone(), minifb.clone(), minifb.clone());
if debug {
gba.cpu.set_verbose(true);
let mut debugger = Debugger::new(gba);
println!("starting debugger...");
debugger.repl(matches.value_of("script_file")).unwrap();
println!("ending debugger...");
} else {
let frame_time = time::Duration::new(0, 1_000_000_000u32 / 60);
loop {
let start_time = time::Instant::now();
gba.frame();
if let Some(fps) = fps_counter.tick() {
let title = format!("{} ({} fps)", rom_name, fps);
// video.borrow_mut().set_window_title(&title);
minifb.borrow_mut().window.set_title(&title);
}
if !no_framerate_limit {
let time_passed = start_time.elapsed();
let delay = frame_time.checked_sub(time_passed);
match delay {
None => {}
Some(delay) => {
::std::thread::sleep(delay);
}
};
}
}
}
}