extern crate crossbeam_channel; extern crate ferretro_components; extern crate ffmpeg_next as ffmpeg; extern crate sdl2; use std::path::PathBuf; use structopt::StructOpt; use ferretro_components::prelude::*; use ferretro_components::provided::{ ffmpeg::FfmpegComponent, sdl2::*, stdlib::*, }; use ferretro_components::base::ControlFlow; #[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, /// Save state to load at startup. #[structopt(long, parse(from_os_str))] state: Option, /// System directory, often containing BIOS files #[structopt(short, long, parse(from_os_str))] system: Option, /// Recorded video to write. #[structopt(short, long, parse(from_os_str))] video: Option, /// Disable OpenGL context creation. #[structopt(long)] no_opengl: bool, /// Trace all API calls. #[structopt(long)] trace_api: bool, } pub fn main() -> Result<(), Box> { let opt: Opt = Opt::from_args(); let mut emu = RetroComponentBase::new(&opt.core); let mut sdl_context = sdl2::init()?; let mut stderr_log = StderrLogComponent::default(); stderr_log.prefix = "{log} ".to_string(); emu.register_component(stderr_log)?; if opt.trace_api { emu.register_component(StderrCallTraceComponent { prefix: "{trace} ".to_string() })?; } // must register before opengl so it can have priority in queries about what N64 plugin to use // (only supports software-rendered 2D frames currently) if let Some(video) = opt.video { ffmpeg::log::set_level(ffmpeg::log::Level::Info); ffmpeg::init()?; let ffmpeg_comp = FfmpegComponent::new(emu.libretro_core(), video); emu.register_component(ffmpeg_comp)?; } let sdl2_ogl_res = if opt.no_opengl { Err("OpenGL disabled".into()) } else { SimpleSdl2OpenglComponent::new(&mut sdl_context, emu.libretro_core()) }; if let Ok(sdl2_ogl) = sdl2_ogl_res { emu.register_component(sdl2_ogl)?; } else { match SimpleSdl2CanvasComponent::new(&mut sdl_context, emu.libretro_core()) { Ok(sdl2_canvas) => emu.register_component(sdl2_canvas)?, Err(e) => eprintln!("Couldn't initialize SDL2 video component: {:?}", e), } } emu.register_component(SimpleSdl2AudioComponent::new(&mut sdl_context)?)?; emu.register_component(SimpleSdl2GamepadComponent::new(&mut sdl_context))?; emu.register_component(SleepFramerateLimitComponent::default())?; emu.register_component(PathBufComponent { sys_path: opt.system.clone(), libretro_path: Some(opt.core.to_path_buf()), core_assets_path: None, save_path: Some(std::env::temp_dir()), })?; emu.init()?; emu.load_game(&opt.rom)?; if let Some(state) = opt.state { emu.unserialize_path(state)?; } let mut frame = 0; while let ControlFlow::Continue = emu.run() { frame += 1; } eprintln!("Ran for {} frames.", frame); Ok(()) }