antirez publishes c64-hw-sim, a pin-level Commodore 64 simulator

antirez has published c64-hw-sim, a program that simulates the motherboard of the Commodore 64 (ASSY 250407) pin by pin. The user can lift the leg of a chip, short it to ground or to +5V, pull a chip out of its socket, or open a resistor, and then watch what the machine does: the picture on the monitor, the keyboard and every signal on the board.
The program knows the board's netlist (the electrical connections on the PCB) and how each chip behaves at its pins. It knows nothing about what a broken C64 looks like. When a simulated broken part fills the screen with garbage, that garbage was computed from the circuit, not chosen by someone who knew what to expect.
The README's worked example: lift pin 17 (A7) of the color RAM before power on, and the machine boots and looks healthy. The CPU writes and the VIC reads with the same wrong address, so the RAM simply aliases. Put the leg back, and the half of the color RAM that was never written shows up as random colors. Lift it again, and the screen is clean. The author says a real 2114 does the same. Another demo shows the classic 10 PRINT maze running while the character ROM (U5) is pulled out and later put back: the CPU, RAM and program keep working, only the character shapes are lost, and the data line D0 of the empty socket floats whenever the VIC fetches a character shape.
The author names two goals. One is learning how the C64 works at a more intimate level, in a way that is hard to reproduce on real hardware without risking damage (and on most boards many chips are soldered, not socketed). The other is for owners of a broken C64 with a hypothesis about the fault: simulate it, perhaps gain clues, and desolder chips in the most logical order and as few as possible. A matching symptom is a clue, not a proof, because different faults can look the same.
Speed is the main limit. Even on fast machines the simulation runs at 31% of real C64 speed on an Apple M3 Max, 39% on an AMD Ryzen AI Max+ PRO 495 (Gorgon Halo) and 48% on an Apple M5 Max, because every pin of every chip is simulated. The author says this suits the program's goals but it is not an emulator to play games with.
Antirez says he got the idea while using Andre Weissflog's (floooh) chips, emulators of the 6502, VIC-II, CIA, SID and others that use pins as their interface. The next step was to take that approach, with floooh's code as a starting point, to its logical extreme: pin-level models of every other part, meaning the RAMs, ROMs, logic chips and the PLA. The chip cores come from floooh's chips via c64-llm (zlib license). The board comes from bwack's C64-250407-Replica-KiCad (CERN OHL). The PLA equations come from the 82S100 read-out by Mark Smith and Marko Mäkelä.
Usage: build with make and run ./c64-hw-sim [program.prg]. It runs on macOS and Linux (X11), with OpenGL; the sokol graphics library and nuklear interface library are bundled in third_party/. The window shows the board, the monitor, a control panel and an oscilloscope. Chips are boxes named by role: RAM1 to RAM8 are the 4164 DRAMs (RAMn holds data bit n-1), VRAM is the 2114 color RAM, BASIC, KERNAL and CHAR are the ROMs, and PLA is the address decoder. Pins are colored like a logic probe: red high, blue low, yellow pulsing, gray floating, magenta when two outputs fight. Clicking a pin puts it on the oscilloscope and lets you break it (floating, shorted to GND or to +5V); clicking a chip pulls it out; clicking a resistor, ferrite bead or the crystal opens it. The control panel lists faults, each with a repair button, and loads .prg files, which are written straight into the DRAM chips as a freezer cartridge would do it, so loading works on a broken board too. Keys: ESC is RUN/STOP, PgUp is RESTORE, TAB is CTRL, left ALT is C=.
A headless mode, for example ./c64-hw-sim --headless 200 --text --shot out.png --fault U17:removed, runs four seconds (200 frames) without a window, prints the text read from the monitor picture and saves the picture. Faults are written REF:what or REF.PIN:what, such as U17:removed, U21.14:gnd, U12.14:vcc, U9.2:open, R51:open or RP4:short. Other options: --at to break and repair parts while the C64 runs, --nets to report nets where outputs fought, C64HW_TYPE to type text after boot, C64HW_CHECK=1 to check every KERNAL read and VIC fetch against the ideal memory map, and --record to save window frames in graphical mode (for example --record 900:DIR --frames 90 saves 90 images, one every 4 emulated frames from frame 900). tests/faults.sh runs 31 common faults, and the expected symptom of each was written down before the simulator was run. tools/kicad2c.py turns bwack's KiCad replica of the 250407 into C tables with 216 parts, their pads and 249 nets.
How the model works: every pin drives its net strongly, weakly (a pull-up), from a supply short, or not at all, and the strongest drive wins. Two equal drives fighting are a contention, and low wins. A net nobody drives keeps its charge and then drifts: to about 1.4V within microseconds if TTL inputs load it, toward 0V in a fraction of a second if only MOS inputs are on it. MOS inputs compare that voltage, plus some seeded noise, with their own threshold, so a floating line can read erratically and a run can be repeated exactly. Power faults depend on the chip: a chip without VCC is dead, a chip without GND lets its outputs float high, and a CMOS chip keeps running on phantom power through the protection diodes of its pins. The glue logic, ROMs, DRAMs (which latch the row on /RAS and the column on /CAS), color RAM and PLA with its real logic equations are modeled in src/parts.c. The 6510, VIC-II, CIAs and SID are cycle-accurate cores from floooh's chips, each sitting in a socket in src/board.c that sees only its pins. Each half cycle runs in three steps (row address, /RAS falls, /CAS falls), and the whole board settles after each step.
The stated limits: the floating and power models have the right shape but their numbers (thresholds, drift times, crosstalk) are guesses, kept as constants in src/sim.c. The video output, the SID filter, the power supply and the dot clock PLL are not simulated. Faults inside a chip, such as bad DRAM cells or slow parts, and bridges between two nets are planned but not done.
Key facts
- c64-hw-sim simulates the Commodore 64 motherboard (ASSY 250407) pin by pin; users can lift pins, short them to GND or +5V, pull chips from sockets or open resistors.
- It runs at 31% of real C64 speed on an Apple M3 Max, 39% on an AMD Ryzen AI Max+ PRO 495 and 48% on an Apple M5 Max, so it is not meant for playing games.
- Board data comes from bwack's KiCad replica (216 parts, 249 nets); the 6510, VIC-II, CIA and SID cores come from floooh's chips.
- tests/faults.sh runs 31 common faults, with the expected symptom of each written down before the simulator was run.
- The author says the floating and power model constants are guesses; analog parts such as video output, SID filter and power supply are not simulated.
Why it matters
This program models the board's circuit and chip behaviour at the pins, so a fault produces symptoms the circuit computes rather than ones someone scripted. The author builds on Andre Weissflog's pin-based chip emulators and takes the idea to pin-level models of the RAMs, ROMs, logic chips and PLA. The README's color RAM example, where a lifted address pin makes the machine look healthy because the RAM aliases, shows the kind of behaviour this approach exposes.
Who it affects
The README names two audiences: people who want to learn how the Commodore 64 works at a close level without risking real hardware, and owners of a broken C64 who have a hypothesis about the fault and want clues on which chips to desolder first. It is not for people who want to play games, since it cannot reach real speed.
How to use it
Build with make and run ./c64-hw-sim [program.prg] on macOS or Linux (X11) with OpenGL. In the window, click a pin to put it on the oscilloscope and break it, click a chip to pull it out, click a resistor, ferrite bead or the crystal to open it; the control panel lists faults with repair buttons and loads .prg files. For scripted runs, --headless 200 --text --shot out.png --fault U17:removed runs 200 frames (four seconds) without a window and prints the screen text. Faults are written REF:what or REF.PIN:what. No price or licence for the simulator's own code is stated; the licences given cover floooh's chip cores (zlib) and bwack's board (CERN OHL).
How solid is it
This is the author's own README, not an independent evaluation. The tests/faults.sh suite runs 31 common faults, each with an expected symptom written before the simulator was run, but the results are not given. The only comparison with real hardware mentioned is the author's remark that a real 2114 behaves like the color RAM example. Speed figures are given for three machines only. The author states plainly that the numeric constants in the floating and power models are guesses.
Risks and caveats
A matching symptom is a clue, not a proof: different faults can look the same. Video output, the SID filter, the power supply and the dot clock PLL are not simulated. Faults inside a chip, such as bad DRAM cells or slow parts, and bridges between two nets are planned but not implemented. Only the ASSY 250407 board is simulated. The simulation runs at about a third to half of real time, so timing-sensitive behaviour is watched slowed down.
“A matching symptom is a clue, not a proof: different faults can look the same, and the simulation has its limits”
— c64-hw-sim README, by antirez