[Project64] Make plugins handle android better

This commit is contained in:
zilmar 2016-04-18 19:38:20 +10:00
parent b55cc5f78e
commit a76a174246
9 changed files with 179 additions and 49 deletions

View File

@ -31,7 +31,7 @@ CAudioPlugin::CAudioPlugin() :
CAudioPlugin::~CAudioPlugin()
{
Close();
Close(NULL);
UnloadPlugin();
}
@ -97,8 +97,13 @@ bool CAudioPlugin::Initiate(CN64System * System, RenderWindow * Window)
AUDIO_INFO Info = { 0 };
#ifdef _WIN32
Info.hwnd = Window ? Window->GetWindowHandle() : NULL;
Info.hinst = Window ? Window->GetModuleInstance() : NULL;;
Info.hinst = Window ? Window->GetModuleInstance() : NULL;
#else
Info.hwnd = NULL;
Info.hinst = NULL;
#endif
Info.MemoryBswaped = true;
Info.CheckInterrupts = DummyCheckInterrupts;
@ -140,7 +145,7 @@ bool CAudioPlugin::Initiate(CN64System * System, RenderWindow * Window)
m_Initialized = InitiateAudio(Info) != 0;
#ifdef _WIN32
//jabo had a bug so I call CreateThread so his dllmain gets called again
//jabo had a bug so I call CreateThread so his dllmain gets called again
pjutil::DynLibCallDllMain();
if (System != NULL)
@ -152,7 +157,7 @@ bool CAudioPlugin::Initiate(CN64System * System, RenderWindow * Window)
WriteTrace(TraceAudioPlugin, TraceDebug, "Terminate Audio Thread");
TerminateThread(m_hAudioThread, 0);
}
DWORD ThreadID;
DWORD ThreadID;
m_hAudioThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AudioThread, (LPVOID)this, 0, &ThreadID);
}
@ -175,7 +180,7 @@ void CAudioPlugin::UnloadPluginDetails(void)
m_hAudioThread = NULL;
}
#endif
AiDacrateChanged = NULL;
AiDacrateChanged = NULL;
AiLenChanged = NULL;
AiReadLength = NULL;
AiUpdate = NULL;

View File

