VECTOR 4/8086 - How to Boot a Custom Floppy (Simple Path)From Inside a Vector Graphic SX/5000 (Vector 4/8086 variant)

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 24002401 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: FAFF.
+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 80h9Fh 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 …

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

        END

4.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.bin

z80asm (z88dk):

z80asm -b -o=hello2400.bin hello2400.asm

4.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())
PY

Expected:

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))
PY

5. 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
sync

That 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
sync

5.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 write

FluxEngine (example pattern):

fluxengine write ibm -s hello2400.img --drive=0 --tracks=0-0

Exact 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

  1. Create hello2400.bin (512 bytes) under WSL or copy from Linux.
  2. 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).
  3. 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

  1. Power on with the custom floppy in the drive (door closed).
  2. Let Executive reach the menu
    (VECTOR GRAPHIC SX/5000 [XH] / EXECUTIVE - REVISION 2.00 (AC)).
  3. Press F (Load system from floppy).
  4. 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

If anyone has additional information, manuals, schematics, or software for this Vector 4/8086 CPU variant (Vector Graphic SX/5000), please contact me.

email

Document generated: July 31,2026
Updated: July 31, 2026