An Intel 8008 in the card, and a whole 8008 toolchain that lives on the Apple IIe
What I tried
The 8008 core is the cycle-exact one from my Intel 8008 VHDL project. GHDL synthesizes it to a Verilog netlist and Yosys takes that unmodified, so the Byte Hamr build never needs VHDL support. On 2026-07-07 I dropped it into gateware/rev2/b8008_hamr/ using the SDRAM monitor’s bus idiom: the bootstrap FSM that jams RST 0 at T1I, ported verbatim from the core’s monitor top; 64-deep TX and RX FIFOs on IN 1 and OUT 9 with USART snapshot-and-pop semantics; an OUT 31 checkpoint latch; reset and go controls; live PC registers; ID $B8 at $C0CF. The 256-byte slot ROM is the whole glass terminal in 122 bytes, so PR#4 drops you at the 8008 monitor prompt with no OS in the loop. Ctrl-Q exits, Ctrl-R reboots the 8008 alone.

I wanted to write the 8008 code on the Apple itself. The first leg was MAC8008, the 8008 instruction set as Merlin macros generated from the ISA JSON, with semicolon two-operand arguments like MOV A;B. B8RUN reads a ProDOS BIN whose aux type is the ORG, turns it into Intel hex and streams it through the FIFO to the monitor’s L command. B8CMP byte-compares two files through the MLI. The second leg, 07-08, was ASM8, a native 8008 assembler written in 6502 that takes true 8008 syntax, MOV A,B and MVI C,41h, with a table generated from the same ISA JSON. A8 wraps it: an 80-column full-screen editor, ^A assembles in memory and jumps the cursor to an error line, ^G streams the object into the card and drops into the monitor, ^Q comes back to the editor with the buffer intact. On 07-10 the vendored netlist went away and FuseSoC generates it at build time from the core repo.


What I measured
- Core in the ECP5: 1453 LUTs, 433 flip-flops, 10 DP16KD, Fmax 74 MHz to 95 MHz at a 25 MHz clock.
- First flash: PR#4, monitor banner, live prompt. H, D, W, G all work. A program hand-keyed with W at
$2000printed 8008 and restarted the monitor. - ECHO8, 37 bytes, written in Merlin Pro on the IIe with MAC8008: the object dumped with D matched the Merlin32 build byte for byte. Loaded with B8RUN, ran, echoed keys, ESC returned to the monitor.
- MAC8008 against the ASL golden hex: 6 of 6 upstream samples byte-identical, hello_8008_ram at 88 of 88 bytes.
- ASM8 acceptance: HELLO8R.ASM, the verbatim upstream source, assembled on the IIe and B8CMP against the 457-byte ASL reference object reported PASS. The Python model of the same spec had already passed 6 of 6 samples on the Mac, so the bench only tested the 6502 implementation.
- A8: ^A on the same file reports OK $01C9 AT $2040, and the object it writes passes the same B8CMP gate. I then wrote COUNT8 from scratch in the editor, assembled it and ran it on the card.
What broke or surprised me
B8RUN’s first bench run went wild. The FIFO put routine clobbered X and Y, the record loop ran off the end, and a 64K read sweep walked straight through the $C0xx soft switches: garbled screen, and the slot 6 drive motors came on in write mode. I checked the floppies afterwards. The driver preserves X and Y now, and I found five more 6502-side bugs the same session, none needing a reflash: the MLI prefix is empty at boot so raw MLI calls fail with $40 until you set it; an error printer that destroyed the code before printing it; lowercase input that ProDOS rejects; an unattended load that overflowed the 64-byte TX FIFO and dropped the monitor’s OK, fixed by draining TX to the screen per record.
Merlin Pro on the IIe loaded the whole 200-line macro file and defined every macro, then threw Operand too long on the generator’s 72-column header comment. Merlin Pro enforces line width and Merlin32 does not. Every generated source is clamped to 40 columns now. Real Merlin also scopes local labels between globals, so self-modifying loops use global labels only, and #',' will not parse, so it is #$2C.
The monitor’s W command chokes on trailing text. My first freeze was annotations typed in with the listing, which the monitor faithfully wrote as garbage into a $00 HLT wall. A program that waits silently for input also reads as hung; the first ECHO8 run got Ctrl-R’d during its own input wait.
Next
SCELBAL as a second personality, a direct load and readback port for RAM snapshots, and merging the block device so the card boots itself. None of it started.