Files
psxrecomp/tools/padcfg.py
Matthew Stanley af303f3454 runtime: Tomba "Hybrid" legacy pad-config compatibility (per-game opt-in)
The launcher Hybrid controller mode (built first, for Tomba, to mimic Tomba:
Special Edition) flips the emulated pad's reported type 0x41<->0x73 on
d-pad<->stick. After the real DualShock config state machine was added for MMX6
(98aa688), that flip regressed every game's libpad re-detect into a 1-frame
"pad unplugged": Tomba unpauses its menu / drops input, MMX6 phantom-dashes.

The modern config SM is correct and required by MMX6, so instead of weakening it
globally, restore the pre-98aa688 "config commands always answer 0xF3" behaviour
as a per-game opt-in: [controller] legacy_pad_config (default OFF). Only Tomba
sets it; with the flag off the modern pad path is byte-for-byte unchanged, so no
other title is affected. A/B verified live: legacy = clean Tomba flip / MMX6
input; modern = Tomba disconnect + MMX6 dash.

Explicitly LEGACY: a correct findpad/re-detect refactor would make the flip
benign for every game with no per-game branch (real hardware tolerates unlimited
analog-button presses); when that lands this whole feature set is to be removed.
Full rationale in sio.c (g_pad_legacy_cfg).

Also includes the deferred coherent pad-type apply (pad_type_req, applied only at
an idle/non-config bus boundary so a flip can't split a poll/handshake) and a
`pad_cfg` debug command + tools/padcfg.py + tools/sio_flip_trace.py used to A/B
the config SM live.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 13:43:34 -07:00

29 lines
847 B
Python

#!/usr/bin/env python3
"""Phantom-input A/B instrument driver: get/set the pad config-SM mode live.
Usage:
python padcfg.py # report current mode
python padcfg.py 1 # legacy pre-98aa688 "always 0xF3" config
python padcfg.py 0 # new config state machine (shipping)
Optional: PORT as 2nd arg (default 4470, Tomba dev build).
"""
import socket, json, sys
port = 4470
setv = None
if len(sys.argv) > 1 and sys.argv[1] != "":
setv = int(sys.argv[1])
if len(sys.argv) > 2:
port = int(sys.argv[2])
cmd = {"cmd": "pad_cfg"}
if setv is not None:
cmd["set"] = setv
try:
s = socket.create_connection(("127.0.0.1", port), 3)
s.sendall((json.dumps(cmd) + "\n").encode())
print(s.recv(65536).decode().strip())
except Exception as e:
print("debug server not up yet (expected until in-game):", e)