2.20 has inline init where 2.23 has runtime code generation
Detail for Part 6 — The BIOS Factory.
Update (2026-04-28): The framing here is wrong.
$DB66and$FB70are the LIST jump-table entries, not BOOT. Real cold-boot vectors are$DEA8(2.20) and$FED1(2.23) — both in runtime-generated regions. The detailed prologue diff below is comparing two routines that aren’t the BOOT-vector target. The structural observation that 2.20 hasCALL $DD8Eafter the prologue is also wrong:$DD8Eis SETDMA per the 2.20 jump table, not an inline init helper. See the BIOS jump-table correction. The “2.20 inline / 2.23 runtime-generated” thesis needs to be re-derived from the correct BOOT entry points.
Diffed the cold-boot routines between 2.20 and 2.23. 2.20’s “LIST” jump-table entry points to $DB66 (analogous to 2.23’s LIST at $FB70). Both routines have identical prologue structure — almost identical instructions, just different addresses:
| Step | 2.20 ($DBxx) | 2.23 ($FBxx) |
|---|---|---|
| Init stack | LD SP,$0080 | LD SP,$0080 |
| Read video | LD A,(E051) | LD A,(E051) |
| Init buffer ptr | LD HL,$0E00 | LD HL,$0E00 |
| Helper call | CALL $DFE8 | CALL $FB45 |
| Runtime-area call | CALL $DAA2 | CALL $FA82 |
| Clear state 1 | LD ($DEB4),A | LD ($FEDD),A |
| Clear state 2 | LD ($DEAF),A | LD ($FED8),A |
| Plant Z-80 reset hi | LD HL,$DA03 | LD HL,$FA03 |
| Plant BDOS target | LD HL,$CC06 | LD HL,$9C06 |
Same code, different addresses (consistent with the 2.20 BIOS at $DACC vs 2.23 BIOS at $FAB8). And 2.20’s BDOS final position is $CC06; 2.23’s is $9C06 — a $3000 (12 KB) shift. So the relocation that moves CCP+BDOS from staged $A300 lands them in different final positions in the two builds. (The 2.23 banner says “60K Ver.” and uses lower BDOS, leaving more LC RAM for the BIOS factory’s generated routines; 2.20 uses higher BDOS with less LC RAM.)
After the prologue, the routines DIVERGE in a structurally meaningful way:
2.20 continues with explicit init code:
$DB7E: LD BC,$0080 ; (2.23 has $FF80 here)
$DB81: CALL $DD8E ; calls into 2.20 BIOS
$DB84: LD A,$01
$DB86: LD ($E5B2),A ; sets a state byte to 1
$DB89-onwards: PUSH HL × N ; (then the rest of newdisk_220 is $E5
; padding — CP/M filesystem "deleted"
; bytes filling the unused page)
2.23 continues with:
$FBB6: LD BC,$FF80 ; different magic value
$FBB9-onwards: FF FF 00 00 / F7 F7 00 00 (runtime-marker pattern)
; The cold-boot generator writes real
; per-device init code over these
; markers based on the slot scanner's
; device-code table.
The implication is decisive. 2.20 has the per-device init logic inlined into the BIOS source code. It runs the same CALL $DD8E / LD A,$01 / LD ($E5B2),A sequence for whatever device configuration it detected. 2.23 replaced the inline logic with runtime code generation. The generator produces different init code based on what the slot scanner found — which lets 2.23 generate Pascal-1.1-aware code when device code $06 is present, generate Pascal-1.0-aware code when only $04 is present, and so on.
This is the BIOS factory model in concrete code. It’s not just an architectural sketch from Part 5 — it’s visible in the byte-level diff.
What this means for the analysis going forward:
- The Pascal 1.1 driver code in 2.23 doesn’t exist as static bytes anywhere on the disk. It’s built by the generator each boot.
- To see what 2.23 actually does for a Videx, we need to either: (a) trace the cold-boot generator’s algorithm and predict what bytes it writes, or (b) boot CP/M in a Z-80 emulator and dump the runtime-generated regions to see what got written.
- The 2.20 inline code (
CALL $DD8E / LD A,$01 / LD ($E5B2),A) shows what 2.20’s “fixed” init does — and we can compare to whatever 2.23 generates for the same device profile to confirm structural compatibility.
The LD A,$01 / LD ($E5B2),A in 2.20 is suggestive: it sets a byte at $E5B2 to 1. $E5B2 is in the upper TPA area but accessible from BIOS. Could be a per-device “index” or “active count” — initialized to 1 in 2.20 because 2.20 always assumes one console device. 2.23’s runtime generator probably sets this byte conditionally based on the device-code table.
The 2.20 CALL $DD8E is a call to a BIOS internal routine. $DD8E lives in the populated 1 KB of 2.20’s BIOS — disassembling that target would tell us what 2.20’s static init does step-by-step.
Status: 2.20 vs 2.23 cold-boot diff complete at the prologue + immediate-post-prologue level. Same prologue; diverging in init strategy: 2.20 inlined, 2.23 runtime-generated. Confirms the BIOS factory model with byte-level evidence. Next: disassemble 2.20’s CALL $DD8E callee to see what the inline init actually does — that’s a good baseline for predicting what 2.23’s generator produces.