From a50068d61d2691e12e9fb95b78e07fd7452851d4 Mon Sep 17 00:00:00 2001 From: pjgat09 Date: Thu, 2 May 2013 02:19:36 +0000 Subject: [PATCH] m64p: Added a stub for a bizhawk handled input plugin --- .../output/dll/mupen64plus-input-bkm.dll | Bin 0 -> 9216 bytes .../mupen64plus-input-bkm.vcxproj | 88 ++++ .../mupen64plus-input-bkm/osal_dynamiclib.h | 30 ++ .../osal_dynamiclib_unix.c | 37 ++ .../osal_dynamiclib_win32.c | 74 +++ .../mupen64plus-input-bkm/osal_preproc.h | 33 ++ libmupen64plus/mupen64plus-input-bkm/plugin.c | 457 ++++++++++++++++++ libmupen64plus/mupen64plus-input-bkm/plugin.h | 175 +++++++ .../mupen64plus-input-bkm/version.h | 37 ++ .../msvc11/mupen64plus-ui-console.sln | 6 + 10 files changed, 937 insertions(+) create mode 100644 BizHawk.MultiClient/output/dll/mupen64plus-input-bkm.dll create mode 100644 libmupen64plus/mupen64plus-input-bkm/mupen64plus-input-bkm/mupen64plus-input-bkm.vcxproj create mode 100644 libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib.h create mode 100644 libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib_unix.c create mode 100644 libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib_win32.c create mode 100644 libmupen64plus/mupen64plus-input-bkm/osal_preproc.h create mode 100644 libmupen64plus/mupen64plus-input-bkm/plugin.c create mode 100644 libmupen64plus/mupen64plus-input-bkm/plugin.h create mode 100644 libmupen64plus/mupen64plus-input-bkm/version.h diff --git a/BizHawk.MultiClient/output/dll/mupen64plus-input-bkm.dll b/BizHawk.MultiClient/output/dll/mupen64plus-input-bkm.dll new file mode 100644 index 0000000000000000000000000000000000000000..f3e19c734ce14392365b56ffb8e99b7d6215031e GIT binary patch literal 9216 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 + + + + Debug + Win32 + + + Release + Win32 + + + + {3D8BD211-6002-4698-B5C1-A0F3146B6ACF} + mupen64plusinputbkm + + + + Application + true + v110 + MultiByte + + + DynamicLibrary + false + v100 + true + MultiByte + + + + + + + + + + + + + false + + + + Level3 + Disabled + + + true + + + + + Level3 + MaxSpeed + + + false + ..\..\mupen64plus-core\src\api;..\..\mupen64plus-win32-deps\SDL-1.2.14\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + + + + true + true + true + ..\..\mupen64plus-win32-deps\SDL-1.2.14\lib\SDL.lib;%(AdditionalDependencies) + Windows + + + xcopy /y $(OutDir)$(TargetName)$(TargetExt) $(TargetDir)..\..\..\..\..\BizHawk.MultiClient\output\dll\ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib.h b/libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib.h new file mode 100644 index 0000000000..daef1541c0 --- /dev/null +++ b/libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib.h @@ -0,0 +1,30 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-core - osal/dynamiclib.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009 Richard Goedeken * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#if !defined(OSAL_DYNAMICLIB_H) +#define OSAL_DYNAMICLIB_H + +#include "m64p_types.h" + +void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName); + +#endif /* #define OSAL_DYNAMICLIB_H */ + diff --git a/libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib_unix.c b/libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib_unix.c new file mode 100644 index 0000000000..b3b7ba52dc --- /dev/null +++ b/libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib_unix.c @@ -0,0 +1,37 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-core - osal/dynamiclib_unix.c * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009 Richard Goedeken * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +#include +#include + +#include "m64p_types.h" +#include "osal_dynamiclib.h" + +void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName) +{ + if (pccProcedureName == NULL) + return NULL; + + return dlsym(LibHandle, pccProcedureName); +} + + diff --git a/libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib_win32.c b/libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib_win32.c new file mode 100644 index 0000000000..4455cee52b --- /dev/null +++ b/libmupen64plus/mupen64plus-input-bkm/osal_dynamiclib_win32.c @@ -0,0 +1,74 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-ui-console - osal_dynamiclib_win32.c * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009 Richard Goedeken * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +#include +#include + +#include "m64p_types.h" +#include "osal_dynamiclib.h" + +m64p_error osal_dynlib_open(m64p_dynlib_handle *pLibHandle, const char *pccLibraryPath) +{ + if (pLibHandle == NULL || pccLibraryPath == NULL) + return M64ERR_INPUT_ASSERT; + + *pLibHandle = LoadLibrary(pccLibraryPath); + + if (*pLibHandle == NULL) + { + char *pchErrMsg; + DWORD dwErr = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL); + fprintf(stderr, "LoadLibrary('%s') error: %s\n", pccLibraryPath, pchErrMsg); + LocalFree(pchErrMsg); + return M64ERR_INPUT_NOT_FOUND; + } + + return M64ERR_SUCCESS; +} + +void * osal_dynlib_getproc(m64p_dynlib_handle LibHandle, const char *pccProcedureName) +{ + if (pccProcedureName == NULL) + return NULL; + + return GetProcAddress(LibHandle, pccProcedureName); +} + +m64p_error osal_dynlib_close(m64p_dynlib_handle LibHandle) +{ + int rval = FreeLibrary(LibHandle); + + if (rval == 0) + { + char *pchErrMsg; + DWORD dwErr = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pchErrMsg, 0, NULL); + fprintf(stderr, "FreeLibrary() error: %s\n", pchErrMsg); + LocalFree(pchErrMsg); + return M64ERR_INTERNAL; + } + + return M64ERR_SUCCESS; +} diff --git a/libmupen64plus/mupen64plus-input-bkm/osal_preproc.h b/libmupen64plus/mupen64plus-input-bkm/osal_preproc.h new file mode 100644 index 0000000000..37c7dc4a86 --- /dev/null +++ b/libmupen64plus/mupen64plus-input-bkm/osal_preproc.h @@ -0,0 +1,33 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus - osal_preproc.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009 Richard Goedeken * + * Copyright (C) 2002 Hacktarux * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* this header file is for system-dependent #defines, #includes, and typedefs */ + +#if !defined(OSAL_PREPROC_H) +#define OSAL_PREPROC_H + +#if defined(WIN32) + #define strcasestr strstr + #define strcasecmp _stricmp +#endif // WIN32 + +#endif // OSAL_PREPROC_H diff --git a/libmupen64plus/mupen64plus-input-bkm/plugin.c b/libmupen64plus/mupen64plus-input-bkm/plugin.c new file mode 100644 index 0000000000..5cc29f46de --- /dev/null +++ b/libmupen64plus/mupen64plus-input-bkm/plugin.c @@ -0,0 +1,457 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-input-sdl - plugin.c * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2008-2011 Richard Goedeken * + * Copyright (C) 2008 Tillin9 * + * Copyright (C) 2002 Blight * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include +#include +#include + +#define M64P_PLUGIN_PROTOTYPES 1 +#include "m64p_types.h" +#include "m64p_plugin.h" +#include "m64p_common.h" +#include "m64p_config.h" + +#include "plugin.h" +#include "config.h" +#include "version.h" +#include "osal_dynamiclib.h" + +#include + +/* definitions of pointers to Core config functions */ +ptr_ConfigOpenSection ConfigOpenSection = NULL; +ptr_ConfigDeleteSection ConfigDeleteSection = NULL; +ptr_ConfigSetParameter ConfigSetParameter = NULL; +ptr_ConfigGetParameter ConfigGetParameter = NULL; +ptr_ConfigGetParameterHelp ConfigGetParameterHelp = NULL; +ptr_ConfigSetDefaultInt ConfigSetDefaultInt = NULL; +ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat = NULL; +ptr_ConfigSetDefaultBool ConfigSetDefaultBool = NULL; +ptr_ConfigSetDefaultString ConfigSetDefaultString = NULL; +ptr_ConfigGetParamInt ConfigGetParamInt = NULL; +ptr_ConfigGetParamFloat ConfigGetParamFloat = NULL; +ptr_ConfigGetParamBool ConfigGetParamBool = NULL; +ptr_ConfigGetParamString ConfigGetParamString = NULL; + +ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath = NULL; +ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath = NULL; +ptr_ConfigGetUserDataPath ConfigGetUserDataPath = NULL; +ptr_ConfigGetUserCachePath ConfigGetUserCachePath = NULL; + +/* global data definitions */ +SController controller[4]; // 4 controllers + +/* static data definitions */ +static void (*l_DebugCallback)(void *, int, const char *) = NULL; +static void *l_DebugCallContext = NULL; +static int l_PluginInit = 0; + +static unsigned short button_bits[] = { + 0x0001, // R_DPAD + 0x0002, // L_DPAD + 0x0004, // D_DPAD + 0x0008, // U_DPAD + 0x0010, // START_BUTTON + 0x0020, // Z_TRIG + 0x0040, // B_BUTTON + 0x0080, // A_BUTTON + 0x0100, // R_CBUTTON + 0x0200, // L_CBUTTON + 0x0400, // D_CBUTTON + 0x0800, // U_CBUTTON + 0x1000, // R_TRIG + 0x2000, // L_TRIG + 0x4000, // Mempak switch + 0x8000 // Rumblepak switch +}; + +static int romopen = 0; // is a rom opened + +static unsigned char myKeyState[SDL_NUM_SCANCODES]; + +#ifdef __linux__ +static struct ff_effect ffeffect[3]; +static struct ff_effect ffstrong[3]; +static struct ff_effect ffweak[3]; +#endif //__linux__ + +/* Global functions */ +void DebugMessage(int level, const char *message, ...) +{ + char msgbuf[1024]; + va_list args; + + if (l_DebugCallback == NULL) + return; + + va_start(args, message); + vsprintf(msgbuf, message, args); + + (*l_DebugCallback)(l_DebugCallContext, level, msgbuf); + + va_end(args); +} + +static CONTROL temp_core_controlinfo[4]; + +/* Mupen64Plus plugin functions */ +EXPORT m64p_error CALL PluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context, + void (*DebugCallback)(void *, int, const char *)) +{ + ptr_CoreGetAPIVersions CoreAPIVersionFunc; + + int i, ConfigAPIVersion, DebugAPIVersion, VidextAPIVersion; + + if (l_PluginInit) + return M64ERR_ALREADY_INIT; + + /* first thing is to set the callback function for debug info */ + l_DebugCallback = DebugCallback; + l_DebugCallContext = Context; + + /* attach and call the CoreGetAPIVersions function, check Config API version for compatibility */ + CoreAPIVersionFunc = (ptr_CoreGetAPIVersions) osal_dynlib_getproc(CoreLibHandle, "CoreGetAPIVersions"); + if (CoreAPIVersionFunc == NULL) + { + DebugMessage(M64MSG_ERROR, "Core emulator broken; no CoreAPIVersionFunc() function found."); + return M64ERR_INCOMPATIBLE; + } + + (*CoreAPIVersionFunc)(&ConfigAPIVersion, &DebugAPIVersion, &VidextAPIVersion, NULL); + if ((ConfigAPIVersion & 0xffff0000) != (CONFIG_API_VERSION & 0xffff0000)) + { + DebugMessage(M64MSG_ERROR, "Emulator core Config API (v%i.%i.%i) incompatible with plugin (v%i.%i.%i)", + VERSION_PRINTF_SPLIT(ConfigAPIVersion), VERSION_PRINTF_SPLIT(CONFIG_API_VERSION)); + return M64ERR_INCOMPATIBLE; + } + + /* Get the core config function pointers from the library handle */ + ConfigOpenSection = (ptr_ConfigOpenSection) osal_dynlib_getproc(CoreLibHandle, "ConfigOpenSection"); + ConfigDeleteSection = (ptr_ConfigDeleteSection) osal_dynlib_getproc(CoreLibHandle, "ConfigDeleteSection"); + ConfigSetParameter = (ptr_ConfigSetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigSetParameter"); + ConfigGetParameter = (ptr_ConfigGetParameter) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParameter"); + ConfigSetDefaultInt = (ptr_ConfigSetDefaultInt) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultInt"); + ConfigSetDefaultFloat = (ptr_ConfigSetDefaultFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultFloat"); + ConfigSetDefaultBool = (ptr_ConfigSetDefaultBool) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultBool"); + ConfigSetDefaultString = (ptr_ConfigSetDefaultString) osal_dynlib_getproc(CoreLibHandle, "ConfigSetDefaultString"); + ConfigGetParamInt = (ptr_ConfigGetParamInt) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamInt"); + ConfigGetParamFloat = (ptr_ConfigGetParamFloat) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamFloat"); + ConfigGetParamBool = (ptr_ConfigGetParamBool) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamBool"); + ConfigGetParamString = (ptr_ConfigGetParamString) osal_dynlib_getproc(CoreLibHandle, "ConfigGetParamString"); + + ConfigGetSharedDataFilepath = (ptr_ConfigGetSharedDataFilepath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetSharedDataFilepath"); + ConfigGetUserConfigPath = (ptr_ConfigGetUserConfigPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserConfigPath"); + ConfigGetUserDataPath = (ptr_ConfigGetUserDataPath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserDataPath"); + ConfigGetUserCachePath = (ptr_ConfigGetUserCachePath) osal_dynlib_getproc(CoreLibHandle, "ConfigGetUserCachePath"); + + if (!ConfigOpenSection || !ConfigDeleteSection || !ConfigSetParameter || !ConfigGetParameter || + !ConfigSetDefaultInt || !ConfigSetDefaultFloat || !ConfigSetDefaultBool || !ConfigSetDefaultString || + !ConfigGetParamInt || !ConfigGetParamFloat || !ConfigGetParamBool || !ConfigGetParamString || + !ConfigGetSharedDataFilepath || !ConfigGetUserConfigPath || !ConfigGetUserDataPath || !ConfigGetUserCachePath) + { + DebugMessage(M64MSG_ERROR, "Couldn't connect to Core configuration functions"); + return M64ERR_INCOMPATIBLE; + } + + /* reset controllers */ + memset(controller, 0, sizeof(SController) * 4); + for (i = 0; i < SDL_NUM_SCANCODES; i++) + { + myKeyState[i] = 0; + } + /* set CONTROL struct pointers to the temporary static array */ + /* this small struct is used to tell the core whether each controller is plugged in, and what type of pak is connected */ + /* we only need it so that we can call load_configuration below, to auto-config for a GUI front-end */ + for (i = 0; i < 4; i++) + controller[i].control = temp_core_controlinfo + i; + + l_PluginInit = 1; + return M64ERR_SUCCESS; +} + +EXPORT m64p_error CALL PluginShutdown(void) +{ + if (!l_PluginInit) + return M64ERR_NOT_INIT; + + /* reset some local variables */ + l_DebugCallback = NULL; + l_DebugCallContext = NULL; + + l_PluginInit = 0; + return M64ERR_SUCCESS; +} + +EXPORT m64p_error CALL PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities) +{ + /* set version info */ + if (PluginType != NULL) + *PluginType = M64PLUGIN_INPUT; + + if (PluginVersion != NULL) + *PluginVersion = PLUGIN_VERSION; + + if (APIVersion != NULL) + *APIVersion = INPUT_PLUGIN_API_VERSION; + + if (PluginNamePtr != NULL) + *PluginNamePtr = PLUGIN_NAME; + + if (Capabilities != NULL) + { + *Capabilities = 0; + } + + return M64ERR_SUCCESS; +} + +static unsigned char DataCRC( unsigned char *Data, int iLenght ) +{ + unsigned char Remainder = Data[0]; + + int iByte = 1; + unsigned char bBit = 0; + + while( iByte <= iLenght ) + { + int HighBit = ((Remainder & 0x80) != 0); + Remainder = Remainder << 1; + + Remainder += ( iByte < iLenght && Data[iByte] & (0x80 >> bBit )) ? 1 : 0; + + Remainder ^= (HighBit) ? 0x85 : 0; + + bBit++; + iByte += bBit/8; + bBit %= 8; + } + + return Remainder; +} + +/****************************************************************** + Function: ControllerCommand + Purpose: To process the raw data that has just been sent to a + specific controller. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + + note: This function is only needed if the DLL is allowing raw + data, or the plugin is set to raw + + the data that is being processed looks like this: + initilize controller: 01 03 00 FF FF FF + read controller: 01 04 01 FF FF FF FF +*******************************************************************/ +EXPORT void CALL ControllerCommand(int Control, unsigned char *Command) +{ + unsigned char *Data = &Command[5]; + + if (Control == -1) + return; + + switch (Command[2]) + { + case RD_GETSTATUS: +#ifdef _DEBUG + DebugMessage(M64MSG_INFO, "Get status"); +#endif + break; + case RD_READKEYS: +#ifdef _DEBUG + DebugMessage(M64MSG_INFO, "Read keys"); +#endif + break; + case RD_READPAK: +#ifdef _DEBUG + DebugMessage(M64MSG_INFO, "Read pak"); +#endif + if (controller[Control].control->Plugin == PLUGIN_RAW) + { + unsigned int dwAddress = (Command[3] << 8) + (Command[4] & 0xE0); + + if(( dwAddress >= 0x8000 ) && ( dwAddress < 0x9000 ) ) + memset( Data, 0x80, 32 ); + else + memset( Data, 0x00, 32 ); + + Data[32] = DataCRC( Data, 32 ); + } + break; + case RD_WRITEPAK: +#ifdef _DEBUG + DebugMessage(M64MSG_INFO, "Write pak"); +#endif + if (controller[Control].control->Plugin == PLUGIN_RAW) + { + unsigned int dwAddress = (Command[3] << 8) + (Command[4] & 0xE0); + if (dwAddress == PAK_IO_RUMBLE && *Data) + DebugMessage(M64MSG_VERBOSE, "Triggering rumble pack."); +#ifdef __linux__ + struct input_event play; + if( dwAddress == PAK_IO_RUMBLE && controller[Control].event_joystick != 0) + { + if( *Data ) + { + play.type = EV_FF; + play.code = ffeffect[Control].id; + play.value = 1; + + if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1) + perror("Error starting rumble effect"); + + } + else + { + play.type = EV_FF; + play.code = ffeffect[Control].id; + play.value = 0; + + if (write(controller[Control].event_joystick, (const void*) &play, sizeof(play)) == -1) + perror("Error stopping rumble effect"); + } + } +#endif //__linux__ + Data[32] = DataCRC( Data, 32 ); + } + break; + case RD_RESETCONTROLLER: +#ifdef _DEBUG + DebugMessage(M64MSG_INFO, "Reset controller"); +#endif + break; + case RD_READEEPROM: +#ifdef _DEBUG + DebugMessage(M64MSG_INFO, "Read eeprom"); +#endif + break; + case RD_WRITEEPROM: +#ifdef _DEBUG + DebugMessage(M64MSG_INFO, "Write eeprom"); +#endif + break; + } +} + +/****************************************************************** + Function: GetKeys + Purpose: To get the current state of the controllers buttons. + input: - Controller Number (0 to 3) + - A pointer to a BUTTONS structure to be filled with + the controller state. + output: none +*******************************************************************/ +EXPORT void CALL GetKeys( int Control, BUTTONS *Keys ) +{ + // Use a call back function here, or look up a buffer +} + +/****************************************************************** + Function: InitiateControllers + Purpose: This function initialises how each of the controllers + should be handled. + input: - The handle to the main window. + - A controller structure that needs to be filled for + the emulator to know how to handle each controller. + output: none +*******************************************************************/ +EXPORT void CALL InitiateControllers(CONTROL_INFO ControlInfo) +{ + int i; + + for( i = 0; i < 4; i++ ) + { + controller[i].control->Plugin = PLUGIN_MEMPAK; + } + + DebugMessage(M64MSG_INFO, "%s version %i.%i.%i initialized.", PLUGIN_NAME, VERSION_PRINTF_SPLIT(PLUGIN_VERSION)); +} + +/****************************************************************** + Function: ReadController + Purpose: To process the raw data in the pif ram that is about to + be read. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + note: This function is only needed if the DLL is allowing raw + data. +*******************************************************************/ +EXPORT void CALL ReadController(int Control, unsigned char *Command) +{ +#ifdef _DEBUG + if (Command != NULL) + DebugMessage(M64MSG_INFO, "Raw Read (cont=%d): %02X %02X %02X %02X %02X %02X", Control, + Command[0], Command[1], Command[2], Command[3], Command[4], Command[5]); +#endif +} + +/****************************************************************** + Function: RomClosed + Purpose: This function is called when a rom is closed. + input: none + output: none +*******************************************************************/ +EXPORT void CALL RomClosed(void) +{ + romopen = 0; +} + +/****************************************************************** + Function: RomOpen + Purpose: This function is called when a rom is open. (from the + emulation thread) + input: none + output: none +*******************************************************************/ +EXPORT int CALL RomOpen(void) +{ + romopen = 1; + return 1; +} + +/****************************************************************** + Function: SDL_KeyDown + Purpose: To pass the SDL_KeyDown message from the emulator to the + plugin. + input: keymod and keysym of the SDL_KEYDOWN message. + output: none +*******************************************************************/ +EXPORT void CALL SDL_KeyDown(int keymod, int keysym) +{ +} + +/****************************************************************** + Function: SDL_KeyUp + Purpose: To pass the SDL_KeyUp message from the emulator to the + plugin. + input: keymod and keysym of the SDL_KEYUP message. + output: none +*******************************************************************/ +EXPORT void CALL SDL_KeyUp(int keymod, int keysym) +{ +} + diff --git a/libmupen64plus/mupen64plus-input-bkm/plugin.h b/libmupen64plus/mupen64plus-input-bkm/plugin.h new file mode 100644 index 0000000000..882d422cbb --- /dev/null +++ b/libmupen64plus/mupen64plus-input-bkm/plugin.h @@ -0,0 +1,175 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-input-sdl - plugin.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2008-2009 Richard Goedeken * + * Copyright (C) 2008 Tillin9 * + * Copyright (C) 2002 Blight * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef __PLUGIN_H__ +#define __PLUGIN_H__ + +#include +#if ! SDL_VERSION_ATLEAST(1,3,0) + +#define SDL_GetKeyboardState SDL_GetKeyState +#define SDL_SCANCODE_UNKNOWN SDLK_UNKNOWN +#define SDL_NUM_SCANCODES SDLK_LAST +#define SDL_SCANCODE_RCTRL SDLK_RCTRL +#define SDL_SCANCODE_RSHIFT SDLK_RSHIFT +#define SDL_SCANCODE_LCTRL SDLK_LCTRL +#define SDL_SCANCODE_LALT SDLK_LALT +#define SDL_Scancode SDLKey + +#endif + +#if SDL_VERSION_ATLEAST(2,0,0) + +static inline const char* _SDL_JoystickName(int device_index) +{ + SDL_Joystick *joystick; + const char *name; + static char JoyName[256]; + + joystick = SDL_JoystickOpen(device_index); + if (!joystick) + return NULL; + + name = SDL_JoystickName(joystick); + if (name) + { + strncpy(JoyName, name, 255); + JoyName[255] = 0; + } + SDL_JoystickClose(joystick); + + return JoyName; +} + +#define SDL_JoystickName(device_index) _SDL_JoystickName(device_index) + +#endif + +#define M64P_PLUGIN_PROTOTYPES 1 +#include "m64p_plugin.h" +#include "m64p_config.h" + +#define DEVICE_AUTO (-1) +#define DEVICE_NOT_JOYSTICK (-2) + +// Some stuff from n-rage plugin +#define RD_GETSTATUS 0x00 // get status +#define RD_READKEYS 0x01 // read button values +#define RD_READPAK 0x02 // read from controllerpack +#define RD_WRITEPAK 0x03 // write to controllerpack +#define RD_RESETCONTROLLER 0xff // reset controller +#define RD_READEEPROM 0x04 // read eeprom +#define RD_WRITEEPROM 0x05 // write eeprom + +#define PAK_IO_RUMBLE 0xC000 // the address where rumble-commands are sent to + +enum EButton +{ + R_DPAD = 0, + L_DPAD, + D_DPAD, + U_DPAD, + START_BUTTON, + Z_TRIG, + B_BUTTON, + A_BUTTON, + R_CBUTTON, + L_CBUTTON, + D_CBUTTON, + U_CBUTTON, + R_TRIG, + L_TRIG, + MEMPAK, + RUMBLEPAK, + X_AXIS, + Y_AXIS, + NUM_BUTTONS +}; + +typedef struct +{ + int button; // button index; -1 if notassigned + SDL_Scancode key; // sdl keysym; SDL_SCANCODE_UNKNOWN if not assigned + int axis, axis_dir; // aixs + direction (i.e. 0, 1 = X Axis +; 0, -1 = X Axis -); -1 if notassigned + int axis_deadzone; // -1 for default, or >= 0 for custom value + int hat, hat_pos; // hat + hat position; -1 if not assigned + int mouse; // mouse button +} SButtonMap; + +typedef struct +{ + int button_a, button_b; // up/down or left/right; -1 if not assigned + SDL_Scancode key_a, key_b; // up/down or left/right; SDL_SCANCODE_UNKNOWN if not assigned + int axis_a, axis_b; // axis index; -1 if not assigned + int axis_dir_a, axis_dir_b; // direction (1 = X+, 0, -1 = X-) + int hat, hat_pos_a, hat_pos_b; // hat + hat position up/down and left/right; -1 if not assigned +} SAxisMap; + +typedef struct +{ + CONTROL *control; // pointer to CONTROL struct in Core library + BUTTONS buttons; + + // mappings + SButtonMap button[16]; // 14 buttons; in the order of EButton + mempak/rumblepak switches + SAxisMap axis[2]; // 2 axis + int device; // joystick device; -1 = keyboard; -2 = none + int mouse; // mouse enabled: 0 = no; 1 = yes + SDL_Joystick *joystick; // SDL joystick device + int event_joystick; // the /dev/input/eventX device for force feeback + int axis_deadzone[2]; // minimum absolute value before analog movement is recognized + int axis_peak[2]; // highest analog value returned by SDL, used for scaling + float mouse_sens[2]; // mouse sensitivity +} SController; + +/* global data definitions */ +extern SController controller[4]; // 4 controllers + +/* global function definitions */ +extern void DebugMessage(int level, const char *message, ...); + +/* declarations of pointers to Core config functions */ +extern ptr_ConfigListSections ConfigListSections; +extern ptr_ConfigOpenSection ConfigOpenSection; +extern ptr_ConfigDeleteSection ConfigDeleteSection; +extern ptr_ConfigListParameters ConfigListParameters; +extern ptr_ConfigSaveFile ConfigSaveFile; +extern ptr_ConfigSetParameter ConfigSetParameter; +extern ptr_ConfigGetParameter ConfigGetParameter; +extern ptr_ConfigGetParameterHelp ConfigGetParameterHelp; +extern ptr_ConfigSetDefaultInt ConfigSetDefaultInt; +extern ptr_ConfigSetDefaultFloat ConfigSetDefaultFloat; +extern ptr_ConfigSetDefaultBool ConfigSetDefaultBool; +extern ptr_ConfigSetDefaultString ConfigSetDefaultString; +extern ptr_ConfigGetParamInt ConfigGetParamInt; +extern ptr_ConfigGetParamFloat ConfigGetParamFloat; +extern ptr_ConfigGetParamBool ConfigGetParamBool; +extern ptr_ConfigGetParamString ConfigGetParamString; + +extern ptr_ConfigGetSharedDataFilepath ConfigGetSharedDataFilepath; +extern ptr_ConfigGetUserConfigPath ConfigGetUserConfigPath; +extern ptr_ConfigGetUserDataPath ConfigGetUserDataPath; +extern ptr_ConfigGetUserCachePath ConfigGetUserCachePath; + +#endif // __PLUGIN_H__ + diff --git a/libmupen64plus/mupen64plus-input-bkm/version.h b/libmupen64plus/mupen64plus-input-bkm/version.h new file mode 100644 index 0000000000..36dd9ce6ff --- /dev/null +++ b/libmupen64plus/mupen64plus-input-bkm/version.h @@ -0,0 +1,37 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mupen64plus-input-sdl - version.h * + * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * + * Copyright (C) 2009-2012 Richard Goedeken * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* This header file is for versioning information + * + */ + +#if !defined(VERSION_H) +#define VERSION_H + +#define PLUGIN_NAME "Mupen64Plus Bizhawk Input Plugin" +#define PLUGIN_VERSION 0x016305 +#define INPUT_PLUGIN_API_VERSION 0x020000 +#define CONFIG_API_VERSION 0x020000 + +#define VERSION_PRINTF_SPLIT(x) (((x) >> 16) & 0xffff), (((x) >> 8) & 0xff), ((x) & 0xff) + +#endif /* #define VERSION_H */ + diff --git a/libmupen64plus/mupen64plus-ui-console/projects/msvc11/mupen64plus-ui-console.sln b/libmupen64plus/mupen64plus-ui-console/projects/msvc11/mupen64plus-ui-console.sln index 305bedd73f..e550e4c3ec 100644 --- a/libmupen64plus/mupen64plus-ui-console/projects/msvc11/mupen64plus-ui-console.sln +++ b/libmupen64plus/mupen64plus-ui-console/projects/msvc11/mupen64plus-ui-console.sln @@ -16,6 +16,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-video-glide64mk EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-audio-bkm", "..\..\..\mupen64plus-audio-bkm\mupen64plus-audio-bkm\mupen64plus-audio-bkm.vcxproj", "{B6F20769-1385-4C0F-91A9-26F47AD1E78F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupen64plus-input-bkm", "..\..\..\mupen64plus-input-bkm\mupen64plus-input-bkm\mupen64plus-input-bkm.vcxproj", "{3D8BD211-6002-4698-B5C1-A0F3146B6ACF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -54,6 +56,10 @@ Global {B6F20769-1385-4C0F-91A9-26F47AD1E78F}.Debug|Win32.Build.0 = Debug|Win32 {B6F20769-1385-4C0F-91A9-26F47AD1E78F}.Release|Win32.ActiveCfg = Release|Win32 {B6F20769-1385-4C0F-91A9-26F47AD1E78F}.Release|Win32.Build.0 = Release|Win32 + {3D8BD211-6002-4698-B5C1-A0F3146B6ACF}.Debug|Win32.ActiveCfg = Debug|Win32 + {3D8BD211-6002-4698-B5C1-A0F3146B6ACF}.Debug|Win32.Build.0 = Debug|Win32 + {3D8BD211-6002-4698-B5C1-A0F3146B6ACF}.Release|Win32.ActiveCfg = Release|Win32 + {3D8BD211-6002-4698-B5C1-A0F3146B6ACF}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE