DOOM rendered on a hardware oscilloscope via sound card
ScopeDoom renders DOOM's 3D world as wireframe vector graphics on a real oscilloscope. It uses your computer's sound card as a dual-channel DAC - the left channel drives the X-axis, the right channel drives the Y-axis, and the scope displays in X-Y mode.
DOOM Engine (C)
|
| Extract walls & entities as vectors
v
Unix Domain Socket
|
| JSON: {walls: [...], entities: [...]}
v
doom_scope.py (Python)
|
| Convert to X-Y point stream
v
Sound Card (44.1kHz stereo)
|
| Left = X, Right = Y
v
Oscilloscope (X-Y Mode)
- doom_scope.py - Main renderer that receives DOOM vectors and outputs audio
- scope_capture.py - Capture oscilloscope screenshots via VXI-11 (Siglent scopes)
- scope_output.py - Test patterns (squares, circles) for scope calibration
- doom/source/ - Modified DOOM engine with vector extraction
- Computer with 3.5mm audio output (or USB audio interface)
- Oscilloscope with X-Y mode
- Two load resistors (1k ohm recommended)
- Audio cable (3.5mm to bare wires or RCA)
MacBook Pro 3.5mm Jack
|
+--- Left (Tip) ----[1k]----+---- CH1 (X)
| |
+--- Right (Ring) --[1k]----+---- CH2 (Y)
| |
+--- Ground (Sleeve) -------+---- GND
- Mode: X-Y
- Channel 1: X input (left audio)
- Channel 2: Y input (right audio)
- Scale: Start at 500mV/div, adjust as needed
- Coupling: DC or AC (AC removes DC offset from audio)
# Generate test patterns (no DOOM needed)
python3 scope_wav_test.py
afplay scope_square.wav # Should show a square on scope# Terminal 1: Start the scope renderer
python3 doom_scope.py
# Terminal 2: Launch DOOM (from doomgeneric build)
./doomgeneric_kicad -w 1 1- Controls work in the SDL window
- Scope displays wireframe view in real-time
- WASD to move, arrows to turn, Ctrl to fire
ScopeDoom requires a modified DOOM engine that extracts vector data. See doom/source/build.sh for build instructions.
The key modification is extracting wall segments (drawsegs[]) and sprite positions (vissprites[]) and sending them over a Unix socket as JSON.
| Metric | Value |
|---|---|
| Sample Rate | 44,100 Hz |
| Points per Frame | ~5,000-10,000 |
| Effective Refresh | 4-8 Hz |
| Walls Rendered | 30-50 typical |
| Entities Rendered | 0-10 |
The refresh rate depends on scene complexity. More walls/entities = more points = slower refresh. But it's still playable!
pip install sounddevice numpyOptional (for scope screenshots):
pip install python-vxi11ScopeDoom/
├── doom_scope.py # Main DOOM-to-scope renderer
├── scope_capture.py # Oscilloscope screenshot capture
├── scope_output.py # Test pattern generator
├── scope_wav_test.py # WAV file test patterns
├── assets/ # Screenshots and demos
└── doom/source/ # Modified DOOM engine source
- DC Offset - Mac audio has DC bias, image may not be centered
- Visible Retrace - No Z-axis blanking, beam movement visible
- Aliasing - Limited sample rate causes stepping on diagonals
- Z-axis blanking with 3-channel audio interface
- Higher sample rate (96kHz/192kHz audio)
- Optimize point ordering to minimize retrace
- Add simple HUD elements
- DOOM by id Software
- doomgeneric portable DOOM
- Inspired by oscilloscope music artists and Vectrex DOOM
GPL (inherits from DOOM source code)

