Cleanup sdl2 desktop app
Former-commit-id: abc58c25406c6a16efa8acf771ebe2bc95343236 Former-commit-id: 90fbe62bbdd7758fe582280d499a4d23440c7fb5
This commit is contained in:
parent
e51936b880
commit
a750cb8e16
|
@ -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"]
|
|
@ -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) => {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue