/*extern crate sdl2; use sdl2::pixels::PixelFormatEnum; use sdl2::rect::Rect; use sdl2::event::Event; use sdl2::keyboard::Keycode; pub fn main() -> Result<(), String> { let sdl_context = sdl2::init()?; let video_subsystem = sdl_context.video()?; let window = video_subsystem.window("rust-sdl2 demo: Video", 800, 600) .position_centered() .opengl() .build() .map_err(|e| e.to_string())?; let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?; let texture_creator = canvas.texture_creator(); let mut texture = texture_creator.create_texture_streaming(PixelFormatEnum::RGB24, 256, 256) .map_err(|e| e.to_string())?; // Create a red-green gradient texture.with_lock(None, |buffer: &mut [u8], pitch: usize| { for y in 0..256 { for x in 0..256 { let offset = y*pitch + x*3; buffer[offset] = x as u8; buffer[offset + 1] = y as u8; buffer[offset + 2] = 0; } } })?; canvas.clear(); canvas.copy(&texture, None, Some(Rect::new(100, 100, 256, 256)))?; canvas.copy_ex(&texture, None, Some(Rect::new(450, 100, 256, 256)), 30.0, None, false, false)?; canvas.present(); let mut event_pump = sdl_context.event_pump()?; 'running: loop { for event in event_pump.poll_iter() { match event { Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { break 'running }, _ => {} } } // The rest of the game loop goes here... } Ok(()) } */ extern crate rustro; extern crate sdl2; use rustro::retro; use rustro::retro::ffi::GameGeometry; use rustro::retro::ffi::SystemAvInfo; use std::ffi::CStr; use std::path::{PathBuf, Path}; use std::time::Duration; use structopt::StructOpt; use sdl2::render::{WindowCanvas, Texture, TextureCreator}; use sdl2::rect::Rect; use sdl2::event::Event; use sdl2::keyboard::Keycode; use sdl2::video::WindowContext; use std::io::Write; struct MyEmulator { retro: retro::wrapper::LibretroWrapper, av_info: SystemAvInfo, pixel_format: sdl2::pixels::PixelFormatEnum, texture: Option, } impl MyEmulator { pub fn with_core(core: impl AsRef) -> Self { let lib = libloading::Library::new(core.as_ref()).unwrap(); let raw_retro = retro::loading::LibretroApi::from_library(lib).unwrap(); let retro = retro::wrapper::LibretroWrapper::from(raw_retro); println!("api version: {}", retro.as_ref().api_version()); println!("name: {}", unsafe { CStr::from_ptr(retro.as_ref().get_system_info().library_name) }.to_string_lossy()); let av_info = retro.as_ref().get_system_av_info(); let pixel_format = sdl2::pixels::PixelFormatEnum::ABGR1555; let mut result = MyEmulator { retro, av_info, pixel_format, texture: None }; retro::wrapper::register_handler(&mut result); result.retro.as_ref().init(); result } pub fn run(&self) { self.retro.as_ref().run(); } pub fn base_dimensions(&self) -> (u32, u32) { (self.av_info.geometry.base_width, self.av_info.geometry.base_height) } pub fn load_game(&self, rom: impl AsRef) { self.retro.as_ref().load_game(Some(rom.as_ref()), None, None); } } impl retro::convert::Handler for MyEmulator { fn video_refresh(&mut self, data: &[u8], width: u32, height: u32, pitch: u32) { //println!("video_refresh {}x{}", width, height); //let rect = Rect::new(0, 0, width, height); println!("{:?}", self.texture.is_some()); if let Some(ref mut tex) = self.texture { tex.update(None, data, pitch as usize).unwrap(); } } fn set_pixel_format(&mut self, pix_fmt: retro::ffi::PixelFormat) -> bool { self.pixel_format = match pix_fmt { retro::ffi::PixelFormat::ARGB1555 => sdl2::pixels::PixelFormatEnum::RGB555, retro::ffi::PixelFormat::ARGB8888 => sdl2::pixels::PixelFormatEnum::ARGB8888, retro::ffi::PixelFormat::RGB565 => sdl2::pixels::PixelFormatEnum::RGB565, }; true } } pub fn main() -> failure::Fallible<()> { let opt: Opt = Opt::from_args(); let mut emu = MyEmulator::with_core(&opt.core); emu.load_game(&opt.rom); let sdl_context = sdl2::init().map_err(failure::err_msg)?; let video_subsystem = sdl_context.video().map_err(failure::err_msg)?; let (width, height) = emu.base_dimensions(); let window = video_subsystem.window("rust libretro", width, height) .position_centered() .opengl() .build()?; let mut canvas = window.into_canvas().build()?; let texture_creator = canvas.texture_creator(); emu.texture = texture_creator.create_texture_streaming(emu.pixel_format, width, height).ok(); println!("{:?}", emu.texture.is_some()); let mut event_pump = sdl_context.event_pump().map_err(failure::err_msg)?; 'running: loop { for event in event_pump.poll_iter() { match event { Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { break 'running }, _ => {} } } // The rest of the game loop goes here... emu.run(); canvas.clear(); canvas.copy(emu.texture.as_ref().unwrap(), None, Some(Rect::new(0, 0, width, height))).map_err(failure::err_msg)?; canvas.present(); ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60)); } Ok(()) } #[derive(StructOpt)] struct Opt { /// Core module to use. #[structopt(short, long, parse(from_os_str))] core: PathBuf, /// Rom to load using the core. #[structopt(short, long, parse(from_os_str))] rom: PathBuf, }