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