rust_libretro/
core_wrapper.rs

1//! The [`CoreWrapper`] is an _internal_ data structure.
2//!
3//! It stores runtime information provided by the libretro frontend without interfering with your [`Core`] implementation.
4use crate::*;
5use std::sync::{Arc, RwLock};
6
7pub type Interfaces = Arc<RwLock<InterfaceList>>;
8
9#[derive(Debug, Default)]
10#[proc::unstable]
11pub struct InterfaceList {
12    pub location_interface: Option<retro_location_callback>,
13    pub perf_interface: PerfCounters,
14    pub rumble_interface: Option<retro_rumble_interface>,
15
16    #[unstable(feature = "env-commands")]
17    pub camera_interface: Option<retro_camera_callback>,
18
19    #[unstable(feature = "env-commands")]
20    pub led_interface: Option<retro_led_interface>,
21
22    #[unstable(feature = "env-commands")]
23    pub sensor_interface: Option<retro_sensor_interface>,
24
25    #[unstable(feature = "env-commands")]
26    pub midi_interface: Option<retro_midi_interface>,
27
28    #[unstable(feature = "env-commands")]
29    pub vfs_interface_info: VfsInterfaceInfo,
30
31    #[unstable(feature = "env-commands")]
32    pub hw_render_context_negotiation_interface:
33        Option<Box<dyn HwRenderContextNegotiationInterface>>,
34}
35
36/// Holds the core instance as well as runtime information from the libretro frontend.
37///
38/// This struct gets used in the code generated by the [`retro_core!()`]-macro.
39pub(crate) struct CoreWrapper {
40    pub(crate) environment_set: bool,
41    pub(crate) environment_callback: retro_environment_t,
42
43    /// Render a frame. Pixel format is 15-bit `0RGB1555` native endian
44    /// unless changed (see [`RETRO_ENVIRONMENT_SET_PIXEL_FORMAT`]).
45    ///
46    /// Width and height specify dimensions of buffer.
47    /// Pitch specifices length in bytes between two lines in buffer.
48    ///
49    /// For performance reasons, it is highly recommended to have a frame
50    /// that is packed in memory, i.e. `pitch == width * byte_per_pixel`.
51    /// Certain graphic APIs, such as OpenGL ES, do not like textures
52    /// that are not packed in memory.
53    pub(crate) video_refresh_callback: retro_video_refresh_t,
54
55    /// Renders a single audio frame. Should only be used if implementation
56    /// generates a single sample at a time.
57    /// Format is signed 16-bit native endian.
58    pub(crate) audio_sample_callback: retro_audio_sample_t,
59
60    /// Renders multiple audio frames in one go.
61    ///
62    /// One frame is defined as a sample of left and right channels, interleaved.
63    /// I.e. `int16_t buf[4] = { l, r, l, r };` would be 2 frames.
64    /// Only one of the audio callbacks must ever be used.
65    pub(crate) audio_sample_batch_callback: retro_audio_sample_batch_t,
66
67    /// Polls input.
68    pub(crate) input_poll_callback: retro_input_poll_t,
69
70    /// Queries for input for player `port`. device will be masked with
71    /// [`RETRO_DEVICE_MASK`].
72    ///
73    /// Specialization of devices such as `RETRO_DEVICE_JOYPAD_MULTITAP` that
74    /// have been set with [`Core::on_set_controller_port_device`]
75    /// will still use the higher level [`RETRO_DEVICE_JOYPAD`] to request input.
76    pub(crate) input_state_callback: retro_input_state_t,
77
78    pub(crate) can_dupe: bool,
79    pub(crate) had_frame: bool,
80    pub(crate) last_width: u32,
81    pub(crate) last_height: u32,
82    pub(crate) last_pitch: usize,
83
84    pub(crate) supports_bitmasks: bool,
85
86    pub(crate) frame_delta: Option<i64>,
87
88    pub(crate) interfaces: Interfaces,
89
90    /// The wrapped [`Core`] implementation.
91    pub(crate) core: Box<dyn Core>,
92}
93
94impl CoreWrapper {
95    pub(crate) fn new<C: 'static + Core>(core: C) -> Self {
96        Self {
97            environment_set: false,
98            environment_callback: None,
99
100            core: Box::new(core),
101
102            // Callbacks
103            video_refresh_callback: None,
104            audio_sample_callback: None,
105            audio_sample_batch_callback: None,
106            input_poll_callback: None,
107            input_state_callback: None,
108
109            interfaces: Arc::new(RwLock::new(InterfaceList::default())),
110
111            can_dupe: false,
112            had_frame: false,
113            last_width: 0,
114            last_height: 0,
115            last_pitch: 0,
116
117            frame_delta: None,
118
119            supports_bitmasks: false,
120        }
121    }
122
123    #[inline(always)]
124    pub(crate) fn on_set_video_refresh(&mut self, arg1: retro_video_refresh_t) {
125        self.video_refresh_callback = arg1;
126    }
127
128    #[inline(always)]
129    pub(crate) fn on_set_audio_sample(&mut self, arg1: retro_audio_sample_t) {
130        self.audio_sample_callback = arg1;
131    }
132
133    #[inline(always)]
134    pub(crate) fn on_set_audio_sample_batch(&mut self, arg1: retro_audio_sample_batch_t) {
135        self.audio_sample_batch_callback = arg1;
136    }
137
138    #[inline(always)]
139    pub(crate) fn on_set_input_poll(&mut self, arg1: retro_input_poll_t) {
140        self.input_poll_callback = arg1;
141    }
142
143    #[inline(always)]
144    pub(crate) fn on_set_input_state(&mut self, arg1: retro_input_state_t) {
145        self.input_state_callback = arg1;
146    }
147}