A chip you can
see inside
There is no instruction decoder here, no addressing-mode table and no cycle-count lookup. There are 1725 wires and 3510 switches on a die photographed out of a physical chip, and the behaviour falls out of simulating them. A register value is read back off its own storage nodes; a cycle count is something that emerged rather than something that was written down.
The projects
4 projects live under this roof, with 13 working parts between them.
6502
A transistor-level MOS 6502 traced from die photographs, and everything built on it: the explorer, the API over the real chip, the warm engine process and the console.
overviewExplorer6502 APIDie RunnerEditorRegistryHalfwave Labvisual6502 Archive
hotbits
True random bytes from the decay of a radioactive source: a Geiger counter on a Pi, with bits taken from the timing between decay events.
overviewhotbits API
ntsc-crt
Signal-level NTSC: the composite waveform itself, encoded from three sources, pulled apart by four different filters, and displayed through a five-stage CRT model, with a check that can fail at every stage.
overviewBench
the NES console
A working NES assembled from the family's parts: the chips at their switches, the contracts between them proven by recorded reference traces, and the signal path already real.
overviewPlay
Start here if you build things

halfphi
The switch-level engine: die-data parser, netlist, solver. It names no chip and embeds no die data, which is the whole reason it can be depended on freely. Loads the 6502, the 6800 and the Z80 through identical calls.
github.com/tinymachines/halfphiMITa Rust crate
the served release (v0.326) carries halfphi 0.1.6; its six shared files hash to 6102efce4863, identical in both repositories
The 6502 work, piece by piece
Each one exists and runs. 4 of the 6 answer on a public address; the other 2 say why they have none.
halfphi
The switch-level engine: die-data parser, netlist, solver. It names no chip and embeds no die data, which is the whole reason it can be depended on freely. Loads the 6502, the 6800 and the Z80 through identical calls.
- Ships as
- a Rust crate
- Code
- MIT
- Die data
- none: embeds no die data
source
A crate is a dependency, not a running service. There is nothing to answer an HTTP request, so this piece has no reachability to report.
the 6502 info site
The info site: a WebGL2 die renderer, around 25 derived container kinds, the chip map, the primer, the labs and the measured tables.
- Ships as
- built into a content-hashed dist/, served from a release symlink
- Code
- MIT
- Die data
- CC BY-NC-SA 3.0, derived from visual6502 die data
read it heresource
the 6502 API
Stateless HTTP over the real chip: the whole machine travels in every request and the server keeps no sessions. FastAPI and Pydantic, plus the chip atlas, the cartridge mint and an MCP endpoint.
- Ships as
- uvicorn, with --root-path /api behind nginx
- Code
- MIT
- Die data
- CC BY-NC-SA 3.0, derived from visual6502 die data
read it heresource
halfwave
The warm engine process the API talks to: a line protocol, one parsed netlist, one machine, zero dependencies. Plus a reviewer-built lab on a property of its own.
- Ships as
- a release binary, plus a static lab
- Code
- MIT
- Die data
- CC BY-NC-SA 3.0, derived from visual6502 die data
read it heresource
Die Runner
The console: a 6502 ROM, a page of its memory as the screen, and the browser drawing it. Cartridges, builder pages and the editor.
- Ships as
- static ES modules
- Code
- MIT
- Die data
- CC BY-NC-SA 3.0, derived from visual6502 die data
read it heresource
Die Runner API
The cartridge mint, the console spec and the registry. Publishing re-runs every cartridge on the chip rather than believing the verify block the file arrived with, because a file is something its author can edit.
- Ships as
- routes on the same FastAPI app as the 6502 API, not a service of its own
- Code
- MIT
- Die data
- CC BY-NC-SA 3.0, derived from visual6502 die data
source
Not a separate service. It is routes on the 6502 API, so probing it would report that service's health a second time under a different name. See the chip-api piece.
Where to read