Skip to content

Adopt optional RetroArch network output with input-delivery regressions - #6

Merged
jmonster merged 5 commits into
feat/browser-bridge-guardedfrom
feat/retroarch-network-gamepad
Sep 10, 2026
Merged

jmonster merged 5 commits into
feat/browser-bridge-guardedfrom
feat/retroarch-network-gamepad

Conversation

@jmonster

@jmonster jmonster commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Ready for review — optional RetroArch output, stacked on #5

Head 5df0f78577c79fb5ced13ca5d5e8f2d5e7732988. Exact-head macOS tests and actual app build passed.

Adapted with attribution from vialoh/switch2mac retroarch-network-gamepad at 2c7a396336f5a657a16a772b8c056d96ec6ff7f1. This PR follows #5 so the two app output registrations no longer conflict. Both optional features remain disabled by default.

The corrected sender preserves ordered button edges with a 256-edge per-player bound, coalesces analog positions separately, keeps inherited 60/s pacing, and explicitly neutralizes after overload rather than silently dropping releases. Full refreshes include zeros; disconnect/disable attempt repeated neutralization. Destination changes retire the old port before establishing new state. Cancelling a partially completed destination change now reasserts current state and resumes ordered edge delivery.

Nine actual-sink/real-loopback cases pass: packet bytes, complete taps, lost-release refresh, destination retirement, cancelled destination reset, disable, overflow/recovery, send failure and finite axes. The cancelled-reset case failed at 6879a31 and passes after eight added production lines. The app, protocol fixtures and browser tests are compiled/run together on macOS. The complete nine-PR integration test also passed.

Nintendo pairing, command bytes, GATT operations, decoding and keep-alives are unchanged. The legacy 20-byte protocol updates one control per datagram; it is not lossless or atomic, and UDP acceptance is not acknowledgement. It has no rumble return path and maps GameCube triggers to digital L2/R2 rather than full trigger fidelity. Per-report dispatch admission is not byte-bounded. No physical controller or RetroArch gameplay qualification is claimed.

Setup/provenance: docs/retroarch-integration.md. Merge #1 then #5, retarget this PR to main and recheck. #9 follows this PR. No merge, production signing or release performed.

…ion validation

