Related: Winchester load path · Winchester parameters · How to boot floppy
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 Winchester path (menu
[W] → 1066h / helper 1072h),
which is a simple header + JP 2400 path —
not the floppy type-21h multi-file
loader.
Goal: put one 512-byte block at LBA 0 of the fixed
disk so the ROM loads it to 2400h, validates it, and jumps
to your code that prints:
Hello. We booted!
1. What the ROM does (Winchester [W])
Menu [W] or vector 0012
→ CALL 1072
select unit 0 (Winchester)
restore
read LBA 0 → RAM 2400h via low-level 1638 (512 bytes INIR)
validate header
CALL 1434 with A=0 (geometry from header)
→ if OK: JP 2400h
Auto-boot (if ROM config allows) also
CALL 1072 then
CALL 2400 after printing
LOADING - PLEASE WAIT.
Full analysis: Winchester load path.
2. Differences from floppy (read this first)
| Item | Floppy [F] | Winchester [W] |
|---|---|---|
| Unit | 3 | 0 |
| First-sector API | 14A8 (geometry-aware) |
1638 direct |
Format id +02 |
must be 02h |
must be 02h |
Error if +02 wrong |
UNRECOGNIZED SYSTEM DISKETTE (#1) | UNRECOGNIZED MEDIA FORMAT (#2) |
Flags +42 / type 21h |
Checked (need &C0==80, type≠21 for
simple) |
Not checked |
| Config byte | not compared on simple path | +0B must equal ROM
(09AAh) |
| Error if config mismatch | — | CONFIGURATION MISMATCH (#5) |
| Geometry before first read | Table key FEh at select |
None (raw read) |
| Geometry after validate | From +15 / flags via 1434 A=3 |
From header +10…+14 via
1434 A=0 |
| Success | JP 2400 or type21 → FF4C |
Always JP 2400 (menu) |
This ROM dump: (09AAh) = C8h. Your
sector must have offset
+0Bh = C8h.
If you burn a different Executive revision, read byte 09AA
from that ROM and match it.
# From the interleaved image used on your machine:
python3 -c "print(hex(open('ROM/V2_AC_Interleaved_XHE_XHO.bin','rb').read()[0x9AA]))"
# → 0xc8 for the analyzed dump3. Exact checks you must pass
Offsets relative to LBA 0 sector start (= 2400h after
load):
| Offset | RAM | Requirement |
|---|---|---|
+00…+01 |
2400–2401 |
After success, ROM JP 2400 (menu) or
CALL 2400 (auto-boot). First two bytes
should be valid code start; use the same JR +
format trick as floppy so +02 can be
02h. |
+02 |
2402 |
02h. Fail → UNRECOGNIZED MEDIA
FORMAT. |
+0B |
240B |
Must equal ROM 09AAh (this dump:
C8h). Fail → CONFIGURATION
MISMATCH. |
+10…+14 |
2410… |
Consumed by 1434 (A<3) as geometry after the config
check. Prefer zeros for a first experiment, or copy
values from a known-good vendor disk if restore fails. |
+15, +42 |
Not required by Winchester path (unlike floppy). You may still set them for documentation compatibility. |
Same JR header
trick as floppy
+00 18 01 JR start
+02 02 format id
+03 … code (start)
+0B C8 config id (this ROM)
Word at +00 is nonzero; execution begins at
+03 after the short JR.
4. Recommended 512-byte LBA 0 layout
Offset Size Content
------ ---- ------------------------------------------
0000 2 18 01 JR start
0002 1 02 format id
0003 … CODE print + halt (same as floppy)
000B 1 C8 config match for ROM 09AA=C8
000C 4 00 pad
0010 5 00 geometry fields for 1434 (start simple)
0015 1 00 or FE optional
0042 1 80 optional (ignored by W path)
01FF — pad to 512 bytes with 00
5. Minimal Z80 program
Same console calls as floppy: ROM still low, console already up when you use the menu.
; hello_hd.asm — Winchester LBA0 simple image for Executive 2.00 (AC)
; Config byte +0B = C8h matches analyzed ROM (09AA).
ORG 2400h
jr start
db 02h ; +02 format
start:
ld hl, msg
call 03E4h
halt
jr $
msg:
db 0Dh, 0Ah
db "Hello. We booted!"
db '!' | 80h
; --- config id at +0Bh ---
ds 240Bh - $, 0
db 0C8h ; MUST match ROM 09AAh
; --- geometry region +10.. (leave zero for first try) ---
ds 2410h - $, 0
; 2410..2414 = 0
; --- pad to 512 ---
ds 2400h + 512 - $, 0
ENDAssemble like the floppy guide; force 512-byte output.
Python one-shot image
python3 <<'PY'
CONFIG = 0xC8 # ROM[0x9AA] for this dump — change if your ROM differs
msg = b"\r\nHello. We booted!" + bytes([ord("!") | 0x80])
# layout: 18 01 02 | LD HL,msg | CALL 03E4 | HALT | JR $ | msg
prefix = bytes([0x18, 0x01, 0x02])
# body without HL address
call_print = bytes([0xCD, 0xE4, 0x03, 0x76, 0x18, 0xFE])
msg_addr = 0x2400 + len(prefix) + 3 + len(call_print) # after LD HL,nn
ld_hl = bytes([0x21, msg_addr & 0xFF, msg_addr >> 8])
body = ld_hl + call_print + msg
sec = bytearray(512)
sec[0:len(prefix)+len(body)] = prefix + body
sec[0x0B] = CONFIG
# geometry 0x10..0x14 already 0
open("hello_hd.bin", "wb").write(sec)
d = sec
assert d[2] == 2 and d[0x0B] == CONFIG
print("OK hello_hd.bin config+0B=", hex(d[0x0B]), "head", d[:16].hex())
PYVerify:
python3 -c "
d=open('hello_hd.bin','rb').read()
print(len(d), 'format', hex(d[2]), 'config', hex(d[0x0B]))
print('word', hex(d[0]|d[1]<<8))
"6. Getting the image onto the Winchester
This is the hard part. The SX/5000 uses a vendor disk
controller (ports A0–A8 in this ROM),
not a modern AHCI/SATA drive you can plug into a PC.
6.1 Realistic options
| Method | Practicality |
|---|---|
| A. Write LBA 0 from the Vector itself | Best if you already have any bootable floppy or serial loader that can write sector 0. |
| B. Donor / known-good drive | Clone track/sector 0 from a working SX/5000 disk with a tool that talks to the same controller (rare). |
| C. Controller + drive on a bench with custom software | Requires knowing the controller command set (partially in disasm/05-helpers-disk.asm /
1638). Advanced. |
| D. Emulator | If your emulator maps “Winchester” LBA 0 to a file, point it at
hello_hd.bin. |
| Greaseweazle | Floppy flux tool — does not write MFM Winchester drives. Use for floppies only (How to boot floppy). |
6.2 Preferred path: bootstrap with a floppy, then write the HD
- Build and boot hello2400.bin on floppy (see floppy
guide) or use a real vendor system disk.
- From a small program (or monitor), call the ROM disk write path if
available, or poke the controller the same way
1638reads (inverse: program address regs, issue write,OTIRdata).
- There is no public high-level “INT 13” in this ROM
analysis; you must either:
- use OS services after a full vendor SYSTEM boot, or
- implement a write using ports
A2–A7/A0(mirroring the read path).
- use OS services after a full vendor SYSTEM boot, or
Sketch of read path to invert (for experts):
168B program A4/A5/A3/A2 from E/D/B, unit on A6
1638 wait ready, OUT (A7),20h read, INIR×2 from A0 → 512 bytes
A write command will differ in the OUT (A7),xx opcode;
determine from vendor docs or by tracing a working OS format utility. Do
not guess on a production drive without a backup.
6.3 If you only have Linux and the bare drive
Without the original controller:
- You generally cannot
dda modern SATA/IDE image and expect the Vector board to accept it.
- If the “Winchester” is a period drive on a period
controller still attached to a PC ISA clone (unusual), only
then might a raw LBA0
ddapply — still verify sector size 512 and that LBA 0 is what unit 0 restore+read uses.
# ONLY if you are 100% sure /dev/sdX is the target and geometry matches:
sudo dd if=hello_hd.bin of=/dev/sdX bs=512 count=1 conv=fsyncFor almost all readers of this doc: use the Vector + floppy bootstrap, not a random Linux disk device.
6.4 Auto-boot note
This ROM has (09AA) ≠ 0 (C8h), so cold boot
may auto-try Winchester after self-test (phase
"02"). If LBA 0 is invalid, you get an error and fall to
the menu; you can still press W manually.
To force menu-only testing, you would need a ROM with
09AA=00 (not recommended unless you know how to burn
EPROMs).
7. Boot procedure on the machine
- Ensure Winchester is powered, terminated, and ready (controller
responds — menu may probe at start).
- Power on; wait for Executive menu (or auto-boot attempt).
- Press
Wif not auto-booting.
- On success:
JP 2400runs your code.
What you should see if it works
Hello. We booted!
then halt/loop — same as the floppy test.
If auto-boot runs first you may also see:
LOADING - PLEASE WAIT
before your message (auto-boot path prints that, then
CALL 2400).
8. Common failure messages (Winchester)
| Message | Typical cause |
|---|---|
| UNRECOGNIZED MEDIA FORMAT | Byte +02 ≠ 02h. |
| CONFIGURATION MISMATCH | Byte +0B ≠ ROM 09AAh (use
C8h for this dump). |
| CONTROLLER NOT RESPONDING / TIMEOUT | Cable, power, controller, or drive not ready (unit 0). |
| DISK READ / DRIVE RESTORE | Media fault, wrong drive type, or geometry after 1434
rejected. |
| CONTROLLER FAULT / ILLEGAL DISK PARAMETER | Bad address/geometry programming. |
| Returns to menu with no message | 1072 failed with NZ/CF handled by caller; check cables
and +02/+0B. |
| UNRECOGNIZED SYSTEM DISKETTE | You booted with [F] by mistake, or wrong media path. |
Floppy-only messages like DISKETTE DOOR OPEN should not appear on a pure Winchester attempt (different unit path).
9. Side-by-side header: floppy vs hard
| Offset | Floppy simple | Winchester |
|---|---|---|
+00 |
18 01 JR |
same recommended |
+02 |
02 |
02 |
+0B |
don’t care | C8 (match 09AA) |
+15 |
FE geometry |
optional |
+42 |
80 flags |
optional (ignored) |
| Code | CALL 03E4 / HALT |
same |
You can build one 512-byte image that satisfies both:
+00 18 01
+02 02
+0B C8
+15 FE
+42 80
+03 code…
Then the same payload can be written to floppy LBA 0 or Winchester LBA 0 for dual testing.
python3 <<'PY'
CONFIG, GEOM, FLAGS = 0xC8, 0xFE, 0x80
msg = b"\r\nHello. We booted!" + bytes([ord("!")|0x80])
prefix = bytes([0x18,0x01,0x02])
call_print = bytes([0xCD,0xE4,0x03,0x76,0x18,0xFE])
msg_addr = 0x2400 + len(prefix) + 3 + len(call_print)
body = bytes([0x21, msg_addr&0xFF, msg_addr>>8]) + call_print + msg
sec = bytearray(512)
sec[0:len(prefix)+len(body)] = prefix+body
sec[0x0B] = CONFIG
sec[0x15] = GEOM
sec[0x42] = FLAGS
open("hello_both.bin","wb").write(sec)
print("hello_both.bin ready for F or W")
PY10. Checklist (Winchester)
11. References
| Doc | Topic |
|---|---|
| Winchester load path | ROM Winchester path |
| How to boot floppy | Floppy simple boot (easier to test first) |
| Error codes | Error tables |
| disasm/06-winchester-load.asm | Listing 1066/1072 |
Recommendation: Prove your payload on floppy
[F] first (How to boot floppy),
then add +0B=C8 and move the same sector to the Winchester
once you have a safe write path on the real hardware.