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