Skip to content

Commit

Permalink
- Add 4 player (multitap) support.
Browse files Browse the repository at this point in the history
  • Loading branch information
emukidid committed Dec 19, 2023
1 parent 2cffaf6 commit 642960a
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 185 deletions.
29 changes: 19 additions & 10 deletions Gamecube/GamecubeMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,12 @@ char screenMode = 0;
char videoMode = 0;
char fileSortMode = 1;
char padAutoAssign;
char padType[2];
char padAssign[2];
char padType[4];
char padAssign[4];
char rumbleEnabled;
char loadButtonSlot;
char controllerType;
char numMultitaps;
char useDithering;
char multitap1; // Multitap in port 1, determined at runtime if we require this based on the number of controllers set.

#define CONFIG_STRING_TYPE 0
#define CONFIG_STRING_SIZE 256
Expand Down Expand Up @@ -160,12 +159,18 @@ static struct {
{ "PadAutoAssign", &padAutoAssign, PADAUTOASSIGN_MANUAL, PADAUTOASSIGN_AUTOMATIC },
{ "PadType1", &padType[0], PADTYPE_NONE, PADTYPE_WII },
{ "PadType2", &padType[1], PADTYPE_NONE, PADTYPE_WII },
{ "PadType3", &padType[2], PADTYPE_NONE, PADTYPE_WII },
{ "PadType4", &padType[3], PADTYPE_NONE, PADTYPE_WII },
{ "PadAssign1", &padAssign[0], PADASSIGN_INPUT0, PADASSIGN_INPUT3 },
{ "PadAssign2", &padAssign[1], PADASSIGN_INPUT0, PADASSIGN_INPUT3 },
{ "PadAssign3", &padAssign[2], PADASSIGN_INPUT0, PADASSIGN_INPUT3 },
{ "PadAssign4", &padAssign[3], PADASSIGN_INPUT0, PADASSIGN_INPUT3 },
{ "RumbleEnabled", &rumbleEnabled, RUMBLE_DISABLE, RUMBLE_ENABLE },
{ "LoadButtonSlot", &loadButtonSlot, LOADBUTTON_SLOT0, LOADBUTTON_DEFAULT },
{ "ControllerType", &controllerType, CONTROLLERTYPE_STANDARD, CONTROLLERTYPE_MOUSE },
// { "NumberMultitaps", &numMultitaps, MULTITAPS_NONE, MULTITAPS_TWO },
{ "ControllerType1", ((char*)(&in_type[0])+3), PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_ANALOGPAD },
{ "ControllerType2", ((char*)(&in_type[1])+3), PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_ANALOGPAD },
{ "ControllerType3", ((char*)(&in_type[2])+3), PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_ANALOGPAD },
{ "ControllerType4", ((char*)(&in_type[3])+3), PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_ANALOGPAD },
{ "smbusername", smbUserName, CONFIG_STRING_TYPE, CONFIG_STRING_TYPE },
{ "smbpassword", smbPassWord, CONFIG_STRING_TYPE, CONFIG_STRING_TYPE },
{ "smbsharename", smbShareName, CONFIG_STRING_TYPE, CONFIG_STRING_TYPE },
Expand Down Expand Up @@ -205,12 +210,18 @@ void loadSettings(int argc, char *argv[])
padAutoAssign = PADAUTOASSIGN_AUTOMATIC;
padType[0] = PADTYPE_NONE;
padType[1] = PADTYPE_NONE;
padType[2] = PADTYPE_NONE;
padType[3] = PADTYPE_NONE;
padAssign[0] = PADASSIGN_INPUT0;
padAssign[1] = PADASSIGN_INPUT1;
padAssign[2] = PADASSIGN_INPUT2;
padAssign[3] = PADASSIGN_INPUT3;
rumbleEnabled = RUMBLE_ENABLE;
loadButtonSlot = LOADBUTTON_DEFAULT;
controllerType = CONTROLLERTYPE_STANDARD;
numMultitaps = MULTITAPS_NONE;
in_type[0] = PSE_PAD_TYPE_STANDARD;
in_type[1] = PSE_PAD_TYPE_STANDARD;
in_type[2] = PSE_PAD_TYPE_STANDARD;
in_type[3] = PSE_PAD_TYPE_STANDARD;
menuActive = 1;

//PCSX-specific defaults
Expand Down Expand Up @@ -328,8 +339,6 @@ void loadSettings(int argc, char *argv[])
Config.SlowBoot = LoadCdBios;
spu_config.iVolume = 1024 - (volume * 192); //Volume="medium" in PEOPSspu
spu_config.iUseReverb = reverb;
in_type[0] = in_type[1] = (controllerType == CONTROLLERTYPE_ANALOG ? PSE_PAD_TYPE_ANALOGPAD : (controllerType == CONTROLLERTYPE_STANDARD ? PSE_PAD_TYPE_STANDARD : PSE_PAD_TYPE_GUNCON));

}

