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}