rust_libretro/environment.rs
1//! Unsafe functions related to the libretro environment callback.
2//! For safe versions have a look at the [`contexts`] module and
3//! the context types you get in your core callbacks.
4
5use super::{types::*, *};
6
7/// Gets a value from an environment callback.
8///
9/// The first value of the return type is the queried data,
10/// the second value is the return value of the callback itself.
11pub unsafe fn get<T: Default>(callback: retro_environment_t, id: u32) -> Option<(T, bool)> {
12 get_mut(callback, id, Default::default())
13}
14
15/// Similar to [`get`] but uses uninitialized memory instead of the [`Default`] trait.
16pub unsafe fn get_unchecked<T>(callback: retro_environment_t, id: u32) -> Option<(T, bool)> {
17 let data = std::mem::MaybeUninit::zeroed().assume_init();
18
19 get_mut(callback, id, data)
20}
21
22/// Passes a value to the environment callback and returns the modified value.
23///
24/// The second value is the return value of the callback itself.
25pub unsafe fn get_mut<T>(callback: retro_environment_t, id: u32, mut data: T) -> Option<(T, bool)> {
26 if let Some(callback) = callback {
27 if (callback as *const c_void).is_null() {
28 panic!("Expected environment callback, got NULL pointer instead!");
29 }
30
31 let status = (callback)(id, (&mut data as *mut _) as *mut c_void);
32
33 Some((data, status))
34 } else {
35 None
36 }
37}
38
39/// Helper function to query a string pointer and convert it into a [`Path`].
40pub unsafe fn get_path<'a>(callback: retro_environment_t, id: u32) -> Option<&'a Path> {
41 let ptr: *mut c_void = std::ptr::null_mut();
42
43 if let Some((ptr, _)) = get_mut(callback, id, ptr) {
44 return get_path_from_pointer(ptr as *const c_char);
45 }
46
47 None
48}
49
50/// Passes a value to the environment callback.
51///
52/// Returns [`None`] if the environment callback hasn’t been set
53/// and the return status of the callback otherwise.
54pub unsafe fn set<T: std::fmt::Debug>(
55 callback: retro_environment_t,
56 id: u32,
57 value: T,
58) -> Option<bool> {
59 set_ptr(callback, id, &value as *const _)
60}
61
62/// Passes a value (by a raw const pointer) to the environment callback.
63///
64/// Returns [`None`] if the environment callback hasn’t been set
65/// and the return status of the callback otherwise.
66pub unsafe fn set_ptr<T>(callback: retro_environment_t, id: u32, ptr: *const T) -> Option<bool> {
67 if let Some(callback) = callback {
68 if (callback as *const c_void).is_null() {
69 panic!("Expected environment callback, got NULL pointer instead!");
70 }
71
72 let status = (callback)(id, ptr as *mut c_void);
73
74 return Some(status);
75 }
76
77 None
78}
79
80/* ========================================================================== *\
81 * Environment callback implementations *
82\* ========================================================================== */
83
84/// Sets screen rotation of graphics.
85#[proc::context(GenericContext)]
86pub unsafe fn set_rotation(callback: retro_environment_t, rotation: Rotation) -> bool {
87 // const unsigned *
88 set(
89 callback,
90 RETRO_ENVIRONMENT_SET_ROTATION,
91 rotation.get_env_value(),
92 )
93 .unwrap_or(false)
94}
95
96/// Boolean value whether or not the implementation should use overscan,
97/// or crop away overscan.
98#[deprecated(
99 note = "This function is considered deprecated in favor of using core options to manage overscan in a more nuanced, core-specific way"
100)]
101#[proc::context(GenericContext)]
102pub unsafe fn get_overscan(callback: retro_environment_t) -> bool {
103 // bool *
104 get(callback, RETRO_ENVIRONMENT_GET_OVERSCAN)
105 .map(|(v, _)| v)
106 .unwrap_or(false)
107}
108
109/// Boolean value whether or not frontend supports frame duping,
110/// passing NULL to video frame callback.
111#[proc::context(GenericContext)]
112pub unsafe fn can_dupe(callback: retro_environment_t) -> bool {
113 // bool *
114 get(callback, RETRO_ENVIRONMENT_GET_CAN_DUPE)
115 .map(|(v, _)| v)
116 .unwrap_or(false)
117}
118
119/// Sets a message to be displayed in implementation-specific manner
120/// for a certain amount of 'frames'.
121/// Should not be used for trivial messages, which should simply be
122/// logged via [`RETRO_ENVIRONMENT_GET_LOG_INTERFACE`] (or as a
123/// fallback, stderr).
124#[proc::context(GenericContext)]
125pub unsafe fn set_message(callback: retro_environment_t, message: &str, frames: u32) -> bool {
126 let msg = match CString::new(message) {
127 Ok(message) => message,
128 Err(err) => {
129 #[cfg(feature = "log")]
130 log::error!("{}", err);
131
132 return false;
133 }
134 };
135
136 // const struct retro_message *
137 set(
138 callback,
139 RETRO_ENVIRONMENT_SET_MESSAGE,
140 retro_message {
141 msg: msg.as_ptr(),
142 frames,
143 },
144 )
145 .unwrap_or(false)
146}
147
148/// Requests the frontend to shutdown.
149/// Should only be used if game has a specific
150/// way to shutdown the game from a menu item or similar.
151#[proc::context(GenericContext)]
152pub unsafe fn shutdown(callback: retro_environment_t) {
153 // N/A (NULL)
154 set_ptr(
155 callback,
156 RETRO_ENVIRONMENT_SHUTDOWN,
157 std::ptr::null() as *const c_void,
158 );
159}
160
161/// Gives a hint to the frontend how demanding this implementation
162/// is on a system. E.g. reporting a level of 2 means
163/// this implementation should run decently on all frontends
164/// of level 2 and up.
165///
166/// It can be used by the frontend to potentially warn
167/// about too demanding implementations.
168///
169/// The levels are "floating".
170///
171/// This function can be called on a per-game basis,
172/// as certain games an implementation can play might be
173/// particularly demanding.
174#[proc::context(LoadGameContext)]
175pub unsafe fn set_performance_level(callback: retro_environment_t, level: u8) -> bool {
176 // const unsigned *
177 set(
178 callback,
179 RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL,
180 level as u32,
181 )
182 .unwrap_or(false)
183}
184
185/// Returns the "system" directory of the frontend.
186/// This directory can be used to store system specific
187/// content such as BIOSes, configuration data, etc.
188/// The returned value can be `NULL`.
189/// If so, no such directory is defined,
190/// and it's up to the implementation to find a suitable directory.
191///
192/// **NOTE**: Some cores used this folder also for "save" data such as
193/// memory cards, etc, for lack of a better place to put it.
194/// This is now discouraged, and if possible, cores should try to
195/// use the new [`get_save_directory()`].
196#[proc::context(GenericContext)]
197pub unsafe fn get_system_directory<'a>(callback: retro_environment_t) -> Option<&'a Path> {
198 // const char **
199 get_path(callback, RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY)
200}
201
202/// Sets the internal pixel format used by the implementation.
203/// The default pixel format is [`retro_pixel_format::RETRO_PIXEL_FORMAT_0RGB1555`].
204/// This pixel format however, is deprecated (see enum [`retro_pixel_format`]).
205/// If the call returns `false`, the frontend does not support this pixel
206/// format.
207#[proc::context(LoadGameContext)]
208#[proc::context(GetAvInfoContext)]
209pub unsafe fn set_pixel_format<F: Into<retro_pixel_format>>(
210 callback: retro_environment_t,
211 format: F,
212) -> bool {
213 // const enum retro_pixel_format *
214 set(callback, RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, format.into()).unwrap_or(false)
215}
216
217/// Sets an array of retro_input_descriptors.
218/// It is up to the frontend to present this in a usable way.
219/// The array is terminated by retro_input_descriptor::description
220/// being set to `NULL`.
221/// This function can be called at any time, but it is recommended
222/// to call it as early as possible.
223#[proc::context(GenericContext)]
224pub unsafe fn set_input_descriptors(
225 callback: retro_environment_t,
226 descriptors: &[retro_input_descriptor],
227) -> bool {
228 // const struct retro_input_descriptor *
229 set_ptr(
230 callback,
231 RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS,
232 descriptors.as_ptr(),
233 )
234 .unwrap_or(false)
235}
236
237/// Sets a callback function used to notify core about keyboard events.
238#[proc::context(GenericContext)]
239pub unsafe fn set_keyboard_callback(
240 callback: retro_environment_t,
241 data: retro_keyboard_callback,
242) -> bool {
243 // const struct retro_keyboard_callback *
244 set(callback, RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK, data).unwrap_or(false)
245}
246
247/// Sets an interface which frontend can use to eject and insert
248/// disk images.
249/// This is used for games which consist of multiple images and
250/// must be manually swapped out by the user (e.g. PSX).
251#[proc::context(GenericContext)]
252pub unsafe fn set_disk_control_interface(
253 callback: retro_environment_t,
254 data: retro_disk_control_callback,
255) -> bool {
256 // const struct retro_disk_control_callback *
257 set(callback, RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, data).unwrap_or(false)
258}
259
260/// Sets an interface to let a libretro core render with
261/// hardware acceleration.
262///
263/// If successful, libretro cores will be able to render to a
264/// frontend-provided framebuffer.
265/// The size of this framebuffer will be at least as large as
266/// max_width/max_height provided in [`Core::on_get_av_info`].
267/// If HW rendering is used, call either
268/// [`RunContext::draw_hardware_frame`] or [`RunContext::dupe_frame`].
269#[proc::context(LoadGameContext)]
270pub unsafe fn set_hw_render(callback: retro_environment_t, data: retro_hw_render_callback) -> bool {
271 // struct retro_hw_render_callback *
272 set(callback, RETRO_ENVIRONMENT_SET_HW_RENDER, data).unwrap_or(false)
273}
274
275/// Interface to acquire user-defined information from environment
276/// that cannot feasibly be supported in a multi-system way.
277///
278/// The `key` should be set to a key which has already been set by
279/// [`set_variables`] or [`set_core_options`].
280///
281/// Returns [`None`] if the variable could not be found.
282#[proc::context(GenericContext)]
283#[proc::context(OptionsChangedContext)]
284#[allow(clippy::needless_lifetimes)]
285pub unsafe fn get_variable<'a>(callback: retro_environment_t, key: &'a str) -> Option<&'a str> {
286 let key = match CString::new(key) {
287 Ok(key) => key,
288 Err(err) => {
289 #[cfg(feature = "log")]
290 log::error!("{}", err);
291
292 return None;
293 }
294 };
295
296 let var = retro_variable {
297 key: key.as_ptr(),
298 value: std::ptr::null(),
299 };
300
301 // struct retro_variable *
302 if let Some((var, _)) = get_mut(callback, RETRO_ENVIRONMENT_GET_VARIABLE, var) {
303 if !var.value.is_null() {
304 return get_str_from_pointer(var.value as *const c_char);
305 }
306 }
307
308 None
309}
310
311/// Allows an implementation to signal the environment
312/// which variables it might want to check for later using
313/// [`get_variable`].
314/// This allows the frontend to present these variables to
315/// a user dynamically.
316/// This should be called the first time as early as
317/// possible (ideally in [`Core::on_set_environment`]).
318/// Afterward it may be called again for the core to communicate
319/// updated options to the frontend, but the number of core
320/// options must not change from the number in the initial call.
321///
322/// The passed array of [`retro_variable`] structs must be
323/// terminated by a
324/// ```
325/// # use rust_libretro_sys::retro_variable;
326/// retro_variable {
327/// key: 0 as *const libc::c_char,
328/// value: 0 as *const libc::c_char,
329/// }
330/// # ;
331/// ```
332/// element.
333/// [`retro_variable::key`] should be namespaced to not collide
334/// with other implementations' keys. E.g. A core called
335/// 'foo' should use keys named as `foo_option`.
336/// [`retro_variable::value`] should contain a human readable
337/// description of the key as well as a `|` delimited list
338/// of expected values.
339///
340/// The number of possible options should be very limited,
341/// i.e. it should be feasible to cycle through options
342/// without a keyboard.
343///
344/// First entry should be treated as a default.
345///
346/// # Examples
347/// ```
348/// # use rust_libretro_sys::retro_variable;
349/// retro_variable {
350/// key: b"foo_option" as *const u8 as *const libc::c_char,
351/// value: b"Speed hack coprocessor X; false|true" as *const u8 as *const libc::c_char,
352/// }
353/// # ;
354/// ```
355///
356/// Text before the first `;` is a description. This `;` must be
357/// followed by a space, and followed by a list of possible
358/// values split up with `|`.
359///
360/// Only strings are operated on. The possible values will
361/// generally be displayed and stored as-is by the frontend.
362#[proc::context(SetEnvironmentContext)]
363pub unsafe fn set_variables(callback: retro_environment_t, variables: &[retro_variable]) -> bool {
364 // const struct retro_variable *
365 set_ptr(
366 callback,
367 RETRO_ENVIRONMENT_SET_VARIABLES,
368 variables.as_ptr(),
369 )
370 .unwrap_or(false)
371}
372
373/// Result is set to [`true`] if some variables are updated by
374/// frontend since last call to [`get_variable`].
375#[proc::context(GenericContext)]
376pub unsafe fn get_variable_update(callback: retro_environment_t) -> bool {
377 // bool *
378 get(callback, RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE)
379 .map(|(v, _)| v)
380 .unwrap_or(false)
381}
382
383/// Tell the frontend whether this Core can run without particular game data.
384///
385/// If true, the [`Core`] implementation supports calls to
386/// [`Core::on_load_game`] with [`None`] as argument.
387#[proc::context(SetEnvironmentContext)]
388pub unsafe fn set_support_no_game(callback: retro_environment_t, value: bool) -> bool {
389 // const bool *
390 set(callback, RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, value).unwrap_or(false)
391}
392
393/// Retrieves the absolute path from where this libretro
394/// implementation was loaded.
395/// [`None`] is returned if the libretro was loaded statically
396/// (i.e. linked statically to frontend), or if the path cannot be
397/// determined.
398/// Mostly useful in cooperation with [`set_support_no_game`] as assets can
399/// be loaded without ugly hacks.
400#[proc::context(GenericContext)]
401pub unsafe fn get_libretro_path<'a>(callback: retro_environment_t) -> Option<&'a Path> {
402 // const char **
403 get_path(callback, RETRO_ENVIRONMENT_GET_LIBRETRO_PATH)
404}
405
406/// Lets the core know how much time has passed since last
407/// invocation of [`Core::on_run`].
408/// The frontend can tamper with the timing to fake fast-forward,
409/// slow-motion, frame stepping, etc.
410/// In this case the delta time will use the reference value
411/// in [`retro_frame_time_callback`].
412#[proc::context(LoadGameContext)]
413#[proc::context(LoadGameSpecialContext)]
414pub unsafe fn set_frame_time_callback(
415 callback: retro_environment_t,
416 data: retro_frame_time_callback,
417) -> bool {
418 // const struct retro_frame_time_callback *
419 set(callback, RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK, data).unwrap_or(false)
420}
421
422/// Sets an interface which is used to notify a libretro core about audio
423/// being available for writing.
424/// The callback can be called from any thread, so a core using this must
425/// have a thread safe audio implementation.
426///
427/// It is intended for games where audio and video are completely
428/// asynchronous and audio can be generated on the fly.
429/// This interface is not recommended for use with emulators which have
430/// highly synchronous audio.
431///
432/// The callback only notifies about writability; the libretro core still
433/// has to call the normal audio callbacks
434/// to write audio. The audio callbacks must be called from within the
435/// notification callback.
436/// The amount of audio data to write is up to the implementation.
437/// Generally, the audio callback will be called continously in a loop.
438///
439/// Due to thread safety guarantees and lack of sync between audio and
440/// video, a frontend can selectively disallow this interface based on
441/// internal configuration. A core using this interface must also
442/// implement the "normal" audio interface.
443///
444/// A libretro core using [`set_audio_callback`] should also make use of
445/// [`set_frame_time_callback`].
446#[proc::context(GenericContext)]
447pub unsafe fn set_audio_callback(
448 callback: retro_environment_t,
449 data: retro_audio_callback,
450) -> bool {
451 // const struct retro_audio_callback *
452 set(callback, RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK, data).unwrap_or(false)
453}
454
455/// Gets an interface which is used by a libretro core to set
456/// state of rumble motors in controllers.
457/// A strong and weak motor is supported, and they can be
458/// controlled indepedently.
459/// Should be called from either [`Core::on_init`] or [`Core::on_load_game`].
460/// Should not be called from [`Core::on_set_environment`].
461/// Returns false if rumble functionality is unavailable.
462#[proc::context(InitContext)]
463#[proc::context(LoadGameContext)]
464pub unsafe fn get_rumble_interface(
465 callback: retro_environment_t,
466) -> Option<retro_rumble_interface> {
467 // struct retro_rumble_interface *
468 get_unchecked(callback, RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE).map(|(v, _)| v)
469}
470
471/// Gets a bitmask telling which device type are expected to be
472/// handled properly in a call to [`retro_input_state_t`].
473/// Devices which are not handled or recognized always return
474/// 0 in [`retro_input_state_t`].
475/// Example bitmask: `RetroDevice::JOYPAD | RetroDevice::ANALOG`.
476#[proc::context(RunContext)]
477pub unsafe fn get_input_device_capabilities(callback: retro_environment_t) -> RetroDevice {
478 // I’m not entirely sure why this call returns a 64 bit value when the `RETRO_DEVICE_MASK` allows only eight distinct types.
479 // uint64_t *
480 if let Some((caps, _)) = get::<u64>(callback, RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES) {
481 return RetroDevice::from_bits_truncate(caps as u8);
482 }
483
484 RetroDevice::NONE
485}
486
487/// Gets access to the sensor interface.
488/// The purpose of this interface is to allow
489/// setting state related to sensors such as polling rate,
490/// enabling/disable it entirely, etc.
491/// Reading sensor state is done via the normal
492/// input_state_callback API.
493#[proc::context(GenericContext)]
494#[proc::unstable(feature = "env-commands")]
495pub unsafe fn get_sensor_interface(
496 callback: retro_environment_t,
497) -> Option<retro_sensor_interface> {
498 // const struct retro_sensor_interface *
499 get_unchecked(callback, RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE).map(|(v, _)| v)
500}
501
502/// Gets an interface to a video camera driver.
503/// A libretro core can use this interface to get access to a
504/// video camera.
505/// New video frames are delivered in a callback in same
506/// thread as [`Core::on_run`].
507///
508/// [`get_camera_interface`] should be called in [`Core::on_load_game`].
509///
510/// Depending on the camera implementation used, camera frames
511/// will be delivered as a raw framebuffer,
512/// or as an OpenGL texture directly.
513///
514/// The core has to tell the frontend here which types of
515/// buffers can be handled properly.
516/// An OpenGL texture can only be handled when using a
517/// libretro GL core ([`set_hw_render`]).
518/// It is recommended to use a libretro GL core when
519/// using camera interface.
520///
521/// The camera is not started automatically. The retrieved start/stop
522/// functions must be used to explicitly
523#[proc::context(LoadGameContext)]
524#[proc::unstable(feature = "env-commands")]
525pub unsafe fn get_camera_interface(
526 callback: retro_environment_t,
527 data: retro_camera_callback,
528) -> Option<retro_camera_callback> {
529 // struct retro_camera_callback *
530 get_mut(callback, RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE, data).map(|(v, _)| v)
531}
532
533/// Gets an interface for logging. This is useful for
534/// logging in a cross-platform way
535/// as certain platforms cannot use `stderr` for logging.
536/// It also allows the frontend to
537/// show logging information in a more suitable way.
538/// If this interface is not used, libretro cores should
539/// log to `stderr` as desired.
540#[proc::context(GenericContext)]
541pub unsafe fn get_log_callback(
542 callback: retro_environment_t,
543) -> Result<Option<retro_log_callback>, Box<dyn std::error::Error>> {
544 // struct retro_log_callback *
545 match get_unchecked(callback, RETRO_ENVIRONMENT_GET_LOG_INTERFACE) {
546 Some((callback, true)) => Ok(Some(callback)),
547 _ => Err("Failed to query log callback".into()),
548 }
549}
550
551/// Gets an interface for performance counters. This is useful
552/// for performance logging in a cross-platform way and for detecting
553/// architecture-specific features, such as SIMD support.
554#[proc::context(GenericContext)]
555pub unsafe fn get_perf_interface(callback: retro_environment_t) -> Option<retro_perf_callback> {
556 // struct retro_perf_callback *
557 get_unchecked(callback, RETRO_ENVIRONMENT_GET_PERF_INTERFACE).map(|(v, _)| v)
558}
559
560/// Gets access to the location interface.
561/// The purpose of this interface is to be able to retrieve
562/// location-based information from the host device,
563/// such as current latitude / longitude.
564#[proc::context(GenericContext)]
565pub unsafe fn get_location_callback(
566 callback: retro_environment_t,
567) -> Option<retro_location_callback> {
568 // struct retro_location_callback *
569 get_unchecked(callback, RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE).map(|(v, _)| v)
570}
571
572/// Returns the "core assets" directory of the frontend.
573/// This directory can be used to store specific assets that the
574/// core relies upon, such as art assets,
575/// input data, etc etc.
576/// The returned value can be [`None`].
577/// If so, no such directory is defined,
578/// and it's up to the implementation to find a suitable directory.
579#[proc::context(GenericContext)]
580pub unsafe fn get_core_assets_directory<'a>(callback: retro_environment_t) -> Option<&'a Path> {
581 // const char **
582 get_path(callback, RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY)
583}
584
585/// Returns the "save" directory of the frontend, unless there is no
586/// save directory available. The save directory should be used to
587/// store SRAM, memory cards, high scores, etc, if the libretro core
588/// cannot use the regular memory interface ([`Core::get_memory_data`]).
589///
590/// If the frontend cannot designate a save directory, it will return
591/// [`None`] to indicate that the core should attempt to operate without a
592/// save directory set.
593///
594/// NOTE: early libretro cores used the system directory for save
595/// files. Cores that need to be backwards-compatible can still check
596/// [`get_system_directory`].
597#[proc::context(GenericContext)]
598pub unsafe fn get_save_directory<'a>(callback: retro_environment_t) -> Option<&'a Path> {
599 // const char **
600 get_path(callback, RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY)
601}
602
603/// Sets a new av_info structure.
604///
605/// This should **only** be used if the core is completely altering the
606/// internal resolutions, aspect ratios, timings, sampling rate, etc.
607/// Calling this can require a full reinitialization of video/audio
608/// drivers in the frontend,
609///
610/// so it is important to call it very sparingly, and usually only with
611/// the users explicit consent.
612/// An eventual driver reinitialize will happen so that video and
613/// audio callbacks
614/// happening after this call within the same [`Core::on_run`] call will
615/// target the newly initialized driver.
616///
617/// This callback makes it possible to support configurable resolutions
618/// in games, which can be useful to
619/// avoid setting the "worst case" in max_width/max_height.
620///
621/// **HIGHLY RECOMMENDED**
622/// Do not call this callback every time
623/// resolution changes in an emulator core if it's
624/// expected to be a temporary change, for the reasons of possible
625/// driver reinitialization.
626/// This call is not a free pass for not trying to provide
627/// correct values in [`Core::on_get_av_info`]. If you need to change
628/// things like aspect ratio or nominal width/height,
629/// use [`set_game_geometry`], which is a softer variant
630/// of [`set_system_av_info`].
631///
632/// If this returns [`false`], the frontend does not acknowledge a
633/// changed [`retro_system_av_info`] struct.
634#[proc::context(RunContext)]
635pub unsafe fn set_system_av_info(
636 callback: retro_environment_t,
637 av_info: retro_system_av_info,
638) -> bool {
639 // const struct retro_system_av_info *
640 set(callback, RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, av_info).unwrap_or(false)
641}
642
643/// Allows a libretro core to announce support for the
644/// [`retro_get_proc_address_interface`] interface.
645/// This interface allows for a standard way to extend libretro where
646/// use of environment calls are too indirect,
647/// e.g. for cases where the frontend wants to call directly into the core.
648///
649/// If a core wants to expose this interface, [`set_proc_address_callback`]
650/// **MUST** be called from within [`Core::on_set_environment`].
651#[proc::context(SetEnvironmentContext)]
652pub unsafe fn set_proc_address_callback(
653 callback: retro_environment_t,
654 data: retro_get_proc_address_interface,
655) -> bool {
656 // const struct retro_get_proc_address_interface *
657 set(callback, RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK, data).unwrap_or(false)
658}
659
660/// This environment call introduces the concept of libretro "subsystems".
661/// A subsystem is a variant of a libretro core which supports
662/// different kinds of games.
663/// The purpose of this is to support e.g. emulators which might
664/// have special needs, e.g. Super Nintendo's Super GameBoy, Sufami Turbo.
665/// It can also be used to pick among subsystems in an explicit way
666/// if the libretro implementation is a multi-system emulator itself.
667///
668/// Loading a game via a subsystem is done with [`Core::on_load_game_special`],
669/// and this environment call allows a libretro core to expose which
670/// subsystems are supported for use with [`Core::on_load_game_special`].
671/// A core passes an array of [`retro_game_info`] which is terminated
672/// with a zeroed out [`retro_game_info`] struct.
673///
674/// If a core wants to use this functionality, [`set_subsystem_info`]
675/// **MUST** be called from within [`Core::on_set_environment`].
676#[proc::context(SetEnvironmentContext)]
677pub unsafe fn set_subsystem_info(
678 callback: retro_environment_t,
679 data: &[retro_subsystem_info],
680) -> bool {
681 // const struct retro_subsystem_info *
682 set_ptr(
683 callback,
684 RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO,
685 data.as_ptr(),
686 )
687 .unwrap_or(false)
688}
689
690/// This environment call lets a libretro core tell the frontend
691/// which controller subclasses are recognized in calls to
692/// [`Core::on_set_controller_port_device`].
693///
694/// Some emulators such as Super Nintendo support multiple lightgun
695/// types which must be specifically selected from. It is therefore
696/// sometimes necessary for a frontend to be able to tell the core
697/// about a special kind of input device which is not specifcally
698/// provided by the Libretro API.
699///
700/// In order for a frontend to understand the workings of those devices,
701/// they must be defined as a specialized subclass of the generic device
702/// types already defined in the libretro API.
703///
704/// The core must pass an **array** of `const struct` [`retro_controller_info`] which
705/// is **terminated with a blanked out struct**.
706/// Each element of the [`retro_controller_info`] struct corresponds to the
707/// ascending port index that is passed to [`Core::on_set_controller_port_device`]
708/// when that function is called to indicate to the core that the frontend has
709/// changed the active device subclass.
710/// **SEE ALSO**: [`Core::on_set_controller_port_device`]
711///
712/// The ascending input port indexes provided by the core in the struct
713/// are generally presented by frontends as ascending User # or Player #,
714/// such as Player 1, Player 2, Player 3, etc. Which device subclasses are
715/// supported can vary per input port.
716///
717/// The first inner element of each entry in the [`retro_controller_info`] array
718/// is a [`retro_controller_description`] struct that specifies the names and
719/// codes of all device subclasses that are available for the corresponding
720/// User or Player, beginning with the generic Libretro device that the
721/// subclasses are derived from. The second inner element of each entry is the
722/// total number of subclasses that are listed in the [`retro_controller_description`].
723///
724/// NOTE: Even if special device types are set in the libretro core,
725/// libretro should only poll input based on the base input device types.
726#[proc::context(GenericContext)]
727pub unsafe fn set_controller_info(
728 callback: retro_environment_t,
729 data: &[retro_controller_info],
730) -> bool {
731 // const struct retro_controller_info *
732 set_ptr(
733 callback,
734 RETRO_ENVIRONMENT_SET_CONTROLLER_INFO,
735 data.as_ptr(),
736 )
737 .unwrap_or(false)
738}
739
740/// This environment call lets a libretro core tell the frontend
741/// about the memory maps this core emulates.
742/// This can be used to implement, for example, cheats in a core-agnostic way.
743///
744/// Should only be used by emulators; it doesn't make much sense for
745/// anything else.
746/// It is recommended to expose all relevant pointers through
747/// retro_get_memory_* as well.
748///
749/// Can be called from [`Core::on_init`] and [`Core::on_load_game`].
750#[proc::context(InitContext)]
751#[proc::context(LoadGameContext)]
752#[proc::unstable(feature = "env-commands")]
753pub unsafe fn set_memory_maps(callback: retro_environment_t, data: retro_memory_map) -> bool {
754 // const struct retro_memory_map *
755 set(callback, RETRO_ENVIRONMENT_SET_MEMORY_MAPS, data).unwrap_or(false)
756}
757
758/// Sets a new game_geometry structure.
759///
760/// This environment call is similar to [`set_system_av_info`] for changing
761/// video parameters, but provides a guarantee that drivers will not be
762/// reinitialized.
763///
764/// The purpose of this call is to allow a core to alter nominal
765/// width/heights as well as aspect ratios on-the-fly, which can be
766/// useful for some emulators to change in run-time.
767///
768/// max_width/max_height arguments are ignored and cannot be changed
769/// with this call as this could potentially require a reinitialization or a
770/// non-constant time operation.
771/// If max_width/max_height are to be changed, [`set_system_av_info`] is required.
772///
773/// A frontend must guarantee that this environment call completes in
774/// constant time.
775#[proc::context(RunContext)]
776pub unsafe fn set_game_geometry(
777 callback: retro_environment_t,
778 geometry: retro_game_geometry,
779) -> bool {
780 // const struct retro_game_geometry *
781 set(callback, RETRO_ENVIRONMENT_SET_GEOMETRY, geometry).unwrap_or(false)
782}
783
784/// Returns the specified username of the frontend, if specified by the user.
785/// This username can be used as a nickname for a core that has online facilities
786/// or any other mode where personalization of the user is desirable.
787/// The returned value can be [`None`].
788/// If this environment callback is used by a core that requires a valid username,
789/// a default username should be specified by the core.
790#[proc::context(GenericContext)]
791pub unsafe fn get_username<'a>(callback: retro_environment_t) -> Option<&'a str> {
792 let ptr: *mut c_void = std::ptr::null_mut();
793
794 // const char **
795 if let Some((ptr, _)) = get_mut(callback, RETRO_ENVIRONMENT_GET_USERNAME, ptr) {
796 if ptr.is_null() {
797 return None;
798 }
799
800 return get_str_from_pointer(ptr as *const c_char);
801 }
802
803 None
804}
805
806/// Returns the language of the frontend, if specified by the user.
807/// It can be used by the core for localization purposes.
808#[proc::context(GenericContext)]
809pub unsafe fn get_language(callback: retro_environment_t) -> Option<retro_language> {
810 // unsigned *
811 if let Some((id, _)) = get::<u32>(callback, RETRO_ENVIRONMENT_GET_LANGUAGE) {
812 if id < retro_language::RETRO_LANGUAGE_LAST as u32 {
813 // This is safe because all values from 0 to RETRO_LANGUAGE_LAST have defined values
814 return Some(std::mem::transmute(id));
815 }
816 }
817
818 None
819}
820
821/// Returns a preallocated framebuffer which the core can use for rendering
822/// the frame into when not using [`set_hw_render`].
823/// The framebuffer returned from this call must not be used
824/// after the current call to [`Core::on_run`] returns.
825///
826/// The goal of this call is to allow zero-copy behavior where a core
827/// can render directly into video memory, avoiding extra bandwidth cost by copying
828/// memory from core to video memory.
829///
830/// If this call succeeds and the core renders into it,
831/// the framebuffer pointer and pitch can be passed to [`RunContext::draw_framebuffer`].
832/// If the buffer from [`get_current_software_framebuffer`] is to be used,
833/// the core must pass the exact
834/// same pointer as returned by [`get_current_software_framebuffer`];
835/// i.e. passing a pointer which is offset from the
836/// buffer is undefined. The width, height and pitch parameters
837/// must also match exactly to the values obtained from [`get_current_software_framebuffer`].
838///
839/// It is possible for a frontend to return a different pixel format
840/// than the one used in [`set_pixel_format`]. This can happen if the frontend
841/// needs to perform conversion.
842///
843/// It is still valid for a core to render to a different buffer
844/// even if [`get_current_software_framebuffer`] succeeds.
845///
846/// A frontend must make sure that the pointer obtained from this function is
847/// writeable (and readable).
848#[proc::context(GenericContext)]
849#[proc::unstable(feature = "env-commands")]
850pub unsafe fn get_current_software_framebuffer(
851 callback: retro_environment_t,
852 data: retro_framebuffer,
853) -> Option<retro_framebuffer> {
854 // struct retro_framebuffer *
855 get_mut(
856 callback,
857 RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER,
858 data,
859 )
860 .map(|(v, _)| v)
861}
862
863/// Returns an API specific rendering interface for accessing API specific data.
864/// Not all HW rendering APIs support or need this.
865/// The contents of the returned pointer is specific to the rendering API
866/// being used. See the various headers like libretro_vulkan.h, etc.
867///
868/// [`get_hw_render_interface`] cannot be called before [`retro_hw_context_reset_callback`] has been called.
869///
870/// Similarly, after [`retro_hw_context_destroyed_callback`] returns, the contents of the HW_RENDER_INTERFACE are invalidated.
871///
872/// **TODO:** Set a status flag in [`retro_hw_context_reset_callback`] and [`retro_hw_context_destroyed_callback`] to force the mentioned call restrictions.
873#[proc::context(GenericContext)]
874#[proc::unstable(feature = "env-commands")]
875pub unsafe fn get_hw_render_interface(
876 callback: retro_environment_t,
877) -> Option<retro_hw_render_interface> {
878 // const struct retro_hw_render_interface **
879 get_mut(
880 callback,
881 RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE,
882 std::ptr::null(),
883 )
884 .map(|(v, _)| *v)
885}
886
887/// See [`get_hw_render_interface`].
888#[cfg(feature = "vulkan")]
889#[proc::context(GenericContext)]
890#[proc::unstable(feature = "env-commands")]
891pub unsafe fn get_hw_render_interface_vulkan(
892 callback: retro_environment_t,
893) -> Option<retro_hw_render_interface_vulkan> {
894 // const struct retro_hw_render_interface_vulkan **
895 get_mut(
896 callback,
897 RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE,
898 std::ptr::null::<retro_hw_render_interface_vulkan>(),
899 )
900 .map(|(v, _)| (*v).clone())
901}
902
903/// If true, the Core implementation supports achievements.
904///
905/// Either via memory descriptors set with [`RETRO_ENVIRONMENT_SET_MEMORY_MAPS`]
906/// or via [`Core::get_memory_data`] / [`Core::get_memory_size`].
907#[proc::context(InitContext)]
908#[proc::unstable(feature = "env-commands")]
909pub unsafe fn set_support_achievements(callback: retro_environment_t, value: bool) -> bool {
910 // const bool *
911 set(callback, RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS, value).unwrap_or(false)
912}
913
914/// Sets an interface which lets the libretro core negotiate with frontend how a context is created.
915/// The semantics of this interface depends on which API is used in [`set_hw_render`] earlier.
916/// This interface will be used when the frontend is trying to create a HW rendering context,
917/// so it will be used after [`set_hw_render`], but before the context_reset callback.
918#[proc::context(LoadGameContext)]
919#[proc::unstable(feature = "env-commands")]
920pub unsafe fn set_hw_render_context_negotiation_interface(
921 callback: retro_environment_t,
922 interface: &retro_hw_render_context_negotiation_interface,
923) -> bool {
924 // const struct retro_hw_render_context_negotiation_interface *
925 set_ptr(
926 callback,
927 RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE,
928 interface,
929 )
930 .unwrap_or(false)
931}
932
933/// Sets quirk flags associated with serialization.
934/// The frontend will zero any flags it doesn't recognize or support.
935///
936/// **Should be set in either [`Core::on_init`] or [`Core::on_load_game`], but not both.**
937#[proc::context(InitContext)]
938#[proc::context(LoadGameContext)]
939pub unsafe fn set_serialization_quirks(
940 callback: retro_environment_t,
941 quirks: SerializationQuirks,
942) -> bool {
943 // uint64_t *
944 set(
945 callback,
946 RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS,
947 quirks.bits() as u64,
948 )
949 .unwrap_or(false)
950}
951
952/// The frontend will try to use a 'shared' hardware context (mostly applicable
953/// to OpenGL) when a hardware context is being set up.
954///
955/// Returns [`true`] if the frontend supports shared hardware contexts and [`false`]
956/// if the frontend does not support shared hardware contexts.
957///
958/// This will do nothing on its own until `SET_HW_RENDER` environment callbacks are
959/// being used.
960#[proc::context(GenericContext)]
961#[proc::unstable(feature = "env-commands")]
962pub unsafe fn set_hw_shared_context(callback: retro_environment_t) -> bool {
963 // N/A (null) *
964 set_ptr(
965 callback,
966 RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT,
967 std::ptr::null() as *const c_void,
968 )
969 .unwrap_or(false)
970}
971
972/// Gets access to the VFS interface.
973/// VFS presence needs to be queried prior to load_game or any
974/// get_system/save/other_directory being called to let front end know
975/// core supports VFS before it starts handing out paths.
976/// It is recomended to do so in [`Core::on_set_environment`].
977#[proc::context(SetEnvironmentContext)]
978#[proc::unstable(feature = "env-commands")]
979pub fn get_vfs_interface(
980 callback: retro_environment_t,
981 data: retro_vfs_interface_info,
982) -> Option<retro_vfs_interface_info> {
983 // struct retro_vfs_interface_info *
984 get_mut(callback, RETRO_ENVIRONMENT_GET_VFS_INTERFACE, data).map(|(v, _)| v)
985}
986
987/// Gets an interface which is used by a libretro core to set state of LEDs.
988#[proc::context(GenericContext)]
989#[proc::unstable(feature = "env-commands")]
990pub fn get_led_interface(callback: retro_environment_t) -> Option<retro_led_interface> {
991 // struct retro_led_interface *
992 get_unchecked(callback, RETRO_ENVIRONMENT_GET_LED_INTERFACE).map(|(v, _)| v)
993}
994
995/// Tells the core if the frontend wants audio or video.
996/// If disabled, the frontend will discard the audio or video,
997/// so the core may decide to skip generating a frame or generating audio.
998/// This is mainly used for increasing performance.
999///
1000/// See [`AudioVideoEnable`] for descriptions of the flags.
1001#[proc::context(GenericContext)]
1002#[proc::unstable(feature = "env-commands")]
1003pub unsafe fn get_audio_video_enable(callback: retro_environment_t) -> AudioVideoEnable {
1004 // int *
1005 if let Some((info, _)) = get(callback, RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE) {
1006 return AudioVideoEnable::from_bits_truncate(info);
1007 }
1008
1009 AudioVideoEnable::empty()
1010}
1011
1012/// Returns a MIDI interface that can be used for raw data I/O.
1013#[proc::context(GenericContext)]
1014#[proc::unstable(feature = "env-commands")]
1015pub fn get_midi_interface(callback: retro_environment_t) -> Option<retro_midi_interface> {
1016 // struct retro_midi_interface **
1017 get_unchecked(callback, RETRO_ENVIRONMENT_GET_MIDI_INTERFACE).map(|(v, _)| v)
1018}
1019
1020/// Boolean value that indicates whether or not the frontend is in fastforwarding mode.
1021#[proc::context(GenericContext)]
1022#[proc::unstable(feature = "env-commands")]
1023pub unsafe fn get_fastforwarding(callback: retro_environment_t) -> bool {
1024 // bool *
1025 get(callback, RETRO_ENVIRONMENT_GET_FASTFORWARDING)
1026 .map(|(v, _)| v)
1027 .unwrap_or(false)
1028}
1029
1030/// Float value that lets us know what target refresh rate
1031/// is curently in use by the frontend.
1032///
1033/// The core can use the returned value to set an ideal
1034/// refresh rate/framerate.
1035#[proc::context(GenericContext)]
1036#[proc::unstable(feature = "env-commands")]
1037pub unsafe fn get_target_refresh_rate(callback: retro_environment_t) -> Option<f32> {
1038 // float *
1039 get(callback, RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE).map(|(v, _)| v)
1040}
1041
1042/// Boolean value that indicates whether or not the frontend supports
1043/// input bitmasks being returned by [`retro_input_state_t`]. The advantage
1044/// of this is that [`retro_input_state_t`] has to be only called once to
1045/// grab all button states instead of multiple times.
1046///
1047/// If it returns true, you can pass [`RETRO_DEVICE_ID_JOYPAD_MASK`] as `id`
1048/// to [`retro_input_state_t`] (make sure `device` is set to [`RETRO_DEVICE_JOYPAD`]).
1049/// It will return a bitmask of all the digital buttons.
1050#[proc::context(GenericContext)]
1051#[proc::unstable(feature = "env-commands")]
1052pub unsafe fn get_input_bitmasks(callback: retro_environment_t) -> bool {
1053 // bool *
1054 // get(callback, RETRO_ENVIRONMENT_GET_INPUT_BITMASKS).map(|(v, _)| v).unwrap_or(false)
1055
1056 // RetroArch uses the callback’s return value instead
1057 set_ptr(
1058 callback,
1059 RETRO_ENVIRONMENT_GET_INPUT_BITMASKS,
1060 std::ptr::null() as *const c_void,
1061 )
1062 .unwrap_or(false)
1063}
1064
1065/// The returned value is the API version number of the core options
1066/// interface supported by the frontend.
1067/// If the underlying callback failed, API version is assumed to be 0.
1068///
1069/// In legacy code, core options are set by passing an array of
1070/// retro_variable structs to [`set_variables`].
1071/// This may be still be done regardless of the core options
1072/// interface version.
1073///
1074/// If version is `>= 1` however, core options may instead be set by
1075/// passing an array of [`retro_core_option_definition`] structs to
1076/// [`set_core_options`], or a 2D array of
1077/// [`retro_core_option_definition`] structs to [`RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL`].
1078/// This allows the core to additionally set option sublabel information
1079/// and/or provide localisation support.
1080///
1081/// If version is `>= 2,` core options may instead be set by passing
1082/// a `retro_core_options_v2` struct to [`set_core_options_v2`],
1083/// or an array of [`retro_core_options_v2`] structs to
1084/// [`set_core_options_v2_intl`]. This allows the core
1085/// to additionally set optional core option category information
1086/// for frontends with core option category support.
1087#[proc::context(GenericContext)]
1088pub unsafe fn get_core_options_version(callback: retro_environment_t) -> u32 {
1089 // unsigned *
1090 get(callback, RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION)
1091 .map(|(v, _)| v)
1092 .unwrap_or(0)
1093}
1094
1095/// Checks whether the frontend supports the [`set_core_options`] interface.
1096#[proc::context(SetEnvironmentContext)]
1097pub unsafe fn supports_set_core_options(callback: retro_environment_t) -> bool {
1098 get_core_options_version(callback) >= 1
1099}
1100
1101/// Checks whether the frontend supports the [`set_core_options_v2`] interface.
1102#[proc::context(SetEnvironmentContext)]
1103pub unsafe fn supports_set_core_options_v2(callback: retro_environment_t) -> bool {
1104 get_core_options_version(callback) >= 2
1105}
1106
1107/// Allows an implementation to signal the environment
1108/// which variables it might want to check for later using
1109/// [`get_variable`].
1110/// This allows the frontend to present these variables to
1111/// a user dynamically.
1112/// This should only be called if [`get_core_options_version`]
1113/// returns an API version of >= 1.
1114/// This should be called instead of [`set_variables`].
1115/// This should be called the first time as early as
1116/// possible (ideally in [`Core::on_set_environment`]).
1117/// Afterwards it may be called again for the core to communicate
1118/// updated options to the frontend, but the number of core
1119/// options must not change from the number in the initial call.
1120///
1121/// 'data' points to an array of [`retro_core_option_definition`] structs
1122/// terminated by a `{ NULL, NULL, NULL, {{0}}, NULL }` element.
1123/// [`retro_core_option_definition::key`] should be namespaced to not collide
1124/// with other implementations' keys. e.g. A core called
1125/// `foo` should use keys named as `foo_option`.
1126/// [`retro_core_option_definition::desc`] should contain a human readable
1127/// description of the key.
1128/// [`retro_core_option_definition::info`] should contain any additional human
1129/// readable information text that a typical user may need to
1130/// understand the functionality of the option.
1131/// [`retro_core_option_definition::values`] is an array of [`retro_core_option_value`]
1132/// structs terminated by a `{ NULL, NULL }` element.
1133/// > `retro_core_option_definition::values[index].value` is an expected option
1134/// value.
1135/// > `retro_core_option_definition::values[index].label` is a human readable
1136/// label used when displaying the value on screen. If `NULL`,
1137/// the value itself is used.
1138/// [`retro_core_option_definition::default_value`] is the default core option
1139/// setting. It must match one of the expected option values in the
1140/// [`retro_core_option_definition::values`] array. If it does not, or the
1141/// default value is `NULL`, the first entry in the
1142/// [`retro_core_option_definition::values`] array is treated as the default.
1143///
1144/// The number of possible option values should be very limited,
1145/// and must be less than [`RETRO_NUM_CORE_OPTION_VALUES_MAX`].
1146/// i.e. it should be feasible to cycle through options
1147/// without a keyboard.
1148///
1149/// # Examples
1150/// ```c
1151/// {
1152/// "foo_option",
1153/// "Speed hack coprocessor X",
1154/// "Provides increased performance at the expense of reduced accuracy",
1155/// {
1156/// { "false", NULL },
1157/// { "true", NULL },
1158/// { "unstable", "Turbo (Unstable)" },
1159/// { NULL, NULL },
1160/// },
1161/// "false"
1162/// }
1163/// ```
1164///
1165/// Only strings are operated on. The possible values will
1166/// generally be displayed and stored as-is by the frontend.
1167#[proc::context(SetEnvironmentContext)]
1168pub unsafe fn set_core_options(
1169 callback: retro_environment_t,
1170 options: &[retro_core_option_definition],
1171) -> bool {
1172 // const struct retro_core_option_definition **
1173 set_ptr(
1174 callback,
1175 RETRO_ENVIRONMENT_SET_CORE_OPTIONS,
1176 options.as_ptr(),
1177 )
1178 .unwrap_or(false)
1179}
1180
1181/// Allows an implementation to signal the environment
1182/// which variables it might want to check for later using
1183/// [`get_variable`].
1184/// This allows the frontend to present these variables to
1185/// a user dynamically.
1186///
1187/// This should only be called if [`get_core_options_version`]
1188/// returns an API version of `>= 2`.
1189///
1190/// This should be called instead of [`set_variables`].
1191///
1192/// This should be called instead of [`set_core_options`].
1193///
1194/// This should be called the first time as early as
1195/// possible (ideally in [`Core::on_set_environment`]).
1196///
1197/// Afterwards it may be called again for the core to communicate
1198/// updated options to the frontend, but the number of core
1199/// options must not change from the number in the initial call.
1200///
1201/// If [`get_core_options_version`] returns an API
1202/// version of `>= 2`, this callback is guaranteed to succeed
1203/// (i.e. callback return value does not indicate success)
1204///
1205/// If callback returns [`true`], frontend has core option category
1206/// support.
1207///
1208/// If callback returns [`false`], frontend does not have core option
1209/// category support.
1210///
1211/// 'data' points to a [`retro_core_options_v2`] struct, containing
1212/// of two pointers:
1213/// - [`retro_core_options_v2::categories`] is an array of
1214/// [`retro_core_option_v2_category`] structs terminated by a
1215/// `{ NULL, NULL, NULL }` element. If [`retro_core_options_v2::categories`]
1216/// is `NULL , all core options will have no category and will be shown
1217/// at the top level of the frontend core option interface. If frontend
1218/// does not have core option category support, categories array will
1219/// be ignored.
1220/// - [`retro_core_options_v2::definitions`] is an array of
1221/// [`retro_core_option_v2_definition`] structs terminated by a
1222/// `{ NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL }`
1223/// element.
1224///
1225/// ## [`retro_core_option_v2_category`] notes:
1226///
1227/// - [`retro_core_option_v2_category::key`] should contain string
1228/// that uniquely identifies the core option category. Valid
1229/// key characters are `[a-z, A-Z, 0-9, _, -]`.
1230///
1231/// Namespace collisions with other implementations' category
1232/// keys are permitted.
1233/// - [`retro_core_option_v2_category::desc`] should contain a human
1234/// readable description of the category key.
1235/// - [`retro_core_option_v2_category::info`] should contain any
1236/// additional human readable information text that a typical
1237/// user may need to understand the nature of the core option
1238/// category.
1239///
1240/// ### Examples
1241/// ```c
1242/// {
1243/// "advanced_settings",
1244/// "Advanced",
1245/// "Options affecting low-level emulation performance and accuracy."
1246/// }
1247/// ```
1248///
1249/// ## [`retro_core_option_v2_definition`] notes:
1250///
1251/// - [`retro_core_option_v2_definition::key`] should be namespaced to not
1252/// collide with other implementations' keys. e.g. A core called
1253/// `foo` should use keys named as `foo_option`. Valid key characters
1254/// are `[a-z, A-Z, 0-9, _, -]`.
1255/// - [`retro_core_option_v2_definition::desc`] should contain a human readable
1256/// description of the key. Will be used when the frontend does not
1257/// have core option category support. Examples: `Aspect Ratio` or
1258/// `Video > Aspect Ratio`.
1259/// - [`retro_core_option_v2_definition::desc_categorized`] should contain a
1260/// human readable description of the key, which will be used when
1261/// frontend has core option category support. Example: `Aspect Ratio`,
1262/// where associated [`retro_core_option_v2_category::desc`] is `Video`.
1263///
1264/// If empty or `NULL`, the string specified by
1265/// [`retro_core_option_v2_definition::desc`] will be used instead.
1266///
1267/// [`retro_core_option_v2_definition::desc_categorized`] will be ignored
1268/// if [`retro_core_option_v2_definition::category_key`] is empty or `NULL`.
1269/// - [`retro_core_option_v2_definition::info`] should contain any additional
1270/// human readable information text that a typical user may need to
1271/// understand the functionality of the option.
1272/// - [`retro_core_option_v2_definition::info_categorized`] should contain
1273/// any additional human readable information text that a typical user
1274/// may need to understand the functionality of the option, and will be
1275/// used when frontend has core option category support. This is provided
1276/// to accommodate the case where info text references an option by
1277/// name/desc, and the desc/desc_categorized text for that option differ.
1278///
1279/// If empty or `NULL`, the string specified by
1280/// [`retro_core_option_v2_definition::info`] will be used instead.
1281///
1282/// [`retro_core_option_v2_definition::info_categorized`] will be ignored
1283/// if [`retro_core_option_v2_definition::category_key`] is empty or `NULL`.
1284/// - [`retro_core_option_v2_definition::category_key`] should contain a
1285/// category identifier (e.g. `video` or `audio`) that will be
1286/// assigned to the core option if frontend has core option category
1287/// support. A categorized option will be shown in a subsection/
1288/// submenu of the frontend core option interface.
1289///
1290/// If key is empty or `NULL`, or if key does not match one of the
1291/// [`retro_core_option_v2_category::key`] values in the associated
1292/// [`retro_core_option_v2_category`] array, option will have no category
1293/// and will be shown at the top level of the frontend core option
1294/// interface.
1295/// - [`retro_core_option_v2_definition::values`] is an array of
1296/// retro_core_option_value structs terminated by a `{ NULL, NULL }`
1297/// element.
1298///
1299/// - [`retro_core_option_v2_definition::values[index].value`](retro_core_option_value::value) is an
1300/// expected option value.
1301///
1302/// - [`retro_core_option_v2_definition::values[index].label`](retro_core_option_value::label) is a
1303/// human readable label used when displaying the value on screen.
1304/// If `NULL`, the value itself is used.
1305/// - [`retro_core_option_v2_definition::default_value`] is the default
1306/// core option setting.
1307///
1308/// It must match one of the expected option
1309/// values in the [`retro_core_option_v2_definition::values`] array.
1310///
1311/// If it does not, or the default value is `NULL`, the first entry in the
1312/// [`retro_core_option_v2_definition::values`] array is treated as the
1313/// default.
1314///
1315/// The number of possible option values should be very limited,
1316/// and must be less than [`RETRO_NUM_CORE_OPTION_VALUES_MAX`].
1317/// i.e. it should be feasible to cycle through options
1318/// without a keyboard.
1319///
1320/// ### Examples
1321///
1322/// - Uncategorized:
1323///
1324///```c
1325/// {
1326/// "foo_option",
1327/// "Speed hack coprocessor X",
1328/// NULL,
1329/// "Provides increased performance at the expense of reduced accuracy.",
1330/// NULL,
1331/// NULL,
1332/// {
1333/// { "false", NULL },
1334/// { "true", NULL },
1335/// { "unstable", "Turbo (Unstable)" },
1336/// { NULL, NULL },
1337/// },
1338/// "false"
1339/// }
1340///```
1341///
1342/// - Categorized:
1343///
1344///```c
1345/// {
1346/// "foo_option",
1347/// "Advanced > Speed hack coprocessor X",
1348/// "Speed hack coprocessor X",
1349/// "Setting 'Advanced > Speed hack coprocessor X' to 'true' or 'Turbo' provides increased performance at the expense of reduced accuracy",
1350/// "Setting 'Speed hack coprocessor X' to 'true' or 'Turbo' provides increased performance at the expense of reduced accuracy",
1351/// "advanced_settings",
1352/// {
1353/// { "false", NULL },
1354/// { "true", NULL },
1355/// { "unstable", "Turbo (Unstable)" },
1356/// { NULL, NULL },
1357/// },
1358/// "false"
1359/// }
1360///```
1361///
1362/// Only strings are operated on. The possible values will
1363/// generally be displayed and stored as-is by the frontend.
1364#[proc::context(SetEnvironmentContext)]
1365pub unsafe fn set_core_options_v2(
1366 callback: retro_environment_t,
1367 options: &retro_core_options_v2,
1368) -> bool {
1369 // const struct retro_core_options_v2 *
1370 set_ptr(
1371 callback,
1372 RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2,
1373 options as *const _,
1374 )
1375 .unwrap_or(false)
1376}
1377
1378/// Allows an implementation to signal the environment
1379/// which variables it might want to check for later using
1380/// [`get_variable`].
1381///
1382/// This allows the frontend to present these variables to
1383/// a user dynamically.
1384///
1385/// This should only be called if [`get_core_options_version`]
1386/// returns an API version of `>= 1`.
1387///
1388/// This should be called instead of [`set_variables`].
1389///
1390/// This should be called instead of [`set_core_options`].
1391///
1392/// This should be called the first time as early as
1393/// possible (ideally in [`Core::on_set_environment`]).
1394///
1395/// Afterwards it may be called again for the core to communicate
1396/// updated options to the frontend, but the number of core
1397/// options must not change from the number in the initial call.
1398///
1399/// This is fundamentally the same as [`set_core_options`],
1400/// with the addition of localisation support. The description of
1401/// [`set_core_options`] callback should be consulted for further details.
1402///
1403/// 'data' points to a [`retro_core_options_intl`] struct.
1404///
1405/// [`retro_core_options_intl::us`] is a pointer to an array of
1406/// [`retro_core_option_definition`] structs defining the US English
1407/// core options implementation. It must point to a valid array.
1408///
1409/// [`retro_core_options_intl::local`] is a pointer to an array of
1410/// [`retro_core_option_definition`] structs defining core options for
1411/// the current frontend language. It may be `NULL` (in which case
1412/// [`retro_core_options_intl::us`] is used by the frontend). Any items
1413/// missing from this array will be read from [`retro_core_options_intl::us`]
1414/// instead.
1415///
1416/// NOTE: Default core option values are always taken from the
1417/// [`retro_core_options_intl::us`] array. Any default values in
1418/// [`retro_core_options_intl::local`] array will be ignored.
1419#[proc::context(SetEnvironmentContext)]
1420pub unsafe fn set_core_options_intl(
1421 callback: retro_environment_t,
1422 options: retro_core_options_intl,
1423) -> bool {
1424 // const struct retro_core_options_intl *
1425 set(callback, RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, options).unwrap_or(false)
1426}
1427
1428/// Allows an implementation to signal the environment
1429/// which variables it might want to check for later using
1430/// [`get_variable`].
1431///
1432/// This allows the frontend to present these variables to
1433/// a user dynamically.
1434///
1435/// This should only be called if [`get_core_options_version`]
1436/// returns an API version of >= 2.
1437///
1438/// This should be called instead of [`set_variables`].
1439///
1440/// This should be called instead of [`set_core_options`].
1441///
1442/// This should be called instead of [`set_core_options_intl`].
1443///
1444/// This should be called instead of [`set_core_options_v2`].
1445///
1446/// This should be called the first time as early as
1447/// possible (ideally in [`Core::on_set_environment`]).
1448///
1449/// Afterwards it may be called again for the core to communicate
1450/// updated options to the frontend, but the number of core
1451/// options must not change from the number in the initial call.
1452///
1453/// If [`get_core_options_version`] returns an API
1454/// version of `>= 2`, this callback is guaranteed to succeed
1455/// (i.e. callback return value does not indicate success)
1456///
1457/// If callback returns [`true`], frontend has core option category
1458/// support.
1459///
1460/// If callback returns [`false`], frontend does not have core option
1461/// category support.
1462///
1463/// This is fundamentally the same as [`set_core_options_v2`],
1464/// with the addition of localisation support. The description of the
1465/// [`set_core_options_v2`] callback should be consulted
1466/// for further details.
1467///
1468/// 'data' points to a [`retro_core_options_v2_intl`] struct.
1469///
1470/// - [`retro_core_options_v2_intl::us`] is a pointer to a
1471/// [`retro_core_options_v2`] struct defining the US English
1472/// core options implementation. It must point to a valid struct.
1473///
1474/// - [`retro_core_options_v2_intl::local`] is a pointer to a
1475/// [`retro_core_options_v2`] struct defining core options for
1476/// the current frontend language.
1477///
1478/// It may be `NULL` (in which case [`retro_core_options_v2_intl::us`] is used by the frontend).
1479/// Any items missing from this struct will be read from
1480/// [`retro_core_options_v2_intl::us`] instead.
1481///
1482/// NOTE: Default core option values are always taken from the
1483/// [`retro_core_options_v2_intl::us`] struct. Any default values in
1484/// the [`retro_core_options_v2_intl::local`] struct will be ignored.
1485#[proc::context(SetEnvironmentContext)]
1486pub unsafe fn set_core_options_v2_intl(
1487 callback: retro_environment_t,
1488 options: retro_core_options_v2_intl,
1489) -> bool {
1490 // const struct retro_core_options_v2_intl *
1491 set(
1492 callback,
1493 RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL,
1494 options,
1495 )
1496 .unwrap_or(false)
1497}
1498
1499/// Allows an implementation to signal the environment to show
1500/// or hide a variable when displaying core options. This is
1501/// considered a **suggestion**. The frontend is free to ignore
1502/// this callback, and its implementation not considered mandatory.
1503///
1504/// 'data' points to a [`retro_core_option_display`] struct
1505///
1506/// [`retro_core_option_display::key`] is a variable identifier
1507/// which has already been set by [`set_variables`] / [`set_core_options`].
1508///
1509/// [`retro_core_option_display::visible`] is a boolean, specifying
1510/// whether variable should be displayed
1511///
1512/// Note that all core option variables will be set visible by
1513/// default when calling [`set_variables`] / [`set_core_options`].
1514#[proc::context(GenericContext)]
1515pub unsafe fn set_core_options_display(
1516 callback: retro_environment_t,
1517 options: retro_core_option_display,
1518) -> bool {
1519 // struct retro_core_option_display *
1520 set(
1521 callback,
1522 RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY,
1523 options,
1524 )
1525 .unwrap_or(false)
1526}
1527
1528/// Allows an implementation to ask frontend preferred hardware
1529/// context to use. Core should use this information to deal
1530/// with what specific context to request with SET_HW_RENDER.
1531///
1532/// 'data' points to an unsigned variable
1533#[proc::context(GenericContext)]
1534pub unsafe fn get_preferred_hw_render(callback: retro_environment_t) -> u32 {
1535 // unsigned *
1536 get(callback, RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER)
1537 .map(|(v, _)| v)
1538 .unwrap_or(0)
1539}
1540
1541/// Unsigned value is the API version number of the disk control
1542/// interface supported by the frontend. If callback return false,
1543/// API version is assumed to be 0.
1544///
1545/// In legacy code, the disk control interface is defined by passing
1546/// a struct of type [`retro_disk_control_callback] to
1547/// [`set_disk_control_interface`].
1548/// This may be still be done regardless of the disk control
1549/// interface version.
1550///
1551/// If version is >= 1 however, the disk control interface may
1552/// instead be defined by passing a struct of type
1553/// [`retro_disk_control_ext_callback`] to
1554/// [`set_disk_control_ext_interface`].
1555/// This allows the core to provide additional information about
1556/// disk images to the frontend and/or enables extra
1557/// disk control functionality by the frontend.
1558#[proc::context(GenericContext)]
1559pub unsafe fn get_disk_control_interface_version(callback: retro_environment_t) -> u32 {
1560 // unsigned *
1561 get(
1562 callback,
1563 RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION,
1564 )
1565 .map(|(v, _)| v)
1566 .unwrap_or(0)
1567}
1568
1569/// Sets an interface which frontend can use to eject and insert
1570/// disk images, and also obtain information about individual
1571/// disk image files registered by the core.
1572/// This is used for games which consist of multiple images and
1573/// must be manually swapped out by the user (e.g. PSX, floppy disk
1574/// based systems).
1575#[proc::context(GenericContext)]
1576pub unsafe fn set_disk_control_ext_interface(
1577 callback: retro_environment_t,
1578 data: retro_disk_control_ext_callback,
1579) -> bool {
1580 // const struct retro_disk_control_ext_callback *
1581 set(
1582 callback,
1583 RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE,
1584 data,
1585 )
1586 .unwrap_or(false)
1587}
1588
1589/// The returned value is the API version number of the message
1590/// interface supported by the frontend.
1591/// If the underlying callback failed, API version is assumed to be 0.
1592///
1593/// In legacy code, messages may be displayed in an
1594/// implementation-specific manner by passing a struct
1595/// of type retro_message to [`set_message`].
1596/// This may be still be done regardless of the message
1597/// interface version.
1598///
1599/// If version is >= 1 however, messages may instead be
1600/// displayed by calling [`set_message_ext`].
1601/// This allows the core to specify message logging level, priority and
1602/// destination (OSD, logging interface or both).
1603#[proc::context(GenericContext)]
1604pub unsafe fn get_message_interface_version(callback: retro_environment_t) -> u32 {
1605 // unsigned *
1606 get(callback, RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION)
1607 .map(|(v, _)| v)
1608 .unwrap_or(0)
1609}
1610
1611/// Sets a message to be displayed in an implementation-specific
1612/// manner for a certain duration of milliseconds.
1613/// Additionally allows the core to specify message logging level, priority and
1614/// destination (OSD, logging interface or both).
1615/// Should not be used for trivial messages, which should simply be
1616/// logged via [`RETRO_ENVIRONMENT_GET_LOG_INTERFACE`] (or as a fallback, stderr).
1617#[allow(clippy::too_many_arguments)]
1618#[proc::context(GenericContext)]
1619pub unsafe fn set_message_ext(
1620 callback: retro_environment_t,
1621 message: &str,
1622 duration: u32,
1623 priority: u32,
1624 level: retro_log_level,
1625 target: retro_message_target,
1626 type_: retro_message_type,
1627 progress: MessageProgress,
1628) -> bool {
1629 let msg = match CString::new(message) {
1630 Ok(message) => message,
1631 Err(err) => {
1632 #[cfg(feature = "log")]
1633 log::error!("{}", err);
1634
1635 return false;
1636 }
1637 };
1638
1639 // const struct retro_message_ext *
1640 set(
1641 callback,
1642 RETRO_ENVIRONMENT_SET_MESSAGE_EXT,
1643 retro_message_ext {
1644 msg: msg.as_ptr(),
1645 duration,
1646 priority,
1647 level,
1648 target,
1649 type_,
1650 progress: progress.as_i8(),
1651 },
1652 )
1653 .unwrap_or(false)
1654}
1655
1656/// The first returned value is the number of active input devices
1657/// provided by the frontend. This may change between
1658/// frames, but will remain constant for the duration
1659/// of each frame.
1660///
1661/// If the second return value is [`true`], a core does not need to
1662/// poll any input device with an index greater than or equal to
1663/// the number of active devices.
1664///
1665/// If the second return value is [`false`], the number of active input
1666/// devices is unknown. In this case, all input devices
1667/// should be considered active.
1668#[proc::context(GenericContext)]
1669pub unsafe fn get_input_max_users(callback: retro_environment_t) -> (u32, bool) {
1670 // unsigned *
1671 get(callback, RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS).unwrap_or((0, false))
1672}
1673
1674/// Lets the core know the occupancy level of the frontend
1675/// audio buffer. Can be used by a core to attempt frame
1676/// skipping in order to avoid buffer under-runs.
1677/// A core may pass `NULL` to disable buffer status reporting
1678/// in the frontend.
1679#[proc::context(GenericContext)]
1680pub unsafe fn set_audio_buffer_status_callback(
1681 callback: retro_environment_t,
1682 data: retro_audio_buffer_status_callback,
1683) -> bool {
1684 // const struct retro_audio_buffer_status_callback *
1685 set(
1686 callback,
1687 RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK,
1688 data,
1689 )
1690 .unwrap_or(false)
1691}
1692
1693/// Sets minimum frontend audio latency in milliseconds.
1694/// Resultant audio latency may be larger than set value,
1695/// or smaller if a hardware limit is encountered. A frontend
1696/// is expected to honour requests up to 512 ms.
1697///
1698/// * If value is less than current frontend
1699/// audio latency, callback has no effect
1700/// * If value is zero, default frontend audio
1701/// latency is set
1702///
1703/// May be used by a core to increase audio latency and
1704/// therefore decrease the probability of buffer under-runs
1705/// (crackling) when performing 'intensive' operations.
1706/// A core utilising [`RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK`]
1707/// to implement audio-buffer-based frame skipping may achieve
1708/// optimal results by setting the audio latency to a 'high'
1709/// (typically 6x or 8x) integer multiple of the expected
1710/// frame time.
1711///
1712/// Calling this can require a full reinitialization of audio
1713/// drivers in the frontend, so it is important to call it very
1714/// sparingly, and usually only with the users explicit consent.
1715/// An eventual driver reinitialize will happen so that audio
1716/// callbacks happening after this call within the same [`Core::on_run`]
1717/// call will target the newly initialized driver.
1718#[proc::context(RunContext)]
1719pub unsafe fn set_minimum_audio_latency(callback: retro_environment_t, latency: u32) -> bool {
1720 // const unsigned *
1721 set(
1722 callback,
1723 RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY,
1724 latency,
1725 )
1726 .unwrap_or(false)
1727}
1728
1729/// Checks whether the frontend supports the [`set_fastforwarding_override`] interface.
1730#[proc::context(GenericContext)]
1731pub unsafe fn supports_fastforwarding_override(callback: retro_environment_t) -> bool {
1732 // const struct retro_fastforwarding_override *
1733 set_ptr(
1734 callback,
1735 RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE,
1736 std::ptr::null() as *const c_void,
1737 )
1738 .unwrap_or(false)
1739}
1740
1741/// Used by a libretro core to override the current
1742/// fastforwarding mode of the frontend.
1743#[proc::context(GenericContext)]
1744pub unsafe fn set_fastforwarding_override(
1745 callback: retro_environment_t,
1746 value: retro_fastforwarding_override,
1747) -> bool {
1748 // const struct retro_fastforwarding_override *
1749 set(
1750 callback,
1751 RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE,
1752 value,
1753 )
1754 .unwrap_or(false)
1755}
1756
1757/// Allows an implementation to override 'global' content
1758/// info parameters reported by [`Core::get_info`].
1759/// Overrides also affect subsystem content info parameters
1760/// set via [`set_subsystem_info`].
1761/// This function must be called inside [`Core::on_set_environment`].
1762/// If callback returns [`false`], content info overrides
1763/// are unsupported by the frontend, and will be ignored.
1764/// If callback returns [`true`], extended game info may be
1765/// retrieved by calling [`get_game_info_ext`]
1766/// in [`Core::on_load_game`] or [`Core::on_load_game_special`].
1767///
1768/// 'data' points to an array of [`retro_system_content_info_override`]
1769/// structs terminated by a `{ NULL, false, false }` element.
1770/// If 'data' is `NULL`, no changes will be made to the frontend;
1771/// a core may therefore pass `NULL` in order to test whether
1772/// the [`set_content_info_override`] and
1773/// [`get_game_info_ext`] callbacks are supported
1774/// by the frontend.
1775///
1776/// For struct member descriptions, see the definition of
1777/// struct [`retro_system_content_info_override`].
1778///
1779/// Example:
1780///
1781/// - struct retro_system_info:
1782/// ```c
1783/// {
1784/// "My Core", // library_name
1785/// "v1.0", // library_version
1786/// "m3u|md|cue|iso|chd|sms|gg|sg", // valid_extensions
1787/// true, // need_fullpath
1788/// false // block_extract
1789/// }
1790/// ```
1791///
1792/// - Array of struct retro_system_content_info_override:
1793/// ```c
1794/// {
1795/// {
1796/// "md|sms|gg", // extensions
1797/// false, // need_fullpath
1798/// true // persistent_data
1799/// },
1800/// {
1801/// "sg", // extensions
1802/// false, // need_fullpath
1803/// false // persistent_data
1804/// },
1805/// { NULL, false, false }
1806/// }
1807/// ```
1808///
1809/// Result:
1810/// - Files of type `m3u`, `cue`, `iso`, `chd` will not be
1811/// loaded by the frontend. Frontend will pass a
1812/// valid path to the core, and core will handle
1813/// loading internally
1814/// - Files of type `md`, `sms`, `gg` will be loaded by
1815/// the frontend. A valid memory buffer will be
1816/// passed to the core. This memory buffer will
1817/// remain valid until [`Core::on_deinit`] returns
1818/// - Files of type `sg` will be loaded by the frontend.
1819/// A valid memory buffer will be passed to the core.
1820/// This memory buffer will remain valid until
1821/// [`Core::on_load_game`] (or [`Core::on_load_game_special`])
1822/// returns
1823///
1824/// NOTE: If an extension is listed multiple times in
1825/// an array of [`retro_system_content_info_override`]
1826/// structs, only the **first** instance will be registered
1827#[proc::context(SetEnvironmentContext)]
1828pub unsafe fn set_content_info_override(
1829 callback: retro_environment_t,
1830 value: retro_system_content_info_override,
1831) -> bool {
1832 // const struct retro_system_content_info_override *
1833 set(callback, RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE, value).unwrap_or(false)
1834}
1835
1836/// Allows an implementation to fetch extended game
1837/// information, providing additional content path
1838/// and memory buffer status details.
1839/// This function may only be called inside
1840/// [`Core::on_load_game`] or [`Core::on_load_game_special`].
1841///
1842/// If callback returns `false`, extended game information
1843/// is unsupported by the frontend. In this case, only
1844/// regular [`retro_game_info`] will be available.
1845/// [`get_game_info_ext`] is guaranteed
1846/// to return true if [`set_content_info_override`]
1847/// returns [`true`].
1848///
1849/// 'data' points to an array of [`retro_game_info_ext structs`].
1850///
1851/// For struct member descriptions, see the definition of
1852/// struct [`retro_game_info_ext`].
1853///
1854/// - If function is called inside [`Core::on_load_game`],
1855/// the [`retro_game_info_ext`] array is guaranteed to
1856/// have a size of 1 - i.e. the returned pointer may
1857/// be used to access directly the members of the
1858/// first [`retro_game_info_ext`] struct, for example:
1859///
1860/// ```c
1861/// struct retro_game_info_ext *game_info_ext;
1862/// if (environ_cb(RETRO_ENVIRONMENT_GET_GAME_INFO_EXT, &game_info_ext))
1863/// printf("Content Directory: %s\n", game_info_ext->dir);
1864///```
1865///
1866/// - If the function is called inside [`Core::on_load_game_special`],
1867/// the [`retro_game_info_ext`] array is guaranteed to have a
1868/// size equal to the `num_info` argument passed to
1869/// [`Core::on_load_game_special`]
1870#[proc::context(LoadGameContext)]
1871#[proc::context(LoadGameSpecialContext)]
1872pub unsafe fn get_game_info_ext(callback: retro_environment_t) -> Option<retro_game_info_ext> {
1873 // const struct retro_game_info_ext **
1874 if let Some((v, true)) = get_unchecked(callback, RETRO_ENVIRONMENT_GET_GAME_INFO_EXT) {
1875 Some(v)
1876 } else {
1877 None
1878 }
1879}
1880
1881/// Allows a frontend to signal that a core must update
1882/// the visibility of any dynamically hidden core options,
1883/// and enables the frontend to detect visibility changes.
1884///
1885/// Used by the frontend to update the menu display status
1886/// of core options without requiring a call of [`Core::on_run`].
1887/// Must be called in [`Core::on_set_environment`].
1888#[proc::context(SetEnvironmentContext)]
1889pub unsafe fn set_core_options_update_display_callback(
1890 callback: retro_environment_t,
1891 data: retro_core_options_update_display_callback,
1892) -> bool {
1893 // const struct retro_core_options_update_display_callback *
1894 set(
1895 callback,
1896 RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK,
1897 data,
1898 )
1899 .unwrap_or(false)
1900}
1901
1902/// Allows an implementation to notify the frontend
1903/// that a core option value has changed.
1904///
1905/// [`retro_variable::key`] and [`retro_variable::value`]
1906/// must match strings that have been set previously
1907/// via one of the following:
1908///
1909/// - [`set_variables`]
1910/// - [`set_core_options`]
1911/// - [`set_core_options_intl`]
1912/// - [`set_core_options_v2`]
1913/// - [`set_core_options_v2_intl`]
1914///
1915/// After changing a core option value via this
1916/// callback, [`get_variable_update`]
1917/// will return [`true`].
1918///
1919/// If data is `NULL`, no changes will be registered
1920/// and the callback will return [`true`]; an
1921/// implementation may therefore pass `NULL` in order
1922/// to test whether the callback is supported.
1923#[proc::context(GenericContext)]
1924pub unsafe fn set_variable(callback: retro_environment_t, value: retro_variable) -> bool {
1925 // const struct retro_variable *
1926 set(callback, RETRO_ENVIRONMENT_SET_VARIABLE, value).unwrap_or(false)
1927}
1928
1929/// Allows an implementation to get details on the actual rate
1930/// the frontend is attempting to call [`Core::on_run`].
1931#[proc::context(GenericContext)]
1932#[proc::unstable(feature = "env-commands")]
1933pub unsafe fn get_throttle_state(callback: retro_environment_t) -> Option<retro_throttle_state> {
1934 // struct retro_throttle_state *
1935 get_unchecked(callback, RETRO_ENVIRONMENT_GET_THROTTLE_STATE).map(|(v, _)| v)
1936}
1937
1938/// Tells the core about the context the frontend is asking for savestate.
1939// See [`retro_savestate_context`]
1940#[proc::context(GenericContext)]
1941#[proc::unstable(feature = "env-commands")]
1942pub unsafe fn get_savestate_context(
1943 callback: retro_environment_t,
1944) -> Option<retro_savestate_context> {
1945 // int *
1946
1947 if let Some((value, _)) =
1948 get::<retro_savestate_context_REPR_TYPE>(callback, RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT)
1949 {
1950 return retro_savestate_context::try_from(value).ok();
1951 }
1952
1953 None
1954}