ferretro/ferretro_components/examples/multifunction_emulator.rs
lifning ebea5ffd22 video and audio callback API change:
fn video_refresh(&mut self, data: &[u8], width: c_uint, height: c_uint, pitch: c_uint);
    fn video_refresh_dupe(&mut self, width: c_uint, height: c_uint, pitch: c_uint);
    fn video_refresh_hw(&mut self, width: c_uint, height: c_uint);
    fn audio_sample(&mut self, left: i16, right: i16);
    fn audio_sample_batch(&mut self, stereo_pcm: &[i16]) -> usize;

have been replaced with

    fn video_refresh(&mut self, frame: &VideoFrame);
    fn audio_samples(&mut self, stereo_pcm: &[i16]) -> usize;

where VideoFrame is

    pub enum VideoFrame<'a> {
        XRGB1555 { data: &'a [u16], width: c_uint, height: c_uint, pitch_u16: usize },
        RGB565 { data: &'a [u16], width: c_uint, height: c_uint, pitch_u16: usize },
        XRGB8888 { data: &'a [u32], width: c_uint, height: c_uint, pitch_u32: usize },
        Duplicate { width: c_uint, height: c_uint, pitch_u8: usize, },
        HardwareRender { width: c_uint, height: c_uint, },
    }

use `pub fn VideoFrame::data_pitch_as_bytes(&self) -> Option<(&'a [u8], usize)>` for things that need to access the framebuffer data as a byte array rather than a pixel array.
2021-11-01 00:56:23 -07:00

86 lines
2.6 KiB
Rust

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::{PathBufComponent, StderrLogComponent, SleepFramerateLimitComponent},
};
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<PathBuf>,
/// System directory, often containing BIOS files
#[structopt(short, long, parse(from_os_str))]
system: Option<PathBuf>,
/// Recorded video to write.
#[structopt(short, long, parse(from_os_str))]
video: Option<PathBuf>,
}
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
let opt: Opt = Opt::from_args();
let mut emu = RetroComponentBase::new(&opt.core);
let mut sdl_context = sdl2::init()?;
emu.register_component(StderrLogComponent { prefix: "{log} ".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 = SimpleSdl2OpenglComponent::new(&mut sdl_context, emu.libretro_core())?;
emu.register_component(sdl2_ogl)?;
let sdl2_audio = SimpleSdl2AudioComponent::new(&mut sdl_context, emu.libretro_core());
emu.register_component(sdl2_audio)?;
emu.register_component(SimpleSdl2GamepadComponent::new(&mut sdl_context))?;
let sleep_fps = SleepFramerateLimitComponent::new(emu.libretro_core());
emu.register_component(sleep_fps)?;
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(())
}