~/wiseowl/devlogs
Dev Logs
Raw engineering notes — less polished than articles, more immediate. What was tried, what worked, what didn't, and what's next.
53 entries across 4 projects
cpm-videx
2.20 hang settled in the emulator: Case B (Z-80 stack overflow on $E5 spam)
2.20 hang reproduced in emulator. CONOUT goes to $DFBE, which is pure $E5 PUSH-HL fill. SP wraps from $0080 past $0000, fills high memory with HL marker. Case B from byte-trace, confirmed.
cpm-videx
The cold-boot generator runs and dispatches CALL $FDB0 for the Videx
DD/FD opcodes added. Cold-boot generator at $1A82 dispatches CALL $FDB0 for Videx (device 6, the 2.23 Pascal 1.1 path). Two setup steps still untraced: $F3B8 slot info, $FAB8 BIOS load.
cpm-videx
The SoftCard CPU-switch trigger: JSR $0E36
The 6502 warm-boot routine at Apple $03C0 ends in JSR $0E36. Apple $0E36 contains Z-80 instructions, not 6502. The SoftCard hardware monitors that fetch and uses it as the CPU-switch trigger.
cpm-videx
2.20's BIOS architecture is fundamentally different from 2.23's
Booting 2.20 reveals 6502 LOAD_CPM writes ~7 KB directly into LC RAM ($EB-$FF) -- unlike 2.23 which stages and redistributes. But $DA00 (Z-80 reset target) ends up empty.
cpm-videx
End-to-end emulator-confirmed: 2.23 detects Videx as Pascal 1.1, 2.20 doesn't
Added Videx slot-3 model from a2fpga ROM 2.4. Boot trace: 2.23 stores device $06 (Pascal 1.1) for Videx; 2.20 stores $04 (Pascal 1.0). The 11-byte $C30B check is emulator-confirmed.
cpm-videx
2.20 also makes two LOAD_CPM calls — not unique to 2.23
2.20 has two JSR $0E10 calls (LOAD_CPM-equivalent) at $1608 and $17D0 — just like 2.23 has two JSR $BBEB. The dual-load mechanism is shared between versions, not 2.23-specific.
cpm-videx
2.20's BIOS dispatch table has 6 entries vs 2.23's 4
2.20 has a 6-entry dispatch table (96 bytes) at $DAFF vs 2.23's 4-entry (64 bytes) at $FAEB. Entries 0-3 are static handlers; entries 4-5 point into $E5-filled regions (runtime slots).
cpm-videx
Factual byte-level trace of the v2.20 hang
Traced 2.20's CONOUT-on-Videx path byte-by-byte. Static evidence reaches handler at $DFBE → CALL $DAC5 (runtime-generator zone). Two failure modes identified, both consistent with the observed hang.
cpm-videx
The 6502 loader carries 270 bytes of embedded Z-80 code at $143A-$1547
~270 bytes of Z-80 code embedded in 2.23's 6502 loader at $143A-$1547. Calls BIOS routines, references state slots, contains LDIR. 2.23-specific — 2.20 has no analog.
cpm-videx
Stage 1 emulator: 6502 boot finishes without ever writing $FA00
Stage-1 emulator boots SoftCard CP/M 2.23 in a 6502-only sandbox. Memory write log proves the 6502 never touches $FA00-$FFFF before handoff. So the BIOS proper has to be Z-80-generated.
cpm-videx
Stage 2 emulator: BIOS jump table is at Z-80 $1A00, not $FAB8
Stage-2 adds Z-80 emulator + SoftCard XOR mapping + CPU-switch. Boot reaches Z-80 takeover at $0E36. BIOS jump table actually lives at Z-80 $1A00 (Apple $0A00), not $FAB8.
cpm-videx
Byte-by-byte loader diff: 2.20 vs 2.23 differ in 74% of bytes
Byte diff of the 3 KB loaders: 40 runs differ (2280 bytes, 74%). The 11-byte Videx fix is a small island in a larger rewrite, including one 1048-byte run.
cpm-videx
Walking the 6502 RWTS the SoftCard borrowed from
Disassembled the 6502 RWTS at $0A00-$0FFF. Two 6502 code blocks plus a 199-byte Z-80 BIOS gap and a GCR codec page, interleaved across six sectors. PREP_HANDOFF moves it to $BA00-$BFFF.
cpm-videx
The inter-CPU sync polling loop at Z-80 $1E39
Z-80 $1E39-$1E44 is the inter-CPU sync polling loop. Six instructions: LD A,($E000) / RLA / JR NC / LD ($E010),A / CCF / RRA / RET. Reads $E000 sync flag, waits for high bit, signals back via $E010.
cpm-videx
Microsoft CP/M 2.20 vs 2.23: Digital Research's CP/M base also changed (2.0 → 2.2)
Diffed sysimg (CCP+BDOS) for both versions. 5807/5888 bytes differ — too much for relocation alone. Microsoft bumped the underlying Digital Research CP/M from 2.0 to 2.2 between releases.
cpm-videx
2.20 has inline init where 2.23 has runtime code generation
2.20 cold-boot at $DB66 vs 2.23 at $FB70: same prologue, then 2.20 has inline init (CALL $DD8E / LD A,$01 / LD (E5B2),A) while 2.23 has runtime-marker bytes. Code generation REPLACED inline.
cpm-videx
BIOS jump tables read: cold-boot is BOOT (offset 0), not LIST
Re-read both BIOS jump tables. BOOT=$FED1 in 2.23, $DEA8 in 2.20. LIST=$FB70/$DB66. Earlier devlogs confused LIST with BOOT. Both BOOT vectors land in runtime-generated regions.
cpm-videx
The cold-boot generator: $FB3A in 2.23, $DB6E in 2.20 — and the device-code 6 branch only 2.23 has
Located the cold-boot generator. 2.23 at $FB3A dispatches on device codes 3, 4, and 6 (Pascal 1.1). 2.20 at $DB6E does the same loop but only dispatches on 3 and 4 — no Pascal 1.1 branch.
cpm-videx
2.20 and 2.23 BIOSes have identical device-scan loops
Both BIOSes scan 9 entries from a device-code table — same instructions, same encoding. 2.23 adds preflight logic 2.20 lacks. The fix between versions wasn't in the BIOS; the scan was already there.
cpm-videx
Real Z-80 code at trk2:physA — past where LOAD_CPM reads
BIOS extract grabs 8 sectors but only 5.3 are BIOS proper. trk2:physA contains real Z-80 code calling BIOS routines, but it's NOT in LOAD_CPM's staging — must be loaded by a later step.
cpm-videx
$FDB0 (the Pascal 1.1 callee) is a RET stub — driver init lives somewhere else
Disassembled the device-6 callee at $FDB0. It's a single RET. So 2.23's generator dispatches Pascal 1.1 to a no-op stub — the actual driver-install path is elsewhere, not in the cold-boot call site.
cpm-videx
Loader $191E: a second JSR $BBEB before the CPU switch
Loader $1900-$194B is the boot-finalization. It calls LOAD_CPM-equivalent ($BBEB) a second time with A=$80, likely loading BIOS handler templates past the main 29-sector read.
cpm-videx
2.20 ships static device handlers in BIOS; 2.23 generates them at runtime
2.20 BIOS has a 256-byte page of static device handlers at $E0CC. 2.23 has no equivalent page — handlers are runtime-generated instead. This is the architectural shift between versions.
cpm-videx
Two versions, two BIOS layouts: 2.20 vs 2.23 staging compared
Ran LOAD_CPM reconstruction on 2.20 (PRODOS_INTERLEAVE). Same 29-sector mechanism, different content layout: 2.20 BIOS at staging $1700; 2.23 at $1900. No 'Softcard' banner in 2.20 — added in 2.23.
cpm-videx
Some BIOS routines disassemble cleanly; others are dispatch tables in disguise
Disassembled the 2.23 BIOS at the jump-table offset. CONOUT at $FB4D is real code. But CONST at $FB10 and CONIN at $FB1A decode as structured data — a 4-entry × 16-byte per-device dispatch table.
cpm-videx
Half the BIOS is zero on disk because it's generated at runtime
The 'missing' second 1 KB of BIOS at trk2:$08-$0B is all zeros on disk. SoftCard CP/M's BIOS isn't missing — half of it is generated at runtime by code that runs after the SoftCard switch.
cpm-videx
The Z-80 callbacks read and write the BIOS second half
Z-80 callback instructions write into the BIOS second half: 'LD HL,$FECB / LD (HL),A', 'LD ($FED2),A'. The second half is runtime-generated routines + per-device state storage.
cpm-videx
Tracing CONOUT into the BIOS hits the extraction wall
Followed CONOUT's CALL $FB45 into the BIOS. The chain hits routines that are zeros in our partial extract. About half of 2.23's BIOS is reachable; the per-device dispatch handlers aren't.
cpm-videx
The 6502 plants the Z-80's reset vector
Annotated the 2.23 6502 boot loader. Cleanest find: the bytes written into Apple $1000-$1002 are Z-80 'JP $FA00' — the BIOS cold-boot entry, planted at Z-80's reset vector before the CPU switch.
cpm-videx
The cold-boot generator hides at the LIST jump-table entry
The 2.23 BIOS jump table's LIST entry ($FB70) is actually cold-boot init: stack setup, BDOS call vector at $0005 (JP $9C06), Z-80 reset vector rewritten from JP $FA00 to JP $FA03.
cpm-videx
LOAD_CPM cracked: 29 sectors, $8000 staging, then Z-80 disk callbacks at $0A00
LOAD_CPM at $0BEB reads 29 sectors from trk0:$0B onward, stages $8000-$9CFF, splits into CCP+BDOS at $A300 (with the 'CP/M 60K Ver. 2.23' banner) and Z-80 disk callbacks at $0A00.
cpm-videx
The runtime-code marker: FF FF 00 00 / F7 F7 00 00
The BIOS regions awaiting runtime code aren't all-zero on disk — they have a marker pattern (FF FF 00 00 / F7 F7 00 00). Populated BIOS code calls into these regions, confirming code-gen runs first.
cpm-videx
$C800 isn't the Videx — it's the shared expansion-ROM window
The 'LD HL,$C800' in 2.23's CONOUT was overstated as direct Videx evidence. $C800-$CFFF is a shared expansion-ROM window that any slot card can occupy. Corrected the writeups; saved the lesson.
cpm-videx
Z-80 disassembler online; CONOUT loads HL with the Videx VRAM window
Added a Z-80 disassembler. First test on 2.23 BIOS: CONOUT at $FB4D has 'LD HL,$C800' — the shared expansion-ROM window. Targets expansion cards but not Videx-specific from this alone.
cpm-videx
The BIOS that wouldn't byte-diff
Found the Z-80 BIOS jump tables — 2.20 at $DACC, 2.23 at $FAB8 (8 KB shift). The address shift plus non-contiguous on-disk layout made byte-aligned diffing useless. Pivoting to the 6502 side.
cpm-videx
What does device code 4 mean? What does device code 6 mean?
Three clues to what device codes mean: 2.20 has default codes baked in, 2.23 starts blank; both install a Z-80 dispatch table at $0380; 2.20 has Z-80 handler code at $0344 that 2.23 eliminated.
cpm-videx
Three disks, two versions, one shared boot stub
CPMV233.DSK is actually CP/M 2.23 (filename misleads); CPM220Disk1/2.po are the 2.20 two-disk distribution. The 6502 boot stub is byte-identical across all three — change isn't there.
cpm-videx
Eleven bytes that recognize a Videx
CP/M 2.23 added 11 bytes to its 6502 boot loader's slot scanner that read the Pascal 1.1 signature at $Cn0B and tag Pascal-1.1 cards (Videx included) with a new device code $06. 2.20 ignores $Cn0B.
cpm-videx
Microsoft CP/M doesn't boot on a Videx — and never did
Joshua Norrid found Microsoft SoftCard CP/M won't boot with a Videx — same failure on real cards and A2FPGA emulation. Version survey isolated the boundary: 2.20/2.20B fail; 2.23 works.
a2fpga
ThunderClock complete. ProDOS timestamps work.
ThunderClock Plus emulation complete. ProDOS auto-detects the card on boot and file timestamps appear immediately. USB-C power persistence works as designed.
a2fpga
Videx emulation complete
Videx VideoTerm emulation passes all VIDEX_DIAG tests and boots Apple Pascal 1.3. Three upstream bugs fixed and submitted as PRs. README rewritten.
a2fpga
Samsung G9 won't display — HDMI switch fixes it
HDMI timing fixes resolved most displays. Samsung Odyssey Neo G9 still blank direct — but works perfectly through an HDMI switch. Likely electrical signal levels, not protocol.
a2fpga
CI/CD attempt — OSS toolchain doesn't produce a usable bitstream
OSS Yosys/nextpnr toolchain synthesizes but doesn't produce a bitstream the Gowin programmer accepts. Shelved — proprietary Gowin IDE remains the only path to a flashable build.
smalltalk-from-scratch
884 tests. CI is green.
All 884 tests pass in headless CI. Save/restore runs as a separate workflow job. Four Level 1 failures from last week are fixed.
smalltalk-from-scratch
Delete BitBlt
Deleted Form, BitBlt, Pen — three foundational 1980 classes. Canvas draws everything now. The image boots and renders.
smalltalk-from-scratch
First window
Smalltalk sent beDisplay. A WinForms window appeared. The image can now paint pixels.
smalltalk-from-scratch
Cold start: zero GC, 380ms
Rewrote the cold start loader. The full object graph loads in 380ms with zero GC collections.
smalltalk-from-scratch
The compiler compiles the compiler
Full compilation pipeline working: the standalone C# compiler compiles the entire Smalltalk-80 source, including the Smalltalk-80 compiler itself, to Blue Book bytecodes.
smalltalk-from-scratch
14,840 lines, zero parse errors
The standalone ANTLR4 compiler parsed the complete Smalltalk-80 system source — all 14,840 lines — without a single error.
apple-panic
nibbler v0.1 reads the disk
First working build of nibbler correctly reads, validates, and reports on all 35 tracks of the Apple Panic protection disk.
apple-panic
45 kilobytes hiding in plain sight
The custom RWTS loads 45 KB of game data that doesn't fit in an Apple II. It's compressed. Decoding it took two days.
apple-panic
The code that isn't the code
The loader decodes itself in memory before it runs. The bytes on disk are not the bytes that execute.
apple-panic
The sectors that don't read
Standard DOS 3.3 read routines return garbage on every track past track 2. The disk is not broken — it's deliberate.
cpm-videx
39 entries2.20 hang settled in the emulator: Case B (Z-80 stack overflow on $E5 spam)
2.20 hang reproduced in emulator. CONOUT goes to $DFBE, which is pure $E5 PUSH-HL fill. SP wraps from $0080 past $0000, fills high memory with HL marker. Case B from byte-trace, confirmed.
success
The cold-boot generator runs and dispatches CALL $FDB0 for the Videx
DD/FD opcodes added. Cold-boot generator at $1A82 dispatches CALL $FDB0 for Videx (device 6, the 2.23 Pascal 1.1 path). Two setup steps still untraced: $F3B8 slot info, $FAB8 BIOS load.
success
The SoftCard CPU-switch trigger: JSR $0E36
The 6502 warm-boot routine at Apple $03C0 ends in JSR $0E36. Apple $0E36 contains Z-80 instructions, not 6502. The SoftCard hardware monitors that fetch and uses it as the CPU-switch trigger.
success
2.20's BIOS architecture is fundamentally different from 2.23's
Booting 2.20 reveals 6502 LOAD_CPM writes ~7 KB directly into LC RAM ($EB-$FF) -- unlike 2.23 which stages and redistributes. But $DA00 (Z-80 reset target) ends up empty.
success
End-to-end emulator-confirmed: 2.23 detects Videx as Pascal 1.1, 2.20 doesn't
Added Videx slot-3 model from a2fpga ROM 2.4. Boot trace: 2.23 stores device $06 (Pascal 1.1) for Videx; 2.20 stores $04 (Pascal 1.0). The 11-byte $C30B check is emulator-confirmed.
success
2.20 also makes two LOAD_CPM calls — not unique to 2.23
2.20 has two JSR $0E10 calls (LOAD_CPM-equivalent) at $1608 and $17D0 — just like 2.23 has two JSR $BBEB. The dual-load mechanism is shared between versions, not 2.23-specific.
success
2.20's BIOS dispatch table has 6 entries vs 2.23's 4
2.20 has a 6-entry dispatch table (96 bytes) at $DAFF vs 2.23's 4-entry (64 bytes) at $FAEB. Entries 0-3 are static handlers; entries 4-5 point into $E5-filled regions (runtime slots).
success
Factual byte-level trace of the v2.20 hang
Traced 2.20's CONOUT-on-Videx path byte-by-byte. Static evidence reaches handler at $DFBE → CALL $DAC5 (runtime-generator zone). Two failure modes identified, both consistent with the observed hang.
partial
The 6502 loader carries 270 bytes of embedded Z-80 code at $143A-$1547
~270 bytes of Z-80 code embedded in 2.23's 6502 loader at $143A-$1547. Calls BIOS routines, references state slots, contains LDIR. 2.23-specific — 2.20 has no analog.
success
Stage 1 emulator: 6502 boot finishes without ever writing $FA00
Stage-1 emulator boots SoftCard CP/M 2.23 in a 6502-only sandbox. Memory write log proves the 6502 never touches $FA00-$FFFF before handoff. So the BIOS proper has to be Z-80-generated.
success
Stage 2 emulator: BIOS jump table is at Z-80 $1A00, not $FAB8
Stage-2 adds Z-80 emulator + SoftCard XOR mapping + CPU-switch. Boot reaches Z-80 takeover at $0E36. BIOS jump table actually lives at Z-80 $1A00 (Apple $0A00), not $FAB8.
partial
Byte-by-byte loader diff: 2.20 vs 2.23 differ in 74% of bytes
Byte diff of the 3 KB loaders: 40 runs differ (2280 bytes, 74%). The 11-byte Videx fix is a small island in a larger rewrite, including one 1048-byte run.
success
Walking the 6502 RWTS the SoftCard borrowed from
Disassembled the 6502 RWTS at $0A00-$0FFF. Two 6502 code blocks plus a 199-byte Z-80 BIOS gap and a GCR codec page, interleaved across six sectors. PREP_HANDOFF moves it to $BA00-$BFFF.
success
The inter-CPU sync polling loop at Z-80 $1E39
Z-80 $1E39-$1E44 is the inter-CPU sync polling loop. Six instructions: LD A,($E000) / RLA / JR NC / LD ($E010),A / CCF / RRA / RET. Reads $E000 sync flag, waits for high bit, signals back via $E010.
success
Microsoft CP/M 2.20 vs 2.23: Digital Research's CP/M base also changed (2.0 → 2.2)
Diffed sysimg (CCP+BDOS) for both versions. 5807/5888 bytes differ — too much for relocation alone. Microsoft bumped the underlying Digital Research CP/M from 2.0 to 2.2 between releases.
success
2.20 has inline init where 2.23 has runtime code generation
2.20 cold-boot at $DB66 vs 2.23 at $FB70: same prologue, then 2.20 has inline init (CALL $DD8E / LD A,$01 / LD (E5B2),A) while 2.23 has runtime-marker bytes. Code generation REPLACED inline.
success
BIOS jump tables read: cold-boot is BOOT (offset 0), not LIST
Re-read both BIOS jump tables. BOOT=$FED1 in 2.23, $DEA8 in 2.20. LIST=$FB70/$DB66. Earlier devlogs confused LIST with BOOT. Both BOOT vectors land in runtime-generated regions.
success
The cold-boot generator: $FB3A in 2.23, $DB6E in 2.20 — and the device-code 6 branch only 2.23 has
Located the cold-boot generator. 2.23 at $FB3A dispatches on device codes 3, 4, and 6 (Pascal 1.1). 2.20 at $DB6E does the same loop but only dispatches on 3 and 4 — no Pascal 1.1 branch.
success
2.20 and 2.23 BIOSes have identical device-scan loops
Both BIOSes scan 9 entries from a device-code table — same instructions, same encoding. 2.23 adds preflight logic 2.20 lacks. The fix between versions wasn't in the BIOS; the scan was already there.
success
Real Z-80 code at trk2:physA — past where LOAD_CPM reads
BIOS extract grabs 8 sectors but only 5.3 are BIOS proper. trk2:physA contains real Z-80 code calling BIOS routines, but it's NOT in LOAD_CPM's staging — must be loaded by a later step.
partial
$FDB0 (the Pascal 1.1 callee) is a RET stub — driver init lives somewhere else
Disassembled the device-6 callee at $FDB0. It's a single RET. So 2.23's generator dispatches Pascal 1.1 to a no-op stub — the actual driver-install path is elsewhere, not in the cold-boot call site.
partial
Loader $191E: a second JSR $BBEB before the CPU switch
Loader $1900-$194B is the boot-finalization. It calls LOAD_CPM-equivalent ($BBEB) a second time with A=$80, likely loading BIOS handler templates past the main 29-sector read.
success
2.20 ships static device handlers in BIOS; 2.23 generates them at runtime
2.20 BIOS has a 256-byte page of static device handlers at $E0CC. 2.23 has no equivalent page — handlers are runtime-generated instead. This is the architectural shift between versions.
success
Two versions, two BIOS layouts: 2.20 vs 2.23 staging compared
Ran LOAD_CPM reconstruction on 2.20 (PRODOS_INTERLEAVE). Same 29-sector mechanism, different content layout: 2.20 BIOS at staging $1700; 2.23 at $1900. No 'Softcard' banner in 2.20 — added in 2.23.
success
Some BIOS routines disassemble cleanly; others are dispatch tables in disguise
Disassembled the 2.23 BIOS at the jump-table offset. CONOUT at $FB4D is real code. But CONST at $FB10 and CONIN at $FB1A decode as structured data — a 4-entry × 16-byte per-device dispatch table.
partial
Half the BIOS is zero on disk because it's generated at runtime
The 'missing' second 1 KB of BIOS at trk2:$08-$0B is all zeros on disk. SoftCard CP/M's BIOS isn't missing — half of it is generated at runtime by code that runs after the SoftCard switch.
success
The Z-80 callbacks read and write the BIOS second half
Z-80 callback instructions write into the BIOS second half: 'LD HL,$FECB / LD (HL),A', 'LD ($FED2),A'. The second half is runtime-generated routines + per-device state storage.
success
Tracing CONOUT into the BIOS hits the extraction wall
Followed CONOUT's CALL $FB45 into the BIOS. The chain hits routines that are zeros in our partial extract. About half of 2.23's BIOS is reachable; the per-device dispatch handlers aren't.
partial
The 6502 plants the Z-80's reset vector
Annotated the 2.23 6502 boot loader. Cleanest find: the bytes written into Apple $1000-$1002 are Z-80 'JP $FA00' — the BIOS cold-boot entry, planted at Z-80's reset vector before the CPU switch.
success
The cold-boot generator hides at the LIST jump-table entry
The 2.23 BIOS jump table's LIST entry ($FB70) is actually cold-boot init: stack setup, BDOS call vector at $0005 (JP $9C06), Z-80 reset vector rewritten from JP $FA00 to JP $FA03.
success
LOAD_CPM cracked: 29 sectors, $8000 staging, then Z-80 disk callbacks at $0A00
LOAD_CPM at $0BEB reads 29 sectors from trk0:$0B onward, stages $8000-$9CFF, splits into CCP+BDOS at $A300 (with the 'CP/M 60K Ver. 2.23' banner) and Z-80 disk callbacks at $0A00.
success
The runtime-code marker: FF FF 00 00 / F7 F7 00 00
The BIOS regions awaiting runtime code aren't all-zero on disk — they have a marker pattern (FF FF 00 00 / F7 F7 00 00). Populated BIOS code calls into these regions, confirming code-gen runs first.
success
$C800 isn't the Videx — it's the shared expansion-ROM window
The 'LD HL,$C800' in 2.23's CONOUT was overstated as direct Videx evidence. $C800-$CFFF is a shared expansion-ROM window that any slot card can occupy. Corrected the writeups; saved the lesson.
partial
Z-80 disassembler online; CONOUT loads HL with the Videx VRAM window
Added a Z-80 disassembler. First test on 2.23 BIOS: CONOUT at $FB4D has 'LD HL,$C800' — the shared expansion-ROM window. Targets expansion cards but not Videx-specific from this alone.
success
The BIOS that wouldn't byte-diff
Found the Z-80 BIOS jump tables — 2.20 at $DACC, 2.23 at $FAB8 (8 KB shift). The address shift plus non-contiguous on-disk layout made byte-aligned diffing useless. Pivoting to the 6502 side.
failure
What does device code 4 mean? What does device code 6 mean?
Three clues to what device codes mean: 2.20 has default codes baked in, 2.23 starts blank; both install a Z-80 dispatch table at $0380; 2.20 has Z-80 handler code at $0344 that 2.23 eliminated.
partial
Three disks, two versions, one shared boot stub
CPMV233.DSK is actually CP/M 2.23 (filename misleads); CPM220Disk1/2.po are the 2.20 two-disk distribution. The 6502 boot stub is byte-identical across all three — change isn't there.
success
Eleven bytes that recognize a Videx
CP/M 2.23 added 11 bytes to its 6502 boot loader's slot scanner that read the Pascal 1.1 signature at $Cn0B and tag Pascal-1.1 cards (Videx included) with a new device code $06. 2.20 ignores $Cn0B.
success
Microsoft CP/M doesn't boot on a Videx — and never did
Joshua Norrid found Microsoft SoftCard CP/M won't boot with a Videx — same failure on real cards and A2FPGA emulation. Version survey isolated the boundary: 2.20/2.20B fail; 2.23 works.
ongoing
a2fpga
4 entriesThunderClock complete. ProDOS timestamps work.
ThunderClock Plus emulation complete. ProDOS auto-detects the card on boot and file timestamps appear immediately. USB-C power persistence works as designed.
success
Videx emulation complete
Videx VideoTerm emulation passes all VIDEX_DIAG tests and boots Apple Pascal 1.3. Three upstream bugs fixed and submitted as PRs. README rewritten.
success
Samsung G9 won't display — HDMI switch fixes it
HDMI timing fixes resolved most displays. Samsung Odyssey Neo G9 still blank direct — but works perfectly through an HDMI switch. Likely electrical signal levels, not protocol.
partial
CI/CD attempt — OSS toolchain doesn't produce a usable bitstream
OSS Yosys/nextpnr toolchain synthesizes but doesn't produce a bitstream the Gowin programmer accepts. Shelved — proprietary Gowin IDE remains the only path to a flashable build.
failure
smalltalk-from-scratch
6 entries884 tests. CI is green.
All 884 tests pass in headless CI. Save/restore runs as a separate workflow job. Four Level 1 failures from last week are fixed.
success
Delete BitBlt
Deleted Form, BitBlt, Pen — three foundational 1980 classes. Canvas draws everything now. The image boots and renders.
success
First window
Smalltalk sent beDisplay. A WinForms window appeared. The image can now paint pixels.
success
Cold start: zero GC, 380ms
Rewrote the cold start loader. The full object graph loads in 380ms with zero GC collections.
success
The compiler compiles the compiler
Full compilation pipeline working: the standalone C# compiler compiles the entire Smalltalk-80 source, including the Smalltalk-80 compiler itself, to Blue Book bytecodes.
success
14,840 lines, zero parse errors
The standalone ANTLR4 compiler parsed the complete Smalltalk-80 system source — all 14,840 lines — without a single error.
success
apple-panic
4 entriesnibbler v0.1 reads the disk
First working build of nibbler correctly reads, validates, and reports on all 35 tracks of the Apple Panic protection disk.
success
45 kilobytes hiding in plain sight
The custom RWTS loads 45 KB of game data that doesn't fit in an Apple II. It's compressed. Decoding it took two days.
success
The code that isn't the code
The loader decodes itself in memory before it runs. The bytes on disk are not the bytes that execute.
success
The sectors that don't read
Standard DOS 3.3 read routines return garbage on every track past track 2. The disk is not broken — it's deliberate.
partial