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
31 #define M64P_CORE_PROTOTYPES 1
32 #include "m64p_types.h"
33 #include "callbacks.h"
34 #include "m64p_config.h"
35 #include "m64p_frontend.h"
36 #include "audio_backend.h"
37 #include "config.h"
38 #include "vidext.h"
39 #include "../main/cheat.h"
40
41 #include "main/main.h"
42 #include "main/rom.h"
43 #include "main/version.h"
44 #include "main/util.h"
45 #include "dd/dd_rom.h"
46 #include "dd/dd_disk.h"
47 #include "plugin/plugin.h"
48
49 /* some local state variables */
50 static int l_CoreInit = 0;
51 static int l_ROMOpen = 0;
52 static int l_DDROMOpen = 0;
53 static int l_DDDiskOpen = 0;
54
55 /* functions exported outside of libmupen64plus to front-end application */
CoreStartup(int APIVersion,const char * ConfigPath,const char * DataPath,void * Context,void (* DebugCallback)(void *,int,const char *),void * Context2,void (* StateCallback)(void *,m64p_core_param,int))56 EXPORT 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 /* next, start up the configuration handling code by loading and parsing the config file */
76 if (ConfigInit(ConfigPath, DataPath) != M64ERR_SUCCESS)
77 return M64ERR_INTERNAL;
78
79 /* set default configuration parameter values for Core */
80 if (ConfigOpenSection("Core", &g_CoreConfig) != M64ERR_SUCCESS || g_CoreConfig == NULL)
81 return M64ERR_INTERNAL;
82
83 if (!main_set_core_defaults())
84 return M64ERR_INTERNAL;
85
86 l_CoreInit = 1;
87 return M64ERR_SUCCESS;
88 }
89
CoreShutdown(void)90 EXPORT m64p_error CALL CoreShutdown(void)
91 {
92 if (!l_CoreInit)
93 return M64ERR_NOT_INIT;
94
95 ConfigShutdown();
96
97 l_CoreInit = 0;
98 return M64ERR_SUCCESS;
99 }
100
CoreDoCommand(m64p_command Command,int ParamInt,void * ParamPtr)101 EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *ParamPtr)
102 {
103 m64p_error rval;
104 int keysym, keymod;
105 (void)keysym;
106 (void)keymod;
107
108 if (!l_CoreInit)
109 return M64ERR_NOT_INIT;
110
111 switch(Command)
112 {
113 case M64CMD_NOP:
114 return M64ERR_SUCCESS;
115 case M64CMD_ROM_OPEN:
116 if (g_EmulatorRunning || l_ROMOpen)
117 return M64ERR_INVALID_STATE;
118 if (ParamPtr == NULL || ParamInt < 4096)
119 return M64ERR_INPUT_ASSERT;
120 rval = open_rom((const unsigned char *) ParamPtr, ParamInt);
121 if (rval == M64ERR_SUCCESS)
122 {
123 l_ROMOpen = 1;
124 cheat_init();
125 }
126 return rval;
127 case M64CMD_ROM_CLOSE:
128 if (g_EmulatorRunning || !l_ROMOpen)
129 return M64ERR_INVALID_STATE;
130 l_ROMOpen = 0;
131 cheat_delete_all();
132 cheat_uninit();
133 return close_rom();
134 case M64CMD_ROM_GET_HEADER:
135 if (!l_ROMOpen && !l_DDROMOpen)
136 return M64ERR_INVALID_STATE;
137 if (ParamPtr == NULL)
138 return M64ERR_INPUT_ASSERT;
139 if (sizeof(m64p_rom_header) < ParamInt)
140 ParamInt = sizeof(m64p_rom_header);
141 memmove(ParamPtr, &ROM_HEADER, ParamInt);
142 // Mupen64Plus used to keep a m64p_rom_header with a clean ROM name
143 // Keep returning a clean ROM name for backwards compatibility
144 if (ParamInt >= 0x20)
145 {
146 int size = (ParamInt >= 0x20 + 20) ? 20 : (ParamInt - 0x20);
147 memcpy((char *)ParamPtr + 0x20, ROM_PARAMS.headername, size);
148 }
149 return M64ERR_SUCCESS;
150 case M64CMD_ROM_GET_SETTINGS:
151 if (!l_ROMOpen)
152 return M64ERR_INVALID_STATE;
153 if (ParamPtr == NULL)
154 return M64ERR_INPUT_ASSERT;
155 if (sizeof(m64p_rom_settings) < ParamInt)
156 ParamInt = sizeof(m64p_rom_settings);
157 memcpy(ParamPtr, &ROM_SETTINGS, ParamInt);
158 return M64ERR_SUCCESS;
159 case M64CMD_EXECUTE:
160 if (g_EmulatorRunning || !l_ROMOpen && !l_DDROMOpen)
161 return M64ERR_INVALID_STATE;
162 /* the main_run() function will not return until the player has quit the game */
163 return main_init();
164 case M64CMD_STOP:
165 if (!g_EmulatorRunning)
166 return M64ERR_INVALID_STATE;
167 /* this stop function is asynchronous. The emulator may not terminate until later */
168 return main_core_state_set(M64CORE_EMU_STATE, M64EMU_STOPPED);
169 case M64CMD_PAUSE:
170 if (!g_EmulatorRunning)
171 return M64ERR_INVALID_STATE;
172 return main_core_state_set(M64CORE_EMU_STATE, M64EMU_PAUSED);
173 case M64CMD_RESUME:
174 if (!g_EmulatorRunning)
175 return M64ERR_INVALID_STATE;
176 return main_core_state_set(M64CORE_EMU_STATE, M64EMU_RUNNING);
177 case M64CMD_CORE_STATE_QUERY:
178 if (ParamPtr == NULL)
179 return M64ERR_INPUT_ASSERT;
180 return main_core_state_query((m64p_core_param) ParamInt, (int *) ParamPtr);
181 case M64CMD_CORE_STATE_SET:
182 if (ParamPtr == NULL)
183 return M64ERR_INPUT_ASSERT;
184 return main_core_state_set((m64p_core_param) ParamInt, *((int *)ParamPtr));
185 case M64CMD_SET_FRAME_CALLBACK:
186 g_FrameCallback = (m64p_frame_callback) ParamPtr;
187 return M64ERR_SUCCESS;
188 case M64CMD_READ_SCREEN:
189 if (!g_EmulatorRunning)
190 return M64ERR_INVALID_STATE;
191 if (ParamPtr == NULL)
192 return M64ERR_INPUT_ASSERT;
193 if (ParamInt < 0 || ParamInt > 1)
194 return M64ERR_INPUT_INVALID;
195 return main_read_screen(ParamPtr, ParamInt);
196 case M64CMD_RESET:
197 if (!g_EmulatorRunning)
198 return M64ERR_INVALID_STATE;
199 if (ParamInt < 0 || ParamInt > 1)
200 return M64ERR_INPUT_INVALID;
201 return main_reset(ParamInt);
202 case M64CMD_DDROM_OPEN:
203 if (g_EmulatorRunning || l_DDROMOpen)
204 return M64ERR_INVALID_STATE;
205 if (ParamPtr == NULL || ParamInt < 4096)
206 return M64ERR_INPUT_ASSERT;
207 rval = open_ddrom((const unsigned char *)ParamPtr, ParamInt);
208 if (rval == M64ERR_SUCCESS)
209 l_DDROMOpen = 1;
210 return rval;
211 case M64CMD_DISK_OPEN:
212 if (g_EmulatorRunning || l_DDDiskOpen)
213 return M64ERR_INVALID_STATE;
214 if (ParamPtr == NULL || ParamInt < 4096)
215 return M64ERR_INPUT_ASSERT;
216 rval = open_dd_disk((const unsigned char *)ParamPtr, ParamInt);
217 if (rval == M64ERR_SUCCESS)
218 l_DDDiskOpen = 1;
219 return rval;
220 case M64CMD_DISK_CLOSE:
221 if (g_EmulatorRunning || !l_DDDiskOpen)
222 return M64ERR_INVALID_STATE;
223 l_DDDiskOpen = 0;
224 return close_dd_disk();
225 default:
226 return M64ERR_INPUT_INVALID;
227 }
228
229 return M64ERR_INTERNAL;
230 }
231
CoreSetAudioInterfaceBackend(const struct m64p_audio_backend * backend)232 EXPORT m64p_error CALL CoreSetAudioInterfaceBackend(const struct m64p_audio_backend* backend)
233 {
234 return M64ERR_SUCCESS;
235 }
236
CoreAddCheat(const char * CheatName,m64p_cheat_code * CodeList,int NumCodes)237 EXPORT m64p_error CALL CoreAddCheat(const char *CheatName, m64p_cheat_code *CodeList, int NumCodes)
238 {
239 if (!l_CoreInit)
240 return M64ERR_NOT_INIT;
241 if (CheatName == NULL || CodeList == NULL)
242 return M64ERR_INPUT_ASSERT;
243 if (strlen(CheatName) < 1 || NumCodes < 1)
244 return M64ERR_INPUT_INVALID;
245
246 if (cheat_add_new(CheatName, CodeList, NumCodes))
247 return M64ERR_SUCCESS;
248
249 return M64ERR_INPUT_INVALID;
250 }
251
CoreCheatEnabled(const char * CheatName,int Enabled)252 EXPORT m64p_error CALL CoreCheatEnabled(const char *CheatName, int Enabled)
253 {
254 if (!l_CoreInit)
255 return M64ERR_NOT_INIT;
256 if (CheatName == NULL)
257 return M64ERR_INPUT_ASSERT;
258
259 if (cheat_set_enabled(CheatName, Enabled))
260 return M64ERR_SUCCESS;
261
262 return M64ERR_INPUT_INVALID;
263 }
264
CoreCheatClearAll(void)265 EXPORT m64p_error CALL CoreCheatClearAll(void)
266 {
267 if (!l_CoreInit)
268 return M64ERR_NOT_INIT;
269
270 cheat_delete_all();
271 return M64ERR_SUCCESS;
272 }
273
CoreGetRomSettings(m64p_rom_settings * RomSettings,int RomSettingsLength,int Crc1,int Crc2)274 EXPORT m64p_error CALL CoreGetRomSettings(m64p_rom_settings *RomSettings, int RomSettingsLength, int Crc1, int Crc2)
275 {
276 return M64ERR_SUCCESS;
277 }
278
279
280