What this system is designed to solve
Today, an emulator usually assumes its input devices and display are attached to the same computer. Networked Shared Sessions extends Phlegmulator so people on other computers can see the running emulated machine, hear its audio, and operate assigned controls over a local network or the internet.
The host runs the emulator. Guests do not run an independent copy of the emulated hardware; instead, their keyboards, gamepads, joysticks, and other devices are converted into authorized virtual input signals at the host.
Because there is only one emulated machine, all users interact with the same memory contents, running program, and game or application. A guest may experience slightly more video delay than another guest because of network conditions, but the underlying machine state is shared and authoritative.
How the pieces connect
Single-host session model
Virtual input ports · Session manager
Display + audio → Guests
Control messages ↔ Both
↓ MULTIPLE CONNECTED PARTICIPANTS ↓
Host
Executes microcode and machine hardware; receives authorized virtual control states; produces frames and audio.
Connection service
Helps guests find and securely connect to a host. Direct peer connections are preferred when possible.
Guests
Decode media, display the session, and send changes from one or more physical devices.
A session is tied to a running emulator instance, not merely to a downloadable machine definition. The existing Hosted Definitions feature remains separate: it discovers or downloads machine definitions, while Network Sessions finds and joins active emulation sessions.
Multiple physical devices, one virtual hardware interface
Clients can attach keyboards, mice, digital/analog joysticks, modern gamepads, touch controls, and machine-specific peripherals where the selected machine supports them. One client may contribute more than one device. Devices receive session-scoped identifiers, so two guests with identical controllers are not confused.
| Participant | Local hardware | Host assignment | Can watch? |
|---|---|---|---|
| Host | Keyboard | Emulated keyboard | Yes |
| Guest A | Gamepad | Port 1 | Yes |
| Guest B | Gamepad | Port 2 | Yes |
| Guest C | Joystick | Port 1 (shared) | Yes |
| Guest D | No controller | Spectator | Yes |
Controller capacity depends on the emulated machine and its configured peripherals, not on the number of people allowed to connect. For instance, two standard SNES controller ports do not automatically become four ports because four guests joined. A data-defined multitap can legitimately expand hardware capacity.
Keep machine behavior in .phlegm definitions
The network layer should be generic. It must not include special cases for the Commodore keyboard, NES controller shift registers, or SNES ports. Instead, the machine's existing or extended .phlegm files describe the input hardware, while a separate mapping layer translates remote physical devices into those hardware interfaces.
| Owned by the machine definition | Owned by the session or device profile |
|---|---|
| Port count, controller types, register mappings | Which person/device is assigned to each port |
| Keyboard matrix and scan behavior | Which host/guest keyboard keys map to virtual keys |
| Polling and latch behavior | Transport format, update cadence, connection status |
| Multitap or expansion-device capabilities | Permission, arbitration policy and priority |
Illustrative design schema — NOT existing .phlegm syntax
machine.input_interfaces:
keyboard:
type: matrix
source: <machine-defined matrix and scan rules>
controller_port_1:
compatible_devices: <defined controller types>
source: <machine-defined electrical/register behavior>
controller_port_2:
compatible_devices: <defined controller types>
source: <machine-defined electrical/register behavior>
session.assignments:
guest-A/gamepad-0: controller_port_1
guest-B/gamepad-0: controller_port_2
guest-C/keyboard-0: keyboard
The example expresses the division of responsibility. The actual serialization must match PHLEGM v10's real definition grammar and compiler/runtime interfaces.
What happens when two people control the same device?
For each emulated input device, the host maintains an authoritative current state. Inputs may be assigned exclusively to one user, shared among several users, or not assigned at all for spectators.
Exclusive
Only the selected participant can change the device state. Best for competitive multiplayer.
Shared
Multiple participants jointly operate one emulated keyboard or controller, using configured merging rules.
Spectator
A guest watches and listens but cannot influence hardware until the host grants input access.
Host override
The host can release a controller, move it to another guest, deny access, or disconnect a participant.
| Input type | Suggested default merge | Reason |
|---|---|---|
| Ordinary digital buttons/keys | Pressed if any authorized contributor holds the control | Allows collaborative keyboard and button use. |
| Opposing directions (left/right, up/down) | Neutralize simultaneous opposites, unless machine policy overrides | Avoids contradictory directional states. |
| Analog axes | Exclusive owner or priority-based active contributor | Prevents unnatural summed or averaged joystick movement. |
| Mouse / pointer | Single active owner by default | Prevents multiple cursors fighting over one virtual pointer. |
Button presses should be tracked per contributing device. If Guest A holds a key and Guest B releases the same key, the combined key should remain held until A also releases it. On disconnect, revocation, or device reassignment, the host removes only that contributor's held states—preventing stuck keys without erasing another user's input.
Live display visible to every shared user
The host captures the emulator's completed framebuffer or equivalent final video surface after emulated video hardware has produced a frame. That image is sent to a media encoder, distributed to connected clients, and displayed in their viewing windows.
This is not desktop screen sharing. Remote users should not see the host's unrelated windows, notifications, other monitors, or private applications. They see only the designated emulated display.
- Same content: everyone views output from the same host machine state. Individual playback delay may differ by client.
- Native image behavior: retain the machine's aspect ratio, refresh characteristics, pixel geometry, and display timing. Do not stretch a 4:3 framebuffer into 16:9 by default.
- Client scaling: each guest independently chooses windowed/fullscreen and nearest-neighbor or other supported scaling.
- Spectators included: a guest without an input assignment still receives video and, if enabled, audio.
- Adaptive quality: lower the transmitted resolution, bitrate, or streamed frame rate for poor connections without altering emulated CPU/PPU timing.
- No stale backlog: if a viewer falls behind, skip old network video frames instead of delaying the host machine.
Share the APU output alongside video
The completed mixed audio from the emulated APU is routed to local playback as usual and, independently, into a network audio encoder. Opus is a sensible candidate for interactive network playback; the exact codec and integration should follow the selected native media stack.
Each guest should have a local volume/mute control. Host-generated audio/video presentation timestamps keep sound aligned with the corresponding emulated display. A small bounded client jitter buffer can smooth network variation, with a user-selectable tradeoff between delay and stability.
For systems with no audio device or when sound sharing is disabled, the rest of the shared session continues to work. Remote audio must not block the emulated APU or change its timing.
Different traffic needs different handling
| Logical channel | Direction | Behavior |
|---|---|---|
| Session control | Both ways | Reliable ordered delivery for join/leave, role grants, assignments, configuration and host commands. |
| Live input | Guest → host | Low latency; sequence numbers and full-state refreshes; stale states are discarded rather than queued indefinitely. |
| Display/audio | Host → guests | Real-time encoded streams; bounded buffering; prefer recent playback over perfect delivery of old frames. |
Recommended transport: evaluate a native WebRTC implementation for encrypted media, data channels, and NAT traversal. WebRTC is a design recommendation, not a claim that PHLEGM already includes this functionality. Other native transports are possible if they satisfy the latency and security requirements.
LAN: permit directly joined hosts and optional local discovery. Internet: use signaling plus ICE/STUN/TURN where needed for connections across routers and firewalls. A relay may be required on restrictive networks. Session discovery services do not need to execute the emulated machine.
A native client should require no JavaScript in the emulator's runtime path. An optional browser client would naturally use browser technologies for media and controller access, but must not dictate the native implementation.
Handling latency without breaking emulation
Client inputs arrive later than local inputs; that delay cannot be eliminated entirely over the internet. The design goal is to minimize it, avoid stale input, and preserve hardware-accurate polling on the host.
- Client detects a change. Button, axis, keyboard, or pointer state changes are converted using the active device mapping.
- Client sends a numbered state update. Include session/device identity, assignment generation, sequence number, and input values; client timestamp is useful for diagnostics but not trusted as authoritative host time.
- Host checks permission and freshness. Reject invalid, obsolete, duplicate, oversize, or unauthorized data before it reaches the emulated machine.
- Host applies input at a defined boundary. Update the virtual device state at the normal point where the emulated hardware reads or latches control signals, without waiting for an acknowledgment.
- Host streams the result. The next relevant video/audio output is captured and sent to viewers with presentation timestamps.
Conceptual input-state message
{
protocol_version: 1,
session_id: <opaque session ID>,
device_id: <connection-scoped ID>,
assignment_revision: <number>,
sequence: <increasing number>,
buttons: <bitset>,
axes: <normalized values>,
pointer: <optional motion/position>,
client_time: <diagnostic monotonic timestamp>
}
Authentication: established secure connection, NOT claimed fields.
Send immediate state changes plus periodic snapshots for loss recovery. When a connection ends or an input lease expires, the host releases that participant's contributions. Keep jitter/input queues bounded. Avoid rollback or speculative emulation in the first version; those techniques introduce complexity and can be assessed later if measurements justify them.
New Network Sessions interface
Add a Network Sessions area to Phlegmulator, clearly separate from Hosted Definitions. The host can start a session, generate an invitation, view participants, grant input access, assign controller ports, toggle audio/video sharing, and end the session. Guests can discover or join a session, inspect device mappings, adjust their own viewer settings, and leave.
| GUI control | Purpose |
|---|---|
| Host / Join Session | Create or connect to an active shared emulator instance. |
| Connected Users | View guests, roles, and connection health. |
| Input Devices | List devices local to each participant and their session assignments. |
| Assign / Revoke | Change virtual controller, keyboard, or pointer ownership. |
| Shared Display / Audio | Manage streaming policy and local playback controls. |
| Invite / Disconnect / End | Control session admission and termination. |
| Diagnostics | Monitor RTT, packet loss, encode time, stream FPS, and input-to-display delay estimates. |
Access rule: a client given input permissions should automatically receive the session's live display. Otherwise, they would be operating a machine whose response they cannot see. A policy that deliberately disables display sharing should also disable remote interactive control or clearly reject the configuration.
Let guests control hardware, not the host computer
The host is always the authority for joining, device assignment, role changes, resets, and other privileged operations. Each connection has an authenticated session identity with an explicit role. Invitations should be unguessable, revocable and preferably time-limited.
- Encrypt traffic; verify authenticated peers and message integrity.
- Allow spectators without implicitly granting input.
- Require explicit host authorization before enabling any remote device control.
- Validate input payload lengths, device types, assignment revisions, and update rates.
- Reject remote commands that attempt filesystem access, script execution, arbitrary memory changes, or compiler control.
- Do not send ROMs, cartridge/program images, machine files, or unrelated host data just to enable viewing.
- Expose only the emulated framebuffer and optional audio—not the entire desktop.
Keep network work off the emulation hot path
PHLEGM's interpreter, microcode execution, and hardware timing should not wait on internet traffic. Network functions should be connected by bounded, nonblocking queues and independently scheduled workers. The following responsibilities are logical partitions, not a requirement to create exactly six operating-system threads.
| Responsibility | Constraint |
|---|---|
| Emulation / microcode | Remains authoritative and timing-correct. |
| Local rendering | Continues when networking is slow or absent. |
| Input reception | Checks and stages only current valid states. |
| Media capture/encoding | Operates asynchronously; never blocks the emulated video/audio hardware. |
| Network transmission | Uses bounded buffers and rate adaptation. |
| Session control | Maintains authenticated roles, permissions, and lifecycle state. |
For small groups, encode one suitable common stream and fan it out rather than encoding identical output separately for each user. If guests have vastly different bandwidth, add a small number of quality tiers or adaptive layers. Large spectator audiences could later use a relay/SFU rather than multiplying the host's upload load indefinitely.
Build it in measurable phases
Phase 1 — Virtual input boundary and LAN sessions
Extract machine-independent input adapters, device identities, host-side arbitration, permission checks, and basic local-network connections. Demonstrate two remote controllers operating one host machine.
Phase 2 — Shared display
Add completed-frame capture, native encoding, media distribution, and a guest viewer. Every permitted guest sees the same machine output without desktop capture.
Phase 3 — Shared audio and sync
Stream emulated APU output with timestamped presentation and bounded buffering. Validate that guest playback does not affect emulation timing.
Phase 4 — Internet connectivity and security hardening
Add signaling, secure invitations, authentication, NAT traversal, relaying when required, and comprehensive malformed-packet handling.
Phase 5 — Optional browser viewer
Provide audiovisual viewing and gamepad/keyboard input in a browser, separately from the native emulator runtime.
Phase 6 — Advanced multiuser controls
Improve per-user quality settings, collaborative inputs, large spectator sessions, host administration, and instrumented latency diagnostics.
Phases are a proposed development sequence, not a statement that these components are already implemented.
What would prove the design works?
| Test | Pass condition |
|---|---|
| Two remote controllers | Each user controls a different data-defined port on the same running machine. |
| Shared controller | Contributors merge correctly; releasing one user does not release another's held button. |
| Shared keyboard | Multiple authorized keyboards use the machine's real keyboard matrix behavior. |
| Spectator | A viewer with no device assignment can still see display and hear enabled audio. |
| Same machine output | All guests view frames derived from the host's one emulated framebuffer, with no separate guest emulation. |
| Disconnect / revoke | Only the departing participant's input contributions are cleared; no stuck keys. |
| Packet loss / jitter | Outdated input is discarded, snapshots recover states, and media degrades gracefully. |
| Slow viewer | The remote stream may skip frames, but host emulation timing and local display remain stable. |
| Data-driven device expansion | Machine-defined expansion peripherals increase ports without new network-specific code. |
| Permission attack | A spectator cannot inject controls, write memory, request host files, or run scripts. |
Representative machine tests should include a Commodore PET keyboard matrix, Commodore 64 keyboard/joystick, NES dual controllers, and SNES controllers with and without a data-defined multitap. These test targets must use real machine definitions rather than hand-built networking shortcuts.
One machine. Many operators. A shared view.
The architecture separates emulated hardware behavior from remote device transport and audiovisual distribution. That separation is what keeps the feature scalable, reusable, and consistent with PHLEGM v10's data-driven design.
Remote users connect to a session, watch the host's actual emulated display, hear its audio if enabled, and provide inputs that the host maps to ordinary virtual hardware ports. The host remains authoritative, handles conflicts and permissions, and never lets media encoding or networking interrupt execution.
.phlegm definitions.Status: design explanation only. This document does not modify PHLEGM v10 source code, define final wire protocols, or claim networking support already exists.