Cleanup sdl2 desktop app

Former-commit-id: abc58c25406c6a16efa8acf771ebe2bc95343236
Former-commit-id: 90fbe62bbdd7758fe582280d499a4d23440c7fb5
This commit is contained in:
Michel Heily 2022-09-15 00:34:41 +03:00
parent e51936b880
commit a750cb8e16
3 changed files with 54 additions and 101 deletions

View file

@ -19,7 +19,7 @@ spin_sleep = "0.3.7"
[target.'cfg(windows)'.build-dependencies] [target.'cfg(windows)'.build-dependencies]
winres = "0.1" winres = "0.1"
[features] # [features]
default = ["gdb"] # default = ["gdb"]
debugger = ["rustboyadvance-core/debugger"] # debugger = ["rustboyadvance-core/debugger"]
gdb = ["rustboyadvance-core/gdb"] # gdb = ["rustboyadvance-core/gdb"]

View file

@ -1,15 +1,8 @@
use sdl2::controller::Button; use sdl2::controller::Button;
use sdl2::event::{Event, WindowEvent}; use sdl2::event::Event;
use sdl2::image::{InitFlag, LoadSurface, LoadTexture};
use sdl2::keyboard::Scancode; use sdl2::keyboard::Scancode;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::WindowCanvas;
use sdl2::surface::Surface;
use sdl2::{self}; use sdl2::{self};
use sdl2::EventPump;
use bytesize; use bytesize;
use spin_sleep; use spin_sleep;
use structopt::StructOpt; use structopt::StructOpt;
@ -17,7 +10,6 @@ use structopt::StructOpt;
use std::fs; use std::fs;
use std::io::Cursor; use std::io::Cursor;
use std::path::Path; use std::path::Path;
use std::process;
use std::time; use std::time;
#[macro_use] #[macro_use]
@ -30,8 +22,6 @@ mod input;
mod options; mod options;
mod video; mod video;
use video::{SCREEN_HEIGHT, SCREEN_WIDTH};
use rustboyadvance_core::prelude::*; use rustboyadvance_core::prelude::*;
use rustboyadvance_utils::FpsCounter; use rustboyadvance_utils::FpsCounter;
@ -39,53 +29,6 @@ use rustboyadvance_utils::FpsCounter;
const LOG_DIR: &str = ".logs"; const LOG_DIR: &str = ".logs";
const DEFAULT_GDB_SERVER_ADDR: &'static str = "localhost:1337"; const DEFAULT_GDB_SERVER_ADDR: &'static str = "localhost:1337";
const CANVAS_WIDTH: u32 = SCREEN_WIDTH;
const CANVAS_HEIGHT: u32 = SCREEN_HEIGHT;
/// Waits for the user to drag a rom file to window
fn wait_for_rom(canvas: &mut WindowCanvas, event_pump: &mut EventPump) -> Result<String, String> {
let texture_creator = canvas.texture_creator();
let icon_texture = texture_creator
.load_texture("assets/icon_cropped_small.png")
.expect("failed to load icon");
let background = Color::RGB(0xDD, 0xDD, 0xDD);
let mut redraw = || -> Result<(), String> {
canvas.set_draw_color(background);
canvas.clear();
canvas.copy(
&icon_texture,
None,
Some(Rect::from_center(
((CANVAS_WIDTH / 2) as i32, (CANVAS_HEIGHT / 2) as i32),
160,
100,
)),
)?;
canvas.present();
Ok(())
};
redraw()?;
loop {
for event in event_pump.wait_iter() {
match event {
Event::DropFile { filename, .. } => {
return Ok(filename);
}
Event::Quit { .. } => process::exit(0),
Event::Window { win_event, .. } => match win_event {
WindowEvent::SizeChanged(..) | WindowEvent::Restored => redraw()?,
_ => {}
},
_ => {}
}
}
}
}
fn ask_download_bios() { fn ask_download_bios() {
const OPEN_SOURCE_BIOS_URL: &'static str = const OPEN_SOURCE_BIOS_URL: &'static str =
"https://github.com/Nebuleon/ReGBA/raw/master/bios/gba_bios.bin"; "https://github.com/Nebuleon/ReGBA/raw/master/bios/gba_bios.bin";
@ -119,23 +62,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
info!("Initializing SDL2 context"); info!("Initializing SDL2 context");
let sdl_context = sdl2::init().expect("failed to initialize sdl2"); let sdl_context = sdl2::init().expect("failed to initialize sdl2");
let mut event_pump = sdl_context.event_pump()?;
let video_subsystem = sdl_context.video()?;
let _image_context = sdl2::image::init(InitFlag::PNG | InitFlag::JPG)?;
let mut window = video_subsystem
.window("RustBoyAdvance", SCREEN_WIDTH * 3, SCREEN_HEIGHT * 3)
.opengl()
.position_centered()
.resizable()
.build()?;
let window_icon = Surface::from_file("assets/icon.png")?;
window.set_icon(window_icon);
let mut canvas = window.into_canvas().accelerated().build()?;
canvas.set_logical_size(CANVAS_WIDTH, CANVAS_HEIGHT)?;
let controller_subsystem = sdl_context.game_controller()?; let controller_subsystem = sdl_context.game_controller()?;
let controller_mappings = let controller_mappings =
include_str!("../../../external/SDL_GameControllerDB/gamecontrollerdb.txt"); include_str!("../../../external/SDL_GameControllerDB/gamecontrollerdb.txt");
@ -157,17 +83,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
}; };
let mut renderer = video::Renderer::from_canvas(canvas); let mut renderer = video::init(&sdl_context)?;
let (audio_interface, mut _sdl_audio_device) = audio::create_audio_player(&sdl_context)?; let (audio_interface, mut _sdl_audio_device) = audio::create_audio_player(&sdl_context)?;
let mut rom_name = opts.rom_name(); let mut rom_name = opts.rom_name();
let bios_bin = load_bios(&opts.bios); let bios_bin = load_bios(&opts.bios);
let mut gba = GameBoyAdvance::new( let mut gba = Box::new(GameBoyAdvance::new(
bios_bin.clone(), bios_bin.clone(),
opts.cartridge_from_opts()?, opts.cartridge_from_opts()?,
audio_interface, audio_interface,
); ));
if opts.skip_bios { if opts.skip_bios {
gba.skip_bios(); gba.skip_bios();
@ -179,7 +105,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut vsync = true; let mut vsync = true;
let mut fps_counter = FpsCounter::default(); let mut fps_counter = FpsCounter::default();
let frame_time = time::Duration::new(0, 1_000_000_000u32 / 60); const FRAME_TIME: time::Duration = time::Duration::new(0, 1_000_000_000u32 / 60);
let mut event_pump = sdl_context.event_pump()?;
'running: loop { 'running: loop {
let start_time = time::Instant::now(); let start_time = time::Instant::now();
@ -279,7 +206,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
if vsync { if vsync {
let time_passed = start_time.elapsed(); let time_passed = start_time.elapsed();
let delay = frame_time.checked_sub(time_passed); let delay = FRAME_TIME.checked_sub(time_passed);
match delay { match delay {
None => {} None => {}
Some(delay) => { Some(delay) => {

View file

@ -1,7 +1,10 @@
use sdl2::image::{InitFlag, LoadSurface, Sdl2ImageContext};
use sdl2::pixels::{Color, PixelFormatEnum}; use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::Rect; use sdl2::rect::Rect;
use sdl2::render::{Texture, TextureCreator, WindowCanvas}; use sdl2::render::{Texture, TextureCreator, WindowCanvas};
use sdl2::surface::Surface;
use sdl2::video::WindowContext; use sdl2::video::WindowContext;
use sdl2::{Sdl, VideoSubsystem};
use rustboyadvance_core::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH}; use rustboyadvance_core::gpu::{DISPLAY_HEIGHT, DISPLAY_WIDTH};
@ -9,27 +12,50 @@ pub const SCREEN_WIDTH: u32 = DISPLAY_WIDTH as u32;
pub const SCREEN_HEIGHT: u32 = DISPLAY_HEIGHT as u32; pub const SCREEN_HEIGHT: u32 = DISPLAY_HEIGHT as u32;
pub struct Renderer<'a> { pub struct Renderer<'a> {
_tc: TextureCreator<WindowContext>, // only kept alive because of the texture texture: Texture<'a>, // TODO - what happens if _tc is destroyed first ?
texture: Texture<'a>, // TODO - what happens if _tc is destroyed first ?
canvas: WindowCanvas, canvas: WindowCanvas,
#[allow(unused)]
tc: TextureCreator<WindowContext>, // only kept alive because of the texture
#[allow(unused)]
video_subsystem: VideoSubsystem, // holds a reference to the video subsystem
#[allow(unused)]
image_context: Sdl2ImageContext,
}
pub fn init<'a>(sdl_context: &'a Sdl) -> Result<Renderer<'a>, Box<dyn std::error::Error>> {
let video_subsystem = sdl_context.video()?;
let image_context = sdl2::image::init(InitFlag::PNG | InitFlag::JPG)?;
let mut window = video_subsystem
.window("RustBoyAdvance", SCREEN_WIDTH * 3, SCREEN_HEIGHT * 3)
.opengl()
.position_centered()
.resizable()
.build()?;
let window_icon = Surface::from_file("assets/icon.png")?;
window.set_icon(window_icon);
let mut canvas = window.into_canvas().accelerated().build()?;
canvas.set_logical_size(SCREEN_WIDTH, SCREEN_HEIGHT)?;
let mut tc = canvas.texture_creator();
let texture = unsafe {
let tc_ptr = &mut tc as *mut TextureCreator<WindowContext>;
(*tc_ptr)
.create_texture_streaming(PixelFormatEnum::BGRA32, SCREEN_WIDTH, SCREEN_HEIGHT)
.unwrap()
};
Ok(Renderer {
tc,
texture,
canvas,
video_subsystem,
image_context,
})
} }
impl<'a> Renderer<'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<WindowContext>;
(*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) { pub fn set_window_title(&mut self, title: &str) {
self.canvas.window_mut().set_title(&title).unwrap(); self.canvas.window_mut().set_title(&title).unwrap();
} }