rework input code master github/master
authornotaz <notasas@gmail.com>
Wed, 11 Mar 2026 01:10:06 +0000 (03:10 +0200)
committernotaz <notasas@gmail.com>
Thu, 12 Mar 2026 01:23:23 +0000 (03:23 +0200)
an attempt to improve multitap support
notaz/pcsx_rearmed#410

Makefile
include/psemu_plugin_defs.h
jni/Android.mk
libpcsxcore/pad.c [new file with mode: 0644]
libpcsxcore/plugins.c
libpcsxcore/plugins.h
libpcsxcore/r3000a.c

index 3975e3a..c13e21e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -88,7 +88,8 @@ OBJS += libpcsxcore/cdriso.o libpcsxcore/cdrom.o libpcsxcore/cdrom-async.o \
        libpcsxcore/psxcommon.o libpcsxcore/psxcounters.o libpcsxcore/psxdma.o \
        libpcsxcore/psxhw.o libpcsxcore/psxinterpreter.o libpcsxcore/psxmem.o \
        libpcsxcore/psxevents.o libpcsxcore/r3000a.o \
-       libpcsxcore/sio.o libpcsxcore/spu.o libpcsxcore/gpu.o
+       libpcsxcore/sio.o libpcsxcore/spu.o libpcsxcore/gpu.o \
+       libpcsxcore/pad.o
 OBJS += libpcsxcore/gte.o libpcsxcore/gte_nf.o libpcsxcore/gte_divider.o
 #OBJS += libpcsxcore/debug.o libpcsxcore/socket.o libpcsxcore/disr3000a.o
 
index 88331f1..2f8e838 100644 (file)
@@ -235,10 +235,15 @@ typedef struct PadDataS
                unsigned char padding;
        } ds;
        unsigned char multitapLongModeEnabled;
