Skip to content

tools/c128: GEOS 128 crt from the boot disk's GEOBOOT128 - #63

Draft
kfox wants to merge 15 commits into
SensoriumEmbedded:mainfrom
kfox:geos128-ramcrt
Draft

kfox wants to merge 15 commits into
SensoriumEmbedded:mainfrom
kfox:geos128-ramcrt

Conversation

@kfox

@kfox kfox commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #60 (C128 tools): the first commits here are #60's. Review the last five, starting at 62ca47c.

geos128crt.py now builds the GEOS 128 crt from the GEOBOOT128 file on a GEOS 128 v2 boot disk instead of the U36 function ROM:

c1541 boot.d81 -read geoboot128 geoboot128.prg
python3 tools/c128/geos128crt.py geoboot128.prg geos128.crt

The cart LZ-packs GEOBOOT128 into its 32 KB, unpacks it into RAM bank 1 at $2B19 where the disk's boot loader would put it, and enters it at $2F3C as GEOS's ROM loader does. GEOS loads the rest from drive 8, so the cart runs the same kernal a disk boot does, and the boot disk picks the RAM expansion. That makes GeoRAM work (#61): GEOS 2.0r's GeoRAM GEOBOOT (GR81128) with 128 CONFIG 2.0R needs the 2.0r kernal, which the U36 ROM's build is not. The U36 path, its patches and its sd2iec 1581 fix are gone. The clock record (#62) stays, at $81F0.

Two things the cart has to do, both found on the TR+:

  • GEOS's RAM reset key. GEOS leaves CBM and a vector to $03E4 at bank 1 $FFF5. The C128 KERNAL jumps through it on every C128-mode reset, before initializing anything, and it survives every reset. The TR menu runs in C64 mode, which reuses $03E4, so after one GEOS session every later C128 crt (BASIC 7 included) crashed at reset until a power cycle. The tool breaks the C, as Berkeley's ROM build does.
  • IRQs at the cold start. The C128 enters a function ROM's cold start with IRQs on and the cart's top page mapped over the CPU vectors. The cold start masks IRQs first; IRQ points at the cold start and NMI at an RTI at $FFF9. Without it, a jiffy IRQ during the stub copy crashed about 1 launch in 3 (VICE's timing never hits it).

Tested: TR+ in an NTSC C128, 40-column, TR GeoRAM 512 KB, SD2IEC with the GR81128 boot D81: 20 launches in a row reached GEOS with no power cycle (16 on the prototype, 4 on the final build, which differs from it only in the IRQ vector); a DMA read of the screen showed the DeskTop with a RAM 1571 as drive B and the TR-kept clock. VICE: the GeoRAM build reaches the DeskTop in 40 and 80 columns; the stock GEOBOOT128 build with a 512 KB REU reaches GEOS's screen (DeskTop not inspected). TR+ with its 512 KB REU, the stock GEOBOOT128 build and the stock 1581 boot disk (GEOS128.D81): 6 launches in a row reached the DeskTop, and GEOS reports the REU (ramExpSize 8, sysRAMFlg $50).

Draft until the GEOS package is roughly complete.

kfox added 15 commits October 15, 2026 14:39
…ript

geos128crt.py wraps a GEOS 128 v2 U36 ROM as a C128 .crt with the
cartridge-port loader patch, plus the sd2iec 1581 hook for the English
1581 ROM. iecdecode.py and vicemon.py are how the 1581 restart loop was
found: decode the drive commands from a VICE KERNAL trace, with sd2iec's
fast-loader CRC. type.py types a line by DMA, in C64 or C128 mode.
GEOS 128 handles years past 1999 on its own; what it lacks is a clock
source, so every cold boot starts at 1:00 PM on 3/23/92. The loader's
unpack hook now calls a routine in unused ROM filler that sets CIA1's
TOD and GEOS's date from a tagged record, which the tool fills with the
build time or --clock and the TR can keep current. The Am1581 sd2iec
fix moves into the same ROM filler, since the stub's 34 free bytes no
longer hold both.
…T128 instead of the U36 ROM

The cart unpacks GEOBOOT128 into RAM bank 1 and enters it as GEOS's ROM
loader does, so GEOS runs the same kernal a disk boot loads: GeoRAM works
with GEOS 2.0r's GEOBOOT, and the U36 ROM's own kernal and its sd2iec 1581
fix are gone. It breaks GEOS's RAM reset key, which crashed every later C128
crt until a power cycle, and masks IRQs in the cold start, which the C128
enters with the cart's top page mapped over the CPU vectors.
…to the cold start, and checks the rest of its baked-in operands

An IRQ taken through the RTI at $FFF9 is still asserted when the RTI
returns, and the 6502 takes it again before the next instruction, so one
arriving between the KERNAL's call and the SEI hung the boot.
…nd CLOCK, and refuses a pack that puts CBM at $C007
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant