Skip to content

Commit

Permalink
Expose all retro_* callbacks in RetroCore.
Browse files Browse the repository at this point in the history
  • Loading branch information
InquisitiveCoder committed Dec 9, 2022
1 parent a23aa43 commit 6fc4f96
Show file tree
Hide file tree
Showing 7 changed files with 347 additions and 91 deletions.
8 changes: 4 additions & 4 deletions example/src/cpu.rs
Expand Up @@ -182,14 +182,14 @@ impl Cpu {
// 8xy4 - ADD Vx, Vy
(0x8, _, _, 0x4) => {
let (result, overflow) = self.get(code.x()).overflowing_add(self.get(code.y()));
self.set(code.f(), if overflow { 1 } else { 0 });
self.set(code.f(), u8::from(overflow));
self.set(code.x(), result);
}

// 8xy5 - SUB Vx, Vy
(0x8, _, _, 0x5) => {
let (result, overflow) = self.get(code.x()).overflowing_sub(self.get(code.y()));
self.set(code.f(), if overflow { 1 } else { 0 });
self.set(code.f(), u8::from(overflow));
self.set(code.x(), result)
}

Expand All @@ -202,7 +202,7 @@ impl Cpu {
// 8xy7 - SUBN Vx, Vy
(0x8, _, _, 0x7) => {
let (result, overflow) = self.get(code.y()).overflowing_sub(self.get(code.x()));
self.set(code.f(), if overflow { 1 } else { 0 });
self.set(code.f(), u8::from(overflow));
self.set(code.x(), result);
}

Expand Down Expand Up @@ -242,7 +242,7 @@ impl Cpu {
let vy = self.get(code.y()) as usize;
let collisions = self.display.drw(vx, vy, &sprite_data);

self.set(code.f(), if collisions { 1 } else { 0 });
self.set(code.f(), u8::from(collisions));
}

// Ex9E - SKP Vx
Expand Down
26 changes: 12 additions & 14 deletions example/src/libretro.rs
Expand Up @@ -65,37 +65,35 @@ fn key_to_retro_button(key: keyboard::Key) -> RetroJoypadButton {
}

impl RetroCore for LibretroCore {
type SpecialGameType = ();
type SubsystemMemoryType = ();

fn get_system_info() -> RetroSystemInfo {
RetroSystemInfo::new("chip8.rs", env!("CARGO_PKG_VERSION"))
}

fn load_game(_env: &mut RetroEnvironment, game: RetroGame) -> RetroLoadGameResult<Self> {
const WINDOW_SCALE: u32 = 8;
const WINDOW_WIDTH: u32 = WINDOW_SCALE * display::WIDTH as u32;
const WINDOW_HEIGHT: u32 = WINDOW_SCALE * display::HEIGHT as u32;

match game {
RetroGame::Data { data, .. } => {
let region = RetroRegion::NTSC;
let audio = RetroAudioInfo::new(44100.0);
let video = RetroVideoInfo::new(60.0, WINDOW_WIDTH, WINDOW_HEIGHT).with_pixel_format(RetroPixelFormat::XRGB8888);
let core = LibretroCore {
cpu: cpu::Cpu::new(&data),
audio_buffer: [0; timer::AUDIO_BUFFER_SIZE * 2],
frame_buffer: [0; display::AREA * std::mem::size_of::<i32>()],
};

RetroLoadGameResult::Success {
region,
audio,
video,
core,
}
RetroLoadGameResult::Success(core)
}
_ => RetroLoadGameResult::Failure,
}
}

fn get_system_av_info(&self, env: &mut RetroEnvironment) -> RetroSystemAVInfo {
const WINDOW_SCALE: u16 = 8;
const WINDOW_WIDTH: u16 = WINDOW_SCALE * display::WIDTH as u16;
const WINDOW_HEIGHT: u16 = WINDOW_SCALE * display::HEIGHT as u16;
env.set_pixel_format(RetroPixelFormat::XRGB8888);
RetroSystemAVInfo::default_timings(RetroGameGeometry::fixed(WINDOW_WIDTH, WINDOW_HEIGHT))
}

fn reset(&mut self, _env: &mut RetroEnvironment) {
todo!()
}
Expand Down
2 changes: 1 addition & 1 deletion example/src/memory.rs
Expand Up @@ -18,7 +18,7 @@ impl Memory {
pub fn new(game: &[u8]) -> Memory {
let mut data = [0; MEMORY_SIZE];
data[0x000..0x000 + FONT.len()].copy_from_slice(&FONT);
data[0x200..0x200 + game.len()].copy_from_slice(&game);
data[0x200..0x200 + game.len()].copy_from_slice(game);

Memory { data }
}
Expand Down
3 changes: 2 additions & 1 deletion libretro-rs-sys/build.rs
Expand Up @@ -3,7 +3,7 @@ extern crate bindgen;
use std::env;
use std::path::PathBuf;

const LIBRETRO_HEADER_FILE: &'static str = "include/libretro.h";
const LIBRETRO_HEADER_FILE: &str = "include/libretro.h";

fn main() {
println!("cargo:rerun-if-changed={}", LIBRETRO_HEADER_FILE);
Expand All @@ -13,6 +13,7 @@ fn main() {
.allowlist_type("^retro_.+$")
.allowlist_var("^RETRO_.+$")
.default_enum_style(bindgen::EnumVariation::Rust { non_exhaustive: false })
.derive_default(true)
.layout_tests(true)
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
Expand Down
147 changes: 147 additions & 0 deletions libretro-rs/src/av_info.rs
@@ -0,0 +1,147 @@
use core::ffi::*;
use core::ops::*;
use libretro_rs_sys::*;

/// Rust interface for [retro_system_av_info].
#[repr(transparent)]
#[derive(Debug, Clone)]
pub struct RetroSystemAVInfo(retro_system_av_info);

impl RetroSystemAVInfo {
/// Main constructor.
pub fn new(geometry: RetroGameGeometry, timing: RetroSystemTiming) -> Self {
Self(retro_system_av_info {
geometry: geometry.into(),
timing: timing.into(),
})
}

/// Returns a [RetroSystemAVInfo] with the default [RetroSystemTiming].
pub fn default_timings(geometry: RetroGameGeometry) -> Self {
Self::new(geometry, RetroSystemTiming::default())
}

pub fn geometry(&self) -> RetroGameGeometry {
RetroGameGeometry(self.0.geometry)
}

pub fn timing(&self) -> RetroSystemTiming {
RetroSystemTiming(self.0.timing)
}

pub fn into_inner(self) -> retro_system_av_info {
self.0
}
}

impl From<RetroSystemAVInfo> for retro_system_av_info {
fn from(av_info: RetroSystemAVInfo) -> Self {
av_info.into_inner()
}
}

/// Rust interface for [retro_game_geometry].
#[repr(transparent)]
#[derive(Clone, Debug)]
pub struct RetroGameGeometry(retro_game_geometry);

impl RetroGameGeometry {
/// Creates a [retro_game_geometry] with fixed width and height and automatically
/// derived aspect ratio.
pub fn fixed(width: u16, height: u16) -> Self {
Self(retro_game_geometry {
base_width: width.into(),
base_height: height.into(),
max_width: width.into(),
max_height: height.into(),
aspect_ratio: 0.0,
})
}

/// Creates a [retro_game_geometry] with the given base and max width and height,
/// and automatically derived aspect ratio.
pub fn variable(width: RangeInclusive<u16>, height: RangeInclusive<u16>) -> Self {
Self::new(width, height, 0.0)
}

/// Main constructor.
pub fn new(width: RangeInclusive<u16>, height: RangeInclusive<u16>, aspect_ratio: f32) -> Self {
Self(retro_game_geometry {
base_width: c_uint::from(*width.start()),
base_height: c_uint::from(*height.start()),
max_width: c_uint::from(*width.end()),
max_height: c_uint::from(*height.end()),
aspect_ratio,
})
}

pub fn base_width(&self) -> u16 {
self.0.base_width as u16
}

pub fn base_height(&self) -> u16 {
self.0.base_height as u16
}

pub fn max_width(&self) -> u16 {
self.0.max_width as u16
}

pub fn max_height(&self) -> u16 {
self.0.max_height as u16
}

pub fn aspect_ratio(&self) -> f32 {
self.0.aspect_ratio
}

pub fn into_inner(self) -> retro_game_geometry {
self.0
}
}

impl From<RetroGameGeometry> for retro_game_geometry {
fn from(geometry: RetroGameGeometry) -> Self {
geometry.into_inner()
}
}

/// Rust interface for [retro_system_timing].
#[repr(transparent)]
#[derive(Clone, Debug)]
pub struct RetroSystemTiming(retro_system_timing);

impl RetroSystemTiming {
/// Main constructor.
pub fn new(fps: f64, sample_rate: f64) -> Self {
Self(retro_system_timing { fps, sample_rate })
}

pub fn fps(&self) -> f64 {
self.0.fps
}

pub fn sample_rate(&self) -> f64 {
self.0.sample_rate
}

pub fn into_inner(self) -> retro_system_timing {
self.0
}
}

impl Default for RetroSystemTiming {
/// 60.0 FPS and 44.1khz sample rate.
fn default() -> Self {
Self(retro_system_timing {
fps: 60.0,
sample_rate: 44_100.0,
})
}
}

impl From<RetroSystemTiming> for retro_system_timing {
fn from(timing: RetroSystemTiming) -> Self {
timing.into_inner()
}
}

0 comments on commit 6fc4f96

Please sign in to comment.