From: notaz Date: Fri, 13 Mar 2026 23:42:15 +0000 (+0200) Subject: pad: more input updates X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=97aae9856e1de6c0c58abb50d0e2ce9ae8c89c8b;p=pcsx_rearmed.git pad: more input updates simulate replug on config changes, cleanups --- diff --git a/frontend/libretro.c b/frontend/libretro.c index 87e9b21e..4040b3e4 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -881,8 +881,8 @@ static char *get_pse_pad_label[] = { static const struct retro_controller_description pads[8] = { { "standard", RETRO_DEVICE_JOYPAD }, - { "analog", RETRO_DEVICE_PSE_ANALOG }, { "dualshock", RETRO_DEVICE_PSE_DUALSHOCK }, + { "analog", RETRO_DEVICE_PSE_ANALOG }, { "negcon", RETRO_DEVICE_PSE_NEGCON }, { "guncon", RETRO_DEVICE_PSE_GUNCON }, { "konami gun", RETRO_DEVICE_PSE_JUSTIFIER }, @@ -1138,6 +1138,8 @@ unsigned retro_api_version(void) static void update_multitap(void) { struct retro_variable var = { 0 }; + int multitap1_old = multitap1; + int multitap2_old = multitap2; multitap1 = 0; multitap2 = 0; @@ -1156,13 +1158,19 @@ static void update_multitap(void) multitap2 = 1; } } + if (multitap1 != multitap1_old || multitap2 != multitap2_old) { + SysPrintf("multitap: %d %d\n", multitap1, multitap2); + padChanged(); + } } void retro_set_controller_port_device(unsigned port, unsigned device) { + int in_type_old; if (port >= PORTS_NUMBER) return; + in_type_old = in_type[port]; switch (device) { case RETRO_DEVICE_JOYPAD: @@ -1193,7 +1201,10 @@ void retro_set_controller_port_device(unsigned port, unsigned device) break; } - SysPrintf("port: %u device: %s\n", port + 1, get_pse_pad_label[in_type[port]]); + if (in_type[port] != in_type_old) { + SysPrintf("port: %u device: %s\n", port + 1, get_pse_pad_label[in_type[port]]); + padChanged(); + } } void retro_get_system_info(struct retro_system_info *info) diff --git a/frontend/menu.c b/frontend/menu.c index 436c104a..2702be3f 100644 --- a/frontend/menu.c +++ b/frontend/menu.c @@ -308,6 +308,7 @@ static int optional_cdimg_filter(struct dirent **namelist, int count, static void menu_sync_config(void) { static int allow_abs_only_old; + int in_type_old[2] = { in_type[0], in_type[1] }; Config.PsxAuto = 1; if (region > 0) { @@ -334,6 +335,8 @@ static void menu_sync_config(void) in_probe(); allow_abs_only_old = in_evdev_allow_abs_only; } + if (in_type[0] != in_type_old[0] || in_type[1] != in_type_old[1]) + padChanged(); spu_config.iVolume = 768 + 128 * volume_boost; pl_rearmed_cbs.frameskip = frameskip - 1; diff --git a/frontend/plugin.c b/frontend/plugin.c index 86b8bb92..0180e468 100644 --- a/frontend/plugin.c +++ b/frontend/plugin.c @@ -24,14 +24,12 @@ #include "../plugins/dfsound/spu.h" /* PAD */ -long PAD1_readPort(PadDataS *pad) { +void PAD1_readPort(PadDataS *pad, int *is_multitap) { int pad_index = pad->requestPadIndex; pad->controllerType = in_type[pad_index]; pad->buttonStatus = ~in_keystate[pad_index]; - pad->portMultitap = multitap1; - 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 = in_analog_left[pad_index][0]; @@ -49,17 +47,16 @@ long PAD1_readPort(PadDataS *pad) { pad->moveY = in_mouse[pad_index][1]; } - return 0; + if (is_multitap) + *is_multitap = multitap1; } -long PAD2_readPort(PadDataS *pad) { +void PAD2_readPort(PadDataS *pad, int *is_multitap) { int pad_index = pad->requestPadIndex; pad->controllerType = in_type[pad_index]; pad->buttonStatus = ~in_keystate[pad_index]; - pad->portMultitap = multitap2; - 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 = in_analog_left[pad_index][0]; @@ -77,7 +74,8 @@ long PAD2_readPort(PadDataS *pad) { pad->moveY = in_mouse[pad_index][1]; } - return 0; + if (is_multitap) + *is_multitap = multitap2; } /* GPU */ diff --git a/frontend/plugin.h b/frontend/plugin.h index 20c622d7..a77ec702 100644 --- a/frontend/plugin.h +++ b/frontend/plugin.h @@ -16,7 +16,7 @@ void *plugin_link(enum builtint_plugins_e id, const char *sym); void plugin_call_rearmed_cbs(void); struct PadDataS; -long PAD1_readPort(struct PadDataS *); -long PAD2_readPort(struct PadDataS *); +void PAD1_readPort(struct PadDataS *, int *is_multitap); +void PAD2_readPort(struct PadDataS *, int *is_multitap); #endif /* __PLUGIN_H__ */ diff --git a/libpcsxcore/pad.c b/libpcsxcore/pad.c index 2f107b26..13d7de89 100644 --- a/libpcsxcore/pad.c +++ b/libpcsxcore/pad.c @@ -15,12 +15,14 @@ #include "psxcounters.h" #include "plugins.h" -extern int in_type[8]; +#define REPLUG_FRAMES 32u // Pad information, keystate, mode, config mode, vibration -static PadDataS pads[8]; - -static int reqPos; +static struct { + PadDataS pads[8]; + int reqPos; + u32 replug_frame; +} g; // response for request 44, 45, 46, 47, 4C, 4D static const u8 resp45[8] = {0xF3, 0x5A, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00}; @@ -179,7 +181,7 @@ static void initBufForRequest(PadDataS *pad, unsigned char value) if (pad->ds.autoAnalogTried == 16) { // auto-enable for convenience SysPrintf("Pad%ld: Auto-enabling dualshock analog mode.\n", - (long)(pad - pads + 1)); + (long)(pad - g.pads + 1)); pad->ds.padMode = 1; pad->ds.autoAnalogTried = 255; } @@ -265,7 +267,7 @@ static void ds_update_vibrate(PadDataS *pad) pad->Vib[1] = 0; } if (pad->Vib[0] != pad->VibF[0] || pad->Vib[1] != pad->VibF[1]) { - size_t padIndex = pad - pads; + size_t padIndex = pad - g.pads; //value is different update Value and call libretro for vibration pad->VibF[0] = pad->Vib[0]; pad->VibF[1] = pad->Vib[1]; @@ -381,7 +383,8 @@ static void PADstartPoll_(PadDataS *pad) pad->respSize = 4; break; default: - pad->respSize = 0; + pad->rxData[0] = 0xff; + pad->respSize = 1; break; } } @@ -421,14 +424,16 @@ static void PADpoll_dualshock(PadDataS *pad, unsigned char value, int pos) static unsigned char PADpoll_(int port, unsigned char value, int pos, int *more_data) { - PadDataS *pad = &pads[port]; + PadDataS *pad = &g.pads[port]; if (pos < sizeof(pad->txData)) pad->txData[pos] = value; - if (pos == 0 && value != 0x42 && in_type[port] != PSE_PAD_TYPE_ANALOGPAD) + if (pos == 0 && value != 0x42 && pad->controllerType != PSE_PAD_TYPE_ANALOGPAD) { pad->respSize = 1; + pad->rxData[0] = 0xff; + } - switch (in_type[port]) { + switch (pad->controllerType) { case PSE_PAD_TYPE_ANALOGPAD: PADpoll_dualshock(pad, value, pos); break; @@ -440,7 +445,7 @@ static unsigned char PADpoll_(int port, unsigned char value, int pos, int *more_ *more_data = pos < pad->respSize - 1; if (pos >= pad->respSize) { - log_unhandled("pad %zd read %d/%d\n", pad - pads, pos, pad->respSize); + log_unhandled("pad %zd read %d/%d\n", pad - g.pads, pos, pad->respSize); return 0xff; // no response/HiZ } @@ -468,7 +473,7 @@ static unsigned char PADpollMultitap(int port, unsigned char value, int pos, int pos_dev = pos - 2; dev = pos_dev / 8u; - pad = &pads[port + dev]; + pad = &g.pads[port + dev]; if (pos_dev % 8u == 0) { memcpy(pad->rxDataOld, pad->rxData, sizeof(pad->rxDataOld)); PADstartPoll_(pad); @@ -481,13 +486,19 @@ static unsigned char PADpollMultitap(int port, unsigned char value, int pos, int static unsigned char PADpollMain(int port, unsigned char value, int *more_data) { unsigned char ret; - int pos = reqPos++; + int pos = g.reqPos++; PAD_LOG_TX(pos, value); - if (pos == 1) - pads[port].txData1 = value; - if (!pads[port].portMultitap || !pads[port].multitapLongModeEnabled) + g.pads[port].txData1 = value; + + if (g.replug_frame) { + if (frame_counter - g.replug_frame > REPLUG_FRAMES) + g.replug_frame = 0; + ret = 0xff; + *more_data = 0; + } + else if (!g.pads[port].portMultitap || !g.pads[port].multitapLongModeEnabled) ret = PADpoll_(port, value, pos, more_data); else ret = PADpollMultitap(port, value, pos, more_data); @@ -499,84 +510,99 @@ static unsigned char PADpollMain(int port, unsigned char value, int *more_data) } +static int PADstartPollMain(PadDataS *pad) +{ + g.reqPos = 0; + + pad->multitapLongModeEnabled = 0; + if (pad->portMultitap) + pad->multitapLongModeEnabled = pad->txData1 & 1; + + if (!pad->portMultitap || !pad->multitapLongModeEnabled) { + PADstartPoll_(pad); + return 0; + } + return 1; +} + // refresh the button state on port 1. // int pad is not needed. -unsigned char PAD1_startPoll(int unused) +unsigned char PAD1_startPoll(void) { + PadDataS *pad = &g.pads[0]; 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; + pad->requestPadIndex = 0; + PAD1_readPort(pad, &pad->portMultitap); - if (!pads[0].portMultitap || !pads[0].multitapLongModeEnabled) { - PADstartPoll_(&pads[0]); - } else { + if (PADstartPollMain(pad)) { // a multitap is plugged and enabled: refresh pads 1-3 for (i = 1; i < 4; i++) { - pads[i].requestPadIndex = i; - PAD1_readPort(&pads[i]); + g.pads[i].requestPadIndex = i; + PAD1_readPort(&g.pads[i], NULL); } } return 0xff; } -unsigned char PAD1_poll(unsigned char value, int *more_data) { +unsigned char PAD1_poll(unsigned char value, int *more_data) +{ return PADpollMain(0, value, more_data); } - -unsigned char PAD2_startPoll(int pad) +unsigned char PAD2_startPoll(void) { - int pad_index = pads[0].portMultitap ? 4 : 1; + int pad_index = g.pads[0].portMultitap ? 4 : 1; + PadDataS *pad = &g.pads[pad_index]; 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; + pad->requestPadIndex = pad_index; + PAD2_readPort(pad, &pad->portMultitap); - if (!pads[pad_index].portMultitap || !pads[pad_index].multitapLongModeEnabled) { - PADstartPoll_(&pads[pad_index]); - } else { + if (PADstartPollMain(pad)) { for (i = 1; i < 4; i++) { - pads[pad_index + i].requestPadIndex = pad_index + i; - PAD2_readPort(&pads[pad_index + i]); + g.pads[pad_index + i].requestPadIndex = pad_index + i; + PAD2_readPort(&g.pads[pad_index + i], NULL); } } return 0xff; } -unsigned char PAD2_poll(unsigned char value, int *more_data) { - return PADpollMain(pads[0].portMultitap ? 4 : 1, value, more_data); +unsigned char PAD2_poll(unsigned char value, int *more_data) +{ + return PADpollMain(g.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)); + memset(&g, 0, sizeof(g)); + for (p = 0; p < sizeof(g.pads) / sizeof(g.pads[0]); p++) { + memset(g.pads[p].rxData, 0xff, sizeof(g.pads[p].rxData)); + memset(g.pads[p].ds.cmd4dConfig, 0xff, sizeof(g.pads[p].ds.cmd4dConfig)); } } -int padFreeze(void *f, int Mode) { +int padFreeze(void *f, int Mode) +{ + int changed = 0; 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); + for (i = 0; i < sizeof(g.pads) / sizeof(g.pads[0]); i++) { + unsigned char controllerType = g.pads[i].controllerType; + int portMultitap = g.pads[i].portMultitap; + g.pads[i].saveSize = sizeof(g.pads[i]); + gzfreeze(&g.pads[i], sizeof(g.pads[i])); + if (Mode == 0) { // load + if (g.pads[i].saveSize != sizeof(g.pads[i])) + SaveFuncs.seek(f, g.pads[i].saveSize - sizeof(g.pads[i]), + SEEK_CUR); + changed |= controllerType != g.pads[i].controllerType; + changed |= portMultitap != g.pads[i].portMultitap; + } } + if (changed) + padChanged(); return 0; } @@ -585,9 +611,15 @@ 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; + if (index < sizeof(g.pads) / sizeof(g.pads[0])) { + r = (g.pads[index].ds.padMode ^= 1); + g.pads[index].ds.userToggled = 1; } return r; } + +void padChanged(void) +{ + padReset(); + g.replug_frame = frame_counter; +} diff --git a/libpcsxcore/plugins.h b/libpcsxcore/plugins.h index f8a3197c..f44e425d 100644 --- a/libpcsxcore/plugins.h +++ b/libpcsxcore/plugins.h @@ -124,17 +124,18 @@ extern SPUplayCDDAchannel SPU_playCDDAchannel; extern SPUsetCDvol SPU_setCDvol; // PAD Functions -long PAD1_readPort(PadDataS *); -unsigned char PAD1_startPoll(int); +void PAD1_readPort(struct PadDataS *, int *is_multitap); +unsigned char PAD1_startPoll(void); unsigned char PAD1_poll(unsigned char, int *); -long PAD2_readPort(PadDataS *); -unsigned char PAD2_startPoll(int); +void PAD2_readPort(struct PadDataS *, int *is_multitap); +unsigned char PAD2_startPoll(void); unsigned char PAD2_poll(unsigned char, int *); int padFreeze(void *f, int Mode); int padToggleAnalog(unsigned int index); void padReset(void); +void padChanged(void); #ifdef ENABLE_SIO1API diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index de3768fb..ee358a7e 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -4135,7 +4135,7 @@ void psxBiosCnfLoaded(u32 tcb_cnt, u32 evcb_cnt, u32 stack) { #define psxBios_PADpoll(pad) { \ int i, more_data = 0; \ - PAD##pad##_startPoll(pad); \ + PAD##pad##_startPoll(); \ pad_buf##pad[1] = PAD##pad##_poll(0x42, &more_data); \ pad_buf##pad[0] = more_data ? 0 : 0xff; \ PAD##pad##_poll(0, &more_data); \ diff --git a/libpcsxcore/sio.c b/libpcsxcore/sio.c index 32345412..e35631b9 100644 --- a/libpcsxcore/sio.c +++ b/libpcsxcore/sio.c @@ -208,8 +208,8 @@ void sioWrite8(unsigned char value) { StatReg |= RX_RDY; // Transfer is Ready switch (CtrlReg & 0x2002) { - case 0x0002: buf[0] = PAD1_startPoll(1); break; - case 0x2002: buf[0] = PAD2_startPoll(2); break; + case 0x0002: buf[0] = PAD1_startPoll(); break; + case 0x2002: buf[0] = PAD2_startPoll(); break; } bufcount = 1; parp = 0;