#include #include #include #include #include #if defined(_WIN32) #define EXPORT extern "C" __declspec(dllexport) #define CALL __cdecl #else #define EXPORT extern "C" __attribute__((visibility("default"))) #define CALL #endif CNotification g_NotifyLocal; CNotification * g_Notify = &g_NotifyLocal; enum SettingLocation { SettingType_ConstString = 0, SettingType_ConstValue = 1, SettingType_CfgFile = 2, SettingType_Registry = 3, SettingType_RelativePath = 4, TemporarySetting = 5, SettingType_RomDatabase = 6, SettingType_CheatSetting = 7, SettingType_GameSetting = 8, SettingType_BoolVariable = 9, SettingType_NumberVariable = 10, SettingType_StringVariable = 11, SettingType_SelectedDirectory = 12, SettingType_RdbSetting = 13, }; enum SettingDataType { Data_DWORD = 0, Data_String = 1, Data_CPUTYPE = 2, Data_SelfMod = 3, Data_OnOff = 4, Data_YesNo = 5, Data_SaveChip = 6 }; typedef struct { uint32_t dwSize; int DefaultStartRange; int SettingStartRange; int MaximumSettings; int NoDefault; int DefaultLocation; void * handle; unsigned int(*GetSetting) (void * handle, int ID); const char * (*GetSettingSz) (void * handle, int ID, char * Buffer, int BufferLen); void(*SetSetting) (void * handle, int ID, unsigned int Value); void(*SetSettingSz) (void * handle, int ID, const char * Value); void(*RegisterSetting) (void * handle, int ID, int DefaultID, SettingDataType Type, SettingLocation Location, const char * Category, const char * DefaultStr, uint32_t Value); void(*UseUnregisteredSetting) (int ID); } PLUGIN_SETTINGS; typedef struct { unsigned int(*FindSystemSettingId) (void * handle, const char * Name); } PLUGIN_SETTINGS2; typedef struct { void(*FlushSettings) (void * handle); } PLUGIN_SETTINGS3; typedef struct { typedef void(*SettingChangedFunc)(void *); void(*RegisterChangeCB)(void * handle, int ID, void * Data, SettingChangedFunc Func); void(*UnregisterChangeCB)(void * handle, int ID, void * Data, SettingChangedFunc Func); } PLUGIN_SETTINGS_NOTIFICATION; typedef struct { void(*DisplayError)(const char * Message); void(*FatalError)(const char * Message); void(*DisplayMessage)(int DisplayTime, const char * Message); void(*DisplayMessage2)(const char * Message); void(*BreakPoint)(const char * FileName, int32_t LineNumber); } PLUGIN_NOTIFICATION; static PLUGIN_SETTINGS g_PluginSettings; static PLUGIN_SETTINGS2 g_PluginSettings2; static PLUGIN_SETTINGS3 g_PluginSettings3; static PLUGIN_SETTINGS_NOTIFICATION g_PluginSettingsNotification; static PLUGIN_NOTIFICATION g_PluginNotification; static bool g_PluginInitilized = false; static char g_PluginSettingName[300]; EXPORT void SetSettingInfo(PLUGIN_SETTINGS * info); EXPORT void SetSettingInfo2(PLUGIN_SETTINGS2 * info); EXPORT void SetSettingInfo3(PLUGIN_SETTINGS3 * info); EXPORT void SetPluginNotification(PLUGIN_NOTIFICATION * info); EXPORT void SetSettingInfo(PLUGIN_SETTINGS * info) { g_PluginSettings = *info; g_PluginInitilized = true; info->UseUnregisteredSetting = UseUnregisteredSetting; } EXPORT void SetSettingInfo2(PLUGIN_SETTINGS2 * info) { g_PluginSettings2 = *info; } EXPORT void SetSettingInfo3(PLUGIN_SETTINGS3 * info) { g_PluginSettings3 = *info; } EXPORT void SetSettingNotificationInfo(PLUGIN_SETTINGS_NOTIFICATION * info) { g_PluginSettingsNotification = *info; } EXPORT void SetPluginNotification(PLUGIN_NOTIFICATION * info) { g_PluginNotification = *info; } int32_t SettingsInitilized(void) { return g_PluginInitilized; } void SetModuleName(const char * Name) { _snprintf(g_PluginSettingName, sizeof(g_PluginSettingName), "%s", Name); } void RegisterSetting(short SettingID, SETTING_DATA_TYPE Type, const char * Name, const char * Category, unsigned int DefaultDW, const char * DefaultStr) { if (g_PluginSettings.RegisterSetting == nullptr) { return; } int DefaultID = g_PluginSettings.NoDefault; SettingLocation Location = (SettingLocation)g_PluginSettings.DefaultLocation; char FullCategory[400]; if (Category && Category[0] != 0) { _snprintf(FullCategory, sizeof(FullCategory), "%s\\%s", g_PluginSettingName, Category); } else { _snprintf(FullCategory, sizeof(FullCategory), "%s", g_PluginSettingName); } switch (Type) { case Data_DWORD_Game: case Data_String_Game: Location = SettingType_GameSetting; break; case Data_DWORD_RDB: case Data_String_RDB: Location = SettingType_RomDatabase; break; case Data_DWORD_RDB_Setting: case Data_String_RDB_Setting: Location = SettingType_RdbSetting; break; case Data_DWORD_General: case Data_String_General: default: Location = (SettingLocation)g_PluginSettings.DefaultLocation; break; } switch (Type) { case Data_DWORD_Game: g_PluginSettings.RegisterSetting(g_PluginSettings.handle, SettingID + g_PluginSettings.SettingStartRange, g_PluginSettings.NoDefault, Data_DWORD, Location, FullCategory, Name, DefaultDW); break; case Data_DWORD_General: case Data_DWORD_RDB: case Data_DWORD_RDB_Setting: if (DefaultDW != 0) { // Create default DefaultID = SettingID + g_PluginSettings.DefaultStartRange; g_PluginSettings.RegisterSetting(g_PluginSettings.handle, DefaultID, g_PluginSettings.NoDefault, Data_DWORD, SettingType_ConstValue, g_PluginSettingName, "", DefaultDW); } g_PluginSettings.RegisterSetting(g_PluginSettings.handle, SettingID + g_PluginSettings.SettingStartRange, DefaultID, Data_DWORD, Location, FullCategory, Name, 0); break; case Data_String_General: case Data_String_Game: case Data_String_RDB: case Data_String_RDB_Setting: if (DefaultStr != nullptr && strlen(DefaultStr) > 0) { // Create default DefaultID = SettingID + g_PluginSettings.DefaultStartRange; g_PluginSettings.RegisterSetting(g_PluginSettings.handle, DefaultID, g_PluginSettings.NoDefault, Data_String, SettingType_ConstString, g_PluginSettingName, DefaultStr, 0); } g_PluginSettings.RegisterSetting(g_PluginSettings.handle, SettingID + g_PluginSettings.SettingStartRange, DefaultID, Data_String, Location, FullCategory, Name, 0); break; } } void RegisterSetting2(short SettingID, SETTING_DATA_TYPE Type, const char * Name, const char * Category, short DefaultID) { SettingLocation Location = (SettingLocation)g_PluginSettings.DefaultLocation; char FullCategory[400]; if (Category && Category[0] != 0) { _snprintf(FullCategory, sizeof(FullCategory), "%s\\%s", g_PluginSettingName, Category); } else { _snprintf(FullCategory, sizeof(FullCategory), "%s", g_PluginSettingName); } switch (Type) { case Data_DWORD_Game: case Data_String_Game: Location = SettingType_GameSetting; break; case Data_DWORD_RDB: case Data_String_RDB: Location = SettingType_RomDatabase; break; case Data_DWORD_RDB_Setting: case Data_String_RDB_Setting: Location = SettingType_RdbSetting; break; case Data_DWORD_General: case Data_String_General: default: Location = (SettingLocation)g_PluginSettings.DefaultLocation; break; } switch (Type) { case Data_DWORD_Game: case Data_DWORD_General: case Data_DWORD_RDB: case Data_DWORD_RDB_Setting: g_PluginSettings.RegisterSetting(g_PluginSettings.handle, SettingID + g_PluginSettings.SettingStartRange, DefaultID + g_PluginSettings.SettingStartRange, Data_DWORD, Location, FullCategory, Name, 0); break; case Data_String_General: case Data_String_Game: case Data_String_RDB: case Data_String_RDB_Setting: g_PluginSettings.RegisterSetting(g_PluginSettings.handle, SettingID + g_PluginSettings.SettingStartRange, DefaultID + g_PluginSettings.SettingStartRange, Data_String, Location, FullCategory, Name, 0); break; } } short FindSystemSettingId(const char * Name) { if (g_PluginSettings2.FindSystemSettingId && g_PluginSettings.handle) { return (short)g_PluginSettings2.FindSystemSettingId(g_PluginSettings.handle, Name); } return 0; } void FlushSettings(void) { if (g_PluginSettings3.FlushSettings && g_PluginSettings.handle) { g_PluginSettings3.FlushSettings(g_PluginSettings.handle); } } unsigned int GetSetting(short SettingID) { if (g_PluginSettings.GetSetting == nullptr) { return 0; } return g_PluginSettings.GetSetting(g_PluginSettings.handle, SettingID + g_PluginSettings.SettingStartRange); } unsigned int GetSystemSetting(short SettingID) { return g_PluginSettings.GetSetting(g_PluginSettings.handle, SettingID); } const char * GetSettingSz(short SettingID, char * Buffer, int BufferLen) { return g_PluginSettings.GetSettingSz(g_PluginSettings.handle, SettingID + g_PluginSettings.SettingStartRange, Buffer, BufferLen); } const char * GetSystemSettingSz(short SettingID, char * Buffer, int BufferLen) { if (g_PluginSettings.GetSettingSz == nullptr) { return ""; } return g_PluginSettings.GetSettingSz(g_PluginSettings.handle, SettingID, Buffer, BufferLen); } void SetSetting(short SettingID, unsigned int Value) { g_PluginSettings.SetSetting(g_PluginSettings.handle, SettingID + g_PluginSettings.SettingStartRange, Value); } void SetSettingSz(short SettingID, const char * Value) { g_PluginSettings.SetSettingSz(g_PluginSettings.handle, SettingID + g_PluginSettings.SettingStartRange, Value); } void SetSystemSetting(short SettingID, unsigned int Value) { g_PluginSettings.SetSetting(g_PluginSettings.handle, SettingID, Value); } void SetSystemSettingSz(short SettingID, const char * Value) { g_PluginSettings.SetSettingSz(g_PluginSettings.handle, SettingID, Value); } void SettingsRegisterChange(bool SystemSetting, int SettingID, void * Data, SettingChangedFunc Func) { if (g_PluginSettingsNotification.RegisterChangeCB && g_PluginSettings.handle) { g_PluginSettingsNotification.RegisterChangeCB(g_PluginSettings.handle, SettingID + (SystemSetting ? 0 : g_PluginSettings.SettingStartRange), Data, Func); } } void SettingsUnregisterChange(bool SystemSetting, int SettingID, void * Data, SettingChangedFunc Func) { if (g_PluginSettingsNotification.UnregisterChangeCB && g_PluginSettings.handle) { g_PluginSettingsNotification.UnregisterChangeCB(g_PluginSettings.handle, SettingID + (SystemSetting ? 0 : g_PluginSettings.SettingStartRange), Data, Func); } } void CNotification::DisplayError(const char * Message) { if (g_PluginNotification.BreakPoint != nullptr) { g_PluginNotification.DisplayError(Message); } } void CNotification::FatalError(const char * Message) { if (g_PluginNotification.BreakPoint != nullptr) { g_PluginNotification.FatalError(Message); } } void CNotification::DisplayMessage(int DisplayTime, const char * Message) { if (g_PluginNotification.BreakPoint != nullptr) { g_PluginNotification.DisplayMessage(DisplayTime, Message); } } void CNotification::DisplayMessage2(const char * Message) { if (g_PluginNotification.BreakPoint != nullptr) { g_PluginNotification.DisplayMessage2(Message); } } void CNotification::BreakPoint(const char * FileName, int LineNumber) { if (g_PluginNotification.BreakPoint != nullptr) { g_PluginNotification.BreakPoint(FileName, LineNumber); } }