Skip to content

Commit

Permalink
Merge pull request #118 from saulfabregwiivc/main
Browse files Browse the repository at this point in the history
Add PS1 Multitap support, add Memory Card enable/disable options (Jokippo)
  • Loading branch information
xjsxjs197 committed Sep 12, 2023
2 parents 8b408c2 + d624b4c commit 7f3bfbf
Show file tree
Hide file tree
Showing 16 changed files with 672 additions and 121 deletions.
42 changes: 32 additions & 10 deletions Gamecube/GamecubeMain.cpp
Expand Up @@ -125,8 +125,8 @@ char screenMode = 0;
char videoMode = 0;
char fileSortMode = 1;
char padAutoAssign;
char padType[2];
char padAssign[2];
char padType[10];
char padAssign[10];
char rumbleEnabled;
char loadButtonSlot;
char controllerType;
Expand All @@ -141,6 +141,7 @@ char trapFilter = 1;
char interlacedMode = 0;
char deflickerFilter = 1;
char lightGun = 0;
char memCard[2];

#define CONFIG_STRING_TYPE 0
#define CONFIG_STRING_SIZE 256
Expand Down Expand Up @@ -176,10 +177,26 @@ static struct {
{ "SkipFrames", &frameSkip, FRAMESKIP_DISABLE, FRAMESKIP_ENABLE },
{ "Dithering", &useDithering, USEDITHER_NONE, USEDITHER_ALWAYS },
{ "PadAutoAssign", &padAutoAssign, PADAUTOASSIGN_MANUAL, PADAUTOASSIGN_AUTOMATIC },
{ "PadType1", &padType[0], PADTYPE_NONE, PADTYPE_WII },
{ "PadType2", &padType[1], PADTYPE_NONE, PADTYPE_WII },
{ "PadAssign1", &padAssign[0], PADASSIGN_INPUT0, PADASSIGN_INPUT3 },
{ "PadAssign2", &padAssign[1], PADASSIGN_INPUT0, PADASSIGN_INPUT3 },
{ "PadType1", &padType[0], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadType2", &padType[1], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadType3", &padType[2], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadType4", &padType[3], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadType5", &padType[4], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadType6", &padType[5], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadType7", &padType[6], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadType8", &padType[7], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadType9", &padType[8], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadType10", &padType[9], PADTYPE_NONE, PADTYPE_MULTITAP },
{ "PadAssign1", &padAssign[0], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "PadAssign2", &padAssign[1], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "PadAssign3", &padAssign[2], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "PadAssign4", &padAssign[3], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "PadAssign5", &padAssign[4], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "PadAssign6", &padAssign[5], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "PadAssign7", &padAssign[6], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "PadAssign8", &padAssign[7], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "PadAssign9", &padAssign[8], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "PadAssign10", &padAssign[9], PADASSIGN_INPUT0, PADASSIGN_INPUT1D },
{ "RumbleEnabled", &rumbleEnabled, RUMBLE_DISABLE, RUMBLE_ENABLE },
{ "LoadButtonSlot", &loadButtonSlot, LOADBUTTON_SLOT0, LOADBUTTON_DEFAULT },
{ "ControllerType", &controllerType, CONTROLLERTYPE_STANDARD, CONTROLLERTYPE_ANALOG },
Expand All @@ -195,7 +212,9 @@ static struct {
{ "TrapFilter", &trapFilter, TRAPFILTER_DISABLE, TRAPFILTER_ENABLE },
{ "Interlaced", &interlacedMode, INTERLACED_DISABLE, INTERLACED_ENABLE },
{ "DeflickerFilter", &deflickerFilter, DEFLICKER_DISABLE, DEFLICKER_ENABLE },
{ "LightGun", &lightGun, LIGHTGUN_DISABLE, LIGHTGUN_JUST }
{ "LightGun", &lightGun, LIGHTGUN_DISABLE, LIGHTGUN_JUST },
{ "Memcard0", &memCard[0], MEMCARD_DISABLE, MEMCARD_ENABLE },
{ "Memcard1", &memCard[1], MEMCARD_DISABLE, MEMCARD_ENABLE }
};
void handleConfigPair(char* kv);
void readConfig(FILE* f);
Expand Down Expand Up @@ -227,10 +246,13 @@ void loadSettings(int argc, char *argv[])
videoMode = VIDEOMODE_AUTO;
fileSortMode = FILESORT_DIRS_FIRST;
padAutoAssign = PADAUTOASSIGN_AUTOMATIC;
padType[0] = PADTYPE_NONE;
padType[1] = PADTYPE_NONE;
padAssign[0] = PADASSIGN_INPUT0;
for (int i = 0; i < 10; i++){
padType[i] = PADTYPE_NONE;
padAssign[i] = PADASSIGN_INPUT0;
}
padAssign[1] = PADASSIGN_INPUT1;
memCard[0] = MEMCARD_ENABLE;
memCard[1] = MEMCARD_ENABLE;
rumbleEnabled = RUMBLE_ENABLE;
loadButtonSlot = LOADBUTTON_DEFAULT;
controllerType = CONTROLLERTYPE_STANDARD;
Expand Down
130 changes: 98 additions & 32 deletions Gamecube/PadSSSPSX.c
Expand Up @@ -53,23 +53,26 @@ static struct
{
SSSConfig config; //unused?
//int devcnt; //unused
u16 padStat[2]; //Digital Buttons
int padID[2];
int padMode1[2]; //0 = digital, 1 = analog
int padMode2[2];
int padModeE[2]; //Config/Escape mode??
int padModeC[2];
int padModeF[2];
int padVib0[2]; //Command byte for small motor
int padVib1[2]; //Command byte for large motor
int padVibF[2][4]; //Sm motor value; Big motor value; Sm motor running?; Big motor running?
//int padVibC[2]; //unused
u64 padPress[2][16];//unused?
u16 padStat[10]; //Digital Buttons
int padID[10];
int padMode1[10]; //0 = digital, 1 = analog
int padMode2[10];
int padModeE[10]; //Config/Escape mode??
int padModeC[10];
int padModeF[10];
int padVib0[10]; //Command byte for small motor
int padVib1[10]; //Command byte for large motor
int padVibF[10][4]; //Sm motor value; Big motor value; Sm motor running?; Big motor running?
//int padVibC[10]; //unused
u64 padPress[10][16];//unused?
int curPad; //0=pad1; 1=pad2
int curByte; //current command/data byte
int curCmd; //current command from PSX/PS2
int cmdLen; //# of bytes in pad reply
int irq10En[2]; // enable IRQ10 output for lightgun port
int irq10En[10]; // enable IRQ10 output for lightgun port
int isConnected[10]; // is controller connected?
int trAll[2]; // transfer all mode select
int multiPad[2]; // which controller is connected to the multipad
} global;

extern void SysPrintf(char *fmt, ...);
Expand All @@ -80,7 +83,7 @@ extern int stop;
extern long PadFlags;
extern int gLightgun;

extern virtualControllers_t virtualControllers[2];
extern virtualControllers_t virtualControllers[10];

// Use to invoke func on the mapped controller with args
#define DO_CONTROL(Control,func,args...) \
Expand Down Expand Up @@ -181,8 +184,8 @@ static void UpdateState (const int pad) //Note: pad = 0 or 1
if (lightGun == LIGHTGUN_GUNCON){
global.padID[pad] = 0x63;
wpad = WPAD_Data(0);
if(screenMode == 2) cursorX = ((wpad[virtualControllers[Control].number].ir.x*848/640 - 104)/1.78) + 80;
else cursorX = (wpad[virtualControllers[Control].number].ir.x/1.78) + 80;
if(screenMode == 2) cursorX = ((wpad[virtualControllers[Control].number].ir.x*848/640 - 104)/1.72) + 75;
else cursorX = (wpad[virtualControllers[Control].number].ir.x/1.72) + 75;

cursorY = (wpad[virtualControllers[Control].number].ir.y/2) + (Config.PsxType ? 48 : 25);

Expand Down Expand Up @@ -210,12 +213,14 @@ static void UpdateState (const int pad) //Note: pad = 0 or 1

if(virtualControllers[Control].inUse)
{
global.isConnected[pad] = 1;
if(DO_CONTROL(Control, GetKeys, (BUTTONS*)&PAD_Data, virtualControllers[Control].config))
stop = 1;
}
else
{ //TODO: Emulate no controller present in this case.
//Reset buttons & sticks if PAD is not in use
global.isConnected[pad] = 0;
PAD_Data.btns.All = 0xFFFF;
PAD_Data.leftStickX = PAD_Data.leftStickY = PAD_Data.rightStickX = PAD_Data.rightStickY = 128;
}
Expand All @@ -227,7 +232,7 @@ static void UpdateState (const int pad) //Note: pad = 0 or 1

if ((global.padID[pad] == 0x31) || (global.padID[pad] == 0x63)){
global.padStat[pad] |= lightGun == LIGHTGUN_GUNCON ? ~0x860:~0x8c0;
if (pad==0)
if ((pad==0) || (padType[global.curPad] == PADTYPE_MULTITAP))
{
lastport1.leftJoyX = cursorY & 0xFF; lastport1.leftJoyY = cursorY >> 8;
lastport1.rightJoyX = cursorX & 0xFF; lastport1.rightJoyY = cursorX >> 8;
Expand All @@ -241,7 +246,7 @@ static void UpdateState (const int pad) //Note: pad = 0 or 1
}
}
else{
if (pad==0)
if ((pad==0) || (padType[global.curPad] == PADTYPE_MULTITAP))
{
lastport1.leftJoyX = PAD_Data.leftStickX; lastport1.leftJoyY = PAD_Data.leftStickY;
lastport1.rightJoyX = PAD_Data.rightStickX; lastport1.rightJoyY = PAD_Data.rightStickY;
Expand Down Expand Up @@ -271,15 +276,16 @@ static void UpdateState (const int pad) //Note: pad = 0 or 1

long SSS_PADopen (void *p)
{
int i;
if (!pad_initialized)
{
memset (&global, 0, sizeof (global));
memset( &lastport1, 0, sizeof(lastport1) ) ;
memset( &lastport2, 0, sizeof(lastport2) ) ;
global.padStat[0] = 0xffff;
global.padStat[1] = 0xffff;
PADsetMode (0, controllerType == CONTROLLERTYPE_ANALOG ? 1 : 0); //port 0, analog
PADsetMode (1, controllerType == CONTROLLERTYPE_ANALOG ? 1 : 0); //port 1, analog
for(i = 0; i < 10; i++){
global.padStat[i] = 0xffff;
PADsetMode (i, controllerType == CONTROLLERTYPE_ANALOG ? 1 : 0); //port 0, analog
}
}
return 0;
}
Expand All @@ -304,6 +310,14 @@ unsigned char SSS_PADstartPoll (int pad)
return 0xff;
}

void SSS_SetMultiPad(int pad, int mpad)
{
if (pad)
global.multiPad[1] = mpad+5;
else
global.multiPad[0] = mpad+1;
}

static const u8 cmd40[8] =
{
0xff, 0x5a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5a
Expand Down Expand Up @@ -343,18 +357,29 @@ static const u8 cmd4f[8] = //Enable/disable digital/analog responses bits; only
0xff, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a,
};

unsigned char multitap[34] = { 0x80, 0x5a,
0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x41, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

unsigned char SSS_PADpoll (const unsigned char value)
{
const int pad = global.curPad;
int i, offset, offsetSlot;
int pad = global.curPad;
int slot = pad;
if (padType[slot] == PADTYPE_MULTITAP)
pad = global.multiPad[slot];

const int cur = global.curByte;

//Pragma to avoid packing on "buffer" union
//Not sure if necessary on PPC
#pragma pack(push,1)
union buffer
{
u16 b16[10];
u8 b8[20];
u16 b16[20];
u8 b8[40];
};

static union buffer buf;
Expand All @@ -364,7 +389,10 @@ unsigned char SSS_PADpoll (const unsigned char value)
global.curCmd = value;
if (controllerType != CONTROLLERTYPE_ANALOG)
{
global.curCmd = 0x42;
if (value != 0x42){
buf.b8[1] = 0xFF;
return 0xFF;
}
}
switch (global.curCmd)
{
Expand All @@ -377,7 +405,32 @@ unsigned char SSS_PADpoll (const unsigned char value)
memcpy (buf.b8, cmd41, sizeof (cmd41));
return 0xf3;
case 0x42:
UpdateState (pad);
if (padType[slot] == PADTYPE_MULTITAP){
if (global.trAll[slot] == 1){
global.cmdLen = sizeof (multitap);
memcpy (buf.b8, multitap, sizeof (multitap));
offsetSlot = 2+(slot*4);
for(i = 0; i < 4; i++) {
UpdateState (i+offsetSlot);
offset = i*8;
if (global.isConnected[i+offsetSlot]) {
buf.b8[2+offset] = global.padID[i+offsetSlot];
}
else {
buf.b8[2+offset] = 0xFF;
buf.b8[3+offset] = 0xFF;
}
buf.b8[6+offset] = lastport1.rightJoyX ;
buf.b8[7+offset] = lastport1.rightJoyY ;
buf.b8[8+offset] = lastport1.leftJoyX ;
buf.b8[9+offset] = lastport1.leftJoyY ;
buf.b16[2+(i*4)] = global.padStat[i+offsetSlot];
}
return 0x80;
}
}
UpdateState(pad);

case 0x43:
global.cmdLen = 2 + 2 * (global.padID[pad] & 0x0f);
buf.b8[1] = global.padModeC[pad] ? 0x00 : 0x5a;
Expand All @@ -390,10 +443,19 @@ unsigned char SSS_PADpoll (const unsigned char value)
}
else
{
buf.b8[4] = pad ? lastport2.rightJoyX : lastport1.rightJoyX ;
buf.b8[5] = pad ? lastport2.rightJoyY : lastport1.rightJoyY ;
buf.b8[6] = pad ? lastport2.leftJoyX : lastport1.leftJoyX ;
buf.b8[7] = pad ? lastport2.leftJoyY : lastport1.leftJoyY ;
if (padType[slot] != PADTYPE_MULTITAP){
buf.b8[4] = pad ? lastport2.rightJoyX : lastport1.rightJoyX ;
buf.b8[5] = pad ? lastport2.rightJoyY : lastport1.rightJoyY ;
buf.b8[6] = pad ? lastport2.leftJoyX : lastport1.leftJoyX ;
buf.b8[7] = pad ? lastport2.leftJoyY : lastport1.leftJoyY ;
}
else{
buf.b8[4] = lastport1.rightJoyX ;
buf.b8[5] = lastport1.rightJoyY ;
buf.b8[6] = lastport1.leftJoyX ;
buf.b8[7] = lastport1.leftJoyY ;
}

//if (global.padID[pad] == 0x79)
//{
// do some pressure stuff (this is for PS2 only!)
Expand Down Expand Up @@ -442,7 +504,9 @@ unsigned char SSS_PADpoll (const unsigned char value)
if (cur == global.padVib1[pad])
global.padVibF[pad][1] = value;
if (cur == 2)
global.irq10En[pad] = value;
global.irq10En[slot] = value;
if (cur == 1 && padType[slot] == PADTYPE_MULTITAP)
global.trAll[slot] = value & 1;
break;
case 0x43:
if (cur == 2)
Expand Down Expand Up @@ -502,6 +566,8 @@ unsigned char SSS_PADpoll (const unsigned char value)
}
break;
}


if (cur >= global.cmdLen)
return 0;
return buf.b8[global.curByte++];
Expand Down
1 change: 1 addition & 0 deletions Gamecube/PadSSSPSX.h
Expand Up @@ -31,5 +31,6 @@ typedef struct
} SSSConfig;

void lightgunInterrupt(void);
void SSS_SetMultiPad(int pad, int mpad);

#endif
2 changes: 1 addition & 1 deletion Gamecube/PadWiiSX.c
Expand Up @@ -30,7 +30,7 @@
#include "gc_input/controller.h"
#include "wiiSXconfig.h"

extern virtualControllers_t virtualControllers[2];
extern virtualControllers_t virtualControllers[10];
extern int stop;

// Use to invoke func on the mapped controller with args
Expand Down
4 changes: 2 additions & 2 deletions Gamecube/PlugPAD.c
Expand Up @@ -52,7 +52,7 @@ extern int stop;
//extern char controllerType = 0; // 0 = standard, 1 = analog (analog fails on old games)
long PadFlags = 0;

virtualControllers_t virtualControllers[2];
virtualControllers_t virtualControllers[10];

controller_t* controller_ts[num_controller_t] =
#if defined(WII) && !defined(NO_BT)
Expand Down Expand Up @@ -110,7 +110,7 @@ void assign_controller(int wv, controller_t* type, int wp){
virtualControllers[wv].control = type;
virtualControllers[wv].inUse = 1;
virtualControllers[wv].number = wp;
virtualControllers[wv].config = &type->config[wv];
virtualControllers[wv].config = &type->config[wp];

type->assign(wp,wv);
}
Expand Down
2 changes: 1 addition & 1 deletion Gamecube/gc_input/controller.h
Expand Up @@ -134,7 +134,7 @@ typedef struct _virtualControllers_t {
controller_config_t* config; // This is no longer needed...
} virtualControllers_t;

extern virtualControllers_t virtualControllers[2];
extern virtualControllers_t virtualControllers[10];

// List of all the defined controller_t's
#if defined(WII) && !defined(NO_BT)
Expand Down

0 comments on commit 7f3bfbf

Please sign in to comment.