5288f542 |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus-ui-console - core_interface.c * |
3 | * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * |
4 | * Copyright (C) 2009 Richard Goedeken * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the * |
18 | * Free Software Foundation, Inc., * |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
20 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
21 | |
22 | /* This file contains the routines for attaching to the Mupen64Plus core |
23 | * library and pointers to the core functions |
24 | */ |
25 | |
26 | #include <stdio.h> |
27 | |
28 | #include "m64p_types.h" |
29 | #include "m64p_common.h" |
30 | #include "m64p_frontend.h" |
31 | #include "m64p_config.h" |
32 | #include "m64p_debugger.h" |
33 | |
34 | #include "osal_preproc.h" |
35 | #include "osal_dynamiclib.h" |
36 | |
37 | #include "main.h" |
38 | #include "version.h" |
39 | #include "core_interface.h" |
40 | |
41 | /* global data definitions */ |
42 | int g_CoreCapabilities; |
43 | int g_CoreAPIVersion; |
44 | |
45 | /* definitions of pointers to Core common functions */ |
46 | ptr_CoreErrorMessage CoreErrorMessage = NULL; |
47 | |
48 | /* definitions of pointers to Core front-end functions */ |
49 | ptr_CoreStartup CoreStartup = NULL; |
50 | ptr_CoreShutdown CoreShutdown = NULL; |
51 | ptr_CoreAttachPlugin CoreAttachPlugin = NULL; |
52 | ptr_CoreDetachPlugin CoreDetachPlugin = NULL; |
53 | ptr_CoreDoCommand CoreDoCommand = NULL; |
54 | ptr_CoreOverrideVidExt CoreOverrideVidExt = NULL; |
55 | ptr_CoreAddCheat CoreAddCheat = NULL; |
56 | ptr_CoreCheatEnabled CoreCheatEnabled = NULL; |
57 | |
58 | /* definitions of pointers to Core config functions */ |
59 | ptr_ConfigListSections ConfigListSections = NULL; |
60 | ptr_ConfigOpenSection ConfigOpenSection = NULL; |
61 | ptr_ConfigDeleteSection ConfigDeleteSection = NULL; |
62 | ptr_ConfigSaveSection ConfigSaveSection = NULL; |
63 | ptr_ConfigListParameters ConfigListParameters = NULL; |
64 | ptr_ConfigSaveFile ConfigSaveFile = NULL; |
65 | ptr_ConfigSetParameter ConfigSetParameter = NULL; |
66 | ptr_ConfigGetParameter ConfigGetParameter = NULL; |
67 | ptr_ConfigGetParameterType ConfigGetParameterType = NULL; |
68 | ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL; |
69 | ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL; |
70 | ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL; |
71 | ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL; |
72 | ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL; |
73 | ptr_ConfigGetParamInt ConfigGetParamInt = NULL; |
74 | ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL; |
75 | ptr_ConfigGetParamBool ConfigGetParamBool = NULL; |
76 | ptr_ConfigGetParamString ConfigGetParamString = NULL; |
77 | |
78 | ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL; |
79 | ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL; |
80 | ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL; |
81 | ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL; |
82 | |
83 | /* definitions of pointers to Core debugger functions */ |
84 | ptr_DebugSetCallbacks DebugSetCallbacks = NULL; |
85 | ptr_DebugSetCoreCompare DebugSetCoreCompare = NULL; |
86 | ptr_DebugSetRunState DebugSetRunState = NULL; |
87 | ptr_DebugGetState DebugGetState = NULL; |
88 | ptr_DebugStep DebugStep = NULL; |
89 | ptr_DebugDecodeOp DebugDecodeOp = NULL; |
90 | ptr_DebugMemGetRecompInfo DebugMemGetRecompInfo = NULL; |
91 | ptr_DebugMemGetMemInfo DebugMemGetMemInfo = NULL; |
92 | ptr_DebugMemGetPointer DebugMemGetPointer = NULL; |
93 | |
94 | ptr_DebugMemRead64 DebugMemRead64 = NULL; |
95 | ptr_DebugMemRead32 DebugMemRead32 = NULL; |
96 | ptr_DebugMemRead16 DebugMemRead16 = NULL; |
97 | ptr_DebugMemRead8 DebugMemRead8 = NULL; |
98 | |
99 | ptr_DebugMemWrite64 DebugMemWrite64 = NULL; |
100 | ptr_DebugMemWrite32 DebugMemWrite32 = NULL; |
101 | ptr_DebugMemWrite16 DebugMemWrite16 = NULL; |
102 | ptr_DebugMemWrite8 DebugMemWrite8 = NULL; |
103 | |
104 | ptr_DebugGetCPUDataPtr DebugGetCPUDataPtr = NULL; |
105 | ptr_DebugBreakpointLookup DebugBreakpointLookup = NULL; |
106 | ptr_DebugBreakpointCommand DebugBreakpointCommand = NULL; |
107 | |
108 | /* global variables */ |
109 | m64p_dynlib_handle CoreHandle = NULL; |
110 | |
111 | /* functions */ |
112 | m64p_error AttachCoreLib(const char *CoreLibFilepath) |
113 | { |
114 | /* check if Core DLL is already attached */ |
115 | if (CoreHandle != NULL) |
116 | return M64ERR_INVALID_STATE; |
117 | |
118 | /* load the DLL */ |
119 | m64p_error rval = M64ERR_INTERNAL; |
120 | /* first, try a library path+name that was given on the command-line */ |
121 | if (CoreLibFilepath != NULL) |
122 | { |
123 | rval = osal_dynlib_open(&CoreHandle, CoreLibFilepath); |
124 | } |
125 | /* then try a library path that was given at compile time */ |
126 | #if defined(COREDIR) |
127 | if (rval != M64ERR_SUCCESS || CoreHandle == NULL) |
128 | { |
129 | rval = osal_dynlib_open(&CoreHandle, COREDIR OSAL_DEFAULT_DYNLIB_FILENAME); |
130 | } |
131 | #endif |
132 | /* then try just the filename of the shared library, to let dlopen() look through the system lib dirs */ |
133 | if (rval != M64ERR_SUCCESS || CoreHandle == NULL) |
134 | { |
135 | rval = osal_dynlib_open(&CoreHandle, OSAL_DEFAULT_DYNLIB_FILENAME); |
136 | } |
137 | /* as a last-ditch effort, try loading library in current directory */ |
138 | if (rval != M64ERR_SUCCESS || CoreHandle == NULL) |
139 | { |
140 | rval = osal_dynlib_open(&CoreHandle, OSAL_CURRENT_DIR OSAL_DEFAULT_DYNLIB_FILENAME); |
141 | } |
142 | /* if we haven't found a good core library by now, then we're screwed */ |
143 | if (rval != M64ERR_SUCCESS || CoreHandle == NULL) |
144 | { |
145 | DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: failed to find Mupen64Plus Core library"); |
146 | CoreHandle = NULL; |
147 | return M64ERR_INPUT_NOT_FOUND; |
148 | } |
149 | |
150 | /* attach and call the PluginGetVersion function, check the Core and API versions for compatibility with this front-end */ |
151 | ptr_PluginGetVersion CoreVersionFunc; |
152 | CoreVersionFunc = (ptr_PluginGetVersion) osal_dynlib_getproc(CoreHandle, "PluginGetVersion"); |
153 | if (CoreVersionFunc == NULL) |
154 | { |
155 | DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Shared library '%s' invalid; no PluginGetVersion() function found.", CoreLibFilepath); |
156 | osal_dynlib_close(CoreHandle); |
157 | CoreHandle = NULL; |
158 | return M64ERR_INPUT_INVALID; |
159 | } |
160 | m64p_plugin_type PluginType = (m64p_plugin_type) 0; |
161 | int Compatible = 0; |
162 | int CoreVersion = 0; |
163 | const char *CoreName = NULL; |
164 | (*CoreVersionFunc)(&PluginType, &CoreVersion, &g_CoreAPIVersion, &CoreName, &g_CoreCapabilities); |
165 | if (PluginType != M64PLUGIN_CORE) |
166 | DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Shared library '%s' invalid; this is not the emulator core.", CoreLibFilepath); |
167 | else if (CoreVersion < MINIMUM_CORE_VERSION) |
168 | DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Shared library '%s' incompatible; core version %i.%i.%i is below minimum supported %i.%i.%i", |
169 | CoreLibFilepath, VERSION_PRINTF_SPLIT(CoreVersion), VERSION_PRINTF_SPLIT(MINIMUM_CORE_VERSION)); |
170 | else if ((g_CoreAPIVersion & 0xffff0000) != (CORE_API_VERSION & 0xffff0000)) |
171 | DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Shared library '%s' incompatible; core API major version %i.%i.%i doesn't match with this application (%i.%i.%i)", |
172 | CoreLibFilepath, VERSION_PRINTF_SPLIT(g_CoreAPIVersion), VERSION_PRINTF_SPLIT(CORE_API_VERSION)); |
173 | else |
174 | Compatible = 1; |
175 | /* exit if not compatible */ |
176 | if (Compatible == 0) |
177 | { |
178 | osal_dynlib_close(CoreHandle); |
179 | CoreHandle = NULL; |
180 | return M64ERR_INCOMPATIBLE; |
181 | } |
182 | |
183 | /* attach and call the CoreGetAPIVersion function, check Config API version for compatibility */ |
184 | ptr_CoreGetAPIVersions CoreAPIVersionFunc; |
185 | CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreHandle, "CoreGetAPIVersions"); |
186 | if (CoreAPIVersionFunc == NULL) |
187 | { |
188 | DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Library '%s' broken; no CoreAPIVersionFunc() function found.", CoreLibFilepath); |
189 | osal_dynlib_close(CoreHandle); |
190 | CoreHandle = NULL; |
191 | return M64ERR_INPUT_INVALID; |
192 | } |
193 | int ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion; |
194 | (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL); |
195 | if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000)) |
196 | { |
197 | DebugMessage(M64MSG_ERROR, "AttachCoreLib() Error: Emulator core '%s' incompatible; Config API major version %i.%i.%i doesn't match application: %i.%i.%i", |
198 | CoreLibFilepath, VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION)); |
199 | osal_dynlib_close(CoreHandle); |
200 | CoreHandle = NULL; |
201 | return M64ERR_INCOMPATIBLE; |
202 | } |
203 | |
204 | /* print some information about the core library */ |
205 | DebugMessage(M64MSG_INFO, "attached to core library '%s' version %i.%i.%i", CoreName, VERSION_PRINTF_SPLIT(CoreVersion)); |
206 | if (g_CoreCapabilities & M64CAPS_DYNAREC) |
207 | DebugMessage(M64MSG_INFO, " Includes support for Dynamic Recompiler."); |
208 | if (g_CoreCapabilities & M64CAPS_DEBUGGER) |
209 | DebugMessage(M64MSG_INFO, " Includes support for MIPS r4300 Debugger."); |
210 | if (g_CoreCapabilities & M64CAPS_CORE_COMPARE) |
211 | DebugMessage(M64MSG_INFO, " Includes support for r4300 Core Comparison."); |
212 | |
213 | /* get function pointers to the common and front-end functions */ |
214 | CoreErrorMessage = (ptr_CoreErrorMessage) osal_dynlib_getproc(CoreHandle, "CoreErrorMessage"); |
215 | CoreStartup = (ptr_CoreStartup) osal_dynlib_getproc(CoreHandle, "CoreStartup"); |
216 | CoreShutdown = (ptr_CoreShutdown) osal_dynlib_getproc(CoreHandle, "CoreShutdown"); |
217 | CoreAttachPlugin = (ptr_CoreAttachPlugin) osal_dynlib_getproc(CoreHandle, "CoreAttachPlugin"); |
218 | CoreDetachPlugin = (ptr_CoreDetachPlugin) osal_dynlib_getproc(CoreHandle, "CoreDetachPlugin"); |
219 | CoreDoCommand = (ptr_CoreDoCommand) osal_dynlib_getproc(CoreHandle, "CoreDoCommand"); |
220 | CoreOverrideVidExt = (ptr_CoreOverrideVidExt) osal_dynlib_getproc(CoreHandle, "CoreOverrideVidExt"); |
221 | CoreAddCheat = (ptr_CoreAddCheat) osal_dynlib_getproc(CoreHandle, "CoreAddCheat"); |
222 | CoreCheatEnabled = (ptr_CoreCheatEnabled) osal_dynlib_getproc(CoreHandle, "CoreCheatEnabled"); |
223 | |
224 | /* get function pointers to the configuration functions */ |
225 | ConfigListSections = (ptr_ConfigListSections) osal_dynlib_getproc(CoreHandle, "ConfigListSections"); |
226 | ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreHandle, "ConfigOpenSection"); |
227 | ConfigDeleteSection = (ptr_ConfigDeleteSection) osal_dynlib_getproc(CoreHandle, "ConfigDeleteSection"); |
228 | ConfigSaveSection = (ptr_ConfigSaveSection) osal_dynlib_getproc(CoreHandle, "ConfigSaveSection"); |
229 | ConfigListParameters = (ptr_ConfigListParameters) osal_dynlib_getproc(CoreHandle, "ConfigListParameters"); |
230 | ConfigSaveFile = (ptr_ConfigSaveFile) osal_dynlib_getproc(CoreHandle, "ConfigSaveFile"); |
231 | ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreHandle, "ConfigSetParameter"); |
232 | ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreHandle, "ConfigGetParameter"); |
233 | ConfigGetParameterType = (ptr_ConfigGetParameterType) osal_dynlib_getproc(CoreHandle, "ConfigGetParameterType"); |
234 | ConfigGetParameterHelp = (ptr_ConfigGetParameterHelp) osal_dynlib_getproc(CoreHandle, "ConfigGetParameterHelp"); |
235 | ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreHandle, "ConfigSetDefaultInt"); |
236 | ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreHandle, "ConfigSetDefaultFloat"); |
237 | ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreHandle, "ConfigSetDefaultBool"); |
238 | ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreHandle, "ConfigSetDefaultString"); |
239 | ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreHandle, "ConfigGetParamInt"); |
240 | ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreHandle, "ConfigGetParamFloat"); |
241 | ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreHandle, "ConfigGetParamBool"); |
242 | ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreHandle, "ConfigGetParamString"); |
243 | |
244 | ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreHandle, "ConfigGetSharedDataFilepath"); |
245 | ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreHandle, "ConfigGetUserConfigPath"); |
246 | ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreHandle, "ConfigGetUserDataPath"); |
247 | ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreHandle, "ConfigGetUserCachePath"); |
248 | |
249 | /* get function pointers to the debugger functions */ |
250 | DebugSetCallbacks = (ptr_DebugSetCallbacks) osal_dynlib_getproc(CoreHandle, "DebugSetCallbacks"); |
251 | DebugSetCoreCompare = (ptr_DebugSetCoreCompare) osal_dynlib_getproc(CoreHandle, "DebugSetCoreCompare"); |
252 | DebugSetRunState = (ptr_DebugSetRunState) osal_dynlib_getproc(CoreHandle, "DebugSetRunState"); |
253 | DebugGetState = (ptr_DebugGetState) osal_dynlib_getproc(CoreHandle, "DebugGetState"); |
254 | DebugStep = (ptr_DebugStep) osal_dynlib_getproc(CoreHandle, "DebugStep"); |
255 | DebugDecodeOp = (ptr_DebugDecodeOp) osal_dynlib_getproc(CoreHandle, "DebugDecodeOp"); |
256 | DebugMemGetRecompInfo = (ptr_DebugMemGetRecompInfo) osal_dynlib_getproc(CoreHandle, "DebugMemGetRecompInfo"); |
257 | DebugMemGetMemInfo = (ptr_DebugMemGetMemInfo) osal_dynlib_getproc(CoreHandle, "DebugMemGetMemInfo"); |
258 | DebugMemGetPointer = (ptr_DebugMemGetPointer) osal_dynlib_getproc(CoreHandle, "DebugMemGetPointer"); |
259 | |
260 | DebugMemRead64 = (ptr_DebugMemRead64) osal_dynlib_getproc(CoreHandle, "DebugMemRead64"); |
261 | DebugMemRead32 = (ptr_DebugMemRead32) osal_dynlib_getproc(CoreHandle, "DebugMemRead32"); |
262 | DebugMemRead16 = (ptr_DebugMemRead16) osal_dynlib_getproc(CoreHandle, "DebugMemRead16"); |
263 | DebugMemRead8 = (ptr_DebugMemRead8) osal_dynlib_getproc(CoreHandle, "DebugMemRead8"); |
264 | |
265 | DebugMemWrite64 = (ptr_DebugMemWrite64) osal_dynlib_getproc(CoreHandle, "DebugMemRead64"); |
266 | DebugMemWrite32 = (ptr_DebugMemWrite32) osal_dynlib_getproc(CoreHandle, "DebugMemRead32"); |
267 | DebugMemWrite16 = (ptr_DebugMemWrite16) osal_dynlib_getproc(CoreHandle, "DebugMemRead16"); |
268 | DebugMemWrite8 = (ptr_DebugMemWrite8) osal_dynlib_getproc(CoreHandle, "DebugMemRead8"); |
269 | |
270 | DebugGetCPUDataPtr = (ptr_DebugGetCPUDataPtr) osal_dynlib_getproc(CoreHandle, "DebugGetCPUDataPtr"); |
271 | DebugBreakpointLookup = (ptr_DebugBreakpointLookup) osal_dynlib_getproc(CoreHandle, "DebugBreakpointLookup"); |
272 | DebugBreakpointCommand = (ptr_DebugBreakpointCommand) osal_dynlib_getproc(CoreHandle, "DebugBreakpointCommand"); |
273 | |
274 | return M64ERR_SUCCESS; |
275 | } |
276 | |
277 | m64p_error DetachCoreLib(void) |
278 | { |
279 | if (CoreHandle == NULL) |
280 | return M64ERR_INVALID_STATE; |
281 | |
282 | /* set the core function pointers to NULL */ |
283 | CoreErrorMessage = NULL; |
284 | CoreStartup = NULL; |
285 | CoreShutdown = NULL; |
286 | CoreAttachPlugin = NULL; |
287 | CoreDetachPlugin = NULL; |
288 | CoreDoCommand = NULL; |
289 | CoreOverrideVidExt = NULL; |
290 | CoreAddCheat = NULL; |
291 | CoreCheatEnabled = NULL; |
292 | |
293 | ConfigListSections = NULL; |
294 | ConfigOpenSection = NULL; |
295 | ConfigDeleteSection = NULL; |
296 | ConfigSaveSection = NULL; |
297 | ConfigListParameters = NULL; |
298 | ConfigSetParameter = NULL; |
299 | ConfigGetParameter = NULL; |
300 | ConfigGetParameterType = NULL; |
301 | ConfigGetParameterHelp = NULL; |
302 | ConfigSetDefaultInt = NULL; |
303 | ConfigSetDefaultBool = NULL; |
304 | ConfigSetDefaultString = NULL; |
305 | ConfigGetParamInt = NULL; |
306 | ConfigGetParamBool = NULL; |
307 | ConfigGetParamString = NULL; |
308 | |
309 | ConfigGetSharedDataFilepath = NULL; |
310 | ConfigGetUserDataPath = NULL; |
311 | ConfigGetUserCachePath = NULL; |
312 | |
313 | DebugSetCallbacks = NULL; |
314 | DebugSetCoreCompare = NULL; |
315 | DebugSetRunState = NULL; |
316 | DebugGetState = NULL; |
317 | DebugStep = NULL; |
318 | DebugDecodeOp = NULL; |
319 | DebugMemGetRecompInfo = NULL; |
320 | DebugMemGetMemInfo = NULL; |
321 | DebugMemGetPointer = NULL; |
322 | |
323 | DebugMemRead64 = NULL; |
324 | DebugMemRead32 = NULL; |
325 | DebugMemRead16 = NULL; |
326 | DebugMemRead8 = NULL; |
327 | |
328 | DebugMemWrite64 = NULL; |
329 | DebugMemWrite32 = NULL; |
330 | DebugMemWrite16 = NULL; |
331 | DebugMemWrite8 = NULL; |
332 | |
333 | DebugGetCPUDataPtr = NULL; |
334 | DebugBreakpointLookup = NULL; |
335 | DebugBreakpointCommand = NULL; |
336 | |
337 | /* detach the shared library */ |
338 | osal_dynlib_close(CoreHandle); |
339 | CoreHandle = NULL; |
340 | |
341 | return M64ERR_SUCCESS; |
342 | } |
343 | |
344 | |