1 module m64p;
2 
3 import dynalib;
4 
5 private __gshared m64p_handle coreHandle;
6 private __gshared m64p_handle audioHandle;
7 private __gshared m64p_handle inputHandle;
8 private __gshared m64p_handle rspHandle;
9 private __gshared m64p_handle videoHandle;
10 
11 public:
12 
13     import m64p_common;
14     import m64p_config;
15     import m64p_debugger;
16     import m64p_frontend;
17     import m64p_plugin;
18     import m64p_types;
19     import m64p_vidext;
20 
21     m64p_handle m64p_coreHandle() { return coreHandle; }
22     bool m64p_coreIsLoaded() { return coreHandle != null; }
23 
24     m64p_error m64p_loadCore()
25     {
26         if (m64p_coreIsLoaded) return M64ERR_SUCCESS;
27 
28         DynaLib lib;
29         if (!lib.loadFromConfig("mupen64plus", "mupen64plus-core"))
30         {
31             import std.stdio : writeln;
32             writeln("There was a problem loading mupen64plus-core");
33             return M64ERR_NOT_INIT;
34         } coreHandle = lib.handle;
35 
36         m64p_coreBind(&lib);
37     
38         return M64ERR_SUCCESS;
39     }
40 
41     m64p_error m64p_loadCore(string libDir = "", string depDir = "!")
42     {
43         if (m64p_coreIsLoaded) return M64ERR_SUCCESS;
44 
45         DynaLib lib;
46         if (!lib.load("mupen64plus", libDir, depDir))
47         {
48             import std.stdio : writeln;
49             writeln("There was a problem loading mupen64plus-core");
50             return M64ERR_NOT_INIT;
51         } coreHandle = lib.handle;
52 
53         m64p_coreBind(&lib);
54     
55         return M64ERR_SUCCESS;
56     }
57 
58     private void m64p_coreBind(DynaLib* lib)
59     {
60         /* Common */
61         lib.bind(&PluginGetVersion,"PluginGetVersion");
62         lib.bind(&CoreGetAPIVersions,"CoreGetAPIVersions");
63         lib.bind(&CoreErrorMessage,"CoreErrorMessage");
64             
65         /* Config */
66         lib.bind(&ConfigListSections,"ConfigListSections");
67         lib.bind(&ConfigOpenSection,"ConfigOpenSection");
68         lib.bind(&ConfigListParameters,"ConfigListParameters");
69         lib.bind(&ConfigSaveFile,"ConfigSaveFile");
70         lib.bind(&ConfigSaveSection,"ConfigSaveSection");
71         lib.bind(&ConfigHasUnsavedChanges,"ConfigHasUnsavedChanges");
72         lib.bind(&ConfigDeleteSection,"ConfigDeleteSection");
73         lib.bind(&ConfigRevertChanges,"ConfigRevertChanges");
74         lib.bind(&ConfigSetParameter,"ConfigSetParameter");
75         lib.bind(&ConfigSetParameterHelp,"ConfigSetParameterHelp");
76         lib.bind(&ConfigGetParameter,"ConfigGetParameter");
77         lib.bind(&ConfigGetParameterType,"ConfigGetParameterType");
78         lib.bind(&ConfigGetParameterHelp,"ConfigGetParameterHelp");
79         lib.bind(&ConfigSetDefaultInt,"ConfigSetDefaultInt");
80         lib.bind(&ConfigSetDefaultFloat,"ConfigSetDefaultFloat");
81         lib.bind(&ConfigSetDefaultBool,"ConfigSetDefaultBool");
82         lib.bind(&ConfigSetDefaultString,"ConfigSetDefaultString");
83         lib.bind(&ConfigGetParamInt,"ConfigGetParamInt");
84         lib.bind(&ConfigGetParamFloat,"ConfigGetParamFloat");
85         lib.bind(&ConfigGetParamBool,"ConfigGetParamBool");
86         lib.bind(&ConfigGetParamString,"ConfigGetParamString");
87         lib.bind(&ConfigGetSharedDataFilepath,"ConfigGetSharedDataFilepath");
88         lib.bind(&ConfigGetUserConfigPath,"ConfigGetUserConfigPath");
89         lib.bind(&ConfigGetUserDataPath,"ConfigGetUserDataPath");
90         lib.bind(&ConfigGetUserCachePath,"ConfigGetUserCachePath");
91         lib.bind(&ConfigExternalOpen,"ConfigExternalOpen");
92         lib.bind(&ConfigExternalClose,"ConfigExternalClose");
93         lib.bind(&ConfigExternalGetParameter,"ConfigExternalGetParameter");
94         lib.bind(&ConfigSendNetplayConfig,"ConfigSendNetplayConfig");
95         lib.bind(&ConfigReceiveNetplayConfig,"ConfigReceiveNetplayConfig");
96         lib.bind(&ConfigOverrideUserPaths,"ConfigOverrideUserPaths");
97             
98         /* Debug */
99         lib.bind(&DebugSetCallbacks,"DebugSetCallbacks");
100         lib.bind(&DebugSetCoreCompare,"DebugSetCoreCompare");
101         lib.bind(&DebugSetRunState,"DebugSetRunState");
102         lib.bind(&DebugGetState,"DebugGetState");
103         lib.bind(&DebugStep,"DebugStep");
104         lib.bind(&DebugDecodeOp,"DebugDecodeOp");
105         lib.bind(&DebugMemGetRecompInfo,"DebugMemGetRecompInfo");
106         lib.bind(&DebugMemGetMemInfo,"DebugMemGetMemInfo");
107         lib.bind(&DebugMemGetPointer,"DebugMemGetPointer");
108         lib.bind(&DebugMemRead64,"DebugMemRead64");
109         lib.bind(&DebugMemRead32,"DebugMemRead32");
110         lib.bind(&DebugMemRead16,"DebugMemRead16");
111         lib.bind(&DebugMemRead8,"DebugMemRead8");
112         lib.bind(&DebugMemWrite64,"DebugMemWrite64");
113         lib.bind(&DebugMemWrite32,"DebugMemWrite32");
114         lib.bind(&DebugMemWrite16,"DebugMemWrite16");
115         lib.bind(&DebugMemWrite8,"DebugMemWrite8");
116         lib.bind(&DebugGetCPUDataPtr,"DebugGetCPUDataPtr");
117         lib.bind(&DebugBreakpointLookup,"DebugBreakpointLookup");
118         lib.bind(&DebugBreakpointCommand,"DebugBreakpointCommand");
119         lib.bind(&DebugBreakpointTriggeredBy,"DebugBreakpointTriggeredBy");
120         lib.bind(&DebugVirtualToPhysical,"DebugVirtualToPhysical");
121             
122         /* Front-End */
123         lib.bind(&CoreStartup,"CoreStartup");
124         lib.bind(&CoreShutdown,"CoreShutdown");
125         lib.bind(&CoreAttachPlugin,"CoreAttachPlugin");
126         lib.bind(&CoreDetachPlugin,"CoreDetachPlugin");
127         lib.bind(&CoreDoCommand,"CoreDoCommand");
128         lib.bind(&CoreOverrideVidExt,"CoreOverrideVidExt");
129         lib.bind(&CoreAddCheat,"CoreAddCheat");
130         lib.bind(&CoreCheatEnabled,"CoreCheatEnabled");
131         lib.bind(&CoreGetRomSettings,"CoreGetRomSettings");
132         version(Modding)
133         {
134             lib.bind(&CoreSaveOverride,"CoreSaveOverride");
135             lib.bind(&GetHeader,"GetHeader");
136             lib.bind(&GetRdRam,"GetRdRam");
137             lib.bind(&GetRom,"GetRom");
138             lib.bind(&GetRdRamSize,"GetRdRamSize");
139             lib.bind(&GetRomSize,"GetRomSize");
140             lib.bind(&RefreshDynarec,"RefreshDynarec");
141         }
142 
143         /* Plugin */
144 
145         /* VidExt */
146         lib.bind(&VidExt_Init,"VidExt_Init");
147         lib.bind(&VidExt_Quit,"VidExt_Quit");
148         lib.bind(&VidExt_ListFullscreenModes,"VidExt_ListFullscreenModes");
149         lib.bind(&VidExt_ListFullscreenRates,"VidExt_ListFullscreenRates");
150         lib.bind(&VidExt_SetVideoMode,"VidExt_SetVideoMode");
151         lib.bind(&VidExt_SetVideoModeWithRate,"VidExt_SetVideoModeWithRate");
152         lib.bind(&VidExt_ResizeWindow,"VidExt_ResizeWindow");
153         lib.bind(&VidExt_SetCaption,"VidExt_SetCaption");
154         lib.bind(&VidExt_ToggleFullScreen,"VidExt_ToggleFullScreen");
155         lib.bind(&VidExt_GL_GetProcAddress,"VidExt_GL_GetProcAddress");
156         lib.bind(&VidExt_GL_SetAttribute,"VidExt_GL_SetAttribute");
157         lib.bind(&VidExt_GL_GetAttribute,"VidExt_GL_GetAttribute");
158         lib.bind(&VidExt_GL_SwapBuffers,"VidExt_GL_SwapBuffers");
159         lib.bind(&VidExt_GL_GetDefaultFramebuffer,"VidExt_GL_GetDefaultFramebuffer");
160     }
161 
162     m64p_error m64p_unloadCore()
163     {
164         if (!m64p_coreIsLoaded) return M64ERR_NOT_INIT;
165 
166         /* In case plugins are attached */
167         m64p_detachPlugins();
168 
169         unloadLib(coreHandle);
170         coreHandle = null;
171 
172         /* Common */
173         PluginGetVersion = null;
174         CoreGetAPIVersions = null;
175         CoreErrorMessage = null;
176         PluginStartup = null;
177         PluginShutdown = null;
178 
179         /* Config */
180         ConfigListSections = null;
181         ConfigOpenSection = null;
182         ConfigListParameters = null;
183         ConfigSaveFile = null;
184         ConfigSaveSection = null;
185         ConfigHasUnsavedChanges = null;
186         ConfigDeleteSection = null;
187         ConfigRevertChanges = null;
188         ConfigSetParameter = null;
189         ConfigSetParameterHelp = null;
190         ConfigGetParameter = null;
191         ConfigGetParameterType = null;
192         ConfigGetParameterHelp = null;
193         ConfigSetDefaultInt = null;
194         ConfigSetDefaultFloat = null;
195         ConfigSetDefaultBool = null;
196         ConfigSetDefaultString = null;
197         ConfigGetParamInt = null;
198         ConfigGetParamFloat = null;
199         ConfigGetParamBool = null;
200         ConfigGetParamString = null;
201         ConfigGetSharedDataFilepath = null;
202         ConfigGetUserConfigPath = null;
203         ConfigGetUserDataPath = null;
204         ConfigGetUserCachePath = null;
205         ConfigExternalOpen = null;
206         ConfigExternalClose = null;
207         ConfigExternalGetParameter = null;
208         ConfigSendNetplayConfig = null;
209         ConfigReceiveNetplayConfig = null;
210         ConfigOverrideUserPaths = null;
211 
212         /* Debug */
213         DebugSetCallbacks = null;
214         DebugSetCoreCompare = null;
215         DebugSetRunState = null;
216         DebugGetState = null;
217         DebugStep = null;
218         DebugDecodeOp = null;
219         DebugMemGetRecompInfo = null;
220         DebugMemGetMemInfo = null;
221         DebugMemGetPointer = null;
222         DebugMemRead64 = null;
223         DebugMemRead32 = null;
224         DebugMemRead16 = null;
225         DebugMemRead8 = null;
226         DebugMemWrite64 = null;
227         DebugMemWrite32 = null;
228         DebugMemWrite16 = null;
229         DebugMemWrite8 = null;
230         DebugGetCPUDataPtr = null;
231         DebugBreakpointLookup = null;
232         DebugBreakpointCommand = null;
233         DebugBreakpointTriggeredBy = null;
234         DebugVirtualToPhysical = null;
235 
236         /* Front-End */
237         CoreStartup = null;
238         CoreShutdown = null;
239         CoreAttachPlugin = null;
240         CoreDetachPlugin = null;
241         CoreDoCommand = null;
242         CoreOverrideVidExt = null;
243         CoreAddCheat = null;
244         CoreCheatEnabled = null;
245         version(Modding)
246         {
247             CoreSaveOverride = null;
248             GetHeader = null;
249             GetRdRam = null;
250             GetRom = null;
251             GetRdRamSize = null;
252             GetRomSize = null;
253             RefreshDynarec = null;
254         }
255 
256         /* Plugin */
257 
258         /* VidExt */
259         VidExt_Init = null;
260         VidExt_Quit = null;
261         VidExt_ListFullscreenModes = null;
262         VidExt_ListFullscreenRates = null;
263         VidExt_SetVideoMode = null;
264         VidExt_SetVideoModeWithRate = null;
265         VidExt_ResizeWindow = null;
266         VidExt_SetCaption = null;
267         VidExt_ToggleFullScreen = null;
268         VidExt_GL_GetProcAddress = null;
269         VidExt_GL_SetAttribute = null;
270         VidExt_GL_GetAttribute = null;
271         VidExt_GL_SwapBuffers = null;
272         VidExt_GL_GetDefaultFramebuffer = null;
273 
274         return M64ERR_SUCCESS;
275     }
276 
277     bool m64p_pluginIsLoaded(m64p_plugin_type type)
278     {
279         switch (type)
280         {
281             case M64PLUGIN_CORE: return coreHandle != null;
282             case M64PLUGIN_AUDIO: return audioHandle != null;
283             case M64PLUGIN_INPUT: return inputHandle != null;
284             case M64PLUGIN_RSP: return rspHandle != null;
285             case M64PLUGIN_GFX: return videoHandle != null;
286             default: return false;
287         }
288     }
289 
290     m64p_error m64p_attachPlugins(DebugCallback debugCallback,
291                                   string videoPlugin, string audioPlugin,
292                                   string inputPlugin, string rspPlugin,
293                                   string libDir = "", string depDir = "!")
294     {
295         auto success =
296         (
297             (m64p_loadPlugin(&videoHandle, M64PLUGIN_GFX, debugCallback,
298                 libDir, videoPlugin, depDir) == M64ERR_SUCCESS) &&
299             (m64p_loadPlugin(&audioHandle, M64PLUGIN_AUDIO, debugCallback,
300                 libDir, audioPlugin, depDir) == M64ERR_SUCCESS) &&
301             (m64p_loadPlugin(&inputHandle, M64PLUGIN_INPUT, debugCallback,
302                 libDir, inputPlugin, depDir) == M64ERR_SUCCESS) &&
303             (m64p_loadPlugin(&rspHandle, M64PLUGIN_RSP, debugCallback,
304                 libDir, rspPlugin, depDir) == M64ERR_SUCCESS)
305         );
306         
307         /* Successfully loaded all plugins */
308         if (success) return M64ERR_SUCCESS;
309 
310         /* Failed horribly! Revert! */
311         m64p_detachPlugins();
312         return M64ERR_PLUGIN_FAIL;
313     }
314 
315     void m64p_detachPlugins()
316     {
317         m64p_unloadPlugin(&rspHandle);
318         m64p_unloadPlugin(&inputHandle);
319         m64p_unloadPlugin(&audioHandle);
320         m64p_unloadPlugin(&videoHandle);
321     }
322 
323     private m64p_error m64p_loadPlugin(m64p_handle* plug, m64p_plugin_type type, DebugCallback callback,
324                                        string path, string name, string depsPath = "!")
325     {
326         /* Check if core is attached */
327         if (coreHandle == null) return M64ERR_NOT_INIT;
328 
329         /* Check if already attached */
330         if (*plug != null) return M64ERR_INVALID_STATE;
331 
332         /* Load the lib */
333         DynaLib lib; lib.load(name, path, depsPath);
334         if (!lib.isLoaded)
335         {
336             import std.stdio : writeln;
337             writeln("Mupen64Plus: failed to find ", name);
338             return M64ERR_INPUT_NOT_FOUND;
339         }
340 
341         /* Initialize the plugin */
342         lib.bind(&PluginStartup, "PluginStartup");
343         PluginStartup(coreHandle, cast(void*) (name ~ 0x00), callback);
344         PluginStartup = null;
345 
346         /* Attempt attaching it to core lib */
347         if (CoreAttachPlugin(type, lib.handle) != M64ERR_SUCCESS)
348         {
349             lib.unload();
350             return M64ERR_NOT_INIT;
351         }
352 
353         *plug = lib.handle;
354         return M64ERR_SUCCESS;
355     }
356 
357     private m64p_error m64p_unloadPlugin(m64p_handle* plug)
358     {
359         if (coreHandle == null) return M64ERR_NOT_INIT;
360 
361         /* Check if not already attached */
362         if (*plug == null) return M64ERR_INVALID_STATE;
363             
364         /* Shutdown the plugin */
365         bindSymbol(*plug, cast(void**)&PluginShutdown,"PluginShutdown");
366         PluginShutdown();
367         PluginShutdown = null;
368 
369         /* Detach the lib */
370         unloadLib(*plug);
371         *plug = null;
372 
373         return M64ERR_SUCCESS;
374     }