diff --git a/Makefile.common b/Makefile.common index 3e4bfd999..59ba98fee 100644 --- a/Makefile.common +++ b/Makefile.common @@ -412,7 +412,7 @@ ifeq ($(HAVE_RAPHNET_INPUT), 1) LDFLAGS += -ludev -ldl SOURCES_C += $(ROOT_DIR)/custom/mupen64plus-input-raphnetraw/plugin_front.c \ - $(INPUTDIR_RAPHNET)/src/plugin_back.c \ + $(ROOT_DIR)/custom/mupen64plus-input-raphnetraw/plugin_back.c \ $(INPUTDIR_RAPHNET)/src/hexdump.c \ $(INPUTDIR_RAPHNET)/src/gcn64lib.c \ $(INPUTDIR_RAPHNET)/src/gcn64.c diff --git a/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c b/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c index 5e27da76d..ad3023881 100644 --- a/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c +++ b/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c @@ -22,11 +22,6 @@ #include "emulate_game_controller_via_input_plugin.h" #include "plugin/plugin.h" -#ifdef HAVE_RAPHNET_INPUT -#include "mupen64plus-input-raphnetraw/plugin_front.h" -#include "plugin_back.h" -#endif - #include "api/m64p_plugin.h" #include "device/controllers/game_controller.h" #include @@ -53,7 +48,6 @@ extern int l_cbutton; extern int d_cbutton; extern int u_cbutton; extern bool alternate_mapping; -extern int raw_input_adapter; static bool libretro_supports_bitmasks = false; extern m64p_rom_header ROM_HEADER; @@ -80,14 +74,6 @@ void inputGetKeys_default( int Control, BUTTONS *Keys ); typedef void (*get_keys_t)(int, BUTTONS*); static get_keys_t getKeys = inputGetKeys_default; -void inputControllerCommand_default( int Control, unsigned char *Command ); -typedef void (*controller_command_t)(int, unsigned char*); -static controller_command_t controllerCommand = inputControllerCommand_default; - -void inputReadController_default( int Control, unsigned char *Command ); -typedef void (*read_controller_t)(int, unsigned char*); -static read_controller_t readController = inputReadController_default; - static void inputGetKeys_default_descriptor(void) { if (alternate_mapping) @@ -161,31 +147,11 @@ EXPORT m64p_error CALL inputPluginStartup(m64p_dynlib_handle CoreLibHandle, void libretro_supports_bitmasks = true; getKeys = inputGetKeys_default; inputGetKeys_default_descriptor(); - -#ifdef HAVE_RAPHNET_INPUT - if (raw_input_adapter == 1) - { - controllerCommand = raphnetControllerCommand; - readController = raphnetReadController; - raphnetPluginStartup(CoreLibHandle, Context, DebugCallback); - } - else - { - controllerCommand = inputControllerCommand_default; - readController = inputReadController_default; - } -#endif - return M64ERR_SUCCESS; } EXPORT m64p_error CALL inputPluginShutdown(void) { -#ifdef HAVE_RAPHNET_INPUT - if (raw_input_adapter == 1) - raphnetPluginShutdown(); -#endif - libretro_supports_bitmasks = false; abort(); return 0; @@ -237,14 +203,8 @@ static unsigned char DataCRC( unsigned char *Data, int iLenght ) initilize controller: 01 03 00 FF FF FF read controller: 01 04 01 FF FF FF FF *******************************************************************/ -EXPORT void CALL inputControllerCommand_default(int Control, unsigned char *Command) +EXPORT void CALL inputControllerCommand(int Control, unsigned char *Command) { - if (controllerCommand != inputControllerCommand_default) - { - controllerCommand(Control, Command); - return; - } - unsigned char *Data = &Command[5]; if (Control == -1) @@ -454,20 +414,6 @@ EXPORT void CALL inputInitiateControllers(CONTROL_INFO ControlInfo) getKeys = inputGetKeys_default; inputGetKeys_default_descriptor(); - -#ifdef HAVE_RAPHNET_INPUT - if (raw_input_adapter == 1) - { - controllerCommand = raphnetControllerCommand; - readController = raphnetReadController; - pb_scanControllers(); - } - else - { - controllerCommand = inputControllerCommand_default; - readController = inputReadController_default; - } -#endif } /****************************************************************** @@ -481,12 +427,9 @@ EXPORT void CALL inputInitiateControllers(CONTROL_INFO ControlInfo) note: This function is only needed if the DLL is allowing raw data. *******************************************************************/ -EXPORT void CALL inputReadController_default(int Control, unsigned char *Command) +EXPORT void CALL inputReadController(int Control, unsigned char *Command) { - if (readController != inputReadController_default) - readController(Control, Command); - else - inputControllerCommand_default(Control, Command); + inputControllerCommand(Control, Command); } /****************************************************************** @@ -495,12 +438,7 @@ EXPORT void CALL inputReadController_default(int Control, unsigned char *Command input: none output: none *******************************************************************/ -EXPORT void CALL inputRomClosed(void) { -#ifdef HAVE_RAPHNET_INPUT - if (raw_input_adapter == 1) - raphnetRomClosed(); -#endif -} +EXPORT void CALL inputRomClosed(void) { } /****************************************************************** Function: RomOpen @@ -509,29 +447,7 @@ EXPORT void CALL inputRomClosed(void) { input: none output: none *******************************************************************/ -EXPORT int CALL inputRomOpen(void) { -#ifdef HAVE_RAPHNET_INPUT - if (raw_input_adapter == 1) - { - bool all_unset = true; - - for (int i = 0; i < 4; i++) - { - if (pad_rawdata[i] == 1) - all_unset = false; - } - - // HACK: handle a special case if we enable raphnet support, but - // don't change any of the controllers to actually use raw data - if (all_unset) - raphnetPluginShutdown(); - else - raphnetRomOpen(); - } -#endif - - return 1; -} +EXPORT int CALL inputRomOpen(void) { return 1; } int egcvip_is_connected(void* opaque, enum pak_type* pak) diff --git a/custom/mupen64plus-input-raphnetraw/plugin_back.c b/custom/mupen64plus-input-raphnetraw/plugin_back.c new file mode 100644 index 000000000..5b1017ceb --- /dev/null +++ b/custom/mupen64plus-input-raphnetraw/plugin_back.c @@ -0,0 +1,573 @@ +/* mupen64plus-input-raphnetraw + * + * Copyright (C) 2016-2017 Raphael Assenat + * + * An input plugin that lets the game under emulation communicate with + * the controllers directly using the direct controller communication + * feature of raphnet V3 adapters[1]. + * + * [1] http://www.raphnet.net/electronique/gcn64_usb_adapter_gen3/index_en.php + * + * 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. + */ + +/* + * plugin_back.c : Plugin back code (in contrast to the "front" emulator interface + * + * Revision history: + * 28 Nov 2016 : Initial version + * 1 Dec 2016 : Switch to block IO api + * + */ + +#include +#include +#include "plugin_back.h" +#include "gcn64.h" +#include "gcn64lib.h" +#include "version.h" +#include "hexdump.h" + +#undef ENABLE_TIMING + +#ifdef ENABLE_TIMING +#include + +#if defined(__MINGW32__) || defined(__MINGW64__) +#error Timing not supported under Windows +#endif +#endif + +#undef TIME_RAW_IO +#undef TIME_COMMAND_TO_READ + +#undef TRACE_BLOCK_IO +// Filter +#define EXTENSION_RW_ONLY 0 + +#define MAX_ADAPTERS 4 +#define MAX_CHANNELS 4 + +static void nodebug(int l, const char *m, ...) { } + +static pb_debugFunc DebugMessage = nodebug; + +#define MAX_OPS 64 +#define DEVICE_NON_RAPHNET 64 + +struct adapter { + gcn64_hdl_t handle; + struct gcn64_info inf; + struct blockio_op biops[MAX_OPS]; + int n_ops; +}; + +static int g_n_adapters = 0; +struct adapter g_adapters[MAX_ADAPTERS] = { }; + +struct rawChannel { + struct adapter *adapter; + int adap; + int chn; + int port; +}; + +/* Multiple adapters are supported, some are single player, others + * two-player. As they are discovered during scan, their + * channels (corresponding to physical controller ports) are added + * to this table. Then, when plugin_front() calls functions in this + * files with a specified channel, the channel is the index in this + * table. + */ +static int g_n_channels = 0; +static struct rawChannel g_channels[MAX_CHANNELS] = { }; + +struct portMap { + int is_plugged; + int is_raphnet; + int raw_chn; + int last_chn; +}; + +static int max_controllers = MAX_CHANNELS; +static int g_portmaps_init[MAX_CHANNELS] = { 0 }; +static struct portMap g_portmaps[MAX_CHANNELS] = { }; + +int pb_init(pb_debugFunc debugFn) +{ + DebugMessage = debugFn; + gcn64_init(1); + + // assume every port is a raphnet device by default + // this generates a standard { 0, 1, 2, 3 } portmap + for (int i=0; ihandle) { + gcn64lib_suspendPolling(adap->handle, 0); + gcn64_closeDevice(adap->handle); + } + + memset(adap, 0, sizeof(struct adapter)); +} + +static void pb_freeAllAdapters(void) +{ + int i; + + for (i=0; iinf, lctx)) { + + adap->handle = gcn64_openDevice(&adap->inf); + if (!adap->handle) { + DebugMessage(PB_MSG_ERROR, "Could not open gcn64 device serial '%ls'. Skipping it.", adap->inf.str_serial); + continue; + } + + DebugMessage(PB_MSG_INFO, "Found USB device 0x%04x:0x%04x serial '%ls' name '%ls'", + adap->inf.usb_vid, adap->inf.usb_pid, adap->inf.str_serial, adap->inf.str_prodname); + DebugMessage(PB_MSG_INFO, "Adapter supports %d raw channel(s)", adap->inf.caps.n_raw_channels); + + g_n_adapters++; + if (g_n_adapters >= max_controllers) + break; + + adap = &g_adapters[g_n_adapters]; + } + gcn64_freeListCtx(lctx); + + // sort the adapters by channel count in descending order + qsort(g_adapters, g_n_adapters, sizeof(struct adapter), pb_sortAdapters); + + /* Pass 2: Fill the g_channel[] array with the available raw channels. + * For instance, if there are adapters A, B and C (where A and C are single-player + * and B is dual-player), we get this: + * + * [0] = Adapter A, raw channel 0 + * [1] = Adapter B, raw channel 0 + * [2] = Adapter B, raw channel 1 + * [3] = Adapter C, raw channel 0 + * + * */ + for (i=0; iinf.caps.n_raw_channels <= 0 || g_n_channels >= max_controllers) + { + pb_freeAdapter(adap); + continue; + } + + // when adding an adapter, try to add the entire adapter, if possible + if (g_n_channels + adap->inf.caps.n_raw_channels > max_controllers && i+1 < g_n_adapters) + { + pb_freeAdapter(adap); + continue; + } + + for (j=0; jinf.caps.n_raw_channels; j++) { + if (g_n_channels >= max_controllers) { + continue; + } + g_channels[g_n_channels].adapter = adap; + g_channels[g_n_channels].adap = i; + g_channels[g_n_channels].chn = j; + g_channels[g_n_channels].port = -1; + + for (k=0; kinf.str_serial, j); + g_n_channels++; + } + } + + return g_n_channels; +} + +int pb_sortAdapters(const void *a, const void *b) +{ + struct adapter *adapA = (struct adapter *) a; + struct adapter *adapB = (struct adapter *) b; + return (adapB->inf.caps.n_raw_channels - adapA->inf.caps.n_raw_channels); +} + +int pb_romOpen(void) +{ + int i; + + for (i=0; i 1 ? 's':' '); + +} + +static void debug_raw_commands_out(unsigned char *command, int channel_id) +{ + int result = command[1]; + int i; + + printf("chn %d: result: 0x%02x : ", channel_id, result); + if (0 == (command[1] & 0xC0)) { + for (i=0; ibiops; + + /* Skip adapters that do not have IO operations queued. */ + if (adap->n_ops <= 0) + continue; + +#ifdef TRACE_BLOCK_IO + for (i=0; in_ops; i++) { + if (EXTENSION_RW_ONLY && (biops[i].tx_data[0] < 0x02)) + continue; + op_was_extio[i] = 1; + printf("Before blockIO: op %d, adap: %d, chn: %d, : tx: 0x%02x, rx: 0x%02x, data: ", i, j, biops[i].chn, + biops[i].tx_len, biops[i].rx_len); + printHexBuf(biops[i].tx_data, biops[i].tx_len); + } +#endif + +#ifdef TIME_RAW_IO + timing(1, NULL); +#endif + res = gcn64lib_blockIO(adap->handle, biops, adap->n_ops); +#ifdef TIME_RAW_IO + timing(0, "blockIO"); +#endif + + if (res == 0) { + // biops rx_data pointed into PIFram so data is there. But we need + // to patch the RX length parameters (the two most significant bits + // are error bits such as timeout..) + for (i=0; in_ops; i++) { + // in PIFram, the read length is one byte before the tx data. A rare + // occasion to use a negative array index ;) + biops[i].tx_data[-1] = biops[i].rx_len; + +#ifdef TRACE_BLOCK_IO + if (EXTENSION_RW_ONLY && (!op_was_extio[i])) // Read + continue; + + printf("After blockIO: op %d, adap: %d, chn: %d, : tx: 0x%02x, rx: 0x%02x, data: ", i, j, biops[i].chn, + biops[i].tx_len, biops[i].rx_len); + if (biops[i].rx_len & BIO_RX_LEN_TIMEDOUT) { + printf("Timeout\n"); + } else if (biops[i].rx_len & BIO_RX_LEN_PARTIAL) { + printf("Incomplete\n"); + } else { + printHexBuf(biops[i].rx_data, biops[i].rx_len); + } +#endif + } + } else { + // For debugging + //exit(1); + } + + adap->n_ops = 0; + } + return 0; + + +} + +static int pb_commandIsValid(int Control, unsigned char *Command) +{ + if (Control < 0 || Control >= g_n_channels) { + DebugMessage(PB_MSG_WARNING, "pb_readController called with Control=%d", Control); + return 0; + } + + if (!Command) { + DebugMessage(PB_MSG_WARNING, "pb_readController called with NULL Command pointer"); + return 0; + } + + // When a CIC challenge took place in update_pif_write(), the pif ram + // contains a bunch 0xFF followed by 0x00 at offsets 46 and 47. Offset + // 48 onwards contains the challenge answer. + // + // Then when update_pif_read() is called, the 0xFF bytes are be skipped + // up to the two 0x00 bytes that increase the channel to 2. Then the + // challenge answer is (incorrectly) processed as if it were commands + // for the third controller. + // + // This cause issues with the raphnetraw plugin since it modifies pif ram + // to store the result or command error flags. This corrupts the reponse + // and leads to challenge failure. + // + // As I know of no controller commands above 0x03, the filter below guards + // against this condition... + // + if (Control == 2 && Command[2] > 0x03) { + DebugMessage(PB_MSG_WARNING, "Invalid controller command"); + return 0; + } + + // When Mario Kart 64 uses a controller pak, such PIF ram content + // occurs: + // + // ff 03 21 02 01 f7 ff ff + // ff ff ff ff ff ff ff ff + // ff ff ff ff ff ff ff ff + // ff ff ff ff ff ff ff ff + // ff ff ff ff ff ff ff 21 + // fe 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 + // + // It results in this: + // - Transmission of 3 bytes with a 33 bytes return on channel 0, + // - Transmission of 33 bytes with 254 bytes in return on channel 1!? + // + // Obviously the second transaction is an error. The 0xFE (254) that follows + // is where processing should actually stop. This happens to be an invalid length detectable + // by looking at the two most significant bits.. + // + if (Command[0] == 0xFE && Command[1] == 0x00) { + DebugMessage(PB_MSG_WARNING, "Ignoring invalid io operation (T: 0x%02x, R: 0x%02x)", + Command[0], Command[1]); + return 0; + } + + return 1; +} + +int pb_readController(int Control, unsigned char *Command) +{ + struct rawChannel *channel; + struct adapter *adap; + struct blockio_op *biops; + struct portMap portMap = g_portmaps[Control]; + int Channel = (portMap.raw_chn == DEVICE_NON_RAPHNET ? portMap.last_chn : portMap.raw_chn); + + // Called with -1 at the end of PIF ram. + if (Control == -1) { + return pb_performIo(); + } + + /* Check for out of bounds Control parameter, for + * NULL Command and filter various invalid conditions. */ + if (!pb_commandIsValid(Channel, Command)) { + return 0; + } + + /* Add the IO operation to the block io list of + * the adapter serving this channel. */ + + channel = &g_channels[Channel]; + adap = channel->adapter; + + if (adap->n_ops >= MAX_OPS) { + DebugMessage(PB_MSG_ERROR, "Too many io ops"); + } else { + biops = adap->biops; + + biops[adap->n_ops].chn = channel->chn; // Control; + biops[adap->n_ops].tx_len = Command[0] & BIO_RXTX_MASK; + biops[adap->n_ops].rx_len = Command[1] & BIO_RXTX_MASK; + biops[adap->n_ops].tx_data = Command + 2; + biops[adap->n_ops].rx_data = Command + 2 + biops[adap->n_ops].tx_len; + + if (biops[adap->n_ops].tx_len == 0 || biops[adap->n_ops].rx_len == 0) { + DebugMessage(PB_MSG_WARNING, "TX or RX was zero"); + return 0; + } + + adap->n_ops++; + } + + return 0; +} diff --git a/custom/mupen64plus-input-raphnetraw/plugin_back.h b/custom/mupen64plus-input-raphnetraw/plugin_back.h new file mode 100644 index 000000000..d40b217ef --- /dev/null +++ b/custom/mupen64plus-input-raphnetraw/plugin_back.h @@ -0,0 +1,24 @@ +#ifndef _plugin_back_h__ +#define _plugin_back_h__ + +/* Those match mupen64plus levels */ +#define PB_MSG_ERROR 1 +#define PB_MSG_WARNING 2 +#define PB_MSG_INFO 3 +#define PB_MSG_STATUS 4 +#define PB_MSG_VERBOSE 5 + +typedef void (*pb_debugFunc)(int level, const char *message, ...); + +int pb_init(pb_debugFunc debugFn); +int pb_updatePortMap(int Control, int IsPlugged, int IsRaphnet); +int pb_shutdown(void); +int pb_scanControllers(void); +int pb_sortAdapters(const void *a, const void *b); +int pb_readController(int Control, unsigned char *Command); +int pb_controllerCommand(int Control, unsigned char *Command); +int pb_romOpen(void); +int pb_romClosed(void); + +#endif // _plugin_back_h__ + diff --git a/custom/mupen64plus-input-raphnetraw/plugin_front.c b/custom/mupen64plus-input-raphnetraw/plugin_front.c index 3dedbc1af..fc66ff686 100644 --- a/custom/mupen64plus-input-raphnetraw/plugin_front.c +++ b/custom/mupen64plus-input-raphnetraw/plugin_front.c @@ -50,6 +50,9 @@ #include "plugin_back.h" #include "version.h" +#ifdef __LIBRETRO__ +#include +#endif /* __LIBRETRO__ */ #ifdef __linux__ #endif /* __linux__ */ @@ -58,7 +61,19 @@ #define MAX_CONTROLLERS 4 -#ifdef PORTS_1_AND_4 +#ifdef __LIBRETRO__ +static int emu2adap_portmap[MAX_CONTROLLERS] = { -1, -1, -1, -1 }; +#undef PLUGIN_NAME +#define PLUGIN_NAME "raphnetraw libretro" + +/* global data definitions */ +struct +{ + CONTROL *control; // pointer to CONTROL struct in Core library + BUTTONS buttons; +} controller[4]; + +#elif PORTS_1_AND_4 static int emu2adap_portmap[MAX_CONTROLLERS] = { 0, 2, 3, 1 }; #undef PLUGIN_NAME #define PLUGIN_NAME "raphnetraw ports 1 and 4" @@ -66,13 +81,7 @@ static int emu2adap_portmap[MAX_CONTROLLERS] = { 0, 2, 3, 1 }; static int emu2adap_portmap[MAX_CONTROLLERS] = { 0, 1, 2, 3 }; #endif -extern struct -{ - CONTROL *control; - BUTTONS buttons; -} controller[4]; -static int pad_portmap[MAX_CONTROLLERS] = { -1, -1, -1, -1 }; -#define EMU_2_ADAP_PORT(a) ((a) == -1 ? -1 : pad_portmap[a]) +#define EMU_2_ADAP_PORT(a) ((a) == -1 ? -1 : emu2adap_portmap[a]) /* static data definitions */ static void (*l_DebugCallback)(void *, int, const char *) = NULL; @@ -80,19 +89,6 @@ static void *l_DebugCallContext = NULL; static int l_PluginInit = 0; /* Global functions */ -void raphnetUpdatePortMap() -{ - int map = 0; - - for( int i = 0; i < MAX_CONTROLLERS; i++ ) - { - if (controller[i].control && controller[i].control->RawData == 1) - pad_portmap[i] = map++; - else - pad_portmap[i] = -1; - } -} - static void DebugMessage(int level, const char *message, ...) { char msgbuf[1024]; @@ -112,6 +108,19 @@ static void DebugMessage(int level, const char *message, ...) } +/* Libretro related functions */ +#ifdef __LIBRETRO__ +void raphnetUpdatePortMap(int in_port, int device) +{ + int is_plugged = (int) (controller[in_port].control ? controller[in_port].control->Present : 0); + int is_raphnet = (int) (device == RETRO_DEVICE_RAPHNET); + + if (pb_updatePortMap(in_port, is_plugged, is_raphnet) > 0) + pb_scanControllers(); +} +#endif + + /* Mupen64Plus plugin functions */ EXPORT m64p_error CALL raphnetPluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context, void (*DebugCallback)(void *, int, const char *)) @@ -200,6 +209,12 @@ EXPORT m64p_error CALL raphnetPluginGetVersion(m64p_plugin_type *PluginType, int *******************************************************************/ EXPORT void CALL raphnetInitiateControllers(CONTROL_INFO ControlInfo) { +#ifdef __LIBRETRO__ + // we need the built-in plugin for GetKeys, this also correctly + // sets ControlInfo to what the user selected in libretro + inputInitiateControllers(ControlInfo); + pb_init(DebugMessage); +#else int i, n_controllers, adap_port; n_controllers = pb_scanControllers(); @@ -223,6 +238,7 @@ EXPORT void CALL raphnetInitiateControllers(CONTROL_INFO ControlInfo) ControlInfo.Controls[i].Present = 1; } } +#endif DebugMessage(PB_MSG_INFO, "%s version %i.%i.%i %s(compiled "__DATE__" "__TIME__") initialized.", PLUGIN_NAME, VERSION_PRINTF_SPLIT(PLUGIN_VERSION), #ifdef _DEBUG @@ -247,16 +263,20 @@ EXPORT void CALL raphnetInitiateControllers(CONTROL_INFO ControlInfo) *******************************************************************/ EXPORT void CALL raphnetReadController(int Control, unsigned char *Command) { - pb_readController(EMU_2_ADAP_PORT(Control), Command); + pb_readController(Control, Command); } EXPORT void CALL raphnetControllerCommand(int Control, unsigned char *Command) { - pb_controllerCommand(EMU_2_ADAP_PORT(Control), Command); + pb_controllerCommand(Control, Command); } -EXPORT void CALL raphnetGetKeys( int Control, BUTTONS *Keys ) +EXPORT void CALL raphnetGetKeys_default( int Control, BUTTONS *Keys ) { +#ifdef __LIBRETRO__ + // pass GetKeys requests back to the built-in plugin + inputGetKeys_default(Control, Keys); +#endif } EXPORT void CALL raphnetRomClosed(void) @@ -266,7 +286,7 @@ EXPORT void CALL raphnetRomClosed(void) EXPORT int CALL raphnetRomOpen(void) { - pb_romOpen(); + pb_romOpen(); return 1; } diff --git a/custom/mupen64plus-input-raphnetraw/plugin_front.h b/custom/mupen64plus-input-raphnetraw/plugin_front.h index 7011088dd..fc79a2203 100644 --- a/custom/mupen64plus-input-raphnetraw/plugin_front.h +++ b/custom/mupen64plus-input-raphnetraw/plugin_front.h @@ -43,19 +43,21 @@ #define PAK_IO_RUMBLE 0xC000 // the address where rumble-commands are sent to -void raphnetUpdatePortMap(); - m64p_error raphnetPluginStartup(m64p_dynlib_handle CoreLibHandle, void *Context, void (*DebugCallback)(void *, int, const char *)); m64p_error raphnetPluginShutdown(void); m64p_error raphnetPluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, int *APIVersion, const char **PluginNamePtr, int *Capabilities); void raphnetInitiateControllers(CONTROL_INFO ControlInfo); void raphnetReadController(int Control, unsigned char *Command); void raphnetControllerCommand(int Control, unsigned char *Command); -void raphnetGetKeys( int Control, BUTTONS *Keys ); +void raphnetGetKeys_default( int Control, BUTTONS *Keys ); void raphnetRomClosed(void); int raphnetRomOpen(void); void raphnetSDL_KeyDown(int keymod, int keysym); void raphnetSDL_KeyUp(int keymod, int keysym); +#ifdef __LIBRETRO__ +void raphnetUpdatePortMap(int in_port, int device); +#endif + #endif // __PLUGIN_H__ diff --git a/custom/mupen64plus-next_common.h b/custom/mupen64plus-next_common.h index 317cc79f4..e36da1e98 100644 --- a/custom/mupen64plus-next_common.h +++ b/custom/mupen64plus-next_common.h @@ -33,6 +33,13 @@ extern "C" { #include "api/m64p_plugin.h" #include "api/m64p_types.h" +enum input_plugin_type +{ + INPUT_PLUGIN_NONE = 0, + INPUT_PLUGIN_INPUT, + INPUT_PLUGIN_RAPHNET +}; + enum rdp_plugin_type { RDP_PLUGIN_NONE = 0, @@ -51,6 +58,7 @@ enum rsp_plugin_type RSP_PLUGIN_MAX }; +void plugin_connect_input_api(enum input_plugin_type type); void plugin_connect_rsp_api(enum rsp_plugin_type type); void plugin_connect_rdp_api(enum rdp_plugin_type type); void plugin_connect_all(); @@ -179,7 +187,7 @@ extern uint32_t OverscanBottom; #define RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE (4 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK) /* unsigned * -- - * Tells the frontend to override the poll type behavior. + * Tells the frontend to override the poll type behavior. * Allows the frontend to influence the polling behavior of the * frontend. * diff --git a/libretro/libretro.c b/libretro/libretro.c index 2728a0b00..af05f5bfd 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -101,13 +101,6 @@ static struct retro_hw_render_callback hw_render; static struct retro_hw_render_context_negotiation_interface_vulkan hw_context_negotiation; #endif -#define RETRO_DEVICE_RAPHNET RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_NONE, 1) -#ifdef HAVE_RAPHNET_INPUT -#define NUM_DEVICE_TYPES 3 -#else -#define NUM_DEVICE_TYPES 2 -#endif - struct retro_perf_callback perf_cb; retro_get_cpu_features_t perf_get_cpu_features_cb = NULL; @@ -876,6 +869,13 @@ static void update_variables(bool startup) } } + setup_variables(); +#if defined(HAVE_RAPHNET_INPUT) + plugin_connect_input_api(INPUT_PLUGIN_RAPHNET); +#else + plugin_connect_input_api(INPUT_PLUGIN_INPUT); +#endif + if(current_rdp_type == RDP_PLUGIN_GLIDEN64 && EnableThreadedRenderer) { unsigned poll_type_early = 1; /* POLL_TYPE_EARLY */ @@ -2102,8 +2102,10 @@ void retro_set_controller_port_device(unsigned in_port, unsigned device) { break; } +#ifdef HAVE_RAPHNET_INPUT case RETRO_DEVICE_RAPHNET: prefer_rawdata = 1; +#endif case RETRO_DEVICE_JOYPAD: default: @@ -2120,8 +2122,7 @@ void retro_set_controller_port_device(unsigned in_port, unsigned device) { } #ifdef HAVE_RAPHNET_INPUT - if (in_port == 3) - raphnetUpdatePortMap(); + raphnetUpdatePortMap(in_port, device); #endif } diff --git a/libretro/libretro_private.h b/libretro/libretro_private.h index 6d7ac73c0..97127819f 100644 --- a/libretro/libretro_private.h +++ b/libretro/libretro_private.h @@ -29,5 +29,11 @@ void retro_return(); #define strcasecmp stricmp #endif +#ifdef HAVE_RAPHNET_INPUT +#define RETRO_DEVICE_RAPHNET RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_NONE, 1) +#define NUM_DEVICE_TYPES 3 +#else +#define NUM_DEVICE_TYPES 2 +#endif #endif diff --git a/mupen64plus-core/src/plugin/plugin.c b/mupen64plus-core/src/plugin/plugin.c index 347d94dc0..e83e53abe 100644 --- a/mupen64plus-core/src/plugin/plugin.c +++ b/mupen64plus-core/src/plugin/plugin.c @@ -125,30 +125,37 @@ const audio_plugin_functions dummy_audio = { dummyaudio_VolumeGetString }; +/* INPUT */ +#define DEFINE_INPUT(X) \ + EXPORT m64p_error CALL X##PluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, \ + int *APIVersion, const char **PluginNamePtr, int *Capabilities); \ + EXPORT void CALL X##InitiateControllers (CONTROL_INFO ControlInfo); \ + EXPORT void CALL X##GetKeys_default(int Control, BUTTONS * Keys ); \ + EXPORT void CALL X##ControllerCommand(int Control, unsigned char *Command); \ + EXPORT void CALL X##InitiateControllers(CONTROL_INFO ControlInfo); \ + EXPORT void CALL X##ReadController(int Control, unsigned char *Command); \ + EXPORT int CALL X##RomOpen(void); \ + EXPORT void CALL X##RomClosed(void); \ + \ + input_plugin_functions input_##X = { \ + X##PluginGetVersion, \ + X##ControllerCommand, \ + X##GetKeys_default, \ + X##InitiateControllers, \ + X##ReadController, \ + X##RomClosed, \ + X##RomOpen, \ + dummyinput_SDL_KeyDown, \ + dummyinput_SDL_KeyUp, \ + dummyinput_RenderCallback \ + } -extern m64p_error inputPluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, - int *APIVersion, const char **PluginNamePtr, int *Capabilities); -extern void inputInitiateControllers (CONTROL_INFO ControlInfo); -extern void inputGetKeys_default(int Control, BUTTONS * Keys ); -extern void inputControllerCommand_default(int Control, unsigned char *Command); -extern void inputInitiateControllers(CONTROL_INFO ControlInfo); -extern void inputReadController_default(int Control, unsigned char *Command); -extern int inputRomOpen(void); -extern void inputRomClosed(void); - - -const input_plugin_functions dummy_input = { - inputPluginGetVersion, - inputControllerCommand_default, - inputGetKeys_default, - inputInitiateControllers, - inputReadController_default, - inputRomClosed, - inputRomOpen, - dummyinput_SDL_KeyDown, - dummyinput_SDL_KeyUp, - dummyinput_RenderCallback -}; +#if defined(HAVE_RAPHNET_INPUT) +DEFINE_INPUT(input); +DEFINE_INPUT(raphnet); +#else +DEFINE_INPUT(input); +#endif static AUDIO_INFO audio_info; static CONTROL_INFO control_info; @@ -294,7 +301,7 @@ static m64p_error plugin_start_audio(void) static void plugin_disconnect_input(void) { - input = dummy_input; + input = input_input; l_InputAttached = 0; } @@ -387,9 +394,24 @@ m64p_error plugin_check(void) } #ifdef __LIBRETRO__ +enum input_plugin_type current_input_type = INPUT_PLUGIN_NONE; enum rdp_plugin_type current_rdp_type = RDP_PLUGIN_NONE; enum rsp_plugin_type current_rsp_type = RSP_PLUGIN_NONE; +void plugin_connect_input_api(enum input_plugin_type type) +{ + switch (type) + { + case INPUT_PLUGIN_INPUT: + case INPUT_PLUGIN_RAPHNET: + current_input_type = type; + break; + case INPUT_PLUGIN_NONE: + default: + break; + } +} + void plugin_connect_rdp_api(enum rdp_plugin_type type) { switch (type) @@ -473,7 +495,21 @@ void plugin_connect_all() l_AudioAttached = 1; //plugin_start_audio(); - input = dummy_input; + switch (current_input_type) + { + case INPUT_PLUGIN_RAPHNET: +#ifdef HAVE_RAPHNET_INPUT + input = input_raphnet; +#endif + break; + case INPUT_PLUGIN_INPUT: + input = input_input; + break; + case INPUT_PLUGIN_NONE: + default: + break; + } + l_InputAttached = 1; plugin_start_input(); } @@ -493,7 +529,7 @@ void plugin_connect_all() l_AudioAttached = 1; //plugin_start_audio(); - input = dummy_input; + input = input_input; l_InputAttached = 1; plugin_start_input(); }