mirror of https://github.com/PCSX2/pcsx2.git
onepad 1.3: import lilypad state machine into onepad
Not tested * rumble Save/load state will be implemented in the next commit v2: * Print current deteced pad mode * fix dpad button tranmission close #366
This commit is contained in:
parent
20aee23edc
commit
62aff1f2a1
|
@ -38,7 +38,7 @@ set(onepadGuiResources
|
||||||
)
|
)
|
||||||
|
|
||||||
# plugin name
|
# plugin name
|
||||||
set(Output onepad-1.2.0)
|
set(Output onepad-1.3.0)
|
||||||
set(onepadFinalFlags "")
|
set(onepadFinalFlags "")
|
||||||
|
|
||||||
# onepad sources
|
# onepad sources
|
||||||
|
@ -48,7 +48,8 @@ set(onepadSources
|
||||||
SDL/joystick.cpp
|
SDL/joystick.cpp
|
||||||
keyboard.cpp
|
keyboard.cpp
|
||||||
KeyStatus.cpp
|
KeyStatus.cpp
|
||||||
onepad.cpp)
|
onepad.cpp
|
||||||
|
state_management.cpp)
|
||||||
|
|
||||||
# onepad headers
|
# onepad headers
|
||||||
set(onepadHeaders
|
set(onepadHeaders
|
||||||
|
@ -58,7 +59,8 @@ set(onepadHeaders
|
||||||
SDL/joystick.h
|
SDL/joystick.h
|
||||||
keyboard.h
|
keyboard.h
|
||||||
KeyStatus.h
|
KeyStatus.h
|
||||||
onepad.h)
|
onepad.h
|
||||||
|
state_management.h)
|
||||||
|
|
||||||
# onepad Linux sources
|
# onepad Linux sources
|
||||||
set(onepadLinuxSources
|
set(onepadLinuxSources
|
||||||
|
@ -85,14 +87,10 @@ set(onepadWindowsHeaders
|
||||||
)
|
)
|
||||||
|
|
||||||
if (SDL2_API)
|
if (SDL2_API)
|
||||||
set(onepadFinalLibs
|
set(onepadFinalLibs ${SDL2_LIBRARIES})
|
||||||
${SDL2_LIBRARIES}
|
|
||||||
)
|
|
||||||
add_definitions(-DSDL_BUILD)
|
add_definitions(-DSDL_BUILD)
|
||||||
else()
|
else()
|
||||||
set(onepadFinalLibs
|
set(onepadFinalLibs ${SDL_LIBRARY})
|
||||||
${SDL_LIBRARY}
|
|
||||||
)
|
|
||||||
add_definitions(-DSDL_BUILD)
|
add_definitions(-DSDL_BUILD)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "GamePad.h"
|
#include "GamePad.h"
|
||||||
#include "onepad.h"
|
#include "onepad.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
|
#include "state_management.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
@ -188,6 +189,8 @@ EXPORT_C_(void) PADupdate(int pad)
|
||||||
|
|
||||||
key_status->commit_status(cpad);
|
key_status->commit_status(cpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pad::rumble_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_C_(void) PADconfigure()
|
EXPORT_C_(void) PADconfigure()
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "onepad.h"
|
#include "onepad.h"
|
||||||
#include "svnrev.h"
|
#include "svnrev.h"
|
||||||
|
#include "state_management.h"
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -47,79 +48,8 @@ bool toggleAutoRepeat = false;
|
||||||
|
|
||||||
const u32 version = PS2E_PAD_VERSION;
|
const u32 version = PS2E_PAD_VERSION;
|
||||||
const u32 revision = 1;
|
const u32 revision = 1;
|
||||||
const u32 build = 2; // increase that with each version
|
const u32 build = 3; // increase that with each version
|
||||||
|
|
||||||
// Useless variable ...
|
|
||||||
//int PadEnum[2][2] = {{0, 2}, {1, 3}};
|
|
||||||
|
|
||||||
u8 stdpar[2][20] = {
|
|
||||||
{0xff, 0x5a, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00},
|
|
||||||
{0xff, 0x5a, 0xff, 0xff, 0x80, 0x80, 0x80, 0x80,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00}
|
|
||||||
};
|
|
||||||
u8 cmd40[2][8] = {
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5a},
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5a}
|
|
||||||
};
|
|
||||||
u8 cmd41[2][8] = {
|
|
||||||
{0xff, 0x5a, 0xff, 0xff, 0x03, 0x00, 0x00, 0x5a},
|
|
||||||
{0xff, 0x5a, 0xff, 0xff, 0x03, 0x00, 0x00, 0x5a}
|
|
||||||
};
|
|
||||||
u8 unk46[2][8] = {
|
|
||||||
{0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A},
|
|
||||||
{0xFF, 0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A}
|
|
||||||
};
|
|
||||||
u8 unk47[2][8] = {
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00},
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}
|
|
||||||
};
|
|
||||||
u8 unk4c[2][8] = {
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
||||||
};
|
|
||||||
u8 unk4d[2][8] = {
|
|
||||||
{0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
|
||||||
{0xff, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
|
||||||
};
|
|
||||||
u8 cmd4f[2][8] = {
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a},
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a}
|
|
||||||
};
|
|
||||||
u8 stdcfg[2][8] = {
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
||||||
}; // 2 & 3 = 0
|
|
||||||
u8 stdmode[2][8] = {
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
||||||
{0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
||||||
};
|
|
||||||
u8 stdmodel[2][8] = {
|
|
||||||
{0xff,
|
|
||||||
0x5a,
|
|
||||||
0x03, // 03 - dualshock2, 01 - dualshock
|
|
||||||
0x02, // number of modes
|
|
||||||
0x01, // current mode: 01 - analog, 00 - digital
|
|
||||||
0x02,
|
|
||||||
0x01,
|
|
||||||
0x00},
|
|
||||||
{0xff,
|
|
||||||
0x5a,
|
|
||||||
0x03, // 03 - dualshock2, 01 - dualshock
|
|
||||||
0x02, // number of modes
|
|
||||||
0x01, // current mode: 01 - analog, 00 - digital
|
|
||||||
0x02,
|
|
||||||
0x01,
|
|
||||||
0x00}
|
|
||||||
};
|
|
||||||
|
|
||||||
u8 *buf;
|
|
||||||
int padID[2];
|
|
||||||
int padMode[2];
|
|
||||||
int curPad, curByte, curCmd, cmdLen;
|
|
||||||
int ds2mode = 0; // DS Mode at start
|
|
||||||
FILE *padLog = NULL;
|
FILE *padLog = NULL;
|
||||||
|
|
||||||
pthread_spinlock_t mutex_KeyEvent;
|
pthread_spinlock_t mutex_KeyEvent;
|
||||||
|
@ -128,11 +58,6 @@ KeyStatus* key_status = NULL;
|
||||||
|
|
||||||
queue<keyEvent> ev_fifo;
|
queue<keyEvent> ev_fifo;
|
||||||
|
|
||||||
static int padVib0[2];
|
|
||||||
static int padVib1[2];
|
|
||||||
//static int padVibC[2];
|
|
||||||
static int padVibF[2][4];
|
|
||||||
|
|
||||||
static void InitLibraryName()
|
static void InitLibraryName()
|
||||||
{
|
{
|
||||||
#ifdef PUBLIC
|
#ifdef PUBLIC
|
||||||
|
@ -237,19 +162,25 @@ EXPORT_C_(s32) PADinit(u32 flags)
|
||||||
|
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
|
|
||||||
PADsetMode(0, 0);
|
|
||||||
PADsetMode(1, 0);
|
|
||||||
|
|
||||||
key_status = new KeyStatus();
|
key_status = new KeyStatus();
|
||||||
|
|
||||||
|
Pad::reset_all();
|
||||||
|
|
||||||
|
query.reset();
|
||||||
|
|
||||||
|
for (int port = 0; port < 2; port++)
|
||||||
|
slots[port] = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_C_(void) PADshutdown()
|
EXPORT_C_(void) PADshutdown()
|
||||||
{
|
{
|
||||||
CloseLogging();
|
CloseLogging();
|
||||||
|
|
||||||
delete conf;
|
delete conf;
|
||||||
conf = nullptr;
|
conf = nullptr;
|
||||||
|
|
||||||
delete key_status;
|
delete key_status;
|
||||||
key_status = nullptr;
|
key_status = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -298,292 +229,27 @@ EXPORT_C_(u32) PADquery()
|
||||||
return 3; // both
|
return 3; // both
|
||||||
}
|
}
|
||||||
|
|
||||||
void PADsetMode(int pad, int mode)
|
EXPORT_C_(s32) PADsetSlot(u8 port, u8 slot)
|
||||||
{
|
{
|
||||||
padMode[pad] = mode;
|
port--;
|
||||||
padVib0[pad] = 0;
|
slot--;
|
||||||
padVib1[pad] = 0;
|
if (port > 1 || slot > 3) {
|
||||||
padVibF[pad][0] = 0;
|
return 0;
|
||||||
padVibF[pad][1] = 0;
|
|
||||||
switch (ds2mode)
|
|
||||||
{
|
|
||||||
case 0: // dualshock
|
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case 0: // digital
|
|
||||||
padID[pad] = 0x41;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // analog
|
|
||||||
padID[pad] = 0x73;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
// Even if no pad there, record the slot, as it is the active slot regardless.
|
||||||
|
slots[port] = slot;
|
||||||
|
|
||||||
case 1: // dualshock2
|
return 1;
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case 0: // digital
|
|
||||||
padID[pad] = 0x41;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // analog
|
|
||||||
padID[pad] = 0x79;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_C_(u8) PADstartPoll(int pad)
|
EXPORT_C_(u8) PADstartPoll(int pad)
|
||||||
{
|
{
|
||||||
//PAD_LOG("PADstartPoll: %d\n", pad);
|
return pad_start_poll(pad);
|
||||||
|
|
||||||
curPad = pad - 1;
|
|
||||||
curByte = 0;
|
|
||||||
|
|
||||||
return 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 _PADpoll(u8 value)
|
|
||||||
{
|
|
||||||
u8 button_check = 0;
|
|
||||||
int vib_small;
|
|
||||||
int vib_big;
|
|
||||||
|
|
||||||
if (curByte == 0)
|
|
||||||
{
|
|
||||||
curByte++;
|
|
||||||
|
|
||||||
//PAD_LOG("PADpoll: cmd: %x\n", value);
|
|
||||||
|
|
||||||
curCmd = value;
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case CMD_SET_VREF_PARAM: // DUALSHOCK2 ENABLER
|
|
||||||
cmdLen = 8;
|
|
||||||
buf = cmd40[curPad];
|
|
||||||
return 0xf3;
|
|
||||||
|
|
||||||
case CMD_QUERY_DS2_ANALOG_MODE: // QUERY_DS2_ANALOG_MODE
|
|
||||||
cmdLen = 8;
|
|
||||||
buf = cmd41[curPad];
|
|
||||||
return 0xf3;
|
|
||||||
|
|
||||||
case CMD_READ_DATA_AND_VIBRATE: // READ_DATA
|
|
||||||
|
|
||||||
stdpar[curPad][2] = key_status->get(curPad) >> 8;
|
|
||||||
stdpar[curPad][3] = key_status->get(curPad) & 0xff;
|
|
||||||
stdpar[curPad][4] = key_status->get(curPad, PAD_R_RIGHT);
|
|
||||||
stdpar[curPad][5] = key_status->get(curPad, PAD_R_UP);
|
|
||||||
stdpar[curPad][6] = key_status->get(curPad, PAD_L_RIGHT);
|
|
||||||
stdpar[curPad][7] = key_status->get(curPad, PAD_L_UP);
|
|
||||||
|
|
||||||
if (padMode[curPad] == 1)
|
|
||||||
cmdLen = 20;
|
|
||||||
else
|
|
||||||
cmdLen = 4;
|
|
||||||
|
|
||||||
// Square
|
|
||||||
stdpar[curPad][15] = !test_bit(stdpar[curPad][3], 7) ? key_status->get(curPad, PAD_SQUARE) : 0;
|
|
||||||
// X
|
|
||||||
stdpar[curPad][14] = !test_bit(stdpar[curPad][3], 6) ? key_status->get(curPad, PAD_CROSS) : 0;
|
|
||||||
// Circle
|
|
||||||
stdpar[curPad][13] = !test_bit(stdpar[curPad][3], 5) ? key_status->get(curPad, PAD_CIRCLE) : 0;
|
|
||||||
// Triangle
|
|
||||||
stdpar[curPad][12] = !test_bit(stdpar[curPad][3], 4) ? key_status->get(curPad, PAD_TRIANGLE) : 0;
|
|
||||||
// R1
|
|
||||||
stdpar[curPad][17] = !test_bit(stdpar[curPad][3], 3) ? key_status->get(curPad, PAD_R1) : 0;
|
|
||||||
// L1
|
|
||||||
stdpar[curPad][16] = !test_bit(stdpar[curPad][3], 2) ? key_status->get(curPad, PAD_L1) : 0;
|
|
||||||
// R2
|
|
||||||
stdpar[curPad][19] = !test_bit(stdpar[curPad][3], 1) ? key_status->get(curPad, PAD_R2) : 0;
|
|
||||||
// L2
|
|
||||||
stdpar[curPad][18] = !test_bit(stdpar[curPad][3], 0) ? key_status->get(curPad, PAD_L2) : 0;
|
|
||||||
|
|
||||||
button_check = stdpar[curPad][2] >> 4;
|
|
||||||
// LEFT
|
|
||||||
stdpar[curPad][9] = !test_bit(button_check, 3) ? key_status->get(curPad, PAD_LEFT) : 0;
|
|
||||||
// DOWN
|
|
||||||
stdpar[curPad][11] = !test_bit(button_check, 2) ? key_status->get(curPad, PAD_DOWN) : 0;
|
|
||||||
// RIGHT
|
|
||||||
stdpar[curPad][8] = !test_bit(button_check, 1) ? key_status->get(curPad, PAD_RIGHT) : 0;
|
|
||||||
// UP
|
|
||||||
stdpar[curPad][10] = !test_bit(button_check, 0) ? key_status->get(curPad, PAD_UP) : 0;
|
|
||||||
|
|
||||||
buf = stdpar[curPad];
|
|
||||||
|
|
||||||
/* Small Motor */
|
|
||||||
vib_small = padVibF[curPad][0] ? 2000 : 0;
|
|
||||||
// if ((padVibF[curPad][2] != vib_small) && (padVibC[curPad] >= 0))
|
|
||||||
if (padVibF[curPad][2] != vib_small)
|
|
||||||
{
|
|
||||||
padVibF[curPad][2] = vib_small;
|
|
||||||
GamePad::DoRumble(0, curPad);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Big Motor */
|
|
||||||
vib_big = padVibF[curPad][1] ? 500 + 37*padVibF[curPad][1] : 0;
|
|
||||||
// if ((padVibF[curPad][3] != vib_big) && (padVibC[curPad] >= 0))
|
|
||||||
if (padVibF[curPad][3] != vib_big)
|
|
||||||
{
|
|
||||||
padVibF[curPad][3] = vib_big;
|
|
||||||
GamePad::DoRumble(1, curPad);
|
|
||||||
}
|
|
||||||
|
|
||||||
return padID[curPad];
|
|
||||||
|
|
||||||
case CMD_CONFIG_MODE: // CONFIG_MODE
|
|
||||||
cmdLen = 8;
|
|
||||||
buf = stdcfg[curPad];
|
|
||||||
if (stdcfg[curPad][3] == 0xff)
|
|
||||||
return 0xf3;
|
|
||||||
else
|
|
||||||
return padID[curPad];
|
|
||||||
|
|
||||||
case CMD_SET_MODE_AND_LOCK: // SET_MODE_AND_LOCK
|
|
||||||
cmdLen = 8;
|
|
||||||
buf = stdmode[curPad];
|
|
||||||
return 0xf3;
|
|
||||||
|
|
||||||
case CMD_QUERY_MODEL_AND_MODE: // QUERY_MODEL_AND_MODE
|
|
||||||
cmdLen = 8;
|
|
||||||
buf = stdmodel[curPad];
|
|
||||||
buf[4] = padMode[curPad];
|
|
||||||
return 0xf3;
|
|
||||||
|
|
||||||
case CMD_QUERY_ACT: // ??
|
|
||||||
cmdLen = 8;
|
|
||||||
buf = unk46[curPad];
|
|
||||||
return 0xf3;
|
|
||||||
|
|
||||||
case CMD_QUERY_COMB: // ??
|
|
||||||
cmdLen = 8;
|
|
||||||
buf = unk47[curPad];
|
|
||||||
return 0xf3;
|
|
||||||
|
|
||||||
case CMD_QUERY_MODE: // QUERY_MODE ??
|
|
||||||
cmdLen = 8;
|
|
||||||
buf = unk4c[curPad];
|
|
||||||
return 0xf3;
|
|
||||||
|
|
||||||
case CMD_VIBRATION_TOGGLE:
|
|
||||||
cmdLen = 8;
|
|
||||||
buf = unk4d[curPad];
|
|
||||||
return 0xf3;
|
|
||||||
|
|
||||||
case CMD_SET_DS2_NATIVE_MODE: // SET_DS2_NATIVE_MODE
|
|
||||||
cmdLen = 8;
|
|
||||||
padID[curPad] = 0x79; // setting ds2 mode
|
|
||||||
ds2mode = 1; // Set DS2 Mode
|
|
||||||
buf = cmd4f[curPad];
|
|
||||||
return 0xf3;
|
|
||||||
|
|
||||||
default:
|
|
||||||
PAD_LOG("*PADpoll*: unknown cmd %x\n", value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (curCmd)
|
|
||||||
{
|
|
||||||
case CMD_READ_DATA_AND_VIBRATE:
|
|
||||||
|
|
||||||
if (curByte == padVib0[curPad])
|
|
||||||
padVibF[curPad][0] = value&1;
|
|
||||||
if (curByte == padVib1[curPad])
|
|
||||||
padVibF[curPad][1] = value;
|
|
||||||
break;
|
|
||||||
case CMD_CONFIG_MODE:
|
|
||||||
if (curByte == 2)
|
|
||||||
{
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
buf[2] = 0;
|
|
||||||
buf[3] = 0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
buf[2] = 0xff;
|
|
||||||
buf[3] = 0xff;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_SET_MODE_AND_LOCK:
|
|
||||||
if (curByte == 2)
|
|
||||||
{
|
|
||||||
PADsetMode(curPad, value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_QUERY_ACT:
|
|
||||||
if (curByte == 2)
|
|
||||||
{
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case 0: // default
|
|
||||||
buf[5] = 0x2;
|
|
||||||
buf[6] = 0x0;
|
|
||||||
buf[7] = 0xA;
|
|
||||||
break;
|
|
||||||
case 1: // Param std conf change
|
|
||||||
buf[5] = 0x1;
|
|
||||||
buf[6] = 0x1;
|
|
||||||
buf[7] = 0x14;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_QUERY_MODE:
|
|
||||||
if (curByte == 2)
|
|
||||||
{
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case 0: // mode 0 - digital mode
|
|
||||||
buf[5] = 0x4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // mode 1 - analog mode
|
|
||||||
buf[5] = 0x7;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CMD_VIBRATION_TOGGLE:
|
|
||||||
|
|
||||||
if (curByte >= 2)
|
|
||||||
{
|
|
||||||
if (curByte == padVib0[curPad])
|
|
||||||
buf[curByte] = 0x00;
|
|
||||||
if (curByte == padVib1[curPad])
|
|
||||||
buf[curByte] = 0x01;
|
|
||||||
if (value == 0x00)
|
|
||||||
{
|
|
||||||
padVib0[curPad] = curByte;
|
|
||||||
}
|
|
||||||
else if (value == 0x01)
|
|
||||||
{
|
|
||||||
padVib1[curPad] = curByte;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curByte >= cmdLen) return 0;
|
|
||||||
return buf[curByte++];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_C_(u8) PADpoll(u8 value)
|
EXPORT_C_(u8) PADpoll(u8 value)
|
||||||
{
|
{
|
||||||
u8 ret;
|
return pad_poll(value);
|
||||||
|
|
||||||
ret = _PADpoll(value);
|
|
||||||
//PAD_LOG("PADpoll: %x (%d: %x)\n", value, curByte, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PADkeyEvent is called every vsync (return NULL if no event)
|
// PADkeyEvent is called every vsync (return NULL if no event)
|
||||||
|
|
|
@ -0,0 +1,465 @@
|
||||||
|
/* OnePAD
|
||||||
|
* Copyright (C) 2016
|
||||||
|
*
|
||||||
|
* Based on LilyPad
|
||||||
|
* Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "state_management.h"
|
||||||
|
|
||||||
|
// Typical packet response on the bus
|
||||||
|
static const u8 ConfigExit[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
static const u8 noclue[7] = {0x5A, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5A};
|
||||||
|
static const u8 setMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
static const u8 queryModelDS2[7] = {0x5A, 0x03, 0x02, 0x00, 0x02, 0x01, 0x00};
|
||||||
|
static const u8 queryModelDS1[7] = {0x5A, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00};
|
||||||
|
static const u8 queryComb[7] = {0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00};
|
||||||
|
static const u8 queryMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
static const u8 setNativeMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A};
|
||||||
|
|
||||||
|
static u8 queryMaskMode[7] = {0x5A, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x5A};
|
||||||
|
|
||||||
|
static const u8 queryAct[2][7] = {
|
||||||
|
{0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0A},
|
||||||
|
{0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x14}};
|
||||||
|
|
||||||
|
QueryInfo query;
|
||||||
|
Pad pads[2][4];
|
||||||
|
int slots[2] = {0, 0};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// QueryInfo implementation
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void QueryInfo::reset()
|
||||||
|
{
|
||||||
|
port = 0;
|
||||||
|
slot = 0;
|
||||||
|
lastByte = 1;
|
||||||
|
currentCommand = 0;
|
||||||
|
numBytes = 0;
|
||||||
|
queryDone = 1;
|
||||||
|
memset(response, 0xF3, sizeof(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 QueryInfo::start_poll(int _port)
|
||||||
|
{
|
||||||
|
if (port > 1) {
|
||||||
|
reset();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
queryDone = 0;
|
||||||
|
port = _port;
|
||||||
|
slot = slots[port];
|
||||||
|
numBytes = 2;
|
||||||
|
lastByte = 0;
|
||||||
|
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Pad implementation
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Pad::set_mode(int _mode)
|
||||||
|
{
|
||||||
|
mode = _mode;
|
||||||
|
|
||||||
|
fprintf(stdout, "OnePad: set new pad mode=");
|
||||||
|
if (mode == MODE_DIGITAL)
|
||||||
|
fprintf(stdout, "DIGITAL\n");
|
||||||
|
else if (mode == MODE_ANALOG)
|
||||||
|
fprintf(stdout, "ANALOG\n");
|
||||||
|
else if (mode == MODE_DS2_NATIVE)
|
||||||
|
fprintf(stdout, "DS2 NATIVE\n");
|
||||||
|
else
|
||||||
|
fprintf(stdout, "??? 0x%x\n", mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pad::set_vibrate(int motor, u8 val)
|
||||||
|
{
|
||||||
|
nextVibrate[motor] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pad::reset_vibrate()
|
||||||
|
{
|
||||||
|
set_vibrate(0, 0);
|
||||||
|
set_vibrate(1, 0);
|
||||||
|
memset(vibrate, 0xFF, sizeof(vibrate));
|
||||||
|
vibrate[0] = 0x5A;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pad::reset()
|
||||||
|
{
|
||||||
|
memset(this, 0, sizeof(PadFreezeData));
|
||||||
|
|
||||||
|
set_mode(MODE_DIGITAL);
|
||||||
|
umask[0] = umask[1] = 0xFF;
|
||||||
|
|
||||||
|
// Sets up vibrate variable.
|
||||||
|
reset_vibrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pad::rumble(int port)
|
||||||
|
{
|
||||||
|
for (int motor=0; motor<2; motor++) {
|
||||||
|
// TODO: Probably be better to send all of these at once.
|
||||||
|
if (nextVibrate[motor] | currentVibrate[motor]) {
|
||||||
|
currentVibrate[motor] = nextVibrate[motor];
|
||||||
|
|
||||||
|
GamePad::DoRumble(motor, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pad::stop_vibrate_all()
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
for (int i=0; i<8; i++) {
|
||||||
|
SetVibrate(i&1, i>>1, 0, 0);
|
||||||
|
SetVibrate(i&1, i>>1, 1, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// FIXME equivalent ?
|
||||||
|
for (int port = 0; port < 2; port++)
|
||||||
|
for (int slot = 0; slot < 4; slot++)
|
||||||
|
pads[port][slot].reset_vibrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pad::reset_all()
|
||||||
|
{
|
||||||
|
for (int port = 0; port < 2; port++)
|
||||||
|
for (int slot = 0; slot < 4; slot++)
|
||||||
|
pads[port][slot].reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pad::rumble_all()
|
||||||
|
{
|
||||||
|
for (int port=0; port<2; port++)
|
||||||
|
for (int slot=0; slot<4; slot++)
|
||||||
|
pads[port][slot].rumble(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Pad implementation
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool IsDualshock2() {
|
||||||
|
// FIXME
|
||||||
|
#if 0
|
||||||
|
return config.padConfigs[query.port][query.slot].type == Dualshock2Pad ||
|
||||||
|
(config.padConfigs[query.port][query.slot].type == GuitarPad && config.GH2);
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 pad_start_poll(u8 pad)
|
||||||
|
{
|
||||||
|
return query.start_poll(pad - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 pad_poll(u8 value)
|
||||||
|
{
|
||||||
|
if (query.lastByte+1 >= query.numBytes) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (query.lastByte && query.queryDone) {
|
||||||
|
return query.response[++query.lastByte];
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
Pad *pad = &pads[query.port][query.slot];
|
||||||
|
|
||||||
|
if (query.lastByte == 0) {
|
||||||
|
query.lastByte++;
|
||||||
|
query.currentCommand = value;
|
||||||
|
|
||||||
|
switch(value) {
|
||||||
|
case CMD_CONFIG_MODE:
|
||||||
|
if (pad->config) {
|
||||||
|
// In config mode. Might not actually be leaving it.
|
||||||
|
query.set_result(ConfigExit);
|
||||||
|
return 0xF3;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CMD_READ_DATA_AND_VIBRATE:
|
||||||
|
{
|
||||||
|
query.response[2] = 0x5A;
|
||||||
|
#if 0
|
||||||
|
Update(query.port, query.slot);
|
||||||
|
ButtonSum *sum = &pad->sum;
|
||||||
|
|
||||||
|
u8 b1 = 0xFF, b2 = 0xFF;
|
||||||
|
for (i = 0; i<4; i++) {
|
||||||
|
b1 -= (sum->buttons[i] > 0) << i;
|
||||||
|
}
|
||||||
|
for (i = 0; i<8; i++) {
|
||||||
|
b2 -= (sum->buttons[i+4] > 0) << i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
#if 0
|
||||||
|
if (config.padConfigs[query.port][query.slot].type == GuitarPad && !config.GH2) {
|
||||||
|
sum->buttons[15] = 255;
|
||||||
|
// Not sure about this. Forces wammy to be from 0 to 0x7F.
|
||||||
|
// if (sum->sticks[2].vert > 0) sum->sticks[2].vert = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (i = 4; i<8; i++) {
|
||||||
|
b1 -= (sum->buttons[i+8] > 0) << i;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
#if 0
|
||||||
|
//Left, Right and Down are always pressed on Pop'n Music controller.
|
||||||
|
if (config.padConfigs[query.port][query.slot].type == PopnPad)
|
||||||
|
b1=b1 & 0x1f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t buttons = key_status->get(query.port);
|
||||||
|
|
||||||
|
query.numBytes = 5;
|
||||||
|
|
||||||
|
query.response[3] = (buttons >> 8) & 0xFF;
|
||||||
|
query.response[4] = (buttons >> 0) & 0xFF;
|
||||||
|
|
||||||
|
if (pad->mode != MODE_DIGITAL) { // ANALOG || DS2 native
|
||||||
|
query.numBytes = 9;
|
||||||
|
|
||||||
|
query.response[5] = key_status->get(query.port, PAD_R_RIGHT);
|
||||||
|
query.response[6] = key_status->get(query.port, PAD_R_UP);
|
||||||
|
query.response[7] = key_status->get(query.port, PAD_L_RIGHT);
|
||||||
|
query.response[8] = key_status->get(query.port, PAD_L_UP);
|
||||||
|
|
||||||
|
if (pad->mode != MODE_ANALOG) { // DS2 native
|
||||||
|
query.numBytes = 21;
|
||||||
|
|
||||||
|
query.response[9] = !test_bit(buttons, 13) ? key_status->get(query.port, PAD_RIGHT) : 0;
|
||||||
|
query.response[10] = !test_bit(buttons, 15) ? key_status->get(query.port, PAD_LEFT) : 0;
|
||||||
|
query.response[11] = !test_bit(buttons, 12) ? key_status->get(query.port, PAD_UP) : 0;
|
||||||
|
query.response[12] = !test_bit(buttons, 14) ? key_status->get(query.port, PAD_DOWN) : 0;
|
||||||
|
|
||||||
|
query.response[13] = !test_bit(buttons, 4) ? key_status->get(query.port, PAD_TRIANGLE) : 0;
|
||||||
|
query.response[14] = !test_bit(buttons, 5) ? key_status->get(query.port, PAD_CIRCLE) : 0;
|
||||||
|
query.response[15] = !test_bit(buttons, 6) ? key_status->get(query.port, PAD_CROSS) : 0;
|
||||||
|
query.response[16] = !test_bit(buttons, 7) ? key_status->get(query.port, PAD_SQUARE) : 0;
|
||||||
|
query.response[17] = !test_bit(buttons, 2) ? key_status->get(query.port, PAD_L1) : 0;
|
||||||
|
query.response[18] = !test_bit(buttons, 3) ? key_status->get(query.port, PAD_R1) : 0;
|
||||||
|
query.response[19] = !test_bit(buttons, 0) ? key_status->get(query.port, PAD_L2) : 0;
|
||||||
|
query.response[20] = !test_bit(buttons, 1) ? key_status->get(query.port, PAD_R2) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
query.response[3] = b1;
|
||||||
|
query.response[4] = b2;
|
||||||
|
|
||||||
|
query.numBytes = 5;
|
||||||
|
if (pad->mode != MODE_DIGITAL) {
|
||||||
|
query.response[5] = Cap((sum->sticks[0].horiz+255)/2);
|
||||||
|
query.response[6] = Cap((sum->sticks[0].vert+255)/2);
|
||||||
|
query.response[7] = Cap((sum->sticks[1].horiz+255)/2);
|
||||||
|
query.response[8] = Cap((sum->sticks[1].vert+255)/2);
|
||||||
|
|
||||||
|
query.numBytes = 9;
|
||||||
|
if (pad->mode != MODE_ANALOG) {
|
||||||
|
// Good idea? No clue.
|
||||||
|
//query.response[3] &= pad->mask[0];
|
||||||
|
//query.response[4] &= pad->mask[1];
|
||||||
|
|
||||||
|
// No need to cap these, already done int CapSum().
|
||||||
|
query.response[9] = (unsigned char)sum->buttons[13]; //D-pad right
|
||||||
|
query.response[10] = (unsigned char)sum->buttons[15]; //D-pad left
|
||||||
|
query.response[11] = (unsigned char)sum->buttons[12]; //D-pad up
|
||||||
|
query.response[12] = (unsigned char)sum->buttons[14]; //D-pad down
|
||||||
|
|
||||||
|
query.response[13] = (unsigned char) sum->buttons[8];
|
||||||
|
query.response[14] = (unsigned char) sum->buttons[9];
|
||||||
|
query.response[15] = (unsigned char) sum->buttons[10];
|
||||||
|
query.response[16] = (unsigned char) sum->buttons[11];
|
||||||
|
query.response[17] = (unsigned char) sum->buttons[6];
|
||||||
|
query.response[18] = (unsigned char) sum->buttons[7];
|
||||||
|
query.response[19] = (unsigned char) sum->buttons[4];
|
||||||
|
query.response[20] = (unsigned char) sum->buttons[5];
|
||||||
|
query.numBytes = 21;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
query.lastByte=1;
|
||||||
|
return pad->mode;
|
||||||
|
|
||||||
|
case CMD_SET_VREF_PARAM:
|
||||||
|
query.set_final_result(noclue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_QUERY_DS2_ANALOG_MODE:
|
||||||
|
// Right? Wrong? No clue.
|
||||||
|
if (pad->mode == MODE_DIGITAL) {
|
||||||
|
queryMaskMode[1] = queryMaskMode[2] = queryMaskMode[3] = 0;
|
||||||
|
queryMaskMode[6] = 0x00;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
queryMaskMode[1] = pad->umask[0];
|
||||||
|
queryMaskMode[2] = pad->umask[1];
|
||||||
|
queryMaskMode[3] = 0x03;
|
||||||
|
// Not entirely sure about this.
|
||||||
|
//queryMaskMode[3] = 0x01 | (pad->mode == MODE_DS2_NATIVE)*2;
|
||||||
|
queryMaskMode[6] = 0x5A;
|
||||||
|
}
|
||||||
|
query.set_final_result(queryMaskMode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_SET_MODE_AND_LOCK:
|
||||||
|
query.set_result(setMode);
|
||||||
|
pad->reset_vibrate();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_QUERY_MODEL_AND_MODE:
|
||||||
|
if (IsDualshock2()) {
|
||||||
|
query.set_final_result(queryModelDS2);
|
||||||
|
} else {
|
||||||
|
query.set_final_result(queryModelDS1);
|
||||||
|
}
|
||||||
|
// Not digital mode.
|
||||||
|
query.response[5] = (pad->mode & 0xF) != 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_QUERY_ACT:
|
||||||
|
query.set_result(queryAct[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_QUERY_COMB:
|
||||||
|
query.set_final_result(queryComb);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_QUERY_MODE:
|
||||||
|
query.set_result(queryMode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_VIBRATION_TOGGLE:
|
||||||
|
memcpy(query.response+2, pad->vibrate, 7);
|
||||||
|
query.numBytes = 9;
|
||||||
|
//query.set_result(pad->vibrate); // warning copy 7b not 8 (but it is really important?)
|
||||||
|
pad->reset_vibrate();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_SET_DS2_NATIVE_MODE:
|
||||||
|
if (IsDualshock2()) {
|
||||||
|
query.set_result(setNativeMode);
|
||||||
|
} else {
|
||||||
|
query.set_final_result(setNativeMode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
query.numBytes = 0;
|
||||||
|
query.queryDone = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0xF3;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
query.lastByte++;
|
||||||
|
|
||||||
|
switch (query.currentCommand) {
|
||||||
|
case CMD_READ_DATA_AND_VIBRATE:
|
||||||
|
if (query.lastByte == pad->vibrateI[0])
|
||||||
|
pad->set_vibrate(1, 255*(value&1));
|
||||||
|
else if (query.lastByte == pad->vibrateI[1])
|
||||||
|
pad->set_vibrate(0, value);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_CONFIG_MODE:
|
||||||
|
if (query.lastByte == 3) {
|
||||||
|
query.queryDone = 1;
|
||||||
|
pad->config = value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_SET_MODE_AND_LOCK:
|
||||||
|
if (query.lastByte == 3 && value < 2) {
|
||||||
|
pad->set_mode(value ? MODE_ANALOG : MODE_DIGITAL);
|
||||||
|
} else if (query.lastByte == 4) {
|
||||||
|
if (value == 3)
|
||||||
|
pad->modeLock = 3;
|
||||||
|
else
|
||||||
|
pad->modeLock = 0;
|
||||||
|
|
||||||
|
query.queryDone = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_QUERY_ACT:
|
||||||
|
if (query.lastByte == 3) {
|
||||||
|
if (value<2) query.set_result(queryAct[value]);
|
||||||
|
// bunch of 0's
|
||||||
|
// else query.set_result(setMode);
|
||||||
|
query.queryDone = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_QUERY_MODE:
|
||||||
|
if (query.lastByte == 3 && value<2) {
|
||||||
|
query.response[6] = 4+value*3;
|
||||||
|
query.queryDone = 1;
|
||||||
|
}
|
||||||
|
// bunch of 0's
|
||||||
|
//else data = setMode;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_VIBRATION_TOGGLE:
|
||||||
|
if (query.lastByte>=3) {
|
||||||
|
if (value == 0) {
|
||||||
|
pad->vibrateI[0] = (u8)query.lastByte;
|
||||||
|
}
|
||||||
|
else if (value == 1) {
|
||||||
|
pad->vibrateI[1] = (u8)query.lastByte;
|
||||||
|
}
|
||||||
|
pad->vibrate[query.lastByte-2] = value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_SET_DS2_NATIVE_MODE:
|
||||||
|
if (query.lastByte == 3 || query.lastByte == 4) {
|
||||||
|
pad->umask[query.lastByte-3] = value;
|
||||||
|
} else if (query.lastByte == 5) {
|
||||||
|
if (!(value & 1))
|
||||||
|
pad->set_mode(MODE_DIGITAL);
|
||||||
|
else if (!(value & 2))
|
||||||
|
pad->set_mode(MODE_ANALOG);
|
||||||
|
else
|
||||||
|
pad->set_mode(MODE_DS2_NATIVE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.response[query.lastByte];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/* OnePAD
|
||||||
|
* Copyright (C) 2016
|
||||||
|
*
|
||||||
|
* Based on LilyPad
|
||||||
|
* Copyright (C) 2002-2014 PCSX2 Dev Team/ChickenLiver
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "onepad.h"
|
||||||
|
|
||||||
|
#define MODE_DIGITAL 0x41
|
||||||
|
#define MODE_ANALOG 0x73
|
||||||
|
#define MODE_DS2_NATIVE 0x79
|
||||||
|
|
||||||
|
// The state of the PS2 bus
|
||||||
|
struct QueryInfo {
|
||||||
|
u8 port;
|
||||||
|
u8 slot;
|
||||||
|
u8 lastByte;
|
||||||
|
u8 currentCommand;
|
||||||
|
u8 numBytes;
|
||||||
|
u8 queryDone;
|
||||||
|
u8 response[42];
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
u8 start_poll(int port);
|
||||||
|
|
||||||
|
template<size_t S>
|
||||||
|
void set_result(const u8 (&rsp)[S])
|
||||||
|
{
|
||||||
|
memcpy(response+2, rsp, S);
|
||||||
|
numBytes = 2 + S;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t S>
|
||||||
|
void set_final_result(const u8 (&rsp)[S])
|
||||||
|
{
|
||||||
|
set_result(rsp);
|
||||||
|
queryDone = 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Freeze data, for a single pad. Basically has all pad state that
|
||||||
|
// a PS2 can set.
|
||||||
|
struct PadFreezeData {
|
||||||
|
// Digital / Analog / DS2 Native
|
||||||
|
u8 mode;
|
||||||
|
|
||||||
|
u8 modeLock;
|
||||||
|
|
||||||
|
// In config mode
|
||||||
|
u8 config;
|
||||||
|
|
||||||
|
u8 vibrate[8];
|
||||||
|
u8 umask[2];
|
||||||
|
|
||||||
|
// Vibration indices.
|
||||||
|
u8 vibrateI[2];
|
||||||
|
|
||||||
|
// Last vibration value sent to controller.
|
||||||
|
// Only used so as not to call vibration
|
||||||
|
// functions when old and new values are both 0.
|
||||||
|
u8 currentVibrate[2];
|
||||||
|
|
||||||
|
// Next vibrate val to send to controller. If next and current are
|
||||||
|
// both 0, nothing is sent to the controller. Otherwise, it's sent
|
||||||
|
// on every update.
|
||||||
|
u8 nextVibrate[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
class Pad : public PadFreezeData {
|
||||||
|
public:
|
||||||
|
// Lilypad store here the state of PC pad
|
||||||
|
|
||||||
|
void rumble(int port);
|
||||||
|
void set_vibrate(int motor, u8 val);
|
||||||
|
void reset_vibrate();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void set_mode(int mode);
|
||||||
|
|
||||||
|
static void reset_all();
|
||||||
|
static void stop_vibrate_all();
|
||||||
|
static void rumble_all();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Full state to manage save state
|
||||||
|
struct PadPluginFreezeData {
|
||||||
|
char format[8];
|
||||||
|
u32 version;
|
||||||
|
// active slot for port
|
||||||
|
u8 slot[2];
|
||||||
|
PadFreezeData padData[2][4];
|
||||||
|
QueryInfo query;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern QueryInfo query;
|
||||||
|
extern Pad pads[2][4];
|
||||||
|
extern int slots[2];
|
||||||
|
|
||||||
|
extern u8 pad_start_poll(u8 pad);
|
||||||
|
extern u8 pad_poll(u8 value);
|
Loading…
Reference in New Issue