Ctrl: Let a press shorter than the sample interval be seen once

A press and release that both land between two sceCtrl samples were
lost. Now the next sample sees the button pressed. Idea from Azahar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-11-02 08:52:24 +01:00
1 parent fc9ca4d1f7
commit 5ea0921301
1 file changed
+12 -2
+12 -2
View File
@@ -114,6 +114,10 @@ static u32 emuRapidFireInterval = 5;
// no buttons and centered sticks, as impose does on a PSP. Host-side peeks still see the real state.
static std::atomic<bool> gameInputBlocked{ false };
// Buttons pressed since the last sample. A press and release that both land between two samples
// would otherwise never be seen by the game. Guarded by ctrlMutex.
static u32 ctrlUnsampledPresses = 0;
// These buttons are not affected by rapid fire (neither is analog.)
const u32 CTRL_EMU_RAPIDFIRE_MASK = CTRL_UP | CTRL_DOWN | CTRL_LEFT | CTRL_RIGHT;
@@ -122,7 +126,8 @@ static void __CtrlUpdateLatch()
std::lock_guard<std::mutex> guard(ctrlMutex);
u64 t = CoreTiming::GetGlobalTimeUs();
u32 buttons = ctrlCurrent.buttons;
u32 buttons = ctrlCurrent.buttons | ctrlUnsampledPresses;
ctrlUnsampledPresses = 0;
if (emuRapidFire && emuRapidFireToggle)
buttons &= CTRL_EMU_RAPIDFIRE_MASK;
@@ -284,7 +289,8 @@ void __CtrlUpdateButtons(u32 bitsToSet, u32 bitsToClear)
std::lock_guard<std::mutex> guard(ctrlMutex);
// There's no atomic operation for this, so mutex it is.
ctrlCurrent.buttons = (ctrlCurrent.buttons & ~bitsToClear) | bitsToSet;
ctrlUnsampledPresses |= bitsToSet & ~ctrlCurrent.buttons;
ctrlCurrent.buttons =(ctrlCurrent.buttons & ~bitsToClear) | bitsToSet;
}
void __CtrlSetAnalogXY(int stick, float x, float y)
@@ -448,6 +454,7 @@ void __CtrlInit() {
latch.btnRelease = 0xffffffff;
gameInputBlocked = false;
ctrlUnsampledPresses = 0;
memset(&ctrlCurrent, 0, sizeof(ctrlCurrent));
memset(ctrlCurrent.analog, CTRL_ANALOG_CENTER, sizeof(ctrlCurrent.analog));
analogEnabled = false;
@@ -464,6 +471,9 @@ void __CtrlDoState(PointerWrap &p)
if (!s)
return;
// Host input from before the load shouldn't show up in the loaded state.
ctrlUnsampledPresses = 0;
Do(p, analogEnabled);
Do(p, ctrlLatchBufs);
Do(p, ctrlOldButtons);