@ -29,7 +29,7 @@ CControl_Plugin::CControl_Plugin(void) :
CControl_Plugin::~CControl_Plugin()
{
Close();
Close(NULL);
UnloadPlugin();
}
@ -78,9 +78,13 @@ bool CControl_Plugin::Initiate(CN64System * System, RenderWindow * Window)
{
//Get Function from DLL
void(CALL *InitiateControllers_1_0)(void * hMainWindow, CONTROL Controls[4]);
_LoadFunction("InitiateControllers",InitiateControllers_1_0);
_LoadFunction("InitiateControllers", InitiateControllers_1_0);
if (InitiateControllers_1_0 == NULL) { return false; }
#ifdef _WIN32
InitiateControllers_1_0(Window->GetWindowHandle(), m_PluginControllers);
#else
InitiateControllers_1_0(NULL, m_PluginControllers);
#endif
m_Initialized = true;
}
else if (m_PluginInfo.Version >= 0x0101)
@ -88,15 +92,20 @@ bool CControl_Plugin::Initiate(CN64System * System, RenderWindow * Window)
CONTROL_INFO ControlInfo;
ControlInfo.Controls = m_PluginControllers;
ControlInfo.HEADER = (System == NULL ? Buffer : g_Rom->GetRomAddress());
#ifdef _WIN32
ControlInfo.hinst = Window ? Window->GetModuleInstance() : NULL;
ControlInfo.hMainWindow = Window ? Window->GetWindowHandle() : NULL;
#else
ControlInfo.hinst = NULL;
ControlInfo.hMainWindow = NULL;
#endif
ControlInfo.MemoryBswaped = true;
if (m_PluginInfo.Version == 0x0101)
{
//Get Function from DLL
void(CALL *InitiateControllers_1_1)(CONTROL_INFO ControlInfo);
_LoadFunction("InitiateControllers",InitiateControllers_1_1);
_LoadFunction("InitiateControllers", InitiateControllers_1_1);
if (InitiateControllers_1_1 == NULL) { return false; }
InitiateControllers_1_1(ControlInfo);
@ -106,7 +115,7 @@ bool CControl_Plugin::Initiate(CN64System * System, RenderWindow * Window)
{
//Get Function from DLL
void(CALL *InitiateControllers_1_2)(CONTROL_INFO * ControlInfo);
_LoadFunction("InitiateControllers",InitiateControllers_1_2);
_LoadFunction("InitiateControllers", InitiateControllers_1_2);
if (InitiateControllers_1_2 == NULL) { return false; }
InitiateControllers_1_2(&ControlInfo);
@ -115,7 +124,7 @@ bool CControl_Plugin::Initiate(CN64System * System, RenderWindow * Window)
}
#ifdef _WIN32
//jabo had a bug so I call CreateThread so his dllmain gets called again
//jabo had a bug so I call CreateThread so his dllmain gets called again
pjutil::DynLibCallDllMain();
#endif

View File

@ -38,8 +38,10 @@ InitiateDebugger(NULL)
CGfxPlugin::~CGfxPlugin()
{
Close();
WriteTrace(TraceGFXPlugin, TraceDebug, "Start");
Close(NULL);
UnloadPlugin();
WriteTrace(TraceGFXPlugin, TraceDebug, "Done");
}
bool CGfxPlugin::LoadFunctions(void)
@ -55,6 +57,10 @@ bool CGfxPlugin::LoadFunctions(void)
LoadFunction(ViStatusChanged);
LoadFunction(ViWidthChanged);
LoadFunction(SoftReset);
#ifdef ANDROID
LoadFunction(SurfaceCreated);
LoadFunction(SurfaceChanged);
#endif
// version 0x104 functions
_LoadFunction("DrawFullScreenStatus", DrawStatus);
@ -104,7 +110,7 @@ bool CGfxPlugin::Initiate(CN64System * System, RenderWindow * Window)
WriteTrace(TraceGFXPlugin, TraceDebug, "Starting");
if (m_Initialized)
{
Close();
Close(Window);
}
typedef struct
@ -150,6 +156,9 @@ bool CGfxPlugin::Initiate(CN64System * System, RenderWindow * Window)
uint32_t * VI__Y_SCALE_REG;
void(CALL *CheckInterrupts)(void);
#ifdef ANDROID
void(CALL *SwapBuffers)(void);
#endif
} GFX_INFO;
//Get Function from DLL
@ -164,8 +173,14 @@ bool CGfxPlugin::Initiate(CN64System * System, RenderWindow * Window)
GFX_INFO Info = { 0 };
Info.MemoryBswaped = true;
#ifdef _WIN32
Info.hWnd = Window ? Window->GetWindowHandle() : NULL;
Info.hStatusBar = Window ? Window->GetStatusBar() : NULL;
#else
Info.SwapBuffers = SwapBuffers;
Info.hWnd = NULL;
Info.hStatusBar = NULL;
#endif
Info.CheckInterrupts = DummyCheckInterrupts;
// We are initializing the plugin before any rom is loaded so we do not have any correct
@ -241,6 +256,7 @@ bool CGfxPlugin::Initiate(CN64System * System, RenderWindow * Window)
void CGfxPlugin::UnloadPluginDetails(void)
{
WriteTrace(TraceGFXPlugin, TraceDebug, "start");
if (m_LibHandle != NULL)
{
pjutil::DynLibClose(m_LibHandle);
@ -265,6 +281,7 @@ void CGfxPlugin::UnloadPluginDetails(void)
ViWidthChanged = NULL;
GetRomBrowserMenu = NULL;
OnRomBrowserMenuItem = NULL;
WriteTrace(TraceGFXPlugin, TraceDebug, "Done");
}
void CGfxPlugin::ProcessMenuItem(int32_t id)
@ -273,4 +290,17 @@ void CGfxPlugin::ProcessMenuItem(int32_t id)
{
m_GFXDebug.ProcessMenuItem(id);
}
}
}
#ifdef ANDROID
void CGfxPlugin::SwapBuffers(void)
{
RenderWindow * render = g_Plugins ? g_Plugins->MainWindow() : NULL;
WriteTrace(TraceGFXPlugin, TraceDebug, "Start (render: %p)",render);
if (render != NULL)
{
render->SwapWindow();
}
WriteTrace(TraceGFXPlugin, TraceDebug, "Done");
}
#endif

View File

