core, linux+libretro, multiplayer adaptor support

This commit is contained in:
kub 2022-01-26 19:34:13 +00:00
parent a833e78c98
commit 1d5885dd84
9 changed files with 104 additions and 49 deletions

View file

@ -262,43 +262,29 @@ static u32 read_pad_team(int i, u32 out_bits)
int phase = Pico.m.padTHPhase[i]; int phase = Pico.m.padTHPhase[i];
u32 value; u32 value;
if (phase == 0) { switch (phase) {
case 0:
value = 0x03; value = 0x03;
goto out; break;
} case 1:
if (phase == 1) {
value = 0x0f; value = 0x0f;
goto out; break;
} case 4: case 5: case 6: case 7: // controller IDs, all 3 btn for now
value = 0x00;
pad = ~PicoIn.padInt[0]; // Get inverse of pad MXYZ SACB RLDU break;
if (phase == 8) { case 8: case 10: case 12: case 14:
pad = ~PicoIn.padInt[(phase-8) >> 1];
value = pad & 0x0f; // ?x?x RLDU value = pad & 0x0f; // ?x?x RLDU
goto out; break;
} case 9: case 11: case 13: case 15:
else if(phase == 9) { pad = ~PicoIn.padInt[(phase-8) >> 1];
value = (pad & 0xf0) >> 4; // ?x?x SACB value = (pad & 0xf0) >> 4; // ?x?x SACB
goto out; break;
default:
value = 0;
break;
} }
pad = ~PicoIn.padInt[1]; // Get inverse of pad MXYZ SACB RLDU
if (phase == 12) {
value = pad & 0x0f; // ?x?x RLDU
goto out;
}
else if(phase == 13) {
value = (pad & 0xf0) >> 4; // ?x?x SACB
goto out;
}
if (phase >= 8 && pad < 16) {
value = 0x0f;
goto out;
}
value = 0;
out:
value |= (out_bits & 0x40) | ((out_bits & 0x20)>>1); value |= (out_bits & 0x40) | ((out_bits & 0x20)>>1);
return value; return value;
} }
@ -308,8 +294,8 @@ static u32 read_pad_4way(int i, u32 out_bits)
u32 pad = (PicoMem.ioports[2] & 0x70) >> 4; u32 pad = (PicoMem.ioports[2] & 0x70) >> 4;
u32 value = 0; u32 value = 0;
if (i == 0 && !(pad & 1)) if (i == 0 && pad <= 3)
value = read_pad_3btn(pad >> 1, out_bits); value = read_pad_3btn(pad, out_bits);
value |= (out_bits & 0x40); value |= (out_bits & 0x40);
return value; return value;
@ -357,7 +343,10 @@ void PicoSetInputDevice(int port, enum input_device device)
if (port < 0 || port > 2) if (port < 0 || port > 2)
return; return;
switch (device) { if (port == 1 && port_readers[0] == read_pad_team)
func = read_nothing;
else switch (device) {
case PICO_INPUT_PAD_3BTN: case PICO_INPUT_PAD_3BTN:
func = read_pad_3btn; func = read_pad_3btn;
break; break;
@ -409,7 +398,7 @@ NOINLINE void io_ports_write(u32 a, u32 d)
Pico.m.padTHPhase[a - 1] = 0; Pico.m.padTHPhase[a - 1] = 0;
else if ((d^PicoMem.ioports[a]) & 0x60) else if ((d^PicoMem.ioports[a]) & 0x60)
Pico.m.padTHPhase[a - 1]++; 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)) if (a == 2 && ((PicoMem.ioports[a] ^ d) & 0x70))
Pico.m.padTHPhase[0] = 0; Pico.m.padTHPhase[0] = 0;
if (a == 1 && !(PicoMem.ioports[a] & 0x40) && (d & 0x40)) if (a == 1 && !(PicoMem.ioports[a] & 0x40) && (d & 0x40))

View file

