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