Two more sigil-retropie commits extend P2 local controller support from the initial NES/SNES/Genesis/SMS batch to 9 more systems. 8e0de8d wires Colecovision, Neo Geo, Atari 2600, and SG-1000. 5eaf9fd wires MSX, C64, PCE, and CPS (CPS-1/2/3 arcade). The EL0 pattern is identical across all systems: sys3(44, 1, 0, 0) reads P2, core_set_input_port(1, btn2) routes it to the core. The differences are all in the hardware register ABIs.
8e0de8d — Coleco / Neo Geo / Atari 2600 / SG-1000
cores/coleco.sg
ColecoVision joystick ports $FC/$FF. ColecoVision has two joystick connectors accessed via I/O ports $FC (P1 column 0 read), $FD (P1 column 1), $FE (P2 column 0), $FF (P2 column 1).
core_set_input_port(0, btn) writes P1 buttons to col_io()+1 ($FC stub offset); core_set_input_port(1, btn2) writes P2 to col_io()+2 ($FE offset). Standard 8-bit active-low normalized bitmask — the ColecoVision column encoding is absorbed by the core's read8 intercept at those ports.cores/neogeo.sg
Neo Geo P1/P2 memory-mapped pads at $10FDFE/$10FFFE. Neo Geo pads are memory-mapped, not I/O-mapped. P1 pad at
$10FDFE, P2 at $10FFFE. The stub's gn_read8 previously served only WRAM for this range. 8e0de8d adds an intercept: reads at $10FDFE return ng_pad_lo(0) (P1), reads at $10FFFE return ng_pad_lo(1) (P2), before falling through to the WRAM catch-all. ng_pad_lo(port) converts the normalized active-high bitmask to Neo Geo active-low format (same inversion as Genesis gn_pad_lo). core_set_input_port(0/1, btn) stores buttons at ng_st()+8 / ng_st()+9.cores/atari.sg
Atari 2600 SWCHA register P1/P2 bit lanes. The Atari 2600 has a single SWCHA register for both joysticks. P1 direction bits are in the high nibble (bits 7-4); P2 direction bits are in the low nibble (bits 3-0). Fire buttons are in SWCHB.
core_set_input_port(0, btn) writes bits 7-4 via read-modify-write on SWCHA; core_set_input_port(1, btn2) writes bits 3-0 via read-modify-write on SWCHA. The read-modify-write is critical — a plain write to SWCHA would clobber the other player's state. Active-low per Atari 2600 hardware spec. el0/atari_app.sg updated.cores/sg1000.sg
SG-1000 I/O $DC/$DD (same layout as SMS). The SG-1000 uses the same I/O-mapped controller layout as the Sega Master System: P1 at
$DC, P2 at $DD. core_set_input_port(0, btn) writes P1 to sg_io()+0; core_set_input_port(1, btn2) writes P2 to sg_io()+1. This is simpler than the SMS split-port model because the SG-1000 doesn't multiplex joystick bits across two ports.5eaf9fd — MSX / C64 / PCE / CPS
cores/msx.sg
MSX PSG R14/R15 joystick rows. MSX joystick ports are read through AY-3-8910 PSG registers R14 (P1 read) and R15 (P2 read). The TMS9918 state area at
tms_st tracks PSG state. core_set_input_port(0, btn) writes normalized bitmask to tms_st+25 (R14); core_set_input_port(1, btn2) writes to tms_st+26 (R15). MSX2 shares the same core; el0/msx2_app.sg updated alongside el0/msx_app.sg.cores/c64.sg
C64 CIA port A/B joystick input ($DC00/$DC01). The Commodore 64 reads joysticks through CIA 1: P1 at
$DC00 (CIA port A), P2 at $DC01 (CIA port B). Active-low: bit 0 = up, 1 = down, 2 = left, 3 = right, 4 = fire. core_set_input_port(0, btn) writes P1's normalized bitmask (inverted) to $DC00; core_set_input_port(1, btn2) writes P2 to $DC01. The full CIA keyboard matrix scan remains a follow-up; joystick reads are served correctly without it.cores/pce.sg
PC Engine joypad latches. PCE uses memory-mapped joypad latches in the PCE hardware block. P1 at
pce_hw+24, P2 at pce_hw+25. core_set_input_port(0, btn) writes P1 to pce_hw+24 via poke8; core_set_input_port(1, btn2) writes P2 to pce_hw+25. el0/pce_cd_app.sg (PC Engine CD) updated alongside el0/pce_app.sg.cores/cps.sg
CPS arcade IN0/IN1 inputs ($800000/$800002). CPS-1/2/3 arcade hardware maps player inputs at memory address
$800000 (P1 IN0) and $800002 (P2 IN1). cps_inputs2() / cps_set_inputs2() access cps_st+16 (P2 state). gn_read8 intercepts reads at $800002 and $800003 — returning P2 button state before falling through to normal memory. core_set_input_port(0, btn) → IN0; core_set_input_port(1, btn2) → IN1 / cps_st+16. CPS2 and CPS3 share the same core; el0/cps2_app.sg and el0/cps3_app.sg updated alongside el0/cps_app.sg.2P status after both waves
NES ✅ · SNES ✅ · Genesis ✅ · SMS ✅ · Colecovision ✅ · Neo Geo ✅ · Atari 2600 ✅ · SG-1000 ✅ · MSX/MSX2 ✅ · C64 ✅ · PC Engine/CD ✅ · CPS-1/2/3 ✅