rust_libretro/
core.rs

1//! Provides the [`Core`] and [`CoreOptions`] traits.
2use crate::*;
3
4/// This trait defines the [`set_core_options`](CoreOptions::set_core_options) function.
5pub trait CoreOptions {
6    /// Used to tell the frontend any options / settings your core supports.
7    /// This can be done by using either of the following functions:
8    /// - [`SetEnvironmentContext::set_core_options_v2`]
9    /// - [`SetEnvironmentContext::set_core_options_v2_intl`]
10    /// - [`SetEnvironmentContext::set_core_options`]
11    /// - [`SetEnvironmentContext::set_core_options_intl`]
12    /// - [`SetEnvironmentContext::set_variables`]
13    fn set_core_options(&self, _ctx: &SetEnvironmentContext) -> bool {
14        true
15    }
16}
17
18/// This trait defines the basic functions that every libretro core must implement.
19/// See also [`retro_core!()`].
20pub trait Core: CoreOptions {
21    /// Returns static info about this core.
22    fn get_info(&self) -> SystemInfo;
23
24    /// Called when the frontend needs information about the
25    /// audio and video timings and the video geometry.
26    fn on_get_av_info(&mut self, _ctx: &mut GetAvInfoContext) -> retro_system_av_info;
27
28    /// Called when the frontend set a new environment callback.
29    ///
30    /// Guaranteed to be called before [`Core::on_init`].
31    fn on_set_environment(&mut self, _initial: bool, _ctx: &mut SetEnvironmentContext) {
32        // Do nothing
33    }
34
35    /// Called when the libretro API has been initialized.
36    fn on_init(&mut self, _ctx: &mut InitContext) {
37        // Do nothing
38    }
39
40    /// Called when the libretro API gets destucted.
41    fn on_deinit(&mut self, _ctx: &mut DeinitContext) {
42        // Do nothing
43    }
44
45    /// **TODO:** Documentation
46    fn on_set_controller_port_device(
47        &mut self,
48        _port: u32,
49        _device: u32,
50        _ctx: &mut GenericContext,
51    ) {
52        // Do nothing
53    }
54
55    /// Called when the frontend requests resetting the system.
56    fn on_reset(&mut self, _ctx: &mut ResetContext) {
57        // Do nothing
58    }
59
60    /// Called once per frame
61    ///
62    /// If a frame is not rendered for reasons where a game "dropped" a frame,
63    /// this still counts as a frame, and [`Core::on_run`] should explicitly dupe
64    /// a frame if [`environment::can_dupe`] returns [`true`].
65    /// In this case, the video callback can take a NULL argument for data.
66    fn on_run(&mut self, _ctx: &mut RunContext, _delta_us: Option<i64>) {
67        // Do nothing
68    }
69
70    /// Returns the amount of data the implementation requires to serialize
71    /// internal state (save states).
72    ///
73    /// Between calls to [`Core::on_load_game`] and [`Core::on_unload_game`], the
74    /// returned size is never allowed to be larger than a previous returned
75    /// value, to ensure that the frontend can allocate a save state buffer once.
76    fn get_serialize_size(&mut self, _ctx: &mut GetSerializeSizeContext) -> usize {
77        // Tell the frontend that we don’t support serialization
78        0
79    }
80
81    /// Serializes internal state. If failed, or size is lower than
82    /// [`Core::get_serialize_size`], it should return [`false`], [`true'] otherwise.
83    fn on_serialize(&mut self, _slice: &mut [u8], _ctx: &mut SerializeContext) -> bool {
84        // Tell the frontend that we don’t support serialization
85        false
86    }
87
88    /// Deserializes internal state.
89    ///
90    /// **TODO:** Documentation
91    fn on_unserialize(&mut self, _slice: &mut [u8], _ctx: &mut UnserializeContext) -> bool {
92        // Tell the frontend that we don’t support serialization
93        false
94    }
95
96    /// Called when a game should be loaded.
97    /// Return [`true`] to indicate successful loading and [`false`] to indicate load failure.
98    fn on_load_game(
99        &mut self,
100        _game: Option<retro_game_info>,
101        _ctx: &mut LoadGameContext,
102    ) -> Result<(), Box<dyn std::error::Error>> {
103        // By default we pretend that loading was successful
104        Ok(())
105    }
106
107    /// Loads a "special" kind of game. Should not be used, except in extreme cases.
108    ///
109    /// **TODO:** Better documentation. What’s a “special” game?
110    fn on_load_game_special(
111        &mut self,
112        _game_type: std::os::raw::c_uint,
113        _info: *const retro_game_info,
114        _num_info: usize,
115        _ctx: &mut LoadGameSpecialContext,
116    ) -> Result<(), Box<dyn std::error::Error>> {
117        Err("on_load_game_special is not implemented".into())
118    }
119
120    /// Called when the currently loaded game should be unloaded.
121    /// Called before [`Core::on_deinit`].
122    fn on_unload_game(&mut self, _ctx: &mut UnloadGameContext) {
123        // Do nothing
124    }
125
126    /// Instructs the core to remove all applied cheats.
127    fn on_cheat_reset(&mut self, _ctx: &mut CheatResetContext) {
128        // Do nothing
129    }
130
131    /// **TODO:** Documentation
132    fn on_cheat_set(
133        &mut self,
134        _index: std::os::raw::c_uint,
135        _enabled: bool,
136        _code: &CStr,
137        _ctx: &mut CheatSetContext,
138    ) {
139        // Do nothing
140    }
141
142    /// Gets the region of the game.
143    ///
144    /// Can be any of:
145    /// - [`RETRO_REGION_NTSC`]
146    /// - [`RETRO_REGION_PAL`]
147    fn on_get_region(&mut self, _ctx: &mut GetRegionContext) -> std::os::raw::c_uint {
148        RETRO_REGION_NTSC
149    }
150
151    /// **TODO:** Documentation
152    fn get_memory_data(
153        &mut self,
154        _id: std::os::raw::c_uint,
155        _ctx: &mut GetMemoryDataContext,
156    ) -> *mut std::os::raw::c_void {
157        // Tell the frontend that we don’t support direct memory access
158        std::ptr::null_mut()
159    }
160
161    /// **TODO:** Documentation
162    fn get_memory_size(
163        &mut self,
164        _id: std::os::raw::c_uint,
165        _ctx: &mut GetMemorySizeContext,
166    ) -> usize {
167        // Tell the frontend that we don’t support direct memory access
168        0
169    }
170
171    /// Gets called when the core options have been changed.
172    ///
173    /// Options get checked before [`Core::on_load_game`], [`Core::on_load_game_special`] and before each call of [`Core::on_run`].
174    fn on_options_changed(&mut self, _ctx: &mut OptionsChangedContext) {
175        // Do nothing
176    }
177
178    /// **TODO:** Documentation
179    fn on_keyboard_event(
180        &mut self,
181        _down: bool,
182        _keycode: retro_key,
183        _character: u32,
184        _key_modifiers: retro_mod,
185    ) {
186        // Do nothing
187    }
188
189    /// Called when the frontend needs more audio frames
190    fn on_write_audio(&mut self, _ctx: &mut AudioContext) {
191        // Do nothing
192    }
193
194    /// **TODO:** Documentation
195    fn on_audio_set_state(&mut self, _enabled: bool) {
196        // Do nothing
197    }
198
199    /// **TODO:** Documentation
200    fn on_audio_buffer_status(&mut self, _active: bool, _occupancy: u32, _underrun_likely: bool) {
201        // Do nothing
202    }
203
204    /// **TODO:** Documentation
205    fn on_hw_context_reset(&mut self, _ctx: &mut GenericContext) {
206        // Do nothing
207    }
208
209    /// **TODO:** Documentation
210    fn on_hw_context_destroyed(&mut self, _ctx: &mut GenericContext) {
211        // Do nothing
212    }
213
214    /// **TODO:** Documentation
215    fn on_get_proc_address(&mut self, _symbol_name: &CStr) -> retro_proc_address_t {
216        None
217    }
218
219    /// **TODO:** Documentation
220    fn on_location_lifetime_status_initialized(&mut self, _ctx: &mut GenericContext) {
221        // Do nothing
222    }
223
224    /// **TODO:** Documentation
225    fn on_location_lifetime_status_deinitialized(&mut self, _ctx: &mut GenericContext) {
226        // Do nothing
227    }
228
229    /// **TODO:** Documentation
230    fn on_camera_initialized(&mut self, _ctx: &mut GenericContext) {
231        // Do nothing
232    }
233
234    /// **TODO:** Documentation
235    fn on_camera_deinitialized(&mut self, _ctx: &mut GenericContext) {
236        // Do nothing
237    }
238
239    /// **TODO:** Documentation
240    fn on_camera_raw_framebuffer(
241        &mut self,
242        _buffer: &[u32],
243        _width: u32,
244        _height: u32,
245        _pitch: usize,
246    ) {
247        // Do nothing
248    }
249
250    /// **TODO:** Documentation
251    fn on_camera_gl_texture(
252        &mut self,
253        _texture_id: u32,
254        _texture_target: u32,
255        _affine_matrix: &[f32; 3 * 3],
256    ) {
257        // Do nothing
258    }
259
260    /// **TODO:** Documentation
261    fn on_set_eject_state(&mut self, _ejected: bool) -> bool {
262        false
263    }
264
265    /// **TODO:** Documentation
266    fn on_get_eject_state(&mut self) -> bool {
267        false
268    }
269
270    /// **TODO:** Documentation
271    fn on_get_image_index(&mut self) -> u32 {
272        0
273    }
274
275    /// **TODO:** Documentation
276    fn on_set_image_index(&mut self, _index: u32) -> bool {
277        false
278    }
279
280    /// **TODO:** Documentation
281    fn on_get_num_images(&mut self) -> u32 {
282        0
283    }
284
285    /// **TODO:** Documentation
286    fn on_replace_image_index(&mut self, _index: u32, _info: *const retro_game_info) -> bool {
287        false
288    }
289
290    /// **TODO:** Documentation
291    fn on_add_image_index(&mut self) -> bool {
292        false
293    }
294
295    /// **TODO:** Documentation
296    fn on_set_initial_image(&mut self, _index: u32, _path: &CStr) -> bool {
297        false
298    }
299
300    /// **TODO:** Documentation
301    fn on_get_image_path(&mut self, _index: u32) -> Option<CString> {
302        None
303    }
304
305    /// **TODO:** Documentation
306    fn on_get_image_label(&mut self, _index: u32) -> Option<CString> {
307        None
308    }
309
310    /// **TODO:** Documentation
311    fn on_core_options_update_display(&mut self) -> bool {
312        false
313    }
314}