Repository navigation
Input: a second pad on port 1 from the window (input.player2) — #101 phase 1 - #102
Merged
gascarcella merged 1 commit intoOct 24, 2026
Conversation
A setting, input.player2 ("off" by default, "first" or "second": that gamepad
by connection order), makes one gamepad player 2: it drives the PS1's port 1
with the gamepad map, port 1 is connected only while that gamepad is there,
and its inputs never reach a hotkey. The keyboard and every other gamepad stay
player 1's, so a one-pad setup, every log and every record are unchanged.
Whoever owns the pad sets both ports every vsync (a script leaves port 1
empty), since the shim's "connected" is part of a save state.
The frame log and the record trace port 1 when it is used ("I <frame> port 1
..." lines, inputs entries with "port": 1); the crash report names pad 2 when
one is connected. --input-test gains a players' part: a second virtual
gamepad, inputs on each pad and on both, player 2's gamepad hotkey chords
(reach pad 2, fire nothing), and the unplugs. hello tints its gradient from
pad 2; tests/hello_test.py --menu runs the self-test with "second" and
"first". The runtime's players are PORT_PADS arrays and the setting is
player<n>, so a multitap can add players later.
Part of #101 (phase 1 of 3: the runtime; the launcher's Controls screen and
the script/debug channel's port 1 follow).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gascarcella
deleted the
gascarcella/input-a-second-pad-port-1-for-two-player-games-l
branch
October 24, 2026 18:35
This was referenced Oct 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1 of #101: the runtime half of a second pad. Phases 2 (the launcher's and in-game menu's Controls screen) and 3 (port 1 for the script, debug channel, MCP and run.lua) come in separate PRs.
What
input.player2("off"default,"first","second"): that gamepad, by connection order (SDL instance ids), is player 2. It drives pad 2 (port 1) with the sharedinput.gamepadmap. Port 1 is connected only while that gamepad is there. The keyboard and every other gamepad stay player 1's. A bad value exits 64 like other settings. The launcher keeps the key when it writes the file (it keeps unknowninputmembers), so it can be set by hand before phase 2.I <frame> port 1 buttons 0x..../I <frame> port 1 none.inputs: port-1 entries get"port": 1(and"connected": falsewhen unplugged).port_framelog_input(port, connected, buttons). The game doesn't call it.pad 2:line when one is connected.--input-test, the players' part:"off": everything on port 0, port 1 empty)."first", the second virtual gamepad is attached first, so the main steps keep a player-1 gamepad.PORT_PADSarrays and the setting isplayer<n>(DECISIONS: "Player 2: a gamepad by connection order, off by default, never a hotkey").Gates that ran
tests/hello_test.py(picture hash unchanged) andtests/hello_test.py --menu: the input self-test with the defaults, then again withplayer2"second"and"first"; each reports 10 of 10 players' checks.--input-test --scriptwith"second": nothing sent, and the script's log is byte-identical to a run without the test.tests/tasks_test.py(plain,--sanitize,--m32),tests/shim_test.py(plain,--sanitize),game_gen_test,replay_test,sha256_test,psyq/check.sh --compile,py_compile.-DPSXSTACK_SDL=ON),tests/hello_test.py --exe --winepasses. By hand under Wine,--input-testwith"second"and"first"passes the players' part too (CI's Wine step doesn't run the input test).tests/port/run.pyat the pin and with-DPSXSTACK_DIR=this branch both pass. All logs, records, SPU traces and checkpoint dumps are byte-identical; the only differences are output paths insidereplay.script.Notes
🤖 Generated with Claude Code