Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ DETAILED_CHANGELOG
!.clang-format
!.clang-format-ignore
!modules/debug/*.irx
# TEST-ONLY (#340): the vendored 2023-era sio2man diagnostic blob
!modules/sio2man-2023/*.irx

#
# Generated source files
Expand Down
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,12 @@ $(EE_ASM_DIR)iomanx.c: $(PS2SDK)/iop/irx/iomanX.irx | $(EE_ASM_DIR)
$(EE_ASM_DIR)filexio.c: $(PS2SDK)/iop/irx/fileXio.irx | $(EE_ASM_DIR)
$(BIN2C) $< $@ $(*F)_irx

$(EE_ASM_DIR)sio2man.c: $(PS2SDK)/iop/irx/freesio2.irx | $(EE_ASM_DIR)
# TEST-ONLY BUILD (#340 diagnosis, DO NOT MERGE): embed the pre-rewrite 2023 sio2man (threaded,
# prio-24 worker) extracted from uOPL's pinned CI container instead of the SDK's current
# threadless freesio2.irx. Confirms/refutes the threadless-sio2man trigger on real hardware.
# EXPECTED side effects: MMCE and MX4SIO menu features may break (they need the new sio2man API).
# See modules/sio2man-2023/PROVENANCE-TEST.md.
$(EE_ASM_DIR)sio2man.c: modules/sio2man-2023/freesio2-2023.irx | $(EE_ASM_DIR)
$(BIN2C) $< $@ $(*F)_irx

$(EE_ASM_DIR)padman.c: $(PS2SDK)/iop/irx/freepad.irx | $(EE_ASM_DIR)
Expand Down
4 changes: 2 additions & 2 deletions include/pad.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ void unloadPads();
// Colors is on (gui.c / dia.c). Field semantics live with the writers in pad.c.
typedef struct
{
unsigned int readMisses; // total failed ready-state pad reads
unsigned int missBurst; // current consecutive-miss run, max across pads (polls)
unsigned int readMisses; // polls where at least one ready-state pad produced no fresh sample
unsigned int missBurst; // current consecutive run of such polls (0 when all ready pads read)
unsigned int missBurstMax; // session peak of the above
unsigned int pollMaxMs; // worst readPads() period this session
unsigned int stateFlaps; // DISCONN -> ready reconnect edges seen
Expand Down
31 changes: 31 additions & 0 deletions modules/sio2man-2023/PROVENANCE-TEST.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# modules/sio2man-2023 -- DIAGNOSTIC blob, never to be merged

`freesio2-2023.irx` (5428 bytes, sha256
`df200af667a3584a54da5096670ec5c347d3f787a5f47f133a0c29d08ac5eaa9`) is the PS2SDK `sio2man`
extracted VERBATIM from `ghcr.io/ps2dev/ps2dev@sha256:362bcd26b8bd94149c539f41749edb13facbb5b68a8b960e219fc079693cb95f`
-- the exact container digest uOPL's CI pins, image created **2023-09-09**, file dated
2023-09-04 inside the image. This is the PRE-rewrite module: its import table carries
`thbase` + `thevent` (dedicated priority-0x18 worker thread driven by event flags) and no
`thsemap`, unlike the post-PR#709 threadless build.

## Purpose (issue #340)

Confirmation experiment requested by KrahJohlito: if the D-pad drop/queue issue disappears
with ONLY this module swapped (everything else stock), the ps2sdk threadless sio2man rewrite
(PR #709, Jan 2025) is confirmed as the trigger on real hardware. This build exists to
produce that pass/fail datum -- it is NOT a fix.

## Expected breakage -- do not report as bugs of this build

- MMCE menu features (mmceman hooks the modern sio2man internals).
- MX4SIO menu browsing (post-PR#862 mx4sio_bd requires the modern sio2man).
- MX4SIO game launches (the same embed is loaded game-side for CORE_IRX_MX4SIO).

Test on a USB-booted, USB-game setup only.

## The actual fix candidate

`feat/340-sio2man-priority-ceiling` -- the modern module rebuilt from pinned source with a
priority-ceiling bracket (same API, no feature breakage). If THIS diagnostic build fixes the
D-pad and the ceiling build does too, ship the ceiling; if this fixes it and the ceiling does
not, the ceiling theory is wrong and the delta between the two modules needs a deeper look.
Binary file added modules/sio2man-2023/freesio2-2023.irx
Binary file not shown.
24 changes: 24 additions & 0 deletions src/pad.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ static u32 oldpaddata;
// are SHOWN only when Settings -> Debug Colors is on.
static pad_diag_t padDiag;

// Per-poll read outcome, reset by readPads() and filled in by each readPad(): how many pads were
// in a ready state, and how many produced a fresh sample. A poll where a ready pad produced no
// fresh sample is a read MISS (per-pad accounting: another pad reading fine does not hide it).
// Misses cluster under SIO2 load on real hardware; an emulator's pad never produces one.
static int pollPadsReady;
static int pollPadsRead;

void padGetDiag(pad_diag_t *out)
{
if (out)
Expand Down Expand Up @@ -483,6 +490,7 @@ static int readPad(struct pad_data_t *pad)
}

if (isPadReadyState(pad->state)) {
pollPadsReady++;
ret = padRead(pad->port, pad->slot, &pad->buttons); // port, slot, buttons

if (ret != 0) {
Expand Down Expand Up @@ -544,6 +552,7 @@ static int readPad(struct pad_data_t *pad)
#endif

if (padsRead > 0) {
pollPadsRead++;
newpdata = readLeftJoy(pad, newpdata);
pad->paddata = newpdata;

Expand Down Expand Up @@ -817,9 +826,24 @@ int readPads()
if (time_since_last > padDiag.pollMaxMs)
padDiag.pollMaxMs = time_since_last;

pollPadsReady = 0;
pollPadsRead = 0;
for (i = 0; i < pad_count; ++i)
result |= readPad(&pad_data[i]);

// Debug-Colors diag: a read MISS is a poll where a ready pad produced no fresh sample --
// counted per-pad, so another pad (or a PADEMU ds34) reading fine does not hide it. These
// counters feed the HUD "PAD miss:" line; they had no writers between the PR #328 revert
// and this change, so the HUD showed miss:0 regardless of what the hardware did.
if (pollPadsRead < pollPadsReady) {
padDiag.readMisses++;
padDiag.missBurst++;
if (padDiag.missBurst > padDiag.missBurstMax)
padDiag.missBurstMax = padDiag.missBurst;
} else {
padDiag.missBurst = 0;
}

// Stamp input activity AFTER the merge: any held button/stick re-arms the PAD_SELF_HEAL_IDLE_MS gate.
if (paddata != 0)
lastInputActivityMs = curtime;
Expand Down