@ -67,6 +67,10 @@ public:
void(CALL *ViStatusChanged) (void);
void(CALL *ViWidthChanged) (void);
void(CALL *SoftReset) (void);
#ifdef ANDROID
void(CALL *SurfaceCreated) (void);
void(CALL *SurfaceChanged) (int w, int h);
#endif
//Rom Browser
void *(CALL * GetRomBrowserMenu)(void); /* Items should have an ID between 4101 and 4200 */
@ -90,6 +94,9 @@ private:
void(CALL *GetDebugInfo) (GFXDEBUG_INFO * GFXDebugInfo);
void(CALL *InitiateDebugger)(DEBUG_INFO DebugInfo);
#ifdef ANDROID
static void SwapBuffers(void);
#endif
static void CALL DummyDrawScreen(void) {}
static void CALL DummyMoveScreen(int32_t /*xpos*/, int32_t /*ypos*/) {}
static void CALL DummyViStatusChanged(void) {}

View File

@ -31,11 +31,15 @@ m_RomOpen(false)
CPlugin::~CPlugin()
{
WriteTrace(PluginTraceType(), TraceDebug, "Start");
UnloadPlugin();
WriteTrace(PluginTraceType(), TraceDebug, "Done");
}
bool CPlugin::Load(const char * FileName)
{
WriteTrace(PluginTraceType(), TraceDebug, "Loading: %s",FileName);
// Already loaded, so unload first.
if (m_LibHandle != NULL)
{
@ -69,6 +73,7 @@ bool CPlugin::Load(const char * FileName)
LoadFunction(SetSettingInfo3);
if (SetSettingInfo3)
{
WriteTrace(PluginTraceType(), TraceDebug, "Found SetSettingInfo3");
PLUGIN_SETTINGS3 info;
info.FlushSettings = (void(*)(void * handle))CSettings::FlushSettings;
SetSettingInfo3(&info);
@ -77,6 +82,7 @@ bool CPlugin::Load(const char * FileName)
LoadFunction(SetSettingInfo2);
if (SetSettingInfo2)
{
WriteTrace(PluginTraceType(), TraceDebug, "Found SetSettingInfo2");
PLUGIN_SETTINGS2 info;
info.FindSystemSettingId = (uint32_t(*)(void * handle, const char *))CSettings::FindSetting;
SetSettingInfo2(&info);
@ -85,6 +91,7 @@ bool CPlugin::Load(const char * FileName)
LoadFunction(SetSettingInfo);
if (SetSettingInfo)
{
WriteTrace(PluginTraceType(), TraceDebug, "Found SetSettingInfo");
PLUGIN_SETTINGS info;
info.dwSize = sizeof(PLUGIN_SETTINGS);
info.DefaultStartRange = GetDefaultSettingStartRange();
@ -110,6 +117,7 @@ bool CPlugin::Load(const char * FileName)
if (!LoadFunctions())
{
WriteTrace(PluginTraceType(), TraceWarning, "Failed to load functions");
return false;
}
WriteTrace(PluginTraceType(), TraceDebug, "Functions loaded");
@ -120,54 +128,83 @@ bool CPlugin::Load(const char * FileName)
PluginOpened();
WriteTrace(PluginTraceType(), TraceDebug, "After Plugin Opened");
}
WriteTrace(PluginTraceType(), TraceDebug, "Loaded");
return true;
}
void CPlugin::RomOpened()
void CPlugin::RomOpened(RenderWindow * Render)
{
if (m_RomOpen)
{
return;
}
#ifdef ANDROID
if (m_PluginInfo.Type == PLUGIN_TYPE_GFX)
{
WriteTrace(PluginTraceType(), TraceDebug, "Render = %p", Render);
if (Render != NULL)
{
WriteTrace(PluginTraceType(), TraceDebug, "Calling GfxThreadInit");
Render->GfxThreadInit();
WriteTrace(PluginTraceType(), TraceDebug, "GfxThreadInit Done");
}
}
#else
Render = Render; // used just for andoid
#endif
if (RomOpen != NULL)
{
WriteTrace(PluginTraceType(), TraceDebug, "Before Rom Open");
RomOpen();
WriteTrace(PluginTraceType(), TraceDebug, "After Rom Open");
}
m_RomOpen = true;
}
void CPlugin::RomClose()
void CPlugin::RomClose(RenderWindow * Render)
{
if (!m_RomOpen)
{
return;
}
#ifdef ANDROID
if (m_PluginInfo.Type == PLUGIN_TYPE_GFX)
{
WriteTrace(PluginTraceType(), TraceDebug, "Render = %p", Render);
if (Render != NULL)
{
WriteTrace(PluginTraceType(), TraceDebug, "Calling GfxThreadDone");
Render->GfxThreadDone();
WriteTrace(PluginTraceType(), TraceDebug, "GfxThreadDone Done");
}
}
#else
Render = Render; // used just for andoid
#endif
WriteTrace(PluginTraceType(), TraceDebug, "Before Rom Close");
RomClosed();
m_RomOpen = false;
WriteTrace(PluginTraceType(), TraceDebug, "After Rom Close");
}
void CPlugin::GameReset()
void CPlugin::GameReset(RenderWindow * Render)
{
if (m_RomOpen)
{
RomClose();
if (RomOpen)
{
RomOpen();
}
RomClose(Render);
RomOpened(Render);
}
}
void CPlugin::Close()
void CPlugin::Close(RenderWindow * Render)
{
WriteTrace(PluginTraceType(), TraceDebug, "(%s): Start", PluginType());
RomClose();
RomClose(Render);
if (m_Initialized)
{
CloseDLL();
@ -178,11 +215,14 @@ void CPlugin::Close()
void CPlugin::UnloadPlugin()
{
WriteTrace(PluginTraceType(), TraceDebug, "(%s): unloading", PluginType());
WriteTrace(PluginTraceType(), TraceDebug, "(%s): Start", PluginType());
memset(&m_PluginInfo, 0, sizeof(m_PluginInfo));
if (m_LibHandle != NULL)
{
UnloadPluginDetails();
}
if (m_LibHandle != NULL)
{
pjutil::DynLibClose(m_LibHandle);
m_LibHandle = NULL;
}
@ -196,6 +236,7 @@ void CPlugin::UnloadPlugin()
SetSettingInfo = NULL;
SetSettingInfo2 = NULL;
SetSettingInfo3 = NULL;
WriteTrace(PluginTraceType(), TraceDebug, "(%s): Done", PluginType());
}
const char * CPlugin::PluginType() const

View File

@ -35,10 +35,10 @@ public:
bool Load(const char * FileName);
void RomOpened();
void RomClose();
void GameReset();
void Close();
void RomOpened(RenderWindow * Render);
void RomClose(RenderWindow * Render);
void GameReset(RenderWindow * Render);
void Close(RenderWindow * Render);
void(CALL *DllAbout) (void * hWnd);
void(CALL *DllConfig) (void * hParent);

View File

@ -60,6 +60,7 @@ CPlugins::~CPlugins(void)
void CPlugins::PluginChanged(CPlugins * _this)
{
WriteTrace(TracePlugins, TraceDebug, "Start");
if (g_Settings->LoadBool(Game_TempLoaded) == true)
{
WriteTrace(TracePlugins, TraceDebug, "Game is temporary loaded, not changing plugins");
@ -70,13 +71,20 @@ void CPlugins::PluginChanged(CPlugins * _this)
bool bAudioChange = _stricmp(_this->m_AudioFile.c_str(), g_Settings->LoadStringVal(Game_Plugin_Audio).c_str()) != 0;
bool bRspChange = _stricmp(_this->m_RSPFile.c_str(), g_Settings->LoadStringVal(Game_Plugin_RSP).c_str()) != 0;
bool bContChange = _stricmp(_this->m_ControlFile.c_str(), g_Settings->LoadStringVal(Game_Plugin_Controller).c_str()) != 0;
if (_stricmp(_this->m_PluginDir.c_str(), g_Settings->LoadStringVal(_this->m_PluginDirSetting).c_str()) != 0)
bool bDirChange = _stricmp(_this->m_PluginDir.c_str(), g_Settings->LoadStringVal(_this->m_PluginDirSetting).c_str()) != 0;
WriteTrace(TracePlugins, TraceVerbose, "m_GfxFile: \"%s\" Game_Plugin_Gfx: \"%s\" changed: %s",_this->m_GfxFile.c_str(), g_Settings->LoadStringVal(Game_Plugin_Gfx).c_str(), bGfxChange ? "true" : "false");
WriteTrace(TracePlugins, TraceVerbose, "m_AudioFile: \"%s\" Game_Plugin_Audio: \"%s\" changed: %s",_this->m_GfxFile.c_str(), g_Settings->LoadStringVal(Game_Plugin_Gfx).c_str(), bAudioChange ? "true" : "false");
WriteTrace(TracePlugins, TraceVerbose, "m_RSPFile: \"%s\" Game_Plugin_RSP: \"%s\" changed: %s",_this->m_GfxFile.c_str(), g_Settings->LoadStringVal(Game_Plugin_Gfx).c_str(), bRspChange ? "true" : "false");
WriteTrace(TracePlugins, TraceVerbose, "m_ControlFile: \"%s\" Game_Plugin_Controller: \"%s\" changed: %s",_this->m_GfxFile.c_str(), g_Settings->LoadStringVal(Game_Plugin_Gfx).c_str(), bContChange ? "true" : "false");
WriteTrace(TracePlugins, TraceVerbose, "m_PluginDir: \"%s\" m_PluginDirSetting: \"%s\" changed: %s",_this->m_PluginDir.c_str(), g_Settings->LoadStringVal(_this->m_PluginDirSetting).c_str(), bDirChange ? "true" : "false");
if (bDirChange)
{
WriteTrace(TracePlugins, TraceDebug, "plugin directory changed");
bGfxChange = true;
bAudioChange = true;
bRspChange = true;
bContChange = true;
WriteTrace(TracePlugins, TraceDebug, "plugin directory changed");
_this->m_PluginDir = g_Settings->LoadStringVal(_this->m_PluginDirSetting);
}
if (bGfxChange || bAudioChange || bRspChange || bContChange)
@ -135,6 +143,12 @@ static void LoadPlugin(SettingID PluginSettingID, SettingID PluginVerSettingID,
void CPlugins::CreatePlugins(void)
{
WriteTrace(TracePlugins, TraceInfo, "Start");
#ifdef ANDROID
//this is a hack and should not be here, glide64 is not correctly freeing something on restart, this needs to be fixed but this is a short term workaround
DestroyGfxPlugin();
#endif
LoadPlugin(Game_Plugin_Gfx, Plugin_GFX_CurVer, m_Gfx, m_PluginDir.c_str(), m_GfxFile, TraceGFXPlugin, "GFX");
LoadPlugin(Game_Plugin_Audio, Plugin_AUDIO_CurVer, m_Audio, m_PluginDir.c_str(), m_AudioFile, TraceAudioPlugin, "Audio");
LoadPlugin(Game_Plugin_RSP, Plugin_RSP_CurVer, m_RSP, m_PluginDir.c_str(), m_RSPFile, TraceRSPPlugin, "RSP");
@ -147,25 +161,26 @@ void CPlugins::CreatePlugins(void)
m_RSP->EnableDebugging(bHaveDebugger());
WriteTrace(TraceRSPPlugin, TraceInfo, "EnableDebugging done");
}
WriteTrace(TracePlugins, TraceInfo, "Done");
}
void CPlugins::GameReset(void)
{
if (m_Gfx)
{
m_Gfx->GameReset();
m_Gfx->GameReset(m_MainWindow);
}
if (m_Audio)
{
m_Audio->GameReset();
m_Audio->GameReset(m_MainWindow);
}
if (m_RSP)
{
m_RSP->GameReset();
m_RSP->GameReset(m_MainWindow);
}
if (m_Control)
{
m_Control->GameReset();
m_Control->GameReset(m_MainWindow);
}
}
@ -175,12 +190,13 @@ void CPlugins::DestroyGfxPlugin(void)
{
return;
}
WriteTrace(TraceGFXPlugin, TraceInfo, "before delete m_Gfx");
WriteTrace(TraceGFXPlugin, TraceInfo, "Start");
delete m_Gfx;
WriteTrace(TraceGFXPlugin, TraceInfo, "after delete m_Gfx");
WriteTrace(TraceGFXPlugin, TraceInfo, "m_Gfx deleted");
m_Gfx = NULL;
// g_Settings->UnknownSetting_GFX = NULL;
DestroyRspPlugin();
WriteTrace(TraceGFXPlugin, TraceInfo, "Done");
}
void CPlugins::DestroyAudioPlugin(void)
@ -190,7 +206,7 @@ void CPlugins::DestroyAudioPlugin(void)
return;
}
WriteTrace(TraceAudioPlugin, TraceDebug, "before close");
m_Audio->Close();
m_Audio->Close(m_MainWindow);
WriteTrace(TraceAudioPlugin, TraceDebug, "before delete");
delete m_Audio;
WriteTrace(TraceAudioPlugin, TraceDebug, "after delete");
@ -208,7 +224,7 @@ void CPlugins::DestroyRspPlugin(void)
return;
}
WriteTrace(TraceRSPPlugin, TraceDebug, "before close");
m_RSP->Close();
m_RSP->Close(m_MainWindow);
WriteTrace(TraceRSPPlugin, TraceDebug, "before delete");
delete m_RSP;
m_RSP = NULL;
@ -223,7 +239,7 @@ void CPlugins::DestroyControlPlugin(void)
return;
}
WriteTrace(TraceControllerPlugin, TraceDebug, "before close");
m_Control->Close();
m_Control->Close(m_MainWindow);
WriteTrace(TraceControllerPlugin, TraceDebug, "before delete");
delete m_Control;
m_Control = NULL;
@ -233,24 +249,25 @@ void CPlugins::DestroyControlPlugin(void)
void CPlugins::SetRenderWindows(RenderWindow * MainWindow, RenderWindow * SyncWindow)
{
WriteTrace(TracePlugins, TraceDebug, "MainWindow = %p SyncWindow = %p",MainWindow,SyncWindow);
m_MainWindow = MainWindow;
m_SyncWindow = SyncWindow;
}
void CPlugins::RomOpened(void)
{
m_Gfx->RomOpened();
m_RSP->RomOpened();
m_Audio->RomOpened();
m_Control->RomOpened();
m_Gfx->RomOpened(m_MainWindow);
m_RSP->RomOpened(m_MainWindow);
m_Audio->RomOpened(m_MainWindow);
m_Control->RomOpened(m_MainWindow);
}
void CPlugins::RomClosed(void)
{
m_Gfx->RomClose();
m_RSP->RomClose();
m_Audio->RomClose();
m_Control->RomClose();
m_Gfx->RomClose(m_MainWindow);
m_RSP->RomClose(m_MainWindow);
m_Audio->RomClose(m_MainWindow);
m_Control->RomClose(m_MainWindow);
}
bool CPlugins::Initiate(CN64System * System)
@ -280,7 +297,11 @@ bool CPlugins::Initiate(CN64System * System)
bool CPlugins::ResetInUiThread(CN64System * System)
{
#ifdef _WIN32
return m_MainWindow->ResetPluginsInUiThread(this, System);
#else
return false;
#endif
}
bool CPlugins::Reset(CN64System * System)

View File

@ -10,6 +10,7 @@
****************************************************************************/
#pragma once
#include <list>
#include <Project64-core/Settings/SettingsClass.h>
#include <Project64-core/Settings/DebugSettings.h>
#ifndef PLUGIN_INFO_STRUCT
@ -85,12 +86,24 @@ class CGfxPlugin; class CAudioPlugin; class CRSP_Plugin; class CControl_Plugin;
class CN64System;
class CPlugins;
#if defined(_WIN32)
#include <objbase.h>
#else
#define __interface struct
#endif
__interface RenderWindow
{
#ifdef _WIN32
virtual bool ResetPluginsInUiThread(CPlugins * plugins, CN64System * System) = 0;
virtual void * GetWindowHandle(void) const = 0;
virtual void * GetStatusBar(void) const = 0;
virtual void * GetModuleInstance(void) const = 0;
#else
virtual void GfxThreadInit() = 0;
virtual void GfxThreadDone() = 0;
virtual void SwapWindow() = 0;
#endif
};
class CPlugins :

View File

@ -30,7 +30,7 @@ CRSP_Plugin::CRSP_Plugin(void) :
CRSP_Plugin::~CRSP_Plugin()
{
Close();
Close(NULL);
UnloadPlugin();
}
@ -113,7 +113,11 @@ bool CRSP_Plugin::Initiate(CPlugins * Plugins, CN64System * System)
RSP_INFO_1_1 Info = { 0 };
Info.hInst = (Plugins != NULL && Plugins->MainWindow()!= NULL ) ? Plugins->MainWindow()->GetModuleInstance() : NULL;
#ifdef _WIN32
Info.hInst = (Plugins != NULL && Plugins->MainWindow() != NULL) ? Plugins->MainWindow()->GetModuleInstance() : NULL;
#else
Info.hInst = NULL;
#endif
Info.CheckInterrupts = DummyCheckInterrupts;
Info.MemoryBswaped = (System == NULL); // only true when the system's not yet loaded