TRS-80 DOS - VTOS v4.0.2 for the Model I - BOOT/SYS Disassembled
Page Customization
Page Index
BOOT/SYS
Other Navigation
Introduction/Summary:
VTOS 4.0.2 BOOT/SYS Disassembly - Boot Sector (Model I)
The BOOT/SYS file is the first thing loaded when the TRS-80 boots from disk. The Model I ROM boot routine reads Track 0, Sector 0 from the floppy disk into RAM at 4200H and jumps to it. The BOOT/SYS file in VTOS 4.0.2 is unique among TRS-80 operating systems because it contains two completely independent boot code sectors: one for the standard Radio Shack Expansion Interface (single-density, WD1771 FDC accessed via memory-mapped I/O at 37ECH-37EFH) and one for the Lobo LX-80 Expansion Interface (which uses a different disk controller interface). This dual-platform design is confirmed by Tim Mann's account of VTOS internals.
Both boot sectors share the same fundamental task: read SYS0/SYS from the disk, parse its /CMD-format load module structure, load the code into memory, and jump to the SYS0 entry point. If SYS0 cannot be found or a disk error occurs, the boot code displays "NO SYSTEM" or "DISK ERROR" and halts.
The BOOT/SYS file on disk occupies 5 sectors (1280 bytes) organized as follows:
| Sector | File Offset | RAM Address | Purpose |
|---|---|---|---|
| 0 | 0000H-00FFH | 4200H-42FFH | Single-density boot code (Radio Shack Expansion Interface) |
| 1 | 0100H-01FFH | 4200H-42FFH | Double-density boot code (Lobo LX-80 Interface) |
| 2 | 0200H-02FFH | 4400H-44FFH | Directory sector: jump vector table, disk serial/password, Disk Geometry parameters |
| 3 | 0300H-03FFH | 4500H-45FFH | GAT (Granule Allocation Table) and disk label |
| 4 | 0400H-04FFH | 4600H-46FFH | HIT (Hash Index Table) - empty on this disk image |
Only one boot sector is loaded during any given boot. The Model I ROM loads Track 0, Sector 0, which on a standard Radio Shack formatted disk is the single-density sector (Sector 0). On a Lobo LX-80 formatted disk, the ROM loads the double-density sector (Sector 1). Both sectors load at 4200H and execute from there.
The boot code structure follows the TRSDOS 2.x convention established by Randy Cook. It begins with 00H FEH, which serves dual purpose: as Z80 code it is NOP / CP 11H (harmless), but it also functions as a /CMD comment record header if the file is loaded as a /CMD program (the BOOT/SYS.WHO easter egg trick from TRSDOS works by exploiting this dual interpretation).
Ihteresting Tidbits about the Lobo portion:
- The LX-80 boot uses IY-indexed memory access (FD 7E xx / FD 77 xx) to read and write a hardware descriptor table, abstracting the FDC interface so the same boot code works on different disk controllers.
- It includes a proper 8-bit shift-and-add multiply routine at 42D3H (ADD A,A / SLA E / JR NC / ADD A,D / DJNZ) that computes sectors-per-track dynamically from drive parameters.
- Self-modifying code at 422DH patches the SUB operand at 42A5H with the computed sectors-per-track, replacing the single-density boot's hardcoded SUB 0AH (10 sectors/track). This is the only self-modifying code in the file.
- The FDC dispatch at 42D1H is a single JP (IY) instruction, which is an elegant hardware abstraction layer - the LX-80 ROM sets IY to point to its FDC driver before loading the boot sector.
Key Memory Locations
| Address | Bytes | Purpose |
|---|---|---|
| 37E0H | 1 | Drive select latch (Model I, memory-mapped). Bits 0-3 select drives 0-3. |
| 37E1H | 1 | Drive select latch (alternate address, same physical latch as 37E0H). Boot code writes 01H here to select Drive 0. |
| 37ECH | 1 | WD1771 FDC Command/Status Register (memory-mapped) |
| 37EDH | 1 | WD1771 FDC Track Register (memory-mapped) |
| 37EEH | 1 | WD1771 FDC Sector Register (memory-mapped) |
| 37EFH | 1 | WD1771 FDC Data Register (memory-mapped) |
| 4200H | 256 | Boot sector load address. Active boot code occupies 4200H-42FFH. |
| 41E0H | - | Stack pointer for single-density boot (grows downward) |
| 4160H | - | Stack pointer for double-density boot (grows downward) |
| 5100H | 256 | Sector buffer. Boot code reads disk sectors here for /CMD parsing. |
| 5116H | 2 | Directory entry pointer within loaded sector buffer (track/sector of SYS0) |
Major Routines - Single-Density Boot (Sector 0)
| Address | Name / Purpose |
|---|---|
| 4200H | Boot Entry Initialization: disable interrupts, set stack, select drive 0, read directory |
| 4242H | /CMD Parser Main loop: reads /CMD record type bytes, dispatches to data load (type 01), skip (type 02), or transfer (type 03) |
| 4279H | Get Next Byte Returns next byte from sector buffer; auto-reads next sector when buffer exhausted |
| 429EH | Display Message Displays 03H-terminated string at (HL) via ROM CALL 0033H |
| 42ACH | Read Sector Reads a single sector from disk using WD1771 FDC via memory-mapped I/O |
| 42B4H | FDC Core Low-level FDC command execution: issues command, waits for completion, transfers data |
| 42E4H | Init Screen Msg Data: screen clear codes (1CH=clear screen, 1FH=home cursor), terminated by 03H |
| 42E7H | No System Msg Data: "NO SYSTEM" with screen positioning prefix 17H E8H |
| 42F3H | Disk Error Msg Data: "DISK ERROR" with screen positioning prefix 17H E8H |
Major Routines - Double-Density Boot (Sector 1)
| Address | Name / Purpose |
|---|---|
| 4200H | Boot Entry Initialization: disable interrupts, set stack to 4160H, configure IY for Lobo interface |
| 4260H | /CMD Parser Same logic as single-density, with Lobo-specific sector read calls |
| 4297H | Get Next Byte Same function, calls Lobo read sector routine |
| 42B7H | Display Message Same display function as single-density |
| 42C5H | Read Sector Disk read using Lobo LX-80 interface (IY-indexed port access) |
| 42D1H | LX-80 FDC Dispatch Dispatches FDC command via JP (IY) for Lobo hardware abstraction |
| 42D3H | CRC/Multiply CRC or sector-to-granule calculation using shift-and-add multiply loop |
| 42E4H | Init Screen Msg Data: 03H (immediate terminator - no screen clear in DD boot) |
| 42E7H | No System Msg Data: "NO SYSTEM" (same text, shifted 2 bytes earlier in sector) |
| 42F1H | Disk Error Msg Data: "DISK ERROR" |
Disk Structures (Sectors 2-4)
| Offset | Sector | Content |
|---|---|---|
| 0200H | 2 | Directory sector header: 40H at offset 0 (64 entries flag) |
| 0220H-0247H | 2 | Jump vector table: four JP 4600H entries with drive/track/sector parameters for SYS overlay loading |
| 0248H-026FH | 2 | Additional entry point stubs (C9H = RET at 0248H, 0252H, 025CH, 0266H) |
| 02C0H-02C7H | 2 | Disk serial/password: "QS81334Q" |
| 02C8H-02DFH | 2 | Disk geometry, granule configuration, allocation info |
| 0300H-03CAH | 3 | GAT (Granule Allocation Table): FFH=allocated, FCH=locked/system, 00H=free |
| 03CBH-03DFH | 3 | Disk label: 40H (track count), 00H 01H E0H 42H (load params), "VTOS40:F08/21/80" (name:format/date) |
| 03E0H-03FFH | 3 | Padding (0DH + spaces) |
| 0400H-04FFH | 4 | HIT (Hash Index Table): all zeros (empty on this disk image) |
Cross-Reference Notes
The boot code calls into Model I ROM routines at 0033H (display character) and 0040H (line input / wait). It reads directory sectors from Track 17 and locates the SYS0/SYS directory entry to determine where SYS0 is stored on disk. The jump vector table at 0220H contains four JP 4600H instructions, indicating that SYS0 loads at or dispatches through 4600H. This is consistent with the TRSDOS 2.x architecture where the resident DOS occupies 4000H-4CFFH and overlay SYS files load into a shared overlay area.
VTOS 4.0.2 served as the direct ancestor of LDOS. According to Tim Mann, who was one of the five core LDOS developers, Lobo Drives obtained rights to VTOS but could not obtain source code from Randy Cook, so all LDOS development was done from raw machine code disassembly using Roy Soltoff's disassembler.
Disassembly of the TRS-80 Boot Sector (Sector 0):
4200H - Boot Entry Point and Initialization
Single-density boot code entry point. The Model I ROM loads Track 0, Sector 0 to 4200H and jumps here. This code initializes the CPU, selects Drive 0, reads the directory to locate SYS0/SYS, and begins loading it into memory.
SYS0 Located
At this point, the directory sector is in the buffer at 5100H and contains a valid SYS0/SYS entry. The code now extracts the starting track/sector from the directory entry to begin reading the SYS0 /CMD load module from disk.
4242H - /CMD Load Module Parser
Main loop that parses the /CMD load module format to load SYS0/SYS into memory. The /CMD format uses record type bytes: 01H = data block (load code into memory), 02H = skip block (discard bytes), 03H = transfer address (jump to loaded code). This parser reads the type byte, dispatches accordingly, and loops until a transfer record is found.
Type 01H Data Block Handler
The record type was 01H (data block). The next bytes in the stream are: length byte (2's complement), followed by 2-byte load address (low/high), followed by the data bytes. The length byte represents (256 - actual_length); the actual number of data bytes is (256 - length_byte).
Data Copy Loop
Register Pair HL points to the destination in memory. Register B holds the remaining byte count. Each iteration reads one byte from the /CMD stream and stores it at (HL), then advances HL.
Type 02H Skip Block Handler
The record type was 02H (skip/comment block). The next byte is a length, followed by that many bytes to be read and discarded.
Type 03H Transfer Record Handler
The record type was 03H (transfer address). The next 3 bytes are: a length/flag byte (discarded), followed by the 2-byte execution address (low/high). After reading the execution address, the code jumps there to begin executing SYS0.
4279H - Get Next Byte From /CMD Stream
Reads the next sequential byte from the /CMD load module being loaded from disk. Uses the alternate register set to track the sector buffer position (BC') and current disk track/sector (DE'). When the buffer is exhausted (C' wraps from FFH to 00H), automatically reads the next sequential sector from disk and resets the buffer pointer.
Buffer Exhausted
C' wrapped to 00H, meaning all 256 bytes of the current sector have been consumed. The code must read the next sequential sector from disk into the buffer at 5100H.
4294H - Error Handler: Display Message and Halt
Error exit point. Loads HL with the "DISK ERROR" message pointer at 42F3H, then falls through to display the message and halt the CPU. The "NO SYSTEM" error path at 422CH jumps to 4297H with HL already pointing to 42E7H.
429EH - Display Message Routine
Displays a 03H-terminated string. On entry, Register Pair HL points to the first character of the message. Characters are displayed one at a time via the ROM character output routine at 0033H until a 03H delimiter byte is encountered.
42ACH - Read Sector Routine
Reads a single 256-byte sector from the floppy disk into the buffer at (BC). On entry: D=track number, E=sector number, BC=buffer address. This routine first calls the FDC core at 42B4H. If the FDC core returns Z (success), this routine returns Z. If the FDC core returns NZ (error), the routine retries by falling through to call 42B4H directly with the buffer address in BC.
Retry on Error
The first read attempt failed. The code falls through to retry. Register Pair HL now contains the buffer address (popped from the stack), and it is copied to BC for the retry call to 42B4H.
42B4H - FDC Core: Low-Level Disk Read
Performs a low-level sector read using the WD1771 FDC via memory-mapped I/O at 37ECH-37EFH. On entry: D=track, E=sector, BC=buffer address. The routine writes the track and sector numbers to the FDC registers, issues a Seek command (1BH) to position the head, waits for the FDC to become ready, issues a Read Sector command (88H), then transfers 256 bytes from the FDC data register to the buffer using a tight polling loop. On return: Z FLAG set = success, NZ FLAG set = error.
| 1771 FDC Registers Written | Function Description | ||||||||
| 37EEH (Sector Reg) | 37EFH (Data Reg) | Summary | |||||||
| E = Sector Number | D = Track Number | Sector register receives E, Data register receives D (target track for Seek) | |||||||
| 1771 FDC Command: 1BH (00011011) | Function Description | ||||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Summary of Bits | |
| 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | Command=Seek Bit 7-4: Command Code (0001) h=1: Enable Head Load/Settle delay V=0: No track verification r1,r0=11: Stepping Motor Rate = 15ms (slowest, most compatible) | |
FDC Timing Delay
After issuing the Seek command, the code must wait for the WD1771 to process it. The four EX (SP),HL instructions below create a timing delay by performing stack exchanges (each takes 19 T-states). This is the critical WD1771 delay that early TRSDOS famously omitted, causing disk errors. The 1771 requires several microseconds after receiving a command before its status register is valid.
Seek Complete
The FDC has finished seeking to the target track. Now issue a Read Sector command to read the data.
| 1771 FDC Command: 88H (10001000) | Function Description | ||||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Summary of Bits | |
| 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | Command=Read Sector Bit 7-5: Read Command (100) m=0: Single Record b=1: IBM format sector E=0: No head load delay (head already loaded from Seek) Remainder: 00 | |
Data Transfer Loop
The FDC is now reading the sector. The code polls the status register and transfers each byte as it becomes available. Bit 1 (DRQ, Data Request) indicates a byte is ready. Bit 0 (Busy) indicates the read is still in progress.
Data Byte Ready
DRQ is set, meaning a byte is available in the FDC Data Register at 37EFH. Read it and store it in the sector buffer.
Read Complete - Check Final Status
The FDC is no longer busy (Busy bit cleared). Check the status register for errors. The relevant error bits are: bit 2 (Lost Data), bit 3 (CRC Error), bit 4 (Record Not Found), bit 6 (Write Protected, not relevant for reads).
| 1771 FDC Status Mask: 5CH (01011100) | Function Description | ||||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Summary of Bits | |
| 0 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | Type II Status Error Mask Bit 6: Write Protected (not expected during read) Bit 4: Record Not Found Bit 3: CRC Error Bit 2: Lost Data Result: Z=no errors, NZ=error detected | |
| 1771 FDC Command: D0H (11010000) | Function Description | ||||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Summary of Bits | |
| 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | Command=Force Interrupt Bit 7-4: Command Code (1101) I3=0, I2=0, I1=0, I0=0: Terminate without interrupt (immediate reset) | |
42E4H - Data: Screen Initialization and Error Messages
Three 03H-terminated message strings used by the boot code. The screen initialization message clears the display, and the two error messages are shown when the boot process fails.
Three bytes: 1CH = clear screen (Model I control code), 1FH = home cursor (move cursor to top-left position), 03H = message terminator. This is displayed by CALL 429EH at boot entry to prepare the screen.
Screen position prefix (17H E8H) followed by the text "NO SYSTEM" and a 03H terminator. The 17H byte is a cursor positioning control code and E8H specifies the screen position. This message is displayed when the SYS0/SYS directory entry is not found at the expected location on Track 17.
Screen position prefix (17H E8H) followed by the text "DISK ERROR" and a 03H terminator. This message is displayed when the FDC sector read routine returns an error (CRC error, lost data, or record not found).
Disassembly - Double-Density Boot (Sector 1):
4200H - Double-Density Boot Entry Point
Lobo LX-80 double-density boot code entry point. This is an alternate boot sector that loads at the same 4200H address but is stored in Sector 1 of the BOOT/SYS file. It executes on Lobo LX-80 hardware, which uses IY-indexed I/O for FDC access instead of the Radio Shack memory-mapped interface. The initialization configures drive parameters from the IY-pointed hardware descriptor table and computes the sectors-per-track dynamically rather than using the hardcoded value of 10 from the single-density boot.
Drive Configuration
The next instructions read and modify the LX-80 drive descriptor at IY+03H to configure the density and sector size for this boot operation. The descriptor byte at IY+03H contains drive flags; the code forces bits 0-1 to 11 (binary) while preserving the upper bits.
Sectors-Per-Track Computation
The following code extracts drive geometry information from the LX-80 descriptor at IY+07H and IY+08H, then computes the number of sectors per track using the multiply routine at 42D3H. This computed value is patched into the SUB instruction at 42A4H via self-modifying code, replacing the hardcoded sectors-per-track used in the single-density boot.
Store the computed sectors-per-track value into address 42A5H. This overwrites the operand byte of the SUB instruction at 42A4H. At assembly time, 42A5H contains 00H (SUB 00H, which does nothing). At runtime, it becomes SUB nn where nn is the actual sectors-per-track for this drive, enabling the Get Next Byte routine to correctly detect track boundary crossings on drives with any sector count.
Read Directory Sector
Now read the directory sector to locate SYS0/SYS, just as the single-density boot does.
SYS0 Located - Extract Starting Track/Sector
The directory entry is valid. Extract the starting track/sector from the directory entry and set up for /CMD parsing. The granule-to-sector conversion in this boot is more complex than the single-density version because it uses the dynamically computed sectors-per-granule from the drive parameters.
4260H - /CMD Load Module Parser (Double-Density)
Identical logic to the single-density /CMD parser at 4242H, but calls the double-density Get Next Byte routine at 4297H instead of 4279H.
Type 01H Data Block
Read length byte, 2-byte load address, then copy data bytes to memory.
Type 02H Skip Block
Read and discard the specified number of bytes.
Type 03H Transfer Record
Read the execution address and jump to SYS0.
4297H - Get Next Byte (Double-Density)
Double-density version of the Get Next Byte routine. Functionally identical to the single-density version at 4279H, but calls the LX-80 Read Sector routine at 42C5H and uses the self-modified SUB instruction at 42A4H for track boundary detection instead of the hardcoded SUB 0AH.
SUBtract the sectors-per-track value from Register A. The operand byte at 42A5H was initialized to 00H at assembly time but is overwritten at runtime by the LD (42A5H),A instruction at 422DH with the actual sectors-per-track computed from the drive parameters. If the result is zero, the sector count has reached the track boundary.
42ADH - Error Handler (Double-Density)
Error exit for the double-density boot. Displays the error message and halts.
42B7H - Display Message Routine (Double-Density)
Identical function to the single-density Display Message at 429EH. Displays 03H-terminated string at (HL) via ROM CALL 0033H.
42C5H - Read Sector Routine (Lobo LX-80)
Reads a sector using the Lobo LX-80 disk interface. Unlike the single-density boot which accesses the WD1771 directly via memory-mapped I/O, this routine abstracts the FDC access through a jump vector at (IY), allowing the same boot code to work with different disk controller hardware. On entry: D=track, E=sector, BC=buffer address.
42D1H - Lobo LX-80 FDC Dispatch
Hardware abstraction layer for the Lobo LX-80 disk interface. Executes JP (IY) to call the LX-80 ROM routine whose address is stored in Register Pair IY. IY was set during LX-80 ROM initialization (before the boot sector was loaded) to point to the LX-80's FDC driver entry point.
42D3H - 8-Bit Multiply Routine
Performs an 8-bit unsigned multiply: A = A x E. Uses the shift-and-add algorithm, processing 8 bits of the multiplicand (E) from MSB to LSB. On entry: A=multiplier, E=multiplicand. On return: A=product (low 8 bits). Registers B and E are destroyed; BC is preserved via PUSH/POP.
Shift-and-Add Multiply Loop
For each bit of the multiplicand (Register E), shift the accumulator (A) left by 1, then shift the multiplicand left by 1. If the bit shifted out of E (into Carry) was 1, add the multiplier (D) to the accumulator.
42E2H - Data: Screen Initialization and Error Messages (Double-Density)
Message strings for the double-density boot. Functionally identical content to the single-density boot's messages, but positioned 2 bytes earlier in the sector (starting at 42E2H instead of 42E4H) because the double-density boot code is 2 bytes shorter.
1CH = clear screen, 1FH = home cursor, 03H = terminator.
Screen position prefix (17H E8H) followed by "NO SYSTEM" and 03H terminator.
Screen position prefix (17H E8H) followed by "DISK ERROR" and 03H terminator.
Two FFH bytes fill the final 2 bytes of the 256-byte sector. These are unused padding.
Disk Structures (Sectors 2-4):
Sector 2 (File Offset 0200H-02FFH) - Directory and System Entry Points
This sector contains the system directory information including a jump vector table for SYS overlay loading, stub entry points, the disk serial/password, and Disk Geometry disk geometry parameters. On a VTOS disk, this sector resides on Track 17 and is part of the directory track structure inherited from TRSDOS 2.x.
The value 40H (64 decimal) at the start of this sector. In TRSDOS-compatible DOSes, this typically indicates the maximum number of directory entries or a directory configuration flag.
SYS Overlay Jump Vector Table
Four entries, each consisting of a JP 4600H instruction followed by 5 bytes of parameters. These vectors are used by the DOS to load SYS overlay files. The JP target of 4600H indicates that SYS0 or its overlay dispatcher is expected at that address. Each entry's parameter bytes encode the drive number, track, sector, and load address for the corresponding SYS file.
Jump to the SYS overlay dispatcher at 4600H. This is the primary SYS0 entry point.
These parameters tell the overlay loader where to find the SYS file on disk:
- 86H = configuration flags (bit 7 set = active, bits 1-2 = sector count encoding)
- 01H = drive 0
- 13H = track 19 (13H = 19 decimal)
- 22H 09H = load address or sector/granule mapping.
- 24H = additional configuration
- 11H = directory track (17 decimal) cross-reference
Second overlay vector, also dispatching through 4600H.
- 03H = flags (lower priority, 2 sectors)
- 02H = drive 0 configuration
- 11H = Track 17
- 22H 09H = load parameters
- 24H = additional configuration
- 11H = directory track (17 decimal) cross-reference
Third overlay vector.
- 03H = flags
- 04H = 4 sectors or drive 2
- 00H = track 0 or flags
- 22H 09H = load parameters
- 24H = additional configuration
- 11H = directory track (17 decimal) cross-reference
Fourth overlay vector.
- 03H = flags
- 08H = 8 sectors or drive 3
- 11H = Track 17
- 22H 09H = load parameters
- 24H = additional configuration
- 11H = directory track (17 decimal) cross-reference
Stub Entry Points
Four RET instructions at fixed offsets provide stub entry points for DOS functions that are not implemented in the boot sector. These will be overwritten when SYS0 loads and installs the full DOS entry point table.
Immediate return. Placeholder for a DOS function not yet loaded.
Immediate return placeholder.
Immediate return placeholder.
Immediate return placeholder.
Disk Serial Number and Disk Geometry Parameters
The disk identification and geometry parameters begin at offset 02C0H. The serial/password is an 8-character ASCII string. The Disk Parameters define the physical disk geometry for the FDC driver.
8-character disk identifier string "QS81334Q". In VTOS and TRSDOS, this serves as both a serial number and an optional disk password. Each formatted disk receives a unique identifier.
EDH = Disk Geometry configuration flags (bit 7 set = configured, other bits encode density, sides, step rate). Three zero bytes follow as reserved/unused parameters.
- 01H = number of sides (1 = single-sided)
- 00H = reserved
- 40H = number of tracks (64 decimal, though 35 or 40 is typical for 5.25" drives - this may encode differently)
- 01H = additional geometry parameter
- 35H = 53 decimal (possibly sectors per track or track count in an alternate encoding)
- 00H = reserved
- 22H 0DH = directory track configuration (Track 17 at 11H*2 = 22H, with 0DH sectors)
- 50H 16H = additional parameters (load address high byte 50H = 5000H region, 16H = sector offset)
- 08H = sectors per granule or granule configuration
- 00H = reserved
- 52H = additional disk parameter
- FFH FFH = allocation bitmap seed (all bits set = all granules initially allocated on a freshly formatted disk)
- BFH = system granule mask
- C0H = high memory boundary or configuration flags
- 3CH = 60 decimal (possibly timing constant)
- 45H 3CH = additional parameters.
Sector 3 (File Offset 0300H-03FFH) - GAT and Disk Label
The Granule Allocation Table (GAT) tracks which granules on the disk are in use. Each byte represents one track's allocation status, with individual bits representing granules within that track. The disk label at the end of the sector identifies the disk name, format, and creation date.
Granule Allocation Table
The GAT occupies bytes 0300H-03CAH. Each byte corresponds to one track on the disk. Byte values: FFH = all granules on this track are allocated, FCH = track is locked/reserved by the system (cannot be allocated to user files), FDH = partially allocated with system reservation, 00H = all granules on this track are free. The GAT covers up to 203 tracks (0300H-03CAH), though a standard 35-track or 40-track disk uses only the first 35-40 bytes.
All granules allocated (FFH). These tracks contain system files (BOOT/SYS, SYS0-SYS9, etc.).
FDH = 11111101 binary. Most granules allocated, with one granule partially free (bit 1 clear). This track contains the tail end of system files with one granule partially used.
All locked/system reserved (FCH). These tracks are reserved for system use and cannot be allocated to user files.
All granules fully allocated (FFH).
Fully allocated.
FDH = mostly allocated, one granule partially free.
Locked/system reserved (FCH).
Locked/system reserved. This is the end of a standard 35-track disk.
All allocated (FFH). On a 40-track disk, tracks 35-39 contain additional data. Tracks beyond the physical disk capacity are marked FFH (allocated) to prevent the DOS from attempting to use non-existent tracks.
Locked/system reserved (FCH). These track entries extend beyond any physical disk and are pre-initialized to prevent allocation.
All allocated (FFH). Remaining GAT entries, all marked as used.
Disk Label
The final 53 bytes of the sector (03CBH-03FFH) contain the disk label record. This identifies the disk to the operating system and stores the disk name, format type, and creation date.
- 40H = track count (64 decimal, or 40H as a flag indicating 40-track disk in VTOS encoding)
- 00H 01H = additional disk parameters
- E0H 42H = 42E0H, which is the boot code transfer address (the last executable address in the boot sector before the data strings begin)
"VTOS40" = disk/OS name (VTOS version 4.0). ":F" = format identifier (F = standard format). "08/21/80" = creation date (August 21, 1980). 0DH = carriage return terminator. This is the date the VTOS 4.0 master disk was formatted.
31 space characters (20H) pad the remainder of the disk label field to fill the sector.
Sector 4 (File Offset 0400H-04FFH) - HIT (Hash Index Table)
The Hash Index Table (HIT) provides a quick lookup mechanism for directory searches. Each byte in the HIT corresponds to a directory entry position and contains a hash value computed from the filename. The DOS can quickly scan the HIT to find candidate directory entries without reading the full directory. On this disk image, the HIT is entirely empty (all zeros), indicating either no files beyond the system files, or that the HIT has been cleared.
All 256 bytes are zero, indicating no filename hash entries. On a freshly formatted VTOS disk, the HIT would be populated as system files are written. An empty HIT suggests this sector was either zeroed during the disk image creation process or represents the state before SYS0 populates it during the first boot.