The runtime-code marker: FF FF 00 00 / F7 F7 00 00
Detail for Part 5 — The BIOS That Half-Exists.
Update (2026-04-28): “Cold-boot routine at
$FB70” is wrong —$FB70is the LIST jump-table entry, and the actual BOOT vector points to$FED1. The marker-pattern observation in this devlog is still valid: theFF FF 00 00 / F7 F7 00 00pattern marks runtime-generated regions, and populated code does call into those regions. What needs correcting is the implied geometry — pages aren’t split cleanly into “first KB code, second KB markers”; the BIOS uses a 256-byte interleave, and 2.20 uses$E5instead of the FF/F7 pattern. See the BIOS jump-table correction.
Following up on the cold-boot location finding: the cold-boot routine at $FB70 only sets up architectural fixed points (stack, BDOS vector, reset vector) — it doesn’t visibly contain the per-device code generation. The actual generation must happen elsewhere.
Disassembling more of the populated 1 KB at $FD60-$FDB0 reveals real Z-80 code that calls into the supposedly-empty regions:
$FD60-$FD82: an address-manipulation routine (writes to (HL))
$FD83: real entry point with multiple jumps:
$FD84: JP M,$FBD0 ; jumps to "data" area
$FD88: CALL $FBC4 ; calls "data" area
$FD92: JP P,$FBE2 ; jumps to "data" area
$FDA9: JP $FCA4 ; jumps elsewhere into BIOS
$FDB1: ED 43 ... LD (nn),BC ; (an ED-prefix instruction my
; disassembler doesn't decode)
The targets $FBC4, $FBD0, $FBE2 are all in the byte range I had previously classified as “data” — the FF FF 00 00 / F7 F7 00 00 pattern visible in static disassembly. But the populated BIOS code is CALLing those addresses. So those bytes must be valid Z-80 code at runtime — they’re runtime-generated, not data.
The FF FF 00 00 / F7 F7 00 00 pattern appears in several places:
$FA00-$FAB7(cold-boot area, before the jump table)$FBB9-$FBFF(between cold-boot routine end and the next populated code)$FE81-$FEB7(just before the second-half boundary)$FEB8-$FFFF(the second half, all-zero on disk; contains theF7 F7 00 00pattern at runtime)
It’s a consistent runtime-code marker. The cold-boot generator allocates slots in these regions, marks them with the pattern, then writes real per-device code over the markers based on the slot scanner’s device-code table. As Z-80 instructions, FF FF 00 00 decodes as RST $38; RST $38; NOP; NOP and F7 F7 00 00 as RST $30; RST $30; NOP; NOP — both are RST instructions that, if executed before the generator runs, would cause traps. Likely an intentional safety measure: any premature execution lands in a defined trap rather than an undefined garbage path.
The implication for our extraction strategy: the BIOS first 1 KB at $FAB8-$FEB7 isn’t pure code. It’s interleaved — populated code (jump table, dispatch table, CONOUT, control-char dispatch, cold-boot routine, address manipulation routines) interleaved with code-generation slots awaiting runtime population. The slots at $FBB9-$FBFF are within the populated 1 KB; the code at addresses just before and after them IS real, but the byte ranges $FBB9-$FBFF themselves are placeholder markers.
So the static structure of the BIOS is more like:
$FAB8-$FAE4 jump table (static)
$FAE5-$FAEA inline LISTST/SECTRAN (static)
$FAEB-$FB2A per-device dispatch (mixed: data + slots within entry padding)
$FB2B-$FB39 control-char data table (static)
$FB3A-$FB68 control-char dispatch (static)
$FB69-$FB6F small helper (static)
$FB70-$FBB6 cold-boot routine (static)
$FBB9-$FBFF RUNTIME GENERATED (marker: FF FF 00 00 / F7 F7 00 00)
$FC00-$FE6B more populated code (static, partly disassembled)
$FE6C-$FE9F HOME / SETTRK / SELDSK (static)
$FEA0-$FEB7 RUNTIME GENERATED (marker)
$FEB8-$FFFF RUNTIME GENERATED (per-device handlers + state)
Approximately 2/3 of the 2 KB BIOS region is statically loaded; 1/3 is runtime-generated. The static portion calls into the runtime-generated portion at multiple points. So the cold-boot generator MUST run before any BIOS routine is invoked — including before the very first instruction the Z-80 fetches, if that’s at $FA00.
This raises a sharper version of the earlier puzzle: the Z-80 reset vector points to $FA00 (in the runtime-generated cold-boot area). Either (a) the reset vector points somewhere ELSE in practice, (b) the SoftCard hardware injects an initial value into $FA00-$FAB7 before flipping to Z-80, or (c) the very first call to a BIOS routine triggers some “first-call trap” that runs the generator. Without a Z-80 emulator to actually boot the system, this is bounded but not yet resolved.
Status: the runtime-code marker pattern is identified and consistent. The cold-boot generator must populate slots interleaved throughout the BIOS region, not just the bookend halves. The exact mechanism by which generation runs before the first BIOS call (given the Z-80 reset vector lands in the unpopulated $FA00 area) remains the next concrete piece. Adding CB/DD/ED/FD prefix decoding to z80disasm would also help — the ED 43 at $FDB1 already shows we’re missing real instructions.