@ -95,8 +95,8 @@ typedef struct PicoInterface
{ {
unsigned int opt; // POPT_* bitfield unsigned int opt; // POPT_* bitfield
unsigned short pad[2]; // Joypads, format is MXYZ SACB RLDU unsigned short pad[4]; // Joypads, format is MXYZ SACB RLDU
unsigned short padInt[2]; // internal copy unsigned short padInt[4]; // internal copy
unsigned short AHW; // active addon hardware: PAHW_* bitfield unsigned short AHW; // active addon hardware: PAHW_* bitfield
unsigned short skipFrame; // skip rendering frame, but still do sound (if enabled) and emulation stuff unsigned short skipFrame; // skip rendering frame, but still do sound (if enabled) and emulation stuff

View file

@ -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++) { for (i = 0; emuctrl_actions[i].name != NULL; i++) {
mask = emuctrl_actions[i].mask; mask = emuctrl_actions[i].mask;
if (mask & binds[IN_BIND_OFFS(k, IN_BINDTYPE_EMU)]) { 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; int player, shift = 0;
player = atoi(val + 6) - 1; player = atoi(val + 6) - 1;
if (player > 1) if (player > 3)
return -1; return -1;
if (player == 1) if (player & 1)
shift = 16; shift = 16;
*type = IN_BINDTYPE_PLAYER12; *type = IN_BINDTYPE_PLAYER12 + (player >> 1);
for (i = 0; me_ctrl_actions[i].name != NULL; i++) { for (i = 0; me_ctrl_actions[i].name != NULL; i++) {
if (strncasecmp(me_ctrl_actions[i].name, val + 8, strlen(val + 8)) == 0) if (strncasecmp(me_ctrl_actions[i].name, val + 8, strlen(val + 8)) == 0)
return me_ctrl_actions[i].mask << shift; return me_ctrl_actions[i].mask << shift;

View file

@ -1180,21 +1180,29 @@ void emu_update_input(void)
{ {
static int prev_events = 0; static int prev_events = 0;
int actions[IN_BINDTYPE_COUNT] = { 0, }; int actions[IN_BINDTYPE_COUNT] = { 0, };
int pl_actions[2]; int pl_actions[4];
int events; int events;
in_update(actions); in_update(actions);
pl_actions[0] = actions[IN_BINDTYPE_PLAYER12]; pl_actions[0] = actions[IN_BINDTYPE_PLAYER12];
pl_actions[1] = actions[IN_BINDTYPE_PLAYER12] >> 16; 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[0] = pl_actions[0] & 0xfff;
PicoIn.pad[1] = pl_actions[1] & 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) if (pl_actions[0] & 0x7000)
do_turbo(&PicoIn.pad[0], pl_actions[0]); do_turbo(&PicoIn.pad[0], pl_actions[0]);
if (pl_actions[1] & 0x7000) if (pl_actions[1] & 0x7000)
do_turbo(&PicoIn.pad[1], pl_actions[1]); 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; events = actions[IN_BINDTYPE_EMU] & PEV_MASK;

View file

@ -366,6 +366,12 @@ static int key_config_loop_wrap(int id, int keys)
case MA_CTRL_PLAYER2: case MA_CTRL_PLAYER2:
key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 1); key_config_loop(me_ctrl_actions, array_size(me_ctrl_actions) - 1, 1);
break; 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: case MA_CTRL_EMU:
key_config_loop(emuctrl_actions, array_size(emuctrl_actions) - 1, -1); key_config_loop(emuctrl_actions, array_size(emuctrl_actions) - 1, -1);
break; break;
@ -396,15 +402,18 @@ static const char *mgn_dev_name(int id, int *offs)
static int mh_saveloadcfg(int id, int keys); static int mh_saveloadcfg(int id, int keys);
static const char *mgn_saveloadcfg(int id, int *offs); 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[] = static menu_entry e_menu_keyconfig[] =
{ {
mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap), 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 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_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 1", MA_OPT_INPUT_DEV0, currentConfig.input_dev0, indev0_names),
mee_enum ("Input device 2", MA_OPT_INPUT_DEV1, currentConfig.input_dev1, indev_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 ("Turbo rate", MA_CTRL_TURBO_RATE, currentConfig.turbo_rate, 1, 30),
mee_range ("Analog deadzone", MA_CTRL_DEADZONE, currentConfig.analog_deadzone, 1, 99), 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), mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_saveloadcfg, mgn_saveloadcfg),

View file

@ -93,6 +93,8 @@ typedef enum
MA_SMSOPT_GHOSTING, MA_SMSOPT_GHOSTING,
MA_CTRL_PLAYER1, MA_CTRL_PLAYER1,
MA_CTRL_PLAYER2, MA_CTRL_PLAYER2,
MA_CTRL_PLAYER3,
MA_CTRL_PLAYER4,
MA_CTRL_EMU, MA_CTRL_EMU,
MA_CTRL_TURBO_RATE, MA_CTRL_TURBO_RATE,
MA_CTRL_DEADZONE, MA_CTRL_DEADZONE,

@ -1 +1 @@
Subproject commit d57c9992201e065f8caf6ce68247195ff98e8420 Subproject commit 25cfdf0a342a64a01710c1b6fbe3b1b04f28975e

View file

@ -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_SELECT,"Mode" },
{ 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 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 }, { 0 },
}; };
@ -1442,6 +1470,10 @@ static enum input_device input_name_to_val(const char *name)
return PICO_INPUT_PAD_3BTN; return PICO_INPUT_PAD_3BTN;
if (strcmp(name, "6 button pad") == 0) if (strcmp(name, "6 button pad") == 0)
return PICO_INPUT_PAD_6BTN; 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) if (strcmp(name, "None") == 0)
return PICO_INPUT_NOTHING; return PICO_INPUT_NOTHING;
@ -1719,8 +1751,8 @@ void retro_run(void)
input_poll_cb(); input_poll_cb();
PicoIn.pad[0] = PicoIn.pad[1] = 0; PicoIn.pad[0] = PicoIn.pad[1] = PicoIn.pad[2] = PicoIn.pad[3] = 0;
for (pad = 0; pad < 2; pad++) { for (pad = 0; pad < 4; pad++) {
if (libretro_supports_bitmasks) { if (libretro_supports_bitmasks) {
input = input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); input = input_state_cb(pad, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
for (i = 0; i < RETRO_PICO_MAP_LEN; i++) for (i = 0; i < RETRO_PICO_MAP_LEN; i++)

View file

@ -294,12 +294,14 @@ struct retro_core_option_v2_definition option_defs_us[] = {
"picodrive_input1", "picodrive_input1",
"Input Device 1", "Input Device 1",
NULL, 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, NULL,
"input", "input",
{ {
{ "3 button pad", "3 Button Pad" }, { "3 button pad", "3 Button Pad" },
{ "6 button pad", "6 Button Pad" }, { "6 button pad", "6 Button Pad" },
{ "team player", "Sega 4 Player Adaptor" },
{ "4way play", "EA 4way Play Adaptor" },
{ "None", NULL }, { "None", NULL },
{ NULL, NULL }, { NULL, NULL },
}, },
@ -309,7 +311,7 @@ struct retro_core_option_v2_definition option_defs_us[] = {
"picodrive_input2", "picodrive_input2",
"Input Device 2", "Input Device 2",
NULL, 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, NULL,
"input", "input",
{ {