void ScanPADSandReset(u32 dummy)
Expand Down
11 changes: 5 additions & 6 deletions Gamecube/PlugPAD.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@


/* Controller type, later do this by a Variable in the GUI */
//extern char controllerType = 0; // 0 = standard, 1 = analog (analog fails on old games)
long PadFlags = 0;

virtualControllers_t virtualControllers[2];
virtualControllers_t virtualControllers[4];

controller_t* controller_ts[num_controller_t] =
#if defined(WII) && !defined(NO_BT)
Expand All @@ -73,13 +72,13 @@ void control_info_init(void){

void pauseInput(void){
int i;
for(i=0; i<2; ++i)
for(i=0; i<4; ++i)
if(virtualControllers[i].inUse) DO_CONTROL(i, pause);
}

void resumeInput(void){
int i;
for(i=0; i<2; ++i)
for(i=0; i<4; ++i)
if(virtualControllers[i].inUse) DO_CONTROL(i, resume);
}

Expand Down Expand Up @@ -126,7 +125,7 @@ void auto_assign_controllers(void)

// Map controllers in the priority given
// Outer loop: virtual controllers
for(i=0; i<2; ++i){
for(i=0; i<4; ++i){
// Middle loop: controller type
for(t=0; t<num_controller_t; ++t){
controller_t* type = controller_ts[t];
Expand All @@ -150,7 +149,7 @@ void auto_assign_controllers(void)
}

// 'Initialize' the unmapped virtual controllers
for(; i<2; ++i){
for(; i<4; ++i){
unassign_controller(i);
padType[i] = PADTYPE_NONE;
}
Expand Down
6 changes: 3 additions & 3 deletions Gamecube/gc_input/controller-Classic.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ static int available(int Control) {
}
}

static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config)
static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config, int psxType)
{
if(wpadNeedScan){ WPAD_ScanPads(); wpadNeedScan = 0; }
WPADData* wpad = WPAD_Data(Control);
Expand Down Expand Up @@ -187,7 +187,7 @@ static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config)
c->btns.L3_BUTTON = isHeld(config->L3);
c->btns.SELECT_BUTTON = isHeld(config->SELECT);

if(controllerType == CONTROLLERTYPE_LIGHTGUN) {
if(psxType == PSE_PAD_TYPE_NEGCON || psxType == PSE_PAD_TYPE_GUNCON || psxType == PSE_PAD_TYPE_GUN) {
s8 stickX = getStickValue(&wpad->exp.classic.ljs, STICK_X, 127);
s8 stickY = getStickValue(&wpad->exp.classic.ljs, STICK_Y, 127);
// deadzone
Expand All @@ -203,7 +203,7 @@ static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config)
c->gunX = c->gunX > 1023 ? 1023 : (c->gunX < 0 ? 0 : c->gunX);
c->gunY = c->gunY > 1023 ? 1023 : (c->gunY < 0 ? 0 : c->gunY);
}
else if(controllerType == CONTROLLERTYPE_MOUSE) {
else if(psxType == PSE_PAD_TYPE_MOUSE) {
s8 stickX = getStickValue(&wpad->exp.classic.ljs, STICK_X, 127);
s8 stickY = getStickValue(&wpad->exp.classic.ljs, STICK_Y, 127);
// deadzone
Expand Down
7 changes: 3 additions & 4 deletions Gamecube/gc_input/controller-GC.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include <ogc/pad.h>
#include "controller.h"
#include "../wiiSXconfig.h"
extern char controllerType;

enum {
ANALOG_AS_ANALOG = 1, C_STICK_AS_ANALOG = 2,
Expand Down Expand Up @@ -123,7 +122,7 @@ static inline s8 GCtoPSXMouse(s8 i)
return a; // PSX mouse range -128-128
}

static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config)
static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config, int psxType)
{
if(padNeedScan){ gc_connected = PAD_ScanPads(); padNeedScan = 0; }
BUTTONS* c = Keys;
Expand Down Expand Up @@ -163,14 +162,14 @@ static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config)
c->btns.L3_BUTTON = isHeld(config->L3);
c->btns.SELECT_BUTTON = isHeld(config->SELECT);

if(controllerType == CONTROLLERTYPE_LIGHTGUN) {
if(psxType == PSE_PAD_TYPE_NEGCON || psxType == PSE_PAD_TYPE_GUNCON || psxType == PSE_PAD_TYPE_GUN) {
// Keep it within 0 to 1023
c->gunX += gunX + ((PAD_StickX(Control)) / 6);
c->gunY += gunY - ((PAD_StickY(Control)) / 6);
c->gunX = c->gunX > 1023 ? 1023 : (c->gunX < 0 ? 0 : c->gunX);
c->gunY = c->gunY > 1023 ? 1023 : (c->gunY < 0 ? 0 : c->gunY);
}
else if(controllerType == CONTROLLERTYPE_MOUSE) {
else if(psxType == PSE_PAD_TYPE_MOUSE) {
s8 stickX = PAD_StickX(Control);
s8 stickY = PAD_StickY(Control);
c->mouseX = GCtoPSXMouse(stickX);
Expand Down
14 changes: 7 additions & 7 deletions Gamecube/gc_input/controller-WiimoteNunchuk.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ static button_t menu_combos[] = {

static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config,
int (*available)(int),
unsigned int (*getButtons)(WPADData*))
unsigned int (*getButtons)(WPADData*), int psxType)
{
if(wpadNeedScan){ WPAD_ScanPads(); wpadNeedScan = 0; }
WPADData* wpad = WPAD_Data(Control);
Expand Down Expand Up @@ -142,7 +142,7 @@ static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config,
c->btns.L3_BUTTON = isHeld(config->L3);
c->btns.SELECT_BUTTON = isHeld(config->SELECT);

if(controllerType == CONTROLLERTYPE_LIGHTGUN) {
if(psxType == PSE_PAD_TYPE_NEGCON || psxType == PSE_PAD_TYPE_GUNCON || psxType == PSE_PAD_TYPE_GUN) {
s8 stickX = 0;
s8 stickY = 0;
if(config->analogL->mask == NUNCHUK_AS_ANALOG){
Expand Down Expand Up @@ -172,7 +172,7 @@ static int _GetKeys(int Control, BUTTONS * Keys, controller_config_t* config,
c->gunX = c->gunX > 1023 ? 1023 : (c->gunX < 0 ? 0 : c->gunX);
c->gunY = c->gunY > 1023 ? 1023 : (c->gunY < 0 ? 0 : c->gunY);
}
else if(controllerType == CONTROLLERTYPE_MOUSE) {
else if(psxType == PSE_PAD_TYPE_MOUSE) {
s8 stickX = 0;
s8 stickY = 0;
if(config->analogL->mask == NUNCHUK_AS_ANALOG){
Expand Down Expand Up @@ -307,12 +307,12 @@ static unsigned int getButtonsWMN(WPADData* controller){
return b;
}

static int GetKeysWM(int con, BUTTONS * keys, controller_config_t* cfg){
return _GetKeys(con, keys, cfg, availableWM, getButtonsWM);
static int GetKeysWM(int con, BUTTONS * keys, controller_config_t* cfg, int psxType){
return _GetKeys(con, keys, cfg, availableWM, getButtonsWM, psxType);
}

static int GetKeysWMN(int con, BUTTONS * keys, controller_config_t* cfg){
return _GetKeys(con, keys, cfg, availableWMN, getButtonsWMN);
static int GetKeysWMN(int con, BUTTONS * keys, controller_config_t* cfg, int psxType){
return _GetKeys(con, keys, cfg, availableWMN, getButtonsWMN, psxType);
}

static void pause(int Control){
Expand Down
5 changes: 3 additions & 2 deletions Gamecube/gc_input/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include <gccore.h>
#include <stdio.h>
#include <psemu_plugin_defs.h>

extern char padNeedScan, wpadNeedScan;
extern u32 gc_connected;
Expand Down Expand Up @@ -97,7 +98,7 @@ typedef struct {
// You should pass in controller num for this type
// Not for the player number assigned
// (eg use GC Controller 1, not player 1)
int (*GetKeys)(int, BUTTONS*, controller_config_t*);
int (*GetKeys)(int, BUTTONS*, controller_config_t*, int);
// Set the configuration for a controller of this type
// You should pass in physical controller num as above
void (*configure)(int, controller_config_t*);
Expand Down Expand Up @@ -139,7 +140,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[4];

// List of all the defined controller_t's
#if defined(WII) && !defined(NO_BT)
Expand Down
80 changes: 31 additions & 49 deletions Gamecube/gc_plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ long PAD2__open(void) {
#include "wiiSXconfig.h"
extern int stop;
//extern void GPUcursor(int iPlayer,int x,int y);
extern virtualControllers_t virtualControllers[2];
extern virtualControllers_t virtualControllers[4];
// Use to invoke func on the mapped controller with args
#define DO_CONTROL(Control,func,args...) \
virtualControllers[Control].control->func( \
Expand Down Expand Up @@ -198,36 +198,19 @@ void setCursor(int iPlayer,int x,int y)

long PAD1__readPort1(PadDataS *pad) {
int pad_index = pad->requestPadIndex;
//SysPrintf("Read port 1 called with %i pad index, in use %s\r\n", pad_index, virtualControllers[pad_index].inUse ? "YES":"NO");
if(!virtualControllers[pad_index].inUse) return 0;

static BUTTONS PAD_Data;
if(virtualControllers[pad_index].inUse && DO_CONTROL(pad_index, GetKeys, (BUTTONS*)&PAD_Data, virtualControllers[pad_index].config))
if(virtualControllers[pad_index].inUse && DO_CONTROL(pad_index, GetKeys, (BUTTONS*)&PAD_Data, virtualControllers[pad_index].config, in_type[pad_index]))
stop = 1;
switch(controllerType) {
case CONTROLLERTYPE_LIGHTGUN:
pad->controllerType = PSE_PAD_TYPE_GUNCON;
break;
case CONTROLLERTYPE_MOUSE:
pad->controllerType = PSE_PAD_TYPE_MOUSE;
usCursorActive=0;
break;
case CONTROLLERTYPE_ANALOG:
pad->controllerType = PSE_PAD_TYPE_ANALOGPAD;
usCursorActive=0;
break;
default:
pad->controllerType = PSE_PAD_TYPE_STANDARD;
usCursorActive=0;
break;
}
pad->controllerType = in_type[pad_index];
pad->buttonStatus = PAD_Data.btns.All;

//if (multitap1 == 1)
// pad->portMultitap = 1;
//else
pad->portMultitap = 0;
pad->portMultitap = multitap1;

if (controllerType == CONTROLLERTYPE_ANALOG || controllerType == CONTROLLERTYPE_LIGHTGUN)
usCursorActive=0;
if (in_type[pad_index] == PSE_PAD_TYPE_ANALOGJOY || in_type[pad_index] == PSE_PAD_TYPE_ANALOGPAD || in_type[pad_index] == PSE_PAD_TYPE_NEGCON || in_type[pad_index] == PSE_PAD_TYPE_GUNCON || in_type[pad_index] == PSE_PAD_TYPE_GUN)
{
pad->leftJoyX = PAD_Data.leftStickX;
pad->leftJoyY = PAD_Data.leftStickY;
Expand All @@ -236,13 +219,13 @@ long PAD1__readPort1(PadDataS *pad) {

pad->absoluteX = PAD_Data.gunX;
pad->absoluteY = PAD_Data.gunY;

if(controllerType == CONTROLLERTYPE_LIGHTGUN) {
if(in_type[pad_index] == PSE_PAD_TYPE_GUN) {
usCursorActive=1;
setCursor(pad_index, pad->absoluteX, pad->absoluteY);
}
}

if (controllerType == CONTROLLERTYPE_MOUSE)
if (in_type[pad_index] == PSE_PAD_TYPE_MOUSE)
{
pad->moveX = PAD_Data.mouseX;
pad->moveY = PAD_Data.mouseY;
Expand All @@ -253,37 +236,27 @@ long PAD1__readPort1(PadDataS *pad) {

long PAD2__readPort2(PadDataS *pad) {
int pad_index = pad->requestPadIndex;
//SysPrintf("Read port 2 called with %i pad index, in use %s\r\n", pad_index, virtualControllers[pad_index].inUse ? "YES":"NO");

// If multi-tap is enabled, this comes up as 4 (port 1 will do 0,1,2,3).
if(pad_index >=4) return 0;

if(!virtualControllers[pad_index].inUse) return 0;

static BUTTONS PAD_Data2;
if(virtualControllers[pad_index].inUse && DO_CONTROL(pad_index, GetKeys, (BUTTONS*)&PAD_Data2, virtualControllers[pad_index].config))
if(virtualControllers[pad_index].inUse && DO_CONTROL(pad_index, GetKeys, (BUTTONS*)&PAD_Data2, virtualControllers[pad_index].config, in_type[pad_index]))
stop = 1;

switch(controllerType) {
case CONTROLLERTYPE_LIGHTGUN:
pad->controllerType = PSE_PAD_TYPE_GUNCON;
break;
case CONTROLLERTYPE_MOUSE:
pad->controllerType = PSE_PAD_TYPE_MOUSE;
usCursorActive=0;
break;
case CONTROLLERTYPE_ANALOG:
pad->controllerType = PSE_PAD_TYPE_ANALOGPAD;
usCursorActive=0;
break;
default:
pad->controllerType = PSE_PAD_TYPE_STANDARD;
usCursorActive=0;
break;
}
pad->controllerType = in_type[pad_index];
pad->buttonStatus = PAD_Data2.btns.All;

//if (multitap2 == 1)
// pad->portMultitap = 2;
//else
pad->portMultitap = 0;

if (controllerType == CONTROLLERTYPE_ANALOG || controllerType == CONTROLLERTYPE_LIGHTGUN)

usCursorActive=0;
if (in_type[pad_index] == PSE_PAD_TYPE_ANALOGJOY || in_type[pad_index] == PSE_PAD_TYPE_ANALOGPAD || in_type[pad_index] == PSE_PAD_TYPE_NEGCON || in_type[pad_index] == PSE_PAD_TYPE_GUNCON || in_type[pad_index] == PSE_PAD_TYPE_GUN)
{
pad->leftJoyX = PAD_Data2.leftStickX;
pad->leftJoyY = PAD_Data2.leftStickY;
Expand All @@ -292,12 +265,13 @@ long PAD2__readPort2(PadDataS *pad) {

pad->absoluteX = PAD_Data2.gunX;
pad->absoluteY = PAD_Data2.gunY;
if(controllerType == CONTROLLERTYPE_LIGHTGUN) {
if(in_type[pad_index] == PSE_PAD_TYPE_GUN) {
usCursorActive=1;
setCursor(pad_index, pad->absoluteX, pad->absoluteY);
}
}

if (controllerType == CONTROLLERTYPE_MOUSE)
if (in_type[pad_index] == PSE_PAD_TYPE_MOUSE)
{
pad->moveX = PAD_Data2.mouseX;
pad->moveY = PAD_Data2.mouseY;
Expand Down Expand Up @@ -866,6 +840,14 @@ void plugin_call_rearmed_cbs(void)
void go(void) {
Config.PsxOut = 0;
stop = 0;

// Enable a multi-tap in port 1 if we have more than 2 mapped controllers.
int controllersConnected = 0;
for(int i = 0; i < 4; i++) {
controllersConnected += ((in_type[i] && virtualControllers[i].inUse) ? 1 : 0);
}
multitap1 = controllersConnected > 2 ? 1 : 0;
SysPrintf("Multi-tap port status: %s\r\n", multitap1 ? "connected" : "disconnected");

/* Apply settings from menu */
gc_rearmed_cbs.gpu_unai.dithering = !!useDithering;
Expand Down
Loading

0 comments on commit 642960a

Please sign in to comment.