4300H – Start of the BOOT/SYS Module.
4300
CP 11H
Compare the value held in Register A against 11H. That said, it is unlikely that this is what is going on as the CP results are never used. It is more likely that this is an unused instruction that puts 11H (directory track) into 4301H. Another hint for why it may not be a used/real instruction is that when 4319H wants to restart this routine, it jumps to the next instruction (4302H) and not to here.
LD A,D0H
LET Register A = D0H (1101 0000). When applied to Port F0H, 1101 0000 is the command to Reset, which puts FDC in mode 1 (INTRQ; “000” terminate command without interrupt).
4304
OUTput the value held in Register A to port F0H (the Floppy Disk Command/Status Register).
4306
LD HL,0002H
LET Register Pair HL = 0002H, which will mean TRACK 00H, SECTOR 02H.
4309
LD (43EAH),HL
Store the value held in Register HL into the memory location 43EAH.
NOTE: 43EAH is where the DISK SECTOR NUMBER and 43EBH is where the DISK TRACK NUMBER is stored.
430C
XOR A
Set Register A to ZERO and clear all Flags.
430D
LD (43ECH),A
Store the value held in Register A (which is now a 0) into the memory location 43ECH.
NOTE: 43ECH is where the BYTE NUMBER is stored.
GOSUB to 433EH (the READ A BYTE FROM DISKETTE routine).
4313
CP 01H
At this point, Register A holds the byte which was read from Diskette; but we don’t know what kind of byte it is. First, we will compare that byte (held in Register A) against 01H (which is a DATA BLOCK designator). If Register A equals 01H, the Z FLAG is set; otherwise the NZ FLAG is set.
4315
If the Z FLAG (Zero) is set then we have a DATA BLOCK so JUMP to 4323H to deal with a data block.
4317
CP 02H
All we know now is that it isn’t a DATA BLOCK, so next we compare that byte (held in Register A) against 02H (which is a JUMP ADDRESS designator). If Register A equals 02H, the Z FLAG is set; otherwise the NZ FLAG is set.
4319
If the NZ FLAG (Not Zero) is set meaning we did not get a JUMP ADDRESS then we need to restart the boot routine by JUMPing BACK to 4302H.
431B
If we’re here then we got a JUMP ADDRESS designator, so GOSUB to 433EH (the READ A BYTE FROM DISKETTE routine) to get the byte.
431E
GOSUB to 4335H (the GET AN ADDRESS FROM DISKETTE routine). Note that the routine exits with the address in Register Pair HL.
4321
JP (HL)
The memory location pointed to by Register Pair HL now holds the jump point, so JUMP to it!
4322H – Data Byte. Number of Backups Permitted.
4322
FFH
Storage Byte for NUMBER OF BACKUPS FOR RESTRICTED FILES ALLOWED. FFH means unlimited. Any directory entry which has Bit 5 of the first relative byte set will be blocked from being backed up once this counter hits 0. Fun Fact: PATCH will not permit you to change this value.
4323H – Read a Data Block from Diskette into a Memory Buffer Pointed To By HL. If we are here, the byte we read from disk was a DATA BLOCK designator.
4323
First, a little primer. Common data block structure is an 01H followed by a data block length byte (either 00H, 01H, or 02H to indicate whether the block is 254, 255, or 256 bytes), followed by the loading address for that block.
So, at this point we have the 01H, so we need to pull the rest of the header bytes from disk. To do this we GOSUB to 433EH (the READ A BYTE FROM DISKETTE routine).
4326
SUB 02H
Here we are going to covert 00H / 01H / 02H into 254 / 255 / 256. To do this, we SUBtract the value 02H from Register A, so that a 00H becomes FEH (254), a 01H becomes FFH (255), and a 02H becomes 00H (256). Those numbers will be the LOOP to read bytes.
4328
LD B,A
Since Register B is pretty much universally used as a loop counter (and definitely by DJNZ), we must put the modified Register A (which is now set as a loop based on the byte read from diskette for the number of bytes to expect) into Register B.
4329
Now that we got the block length indicator, we need to get the 2 byte loading address. To do this we GOSUB to 4335H (the GET AN ADDRESS FROM DISKETTE routine). That routine exits with the address in Register Pair HL.
432CH – Start of LOOP to read “B” bytes from the diskette and put them into a buffer starting at HL.
432C
Get a byte from diskette by GOSUBing to 433EH (the READ A BYTE FROM DISKETTE routine).
432F
LD (HL),A
Store the byte which was read from diskette into the memory location pointed to by Register Pair HL.
4330
INC HL
Bump Register Pair HL by 1.
4331
DJNZ 432CH
LOOP back to 432CH until Register B is ZERO.
4335H – Get an address from diskette. Basically, this just reads 2 bytes into Register Pair HL; LSB into L and MSB into H.
GOSUB to 433EH (the READ A BYTE FROM DISKETTE routine).
4338
LD L,A
LET Register L = Register A.
4339
GOSUB to 433EH (the READ A BYTE FROM DISKETTE routine).
433C
LD H,A
LET Register H = Register A.
433D
RET
RETurn to the caller.
433EH – Read a Byte from Diskette
PUSH BC
PUSH Register BC to the top of the stack.
433F
PUSH HL
PUSH Register HL to the top of the stack.
4340
LD A,(43ECH)
Fetch the value stored at memory location 43ECH and put it into Register A.
NOTE: 43ECH is where the BYTE NUMBER is stored.
4343
OR A
Set FLAGS based on the contents of Register A.
4344
If the NZ FLAG (Not Zero) is set then we are at the sector we want, so JUMP to 4374H.
If we’re here, we are not at the sector we want.
4346
LD B,09H
LET Register B = 09H.
4348H is the start of a loop of 9 tries to get a good sector read.
4348
PUSH BC
Save the count by PUSHing Register BC to the top of the stack.
4349
GOSUB to 437FH to read a sector from diskette.
434C
POP BC
RESTORE Register Pair BC from the top of the STACK.
434D
AND 1DH
MASK the value of Register A against 1DH (0001 1101) to see if we have an error.
434F
If the Z FLAG (Zero) is set then we have no error so JUMP to 4364H.
… uh oh, we have an error!
4351
LD A,D0H
LET Register A = D0H (1101 0000). When sent to the FLOPPY DISK COMMAND register, 1101 0000 is the command to Reset; puts FDC in mode 1 (INTRQ; �000� terminate command without interrupt).
4353
OUTput the value held in Register A to port F0H (the Floppy Disk Command/Status Register).
4355
DJNZ 4348H
LOOP back to 4348H until Register B is ZERO.
At this point we failed 9 times, so its time to error out.
4357
LD A,17H
LET Register A = 17H (ASCII: DOUBLE SIZED character code).
4359
GOSUB to 0033H to set the screen to double size characters.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
435C
LD HL,43EDH
LET Register Pair HL = 43EDH to point to the ERROR message in this BOOT/SYS.
435F
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H or 0DH is found.
Keep executing this JUMP forever.
4364H – Jumped to by 434FH if we weren’t originally at the sector we wanted, but we are now.
4364
LD HL,(43EAH)
Fetch the value stored at memory location 43EAH and put it into Register HL.
NOTE: 43EAH is where the DISK SECTOR NUMBER and 43EBH is where the DISK TRACK NUMBER is stored.
4367
INC L
Bump Register L by 1 so as to point to the next sector.
4368
LD A,L
LET Register A = Register L for testing.
4369
CP 13H
Compare the value held in Register A against 13H (Decimal: 19) which is 1 over the number of sectors in a track. Results:
- If Register A equals 13H, the Z FLAG is set.
- If A < 13H, the CARRY FLAG will be set.
- if A >= 13H, the NO CARRY FLAG will be set.
436B
If we are at less than 19 sectors the C FLAG (Not Zero) will be set, and in that case JUMP to 4370H to bypass the routine to BUMP the track number.
If we are here, the sector number is greater than 18 sectors, so we need to bump the track number and reset the sector number to 01H (which is the lowest sector in TRSDOS v1.3 land).
436D
LD L,01H
LET Register L = 01H to set the sector at 1.
436F
INC H
Bump Register H by 1 to point to the next track.
LD (43EAH),HL
Store the value held in Register HL into the memory location 43EAH.
NOTE: 43EAH is where the DISK SECTOR NUMBER and 43EBH is where the DISK TRACK NUMBER is stored.
4373
XOR A
Set Register A to ZERO and clear all Flags.
LD L,A
We need to set HL to point to 4D00H, so first LET Register L = Register A (which is 00H).
4375
LD H,4DH
LET Register H = 4DH.
4377
INC A
Bump Register A by 1 to point to the next sector.
4378
LD (43ECH),A
Store the value held in Register A into the memory location 43ECH.
NOTE: 43ECH is where the BYTE NUMBER is stored.
437B
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
437C
POP HL
RESTORE Register Pair HL from the value held at the stop of the STACK.
437D
POP BC
RESTORE Register Pair BC from the value held at the stop of the STACK.
437E
RET
RETurn to the caller.
437FH – Read a Sector from Diskette
437F
GOSUB to 43C5H (the POSITION THE READ HEAD routine) which polls the FDC, and sends the TRACK and SECTOR number (held in H and L, respectively) to the FDC.
4382
LD BC,00F3H
LET Register Pair BC = 00F3H. In preparation for an INI command at 43ABH, Register C is loaded with 0F3H which is the FLOPPY DISK CONTROLLER DATA port and Register B is set to 00H for a loop of 256.
4385
LD A,81H
LET Register A = 81H (1000 0001) to send DRIVE 0 SELECT and DOUBLE-DENSITY to the FLOPPY DISK CONTROLLER.
4387
OUTput the value held in Register A (1000 0001) to port F4H.
NOTE: Port F4H is the Floppy drive select and options register. For OUTPUT:
- Bit 0: Drive 0 Select
- Bit 1: Drive 1 Select
- Bit 2: Drive 2 Select
- Bit 3: Drive 3 Select
- Bit 4: Side Select (0 = Select Side 0, 1 = Select Side 1)
- Bit 5: Write Precompensation (0 = Disable WP, 1 = Enable WP)
- Bit 6: Wait State Generation (0 = Disable WSG, 1 = Enable WSG)
- Bit 7: Density Select (0 = Single/FM, 1 = Double/MFM)
4389
LD D,A
Save the DRIVE SELECT code (held in Register A) into Register D.
438A
LD HL,43B7H
LET Register Pair HL = 43B7H to set the interrupt vector.
438D
LD (404AH),HL
Store the value held in Register HL into the memory location 404AH.
NOTE: 4049H is a NMI Vector.
4390
LD A,C3H
LET Register A = C3H.
4392
LD (4049H),A
Store the value held in Register A into the memory location 4049H.
NOTE: 4049H is the RST 0 NMI Vector.
4395
DI
Disable Maskable Interrupts.
4396
LD A,C0H
LET Register A = C0H (1100 0000) to enable the DRQ and INTRQ interrupts.
4398
OUTput the value held in Register A to port F4H.
NOTE: Port E4H is the Non-Maskable Interrupt Latch. Sending a Bit 6 and Bit 7 high to E4 will enable the DRQ and INTRQ Interrupts.
439A
LD E,02H
LET Register E = 02H (0000 0010). This would be the CONTROLLER READY flag. This will be masked against a FDC Status Read in 43A6H so as to test for CONTROLLER READY there.
439C
LD HL,4D00H
LET Register Pair HL = 4D00H to point to a buffer in memory starting at 4D00H.
439F
LD A,84H
LET Register A = 84H (1000 0100).
43A1
OUTput the value held in Register A to port F0H (the Floppy Disk Command/Status Register). In this case, 1000 = READ SECTOR with MULTIPLE RECORD FLAG set, 0 = SIDE COMPARE side 0, 1 = 15 ms delay, 00 = 6ms stepping.
43A3
GOSUB to 43E0H to do some PUSHes and POPs and NOPs to cause a small delay.
INput a byte from Port F0H and put it into Register A.
NOTE: Port F0H is the FDC Status port on input. Input Results:
- Bit 0: Busy
- Bit 1: Index/DRQ
- Bit 2: Track 0/Data Lost
- Bit 3: CRC error
- Bit 4: Seek error/Record not found
- Bit 5: If Reading, Record Type, if Writing, Write Fault/Head loaded
- Bit 6: Write Protect
- Bit 7: Not ready
43A8
AND E
MASK the value of Register A against the value held in Register E. Register E was set in 439AH to 0000 0010, so only Bit 1 will be set in Register A.
43A9
If the Z FLAG (Zero) is set (because Bit was 0; meaning CONTROLLER NOT READY), LOOP BACK to 43A6H to poll the controller again.
If we are here, then the FDC returned CONTROLLER READY.
43AB
INI
Read a single byte from Port C (Set to F3H at 4382H) into the memory location pointed to by HL (Set to 4D00H at 439CH), then DECrement HL and INCrement B (Set to 00H at 4382H). Z is set if B = 0; otherwise it is reset.
43AD
LD A,D
Put the DRIVE SELECT CODE of 81H (which was moved to Register D in 4389H) back into Register A.
43AE
OR 40H
OR Register A against 40H (0100 0000) to turn on Bit 6. This will turn 1000 0001 into 1100 0001.
OUTput the value held in Register A to port F4H. This sends the following to the FDC: DRIVE 0 SELECT, SIDE 0 SELECT, disable WRITE PRECOMP, enable WAIT STATE, DOUBLE DENSITY.
NOTE: Port F4H is the Floppy drive select and options register. For OUTPUT:
- Bit 0: Drive 0 Select
- Bit 1: Drive 1 Select
- Bit 2: Drive 2 Select
- Bit 3: Drive 3 Select
- Bit 4: Side Select (0 = Select Side 0, 1 = Select Side 1)
- Bit 5: Write Precompensation (0 = Disable WP, 1 = Enable WP)
- Bit 6: Wait State Generation (0 = Disable WSG, 1 = Enable WSG)
- Bit 7: Density Select (0 = Single/FM, 1 = Double/MFM)
43B2
INI
Read a byte from Port C into the memory location pointed to by HL, then DECrement HL and INCrement B. Z is set if B = 0; otherwise it is reset.
43B4
LOOP BACK 2 instructions (43B0H) to keep reading bytes. An Interrupt will exit the routine.
43B7H – This routine was set as the INTERRUPT VECTOR at 438AH. This routine exits with Register A holding the FLOPPY DISK CONTROLLER status.
43B7
POP HL
Since HL was set to jump to this specific routine, we need to restore HL. MOVE the value held at the stop of the STACK into Register Pair HL.
43B8
XOR A
Set Register A to ZERO and clear all Flags.
43B9
OUTput the value held in Register A to port F4H.
NOTE: Port E4H is the Non-Maskable Interrupt Latch. Sending a 0 to E4 will turn off all Non-Maskable Interrupts.
43BB
LD A,81H
LET Register A = 81H (1000 0001).
43BD
OUTput the value held in Register A (1000 0001) to port F4H, which, in this case, is DRIVE 0 SELECT and DOUBLE-DENSITY.
NOTE: Port F4H is the Floppy drive select and options register. For OUTPUT:
- Bit 0: Drive 0 Select
- Bit 1: Drive 1 Select
- Bit 2: Drive 2 Select
- Bit 3: Drive 3 Select
- Bit 4: Side Select (0 = Select Side 0, 1 = Select Side 1)
- Bit 5: Write Precompensation (0 = Disable WP, 1 = Enable WP)
- Bit 6: Wait State Generation (0 = Disable WSG, 1 = Enable WSG)
- Bit 7: Density Select (0 = Single/FM, 1 = Double/MFM)
43BF
GOSUB to 43E6H (a VERY short delay routine; basically a PUSH, a POP, a NOP, and a RET.
43C2
INput a byte from Port F0H and put it into Register A.
NOTE: Port F0H is the FDC Status port on input. Input Results:
- Bit 0: Busy
- Bit 1: Index/DRQ
- Bit 2: Track 0/Data Lost
- Bit 3: CRC error
- Bit 4: Seek error/Record not found
- Bit 5: If Reading, Record Type, if Writing, Write Fault/Head loaded
- Bit 6: Write Protect
- Bit 7: Not ready
43C4
RET
RETurn to the caller.
43C5H – Routine to position the read head based on the contents of HL (H=Track, L=Sector)
LD A,81H
LET Register A = 81H (1000 0001).
43C7
OUTput the value held in Register A (1000 0001)to port F4H, which, in this case, is DRIVE 0 SELECT and DOUBLE-DENSITY.
NOTE: Port F4H is the Floppy drive select and options register. For OUTPUT:
- Bit 0: Drive 0 Select
- Bit 1: Drive 1 Select
- Bit 2: Drive 2 Select
- Bit 3: Drive 3 Select
- Bit 4: Side Select (0 = Select Side 0, 1 = Select Side 1)
- Bit 5: Write Precompensation (0 = Disable WP, 1 = Enable WP)
- Bit 6: Wait State Generation (0 = Disable WSG, 1 = Enable WSG)
- Bit 7: Density Select (0 = Single/FM, 1 = Double/MFM)
43C9
LD HL,(43EAH)
Fetch the value stored at memory location 43EAH and put it into Register HL.
NOTE: 43EAH is where the DISK SECTOR NUMBER and 43EBH is where the DISK TRACK NUMBER is stored.
43CC
LD A,H
LET Register A = Register H. Register H holds the TRACK NUMBER we want.
453D
OUTput the value held in Register A to the FDC Data Register (Port F3H).
The reason this is going to the data register is that the FDC seek command requires that the Track Register contains the track number of the current position of the head and the Data Register contains the desired track number.
43CF
LD A,1CH
LET Register A = 1CH (0001 1100). When sent to the FLOPPY DISK COMMAND register, 0001 is Seek, 1=Head Load at Beginning, 1=Verify On Destination Track, 00 = 6 ms stepping.
43D1
OUTput the value held in Register A to port F0H (the Floppy Disk Command/Status Register).
43D3
GOSUB to 43E6H (a VERY short delay routine; basically a PUSH, a POP, a NOP, and a RET.
INput a byte from Port F0H and put it into Register A.
NOTE: Port F0H is the FDC Status port on input. Input Results:
- Bit 0: Busy
- Bit 1: Index/DRQ
- Bit 2: Track 0/Data Lost
- Bit 3: CRC error
- Bit 4: Seek error/Record not found
- Bit 5: If Reading, Record Type, if Writing, Write Fault/Head loaded
- Bit 6: Write Protect
- Bit 7: Not ready
43D8
BIT 0,A
Test Bit Number 0 of Register A. Bit 0 of the result of polling 0F0H is the BUSY bit.
Z FLAG will be set if that bit is 0 (=NOT BUSY), and NZ FLAG will be set if that bit is 1 (=BUSY).
43DA
If the NZ FLAG (Not Zero) is set, meaning that the FDC returned a BUSY status, LOOP BACK 2 instructions (to 43D6H) and keep polling the FDC.
43DC
LD A,L
LET Register A = Register L. Register L holds the SECTOR NUMBER we want.
43DD
OUTput the value held in Register A to Port F2H.
NOTE: Port F2H is the Floppy Disk Controller SECTOR Register.
43DF
RET
RETurn to the caller.
43E0H – Routine delay Of 2 Lengths (Depending on Entry). Used primarily as a short delay between OUTputting to the FDC and INputting from the FDC.
PUSH AF
PUSH Register AF to the top of the stack.
43E1
POP AF
MOVE the value held at the stop of the STACK into Register Pair AF.
43E2
PUSH AF
PUSH Register AF to the top of the stack.
43E3
POP AF
MOVE the value held at the stop of the STACK into Register Pair AF.
43E4
PUSH AF
PUSH Register AF to the top of the stack.
43E5
POP AF
MOVE the value held at the stop of the STACK into Register Pair AF.
PUSH AF
PUSH Register AF to the top of the stack.
43E7
POP AF
MOVE the value held at the stop of the STACK into Register Pair AF.
43E8
NOP
No Operation (Do Nothing).
43E9
RET
RETurn to the caller.
43EAH-43ECH – Byte Storage Area
43EA
02H
Storage location for CURRENT SECTOR
43EB
00H
Storage location for CURRENT TRACK
43EC
00H
Storage location for CURRENT BYTE NUMBER
43EDH – Error Message Storage Location.
43ED
17H
ASCII for DOUBLE WIDTH CHARACTERS
43F4H – Byte Storage Area
43F4H-
43FBH
Storage Location for BCD Coded Serial Number.
43FC
00H
No Operation (Do Nothing).
43FD
00H
No Operation (Do Nothing).
43FE
13H
Storage Location for DOS Version Number (13H = v1.3)
43FF
28H
Storage Location for Number of Tracks on Disk (28H = 40 Tracks)