Related: Floppy load path · Error codes · How to boot hard disk
Practical guide for the Vector Graphic SX/5000 / Vector
4-8086 Executive ROM
Revision 2.00 (AC) — image
V2_AC_Interleaved_XHE_XHO.bin.
This uses the simple boot path (menu
[F] → 1000h), not
type-21h SYSTEM FILE load.
Goal: one 512-byte sector that the ROM loads to 2400h,
then jumps to, printing:
Hello. We booted!
and then halts (or loops).
1. What the ROM does (floppy [F])
Menu [F] or vector 000F
→ select unit 3 (floppy)
→ geometry key FEh (default), restore
→ read LBA 0 / first sector → RAM 2400h (512 bytes)
→ validate header
→ JP 2400h if checks pass and type ≠ 21h
Full analysis: Floppy load path.
2. Exact checks you must pass
All offsets are within the first sector, relative to
byte 0 of that sector
(after load they appear at 2400h + offset).
| Offset | RAM after load | Requirement |
|---|---|---|
+00…+01 |
2400–2401 |
16-bit word ≠ 0 (little-endian). ROM does
LD HL,(2400) / OR H,L / if NZ →
JP 2400 (always enters at
2400, not “call the word as a pointer”). |
+02 |
2402 |
Must be 02h (format id). Fail →
UNRECOGNIZED SYSTEM DISKETTE. |
+15 |
2415 |
Geometry key for second drive setup. Use
FEh (ROM table key; same as default floppy
select). Other valid keys: FA–FF. |
+42 |
2442 |
Flags: (byte & C0h) == 80h (bits
7–6 = 10). Fail →
UNRECOGNIZED SYSTEM DISKETTE. |
+42 low 6 bits |
type | Must not be 21h. If type is
21h, ROM takes the full SYSTEM FILE path (directory + map),
not simple boot. Use 80h (type
00) or any 80h–9Fh except
A1h (80h+21h). |
Critical layout gotcha
You cannot place a normal JP nnnn
(C3 lo hi) at offset 0 if you also need offset 2 =
02h, unless the jump target’s high address byte is
02h (i.e. target in 02xx — ROM space, useless
for your code).
Recommended pattern:
offset 0: 18 01 JR start ; relative jump
offset 2: 02 format id ; required
offset 3: start: … your code …
- Word at
+00=0118h≠ 0 → pass.
- Byte at
+02=02h→ pass.
- CPU continues at offset 3 (
2403h).
3. Recommended 512-byte sector layout
Offset Size Content
------ ---- ------------------------------------------------
0000 2 18 01 JR to 0003
0002 1 02 format id
0003 … CODE your program (print + halt)
0015 1 FE geometry key (pad zeros 0003..0014 as needed)
0016 44 00… reserved / padding through 0041
0042 1 80 flags: simple boot, type 0
0043 … 00 or more code/data if you jump here
01FF — end of 512-byte sector
Fill unused bytes with 00. Total image size
exactly 512 bytes for a single-sector boot test.
You do not need a DOS boot sector, BPB, or “system
tracks” for this path. The ROM only cares about this header + runnable
code at 2400.
4. Minimal Z80 program (uses ROM console)
After the menu path runs, the Executive ROM is still mapped low and console I/O is initialized. You can call:
| Addr | Routine |
|---|---|
03E4 |
Print bit-7-terminated string at
HL |
0443 |
Put character in A (bit 7 cleared) |
Last character of a string for 03E4 must have
bit 7 set (e.g. '!' | 80h).
4.1 Source
(hello2400.asm) — sjasmplus / pasmo / z80asm style
; hello2400.asm — simple-boot sector for SX/5000 Executive 2.00 (AC)
; Assemble to binary origin 2400h, then take first 512 bytes.
ORG 2400h
; --- ROM-required header prefix ---
jr start ; 18 01 — word at 2400 nonzero
db 02h ; format id at 2402
start:
ld hl, msg
call 03E4h ; print bit-7-terminated string
halt ; stop CPU
forever:
jr forever ; if HALT is woken, spin
msg:
; CR, LF optional; last char bit7 set
db 0Dh, 0Ah
db "Hello. We booted!"
db '!' | 80h ; terminator for CALL 03E4
; --- pad to geometry key at +15h (2415h) ---
ds 2415h - $, 0
db 0FEh ; geometry key
; --- pad to flags at +42h (2442h) ---
ds 2442h - $, 0
db 80h ; flags: 10xxxxxx, type 00
; --- pad sector to 512 bytes ---
ds 2400h + 512 - $, 0
END4.2 Assemble (examples)
sjasmplus:
sjasmplus --raw=hello2400.bin hello2400.asm
# ensure 512 bytes:
truncate -s 512 hello2400.bin # if assembler emitted less
# or:
python3 -c "d=open('hello2400.bin','rb').read(); open('hello2400.bin','wb').write(d[:512].ljust(512,b'\0'))"pasmo:
pasmo -d hello2400.asm hello2400.binz80asm (z88dk):
z80asm -b -o=hello2400.bin hello2400.asm4.3 Verify the image before writing
python3 <<'PY'
d=open("hello2400.bin","rb").read()
assert len(d)==512, len(d)
print("word2400", hex(d[0]|d[1]<<8), "nonzero", (d[0]|d[1]<<8)!=0)
print("format ", hex(d[2]), "ok", d[2]==2)
print("geom+15 ", hex(d[0x15]))
print("flags42 ", hex(d[0x42]), "topbits", hex(d[0x42]&0xC0), "type", hex(d[0x42]&0x3F))
print("head ", d[:16].hex())
PYExpected:
word2400 0x118 nonzero True
format 0x2 ok True
geom+15 0xfe
flags42 0x80 topbits 0x80 type 0x0
4.4 Pure hex alternative (no assembler)
If you only want a fixed “Hello. We booted!” sector, build with Python:
python3 <<'PY'
# Minimal simple-boot sector
code = bytes([
0x18, 0x01, # JR start
0x02, # format
# start @ 2403
0x21, 0x0E, 0x24, # LD HL,240Eh (msg address — adjust if you change layout!)
0xCD, 0xE4, 0x03, # CALL 03E4
0x76, # HALT
0x18, 0xFE, # JR $
])
# Better: compute msg address after building
msg = b"\r\nHello. We booted!" + bytes([ord('!')|0x80])
# rebuild with correct HL
start = bytes([
0x18, 0x01,
0x02,
])
body_prefix = bytes([
# LD HL, msg — patch later
0x21, 0x00, 0x00,
0xCD, 0xE4, 0x03,
0x76,
0x18, 0xFE,
])
# msg immediately after body_prefix
msg_addr = 0x2400 + len(start) + len(body_prefix)
body = bytes([0x21, msg_addr & 0xFF, msg_addr >> 8]) + body_prefix[3:] + msg
sector = bytearray(512)
sector[0:len(start)+len(body)] = start + body
sector[0x15] = 0xFE
sector[0x42] = 0x80
open("hello2400.bin","wb").write(sector)
print("wrote hello2400.bin", sector[:0x30].hex())
print("msg at", hex(msg_addr))
PY5. Writing the sector to a physical floppy (Linux)
You need a raw 512-byte image at LBA 0 (cylinder 0, head 0, sector 1 on a classic CHS floppy).
5.1 Identify the drive
lsblk -d -o NAME,SIZE,MODEL,TRAN
# often /dev/fd0 for a real floppy controller
# or a USB floppy: /dev/sdX (BE CAREFUL)Warning: dd to the wrong device
destroys disks. Double-check the device name.
5.2 Write with dd (real
/dev/fd0)
# optional: low-level format first (40 or 80 track depends on drive/media)
# superformat /dev/fd0 fdformat /dev/fd0 # if available
sudo dd if=hello2400.bin of=/dev/fd0 bs=512 count=1 conv=fsync
syncThat writes only the first sector. Enough for this ROM path.
5.3 USB floppy
# find device, e.g. /dev/sdb — confirm with lsblk, NOT your hard disk
sudo dd if=hello2400.bin of=/dev/sdX bs=512 count=1 conv=fsync oflag=direct
sync5.4 Greaseweazle / FluxEngine (no native PC floppy)
Create a single-sector image and write track 0. Example sketch with
Greaseweazle (syntax varies by version; check
gw --help):
# Pack 512-byte sector into a track image your tool understands, then e.g.:
gw write --drive=0 --tracks=0 hello2400.img
# or convert raw sector → SCP/HFE with HxC / fluxengine, then writeFluxEngine (example pattern):
fluxengine write ibm -s hello2400.img --drive=0 --tracks=0-0Exact flags depend on density (SD/DD), 40 vs 80 track, and 8” vs 5.25” media. Vector floppies are often 5.25” DD-class; match media to the drive on the SX/5000.
5.5 ImDisk / Windows
- Create
hello2400.bin(512 bytes) under WSL or copy from Linux.
- Use a raw writer (e.g. RawWrite, dd for
Windows, or ImDisk to mount a 512-byte/virtual floppy and copy
— raw sector 0 write is more reliable than file copy into a FAT
image).
- Prefer writing LBA 0 only, not a full FAT12 filesystem, unless you place the 512 bytes as the true boot sector of that image and write the whole image starting at LBA 0.
5.6 Emulator note
If you use a system emulator with this ROM, point its floppy LBA 0 at
hello2400.bin. Hardware is the ground truth for this rare
machine.
6. Boot procedure on the machine
- Power on with the custom floppy in the drive (door closed).
- Let Executive reach the menu
(VECTOR GRAPHIC SX/5000 [XH]/EXECUTIVE - REVISION 2.00 (AC)).
- Press
F(Load system from floppy).
- Drive should seek/read; then your code runs at
2400h.
What you should see if it works
After the usual title/menu (and any “LOADING” if you came from a path that prints it), the screen should show something like:
Hello. We booted!
then the machine halts (cursor may stop; no menu return).
If you used only HALT without a loop, a stray interrupt
could continue; the sample includes a tight JR loop after
HALT for safety.
7. Common failure messages
Printed roughly as: < ERROR - MESSAGE >
| Message | Meaning for this project |
|---|---|
| UNRECOGNIZED SYSTEM DISKETTE | (2402)≠02, or (2442)&C0h≠80h, or
simple-boot word at 2400 is 0, or type/flags
rejected. Most common for a wrong header. |
| DISKETTE DOOR OPEN | Drive door / disk not ready. |
| DISK READ | Sector 0 read failed (media, density, alignment, bad disk). |
| DRIVE RESTORE | Seek/restore failed. |
| CONTROLLER NOT RESPONDING / TIMEOUT / CONTROLLER FAULT | Floppy controller / cable / power. |
| ILLEGAL DISK PARAMETER | Geometry key / driver params inconsistent (check +15 =
FEh). |
| (seeks forever / no error) | Wrong density or not LBA 0; or unit not unit 3. |
| Garbage / crash after read | Header OK but code at 2400 wrong
(e.g. CALL 03E4 with bad HL, or jumped into
data). |
| Type-21h behavior (long load / SYSTEM FILE errors) | Flags type is 21h (2442 low 6 bits). Use
80h, not A1h. |
Full tables: Error codes.
8. Checklist
9. References
| Doc | Topic |
|---|---|
| Floppy load path | ROM floppy path |
| Reset / entry path | Menu / console init |
| disasm/02-floppy-load.asm | Listing @1000 |
| disasm/04-helpers-console.asm | 03E4 / 0443 |