Add sdl2 backend
Currently has bad performance Former-commit-id: 384ef6b5cd7b1e1baeb6adfbc0b299b0d07d7a5d
This commit is contained in:
parent
acd0e4f338
commit
3f6a52cae6
|
@ -6,10 +6,9 @@ extern crate minifb;
|
||||||
|
|
||||||
use minifb::{Key, Window, WindowOptions};
|
use minifb::{Key, Window, WindowOptions};
|
||||||
|
|
||||||
use super::backend::EmulatorBackend;
|
use super::EmulatorBackend;
|
||||||
use crate::core::gpu::Gpu;
|
use crate::core::gpu::Gpu;
|
||||||
|
use crate::core::keypad;
|
||||||
use super::core::keypad;
|
|
||||||
|
|
||||||
pub struct MinifbBackend {
|
pub struct MinifbBackend {
|
||||||
window: Window,
|
window: Window,
|
||||||
|
@ -41,18 +40,17 @@ impl MinifbBackend {
|
||||||
|
|
||||||
impl EmulatorBackend for MinifbBackend {
|
impl EmulatorBackend for MinifbBackend {
|
||||||
fn render(&mut self, buffer: Vec<u32>) {
|
fn render(&mut self, buffer: Vec<u32>) {
|
||||||
let now = time::Instant::now();
|
self.frames_rendered += 1;
|
||||||
if now - self.first_frame_start >= time::Duration::from_secs(1) {
|
if self.first_frame_start.elapsed() >= time::Duration::from_secs(1) {
|
||||||
let title = format!("rustboyadvance-ng ({} fps)", self.frames_rendered);
|
let title = format!("rustboyadvance-ng ({} fps)", self.frames_rendered);
|
||||||
self.window.set_title(&title);
|
self.window.set_title(&title);
|
||||||
self.first_frame_start = now;
|
self.first_frame_start = time::Instant::now();
|
||||||
self.frames_rendered = 0;
|
self.frames_rendered = 0;
|
||||||
}
|
}
|
||||||
self.window.update_with_buffer(&buffer).unwrap();
|
self.window.update_with_buffer(&buffer).unwrap();
|
||||||
self.frames_rendered += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_key_state(&self) -> u16 {
|
fn get_key_state(&mut self) -> u16 {
|
||||||
let mut keyinput = keypad::KEYINPUT_ALL_RELEASED;
|
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::Up as usize, !self.window.is_key_down(Key::Up));
|
||||||
keyinput.set_bit(
|
keyinput.set_bit(
|
|
@ -1,11 +1,15 @@
|
||||||
use super::core::keypad;
|
use super::core::keypad;
|
||||||
|
|
||||||
pub use super::minifb_backend::MinifbBackend;
|
mod minifb_backend;
|
||||||
|
pub use minifb_backend::MinifbBackend;
|
||||||
|
|
||||||
|
mod sdl2_backend;
|
||||||
|
pub use sdl2_backend::Sdl2Backend;
|
||||||
|
|
||||||
pub trait EmulatorBackend {
|
pub trait EmulatorBackend {
|
||||||
fn render(&mut self, buffer: Vec<u32>);
|
fn render(&mut self, buffer: Vec<u32>);
|
||||||
|
|
||||||
fn get_key_state(&self) -> u16;
|
fn get_key_state(&mut self) -> u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DummyBackend;
|
pub struct DummyBackend;
|
||||||
|
@ -17,7 +21,7 @@ impl DummyBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmulatorBackend for DummyBackend {
|
impl EmulatorBackend for DummyBackend {
|
||||||
fn get_key_state(&self) -> u16 {
|
fn get_key_state(&mut self) -> u16 {
|
||||||
keypad::KEYINPUT_ALL_RELEASED
|
keypad::KEYINPUT_ALL_RELEASED
|
||||||
}
|
}
|
||||||
fn render(&mut self, _buffer: Vec<u32>) {}
|
fn render(&mut self, _buffer: Vec<u32>) {}
|
132
src/backend/sdl2_backend.rs
Normal file
132
src/backend/sdl2_backend.rs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
use std::time;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
use crate::bit::BitIndex;
|
||||||
|
|
||||||
|
extern crate sdl2;
|
||||||
|
use sdl2::event::Event;
|
||||||
|
use sdl2::keyboard::Keycode;
|
||||||
|
use sdl2::pixels::{Color, PixelFormat, PixelFormatEnum};
|
||||||
|
use sdl2::rect::{Point, Rect};
|
||||||
|
use sdl2::render::{Texture, TextureCreator, WindowCanvas};
|
||||||
|
use sdl2::video::{Window, WindowContext};
|
||||||
|
|
||||||
|
use super::EmulatorBackend;
|
||||||
|
use crate::core::gpu::Gpu;
|
||||||
|
use crate::core::keypad;
|
||||||
|
|
||||||
|
pub struct Sdl2Backend {
|
||||||
|
event_pump: sdl2::EventPump,
|
||||||
|
tc: TextureCreator<WindowContext>,
|
||||||
|
canvas: WindowCanvas,
|
||||||
|
frames_rendered: u32,
|
||||||
|
fps_timer: time::Instant,
|
||||||
|
keyinput: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
const SCREEN_WIDTH: u32 = Gpu::DISPLAY_WIDTH as u32;
|
||||||
|
const SCREEN_HEIGHT: u32 = Gpu::DISPLAY_HEIGHT as u32;
|
||||||
|
|
||||||
|
impl Sdl2Backend {
|
||||||
|
pub fn new() -> Sdl2Backend {
|
||||||
|
let sdl_context = sdl2::init().unwrap();
|
||||||
|
let video_subsystem = sdl_context.video().unwrap();
|
||||||
|
|
||||||
|
let window = video_subsystem
|
||||||
|
.window("RustBoyAdvance", SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||||
|
.opengl()
|
||||||
|
.position_centered()
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut canvas = window.into_canvas().accelerated().build().unwrap();
|
||||||
|
canvas.set_draw_color(Color::RGB(0, 0, 0));
|
||||||
|
canvas.clear();
|
||||||
|
let tc = canvas.texture_creator();
|
||||||
|
let event_pump = sdl_context.event_pump().unwrap();
|
||||||
|
|
||||||
|
Sdl2Backend {
|
||||||
|
canvas: canvas,
|
||||||
|
event_pump: event_pump,
|
||||||
|
tc: tc,
|
||||||
|
frames_rendered: 0,
|
||||||
|
fps_timer: time::Instant::now(),
|
||||||
|
keyinput: keypad::KEYINPUT_ALL_RELEASED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EmulatorBackend for Sdl2Backend {
|
||||||
|
fn render(&mut self, buffer: Vec<u32>) {
|
||||||
|
let mut texture = self
|
||||||
|
.tc
|
||||||
|
.create_texture_target(PixelFormatEnum::RGB24, SCREEN_WIDTH, SCREEN_HEIGHT)
|
||||||
|
.unwrap();
|
||||||
|
self.canvas
|
||||||
|
.with_texture_canvas(&mut texture, |texture_canvas| {
|
||||||
|
for y in 0i32..(SCREEN_HEIGHT as i32) {
|
||||||
|
for x in 0i32..(SCREEN_WIDTH as i32) {
|
||||||
|
let c = buffer[index2d!(x, y, SCREEN_WIDTH as i32) as usize];
|
||||||
|
let color = Color::RGB((c >> 16) as u8, (c >> 8) as u8, c as u8);
|
||||||
|
texture_canvas.set_draw_color(color);
|
||||||
|
let _ = texture_canvas.draw_point(Point::from((x, y)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
self.canvas
|
||||||
|
.copy(
|
||||||
|
&texture,
|
||||||
|
None,
|
||||||
|
Some(Rect::new(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
self.canvas.present();
|
||||||
|
|
||||||
|
self.frames_rendered += 1;
|
||||||
|
if self.fps_timer.elapsed() >= time::Duration::from_secs(1) {
|
||||||
|
self.fps_timer = time::Instant::now();
|
||||||
|
let title = format!("rustboyadvance-ng ({} fps)", self.frames_rendered);
|
||||||
|
self.canvas.window_mut().set_title(&title);
|
||||||
|
self.frames_rendered = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_key_state(&mut self) -> u16 {
|
||||||
|
for event in self.event_pump.poll_iter() {
|
||||||
|
match event {
|
||||||
|
Event::KeyDown {
|
||||||
|
keycode: Some(keycode),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if let Some(key) = keycode_to_keypad(keycode) {
|
||||||
|
self.keyinput.set_bit(key as usize, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::KeyUp {
|
||||||
|
keycode: Some(keycode),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if let Some(key) = keycode_to_keypad(keycode) {
|
||||||
|
self.keyinput.set_bit(key as usize, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::Quit { .. } => panic!("quit!"),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.keyinput
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn keycode_to_keypad(keycode: Keycode) -> Option<keypad::Keys> {
|
||||||
|
match keycode {
|
||||||
|
Keycode::Up => Some(keypad::Keys::Up),
|
||||||
|
Keycode::Down => Some(keypad::Keys::Down),
|
||||||
|
Keycode::Left => Some(keypad::Keys::Left),
|
||||||
|
Keycode::Right => Some(keypad::Keys::Right),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ fn run_emulator(matches: &ArgMatches) -> GBAResult<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let backend: Box<EmulatorBackend> = match matches.value_of("backend") {
|
let backend: Box<EmulatorBackend> = match matches.value_of("backend") {
|
||||||
Some("sdl2") => panic!("sdl2 not implemented"),
|
Some("sdl2") => Box::new(Sdl2Backend::new()),
|
||||||
Some("minifb") => Box::new(MinifbBackend::new()),
|
Some("minifb") => Box::new(MinifbBackend::new()),
|
||||||
// None => DummyBackend::new(),
|
// None => DummyBackend::new(),
|
||||||
None => Box::new(DummyBackend::new()),
|
None => Box::new(DummyBackend::new()),
|
||||||
|
|
|
@ -22,4 +22,3 @@ pub mod backend;
|
||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod debugger;
|
pub mod debugger;
|
||||||
pub mod disass;
|
pub mod disass;
|
||||||
pub mod minifb_backend;
|
|
||||||
|
|
Reference in a new issue