Listing: 08-handoff-13A9.asm
Related: Dual-CPU
architecture · Type 21h SYSTEM
FILE · Memory map
Reached from: type-21h load success
JP 13A9 @11BD (also vector
002A)
Not used by: simple floppy JP 2400,
Winchester JP 2400 / CALL 2400
After a successful type-21h SYSTEM FILE load, the
Executive does not JP 2400. It builds an
OS parameter block in low RAM, copies a small Z80 stub, optionally swaps
8 bytes with a high window, reprograms the memory
mapper, then transfers with
JP FF4Ch.
High-level flow
type-21h load complete (file in banked RAM, tables @6600/6660, fields @67F1/F3)
│
▼
13A9 fill OS parameter / vector block @67E0–67F5
LDIR stub 0573 → 674C (18 bytes)
if (5FDD)≠0: map bank 3F; swap 8 bytes 67F0↔77F0; A=1
EX AF,AF'
program mapper port 16h (full walk over banks)
last OUT selects high-memory bank for Fxxx
│
▼
JP FF4Ch ; ★ leave Executive — never returns to menu
FF4C is not in this 8 KB boot ROM
(image ends at 1FFF). After the final mapper write,
FF4C is whatever physical memory is mapped into that
address — expected to be entry code from the loaded SYSTEM
image (or a vector the image installed).
Preconditions
(already done by type-21h path)
| Location | Content |
|---|---|
2400 |
SYSTEM header (sector 0) |
2600 |
Allocation map |
6500 |
80h-byte copy from first file block |
6600 / 6660 |
Drive / media config tables (12B1 /
12FB) |
Banked 7x00 windows |
SYSTEM body via bulk loop (0420 +
1231) |
(67F1) / (67F3) |
Words from file structure (2227) /
(2229) |
(67F6) |
0 (cleared at load start) |
(5FDD) |
RAM-size probe from cold boot (0 = small) |
Where the file body landed (bulk load)
0420 maps page index (2016) (starts at
4, steps +2):
bank = page >> 3
HL = 7000h + ((page & 7) << 8)
CALL 0436 ; OUT (16), ~bank
; then 1231 reads one 512-byte sector into HL
Examples:
| page | bank | buffer |
|---|---|---|
| 4 | 00 |
7400 |
| 6 | 00 |
7600 |
| 8 | 01 |
7000 |
| 16 | 02 |
7000 |
| … | … | … |
So the SYSTEM payload is striped across mapper banks
in the 7000–77FF window, not as one linear
blob at 2400.
1. Parameter block
@ 67E0–67F5
Filled at 13A9–13F0 (plus earlier type-21h
stores):
| Addr | Value set by 13A9 |
Notes |
|---|---|---|
67E0 |
FE00h |
High-memory related base |
67E2 |
1000h if (5FDD)=0, else
3000h |
RAM-size dependent base |
67E4 |
FE60h |
Second high-memory pointer |
67E6 |
same as 67E2 |
Mirror |
67E8 |
word at ROM (0FFBh) |
This dump: FFFFh
(0FFB–0FFC are FF) |
67EA |
0200h |
Constant (sector size / stride?) |
67EC |
48h |
Constant byte |
67EE |
E40Ch |
Constant word |
67F0 |
EAh |
8086 JMP FAR opcode if read as
x86 |
67F1–67F2 |
already from (2227) |
Far-jump offset if paired with EA |
67F3–67F4 |
already from (2229) |
Far-jump segment if paired with
EA |
67F5 |
copy of (5FDD) |
RAM-size flag for OS |
67F6 |
0 |
Load flag (from earlier) |
8086 far-jump image at
67F0
After setup (and optional swap), memory is:
67F0 EA ; JMP FAR
67F1 <offset from SYSTEM file (2227)>
67F3 <segment from SYSTEM file (2229)>
That is a complete 8086 far jump instruction image
in RAM. The Z80 handoff itself does
JP FF4C, not JP 67F0. The
far-jump block is almost certainly for dual-CPU / later 8086
entry, left as a prepared trampoline or BIOS-style vector for
the loaded OS.
High addresses FE00 /
FE60
Point into the top of the 64K Z80 space — consistent with an OS that relocates workspace to high memory after the mapper walk. Exact use is OS-defined (not implemented in this ROM beyond storing the constants).
2. Stub @ 0573 →
copied to 674C (18 bytes)
0573 LD A, 01h
0575 OUT (02h), A ; hardware signal (likely 8086 / bus control)
0577 LD B, 00h
0579 LD A, 00h
057B CPL ; A = FFh
057C LD C, 16h
057E OUT (C), A ; mapper: OUT (16), FFh ≡ bank select ~0 → bank 0 style
0580 IN A, (0Ch) ; status / sync read
0582 JP 0000h ; restart at 0000 under new map
| Item | Role |
|---|---|
| Location after copy | 674C–675D |
| Who runs it? | Not called by 13A9. Left for the
loaded OS (or dual-CPU protocol) to invoke |
Port 02 |
Only used here in analyzed code — handoff / second-CPU line |
JP 0000 |
Cold-style re-entry after remap (not FF4C) |
This is a secondary handoff helper, not the primary
JP FF4C path.
3. Optional high-RAM swap
(13F3–1409)
Only if (5FDD) ≠ 0 (larger RAM from cold probe):
LD D, 3Fh / CALL 0436 ; map bank 3F into 7000 window
B=8
swap bytes: (67F0…67F7) ↔ (77F0…77F7)
LD A, 01h ; mark “large RAM / swap done” in A
Then EX AF,AF' saves that A=01 for the
mapper epilogue.
If (5FDD)=0, swap is skipped; A' may be
stale/zero → treated as small-RAM path in the epilogue.
Effect: eight bytes of the parameter block
(including EA and the two words from the SYSTEM file) are
exchanged with the same offsets in the banked window — so a copy also
exists at 77F0 under bank 3F (and after swap,
67F0 holds what was in that window). Used so high-bank and
low copies of the dual-CPU vector stay coherent.
4. Memory mapper programming
(140B–1432)
Port and operation
C = 16h ; mapper data port (same as cold boot / 0436)
OUT (C), ~D ; bank select value = ones-complement of D
0436 uses the same rule: OUT (16h), ~D.
Main loop
D = 0
B = 0
loop:
OUT (16), ~D
B += 8
if B == 0: JP FF4C ; wrap after F8+8
D += 1
if B == F0h: D = CEh ; force video/attr bank slot
continue
if B == F8h: → epilogue
else loop
First phase: walks D = 00,01,02,… while
B = 08,10,…,F0, then forces
D=CEh for the B=F0 step
(screen/attribute bank used since cold init), then one more step to
B=F8.
Epilogue (when B
becomes F8)
EX AF, AF' ; restore A from swap path (0 or 1)
OR A
LD D, 3Fh
JR Z, loop ; small RAM: final map D=3F
LD D, 7Fh ; large RAM: final map D=7F
JR loop
One more iteration:
| RAM class | Final D |
Final OUT (16) |
Then |
|---|---|---|---|
Small (5FDD)=0 |
3Fh |
~3F = C0h |
B=F8+8=00 → JP FF4C |
| Large (swap ran) | 7Fh |
~7F = 80h |
JP FF4C |
So the last mapper write before transfer selects
bank view 3F or 7F (complemented on the wire).
That defines which physical page is visible in the window associated
with that select — including whatever backs address
FF4C.
Interpretation of B
B steps by 8 through
00…F8, matching the cold-boot mapper’s use of
B as a window base (high-address / slot
index). The handoff rebuilds the full map: sequential banks, special
CE for video, then a final high-RAM bank
(3F/7F) before entry.
5. Where control goes:
JP FF4C
What this ROM does not contain
- No code at offset
FF4CinV2_AC_Interleaved_XHE_XHO.bin(ROM is0000–1FFFonly). - No further Executive instructions after the jump.
What actually runs
- Z80
JP FF4Ch— still the Z80, under the post-walk mapper state.
- Bytes at
FF4Care outside the boot image: they must come from- RAM filled by the type-
21hbulk load and made visible atFxxxby the final map, and/or
- a fixed high-memory region the SYSTEM image is linked to
occupy.
- RAM filled by the type-
- That code is the loaded Executive OS / SYSTEM runtime, not the boot menu firmware.
Relationship to
2400 / simple boot
| Path | Transfer |
|---|---|
| Floppy simple / Winchester | JP 2400 or
CALL 2400 — first sector is the runnable
image |
Type 21h |
Multi-bank load + JP FF4C — entry is
high, after full remap |
Relationship to 8086
Prepared but not executed by this jump:
EA+ offset/seg at67F0— 8086 far jump image
- Stub
@674C—OUT (02),1then map +JP 0000(possible second-CPU / reset assist)
Likely sequence at a product level (inferred):
Z80: load SYSTEM → build 67xx → map → JP FF4C
FF4C code (from SYSTEM) runs on Z80 and/or triggers 8086
8086 may use far jump at 67F0 / stub at 674C
Confirming 8086 start requires a real SYSTEM disk image or bus
traces; this ROM only prepares those structures and
enters FF4C on Z80.
6. Annotated outline
13A9 (67E4)=FE60, (67E0)=FE00
(67E8)=(0FFB), (67EA)=0200, (67EC)=48
LDIR 0573 → 674C, BC=12h ; Z80 stub
(67EE)=E40C, (67F0)=EA
(67F5)=(5FDD)
(67E2)=(67E6)= 1000 or 3000 by 5FDD
if large RAM: map 3F; swap 67F0↔77F0 (8); A=1
EX AF,AF'
C=16, D=0, B=0
loop: OUT (16),~D
B+=8; if B==0 → JP FF4C
D++; if B==F0 D=CE; if B==F8 → epilogue D=3F/7F; loop
7. Return / failure
- No return to the menu on success.
- Failures during type-
21hload happen before13A9(155D/11C0).
- If
FF4Cis unmapped/wrong media, behavior is undefined (crash/halt) — not handled in boot ROM.
8. Open questions
- Exact hardware meaning of final
OUT (16),C0/80(which physical 2K/8K page sits atF000–FFFF).
- Bytes at
FF4Con a real SX/5000 SYSTEM disk after load.
- Whether
FF4Ccode is pure Z80, or a short Z80 stub that releases the 8086 into theEAtrampoline at67F0.
- Role of constants
E40C,48,FE00,FE60inside the vendor OS.
Cross-references
| Doc | Topic |
|---|---|
| Type 21h SYSTEM FILE | Load path that ends at JP 13A9 |
| Reset / entry path | Cold mapper / (5FDD) / port 16 |
| Memory map | 67xx, 7000 window, ports |