diff --git a/Makefile b/Makefile index 89e8d34cc..150833f76 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,6 @@ endif ifneq (,$(findstring unix,$(platform))) TARGET := $(TARGET_NAME)_libretro.so LDFLAGS += -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined - HAVE_RAPHNET_INPUT = 1 ifeq ($(FORCE_GLES),1) GLES = 1 @@ -235,7 +234,6 @@ else ifneq (,$(findstring odroid64,$(platform))) GLES = 0 GLES3= 1 GL_LIB := -lGLESv3 - HAVE_RAPHNET_INPUT = 1 endif COREFLAGS += -DOS_LINUX diff --git a/Makefile.common b/Makefile.common index a296ca3d0..be61733c4 100644 --- a/Makefile.common +++ b/Makefile.common @@ -404,9 +404,12 @@ SOURCES_C += $(VIDEODIR_ANGRYLION)/interface.c \ endif # raphnetraw and hidapi +# FIXME windows build untested and probably incomplete ifeq ($(HAVE_RAPHNET_INPUT), 1) + CFLAGS += -DHAVE_RAPHNET_INPUT + CXXFLAGS += -DHAVE_RAPHNET_INPUT INCFLAGS += $(HIDAPI_INCFLAGS) - LDFLAGS += -ludev -ldl + LDFLAGS += -ludev -ldl SOURCES_C += $(ROOT_DIR)/custom/mupen64plus-input-raphnetraw/plugin_front.c \ $(INPUTDIR_RAPHNET)/src/plugin_back.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 45cd2c124..5e27da76d 100644 --- a/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c +++ b/custom/mupen64plus-core/plugin/emulate_game_controller_via_libretro.c @@ -22,6 +22,11 @@ #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 @@ -40,6 +45,7 @@ extern retro_input_state_t input_cb; extern struct retro_rumble_interface rumble; extern int pad_pak_types[4]; extern int pad_present[4]; +extern int pad_rawdata[4]; extern int astick_deadzone; extern int astick_sensitivity; extern int r_cbutton; @@ -47,6 +53,7 @@ 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; @@ -73,6 +80,14 @@ 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) @@ -146,11 +161,31 @@ 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; @@ -202,8 +237,14 @@ 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(int Control, unsigned char *Command) +EXPORT void CALL inputControllerCommand_default(int Control, unsigned char *Command) { + if (controllerCommand != inputControllerCommand_default) + { + controllerCommand(Control, Command); + return; + } + unsigned char *Data = &Command[5]; if (Control == -1) @@ -399,7 +440,7 @@ EXPORT void CALL inputInitiateControllers(CONTROL_INFO ControlInfo) { controller[i].control = ControlInfo.Controls + i; controller[i].control->Present = pad_present[i]; - controller[i].control->RawData = 0; + controller[i].control->RawData = pad_rawdata[i]; if (pad_pak_types[i] == PLUGIN_MEMPAK) controller[i].control->Plugin = PLUGIN_MEMPAK; @@ -413,6 +454,20 @@ 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 } /****************************************************************** @@ -426,9 +481,12 @@ EXPORT void CALL inputInitiateControllers(CONTROL_INFO ControlInfo) note: This function is only needed if the DLL is allowing raw data. *******************************************************************/ -EXPORT void CALL inputReadController(int Control, unsigned char *Command) +EXPORT void CALL inputReadController_default(int Control, unsigned char *Command) { - inputControllerCommand(Control, Command); + if (readController != inputReadController_default) + readController(Control, Command); + else + inputControllerCommand_default(Control, Command); } /****************************************************************** @@ -437,7 +495,12 @@ EXPORT void CALL inputReadController(int Control, unsigned char *Command) input: none output: none *******************************************************************/ -EXPORT void CALL inputRomClosed(void) { } +EXPORT void CALL inputRomClosed(void) { +#ifdef HAVE_RAPHNET_INPUT + if (raw_input_adapter == 1) + raphnetRomClosed(); +#endif +} /****************************************************************** Function: RomOpen @@ -446,7 +509,29 @@ EXPORT void CALL inputRomClosed(void) { } input: none output: none *******************************************************************/ -EXPORT int CALL inputRomOpen(void) { return 1; } +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; +} int egcvip_is_connected(void* opaque, enum pak_type* pak) diff --git a/custom/mupen64plus-input-raphnetraw/plugin_front.c b/custom/mupen64plus-input-raphnetraw/plugin_front.c index cb5fdce66..3dedbc1af 100644 --- a/custom/mupen64plus-input-raphnetraw/plugin_front.c +++ b/custom/mupen64plus-input-raphnetraw/plugin_front.c @@ -66,7 +66,13 @@ static int emu2adap_portmap[MAX_CONTROLLERS] = { 0, 2, 3, 1 }; static int emu2adap_portmap[MAX_CONTROLLERS] = { 0, 1, 2, 3 }; #endif -#define EMU_2_ADAP_PORT(a) ((a) == -1 ? -1 : emu2adap_portmap[a]) +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]) /* static data definitions */ static void (*l_DebugCallback)(void *, int, const char *) = NULL; @@ -74,6 +80,19 @@ 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]; @@ -252,7 +271,7 @@ EXPORT int CALL raphnetRomOpen(void) } /****************************************************************** - Function: SDL_KeyDown + Function: raphnetSDL_KeyDown Purpose: To pass the SDL_KeyDown message from the emulator to the plugin. input: keymod and keysym of the SDL_KEYDOWN message. diff --git a/custom/mupen64plus-input-raphnetraw/plugin_front.h b/custom/mupen64plus-input-raphnetraw/plugin_front.h index 4370760e7..7011088dd 100644 --- a/custom/mupen64plus-input-raphnetraw/plugin_front.h +++ b/custom/mupen64plus-input-raphnetraw/plugin_front.h @@ -43,5 +43,19 @@ #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 raphnetRomClosed(void); +int raphnetRomOpen(void); +void raphnetSDL_KeyDown(int keymod, int keysym); +void raphnetSDL_KeyUp(int keymod, int keysym); + #endif // __PLUGIN_H__ diff --git a/libretro/libretro.c b/libretro/libretro.c index fae1bb7b2..45166253b 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -58,6 +58,10 @@ #include "audio_plugin.h" +#ifdef HAVE_RAPHNET_INPUT +#include "plugin_front.h" +#endif + #ifndef PRESCALE_WIDTH #define PRESCALE_WIDTH 640 #endif @@ -97,6 +101,13 @@ 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; @@ -122,6 +133,7 @@ int l_cbutton; int d_cbutton; int u_cbutton; bool alternate_mapping; +int raw_input_adapter; static uint8_t* game_data = NULL; static uint32_t game_size = 0; @@ -225,6 +237,7 @@ extern struct // these instead for input_plugin to read. int pad_pak_types[4]; int pad_present[4] = {1, 1, 1, 1}; +int pad_rawdata[4] = {0, 0, 0, 0}; static void n64DebugCallback(void* aContext, int aLevel, const char* aMessage) { @@ -240,14 +253,17 @@ static void setup_variables(void) { static const struct retro_controller_description port[] = { { "Controller", RETRO_DEVICE_JOYPAD }, +#ifdef HAVE_RAPHNET_INPUT + { "Raphnet", RETRO_DEVICE_RAPHNET }, +#endif { "RetroPad", RETRO_DEVICE_JOYPAD }, }; static const struct retro_controller_info ports[] = { - { port, 2 }, - { port, 2 }, - { port, 2 }, - { port, 2 }, + { port, NUM_DEVICE_TYPES }, + { port, NUM_DEVICE_TYPES }, + { port, NUM_DEVICE_TYPES }, + { port, NUM_DEVICE_TYPES }, { 0, 0 } }; @@ -310,7 +326,7 @@ static void set_variable_visibility(void) environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display_parallel_rdp); } } - } + } } static void n64StateCallback(void *Context, m64p_core_param param_type, int new_value) @@ -503,16 +519,16 @@ bool retro_load_game_special(unsigned game_type, const struct retro_game_info *i } else { return false; } - + log_cb(RETRO_LOG_INFO, "Loading %s...\n", info[0].path); - + result = load_file(info[1].path, &gameBuffer, &outSize) == file_ok; if(result) { memcpy(&info[1].data, &gameBuffer, sizeof(void*)); memcpy(&info[1].size, &outSize, sizeof(size_t)); result = result && retro_load_game(&info[1]); - + if(gameBuffer) { free(gameBuffer); @@ -530,7 +546,7 @@ bool retro_load_game_special(unsigned game_type, const struct retro_game_info *i } else { return false; } - + log_cb(RETRO_LOG_INFO, "Loading %s...\n", info[0].path); log_cb(RETRO_LOG_INFO, "Loading %s...\n", info[1].path); log_cb(RETRO_LOG_INFO, "Loading %s...\n", info[2].path); @@ -591,7 +607,7 @@ void retro_set_environment(retro_environment_t cb) environ_cb(RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO, (void*)subsystems); environ_cb(RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB, &environ_clear_thread_waits_cb); - + setup_variables(); } @@ -819,7 +835,7 @@ static void update_variables(bool startup) log_cb(RETRO_LOG_INFO, "Requested Angrylion but no LLE RSP available, falling back to GLideN64!\n"); plugin_connect_rsp_api(RSP_PLUGIN_HLE); plugin_connect_rdp_api(RDP_PLUGIN_GLIDEN64); -#endif +#endif } } else if (!strcmp(var.value, "cxd4")) @@ -847,7 +863,7 @@ static void update_variables(bool startup) log_cb(RETRO_LOG_INFO, "Requested Angrylion but no LLE RSP available, falling back to GLideN64!\n"); plugin_connect_rdp_api(RDP_PLUGIN_GLIDEN64); plugin_connect_rsp_api(RSP_PLUGIN_HLE); -#endif +#endif } } @@ -856,7 +872,7 @@ static void update_variables(bool startup) unsigned poll_type_early = 1; /* POLL_TYPE_EARLY */ environ_cb(RETRO_ENVIRONMENT_POLL_TYPE_OVERRIDE, &poll_type_early); } - + var.key = CORE_NAME "-ThreadedRenderer"; var.value = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -891,7 +907,7 @@ static void update_variables(bool startup) { EnableDitheringQuantization = !strcmp(var.value, "False") ? 0 : 1; } - + var.key = CORE_NAME "-RDRAMImageDitheringMode"; var.value = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -905,7 +921,7 @@ static void update_variables(bool startup) else RDRAMImageDitheringMode = 0; // bdmDisable } - + var.key = CORE_NAME "-FXAA"; var.value = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -1281,7 +1297,7 @@ static void update_variables(bool startup) { CountPerOp = atoi(var.value); } - + if(EnableFullspeed) { CountPerOp = 1; // Force CountPerOp == 1 @@ -1403,6 +1419,21 @@ static void update_variables(bool startup) ForceDisableExtraMem = !strcmp(var.value, "False") ? 0 : 1; } + var.key = CORE_NAME "-RawInputAdapter"; + var.value = NULL; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "None")) + raw_input_adapter = 0; +#ifdef HAVE_RAPHNET_INPUT + else if (!strcmp(var.value, "Raphnet")) + raw_input_adapter = 1; +#else + else + raw_input_adapter = 0; +#endif + } + var.key = CORE_NAME "-IgnoreTLBExceptions"; var.value = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -1749,7 +1780,7 @@ bool retro_load_game(const struct retro_game_info *game) retro_dd_path_img = newPath; } } - + if (!retro_transferpak_rom_path) { gamePath = (char *)game->path; @@ -1847,7 +1878,7 @@ bool retro_load_game(const struct retro_game_info *game) /* Additional check for vioverlay not set at start */ update_variables(false); } - + load_game_successful = true; return true; @@ -1873,7 +1904,7 @@ void retro_unload_game(void) co_switch(game_thread); } glsm_ctl(GLSM_CTL_STATE_UNBIND, NULL); - + pthread_join(emuThread, NULL); environ_clear_thread_waits_cb(0, NULL); @@ -1905,7 +1936,7 @@ void retro_run (void) emuThreadRunning = true; } } - + glsm_ctl(GLSM_CTL_STATE_BIND, NULL); } @@ -1915,7 +1946,7 @@ void retro_run (void) { glsm_ctl(GLSM_CTL_STATE_UNBIND, NULL); } - + if (libretro_swap_buffer) { if(current_rdp_type == RDP_PLUGIN_GLIDEN64) @@ -2049,29 +2080,43 @@ bool retro_unserialize(const void *data, size_t size) //Needed to be able to detach controllers for Lylat Wars multiplayer //Only sets if controller struct is initialised as addon paks do. void retro_set_controller_port_device(unsigned in_port, unsigned device) { + int prefer_rawdata = 0; + if (in_port < 4){ switch(device) { case RETRO_DEVICE_NONE: if (controller[in_port].control){ controller[in_port].control->Present = 0; + controller[in_port].control->RawData = 0; break; } else { pad_present[in_port] = 0; + pad_rawdata[in_port] = 0; break; } + case RETRO_DEVICE_RAPHNET: + prefer_rawdata = 1; + case RETRO_DEVICE_JOYPAD: default: if (controller[in_port].control){ controller[in_port].control->Present = 1; + controller[in_port].control->RawData = prefer_rawdata; break; } else { pad_present[in_port] = 1; + pad_rawdata[in_port] = prefer_rawdata; break; } } } + +#ifdef HAVE_RAPHNET_INPUT + if (in_port == 3) + raphnetUpdatePortMap(); +#endif } unsigned retro_api_version(void) { return RETRO_API_VERSION; } diff --git a/libretro/libretro_core_options.h b/libretro/libretro_core_options.h index a3e1cd575..53939f02b 100644 --- a/libretro/libretro_core_options.h +++ b/libretro/libretro_core_options.h @@ -1275,6 +1275,19 @@ struct retro_core_option_definition option_defs_us[] = { }, "False" }, + { + CORE_NAME "-RawInputAdapter", + "Raw Input Adapter", + "Select a raw input adapter to use over other controller configurations.", + { + {"None", NULL}, +#ifdef HAVE_RAPHNET_INPUT + {"Raphnet", NULL}, +#endif + {NULL, NULL}, + }, + "None" + }, { CORE_NAME "-IgnoreTLBExceptions", "Ignore emulated TLB Exceptions", diff --git a/mupen64plus-core/src/plugin/plugin.c b/mupen64plus-core/src/plugin/plugin.c index daa4a77c3..347d94dc0 100644 --- a/mupen64plus-core/src/plugin/plugin.c +++ b/mupen64plus-core/src/plugin/plugin.c @@ -130,19 +130,19 @@ extern m64p_error inputPluginGetVersion(m64p_plugin_type *PluginType, int *Plugi int *APIVersion, const char **PluginNamePtr, int *Capabilities); extern void inputInitiateControllers (CONTROL_INFO ControlInfo); extern void inputGetKeys_default(int Control, BUTTONS * Keys ); -extern void inputControllerCommand(int Control, unsigned char *Command); +extern void inputControllerCommand_default(int Control, unsigned char *Command); extern void inputInitiateControllers(CONTROL_INFO ControlInfo); -extern void inputReadController(int Control, unsigned char *Command); +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, + inputControllerCommand_default, inputGetKeys_default, inputInitiateControllers, - inputReadController, + inputReadController_default, inputRomClosed, inputRomOpen, dummyinput_SDL_KeyDown, @@ -252,7 +252,7 @@ m64p_error plugin_start_gfx(void) gfx_info.VI_X_SCALE_REG = &(g_dev.vi.regs[VI_X_SCALE_REG]); gfx_info.VI_Y_SCALE_REG = &(g_dev.vi.regs[VI_Y_SCALE_REG]); gfx_info.CheckInterrupts = EmptyFunc; - + gfx_info.version = 2; //Version 2 added SP_STATUS_REG and RDRAM_SIZE gfx_info.SP_STATUS_REG = &g_dev.sp.regs[SP_STATUS_REG]; gfx_info.RDRAM_SIZE = (unsigned int*) &g_dev.rdram.dram_size; @@ -472,7 +472,7 @@ void plugin_connect_all() audio = dummy_audio; l_AudioAttached = 1; //plugin_start_audio(); - + input = dummy_input; l_InputAttached = 1; plugin_start_input(); @@ -492,7 +492,7 @@ void plugin_connect_all() audio = dummy_audio; l_AudioAttached = 1; //plugin_start_audio(); - + input = dummy_input; l_InputAttached = 1; plugin_start_input();