PANDORA: Make GLES context compatible with latest driver (FB only, no X11)
[mupen64plus-pandora.git] / source / mupen64plus-core / src / api / frontend.c
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus-core - api/frontend.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2012 CasualJames *
5 * Copyright (C) 2009 Richard Goedeken *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
21 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
22
23/* This file contains the Core front-end functions which will be exported
24 * outside of the core library.
25 */
26
27#include <stdlib.h>
28#include <string.h>
29#include <stdio.h>
30#include <SDL.h>
31
32#define M64P_CORE_PROTOTYPES 1
33#include "m64p_types.h"
34#include "callbacks.h"
35#include "m64p_config.h"
36#include "m64p_frontend.h"
37#include "config.h"
38#include "vidext.h"
39
40#include "main/cheat.h"
41#include "main/eventloop.h"
42#include "main/main.h"
43#include "main/rom.h"
44#include "main/savestates.h"
45#include "main/version.h"
46#include "main/util.h"
47#include "main/workqueue.h"
48#include "osd/screenshot.h"
49#include "plugin/plugin.h"
50
51/* some local state variables */
52static int l_CoreInit = 0;
53static int l_ROMOpen = 0;
54
55/* functions exported outside of libmupen64plus to front-end application */
56EXPORT m64p_error CALL CoreStartup(int APIVersion, const char *ConfigPath, const char *DataPath, void *Context,
57 void (*DebugCallback)(void *, int, const char *), void *Context2,
58 void (*StateCallback)(void *, m64p_core_param, int))
59{
60 if (l_CoreInit)
61 return M64ERR_ALREADY_INIT;
62
63 /* very first thing is to set the callback functions for debug info and state changing*/
64 SetDebugCallback(DebugCallback, Context);
65 SetStateCallback(StateCallback, Context2);
66
67 /* check front-end's API version */
68 if ((APIVersion & 0xffff0000) != (FRONTEND_API_VERSION & 0xffff0000))
69 {
70 DebugMessage(M64MSG_ERROR, "CoreStartup(): Front-end (API version %i.%i.%i) is incompatible with this core (API %i.%i.%i)",
71 VERSION_PRINTF_SPLIT(APIVersion), VERSION_PRINTF_SPLIT(FRONTEND_API_VERSION));
72 return M64ERR_INCOMPATIBLE;
73 }
74
75 /* set up the default (dummy) plugins */
76 plugin_connect(M64PLUGIN_GFX, NULL);
77 plugin_connect(M64PLUGIN_AUDIO, NULL);
78 plugin_connect(M64PLUGIN_INPUT, NULL);
79 plugin_connect(M64PLUGIN_CORE, NULL);
80
81 savestates_init();
82
83 /* next, start up the configuration handling code by loading and parsing the config file */
84 if (ConfigInit(ConfigPath, DataPath) != M64ERR_SUCCESS)
85 return M64ERR_INTERNAL;
86
87 /* set default configuration parameter values for Core */
88 if (ConfigOpenSection("Core", &g_CoreConfig) != M64ERR_SUCCESS || g_CoreConfig == NULL)
89 return M64ERR_INTERNAL;
90
91 if (!main_set_core_defaults())
92 return M64ERR_INTERNAL;
93
94 /* The ROM database contains MD5 hashes, goodnames, and some game-specific parameters */
95 romdatabase_open();
96
97 workqueue_init();
98
99 l_CoreInit = 1;
100 return M64ERR_SUCCESS;
101}
102
103EXPORT m64p_error CALL CoreShutdown(void)
104{
105 if (!l_CoreInit)
106 return M64ERR_NOT_INIT;
107
108 /* close down some core sub-systems */
109 romdatabase_close();
110 ConfigShutdown();
111 workqueue_shutdown();
112 savestates_deinit();
113
114 /* tell SDL to shut down */
115 SDL_Quit();
116
117 l_CoreInit = 0;
118 return M64ERR_SUCCESS;
119}
120
121EXPORT m64p_error CALL CoreAttachPlugin(m64p_plugin_type PluginType, m64p_dynlib_handle PluginLibHandle)
122{
123 m64p_error rval;
124
125 if (!l_CoreInit)
126 return M64ERR_NOT_INIT;
127 if (g_EmulatorRunning || !l_ROMOpen)
128 return M64ERR_INVALID_STATE;
129
130 rval = plugin_connect(PluginType, PluginLibHandle);
131 if (rval != M64ERR_SUCCESS)
132 return rval;
133
134 rval = plugin_start(PluginType);
135 if (rval != M64ERR_SUCCESS)
136 return rval;
137
138 return M64ERR_SUCCESS;
139}
140
141EXPORT m64p_error CALL CoreDetachPlugin(m64p_plugin_type PluginType)
142{
143 if (!l_CoreInit)
144 return M64ERR_NOT_INIT;
145 if (g_EmulatorRunning)
146 return M64ERR_INVALID_STATE;
147
148 return plugin_connect(PluginType, NULL);
149}
150
151EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *ParamPtr)
152{
153 m64p_error rval;
154 int keysym, keymod;
155
156 if (!l_CoreInit)
157 return M64ERR_NOT_INIT;
158
159 switch(Command)
160 {
161 case M64CMD_NOP:
162 return M64ERR_SUCCESS;
163 case M64CMD_ROM_OPEN:
164 if (g_EmulatorRunning || l_ROMOpen)
165 return M64ERR_INVALID_STATE;
166 if (ParamPtr == NULL || ParamInt < 4096)
167 return M64ERR_INPUT_ASSERT;
168 rval = open_rom((const unsigned char *) ParamPtr, ParamInt);
169 if (rval == M64ERR_SUCCESS)
170 {
171 l_ROMOpen = 1;
172 ScreenshotRomOpen();
173 cheat_init();
174 }
175 return rval;
176 case M64CMD_ROM_CLOSE:
177 if (g_EmulatorRunning || !l_ROMOpen)
178 return M64ERR_INVALID_STATE;
179 l_ROMOpen = 0;
180 cheat_delete_all();
181 cheat_uninit();
182 return close_rom();
183 case M64CMD_ROM_GET_HEADER:
184 if (!l_ROMOpen)
185 return M64ERR_INVALID_STATE;
186 if (ParamPtr == NULL)
187 return M64ERR_INPUT_ASSERT;
188 if (sizeof(m64p_rom_header) < ParamInt)
189 ParamInt = sizeof(m64p_rom_header);
190 memcpy(ParamPtr, &ROM_HEADER, ParamInt);
191 // Mupen64Plus used to keep a m64p_rom_header with a clean ROM name
192 // Keep returning a clean ROM name for backwards compatibility
193 if (ParamInt >= 0x20)
194 {
195 int size = (ParamInt >= 0x20 + 20) ? 20 : (ParamInt - 0x20);
196 memcpy((char *)ParamPtr + 0x20, ROM_PARAMS.headername, size);
197 }
198 return M64ERR_SUCCESS;
199 case M64CMD_ROM_GET_SETTINGS:
200 if (!l_ROMOpen)
201 return M64ERR_INVALID_STATE;
202 if (ParamPtr == NULL)
203 return M64ERR_INPUT_ASSERT;
204 if (sizeof(m64p_rom_settings) < ParamInt)
205 ParamInt = sizeof(m64p_rom_settings);
206 memcpy(ParamPtr, &ROM_SETTINGS, ParamInt);
207 return M64ERR_SUCCESS;
208 case M64CMD_EXECUTE:
209 if (g_EmulatorRunning || !l_ROMOpen)
210 return M64ERR_INVALID_STATE;
211 /* print out plugin-related warning messages */
212 plugin_check();
213 /* the main_run() function will not return until the player has quit the game */
214 rval = main_run();
215 return rval;
216 case M64CMD_STOP:
217 if (!g_EmulatorRunning)
218 return M64ERR_INVALID_STATE;
219 /* this stop function is asynchronous. The emulator may not terminate until later */
220 return main_core_state_set(M64CORE_EMU_STATE, M64EMU_STOPPED);
221 case M64CMD_PAUSE:
222 if (!g_EmulatorRunning)
223 return M64ERR_INVALID_STATE;
224 return main_core_state_set(M64CORE_EMU_STATE, M64EMU_PAUSED);
225 case M64CMD_RESUME:
226 if (!g_EmulatorRunning)
227 return M64ERR_INVALID_STATE;
228 return main_core_state_set(M64CORE_EMU_STATE, M64EMU_RUNNING);
229 case M64CMD_CORE_STATE_QUERY:
230 if (ParamPtr == NULL)
231 return M64ERR_INPUT_ASSERT;
232 return main_core_state_query((m64p_core_param) ParamInt, (int *) ParamPtr);
233 case M64CMD_CORE_STATE_SET:
234 if (ParamPtr == NULL)
235 return M64ERR_INPUT_ASSERT;
236 return main_core_state_set((m64p_core_param) ParamInt, *((int *)ParamPtr));
237 case M64CMD_STATE_LOAD:
238 if (!g_EmulatorRunning)
239 return M64ERR_INVALID_STATE;
240 main_state_load((char *) ParamPtr);
241 return M64ERR_SUCCESS;
242 case M64CMD_STATE_SAVE:
243 if (!g_EmulatorRunning)
244 return M64ERR_INVALID_STATE;
245 if (ParamPtr != NULL && (ParamInt < 1 || ParamInt > 3))
246 return M64ERR_INPUT_INVALID;
247 main_state_save(ParamInt, (char *) ParamPtr);
248 return M64ERR_SUCCESS;
249 case M64CMD_STATE_SET_SLOT:
250 if (ParamInt < 0 || ParamInt > 9)
251 return M64ERR_INPUT_INVALID;
252 return main_core_state_set(M64CORE_SAVESTATE_SLOT, ParamInt);
253 case M64CMD_SEND_SDL_KEYDOWN:
254 if (!g_EmulatorRunning)
255 return M64ERR_INVALID_STATE;
256 keysym = ParamInt & 0xffff;
257 keymod = (ParamInt >> 16) & 0xffff;
258 event_sdl_keydown(keysym, keymod);
259 return M64ERR_SUCCESS;
260 case M64CMD_SEND_SDL_KEYUP:
261 if (!g_EmulatorRunning)
262 return M64ERR_INVALID_STATE;
263 keysym = ParamInt & 0xffff;
264 keymod = (ParamInt >> 16) & 0xffff;
265 event_sdl_keyup(keysym, keymod);
266 return M64ERR_SUCCESS;
267 case M64CMD_SET_FRAME_CALLBACK:
268 g_FrameCallback = (m64p_frame_callback) ParamPtr;
269 return M64ERR_SUCCESS;
270 case M64CMD_TAKE_NEXT_SCREENSHOT:
271 if (!g_EmulatorRunning)
272 return M64ERR_INVALID_STATE;
273 main_take_next_screenshot();
274 return M64ERR_SUCCESS;
275 case M64CMD_READ_SCREEN:
276 if (!g_EmulatorRunning)
277 return M64ERR_INVALID_STATE;
278 if (ParamPtr == NULL)
279 return M64ERR_INPUT_ASSERT;
280 if (ParamInt < 0 || ParamInt > 1)
281 return M64ERR_INPUT_INVALID;
282 return main_read_screen(ParamPtr, ParamInt);
283 case M64CMD_RESET:
284 if (!g_EmulatorRunning)
285 return M64ERR_INVALID_STATE;
286 if (ParamInt < 0 || ParamInt > 1)
287 return M64ERR_INPUT_INVALID;
288 return main_reset(ParamInt);
289 case M64CMD_ADVANCE_FRAME:
290 if (!g_EmulatorRunning)
291 return M64ERR_INVALID_STATE;
292 main_advance_one();
293 return M64ERR_SUCCESS;
294 default:
295 return M64ERR_INPUT_INVALID;
296 }
297
298 return M64ERR_INTERNAL;
299}
300
301EXPORT m64p_error CALL CoreOverrideVidExt(m64p_video_extension_functions *VideoFunctionStruct)
302{
303 if (!l_CoreInit)
304 return M64ERR_NOT_INIT;
305
306 return OverrideVideoFunctions(VideoFunctionStruct); /* in vidext.c */
307}
308
309EXPORT m64p_error CALL CoreAddCheat(const char *CheatName, m64p_cheat_code *CodeList, int NumCodes)
310{
311 if (!l_CoreInit)
312 return M64ERR_NOT_INIT;
313 if (CheatName == NULL || CodeList == NULL)
314 return M64ERR_INPUT_ASSERT;
315 if (strlen(CheatName) < 1 || NumCodes < 1)
316 return M64ERR_INPUT_INVALID;
317
318 if (cheat_add_new(CheatName, CodeList, NumCodes))
319 return M64ERR_SUCCESS;
320
321 return M64ERR_INPUT_INVALID;
322}
323
324EXPORT m64p_error CALL CoreCheatEnabled(const char *CheatName, int Enabled)
325{
326 if (!l_CoreInit)
327 return M64ERR_NOT_INIT;
328 if (CheatName == NULL)
329 return M64ERR_INPUT_ASSERT;
330
331 if (cheat_set_enabled(CheatName, Enabled))
332 return M64ERR_SUCCESS;
333
334 return M64ERR_INPUT_INVALID;
335}
336
337EXPORT m64p_error CALL CoreGetRomSettings(m64p_rom_settings *RomSettings, int RomSettingsLength, int Crc1, int Crc2)
338{
339 romdatabase_entry* entry;
340 int i;
341
342 if (!l_CoreInit)
343 return M64ERR_NOT_INIT;
344 if (RomSettings == NULL)
345 return M64ERR_INPUT_ASSERT;
346 if (RomSettingsLength < sizeof(m64p_rom_settings))
347 return M64ERR_INPUT_INVALID;
348
349 /* Look up this ROM in the .ini file and fill in goodname, etc */
350 entry = ini_search_by_crc(Crc1, Crc2);
351 if (entry == NULL)
352 return M64ERR_INPUT_NOT_FOUND;
353
354 strncpy(RomSettings->goodname, entry->goodname, 255);
355 RomSettings->goodname[255] = '\0';
356 for (i = 0; i < 16; i++)
357 sprintf(RomSettings->MD5 + i*2, "%02X", entry->md5[i]);
358 RomSettings->MD5[32] = '\0';
359 RomSettings->savetype = entry->savetype;
360 RomSettings->status = entry->status;
361 RomSettings->players = entry->players;
362 RomSettings->rumble = entry->rumble;
363
364 return M64ERR_SUCCESS;
365}
366
367