-       unsigned char padding2;
-       unsigned char txData[34];
-
-       unsigned char reserved[22];
+       unsigned char respSize;
+       unsigned char txData[8];      // after multitap
+       unsigned char txData1;        // txData[1] before multitap
+       unsigned char reserved1[25];
+       unsigned char rxData[8];
+       unsigned char rxDataOld[8];   // for multitap
+       unsigned char respSizeOld;
+
+       unsigned char reserved2[5];
 } PadDataS;
 
 typedef struct {
index 88ca248..6f2bfd1 100644 (file)
@@ -36,6 +36,7 @@ SOURCES_C := $(CORE_DIR)/cdriso.c \
              $(CORE_DIR)/decode_xa.c \
              $(CORE_DIR)/mdec.c \
              $(CORE_DIR)/misc.c \
+             $(CORE_DIR)/pad.c \
              $(CORE_DIR)/plugins.c \
              $(CORE_DIR)/ppf.c \
              $(CORE_DIR)/psxbios.c \
diff --git a/libpcsxcore/pad.c b/libpcsxcore/pad.c
new file mode 100644 (file)
index 0000000..2f107b2
--- /dev/null
@@ -0,0 +1,593 @@
+/***************************************************************************
+ *   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.                          *
+ ***************************************************************************/
+
+#include <stdio.h> // SEEK_CUR
+#include "psxcommon.h"
+#include "psxcounters.h"
+#include "plugins.h"
+
+extern int in_type[8];
+
+// Pad information, keystate, mode, config mode, vibration
+static PadDataS pads[8];
+
+static int reqPos;
+
+// response for request 44, 45, 46, 47, 4C, 4D
+static const u8 resp45[8]    = {0xF3, 0x5A, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00};
+static const u8 resp46_00[8] = {0xF3, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A};
+static const u8 resp46_01[8] = {0xF3, 0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x14};
+static const u8 resp47[8]    = {0xF3, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00};
+static const u8 resp4C_00[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00};
+static const u8 resp4C_01[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00};
+
+// fixed reponse of request number 41, 48, 49, 4A, 4B, 4E, 4F
+static const u8 resp4x[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+// Resquest of psx core
+enum {
+       // REQUEST
+       // first call of this request for the pad, the pad is configured as an digital pad.
+       // 0x0X, 0x42, 0x0Y, 0xZZ, 0xAA, 0x00, 0x00, 0x00, 0x00
+       // X pad number (used for the multitap, first request response 0x00, 0x80, 0x5A, (8 bytes pad A), (8 bytes pad B), (8 bytes pad C), (8 bytes pad D)
+       // Y if 1 : psx request the full length response for the multitap, 3 bytes header and 4 block of 8 bytes per pad
+       // Y if 0 : psx request a pad key state
+       // ZZ rumble small motor 00-> OFF, 01 -> ON
+       // AA rumble large motor speed 0x00 -> 0xFF
+       // RESPONSE
+       // header 3 Bytes
+       // 0x00
+       // PadId -> 0x41 for digital pas, 0x73 for analog pad
+       // 0x5A mode has not change (no press on analog button on the center of pad), 0x00 the analog button have been pressed and the mode switch
+       // 6 Bytes for keystates
+       CMD_READ_DATA_AND_VIBRATE = 0x42,
+
+       // REQUEST
+       // Header
+       // 0x0N, 0x43, 0x00, XX, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       // XX = 00 -> Normal mode : Seconde bytes of response = padId
+       // XX = 01 -> Configuration mode : Seconde bytes of response = 0xF3
+       // RESPONSE
+       // enter in config mode example :
+       // req : 01 43 00 01 00 00 00 00 00 00
+       // res : 00 41 5A buttons state, analog states
+       // exit config mode :
+       // req : 01 43 00 00 00 00 00 00 00 00
+       // res : 00 F3 5A buttons state, analog states
+       CMD_CONFIG_MODE = 0x43,
+
+       // Set led State
+       // REQUEST
+       // 0x0N, 0x44, 0x00, VAL, SEL, 0x00, 0x00, 0x00, 0x00
+       // If sel = 2 then
+       // VAL = 00 -> OFF
+       // VAL = 01 -> ON
+       // RESPONSE
+       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       CMD_SET_MODE_AND_LOCK = 0x44,
+
+       // Get Analog Led state
+       // REQUEST
+       // 0x0N, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       // RESPONSE
+       // 0x00, 0xF3, 0x5A, 0x01, 0x02, VAL, 0x02, 0x01, 0x00
+       // VAL = 00 Led OFF
+       // VAL = 01 Led ON
+       CMD_QUERY_MODEL_AND_MODE = 0x45,
+
+       //Get Variable A
+       // REQUEST
+       // 0x0N, 0x46, 0x00, 0xXX, 0x00, 0x00, 0x00, 0x00, 0x00
+       // RESPONSE
+       // XX=00
+       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A
+       // XX=01
+       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x14
+       CMD_QUERY_ACT = 0x46,
+
+       // REQUEST
+       // 0x0N, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+       // RESPONSE
+       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00
+       CMD_QUERY_COMB = 0x47,
+
+       // REQUEST
+       // 0x0N, 0x4C, 0x00, 0xXX, 0x00, 0x00, 0x00, 0x00, 0x00
+       // RESPONSE
+       // XX = 0
+       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00
+       // XX = 1
+       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00
+       CMD_QUERY_MODE = 0x4C,
+
+       // REQUEST
+       // 0x0N, 0x4D, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
+       // RESPONSE
+       // 0x00, 0xF3, 0x5A, old value or
+       // AA = 01 unlock large motor (and swap VAL1 and VAL2)
+       // BB = 01 unlock large motor (default)
+       // CC, DD, EE, FF = all FF -> unlock small motor
+       //
+       // default repsonse for analog pad with 2 motor : 0x00 0xF3 0x5A 0x00 0x01 0xFF 0xFF 0xFF 0xFF
+       //
+       CMD_VIBRATION_TOGGLE = 0x4D,
+       REQ40 = 0x40,
+       REQ41 = 0x41,
+       REQ49 = 0x49,
+       REQ4A = 0x4A,
+       REQ4B = 0x4B,
+       REQ4E = 0x4E,
+       REQ4F = 0x4F
+};
+
+#if 0
+#define PAD_LOG_TX(pos, v) buf_tx[pos] = v
+#define PAD_LOG_RX(pos, v) buf_rx[pos] = v
+static unsigned char buf_tx[35], buf_rx[35];
+static void log_pad_print(int port, int last_pos)
+{
+       if (port == 0) {
+               int i;
+               for (i = 0; i <= last_pos; i++)
+                       printf("%02x ", buf_tx[i]);
+               printf("|");
+               for (i = 0; i <= last_pos; i++)
+                       printf(" %02x", buf_rx[i]);
+               printf("\n");
+       }
+}
+#else
+#define PAD_LOG_TX(pos, v)
+#define PAD_LOG_RX(pos, v)
+#define log_pad_print(port, last_pos)
+#endif
+
+static void initBufForRequest(PadDataS *pad, unsigned char value)
+{
+       if (pad->ds.configMode) {
+               pad->rxData[0] = 0xf3;
+               pad->rxData[1] = 0x5a;
+               pad->respSize = 8;
+       }
+       else if (value != 0x42 && value != 0x43) {
+               pad->respSize = 1;
+               return;
+       }
+
+       if ((u32)(frame_counter - pad->ds.lastUseFrame) > 2*60u
+           && pad->ds.configModeUsed
+           && !Config.hacks.dualshock_init_analog)
+       {
+               //SysPrintf("Pad reset\n");
+               pad->ds.padMode = 0; // according to nocash
+               pad->ds.autoAnalogTried = 0;
+       }
+       else if (pad->ds.padMode == 0 && value == CMD_READ_DATA_AND_VIBRATE
+                && pad->ds.configModeUsed
+                && !pad->ds.configMode
+                && !pad->ds.userToggled)
+       {
+               if (pad->ds.autoAnalogTried == 16) {
+                       // auto-enable for convenience
+                       SysPrintf("Pad%ld: Auto-enabling dualshock analog mode.\n",
+                               (long)(pad - pads + 1));
+                       pad->ds.padMode = 1;
+                       pad->ds.autoAnalogTried = 255;
+               }
+               else if (pad->ds.autoAnalogTried < 16)
+                       pad->ds.autoAnalogTried++;
+       }
+       pad->ds.lastUseFrame = frame_counter;
+
+       switch (value) {
+               // keystate already in buffer, set by PADstartPoll_()
+               //case CMD_READ_DATA_AND_VIBRATE :
+               //case CMD_CONFIG_MODE : // 43
+               //      break;
+               case CMD_SET_MODE_AND_LOCK :
+                       break;
+               case CMD_QUERY_MODEL_AND_MODE :
+                       memcpy(pad->rxData, resp45, 8);
+                       pad->rxData[4] = pad->ds.padMode;
+                       break;
+               case CMD_QUERY_ACT :
+                       memcpy(pad->rxData, resp46_00, 8);
+                       break;
+               case CMD_QUERY_COMB :
+                       memcpy(pad->rxData, resp47, 8);
+                       break;
+               case CMD_QUERY_MODE :
+                       memcpy(pad->rxData, resp4C_00, 8);
+                       break;
+               case CMD_VIBRATION_TOGGLE: // 4d
+                       memcpy(pad->rxData + 2, pad->ds.cmd4dConfig, 6);
+                       break;
+               case REQ40 :
+               case REQ41 :
+               case REQ49 :
+               case REQ4A :
+               case REQ4B :
+               case REQ4E :
+               case REQ4F :
+                       memcpy(pad->rxData, resp4x, 8);
+                       break;
+       }
+}
+
+static void reqIndex2Treatment(PadDataS *pad, unsigned char value)
+{
+       switch (pad->txData[0]) {
+               case CMD_CONFIG_MODE : // 43
+                       if (value == 0) {
+                               pad->ds.configMode = 0;
+                       } else if (value == 1) {
+                               pad->ds.configMode = 1;
+                               pad->ds.configModeUsed = 1;
+                       }
+                       break;
+               case CMD_SET_MODE_AND_LOCK : // 44
+                       //0x44 store the led state for change mode if the next value = 0x02
+                       //0x01 analog ON
+                       //0x00 analog OFF
+                       if ((value & ~1) == 0)
+                               pad->ds.padMode = value;
+                       break;
+               case CMD_QUERY_ACT : // 46
+                       if (value == 1) {
+                               memcpy(pad->rxData, resp46_01, 8);
+                       }
+                       break;
+               case CMD_QUERY_MODE : // 4c
+                       if (value == 1) {
+                               memcpy(pad->rxData, resp4C_01, 8);
+                       }
+                       break;
+       }
+}
+
+static void ds_update_vibrate(PadDataS *pad)
+{
+       if (pad->ds.configModeUsed) {
+               pad->Vib[0] = (pad->Vib[0] == 1) ? 1 : 0;
+       }
+       else {
+               // compat mode
+               pad->Vib[0] = (pad->Vib[0] & 0xc0) == 0x40 && (pad->Vib[1] & 1);
+               pad->Vib[1] = 0;
+       }
+       if (pad->Vib[0] != pad->VibF[0] || pad->Vib[1] != pad->VibF[1]) {
+               size_t padIndex = pad - pads;
+               //value is different update Value and call libretro for vibration
+               pad->VibF[0] = pad->Vib[0];
+               pad->VibF[1] = pad->Vib[1];
+               plat_trigger_vibrate(padIndex, pad->VibF[0], pad->VibF[1]);
+               //printf("vib%zi %02x %02x\n", padIndex, pad->VibF[0], pad->VibF[1]);
+       }
+}
+
+static void adjust_analog(unsigned char *b)
+{
+       // ff8 hates 0x80 for whatever reason (broken in 2d area menus),
+       // or is this caused by something else we do wrong??
+       // Also S.C.A.R.S. treats 0x7f as turning left.
+       if (b[6] == 0x7f || b[6] == 0x80)
+               b[6] = 0x81;
+}
+
+// Build response for 0x42 request Pad in port
+static void PADstartPoll_(PadDataS *pad)
+{
+       pad->respSizeOld = pad->respSize;
+       switch (pad->controllerType) {
+               case PSE_PAD_TYPE_MOUSE:
+                       pad->rxData[0] = 0x12;
+                       pad->rxData[1] = 0x5a;
+                       pad->rxData[2] = pad->buttonStatus & 0xff;
+                       pad->rxData[3] = pad->buttonStatus >> 8;
+                       pad->rxData[4] = pad->moveX;
+                       pad->rxData[5] = pad->moveY;
+                       pad->respSize = 6;
+                       break;
+               case PSE_PAD_TYPE_NEGCON: // npc101/npc104(slph00001/slph00069)
+                       pad->rxData[0] = 0x23;
+                       pad->rxData[1] = 0x5a;
+                       pad->rxData[2] = pad->buttonStatus & 0xff;
+                       pad->rxData[3] = pad->buttonStatus >> 8;
+                       pad->rxData[4] = pad->rightJoyX;
+                       pad->rxData[5] = pad->rightJoyY;
+                       pad->rxData[6] = pad->leftJoyX;
+                       pad->rxData[7] = pad->leftJoyY;
+                       pad->respSize = 8;
+                       break;
+               case PSE_PAD_TYPE_GUNCON: // GUNCON - gun controller SLPH-00034 from Namco
+                       pad->rxData[0] = 0x63;
+                       pad->rxData[1] = 0x5a;
+                       pad->rxData[2] = pad->buttonStatus & 0xff;
+                       pad->rxData[3] = pad->buttonStatus >> 8;
+
+                       int absX = pad->absoluteX; // 0-1023
+                       int absY = pad->absoluteY;
+
+                       if (absX == 65536 || absY == 65536) {
+                               pad->rxData[4] = 0x01;
+                               pad->rxData[5] = 0x00;
+                               pad->rxData[6] = 0x0A;
+                               pad->rxData[7] = 0x00;
+                       }
+                       else {
+                               int y_ofs = 0, yres = 240;
+                               GPU_getScreenInfo(&y_ofs, &yres);
+                               int y_top = (Config.PsxType ? 0x30 : 0x19) + y_ofs;
+                               int w = Config.PsxType ? 385 : 378;
+                               int x = 0x40 + (w * absX >> 10);
+                               int y = y_top + (yres * absY >> 10);
+                               //printf("%3d %3d %4x %4x\n", absX, absY, x, y);
+
+                               pad->rxData[4] = x;
+                               pad->rxData[5] = x >> 8;
+                               pad->rxData[6] = y;
+                               pad->rxData[7] = y >> 8;
+                       }
+                       pad->respSize = 8;
+                       break;
+               case PSE_PAD_TYPE_GUN: // GUN CONTROLLER - gun controller SLPH-00014 from Konami
+                       pad->rxData[0] = 0x31;
+                       pad->rxData[1] = 0x5a;
+                       pad->rxData[2] = pad->buttonStatus & 0xff;
+                       pad->rxData[3] = pad->buttonStatus >> 8;
+                       pad->respSize = 4;
+                       break;
+               case PSE_PAD_TYPE_ANALOGPAD: // scph1150
+                       if ((pad->ds.padMode | pad->ds.configMode) == 0)
+                               goto standard;
+                       pad->rxData[0] = 0x73;
+                       pad->rxData[1] = 0x5a;
+                       pad->rxData[2] = pad->buttonStatus & 0xff;
+                       pad->rxData[3] = pad->buttonStatus >> 8;
+                       pad->rxData[4] = pad->rightJoyX;
+                       pad->rxData[5] = pad->rightJoyY;
+                       pad->rxData[6] = pad->leftJoyX;
+                       pad->rxData[7] = pad->leftJoyY;
+                       adjust_analog(pad->rxData);
+                       pad->respSize = 8;
+                       break;
+               case PSE_PAD_TYPE_ANALOGJOY: // scph1110
+                       pad->rxData[0] = 0x53;
+                       pad->rxData[1] = 0x5a;
+                       pad->rxData[2] = pad->buttonStatus & 0xff;
+                       pad->rxData[3] = pad->buttonStatus >> 8;
+                       pad->rxData[4] = pad->rightJoyX;
+                       pad->rxData[5] = pad->rightJoyY;
+                       pad->rxData[6] = pad->leftJoyX;
+                       pad->rxData[7] = pad->leftJoyY;
+                       adjust_analog(pad->rxData);
+                       pad->respSize = 8;
+                       break;
+               case PSE_PAD_TYPE_STANDARD:
+               standard:
+                       pad->rxData[0] = 0x41;
+                       pad->rxData[1] = 0x5a;
+                       pad->rxData[2] = pad->buttonStatus & 0xff;
+                       pad->rxData[3] = pad->buttonStatus >> 8;
+                       pad->respSize = 4;
+                       break;
+               default:
+                       pad->respSize = 0;
+                       break;
+       }
+}
+
+static void PADpoll_dualshock(PadDataS *pad, unsigned char value, int pos)
+{
+       switch (pos) {
+               case 0:
+                       initBufForRequest(pad, value);
+                       break;
+               case 2:
+                       reqIndex2Treatment(pad, value);
+                       break;
+               case 7:
+                       if (pad->txData[0] == CMD_VIBRATION_TOGGLE)
+                               memcpy(pad->ds.cmd4dConfig, pad->txData + 2, 6);
+                       break;
+       }
+
+       if (pad->txData[0] == CMD_READ_DATA_AND_VIBRATE
+           && !pad->ds.configModeUsed && 2 <= pos && pos < 4)
+       {
+               // "compat" single motor mode
+               pad->Vib[pos - 2] = value;
+       }
+       else if (pad->txData[0] == CMD_READ_DATA_AND_VIBRATE
+                && 2 <= pos && pos < 8)
+       {
+               // 0 - weak motor, 1 - strong motor
+               int dev = pad->ds.cmd4dConfig[pos - 2];
+               if (dev < 2)
+                       pad->Vib[dev] = value;
+       }
+       if (pos == pad->respSize - 1)
+               ds_update_vibrate(pad);
+}
+
+static unsigned char PADpoll_(int port, unsigned char value, int pos, int *more_data)
+{
+       PadDataS *pad = &pads[port];
+
+       if (pos < sizeof(pad->txData))
+               pad->txData[pos] = value;
+       if (pos == 0 && value != 0x42 && in_type[port] != PSE_PAD_TYPE_ANALOGPAD)
+               pad->respSize = 1;
+
+       switch (in_type[port]) {
+               case PSE_PAD_TYPE_ANALOGPAD:
+                       PADpoll_dualshock(pad, value, pos);
+                       break;
+               case PSE_PAD_TYPE_GUN:
+                       if (pos == 2)
+                               pl_gun_byte2(port, value);
+                       break;
+       }
+
+       *more_data = pos < pad->respSize - 1;
+       if (pos >= pad->respSize) {
+               log_unhandled("pad %zd read %d/%d\n", pad - pads, pos, pad->respSize);
+               return 0xff; // no response/HiZ
+       }
+
+       return pad->rxData[pos];
+}
+
+// response: 0x80, 0x5A, 8 bytes each for ports A, B, C, D
+static unsigned char PADpollMultitap(int port, unsigned char value, int pos, int *more_data)
+{
+       unsigned int pos_dev, dev;
+       int unused = 0;
+       PadDataS *pad;
+
+       if (pos == 0) {
+               *more_data = (value == 0x42);
+               return 0x80;
+       }
+       *more_data = pos < 34 - 1;
+       if (pos == 1)
+               return 0x5a;
+       if (pos >= 34) {
+               log_unhandled("pad %d read %d/%d\n", port, pos, 34);
+               return 0xff;
+       }
+
+       pos_dev = pos - 2;
+       dev = pos_dev / 8u;
+       pad = &pads[port + dev];
+       if (pos_dev % 8u == 0) {
+               memcpy(pad->rxDataOld, pad->rxData, sizeof(pad->rxDataOld));
+               PADstartPoll_(pad);
+       }
+       pos_dev = pos_dev & 7;
+       PADpoll_(port + dev, value, pos_dev, &unused);
+       return pos_dev < pad->respSizeOld ? pad->rxDataOld[pos_dev] : 0xff;
+}
+
+static unsigned char PADpollMain(int port, unsigned char value, int *more_data)
+{
+       unsigned char ret;
+       int pos = reqPos++;
+
+       PAD_LOG_TX(pos, value);
+
+       if (pos == 1)
+               pads[port].txData1 = value;
+       if (!pads[port].portMultitap || !pads[port].multitapLongModeEnabled)
+               ret = PADpoll_(port, value, pos, more_data);
+       else
+               ret = PADpollMultitap(port, value, pos, more_data);
+
+       PAD_LOG_RX(pos, ret);
+       if (!*more_data)
+               log_pad_print(port, pos);
+       return ret;
+
+}
+
+// refresh the button state on port 1.
+// int pad is not needed.
+unsigned char PAD1_startPoll(int unused)
+{
+       int i;
+
+       reqPos = 0;
+       pads[0].requestPadIndex = 0;
+       PAD1_readPort(&pads[0]);
+
+       pads[0].multitapLongModeEnabled = 0;
+       if (pads[0].portMultitap)
+               pads[0].multitapLongModeEnabled = pads[0].txData1 & 1;
+
+       if (!pads[0].portMultitap || !pads[0].multitapLongModeEnabled) {
+               PADstartPoll_(&pads[0]);
+       } else {
+               // a multitap is plugged and enabled: refresh pads 1-3
+               for (i = 1; i < 4; i++) {
+                       pads[i].requestPadIndex = i;
+                       PAD1_readPort(&pads[i]);
+               }
+       }
+       return 0xff;
+}
+
+unsigned char PAD1_poll(unsigned char value, int *more_data) {
+       return PADpollMain(0, value, more_data);
+}
+
+
+unsigned char PAD2_startPoll(int pad)
+{
+       int pad_index = pads[0].portMultitap ? 4 : 1;
+       int i;
+
+       reqPos = 0;
+       pads[pad_index].requestPadIndex = pad_index;
+       PAD2_readPort(&pads[pad_index]);
+
+       pads[pad_index].multitapLongModeEnabled = 0;
+       if (pads[pad_index].portMultitap)
+               pads[pad_index].multitapLongModeEnabled = pads[pad_index].txData1 & 1;
+
+       if (!pads[pad_index].portMultitap || !pads[pad_index].multitapLongModeEnabled) {
+               PADstartPoll_(&pads[pad_index]);
+       } else {
+               for (i = 1; i < 4; i++) {
+                       pads[pad_index + i].requestPadIndex = pad_index + i;
+                       PAD2_readPort(&pads[pad_index + i]);
+               }
+       }
+       return 0xff;
+}
+
+unsigned char PAD2_poll(unsigned char value, int *more_data) {
+       return PADpollMain(pads[0].portMultitap ? 4 : 1, value, more_data);
+}
+
+void padReset(void) {
+       size_t p;
+
+       memset(pads, 0, sizeof(pads));
+       for (p = 0; p < sizeof(pads) / sizeof(pads[0]); p++) {
+               memset(pads[p].rxData, 0xff, sizeof(pads[p].rxData));
+               memset(pads[p].ds.cmd4dConfig, 0xff, sizeof(pads[p].ds.cmd4dConfig));
+       }
+}
+
+int padFreeze(void *f, int Mode) {
+       size_t i;
+
+       for (i = 0; i < sizeof(pads) / sizeof(pads[0]); i++) {
+               pads[i].saveSize = sizeof(pads[i]);
+               gzfreeze(&pads[i], sizeof(pads[i]));
+               if (Mode == 0 && pads[i].saveSize != sizeof(pads[i]))
+                       SaveFuncs.seek(f, pads[i].saveSize - sizeof(pads[i]), SEEK_CUR);
+       }
+
+       return 0;
+}
+
+int padToggleAnalog(unsigned int index)
+{
+       int r = -1;
+
+       if (index < sizeof(pads) / sizeof(pads[0])) {
+               r = (pads[index].ds.padMode ^= 1);
+               pads[index].ds.userToggled = 1;
+       }
+       return r;
+}
index 62c15b5..bf1d283 100644 (file)
@@ -206,586 +206,6 @@ static int LoadSPUplugin(const char *SPUdll) {
        return 0;
 }
 
-extern int in_type[8];
-
-// Pad information, keystate, mode, config mode, vibration
-static PadDataS pads[8];
-
-static int reqPos, respSize;
-
-static unsigned char buf[256];
-
-static unsigned char stdpar[8] = { 0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-//response for request 44, 45, 46, 47, 4C, 4D
-static const u8 resp45[8]    = {0xF3, 0x5A, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00};
-static const u8 resp46_00[8] = {0xF3, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A};
-static const u8 resp46_01[8] = {0xF3, 0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x14};
-static const u8 resp47[8]    = {0xF3, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00};
-static const u8 resp4C_00[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00};
-static const u8 resp4C_01[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00};
-
-//fixed reponse of request number 41, 48, 49, 4A, 4B, 4E, 4F
-static const u8 resp40[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const u8 resp41[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const u8 resp43[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const u8 resp44[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const u8 resp49[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const u8 resp4A[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const u8 resp4B[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const u8 resp4E[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const u8 resp4F[8] = {0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-// Resquest of psx core
-enum {
-       // REQUEST
-       // first call of this request for the pad, the pad is configured as an digital pad.
-       // 0x0X, 0x42, 0x0Y, 0xZZ, 0xAA, 0x00, 0x00, 0x00, 0x00
-       // X pad number (used for the multitap, first request response 0x00, 0x80, 0x5A, (8 bytes pad A), (8 bytes pad B), (8 bytes pad C), (8 bytes pad D)
-       // Y if 1 : psx request the full length response for the multitap, 3 bytes header and 4 block of 8 bytes per pad
-       // Y if 0 : psx request a pad key state
-       // ZZ rumble small motor 00-> OFF, 01 -> ON
-       // AA rumble large motor speed 0x00 -> 0xFF
-       // RESPONSE
-       // header 3 Bytes
-       // 0x00
-       // PadId -> 0x41 for digital pas, 0x73 for analog pad
-       // 0x5A mode has not change (no press on analog button on the center of pad), 0x00 the analog button have been pressed and the mode switch
-       // 6 Bytes for keystates
-       CMD_READ_DATA_AND_VIBRATE = 0x42,
-
-       // REQUEST
-       // Header
-       // 0x0N, 0x43, 0x00, XX, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-       // XX = 00 -> Normal mode : Seconde bytes of response = padId
-       // XX = 01 -> Configuration mode : Seconde bytes of response = 0xF3
-       // RESPONSE
-       // enter in config mode example :
-       // req : 01 43 00 01 00 00 00 00 00 00
-       // res : 00 41 5A buttons state, analog states
-       // exit config mode :
-       // req : 01 43 00 00 00 00 00 00 00 00
-       // res : 00 F3 5A buttons state, analog states
-       CMD_CONFIG_MODE = 0x43,
-
-       // Set led State
-       // REQUEST
-       // 0x0N, 0x44, 0x00, VAL, SEL, 0x00, 0x00, 0x00, 0x00
-       // If sel = 2 then
-       // VAL = 00 -> OFF
-       // VAL = 01 -> ON
-       // RESPONSE
-       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-       CMD_SET_MODE_AND_LOCK = 0x44,
-
-       // Get Analog Led state
-       // REQUEST
-       // 0x0N, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-       // RESPONSE
-       // 0x00, 0xF3, 0x5A, 0x01, 0x02, VAL, 0x02, 0x01, 0x00
-       // VAL = 00 Led OFF
-       // VAL = 01 Led ON
-       CMD_QUERY_MODEL_AND_MODE = 0x45,
-
-       //Get Variable A
-       // REQUEST
-       // 0x0N, 0x46, 0x00, 0xXX, 0x00, 0x00, 0x00, 0x00, 0x00
-       // RESPONSE
-       // XX=00
-       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A
-       // XX=01
-       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x14
-       CMD_QUERY_ACT = 0x46,
-
-       // REQUEST
-       // 0x0N, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-       // RESPONSE
-       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00
-       CMD_QUERY_COMB = 0x47,
-
-       // REQUEST
-       // 0x0N, 0x4C, 0x00, 0xXX, 0x00, 0x00, 0x00, 0x00, 0x00
-       // RESPONSE
-       // XX = 0
-       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00
-       // XX = 1
-       // 0x00, 0xF3, 0x5A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00
-       CMD_QUERY_MODE = 0x4C,
-
-       // REQUEST
-       // 0x0N, 0x4D, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
-       // RESPONSE
-       // 0x00, 0xF3, 0x5A, old value or
-       // AA = 01 unlock large motor (and swap VAL1 and VAL2)
-       // BB = 01 unlock large motor (default)
-       // CC, DD, EE, FF = all FF -> unlock small motor
-       //
-       // default repsonse for analog pad with 2 motor : 0x00 0xF3 0x5A 0x00 0x01 0xFF 0xFF 0xFF 0xFF
-       //
-       CMD_VIBRATION_TOGGLE = 0x4D,
-       REQ40 = 0x40,
-       REQ41 = 0x41,
-       REQ49 = 0x49,
-       REQ4A = 0x4A,
-       REQ4B = 0x4B,
-       REQ4E = 0x4E,
-       REQ4F = 0x4F
-};
-
-
-static void initBufForRequest(int padIndex, char value) {
-       if (pads[padIndex].ds.configMode) {
-               buf[0] = 0xf3; buf[1] = 0x5a;
-               respSize = 8;
-       }
-       else if (value != 0x42 && value != 0x43) {
-               respSize = 1;
-               return;
-       }
-
-       if ((u32)(frame_counter - pads[padIndex].ds.lastUseFrame) > 2*60u
-           && pads[padIndex].ds.configModeUsed
-           && !Config.hacks.dualshock_init_analog)
-       {
-               //SysPrintf("Pad reset\n");
-               pads[padIndex].ds.padMode = 0; // according to nocash
-               pads[padIndex].ds.autoAnalogTried = 0;
-       }
-       else if (pads[padIndex].ds.padMode == 0 && value == CMD_READ_DATA_AND_VIBRATE
-                && pads[padIndex].ds.configModeUsed
-                && !pads[padIndex].ds.configMode
-                && !pads[padIndex].ds.userToggled)
-       {
-               if (pads[padIndex].ds.autoAnalogTried == 16) {
-                       // auto-enable for convenience
-                       SysPrintf("Auto-enabling dualshock analog mode.\n");
-                       pads[padIndex].ds.padMode = 1;
-                       pads[padIndex].ds.autoAnalogTried = 255;
-               }
-               else if (pads[padIndex].ds.autoAnalogTried < 16)
-                       pads[padIndex].ds.autoAnalogTried++;
-       }
-       pads[padIndex].ds.lastUseFrame = frame_counter;
-
-       switch (value) {
-               // keystate already in buffer, set by PADstartPoll_()
-               //case CMD_READ_DATA_AND_VIBRATE :
-               //      break;
-               case CMD_CONFIG_MODE :
-                       if (pads[padIndex].ds.configMode) {
-                               memcpy(buf, resp43, 8);
-                               break;
-                       }
-                       // else not in config mode, pad keystate return
-                       break;
-               case CMD_SET_MODE_AND_LOCK :
-                       memcpy(buf, resp44, 8);
-                       break;
-               case CMD_QUERY_MODEL_AND_MODE :
-                       memcpy(buf, resp45, 8);
-                       buf[4] = pads[padIndex].ds.padMode;
-                       break;
-               case CMD_QUERY_ACT :
-                       memcpy(buf, resp46_00, 8);
-                       break;
-               case CMD_QUERY_COMB :
-                       memcpy(buf, resp47, 8);
-                       break;
-               case CMD_QUERY_MODE :
-                       memcpy(buf, resp4C_00, 8);
-                       break;
-               case CMD_VIBRATION_TOGGLE: // 4d
-                       memcpy(buf + 2, pads[padIndex].ds.cmd4dConfig, 6);
-                       break;
-               case REQ40 :
-                       memcpy(buf, resp40, 8);
-                       break;
-               case REQ41 :
-                       memcpy(buf, resp41, 8);
-                       break;
-               case REQ49 :
-                       memcpy(buf, resp49, 8);
-                       break;
-               case REQ4A :
-                       memcpy(buf, resp4A, 8);
-                       break;
-               case REQ4B :
-                       memcpy(buf, resp4B, 8);
-                       break;
-               case REQ4E :
-                       memcpy(buf, resp4E, 8);
-                       break;
-               case REQ4F :
-                       memcpy(buf, resp4F, 8);
-                       break;
-       }
-}
-
-static void reqIndex2Treatment(int padIndex, u8 value) {
-       switch (pads[padIndex].txData[0]) {
-               case CMD_CONFIG_MODE :
-                       //0x43
-                       if (value == 0) {
-                               pads[padIndex].ds.configMode = 0;
-                       } else if (value == 1) {
-                               pads[padIndex].ds.configMode = 1;
-                               pads[padIndex].ds.configModeUsed = 1;
-                       }
-                       break;
-               case CMD_SET_MODE_AND_LOCK :
-                       //0x44 store the led state for change mode if the next value = 0x02
-                       //0x01 analog ON
-                       //0x00 analog OFF
-                       if ((value & ~1) == 0)
-                               pads[padIndex].ds.padMode = value;
-                       break;
-               case CMD_QUERY_ACT :
-                       //0x46
-                       if (value == 1) {
-                               memcpy(buf, resp46_01, 8);
-                       }
-                       break;
-               case CMD_QUERY_MODE :
-                       if (value == 1) {
-                               memcpy(buf, resp4C_01, 8);
-                       }
-                       break;
-       }
-}
-
-static void ds_update_vibrate(int padIndex) {
-       PadDataS *pad = &pads[padIndex];
-       if (pad->ds.configModeUsed) {
-               pad->Vib[0] = (pad->Vib[0] == 1) ? 1 : 0;
-       }
-       else {
-               // compat mode
-               pad->Vib[0] = (pad->Vib[0] & 0xc0) == 0x40 && (pad->Vib[1] & 1);
-               pad->Vib[1] = 0;
-       }
-       if (pad->Vib[0] != pad->VibF[0] || pad->Vib[1] != pad->VibF[1]) {
-               //value is different update Value and call libretro for vibration
-               pad->VibF[0] = pad->Vib[0];
-               pad->VibF[1] = pad->Vib[1];
-               plat_trigger_vibrate(padIndex, pad->VibF[0], pad->VibF[1]);
-               //printf("vib%i %02x %02x\n", padIndex, pad->VibF[0], pad->VibF[1]);
-       }
-}
-
-static void log_pad(int port, int pos)
-{
-#if 0
-       if (port == 0 && pos == respSize - 1) {
-               int i;
-               for (i = 0; i < respSize; i++)
-                       printf("%02x ", pads[port].txData[i]);
-               printf("|");
-               for (i = 0; i < respSize; i++)
-                       printf(" %02x", buf[i]);
-               printf("\n");
-       }
-#endif
-}
-
-static void adjust_analog(unsigned char *b)
-{
-       // ff8 hates 0x80 for whatever reason (broken in 2d area menus),
-       // or is this caused by something else we do wrong??
-       // Also S.C.A.R.S. treats 0x7f as turning left.
-       if (b[6] == 0x7f || b[6] == 0x80)
-               b[6] = 0x81;
-}
-
-// Build response for 0x42 request Pad in port
-static void PADstartPoll_(PadDataS *pad) {
-       switch (pad->controllerType) {
-               case PSE_PAD_TYPE_MOUSE:
-                       stdpar[0] = 0x12;
-                       stdpar[1] = 0x5a;
-                       stdpar[2] = pad->buttonStatus & 0xff;
-                       stdpar[3] = pad->buttonStatus >> 8;
-                       stdpar[4] = pad->moveX;
-                       stdpar[5] = pad->moveY;
-                       memcpy(buf, stdpar, 6);
-                       respSize = 6;
-                       break;
-               case PSE_PAD_TYPE_NEGCON: // npc101/npc104(slph00001/slph00069)
-                       stdpar[0] = 0x23;
-                       stdpar[1] = 0x5a;
-                       stdpar[2] = pad->buttonStatus & 0xff;
-                       stdpar[3] = pad->buttonStatus >> 8;
-                       stdpar[4] = pad->rightJoyX;
-                       stdpar[5] = pad->rightJoyY;
-                       stdpar[6] = pad->leftJoyX;
-                       stdpar[7] = pad->leftJoyY;
-                       memcpy(buf, stdpar, 8);
-                       respSize = 8;
-                       break;
-               case PSE_PAD_TYPE_GUNCON: // GUNCON - gun controller SLPH-00034 from Namco
-                       stdpar[0] = 0x63;
-                       stdpar[1] = 0x5a;
-                       stdpar[2] = pad->buttonStatus & 0xff;
-                       stdpar[3] = pad->buttonStatus >> 8;
-
-                       int absX = pad->absoluteX; // 0-1023
-                       int absY = pad->absoluteY;
-
-                       if (absX == 65536 || absY == 65536) {
-                               stdpar[4] = 0x01;
-                               stdpar[5] = 0x00;
-                               stdpar[6] = 0x0A;
-                               stdpar[7] = 0x00;
-                       }
-                       else {
-                               int y_ofs = 0, yres = 240;
-                               GPU_getScreenInfo(&y_ofs, &yres);
-                               int y_top = (Config.PsxType ? 0x30 : 0x19) + y_ofs;
-                               int w = Config.PsxType ? 385 : 378;
-                               int x = 0x40 + (w * absX >> 10);
-                               int y = y_top + (yres * absY >> 10);
-                               //printf("%3d %3d %4x %4x\n", absX, absY, x, y);
-
-                               stdpar[4] = x;
-                               stdpar[5] = x >> 8;
-                               stdpar[6] = y;
-                               stdpar[7] = y >> 8;
-                       }
-
-                       memcpy(buf, stdpar, 8);
-                       respSize = 8;
-                       break;
-               case PSE_PAD_TYPE_GUN: // GUN CONTROLLER - gun controller SLPH-00014 from Konami
-                       stdpar[0] = 0x31;
-                       stdpar[1] = 0x5a;
-                       stdpar[2] = pad->buttonStatus & 0xff;
-                       stdpar[3] = pad->buttonStatus >> 8;
-                       memcpy(buf, stdpar, 4);
-                       respSize = 4;
-                       break;
-               case PSE_PAD_TYPE_ANALOGPAD: // scph1150
-                       if (pad->ds.padMode == 0)
-                               goto standard;
-                       stdpar[0] = 0x73;
-                       stdpar[1] = 0x5a;
-                       stdpar[2] = pad->buttonStatus & 0xff;
-                       stdpar[3] = pad->buttonStatus >> 8;
-                       stdpar[4] = pad->rightJoyX;
-                       stdpar[5] = pad->rightJoyY;
-                       stdpar[6] = pad->leftJoyX;
-                       stdpar[7] = pad->leftJoyY;
-                       adjust_analog(stdpar);
-                       memcpy(buf, stdpar, 8);
-                       respSize = 8;
-                       break;
-               case PSE_PAD_TYPE_ANALOGJOY: // scph1110
-                       stdpar[0] = 0x53;
-                       stdpar[1] = 0x5a;
-                       stdpar[2] = pad->buttonStatus & 0xff;
-                       stdpar[3] = pad->buttonStatus >> 8;
-                       stdpar[4] = pad->rightJoyX;
-                       stdpar[5] = pad->rightJoyY;
-                       stdpar[6] = pad->leftJoyX;
-                       stdpar[7] = pad->leftJoyY;
-                       adjust_analog(stdpar);
-                       memcpy(buf, stdpar, 8);
-                       respSize = 8;
-                       break;
-               case PSE_PAD_TYPE_STANDARD:
-               standard:
-                       stdpar[0] = 0x41;
-                       stdpar[1] = 0x5a;
-                       stdpar[2] = pad->buttonStatus & 0xff;
-                       stdpar[3] = pad->buttonStatus >> 8;
-                       memcpy(buf, stdpar, 4);
-                       respSize = 4;
-                       break;
-               default:
-                       respSize = 0;
-                       break;
-       }
-}
-
-static void PADpoll_dualshock(int port, unsigned char value, int pos)
-{
-       switch (pos) {
-               case 0:
-                       initBufForRequest(port, value);
-                       break;
-               case 2:
-                       reqIndex2Treatment(port, value);
-                       break;
-               case 7:
-                       if (pads[port].txData[0] == CMD_VIBRATION_TOGGLE)
-                               memcpy(pads[port].ds.cmd4dConfig, pads[port].txData + 2, 6);
-                       break;
-       }
-
-       if (pads[port].txData[0] == CMD_READ_DATA_AND_VIBRATE
-           && !pads[port].ds.configModeUsed && 2 <= pos && pos < 4)
-       {
-               // "compat" single motor mode
-               pads[port].Vib[pos - 2] = value;
-       }
-       else if (pads[port].txData[0] == CMD_READ_DATA_AND_VIBRATE
-                && 2 <= pos && pos < 8)
-       {
-               // 0 - weak motor, 1 - strong motor
-               int dev = pads[port].ds.cmd4dConfig[pos - 2];
-               if (dev < 2)
-                       pads[port].Vib[dev] = value;
-       }
-       if (pos == respSize - 1)
-               ds_update_vibrate(port);
-}
-
-static unsigned char PADpoll_(int port, unsigned char value, int pos, int *more_data) {
-       if (pos == 0 && value != 0x42 && in_type[port] != PSE_PAD_TYPE_ANALOGPAD)
-               respSize = 1;
-
-       switch (in_type[port]) {
-               case PSE_PAD_TYPE_ANALOGPAD:
-                       PADpoll_dualshock(port, value, pos);
-                       break;
-               case PSE_PAD_TYPE_GUN:
-                       if (pos == 2)
-                               pl_gun_byte2(port, value);
-                       break;
-       }
-
-       *more_data = pos < respSize - 1;
-       if (pos >= respSize)
-               return 0xff; // no response/HiZ
-
-       log_pad(port, pos);
-       return buf[pos];
-}
-
-// response: 0x80, 0x5A, 8 bytes each for ports A, B, C, D
-static unsigned char PADpollMultitap(int port, unsigned char value, int pos, int *more_data) {
-       unsigned int devByte, dev;
-       int unused = 0;
-
-       if (pos == 0) {
-               *more_data = (value == 0x42);
-               return 0x80;
-       }
-       *more_data = pos < 34 - 1;
-       if (pos == 1)
-               return 0x5a;
-       if (pos >= 34)
-               return 0xff;
-
-       devByte = pos - 2;
-       dev = devByte / 8;
-       if (devByte % 8 == 0)
-               PADstartPoll_(&pads[port + dev]);
-       return PADpoll_(port + dev, value, devByte % 8, &unused);
-}
-
-static unsigned char PADpollMain(int port, unsigned char value, int *more_data) {
-       unsigned char ret;
-       int pos = reqPos++;
-
-       if (pos < sizeof(pads[port].txData))
-               pads[port].txData[pos] = value;
-       if (!pads[port].portMultitap || !pads[port].multitapLongModeEnabled)
-               ret = PADpoll_(port, value, pos, more_data);
-       else
-               ret = PADpollMultitap(port, value, pos, more_data);
-       return ret;
-
-}
-
-// refresh the button state on port 1.
-// int pad is not needed.
-unsigned char PAD1_startPoll(int unused) {
-       int i;
-
-       reqPos = 0;
-       pads[0].requestPadIndex = 0;
-       PAD1_readPort(&pads[0]);
-
-       pads[0].multitapLongModeEnabled = 0;
-       if (pads[0].portMultitap)
-               pads[0].multitapLongModeEnabled = pads[0].txData[1] & 1;
-
-       if (!pads[0].portMultitap || !pads[0].multitapLongModeEnabled) {
-               PADstartPoll_(&pads[0]);
-       } else {
-               // a multitap is plugged and enabled: refresh pads 1-3
-               for (i = 1; i < 4; i++) {
-                       pads[i].requestPadIndex = i;
-                       PAD1_readPort(&pads[i]);
-               }
-       }
-       return 0xff;
-}
-
-unsigned char PAD1_poll(unsigned char value, int *more_data) {
-       return PADpollMain(0, value, more_data);
-}
-
-
-unsigned char PAD2_startPoll(int pad) {
-       int pad_index = pads[0].portMultitap ? 4 : 1;
-       int i;
-
-       reqPos = 0;
-       pads[pad_index].requestPadIndex = pad_index;
-       PAD2_readPort(&pads[pad_index]);
-
-       pads[pad_index].multitapLongModeEnabled = 0;
-       if (pads[pad_index].portMultitap)
-               pads[pad_index].multitapLongModeEnabled = pads[pad_index].txData[1] & 1;
-
-       if (!pads[pad_index].portMultitap || !pads[pad_index].multitapLongModeEnabled) {
-               PADstartPoll_(&pads[pad_index]);
-       } else {
-               for (i = 1; i < 4; i++) {
-                       pads[pad_index + i].requestPadIndex = pad_index + i;
-                       PAD2_readPort(&pads[pad_index + i]);
-               }
-       }
-       return 0xff;
-}
-
-unsigned char PAD2_poll(unsigned char value, int *more_data) {
-       return PADpollMain(pads[0].portMultitap ? 4 : 1, value, more_data);
-}
-
-static void PAD_init(void) {
-       size_t p;
-
-       memset(pads, 0, sizeof(pads));
-       for (p = 0; p < sizeof(pads) / sizeof(pads[0]); p++) {
-               memset(pads[p].ds.cmd4dConfig, 0xff, sizeof(pads[p].ds.cmd4dConfig));
-       }
-}
-
-int padFreeze(void *f, int Mode) {
-       size_t i;
-
-       for (i = 0; i < sizeof(pads) / sizeof(pads[0]); i++) {
-               pads[i].saveSize = sizeof(pads[i]);
-               gzfreeze(&pads[i], sizeof(pads[i]));
-               if (Mode == 0 && pads[i].saveSize != sizeof(pads[i]))
-                       SaveFuncs.seek(f, pads[i].saveSize - sizeof(pads[i]), SEEK_CUR);
-       }
-
-       return 0;
-}
-
-int padToggleAnalog(unsigned int index)
-{
-       int r = -1;
-
-       if (index < sizeof(pads) / sizeof(pads[0])) {
-               r = (pads[index].ds.padMode ^= 1);
-               pads[index].ds.userToggled = 1;
-       }
-       return r;
-}
-
 #ifdef ENABLE_SIO1API
 
 void *hSIO1Driver = NULL;
@@ -909,7 +329,6 @@ int LoadPlugins() {
        if (ret < 0) { SysMessage (_("Error initializing GPU plugin: %d"), ret); return -1; }
        ret = SPU_init();
        if (ret < 0) { SysMessage (_("Error initializing SPU plugin: %d"), ret); return -1; }
-       PAD_init();
 
 #ifdef ENABLE_SIO1API
        ret = SIO1_init();
index 334899d..f8a3197 100644 (file)
@@ -132,6 +132,10 @@ long PAD2_readPort(PadDataS *);
 unsigned char PAD2_startPoll(int);\r
 unsigned char PAD2_poll(unsigned char, int *);\r
 \r
+int padFreeze(void *f, int Mode);\r
+int padToggleAnalog(unsigned int index);\r
+void padReset(void);\r
+\r
 #ifdef ENABLE_SIO1API\r
 \r
 // SIO1 Functions (link cable)\r
@@ -210,9 +214,6 @@ const char *GetIsoFile(void);
 boolean UsingIso(void);\r
 void SetCdOpenCaseTime(s64 time);\r
 \r
-int padFreeze(void *f, int Mode);\r
-int padToggleAnalog(unsigned int index);\r
-\r
 extern void pl_gun_byte2(int port, unsigned char byte);\r
 extern void plat_trigger_vibrate(int pad, int low, int high);\r
 \r
index a25c01d..de50bc0 100644 (file)
@@ -84,6 +84,7 @@ void psxReset() {
        psxCpu->ApplyConfig();
        psxCpu->Reset();
 
+       padReset();
        psxHwReset();
        psxBiosInit();