From 1d5885dd84764db52407be67aee2aa0516ff66ed Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 26 Jan 2022 19:34:13 +0000 Subject: [PATCH] core, linux+libretro, multiplayer adaptor support --- pico/memory.c | 59 +++++++++-------------- pico/pico.h | 4 +- platform/common/config_file.c | 19 ++++++-- platform/common/emu.c | 10 +++- platform/common/menu_pico.c | 15 ++++-- platform/common/menu_pico.h | 2 + platform/libpicofe | 2 +- platform/libretro/libretro.c | 36 +++++++++++++- platform/libretro/libretro_core_options.h | 6 ++- 9 files changed, 104 insertions(+), 49 deletions(-) diff --git a/pico/memory.c b/pico/memory.c index f98375f4..89093932 100644 --- a/pico/memory.c +++ b/pico/memory.c @@ -262,43 +262,29 @@ static u32 read_pad_team(int i, u32 out_bits) int phase = Pico.m.padTHPhase[i]; u32 value; - if (phase == 0) { + switch (phase) { + case 0: value = 0x03; - goto out; - } - if (phase == 1) { + break; + case 1: value = 0x0f; - goto out; - } - - pad = ~PicoIn.padInt[0]; // Get inverse of pad MXYZ SACB RLDU - if (phase == 8) { - value = pad & 0x0f; // ?x?x RLDU - goto out; - } - else if(phase == 9) { - value = (pad & 0xf0) >> 4; // ?x?x SACB - goto out; - } - - pad = ~PicoIn.padInt[1]; // Get inverse of pad MXYZ SACB RLDU - if (phase == 12) { + break; + case 4: case 5: case 6: case 7: // controller IDs, all 3 btn for now + value = 0x00; + break; + case 8: case 10: case 12: case 14: + pad = ~PicoIn.padInt[(phase-8) >> 1]; value = pad & 0x0f; // ?x?x RLDU - goto out; - } - else if(phase == 13) { + break; + case 9: case 11: case 13: case 15: + pad = ~PicoIn.padInt[(phase-8) >> 1]; value = (pad & 0xf0) >> 4; // ?x?x SACB - goto out; - } - - if (phase >= 8 && pad < 16) { - value = 0x0f; - goto out; + break; + default: + value = 0; + break; } - value = 0; - -out: value |= (out_bits & 0x40) | ((out_bits & 0x20)>>1); return value; } @@ -308,8 +294,8 @@ static u32 read_pad_4way(int i, u32 out_bits) u32 pad = (PicoMem.ioports[2] & 0x70) >> 4; u32 value = 0; - if (i == 0 && !(pad & 1)) - value = read_pad_3btn(pad >> 1, out_bits); + if (i == 0 && pad <= 3) + value = read_pad_3btn(pad, out_bits); value |= (out_bits & 0x40); return value; @@ -357,7 +343,10 @@ void PicoSetInputDevice(int port, enum input_device device) if (port < 0 || port > 2) return; - switch (device) { + if (port == 1 && port_readers[0] == read_pad_team) + func = read_nothing; + + else switch (device) { case PICO_INPUT_PAD_3BTN: func = read_pad_3btn; break; @@ -409,7 +398,7 @@ NOINLINE void io_ports_write(u32 a, u32 d) Pico.m.padTHPhase[a - 1] = 0; else if ((d^PicoMem.ioports[a]) & 0x60) Pico.m.padTHPhase[a - 1]++; - } else if (port_readers[a - 1] == read_pad_4way) { + } else if (port_readers[0] == read_pad_4way) { if (a == 2 && ((PicoMem.ioports[a] ^ d) & 0x70)) Pico.m.padTHPhase[0] = 0; if (a == 1 && !(PicoMem.ioports[a] & 0x40) && (d & 0x40)) diff --git a/pico/pico.h b/pico/pico.h index 39fd838a..8746b9ba 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -95,8 +95,8 @@ typedef struct PicoInterface { unsigned int opt; // POPT_* bitfield - unsigned short pad[2]; // Joypads, format is MXYZ SACB RLDU - unsigned short padInt[2]; // internal copy + unsigned short pad[4]; // Joypads, format is MXYZ SACB RLDU + unsigned short padInt[4]; // internal copy unsigned short AHW; // active addon hardware: PAHW_* bitfield unsigned short skipFrame; // skip rendering frame, but still do sound (if enabled) and emulation stuff diff --git a/platform/common/config_file.c b/platform/common/config_file.c index 18331d71..c4f611d0 100644 --- a/platform/common/config_file.c +++ b/platform/common/config_file.c @@ -85,6 +85,19 @@ static void keys_write(FILE *fn, int dev_id, const int *binds) } } + for (i = 0; me_ctrl_actions[i].name != NULL; i++) { + mask = me_ctrl_actions[i].mask; + if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER34)]) { + strncpy(act, me_ctrl_actions[i].name, 31); + fprintf(fn, "bind %s = player3 %s" NL, name, mystrip(act)); + } + mask = me_ctrl_actions[i].mask << 16; + if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_PLAYER34)]) { + strncpy(act, me_ctrl_actions[i].name, 31); + fprintf(fn, "bind %s = player4 %s" NL, name, mystrip(act)); + } + } + for (i = 0; emuctrl_actions[i].name != NULL; i++) { mask = emuctrl_actions[i].mask; if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_EMU)]) { @@ -371,12 +384,12 @@ static int parse_bind_val(const char *val, int *type) int player, shift = 0; player = atoi(val + 6) - 1; - if (player > 1) + if (player > 3) return -1; - if (player == 1) + if (player & 1) shift = 16; - *type = IN_BINDTYPE_PLAYER12; + *type = IN_BINDTYPE_PLAYER12 + (player >> 1); for (i = 0; me_ctrl_actions[i].name != NULL; i++) { if (strncasecmp(me_ctrl_actions[i].name, val + 8, strlen(val + 8)) == 0) return me_ctrl_actions[i].mask << shift; diff --git a/platform/common/emu.c b/platform/common/emu.c index 1b3e7082..5d4f8ffb 100644 --- a/platform/common/emu.c +++ b/platform/common/emu.c @@ -1180,21 +1180,29 @@ void emu_update_input(void) { static int prev_events = 0; int actions[IN_BINDTYPE_COUNT] = { 0, }; - int pl_actions[2]; + int pl_actions[4]; int events; in_update(actions); pl_actions[0] = actions[IN_BINDTYPE_PLAYER12]; pl_actions[1] = actions[IN_BINDTYPE_PLAYER12] >> 16; + pl_actions[2] = actions[IN_BINDTYPE_PLAYER34]; + pl_actions[3] = actions[IN_BINDTYPE_PLAYER34] >> 16; PicoIn.pad[0] = pl_actions[0] & 0xfff; PicoIn.pad[1] = pl_actions[1] & 0xfff; + PicoIn.pad[2] = pl_actions[2] & 0xfff; + PicoIn.pad[3] = pl_actions[3] & 0xfff; if (pl_actions[0] & 0x7000) do_turbo(&PicoIn.pad[0], pl_actions[0]); if (pl_actions[1] & 0x7000) do_turbo(&PicoIn.pad[1], pl_actions[1]); + if (pl_actions[2] & 0x7000) + do_turbo(&PicoIn.pad[2], pl_actions[2]); + if (pl_actions[3] & 0x7000) + do_turbo(&PicoIn.pad[3], pl_actions[3]); events = actions[IN_BINDTYPE_EMU] & PEV_MASK; diff --git a/platform/common/menu_pico.c b/platform/common/menu_pico.c index 1151ad48..812ea842 100644 --- a/platform/common/menu_pico.c +++ b/platform/common/menu_pico.c @@ -366,6 +366,12 @@ static int key_config_loop_wrap(int id, int keys) case MA_CTRL_PLAYER2: key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 1); break; + case MA_CTRL_PLAYER3: + key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 2); + break; + case MA_CTRL_PLAYER4: + key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 3); + break; case MA_CTRL_EMU: key_config_loop(emuctrl_actions, array_size(emuctrl_actions) - 1, -1); break; @@ -396,15 +402,18 @@ static const char *mgn_dev_name(int id, int *offs) static int mh_saveloadcfg(int id, int keys); static const char *mgn_saveloadcfg(int id, int *offs); -const char *indev_names[] = { "none", "3 button pad", "6 button pad", NULL }; +const char *indev0_names[] = { "none", "3 button pad", "6 button pad", "Team player", "4 way play", NULL }; +const char *indev1_names[] = { "none", "3 button pad", "6 button pad", NULL }; static menu_entry e_menu_keyconfig[] = { mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap), mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap), + mee_handler_id("Player 3", MA_CTRL_PLAYER3, key_config_loop_wrap), + mee_handler_id("Player 4", MA_CTRL_PLAYER4, key_config_loop_wrap), mee_handler_id("Emulator controls", MA_CTRL_EMU, key_config_loop_wrap), - mee_enum ("Input device 1", MA_OPT_INPUT_DEV0, currentConfig.input_dev0, indev_names), - mee_enum ("Input device 2", MA_OPT_INPUT_DEV1, currentConfig.input_dev1, indev_names), + mee_enum ("Input device 1", MA_OPT_INPUT_DEV0, currentConfig.input_dev0, indev0_names), + mee_enum ("Input device 2", MA_OPT_INPUT_DEV1, currentConfig.input_dev1, indev1_names), mee_range ("Turbo rate", MA_CTRL_TURBO_RATE, currentConfig.turbo_rate, 1, 30), mee_range ("Analog deadzone", MA_CTRL_DEADZONE, currentConfig.analog_deadzone, 1, 99), mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg), diff --git a/platform/common/menu_pico.h b/platform/common/menu_pico.h index 0c81563b..fb1c67d9 100644 --- a/platform/common/menu_pico.h +++ b/platform/common/menu_pico.h @@ -93,6 +93,8 @@ typedef enum MA_SMSOPT_GHOSTING, MA_CTRL_PLAYER1, MA_CTRL_PLAYER2, + MA_CTRL_PLAYER3, + MA_CTRL_PLAYER4, MA_CTRL_EMU, MA_CTRL_TURBO_RATE, MA_CTRL_DEADZONE, diff --git a/platform/libpicofe b/platform/libpicofe index d57c9992..25cfdf0a 160000 --- a/platform/libpicofe +++ b/platform/libpicofe @@ -1 +1 @@ -Subproject commit d57c9992201e065f8caf6ce68247195ff98e8420 +Subproject commit 25cfdf0a342a64a01710c1b6fbe3b1b04f28975e diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 8aadedf7..8646865a 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -1235,6 +1235,34 @@ bool retro_load_game(const struct retro_game_info *info) { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT,"Mode" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT,"Mode" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "C" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Y" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "A" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "X" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Z" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT,"Mode" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 0 }, }; @@ -1442,6 +1470,10 @@ static enum input_device input_name_to_val(const char *name) return PICO_INPUT_PAD_3BTN; if (strcmp(name, "6 button pad") == 0) return PICO_INPUT_PAD_6BTN; + if (strcmp(name, "team player") == 0) + return PICO_INPUT_PAD_TEAM; + if (strcmp(name, "4way play") == 0) + return PICO_INPUT_PAD_4WAY; if (strcmp(name, "None") == 0) return PICO_INPUT_NOTHING; @@ -1719,8 +1751,8 @@ void retro_run(void) input_poll_cb(); - PicoIn.pad[0] = PicoIn.pad[1] = 0; - for (pad = 0; pad < 2; pad++) { + PicoIn.pad[0] = PicoIn.pad[1] = PicoIn.pad[2] = PicoIn.pad[3] = 0; + for (pad = 0; pad < 4; pad++) { if (libretro_supports_bitmasks) { input = input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); for (i = 0; i < RETRO_PICO_MAP_LEN; i++) diff --git a/platform/libretro/libretro_core_options.h b/platform/libretro/libretro_core_options.h index 07e8b723..88b48d42 100644 --- a/platform/libretro/libretro_core_options.h +++ b/platform/libretro/libretro_core_options.h @@ -294,12 +294,14 @@ struct retro_core_option_v2_definition option_defs_us[] = { "picodrive_input1", "Input Device 1", NULL, - "Choose which type of controller is plugged into slot 1.", + "Choose which type of controller is plugged into slot 1. Note that a multiplayer adaptor uses both slots.", NULL, "input", { { "3 button pad", "3 Button Pad" }, { "6 button pad", "6 Button Pad" }, + { "team player", "Sega 4 Player Adaptor" }, + { "4way play", "EA 4way Play Adaptor" }, { "None", NULL }, { NULL, NULL }, }, @@ -309,7 +311,7 @@ struct retro_core_option_v2_definition option_defs_us[] = { "picodrive_input2", "Input Device 2", NULL, - "Choose which type of controller is plugged into slot 2.", + "Choose which type of controller is plugged into slot 2. This setting is ignored when a multiplayer adaptor is plugged into slot 1.", NULL, "input", { -- 2.39.2