[HN Gopher] Show HN: KiDoom - Running DOOM on PCB Traces
       ___________________________________________________________________
        
       Show HN: KiDoom - Running DOOM on PCB Traces
        
       I got DOOM running in KiCad by rendering it with PCB traces and
       footprints instead of pixels.  Walls are rendered as PCB_TRACK
       traces, and entities (enemies, items, player) are actual component
       footprints - SOT-23 for small items, SOIC-8 for decorations, QFP-64
       for enemies and the player.  How I did it:  Started by patching
       DOOM's source code to extract vector data directly from the engine.
       Instead of trying to render 64,000 pixels (which would be
       impossibly slow), I grab the geometry DOOM already calculates
       internally - the drawsegs[] array for walls and vissprites[] for
       entities.  Added a field to the vissprite_t structure to capture
       entity types (MT_SHOTGUY, MT_PLAYER, etc.) during
       R_ProjectSprite(). This lets me map 150+ entity types to
       appropriate footprint categories.  The DOOM engine sends this
       vector data over a Unix socket to a Python plugin running in KiCad.
       The plugin pre-allocates pools of traces and footprints at startup,
       then just updates their positions each frame instead of
       creating/destroying objects. Calls pcbnew.Refresh() to update the
       display.  Runs at 10-25 FPS depending on hardware. The bottleneck
       is KiCad's refresh, not DOOM or the data transfer.  Also renders to
       an SDL window (for actual gameplay) and a Python wireframe window
       (for debugging), so you get three views running simultaneously.
       Follow-up: ScopeDoom  After getting the wireframe renderer working,
       I wanted to push it somewhere more physical. Oscilloscopes in X-Y
       mode are vector displays - feed X coordinates to one channel, Y to
       the other. I didn't have a function generator, so I used my
       MacBook's headphone jack instead.  The sound card is just a dual-
       channel DAC at 44.1kHz. Wired 3.5mm jack - 1kO resistors - scope
       CH1 (X) and CH2 (Y). Reused the same vector extraction from KiDoom,
       but the Python script converts coordinates to +-1V range and
       streams them as audio samples.  Each wall becomes a wireframe box,
       the scope traces along each line. With ~7,000 points per frame at
       44.1kHz, refresh rate is about 6 Hz - slow enough to be a
       slideshow, but level geometry is clearly recognizable. A 96kHz
       audio interface or analog scope would improve it significantly
       (digital scopes do sample-and-hold instead of continuous beam
       tracing).  Links:  KiDoom GitHub:
       https://github.com/MichaelAyles/KiDoom, writeup:
       https://www.mikeayles.com/#kidoom  ScopeDoom GitHub:
       https://github.com/MichaelAyles/ScopeDoom, writeup:
       https://www.mikeayles.com/#scopedoom
        
       Author : mikeayles
       Score  : 317 points
       Date   : 2025-11-25 22:13 UTC (1 days ago)
        
 (HTM) web link (www.mikeayles.com)
 (TXT) w3m dump (www.mikeayles.com)
        
       | robbru wrote:
       | Of course I love this. DOOM forever.
        
       | Lerc wrote:
       | One of my to-do-one-day projects is an audio jack display system
       | out of a Microcontroller.
       | 
       | Was never quite sure if I should raw XY it or soft modem so I
       | could decode on a web page on a handy device.
        
         | retrac wrote:
         | > raw XY it or soft modem
         | 
         | How about analog raster scan? a.k.a. slow-scan TV? [0] Like how
         | they returned the live television images from the Apollo
         | missions. (They only had 1 MHz of bandwidth for everything -
         | voice, computer up and downlink, telemetry, and TV. Standard
         | analog broadcast TV was 6 MHz. So they reduced the scan rate to
         | 10 frames per second instead of 60, and halved the horizontal
         | line resolution -- that could fit in 500 kHz.)
         | 
         | Most modern SSTV standards are super-narrowband, designed to
         | fit into just a few hundred Hertz for amateur radio. But what
         | if you had the full 20 kHz of bandwidth of a nice audio
         | channel? With 100 horizontal lines per frame, and 1 frame per
         | second -- that is about 200 cycles per horizontal line, or
         | enough to resolve, in theory, 100 vertical lines on each
         | horizontal line. I.e., 100 x 100 pixels (ish) at 1 fps.
         | 
         | [0] https://en.wikipedia.org/wiki/Slow-scan_television
        
           | Lerc wrote:
           | Now that does present some interesting possibilities.
           | 
           | It looks like a web page with audio input permissions can be
           | expected to sample at 48KHz I wonder what the quality is like
           | from a cable bodged off a spare pin.
           | 
           | A little webapp running on your phone could actually do some
           | nifty on-the-fly display.
        
       | mlhpdx wrote:
       | I don't care how this makes the world a better place, because it
       | just does.
        
       | djmips wrote:
       | This is just a meme now. Doom running on X. I don't get it but
       | congratulations on your very whimsical accomplishment!
        
         | sethaurus wrote:
         | This is a little different from most "Doom on X" projects,
         | because the accomplishment is less about the hardware (it's
         | just a normal computer) and more about turning a circuit-board
         | designer into a real-time game display.
        
           | djmips wrote:
           | That's very cool. A very good use of your free time. The
           | world needs more whimsy!
        
           | wpm wrote:
           | Just like Doom running on Factorio combinators.
           | 
           | https://www.youtube.com/watch?v=0bAuP0gO5pc
        
             | ant6n wrote:
             | Wir a Minute, that's Wolfenstein! (Raycasting)
        
         | nurettin wrote:
         | I wish doom ran on X.
        
           | sho_hn wrote:
           | Sorry, only Wayland allowed.
        
             | georgefrowny wrote:
             | Funnily enough, Wayland doesn't support KiCad very well.
             | https://www.kicad.org/blog/2025/06/KiCad-and-Wayland-
             | Support...
        
         | georgefrowny wrote:
         | Doom on X (or rather "Can it run Doom?") is one of the original
         | internet memes, dating way back to the 90s.
        
       | sho_hn wrote:
       | Love ScopeDoom!
       | 
       | KiDoom I don't fully get. The website says "All components
       | connected to a shared net; the PCB could be sent to a fab house
       | (it just wouldn't do anything useful)" but I don't see any of the
       | component pins hooked up in the demo video.
        
         | hbnjjgff wrote:
         | What don't you get? The pins are not hooked up, so the PCB
         | wouldn't do anything useful
        
           | sho_hn wrote:
           | It means they're not actually "all connected to a shared
           | net", no?
           | 
           | Something that actually connects the components and routes
           | the traces in a way that makes it somehow still recognizable
           | as the 3D environment would've been cool, otherwise this is
           | kind of just like piping draw commands into a <canvas> from a
           | hook in the Doom renderer. KiCAD just happens to be a
           | complicated line drawing app.
           | 
           | Don't get me wrong, still a fun little hack. But some more
           | PCB-ness would make it even cooler.
           | 
           | It might be that the website undersells it and there's more
           | PCB-ness than I can detect in the visuals. Is it using layers
           | and vias between them for the z-sorting or so? Both the
           | website and the commits have a distinct AI slop feel to them
           | and are somehow not very detailed on this part.
        
             | mikeayles wrote:
             | So the reason everything is on one net is so kicad doesn't
             | need to calculate a ratsnest/air wires.
             | 
             | As for the drawing, we pulled the vectors as a list from
             | the C, and used a painters algo and drew back to front
             | using the distance from the player in the python code.
             | 
             | We then treated them as polygons to allow us to work out
             | occlusion to hide things behind walls, but the data pipes
             | to kicad/the headphone jack is just the
             | vector/wireframes/outlines, filtered by what's left after
             | the occlusion test.
             | 
             | So yep, using footprints as sprites was my (clunky) nod to
             | electronics, as I didn't like the idea of drawing polygons.
             | Kicad can definitely handle them, but they're less fun.
             | 
             | Now, if I'm really bored over Christmas, I may port it to
             | fusion360, which will have a 3d engine.
             | 
             | I 100% abused Claude code to get here, and i tend to get it
             | to write the bones of a write up, which I then populated
             | with my own thoughts, else I can't get started. We are
             | worryingly becoming more aligned.
        
       | actinium226 wrote:
       | Lol, I jsut started learning KiCAD last week, and I work in at a
       | game dev coworking space, so this is a perfect combination of the
       | two! Nice!
        
       | ChrisGammell wrote:
       | Never Trust The Automap
        
       | bruckie wrote:
       | This is amazing. It feels like it could be a tom7 project
       | (https://tom7.org/, https://youtube.com/@tom7).
        
         | mikeayles wrote:
         | What an honour, thanks
        
       | GaryBluto wrote:
       | Awesome project, but why is the page a semi-transparent overlay
       | on another page?
        
       | jacquesm wrote:
       | Inception version: make it so shooting components degrades the
       | machine it runs on.
        
         | p0w3n3d wrote:
         | You remind me about Atari XL/XE game "Inside", which was
         | fighting some dust balls or what? inside the Atari. If a
         | circuit was broken you had to fly there and fix it, but when
         | for example Pokey was broken the music was distorted, Antic -
         | the screen was distorted etc
        
           | seg_lol wrote:
           | This is wonderfully nerdy
           | https://www.youtube.com/watch?v=XsSg110yJZg
        
         | ollybee wrote:
         | A bit like psDooM
        
       | oniony wrote:
       | The obvious next step is to play Doom rendered as actual PCBs.
       | Each frame is automatically ordered online and then, when it
       | arrives two weeks later, slotted into a holder whilst the bored
       | player contemplates their life choices.
        
         | junon wrote:
         | Assuming that's 15 FPS that's about 80-100 Euro (sans shipping)
         | per second of gameplay and due to most PCB fabs having a MOQ of
         | 5 you could play 5 at a time!
        
           | roygbiv2 wrote:
           | Yeah but just liked an overclocked gpu, there's errors on
           | those boards so you have to throw them away and wait for the
           | for the next revision.
        
           | Artoooooor wrote:
           | But how motivating it would be to do the best speedruns!
        
         | Someone wrote:
         | You can speed things up with speculative execution. If you add
         | one, you will want a good branch predictor to keep costs down.
        
       | dspillett wrote:
       | _> to extract vector data directly from the engine_
       | 
       | That got me thinking "I wonder if anyone has done this on an
       | oscilloscope" and oddly I can't fine anyone who quite has. That
       | DOOM objects are sprites and not actual 3D objects would limit
       | the fidelity, but the scenery could be rendered at least. There
       | are several examples of managing to use a high-speed scope as a
       | low-res monochrome raster device (scanning like a CRT monitor
       | does and turning the beam on & off as needed).
       | 
       | I did find an example of Quake being done on a scope the way I
       | was imagining: https://www.youtube.com/watch?v=aMli33ornEU - as
       | all objects are actual 3D models in Quake that even manages to
       | give them some presence & shape.
       | 
       | EDIT: _then_ I read the second half of this post and saw
       | ScopeDoom! I 'm surprised there are no earlier examples that are
       | easy to find.
        
         | mikeayles wrote:
         | Author here:
         | 
         | I pulled inspiration from this port to a vectrex:
         | https://www.youtube.com/watch?v=VuVnoqFF3II, there is a wayback
         | machine link to the authors writeup credited in my writeup.
         | 
         | I have seen a lot of ports of DOOM on overpowered Windows based
         | test equipment, particularly the Keysight MXA's, but they're
         | just using them as a computer. Spectrum DOOM though. Could it
         | be done by taking snapshots of a waterfall plot?
        
       | junon wrote:
       | Side note, this is using the new KiCad socket APIs in v9 right?
       | What was your experience using those?
       | 
       | I've written my own s-expr library to inject footprints and
       | symbols and it's a huge pain and flakey. I'd love to move to
       | something a bit more fleshed out and official.
        
         | mikeayles wrote:
         | This isn't using the KiCad socket API, although it probably
         | would have been cleaner. It's a bog standard Plugin that should
         | work for v6+.
         | 
         | I'd be keen to have a look at your s-expr library, it likely
         | has some overlap and utility for one of my other projects,
         | https://www.circuitsnips.com , which is like thingiverse for
         | electrical circuits. I had to figure out how to feed the
         | embedded kicanvas renderer a full sheet, as it can't handle
         | subcircuits, but allow the user to export subcircuits to the
         | clipboard.
         | 
         | When I first shared CircuitSnips with the KiCad discord, the
         | KiCad 9+ design block feature was brought up, which might be of
         | interest to you as well?
        
       | philipwhiuk wrote:
       | As an extension, allow new maps to be added based on chip design
       | CAD files - chips become rooms, soldering lines are corridors
        
       | thenthenthen wrote:
       | Is there a video/demo of it somewhere?
        
         | maaarghk wrote:
         | Literally the first thing in the linked post after the titles.
        
           | p1mrx wrote:
           | That's a potato-quality gif, not a video.
        
       | dcuthbertson wrote:
       | Could you print the designs to paper and make a repeatable flip-
       | card stack? Oh no. How long before it becomes a PowerPoint
       | presentation?!
        
       | danishSuri1994 wrote:
       | This is one of those projects where the implementation is more
       | interesting than the meme. Rendering DOOM isn't the impressive
       | part, hijacking a PCB editor's rendering pipeline and making it
       | behave like a real-time vector engine is.
       | 
       | The part I love most is how many unrelated systems had to
       | cooperate:
       | 
       | extracting geometry directly from DOOM's drawsegs/vissprite
       | internals
       | 
       | mapping sprite classes to physical component footprints
       | 
       | running real-time updates through KiCad's object model without
       | triggering full recompute
       | 
       | and then running the same vector stream to an oscilloscope via
       | audio DAC
       | 
       | That's a really clever chain of "use the tool for something it
       | was never designed to do."
       | 
       | ScopeDoom might end up being the more interesting long-term
       | direction, vector displays force you to think about rendering
       | differently, and there's something poetic about DOOM being
       | rendered as literal analog voltage traces.
       | 
       | If you ever take it further, the combination of:
       | 
       | faster DAC (or multi-kHz arbitrary waveform generator)
       | 
       | true analog persistence phosphor scope
       | 
       | and dynamic sprite simplification
       | 
       | ...could get you surprisingly close to a smooth vector-shooter
       | aesthetic.
       | 
       | Either way: great hack. The world needs more playful abuse of
       | serious tools.
        
         | mikeayles wrote:
         | Thanks very much. ScopeDOOM definitely has potential, I need to
         | work on the occlusion logic to clean up the display, whilst
         | it's not particularly visible on the demo, I did actually use
         | distance to 'camera' to control pcb trace thickness, so close
         | walls look thicker.
         | 
         | In lieu of an intensity channel for the scope implementation,
         | slowing down the vector drawing for segments would make them
         | 'brighter' on a proper scope, but I don't know if my relatively
         | cheap Siglent would be able to distinguish between them.
         | 
         | I've got some NI DAC's here, or could use a mcu, the practical
         | limit of the DAC on a teensy 4.1 is reportedly around 1Mhz,
         | however for me I don't think theres a practical reason to do
         | so.
         | 
         | Although, a native implementation on a teensy, with the wad on
         | an sd card and direct input, no computer at all is very
         | tempting...
         | 
         | Back on track, i've got to spend a bit more time focussing on
         | work and other projects, but I have my next ludicrous port
         | planned already.
        
       | olelele wrote:
       | Just looking quickly but it looks like I have to try to run this
       | on my analog scope
        
       ___________________________________________________________________
       (page generated 2025-11-26 23:00 UTC)