TRS-80 DOS - NEWDOS/80 v2.0 for the Model I - BOOT/SYS Disassembled
Page Index
Introduction/Summary:
General
The BOOT/SYS module is the initial loader for the NEWDOS/80 v2.0 Disk Operating System on the TRS-80 Model I. Its primary purpose is to load and execute the next stage of the DOS, SYS0/SYS, from the floppy disk into RAM.
The module, which starts execution at memory address 4200H, operates by efficiently using the Z80's alternate register set (BC', DE', HL') to manage two distinct sets of pointers: one for the Floppy Disk Controller (FDC) operations and one for the RAM buffer/target load location.
This boot module is basically two main routine, and Cliff Ide treated them as such by use of the EXX register swap. One routine uses HL to point to the Floppy Disk Controller memory locations and DE to point to the track and sector being worked on. The other routine uses HL to point to a RAM buffer which contains the sector data. In fact, Cliff uses the PUSH command only 3 times in this entire boot routine!
Another thing done here, more out of necessity than anything else, is to use the Model I RAM location for the Floppy Disk Controller access. The Model I didn't have ports so it couldn't be any other way (thanks to Eric Dittman for pointing this out), but it remains that by doing it this way only 1 opcode is needed to test and manipulate the controller, instead of 2.
These two things are a HUGE time saver.
Core Process:
Initialization (4200H - 4214H):
- Disables interrupts (DI).
- Initializes the Floppy Disk Controller (FDC) by setting the FDC Status/Command Register (37ECH) to use the 1771 single-density chip (for Percom Doublers) and then resets the FDC (0D0H).
- Sets the FDC Track Register (37EDH) to Track 0 and the Sector Register (37EEH) to Sector 0.
- Initializes the disk/sector pointer DE to 0005H, pointing to Track 0, Sector 5, the expected location of SYS0/SYS.
- Swaps register sets (EXX) to prepare the main set (HL, DE, BC) for RAM buffer management.
RAM Buffer Setup (4215H - 4218H):
- Sets the Stack Pointer (SP) to 41E0H.
- Sets the RAM Buffer pointer HL to 51FFH, which prepares a 256-byte RAM buffer (5200H-52FFH) to hold sector data read from the disk.
Loading SYS0/SYS (421BH - 423EH):
- The code proceeds in segments, reading an initial load byte, followed by the length and the starting address for the code segment.
- It uses a loop to CALL 4252H (get next byte from RAM buffer) and then store the byte from the buffer (pointed to by HL) into the target RAM location (pointed to by DE).
- If the RAM buffer pointer (L-register) rolls over (hits 00H), the code reads the next sector from the disk into the RAM buffer via a call to 4255H.
- The loop continues until all segments of SYS0/SYS are loaded into memory.
Disk I/O / Sector Read (4255H - 42B8H):
- The 4255H subroutine performs a full sector read.
- It swaps registers back (EXX) to use the disk-related pointers.
- It performs a disk drive select (425BH) and sets up a retry count of 10 (0AH).
- It sends the FDC a SEEK command (1BH) to move to the track/sector specified in DE.
- It sends the READ Sector command (88H) and then enters a long loop to poll the FDC status and transfer 256 bytes of data from the FDC Data Register (37EFH) into a separate sector data buffer starting at 5100H.
- It increments the sector/track pointer (DE) for the next sector load and swaps registers back (EXX) before returning.
Execution or Error (4240H - 424BH, 424CH - 42C2H):
Once all sectors are loaded, the code checks the entry point address and verifies a signature byte (A5H) to confirm that SYS0/SYS was successfully loaded.
If successful (Z FLAG set), it RETurns (RET Z), which is the final step, transferring control to the loaded SYS0/SYS entry point (via the address saved on the stack).
If the disk is not a DOS disk ("NO SYS") or a disk error occurs, the code jumps to 42C3H to display the respective error message ("NO SYS" or "DISK ERROR") and enters an endless loop to freeze the system.
Variables:
| Address | Bytes | Purpose |
|---|---|---|
| 37E1H | 1 | DISK DRIVE SELECT LATCH ADDRESS. Used to select the drive (e.g., 01H for Drive :0) and control the drive lights (e.g., 09H for all lights on). |
| 37ECH | 1 | Floppy Disk Controller Status/Command Register. Used for FDC status checks and sending commands like SEEK, READ, or RESET. Mirrors Port F0H. |
| 37EDH | 1 | Floppy Disk Controller TRACK REGISTER. Used to specify the target track for FDC commands. Mirrors Port F1H. |
| 37EEH | 1 | Floppy Disk Controller SECTOR REGISTER. Used to specify the target sector for FDC commands. Mirrors Port F2H. |
| 37EFH | 1 | Floppy Disk Controller DATA Register. Used to read (input) or write (output) the actual sector data to/from the FDC. Mirrors Port F3H. |
| 41E0H | N/A | Initial Stack Pointer (SP) location. The stack grows downward from this address. |
| 5100H-51FFH | 256 | FDC Sector Data Buffer. A temporary buffer used by the 4255H routine to hold one entire sector (256 bytes) read directly from the floppy disk controller. |
| 5200H-52FFH | 256 | RAM Buffer for Code Segments. This buffer is used to stage code segments loaded from the disk before they are moved to their final execution addresses. |
| 42E5H | 7 | "NO SYS" Error Message data storage. |
| 42DDH | 10 | "DISK ERROR" Message data storage. |
Disassembly:
4240H - Jump Point if the Byte was a 20H.
424CH - Display the "NO SYS" Error Message.
4252H - Fetch a byte from the RAM BUFFER.
4255H - Routine to read a whole sector into the RAM Buffer
| 1771 FDC Command: 1BH (0001 1011) | 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 | h | V | r1 | r0 | Command=Seek Bit 7-4: Command Code (0001) h: 1=Enable Head Load/Settle, 0=No delay V: 1=Verify Destination Track ID, 0=No verification r1, r0: Stepping Motor Rate (00=3ms, 01=6ms, 10=10ms, 11=15ms) |
| 1771 FDC Command: 88H (1000 1000) | Function Description | |||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Summary of Bits |
| 1 | 0 | 0 | m | b | E | 0 | 0 | Command=Read Sector Bit 7-5: Read Command (100) m: 1=Multiple Records, 0=Single Record b: 1=IBM format, 0=Non-IBM Format E: 1=Enable HLD, HLT, and 10ms Delay, 0=Assume Head Already Engaged, no Delay Remainder: Unused (00) |
| 1771 FDC Command: D0H (1101 0000) | 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 | I3 | I2 | I1 | I0 | Command=Force Interrupt Bit 7-4: Command Code (1101) I3: 1=Interrupt Immediately, 0=No Interrupt Immediately I2: 1=Interrupt on the next Index Pulse, 0=No Interrupt on the next Index Pulse I1: 1=Interrupt the next time Ready goes to Not Ready, 0=No Interrupt the next time Ready goes to Not Ready I0: 1=Interrupt the next time Not Ready goes to Ready, 0=No Interrupt the next time Not Ready goes to Ready |
42B9H - Wait for the Floppy Drive Controller to be ready, Send a RESET to the FDC, and continue a countdown of retries; failing to DISK ERROR if the retry count expires.
| 1771 FDC Command: 0BH (0000 1011) | Function Description | |||||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Summary of Bits |
| 0 | 0 | 0 | 0 | h | V | r1 | r0 | Command=Restore Bit 7-4: Command Code (0000) h: 1=Enable Head Load/Settle, 0=No delay V: 1=Verify Track 0 ID, 0=No verification r1, r0: Stepping Motor Rate (00=3ms, 01=6ms, 10=10ms, 11=15ms) |
42C3H - Display a Message (Pointed to by HL) and hang the system.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.