1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
use super::*;
/// Static information about the [`Core`] implementation.
#[derive(Debug, Default)]
pub struct SystemInfo {
/// Descriptive name of library. Should not
/// contain any version numbers, etc.
pub library_name: CString,
/// Descriptive version of the core.
pub library_version: CString,
/// A string listing probably content extensions the core will be able to
/// load, separated with pipe. I.e. "bin|rom|iso".
/// Typically used for a GUI to filter out extensions.
pub valid_extensions: CString,
/// libretro cores that need to have direct access to their content
/// files, including cores which use the path of the content files to
/// determine the paths of other files, should set `need_fullpath` to true.
///
/// Cores should strive for setting `need_fullpath` to [`false`],
/// as it allows the frontend to perform patching, etc.
///
/// If `need_fullpath` is [`true`] and [`Core::on_load_game`] is called:
/// - [`retro_game_info::path`] is guaranteed to have a valid path
/// - [`retro_game_info::data`] and [`retro_game_info::size`] are invalid
///
/// If `need_fullpath` is [`false`] and [`Core::on_load_game`] is called:
/// - [`retro_game_info::path`] may be NULL
/// - [`retro_game_info::data`] and [`retro_game_info::size`] are guaranteed
/// to be valid
///
/// See also:
/// - [`environment::get_system_directory`]
/// - [`environment::get_save_directory`]
pub need_fullpath: bool,
/// If [`true`], the frontend is not allowed to extract any archives before
/// loading the real content.
/// Necessary for certain libretro implementations that load games
/// from zipped archives.
pub block_extract: bool,
}
bitflags::bitflags! {
pub struct EnabledCallbacks: u32 {
const KEYBOARD = 1 << 0;
const DISK_CONTROL = 1 << 1;
const HW_RENDER_CALLBACK = 1 << 2;
const FRAME_TIME = 1 << 3;
const AUDIO = 1 << 4;
const RUMBLE = 1 << 5;
const SENSOR = 1 << 6;
const CAMERA = 1 << 7;
const PERFORMANCE = 1 << 8;
const LOCATION = 1 << 9;
const PROC_ADDRESS = 1 << 10;
const HW_RENDER_INTERFACE = 1 << 11;
const HW_RENDER_CONTEXT_NEGOTIATION = 1 << 12;
const VFS = 1 << 13;
const LED = 1 << 14;
const MIDI = 1 << 15;
const DISC_CONTROL_EXT = 1 << 16;
const AUDIO_BUFFER_STATUS = 1 << 17;
}
}
bitflags::bitflags! {
/// Bitflags indicating the type of input device
pub struct RetroDevice: u8 {
/// Input disabled
const NONE = (1 << RETRO_DEVICE_NONE);
/// The JOYPAD is called RetroPad. It is essentially a Super Nintendo
/// controller, but with additional L2/R2/L3/R3 buttons, similar to a
/// PS1 DualShock.
const JOYPAD = (1 << RETRO_DEVICE_JOYPAD);
/// The mouse is a simple mouse, similar to Super Nintendo's mouse.
/// X and Y coordinates are reported relatively to last poll (poll callback).
/// It is up to the libretro implementation to keep track of where the mouse
/// pointer is supposed to be on the screen.
/// The frontend must make sure not to interfere with its own hardware
/// mouse pointer.
const MOUSE = (1 << RETRO_DEVICE_MOUSE);
/// KEYBOARD device lets one poll for raw key pressed.
/// It is poll based, so input callback will return with the current
/// pressed state.
/// For event/text based keyboard input, see
/// [`RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK`].
const KEYBOARD = (1 << RETRO_DEVICE_KEYBOARD);
/// LIGHTGUN device is similar to Guncon-2 for PlayStation 2.
/// It reports X/Y coordinates in screen space (similar to the pointer)
/// in the range `[-0x8000, 0x7fff]` in both axes, with zero being center and
/// `-0x8000` being out of bounds.
/// As well as reporting on/off screen state. It features a trigger,
/// start/select buttons, auxiliary action buttons and a
/// directional pad. A forced off-screen shot can be requested for
/// auto-reloading function in some games.
const LIGHTGUN = (1 << RETRO_DEVICE_LIGHTGUN);
/// The ANALOG device is an extension to JOYPAD (RetroPad).
/// Similar to DualShock2 it adds two analog sticks and all buttons can
/// be analog. This is treated as a separate device type as it returns
/// axis values in the full analog range of `[-0x7fff, 0x7fff]`,
/// although some devices may return `-0x8000`.
/// Positive X axis is right. Positive Y axis is down.
/// Buttons are returned in the range `[0, 0x7fff]`.
/// Only use ANALOG type when polling for analog values.
const ANALOG = (1 << RETRO_DEVICE_ANALOG);
/// Abstracts the concept of a pointing mechanism, e.g. touch.
/// This allows libretro to query in absolute coordinates where on the
/// screen a mouse (or something similar) is being placed.
/// For a touch centric device, coordinates reported are the coordinates
/// of the press.
///
/// Coordinates in X and Y are reported as:
/// `[-0x7fff, 0x7fff]`: `-0x7fff` corresponds to the far left/top of the screen,
/// and `0x7fff` corresponds to the far right/bottom of the screen.
/// The "screen" is here defined as area that is passed to the frontend and
/// later displayed on the monitor.
///
/// The frontend is free to scale/resize this screen as it sees fit, however,
/// `(X, Y) = (-0x7fff, -0x7fff)` will correspond to the top-left pixel of the
/// game image, etc.
///
/// To check if the pointer coordinates are valid (e.g. a touch display
/// actually being touched), PRESSED returns 1 or 0.
///
/// If using a mouse on a desktop, PRESSED will usually correspond to the
/// left mouse button, but this is a frontend decision.
/// PRESSED will only return 1 if the pointer is inside the game screen.
///
/// For multi-touch, the index variable can be used to successively query
/// more presses.
/// If `index = 0` returns `true` for `_PRESSED`, coordinates can be extracted
/// with `_X, _Y` for `index = 0`. One can then query `_PRESSED, _X, _Y` with
/// `index = 1`, and so on.
/// Eventually `_PRESSED` will return `false` for an index. No further presses
/// are registered at this point.
const POINTER = (1 << RETRO_DEVICE_POINTER);
}
}
#[test]
fn retro_device_struct_size() {
assert_eq!(
std::mem::size_of::<RetroDevice>(),
((RETRO_DEVICE_MASK + 1) >> RETRO_DEVICE_TYPE_SHIFT) as usize
);
}
bitflags::bitflags! {
/// Signifies quirks of the [`Core`]’s serialization feature (if any).
pub struct SerializationQuirks: u32 {
/// Serialized state is incomplete in some way. Set if serialization is
/// usable in typical end-user cases but should not be relied upon to
/// implement frame-sensitive frontend features such as netplay or
/// rerecording.
const INCOMPLETE = RETRO_SERIALIZATION_QUIRK_INCOMPLETE;
/// The core must spend some time initializing before serialization is
/// supported. [`Core::on_serialize`] will initially fail; [`Core::on_unserialize`]
/// and [`Core::get_serialize_size`] may or may not work correctly either.
const MUST_INITIALIZE = RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE;
/// Serialization size may change within a session.
const CORE_VARIABLE_SIZE = RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE;
/// Set by the frontend to acknowledge that it supports variable-sized
/// states.
const FRONT_VARIABLE_SIZE = RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE;
/// Serialized state can only be loaded during the same session.
const SINGLE_SESSION = RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION;
/// Serialized state cannot be loaded on an architecture with a different
/// endianness from the one it was saved on.
const ENDIAN_DEPENDENT = RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT;
/// Serialized state cannot be loaded on a different platform from the one it
/// was saved on for reasons other than endianness, such as word size
/// dependence
const PLATFORM_DEPENDENT = RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT;
}
}
/// Used in [`environment::set_message_ext`] to signal some ongoing progress.
pub enum MessageProgress {
/// The message is unmetered or the progress cannot be determined.
Indeterminate,
/// The progress as a percentage (0 - 100).
Percentage(u8),
}
impl MessageProgress {
pub fn indeterminate() -> Self {
MessageProgress::Indeterminate
}
pub fn percentage(value: u8) -> Option<Self> {
if value <= 100 {
Some(MessageProgress::Percentage(value))
} else {
None
}
}
pub fn as_i8(&self) -> i8 {
match *self {
MessageProgress::Percentage(value) => value as i8,
MessageProgress::Indeterminate => -1,
}
}
}
/// Screen rotation in degrees
pub enum Rotation {
None,
Clockwise90,
Clockwise180,
Clockwise270,
CounterClockwise90,
CounterClockwise180,
CounterClockwise270,
}
impl Rotation {
pub fn get_env_value(&self) -> u32 {
match self {
Rotation::None => 0,
Rotation::Clockwise90 => 3,
Rotation::Clockwise180 => 2,
Rotation::Clockwise270 => 1,
Rotation::CounterClockwise90 => 1,
Rotation::CounterClockwise180 => 2,
Rotation::CounterClockwise270 => 3,
}
}
}
/// Data structures used by experimental libretro environment function calls
#[proc::unstable(feature = "env-commands")]
pub mod unstable {
bitflags::bitflags! {
/// Tells the core if the frontend wants audio or video.
pub struct AudioVideoEnable: u32 {
/// When this bit is **not** set:
/// * The frontend wants the core: to not generate any video,
/// including presenting frames via hardware acceleration.
/// * The frontend's video frame callback will do nothing.
/// * After running the frame, the video output of the next frame should be
/// no different than if video was enabled, and saving and loading state
/// should have no issues.
const ENABLE_VIDEO = 0b0001;
/// When this bit is **not** set:
/// * The frontend wants the core to not generate any audio.
/// * The frontend's audio callbacks will do nothing.
/// * After running the frame, the audio output of the next frame should be
/// no different than if audio was enabled, and saving and loading state
/// should have no issues.
const ENABLE_AUDIO = 0b0010;
/// When this bit is set:
/// * Guaranteed to be created by the same binary that will load them.
/// * Will not be written to or read from the disk.
/// * Suggest that the core assumes loading state will succeed.
/// * Suggest that the core updates its memory buffers in-place if possible.
/// * Suggest that the core skips clearing memory.
/// * Suggest that the core skips resetting the system.
/// * Suggest that the core may skip validation steps.
const USE_FAST_SAVESTATES = 0b0100;
/// When this bit is set:
/// * Used for a secondary core when running ahead.
/// * Indicates that the frontend will never need audio from the core.
/// * Suggests that the core may stop synthesizing audio, but this should not
/// compromise emulation accuracy.
/// * Audio output for the next frame does not matter, and the frontend will
/// never need an accurate audio state in the future.
/// * State will never be saved when using Hard Disable Audio.
const HARD_DISABLE_AUDIO = 0b1000;
}
}
bitflags::bitflags! {
/// Joypad button mask
pub struct JoypadState: u16 {
const B = 0b0000_0000_0000_0001;
const Y = 0b0000_0000_0000_0010;
const SELECT = 0b0000_0000_0000_0100;
const START = 0b0000_0000_0000_1000;
const UP = 0b0000_0000_0001_0000;
const DOWN = 0b0000_0000_0010_0000;
const LEFT = 0b0000_0000_0100_0000;
const RIGHT = 0b0000_0000_1000_0000;
const A = 0b0000_0001_0000_0000;
const X = 0b0000_0010_0000_0000;
const L = 0b0000_0100_0000_0000;
const R = 0b0000_1000_0000_0000;
const L2 = 0b0001_0000_0000_0000;
const R2 = 0b0010_0000_0000_0000;
const L3 = 0b0100_0000_0000_0000;
const R3 = 0b1000_0000_0000_0000;
}
}
}
pub use unstable::*;
