Streams a PC's screen to an original Xbox, which displays it over RGB SCART. 640x480, 1:1, no rescaling, 60 fps, with audio.
The Xbox is the display endpoint, not a media player: its analog output is broadcast-spec, so a CRT that rejects PC timings will accept it.
- An original Xbox, softmodded or modchipped. Nothing here is signed.
- RGB SCART to the television. Only sync timing matters — R, G and B are on separate pins, so PAL vs NTSC colour encoding is irrelevant, and the TV takes 60 Hz.
- A wired LAN between PC and Xbox. The stream runs at up to ~67 Mbit/s.
- Windows XP or Windows 10/11 on the capture side.
- MSYS2 with the MinGW toolchains to build; nxdk to build the client.
Server, from an MSYS2 shell — -mingw64 for Windows 10/11, -mingw32 for XP,
where 32-bit is mandatory:
make -C pc-serverHook DLLs, always from -mingw32 because the games are 32-bit:
make -C hookXbox client, from -mingw64 with NXDK_DIR pointing at your nxdk checkout:
bash client-xbox/build.shLaunch wsclient on the Xbox from your dashboard. It prints its own IP and
waits. Then, from the PC:
pc-server/xboxstreamer-server.exe --scale --host <XBOX_IP>--host is required and there is no default. A wrong address cannot be
detected — UDP has nothing to reject against — so the server runs, reports
frames, and the TV stays black.
--scale fits a larger source into 640x480 instead of cropping it to the
top-left corner. Without it, a 4K desktop streams a 640x480 corner of itself.
docs/USAGE.md is the reference: every option, how to find the Xbox's address, how to install the client, and what each line of output means.
Desktop Duplication cannot capture an exclusive-fullscreen game — while a game
owns the display, the desktop is not available to duplicate. Such games are
captured from inside the process instead, by a proxy DLL placed next to the
game's executable. Copy the one matching the API the game presents with, plus
hook/xboxstreamer-hook.ini, into the game's folder, and run the server with
--capture hook:
| Game uses | Drop in | Confirmed against a real game |
|---|---|---|
| DirectDraw / D3D6-7 | hook/ddraw.dll |
Yes |
| OpenGL | hook/opengl32.dll |
Yes |
| Direct3D 8 | hook/d3d8.dll |
No — passes its PC harness only |
| Direct3D 9 | hook/d3d9.dll |
No — passes its PC harness only |
Nothing is installed or registered; Windows searches the application directory
before system32, so deleting the file undoes it. --capture hook is safe to
leave on permanently — with no hooked game running it captures the desktop, and
switches over when one starts.
PC ─ capture ─→ DXT1 encode ─→ block delta ─→ UDP ─→ Xbox ─→ NV2A ─→ SCART ─→ CRT
0.4-7 ms 0.6-1.0 ms changed LAN texture upload
blocks only (DXT1 decoded free)
Four constraints shape it, each trading bandwidth for latency:
- DXT1 is the codec. The NV2A decodes it in the texture unit at no cost: no decode time, no decode latency, a fixed 4:1 ratio, and no frame buffering anywhere. A real video codec would be far smaller on the wire and would reintroduce the delay this exists to avoid.
- Only changed blocks are sent. Each frame is diffed against the last in 4x4 DXT1 blocks; a periodic keyframe bounds how long a lost packet can leave a block stale.
- No retransmission. A lost packet leaves those blocks stale until their next update.
- Input is not streamed. The controller plugs into the PC.
Audio is raw 48 kHz stereo PCM, ~1.5 Mbit/s, for the same reason. SCART carries it on the same cable as the picture.
| Network ceiling | 96 Mbit/s, zero loss — the Xbox saturates its 100 Mbit NIC |
| DXT1 encode | 0.6-1.0 ms per frame, against a 16.7 ms budget |
| Capture | 0.4 ms (Desktop Duplication), 4-7 ms (GDI on XP) |
| Idle desktop | ~1.2 Mbit/s, almost all of it the periodic keyframe |
| Real motion | 7-12.6 Mbit/s at 60 fps |
| A game, full screen | 54-67 Mbit/s at 60 fps, no partial, late or dropped frames at the client |
End-to-end latency is unmeasured. Every figure in the latency budget in docs/DESIGN.md is an estimate except the encode.
pc-server/ |
Capture backends, DXT1 encode, block delta, packetizer, UDP, audio |
client-xbox/ |
lwIP receive, texture upload, fullscreen quad, AC97 audio |
client-core/ |
Portable C99 stream reassembly, shared with the client, tested on the PC |
hook/ |
The four proxy DLLs, and a fake game for each to test against |
protocol/ |
Wire format |
tests/ |
340 checks |
client-core has no platform calls, so the whole reassembly path is tested on
the PC with no console involved:
make -C tests runtests/check-portability.sh also compiles client-core with nxdk's clang,
confirming it builds unmodified for the Xbox. make -C hook test runs all four
proxy harnesses, each verifying the published pixels rather than merely that
nothing crashed.
| docs/USAGE.md | Building, running, every option, reading the output, troubleshooting |
| docs/DESIGN.md | Architecture, bandwidth arithmetic, latency budget |
| docs/PROTOCOL.md | Wire format, normative |
| docs/FINDINGS.md | Measurements, and approaches that were tried and rejected |
d3d8andd3d9have never run against a real game; both pass their PC harnesses.ddrawandopengl32are confirmed on hardware.- End-to-end latency is unmeasured.
- Audio dropouts on XP are not fully closed; the client overlay's underrun counter is the diagnostic.
--capture d3d9is unusably slow on some drivers — see docs/USAGE.md.
MIT — see LICENSE.