363960 Free Memory

Earlier today the Amiga 500 programme got its first hardware numbers: a real Kickstart 1.3 ROM executing its reset path on the STM32H753, comfortably inside the cycle budget, with the chipset still made of stubs. The honest summary at the time was that the ROM was talking to hardware that did not exist yet - half a million open-bus reads, an overlay nobody released, a CPU with nothing to interrupt it.

Tonight the hardware exists. And at the end of the evening, this appeared:

Workbench 1.3 desktop: title bar reading Workbench release, 363960 free memory, with the RAM DISK and Workbench1.3 disk icons on the blue desktop

That is a real Workbench 1.3 floppy, booted by a real Kickstart 1.3, on the emulated machine - the title bar counting its memory, the disk icons drawn by the Blitter, the screen composed from the machine's own palette registers. Rendered pixel-for-pixel from the emulator's line compositor, deterministic across boots. Nothing in that image was drawn by my code directly; my code only agreed to be an Amiga, and the operating system did the rest.

An evening of chips

The chipset went in as separate increments, each with its own test evidence before the next began: the interrupt fabric and both 8520 CIAs first (true port-pin semantics - the reset overlay is literally CIA-A's PA0 pin, pulled high until Kickstart drives it low through the DDRA-then-PRA dance), then bitplane DMA with genuine cycle stealing, the Copper, the Blitter, Paula's four audio channels, sprites, dual playfield with BPLCON2 priorities, and the collision registers.

Three bugs from that stretch are worth retelling.

The Copper sentinel. Every Copper list ever written ends with $FFFF,$FFFE - a WAIT for a beam position that never arrives, which is how a list politely stops. My first WAIT comparison ignored the horizontal component, so the sentinel completed at line 255 and the Copper marched off the end of its list into zeroed chip RAM, executing garbage until a runaway cap caught it. What exposed it was not a display glitch: it was a cycle-budget assertion, because the phantom instructions stole exactly 80 bus slots a frame that had no business being stolen. The fixed rule: an equal-line wait is reached only if some horizontal position the line can actually produce satisfies the masked compare - and hp $FE is forever out of reach, exactly as the hardware intends.

The registers nobody reset. A 68000 reset pulse deliberately does not touch the data and address registers - on real silicon they hold garbage at power-on. Authentic, and fatal for a deterministic emulator: each boot inherited the previous run's register contents, and a thousand-frame double-boot soak diverged at frame 87 because Kickstart's path eventually depends on one. The machine now defines power-on registers as zero, by contract, in writing.

The counter that wrapped. The CPU core counts master-clock cycles against absolute targets, and at seven units per CPU clock the counter crosses 2^31 after about 36 minutes of machine time - after which the run loop's comparison slips an instruction. Nobody had ever run the Mega Drive fork long enough in one process to see it. The soak did.

The floppy

A note before the mechanical language takes over: there is no physical floppy drive here, and no real Amiga. The whole machine is software running on the STM32 microcontroller, so every "drive", "motor", "head", "spindle" and "spin" below is a model in code - the emulator pretending to be a spinning disk convincingly enough that the real operating system cannot tell the difference. Nothing is actually turning.

The disk is where an Amiga stops being a chipset demo and starts being a computer. The drive model speaks the lines trackdisk actually drives: select, motor (latched while selecting, the hardware quirk), step edges, direction, side, and the sense lines coming back - ready, track zero, write protect, disk change. The disk itself is a standard 880K ADF, and on each armed read the current track's eleven sectors are synthesised into MFM and fed to the disk DMA at two words per scanline. A full track takes about ten frames to arrive, which sounds slow until you remember that is precisely how slow a real drive is, and the operating system is built around that patience.

The MFM has one deliberate simplification: the clock bits are left zero. Trackdisk's decoder reconstructs data as ((odd & $55555555) << 1) | (even & $55555555) and computes its checksums over the same masked longs, so clock bits never influence decodability - they exist for the benefit of real magnetic media and real sync detectors. The unit test proves the round trip with an independent decoder before the OS ever touches it.

Three bugs between the motor and the desktop

With the drive model in place, I pointed it at a bootable Workbench ADF - a floppy saved as a file, not a physical disk - and let Kickstart judge the implementation. It failed three times, each failure more instructive than the last.

The seeks that never happened. The boot got as far as spinning the motor and reading track 0 - then read track 0 again, and again, thirty-six times, while the head never moved. The step counter said zero. The cause: trackdisk pulses the /STEP line low and high within microseconds - both edges inside a single scanline - and my drive control was sampling the CIA pins once per line. Every seek fell between two samples. Drive control now reacts to the CIA write itself, and the moment it landed, the probes lit up: cylinder 57, 46, 79, hundreds of steps, the filesystem being walked across both heads.

probe 1000: cyl=79 steps=505  arms=35  INTREQ=0000
probe 2000: cyl=53 steps=1437 arms=105 INTREQ=0000
probe 4000: cyl=32 steps=3448 arms=233 DMACONR=03f0

The motor with no heartbeat. Before that, the motor would spin up and give up. Trackdisk times drive spin-up by counting index pulses on CIA-B's FLAG line - one per disk revolution - and a drive that never pulses looks like a broken mechanism. The emulated spindle now ticks its index every 3,125 scanlines, like a 300rpm drive should.

The sheared desktop. With seeks and index in place, the boot ran deep - DMACONR read $03F0, meaning the OS itself had switched on the Copper, the bitplanes, the Blitter and the sprite DMA. Something was being displayed. I rendered it:

The first Workbench render: recognisable text and icons smeared into diagonal streaks across the blue screen

Recognisably a screen, sliding sideways sixteen pixels per line - the signature of a fetch that is exactly one word too short. The display parameters told the story: Kickstart programs the hires data fetch as $3C to $D0, and my per-line word count computed 39 words where the hardware fetches 40. The real rule is that bitplane DMA runs in 8-CCK blocks aligned at both ends of the fetch window - a stop value below the block boundary still completes its block. One masked subtraction later, the shear was gone and the desktop snapped into place.

There was also a fourth experiment that mattered by failing: I suspected the head-select polarity and flipped it. The bootblock - which lives on side 0 - instantly became unreadable, proving the original mapping had been right all along. Two minutes of a wrong experiment bought certainty that no amount of documentation reading had.

What the screenshot means, and what it does not

Everything in the boot chain worked in concert to produce that image: the CPU running OS code under DMA contention, the CIAs timing it, the interrupt fabric dispatching vertical blanks and disk completions, the Copper running Intuition's display list, the Blitter drawing the windows and icons, sprite DMA carrying the pointer, the floppy delivering nearly four hundred track reads across a seeking head. The thousand-frame double-boot soak still folds bit-identical with the disk in, so all of it is reproducible to the bit.

What it does not mean: a usable computer, yet. The pointer sits frozen at the top-left because mouse input does not exist; the screen lives in a capture buffer because the video transport to the console's HDMI path is a later phase; audio mixes into a ring nothing physical drains yet. The machine boots - using it comes next.

The evening's budget arithmetic held throughout: the full machine frame with every chip active measures around thirty percent of the PAL frame budget on the bench hardware, against a gate of eighty. The Amiga in the microcontroller is not just alive - it has room to breathe.