core, linux+libretro, multiplayer adaptor support
authorkub <derkub@gmail.com>
Wed, 26 Jan 2022 19:34:13 +0000 (19:34 +0000)
committerkub <derkub@gmail.com>
Wed, 26 Jan 2022 19:41:19 +0000 (19:41 +0000)
pico/memory.c
pico/pico.h
platform/common/config_file.c
platform/common/emu.c
platform/common/menu_pico.c
platform/common/menu_pico.h
platform/libpicofe
platform/libretro/libretro.c
platform/libretro/libretro_core_options.h

index f98375f..8909393 100644 (file)
@@ -262,43 +262,29 @@ static u32 read_pad_team(int i, u32 out_bits)
   int phase = Pico.m.padTHPhase[i];\r
   u32 value;\r
 \r
-  if (phase == 0) {\r
+  switch (phase) {\r
+  case 0:\r
     value = 0x03;\r
-    goto out;\r
-  }\r
-  if (phase == 1) {\r
+    break;\r
+  case 1:\r
     value = 0x0f;\r
-    goto out;\r
-  }\r
-\r
-  pad = ~PicoIn.padInt[0]; // Get inverse of pad MXYZ SACB RLDU\r
-  if (phase == 8) {\r
-    value = pad & 0x0f;                          // ?x?x RLDU\r
-    goto out;\r
-  }\r
-  else if(phase == 9) {\r
-    value = (pad & 0xf0) >>  4;                  // ?x?x SACB\r
-    goto out;\r
-  }\r
-\r
-  pad = ~PicoIn.padInt[1]; // Get inverse of pad MXYZ SACB RLDU\r
-  if (phase == 12) {\r
+    break;\r
+  case 4: case 5: case 6: case 7: // controller IDs, all 3 btn for now\r
+    value = 0x00;\r
+    break;\r
+  case 8: case 10: case 12: case 14:\r
+    pad = ~PicoIn.padInt[(phase-8) >> 1];\r
     value = pad & 0x0f;                          // ?x?x RLDU\r
-    goto out;\r
-  }\r
-  else if(phase == 13) {\r
+    break;\r
+  case 9: case 11: case 13: case 15:\r
+    pad = ~PicoIn.padInt[(phase-8) >> 1];\r
     value = (pad & 0xf0) >>  4;                  // ?x?x SACB\r
-    goto out;\r
-  }\r
-\r
-  if (phase >= 8 && pad < 16) {\r
-    value = 0x0f;\r
-    goto out;\r
+    break;\r
+  default:\r
+    value = 0;\r
+    break;\r
   }\r
 \r
-  value = 0;\r
-\r
-out:\r
   value |= (out_bits & 0x40) | ((out_bits & 0x20)>>1);\r
   return value;\r
 }\r
@@ -308,8 +294,8 @@ static u32 read_pad_4way(int i, u32 out_bits)
   u32 pad = (PicoMem.ioports[2] & 0x70) >> 4;\r
   u32 value = 0;\r
 \r
-  if (i == 0 && !(pad & 1))\r
-    value = read_pad_3btn(pad >> 1, out_bits);\r
+  if (i == 0 && pad <= 3)\r
+    value = read_pad_3btn(pad, out_bits);\r
 \r
   value |= (out_bits & 0x40);\r
   return value;\r
@@ -357,7 +343,10 @@ void PicoSetInputDevice(int port, enum input_device device)
   if (port < 0 || port > 2)\r
     return;\r
 \r
-  switch (device) {\r
+  if (port == 1 && port_readers[0] == read_pad_team)\r
+    func = read_nothing;\r
+\r
+  else switch (device) {\r
   case PICO_INPUT_PAD_3BTN:\r
     func = read_pad_3btn;\r
     break;\r
@@ -409,7 +398,7 @@ NOINLINE void io_ports_write(u32 a, u32 d)
         Pico.m.padTHPhase[a - 1] = 0;\r
       else if ((d^PicoMem.ioports[a]) & 0x60)\r
         Pico.m.padTHPhase[a - 1]++;\r
-    } else if (port_readers[a - 1] == read_pad_4way) {\r
+    } else if (port_readers[0] == read_pad_4way) {\r
       if (a == 2 && ((PicoMem.ioports[a] ^ d) & 0x70))\r
         Pico.m.padTHPhase[0] = 0;\r
       if (a == 1 && !(PicoMem.ioports[a] & 0x40) && (d & 0x40))\r
index 39fd838..8746b9b 100644 (file)
@@ -95,8 +95,8 @@ typedef struct PicoInterface
 {\r
        unsigned int opt; // POPT_* bitfield\r
 \r
-       unsigned short pad[2];     // Joypads, format is MXYZ SACB RLDU\r
-       unsigned short padInt[2];  // internal copy\r
+       unsigned short pad[4];     // Joypads, format is MXYZ SACB RLDU\r
+       unsigned short padInt[4];  // internal copy\r
        unsigned short AHW;        // active addon hardware: PAHW_* bitfield\r
 \r
        unsigned short skipFrame;      // skip rendering frame, but still do sound (if enabled) and emulation stuff\r
index 18331d7..c4f611d 100644 (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++) {
                        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;
index 1b3e708..5d4f8ff 100644 (file)
@@ -1180,21 +1180,29 @@ void emu_update_input(void)
 {\r
        static int prev_events = 0;\r
        int actions[IN_BINDTYPE_COUNT] = { 0, };\r
-       int pl_actions[2];\r
+       int pl_actions[4];\r
        int events;\r
 \r
        in_update(actions);\r
 \r
        pl_actions[0] = actions[IN_BINDTYPE_PLAYER12];\r
        pl_actions[1] = actions[IN_BINDTYPE_PLAYER12] >> 16;\r
+       pl_actions[2] = actions[IN_BINDTYPE_PLAYER34];\r
+       pl_actions[3] = actions[IN_BINDTYPE_PLAYER34] >> 16;\r
 \r
        PicoIn.pad[0] = pl_actions[0] & 0xfff;\r
        PicoIn.pad[1] = pl_actions[1] & 0xfff;\r
+       PicoIn.pad[2] = pl_actions[2] & 0xfff;\r
+       PicoIn.pad[3] = pl_actions[3] & 0xfff;\r
 \r
        if (pl_actions[0] & 0x7000)\r
                do_turbo(&PicoIn.pad[0], pl_actions[0]);\r
        if (pl_actions[1] & 0x7000)\r
                do_turbo(&PicoIn.pad[1], pl_actions[1]);\r
+       if (pl_actions[2] & 0x7000)\r
+               do_turbo(&PicoIn.pad[2], pl_actions[2]);\r
+       if (pl_actions[3] & 0x7000)\r
+               do_turbo(&PicoIn.pad[3], pl_actions[3]);\r
 \r
        events = actions[IN_BINDTYPE_EMU] & PEV_MASK;\r
 \r
index 1151ad4..812ea84 100644 (file)
@@ -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),
index 0c81563..fb1c67d 100644 (file)
@@ -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,
index d57c999..25cfdf0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d57c9992201e065f8caf6ce68247195ff98e8420
+Subproject commit 25cfdf0a342a64a01710c1b6fbe3b1b04f28975e
index 8aadedf..8646865 100644 (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_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++)
index 07e8b72..88b48d4 100644 (file)
@@ -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",
       {