Adapted from vialoh/switch2mac retroarch-network-gamepad at
2c7a396 (upstream PR #1).
Retain the contributor's opt-in default and attribution; validate actual
Swift builds and repair edge/lifecycle behavior before marking ready.
…nations

Retain the attributed optional fork output and existing remote_message bytes.
Replace latest-only button state with a bounded edge queue; overflow explicitly
neutralizes this output until disable/re-enable. Include zeros in periodic
refreshes and clear the old port before switching destinations. Reject nonfinite
axes and remove the imported Array safe-subscript compile failure.

Eight synthetic/real-loopback cases pass locally; the tap, release refresh,
destination, overflow and finite-axis cases fail against the imported source.
UDP acceptance is not acknowledgement; no physical-gameplay claim is made.
@jmonster
jmonster marked this pull request as ready for review September 9, 2026 18:31
…hange

A partially completed reset left switchIndex active when the user changed
back to the original port. Subsequent button edges were never queued.
Reassert the desired state and retire that reset; the new real-loopback
regression fails against the previous head and the nine-case suite passes.
Stack the RetroArch PR on the browser PR to remove their shared app-entry
conflict without enabling either optional output by default. Keep RetroArch
setup in its attributed integration document. No controller protocol changes.
#9)

Use io.github.jmonster.switch2mac and a distinct bundle name/defaults domain.
Keep upstream credits but reject default or saved update feeds and updater
entry points until a fork-specific signing/update trust path is established.

Require explicit signing identities, notary credentials and fork-matching
entitlements instead of silently consuming upstream signing configuration.
No certificate, profile, notarization request or release is created here.

Add metadata, actual feed-resolver and early signing-refusal regressions and
build the actual ad-hoc fork app in the existing read-only macOS check.
@jmonster
jmonster merged commit 3d6f413 into feat/browser-bridge-guarded Sep 10, 2026
1 check passed
@jmonster
jmonster deleted the feat/retroarch-network-gamepad branch September 10, 2026 00:01
jmonster added a commit that referenced this pull request Sep 10, 2026
* feat(browser): stage attributed browser bridge for guarded integration

Adapted from Andrei-Kondrykau/switch2mac browser-bridge at
24b0cd3 (upstream PR #2).
Keep the output sink unregistered until access and lifecycle guards are added.
Retain the contributor's source and documentation, with our read-only checks.

* fix(browser): guard replay, rumble ownership, and opt-in WebSocket access

Preserve complete connection/state replay after rename and reject obsolete
socket callbacks. Keep long effects alive only for their requested lifetime,
settle cancelled effects, and reject retired actuators. Eight deterministic
Node regressions cover these behaviors (seven fail on the imported source).

Add an opt-in settings window, exact extension-Origin checks, bounded clients
and messages, and per-client rumble ownership. GameCube HD rumble is withheld
using the existing model capability. Origin checks are not native-process
authentication. Exercise the actual Network.framework listener in macOS CI.

Adapted browser feature retains attribution to Andrei-Kondrykau's upstream
browser-bridge at 24b0cd3.

* fix(browser): distinguish validated rumble values from clamped magnitudes

* docs(browser): document fork opt-in setup and actual compatibility limits

* fix(browser): preserve bridged controllers when native gamepads hotplug

Move only a conflicting virtual index and announce the old/new indices,
without mutating prior snapshots or hiding the native device. A regression
fails against the previous shim and all nine Node cases pass after repair.

* Adopt optional RetroArch network output with input-delivery regressions (#6)

* feat(retroarch): import the optional network gamepad sink for regression validation

Adapted from vialoh/switch2mac retroarch-network-gamepad at
2c7a396 (upstream PR #1).
Retain the contributor's opt-in default and attribution; validate actual
Swift builds and repair edge/lifecycle behavior before marking ready.

* fix(retroarch): preserve edges, refresh releases and retire old destinations

Retain the attributed optional fork output and existing remote_message bytes.
Replace latest-only button state with a bounded edge queue; overflow explicitly
neutralizes this output until disable/re-enable. Include zeros in periodic
refreshes and clear the old port before switching destinations. Reject nonfinite
axes and remove the imported Array safe-subscript compile failure.

Eight synthetic/real-loopback cases pass locally; the tap, release refresh,
destination, overflow and finite-axis cases fail against the imported source.
UDP acceptance is not acknowledgement; no physical-gameplay claim is made.

* fix(retroarch): resume ordered input after cancelling a destination change

A partially completed reset left switchIndex active when the user changed
back to the original port. Subsequent button edges were never queued.
Reassert the desired state and retire that reset; the new real-loopback
regression fails against the previous head and the nine-case suite passes.

* fix(fork): isolate app identity and disable upstream automatic updates (#9)

Use io.github.jmonster.switch2mac and a distinct bundle name/defaults domain.
Keep upstream credits but reject default or saved update feeds and updater
entry points until a fork-specific signing/update trust path is established.

Require explicit signing identities, notary credentials and fork-matching
entitlements instead of silently consuming upstream signing configuration.
No certificate, profile, notarization request or release is created here.

Add metadata, actual feed-resolver and early signing-refusal regressions and
build the actual ad-hoc fork app in the existing read-only macOS check.
jmonster added a commit that referenced this pull request Sep 10, 2026
* test: add protocol fixtures and read-only macOS app build checks

* test: run isolated regression groups alongside protocol fixtures

* Adopt the browser bridge with replay, lifecycle, and access guards (#5)

* feat(browser): stage attributed browser bridge for guarded integration

Adapted from Andrei-Kondrykau/switch2mac browser-bridge at
24b0cd3 (upstream PR #2).
Keep the output sink unregistered until access and lifecycle guards are added.
Retain the contributor's source and documentation, with our read-only checks.

* fix(browser): guard replay, rumble ownership, and opt-in WebSocket access

Preserve complete connection/state replay after rename and reject obsolete
socket callbacks. Keep long effects alive only for their requested lifetime,
settle cancelled effects, and reject retired actuators. Eight deterministic
Node regressions cover these behaviors (seven fail on the imported source).

Add an opt-in settings window, exact extension-Origin checks, bounded clients
and messages, and per-client rumble ownership. GameCube HD rumble is withheld
using the existing model capability. Origin checks are not native-process
authentication. Exercise the actual Network.framework listener in macOS CI.

Adapted browser feature retains attribution to Andrei-Kondrykau's upstream
browser-bridge at 24b0cd3.

* fix(browser): distinguish validated rumble values from clamped magnitudes

* docs(browser): document fork opt-in setup and actual compatibility limits

* fix(browser): preserve bridged controllers when native gamepads hotplug

Move only a conflicting virtual index and announce the old/new indices,
without mutating prior snapshots or hiding the native device. A regression
fails against the previous shim and all nine Node cases pass after repair.

* Adopt optional RetroArch network output with input-delivery regressions (#6)

* feat(retroarch): import the optional network gamepad sink for regression validation

Adapted from vialoh/switch2mac retroarch-network-gamepad at
2c7a396 (upstream PR #1).
Retain the contributor's opt-in default and attribution; validate actual
Swift builds and repair edge/lifecycle behavior before marking ready.

* fix(retroarch): preserve edges, refresh releases and retire old destinations

Retain the attributed optional fork output and existing remote_message bytes.
Replace latest-only button state with a bounded edge queue; overflow explicitly
neutralizes this output until disable/re-enable. Include zeros in periodic
refreshes and clear the old port before switching destinations. Reject nonfinite
axes and remove the imported Array safe-subscript compile failure.

Eight synthetic/real-loopback cases pass locally; the tap, release refresh,
destination, overflow and finite-axis cases fail against the imported source.
UDP acceptance is not acknowledgement; no physical-gameplay claim is made.

* fix(retroarch): resume ordered input after cancelling a destination change

A partially completed reset left switchIndex active when the user changed
back to the original port. Subsequent button edges were never queued.
Reassert the desired state and retire that reset; the new real-loopback
regression fails against the previous head and the nine-case suite passes.

* fix(fork): isolate app identity and disable upstream automatic updates (#9)

Use io.github.jmonster.switch2mac and a distinct bundle name/defaults domain.
Keep upstream credits but reject default or saved update feeds and updater
entry points until a fork-specific signing/update trust path is established.

Require explicit signing identities, notary credentials and fork-matching
entitlements instead of silently consuming upstream signing configuration.
No certificate, profile, notarization request or release is created here.

Add metadata, actual feed-resolver and early signing-refusal regressions and
build the actual ad-hoc fork app in the existing read-only macOS check.

* Neutralize disconnected UDP controllers and bound subscriber processing (#4)

* fix(udp): neutralize disconnected slots and bound subscriber handling

* test(udp): synchronize real datagram arrival before subscriber assertions

* Fix session response matching, fallback sticks, and GameCube motor gating (#3)

* fix(session): preserve command correlation and respect model capabilities

* fix(session): retire callbacks before teardown and require usable input for readiness (#8)

Guard late notifications, queued commands and timers after session retirement.
Clear notify completion before invocation to preserve reentrant replacement.
Require isNotifying on essential channels and one existing-decoder input report
before readiness, retaining the established keep-alive and handshake bytes.

Eleven synthetic production-session tests pass locally; five new targeted
cases fail against the prior session source. Full Apple-framework build and
regressions remain the hosted gate. No new connection deadline or protocol.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant