TRS-80 DOS – TRSDOS v1.3 – SYS07/SYS Disassembled

General:

SYS7 handles the BACKUP and FORMAT Utility Commands. The only parameters permitted are drive numbers (0-2 for Backup, 0-1 for Format), and if drive numbers are not provided the user will be prompted for them.


Disassembly:

 
ORG 4E00H

4E00H – This is the ERROR, EXIT, and FATAL ERROR Routine. This is not the Overlay entry point (whcih is 57A1H).

“FATAL”
4E00
PUSH AF
Save the error code (stored in Register A) to the top of the stack.
4E01
XOR A
Set Register A to ZERO and clear all Flags.
4E02
LD (CSIDE),A
Reset to SIDE 0 of the Diskette by storing a 0 (held in Register A) into the memory location 4463H.
NOTE: 4463H is the storage location for the old system disk side number.
4E05
LD A,(CXFLAG)
Fetch the Permitted Backup Counter (stored at memory location 4E85H) and put it into Register A.
4E08
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4E09
JR Z,FATAL
     [4E1DH]
If the Z FLAG (Zero) then there may be no backups left, which is a fatal error, so JUMP to 4E1DH.
4E0B
CALL CKSRC
     [5492H]
GOSUB to 5492H to prompt the user to insert the source diskette.
4E0E
LD A,(FDRIVS)
Fetch the source drive number (stored at memory location 4E7EH) and put it into Register A.
4E11
AND 0FH
MASK the value of Register A against 0FH (0000 1111). This has the effect of leaving only bits 3, 2, 1, 0 active.
4E13
LD C,A
LET Register C = Register A (i.e., the masked drive number).
4E14
LD DE,0001H
LET Register Pair DE = 0001H for the TRACK (00) and Sector Number (01) – the first sector on the disk.
4E17
LD HL,4100H
LET Register Pair HL = 4100H, which is the saved boot with the updated backup counter.
4E1A
CALL XWRITE
     [45F7H]
GOSUB to 45F7H to write the boot sector with the updated counter.
“FATAL1”
4E1D
CALL CLRBUF
     [4E6EH]
GOSUB to 4E6EH to clear the BOOT from RAM.
4E20
CALL RETRY
     [4E41H]
GOSUB to 4E41H to reset the RETRY counter.
4E23
XOR A
Set Register A to ZERO and clear all Flags.
4E24
LD (CXFLAG),A
Store the value held in Register A into the memory location 4E85H (i.e., the backup exhausted flag).
4E27
LD (CCFLAG),A
Store the value held in Register A into the memory location 4E86H (i.e., the files deleted flag).
4E2A
LD A,0DH
LET Register A = 0DH (ASCII: CARRIAGE RETURN).
4E2C
CALL DSP
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
4E2F
POP AF
Put the value held at the top of the STACK (i.e., the error code) into Restore Register Pair AF, and then remove the entry from the stack.
4E30
OR 40H
OR Register A against 40H (0100 0000). This has the effect of turning on bit 6 to signify that the LONG error message should be displayed.
4E32
JP ERROR
   [4409H]
JUMP to 4409H.
NOTE: 4409H is the SYS00/SYS routine to process DOS errors.


4E35H – ABORT with CAN’T BACK UP DISKETTE Message.

“N12”
4E35
LD HL,N12M
LET Register Pair HL = 507AH to point to the message “CAN’T BACK UP DISKETTE, NOT VERSION 1.3.”
4E38
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
4E3B
CALL RESTRY
     [4E41H]
GOSUB to 4E41H to reset the RETRY counter.
4E3E
JP ABORT
   [4030H]
JUMP to 4030H.
NOTE: 4030H is the OPERATION ABORTED routine. Routine runs, displays an error, and returns to the DOS PROMPT.


4E41H – Reset the Retry Counter in DOS.

“RESTRY”
4E41
LD A,RETRY
LET Register A = 09H for NINE retries.
4E43
LD (TRY1),A
Store the value held in Register A into the memory location 467DH to set up for NINE retries if there is an error.
4E46
LD (TRY2),A
Store the value held in Register A into the memory location 460AH to set up for NINE retries if there is an error.
4E49
RET
RETurn to the caller.


4E4AH – ABORT routine – Jumped to if there was an error along the way.

“ABRT”
4E4A
LD HL,ABMSG
LET Register Pair HL = 50B3H to point to “OPERATION ABORTED DUE TO DISKETTE FLAWS“.
4E4D
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
“EXIT”
4E50
LD A,(CXFLAG)
Fetch the value stored at memory location 4E85H (i.e., the backup count flag) and put it into Register A.
4E53
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4E54
JR Z,EXIT1
     [4E68H]
If the Z FLAG (Zero) is set then the backup counter was not set, so JUMP to 4E68H.
4E56
LD A,(CCFLAG)
Fetch the value stored at memory location 4E86H (i.e., the files deleted flag) and put it into Register A.
4E59
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4E5A
JR Z,EXIT
     [4E68H]
If the Z FLAG (Zero) is set, then we can continue, so JUMP to 4E68H.
4E5C
LD HL,50DFH
LET Register Pair HL = 50DFH to point to “Maximum Backup Count Exceeded“.
4E5F
CALL SPRINT
     [516EH]
GOSUB to 516EH to decode and display the first part of the message (i.e., Maximum Backup Count Exceeded).
4E62
CALL SPRINT
     [516EH]
GOSUB to 516EH to decode and display the second part of the message (i.e., Protected Files NOT Backed Up).
4E65
CALL RESTRY
     [4E41H]
GOSUB to 4E41H.
“EXIT1”
4E68
CALL CLRBUF
     [4E6EH]
GOSUB to 4E6EH to clear the BOOT from RAM.
4E6B
JP SYS1IN
   [402DH]
Exit to DOS Ready via a JUMP to 402DH.


4E6EH – Clear RAM from 5E00H to 5EFFH and return.

“CLRBUF”
4E6E
LD HL,SPAR_
LET Register Pair HL = 5E00H, which will be the starting address for the LDIR move.
4E71
LD DE,SPAR_ + 1
LET Register Pair DE = 5E01H, which is the starting address for the LDIR move + 1.
4E74
LD BC,SECTOR – 1
LET Register Pair BC = 00FFH (Decimal: 255) for a loop of 255 bytes.
4E77
LD (HL),00H
Store a 00H into the memory location pointed to by Register Pair HL.
4E79
LDIR
Clear all RAM from 5E00H to 5EFFH by transferring a byte of data from the memory location pointed to by HL (which will always be 00H) to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
4E7B
RET
RETurn to the caller.


4E7CH – MESSAGE and BYTE STORAGE AREA.

“SDFLAG”
4E7C
DEFB 0
Flag to show SOURCE or DESTINATION disk
“FDRIVE”
4E7D
DEFB 0
Destination Drive for Format
“FDRIVS”
4E7E
DEFB 0
Source Drive for Backup
“FDRIVD”
4E7F
DEFB 1
Destination Drive for Backup
“FLAWC”
4E80
DEFB 0
Flawed Track Count
“BSIDES”
4E81
DEFB 0
Source Side Number to Backup
“BSIDED”
4E82
DEFB 0
Destination Side Number to Backup
“FLAG”
4E83
DEFB 0
Flag for ‘FLASH’ Routine
“CLFN”
4E84
DEFB 0
LFN of File Under Examination
“CXFLAG”
4E85
DEFB 0
Flag for ‘COUNTER’ Active
“CCFLAG”
4E86
DEFB 0
Flag to Show a Protected File Was Skipped
“SINGLE”
4E87
DEFB 0
‘NZ’ if it’s a MULTI-DRIVE Backup
“PTRAP”
4E88
DEFW 8FD3H
Input Password Stored Here
“CSAVE”
4E8A
DEFW 0
Command Line Pointer Here
“BUFPNT”
4E8D
DEFW BUFF
Present Buffer Pointer
“MEMTOP”
4E8F
DEFW 0
Top of Memory
“DATBUF”
4E90
DEFM ’00/00/00′
 
“NAMEBF”
4E98
DEFM ‘TRSDOS ‘ + 00H
Where the DISK ID goes
“NAMBUF”
4EA2
DEFS 10
 
“READM”
4EAB
DEFM 1DH + ‘Reading ‘ + 03H
 
“WRITEM”
4EB6
DEFM 1DH + ‘Writing ‘ + 03H
 
“VERFM”
4EC1
DEFM 1DH + ‘Verifying’ + 03H
 
“REST”
4ECC
DEFM ‘ TRACK ‘
 
“FTRACK”
4ED1
DEFM ’00, SECTOR ‘
 
“SEC”
4EDE
DEFM ’00’ + 1EH + 03H
 
“ANALYZ”
4EE2
DEFM …
1DH + ‘Analyzing Diskette’ + 1DH + 03H“.
“SRCMSG”
4EF7
DEFM …
1DH + ‘Insert SOURCE Diskette >ENTER<‘ + 03H“.
“SYSMSG”
4F17
DEFM …
1DH + ‘Insert DESTINATION Diskette >ENTER<‘ + 03H“.
“SYSMSG”
4F3C
DEFM …
1DH + ‘Insert SYSTEM Diskette >ENTER<‘ + 03H“.
“BCOMP”
4F5C
DEFM …
‘ ** Backup Complete **’ + 0DH“.
“TITLE1”
4F76
DEFM …
‘TRSDOS Model III ‘ + 03H“.
“TITLE2”
4F88
DEFM …
‘ Ver 1.3’ + 0AH + 0DH“.
“BMSG”
4F93
DEFM …
‘Backup Utility’ + 03H“.
“FMSG”
4FA2
DEFM …
‘Disk Formatter’ + 03H“.
“FDRV”
4FB1
DEFM …
‘Format Which Drive? ‘ + 03H“.
“DDATA”
4FC6
DEFM …
‘Diskette contains DATA. Use Disk or not? ‘ + 03H“.
“NAMMES”
4FF1
DEFM …
‘Diskette Name? ‘ + 03H“.
“PASMES”
5001
DEFM …
‘Master Password? ‘ + 03H“.
“SPASS”
5013
DEFM …
‘SOURCE Disk Master Password? ‘ + 03H“.
“INVPAS”
5031
DEFM …
‘Invalid Master Password’ + 0DH“.
“SDRV”
5049
DEFM …
‘SOURCE Drive Number? ‘ + 03H“.
“DDRV”
505F
DEFM …
‘DESTINATION Drive Number? ‘ + 03H“.
“N12M”
507A
DEFM …
0AH + ‘Cannot Backup Version 1.1. Diskette’“.
509E
DEFM …
0AH + ‘Use “XFERSYS” First’ + 0DH“.
“ABMSG”
50B3
0AH + ‘Operation ABORTED due to flaws on diskette’ + 0DH“.
50DF
DEFW 1E
Length of coded string (Decimal: 30)
“GEORGE”
50E0
DEFM …
‘Maximum Backup Count Exceeded’ + 0DH“.
50FE
DEFW 1E
Length of coded string (Decimal: 30)
50FF
DEFM …
‘Protected Files NOT Backed Up’ + 0DH“.
“REFORM”
511D
DEFM …
‘Do you wish to RE-FORMAT the diskette? ‘ + 03H“.
5138
LD A,(FDRIVE)
Fetch the value stored at memory location 4E7DH (i.e., the drive select code) and put it into Register A.
513B
CP 81H
Compare the value held in Register A against 81H (1000 0001), which is DRIVE 0 SELECT and DOUBLE-DENSITY to the FLOPPY DISK CONTROLLER. Results: If the drive select code indicates solely a command to DRIVE 0 SELECT and DOUBLE-DENSITY, the Z FLAG is set; otherwise the NZ FLAG is set.
513D
CALL Z,INSYS
If drive select code is DRIVE 0 SELECT and DOUBLE-DENSITY, GOSUB to INSYS to prompt to insert the system disk.
5140
RET
RETurn to the caller.
5141
LD H,L
LET Register H = Register L.
5142
CCF
Invert the state of the CARRY FLAG.
5143
JR NZ,5148H
If the NZ FLAG (Not Zero) is set, JUMP to 5148H.
“FDSMSG”
5145
DEFM …
‘Source Drive ‘“.
“FDS”
5152
DEFM …
‘0 Destination Drive ‘“.
“FDD”
516B
DEFM …
‘0’ + 0AH + 0DH“.


516EH – Decode and Display a Coded String.

“SPRINT”
516E
LD B,(HL)
Prepare for a DJNZ loop by fetching the character count (stored at memory location pointed to by Register Pair HL) into Register B.
516F
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the next byte.
“SPRIN1”
5170
LD A,(HL)
Fetch the character stored at memory location pointed to by Register Pair HL and put it into Register A.
5171
XOR 55H
Unscramble the character by XORing Register A against 01010101.
5173
CALL DSP
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
5176
INC HL
INCrement HL to point to the next character.
5177
DJNZ SPRIN1
     [5170H]
LOOP back to 5170H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
5179
RET
RETurn to the caller.


517AH – Read a Gran. A Gran in TRSDOS v1.3 is 3 Sectors. D=Track Number, E=Sector Number, HL=Buffer for Storage

“RNEXT”
517A
LD HL,(BUFPNT)
Fetch the START OF THE BUFFER (stored at memory location 4E8CH) and put it into Register HL.
“RGRAN”
517D
PUSH BC
Save Register Pair BC to the top of the stack.
517E
PUSH DE
Save Register Pair DE to the top of the stack.
517F
PUSH HL
Save Register Pair HL to the top of the stack.
5180
LD B,DGRAN
LET Register B = 03H for a read of 3 sectors (which is the number of sectors in a gran) via a DJNZ loop.
5182
LD A,(FDRIVS)
Fetch the source drive number (stored at memory location 4E7EH) and put it into Register A.
5185
LD C,A
LET Register C = the source drive number (stored in Register A).
5186
LD (HL),E
Store the sector number (held in Register E) into the memory location pointed to by Register Pair HL.
5187
INC HL
INCrement the value stored in Register Pair HL by 1.
5188
LD (HL),D
Store the track number (held in Register D) into the memory location pointed to by Register Pair HL.
5189
INC HL
INCrement the value stored in Register Pair HL by 1.
“RGRAN1”
518A
CALL FUNCTA
     [51D8H]
GOSUB to 51D8H to read the sector.
518D
JR NZ,RGRAN2
      [5195H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 5195H.
518F
CALL BUMP
     [5238H]
GOSUB to 5238H to move to the next sector and the next buffer.
5192
DJNZ RGRAN1
     [518AH]
LOOP back to 518AH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
5194
XOR A
Set Register A to ZERO and clear all Flags. This ensures the Z FLAG is set if passed through to the next instruction.
“RGRAN2”
5195
OR A
Set FLAGS based on the contents of Register A.
5196
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5197
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5198
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5199
RET
RETurn to the caller.


519AH – Write a Gran. On entry, HL points to the Data Buffer to Write to Diskette.

“WGRAN”
519A
PUSH BC
Save Register Pair BC to the top of the stack.
519B
PUSH DE
Save Register Pair DE to the top of the stack.
519C
PUSH HL
Save Register Pair HL to the top of the stack.
519D
LD B,DGRAN
LET Register B = 03H for a write of 3 sectors (which is the number of sectors in a gran) via a DJNZ loop.
519F
LD A,(FDRIVD)
Fetch the destination drive number (stored at memory location 4E7FH) and put it into Register A.
51A2
LD C,A
LET Register C = the destination drive number (stored in Register A).
51A3
LD E,(HL)
Fetch the sector number (stored at memory location pointed to by Register Pair HL) and put it into Register E.
51A4
INC HL
INCrement the value stored in Register Pair HL by 1.
51A5
LD D,(HL)
Fetch the track number (stored at memory location pointed to by Register Pair HL) and put it into Register D.
51A6
INC HL
INCrement the value stored in Register Pair HL by 1.
51A7
LD (VER),DE
Store the track number and sector number (held in Register DE) into the memory location 51C5H.
“WGRAN1”
51AB
CALL 51E2H
     [51E2H]
GOSUB to 51E2H to write the sector to disk.
51AE
JR NZ,WGRAN2
      [51B6H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 51B6H.
51B0
CALL BUMP
     [5238H]
GOSUB to 5238H to move to the next sector and the next buffer.
51B3
DJNZ WGRAN1
     [51ABH]
LOOP back to 51ABH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
51B5
XOR A
Set Register A to ZERO and clear all Flags. This ensures the Z FLAG is set if passed through to the next instruction.
“WGRAN2”
51B6
OR A
Set FLAGS based on the contents of Register A.
51B7
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
51B8
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
51B9
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
51BA
RET
RETurn to the caller.


51BBH – Verify a Gran.

“VGRAN”
51BB
PUSH BC
Save Register Pair BC to the top of the stack.
51BC
PUSH DE
Save Register Pair DE to the top of the stack.
51BD
PUSH HL
Save Register Pair HL to the top of the stack.
51BE
LD B,03H
LET Register B = 03H for a verify of 3 sectors (which is the number of sectors in a gran) via a DJNZ loop.
51C0
LD A,(FDRIVD)
Fetch the destination drive number (stored at memory location 4E7FH) and put it into Register A.
51C3
LD C,A
LET Register C = the destination drive number (stored in Register A).
51C4
LD DE,VER
LET Register Pair DE = the track and sector which was stored at 51C5H-51C6H elsewhere in this overlay.
51C7
LD HL,0000H
LET Register Pair HL = 0000H to throw away the data
“VGRAN1”
51CA
CALL FUNCTC
     [51ECH]
GOSUB to 51ECH to perform a sector verify.
51CD
JR NZ,VGRAN2
      [51D3H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 51D3H.
51CF
INC E
INCrement the sector number (stored in Register E) by 1.
51D0
DJNZ VGRAN1
     [51CAH]
LOOP back to 51CAH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
51D2
XOR A
Set Register A to ZERO and clear all Flags. This ensures the Z FLAG is set if passed through to the next instruction.
“VGRAN2”
51D3
OR A
Set FLAGS based on the contents of Register A.
51D4
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
51D5
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
51D6
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
51D7
RET
RETurn to the caller.


51D8H – Read a Sector and Display a Message.

“FUNCTA”
51D8
LD IX,XREAD
LET Register Pair IX = 4675H, which is the read-sector routine.
51DC
LD IY,READM
LET Special Index Register IY = 4EABH, which points to the MESSAGE STORAGE AREA for a message “1DH + ‘Reading ‘ + 03H“.
51E0
JR GREAD
   [51F4H]
JUMP to 51F4H to continue the routine.


51E2H – Write a Sector and Display a Message.

“FUNCTB”
51E2
LD IX,XWRITE
LET Register Pair IX = 45F7H, which is the write-sector routine.
51E6
LD IY,WRITM
LET Special Index Register IY = 4EB6H, which points to the MESSAGE STORAGE AREA for a message “1DH + ‘Writing ‘ + 03H“.
51EA
JR GREAD
   [51F4H]
JUMP to 51F4H to continue the routine.


51ECH – Verify a Sector and Display a Message.

“FUNCTC”
51EC
LD IX,XREAD
LET Register Pair IX = 4675H, which is the read-sector routine.
51F0
LD IY,VERFM
LET Special Index Register IY = 4EC1H, which points to the MESSAGE STORAGE AREA for a message “1DH + ‘Verifying’ + 03H“.
“GREAD”
51F4
PUSH BC
Save Register Pair BC to the top of the stack.
51F5
PUSH DE
Save Register Pair DE to the top of the stack.
51F6
PUSH HL
Save Register Pair HL to the top of the stack.
51F7
PUSH IX
Save Register Pair IX (i.e., the function) to the top of the stack.
51F9
LD IX,GEXIT
LET Register Pair IX = 5228H, which is the function exit address.
51FD
EX (SP),IX
Put the function exit address at the top of the stack via an EXchange, which swaps the value stored in Register Pair IX with the value stored in Register Pair (SP).
51FF
PUSH IX
Save Register Pair IX (the loop exit address)to the top of the stack.
5201
LD A,D
LET Register A = the track number (stored in Register D).
5202
CP 28H
Compare the value held in Register A against 28H (Decimal: 40). Results:
  • If Register A equals track 40, the Z FLAG is set.
  • If A < track 40, the CARRY FLAG will be set.
  • if A >= track 40, the NO CARRY FLAG will be set.
5204
JR C,GREAD1
     [520BH]
If A < track 40 then the C FLAG (Carry) is set, JUMP to 520BH.

If we are here, then we are at track 40, which gets special handling.

5206
LD A,E
LET Register A = the sector number (stored in Register E).
5207
OR 80H
OR Register A against 80H to add back the offset.
5209
LD E,A
LET Register E = the masked sector number (stored in Register A).
520A
RET
RETurn to the caller.


520BH – Display the appropriate Reading/Writing/Verifying Track xx Sector yy Message. On Entry, IY is pointing to a message of Reading, Writing, or Verifying, D holds the track number, and E holds the sector number.

“GREAD1”
520B
PUSH BC
Save Register Pair BC to the top of the stack.
520C
PUSH DE
Save Register Pair DE to the top of the stack.
520D
PUSH HL
Save Register Pair HL to the top of the stack.
520E
LD HL,FTRACK
LET Register Pair HL = 4ED3H, which is where the track number would go in the applicable Reading/Writing/Verifying message.
5211
LD A,D
LET Register A = the track number (held in Register D).
5212
CALL OUTHEX
     [522CH]
GOSUB to 522CH to convert the value held in Register A into text and insert it at location (HL).
5215
LD HL,SEC
LET Register Pair HL = 4EDEH, which is where the sctor number would go in the message.
5218
LD A,E
LET Register A = the track number (held in Register E).
5219
CALL OUTHEX
     [522CH]
GOSUB to 522CH to convert the value held in Register A into text and insert it at location (HL).
521C
521E
PUSH IY
POP HL
Let Register Pair HL = Special Index Register IY (which was holding the first message to display)
521F
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
5222
LD HL,REST
LET Register Pair HL = 4ECCH, which is the message location for Track xx, Sector yy. xx and yy will already have been filled in.
5225
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
“GEXIT”
5228
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5229
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
522A
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
522B
RET
RETurn to the caller.


522CH – Convert the Value in Register A into a Two Digit Decimal, stored in (HL).

“OUTHEX”
522C
LD (HL),2FH
Store the ASCII value of the character before “0” into into the memory location pointed to by Register Pair HL.
“ASCII1”
522E
INC (HL)
Bump the value stored in (HL) by 1. On the INITIAL run of this instruction, (HL) will then contain a “0”.
522F
SUB 0AH
SUBtract 0AH (Decimal: 10) from Register A.
5231
JR NC,ASCII1
      [522EH]
If Register A was less than 10, the NC FLAG (No Carry) is set, LOOP BACK to 522EH until it finally is negative.
5233
ADD A,3AH
LET Register A (which is the remainder of that subtraction) = Register A + “0” + 10 (note: The +10 brings us back positive).
5235
INC HL
INCrement the value stored in Register Pair HL by 1 for the next character.
5236
LD (HL),A
Store the converted remaimder (held in Register A) into the memory location pointed to by Register Pair HL.
5237
RET
RETurn to the caller.


5238H – Move to the Next Sector Buffer for a Given Gran. Since a Gran is 3 Sectors, processing a gran requires moving between 3 memory buffers. On Entry, D holds the Track, E holds the Sector Number, and HL points to the associated Data Buffer.

“BUMP”
5238
INC E
INCrement the sector number (stored in Register E) by 1.
5239
PUSH DE
Save the track and sector (held in Register Pair DE) to the top of the stack.
523A
LD DE,0100H
LET Register Pair DE = 0100H (Decimal: 256) which is the number of bytes in a sector.
523D
ADD HL,DE
LET Register Pair HL = Register Pair HL (which is the prior buffer) + Register DE (a full sector worth of memory), this making HL point to the next 256 byte data buffer.
523E
POP DE
Restore the track and sector number from the top of the STACK into Register Pair DE, and then remove the entry from the stack.
523F
RET
RETurn to the caller.


5240H – Move to the next Gran Buffer in a Given Track.

“GBUMP”
5240
LD IY,03H
LET Special Index Register IY = 0003H, for the number of sectors in a gran.
5244
ADD IY,DE
LET Special Index Register IY = Special Index Register IY + Register Pair DE (which is the track and sector pointer).
5246
5248
PUSH IY
POP DE
Let Register Pair DE = Special Index Register IY.
5249
524A
INC HL
INC HL
INCrement the value stored in Register Pair HL by 2 to skip over the track and sector bytes.
524B
EX DE,HL
EXchange the value stored in Register Pair HL (i.e., the memory buffer) with the value stored in Register Pair DE (i.e., the next track/sector).
524C
LD IY,0300H
LET Special Index Register IY = 0300H (Decimal: 768), which is 3 sectors worth of 256 bytes.
5250
ADD IY,DE
LET Special Index Register IY = Special Index Register IY (i.e., an offset of 3 sectors worth of bytes) + Register DE (i.e., the memory buffer).
5252
EX DE,HL
EXchange the value stored in Register Pair HL (i.e., the next track/sector) with the value stored in Register Pair DE (i.e., the memory buffer).
5253
5255
PUSH IY
POP HL
Save the new buffer pointer (held in Special Index Register IY) to Register Pair HL.
5256
RET
RETurn to the caller.


5257H – Copy of the BOOT Sector and Check for Permitted Backup.

“RBOOT”
5257
LD A,(SGAT)
Fetch the value stored at memory location 6000H (i.e., the boot allocation) and put it into Register A.
525A
RES 0,A
RESet (i.e., set as 0) BIT 0 of Register A to indicate that the bootstrap gran has been copied.
525C
LD (SGAT),A
Store the value held in Register A into the memory location 6000H to indicate that the boot sector has already been read.
525F
LD A,(BSIDES)
Fetch the source side number (stored at memory location 4E81H) and put it into Register A.
5262
LD (CSIDE),A
Store the source side number (held in Register A) into the memory location 4463H.
NOTE: 4463H is the storage location for the old system disk side number.
5265
LD DE,0001H
LET Register Pair DE = 0001H to select the bootstrap sector (D = Track 00, E = Sector 01).
5268
LD HL,BUFF
LET Register Pair HL = 6200H to point to a buffer.
526B
CALL RGRAN
     [517DH]
GOSUB to 517DH to read a gran into a memory buffer.
526E
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
5271
LD HL,BUFF + 2
We need to set up for a LDIR, so LET Register Pair HL = 6202H, which is 2 bytes into the boot sector (skipping track and sector bytes), as the source of the data to move.
5274
LD DE,SPAR_
LET Register Pair DE = 5E00H, which will be the scratch pad / destination buffer for the moved data.
5277
LD BC,0100H
LET Register Pair BC = 0100H (Decimal: 256) which is the number of bytes to move.
527A
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
527C
LD A,(BUFF + S1TYPE + 2)
Fetch the dos version number (stored at memory location 6300H) and put it into Register A.
527F
CP 12H
Compare the value held in Register A against 12H to see if it is before version 1.3. Results:
  • If Register A equals 12H, the Z FLAG is set.
  • If A < 12H, the CARRY FLAG will be set.
  • if A >= 12H, the NO CARRY FLAG will be set.
5281
JP C,N12
     [4E35H]
If A < 12H (i.e., v1.1) then the C FLAG (Carry) is set, JUMP to 4E35H.
5284
LD IXH,62H
Let the MSB of Special Index Register IX be 62H (which is the MSB of the buffer location)
5287
LD IXL,24H
Let the LSB of Special Index Register IX be 24H (which is the offset to the protection counter), so now Special Index Register IX = 6224H, which is the storage location for the limited backup counter
528A
LD A,(IX+00H)
Fetch the number of permitted backups remaining from the memory location pointed to by IX+00H.
528D
INC A
INCrement the value stored in Register A by 1 so that if the counter was set to infinite (FF), a Z FLAG will be triggered due to the INC.
528E
RET Z
If the Z FLAG (Zero) is set (so the counter was set to infinite), RETurn to the caller.
528F
DEC A
If we are here, then the backups are being tracked, so DECrement the value stored in Register A by 1 to use up 1 backup.
5290
JR Z,RBOOT1
     [52A9H]
If this reduction leaves us with 0 backups left, JUMP to 52A9H to set the counter flag.
5292
DEC (IX+00H)
All those INCs and DECs were for testing purposes. Here we actually debit the number of backups left.
5295
PUSH HL
Save the buffer pointer (held in Register Pair HL) to the top of the stack.
5296
LD DE,0001H
LET Register Pair DE = 0001H which is the location of the bootstrap sector (Track 00H, Sector 01H)
5299
LD HL,BUFF + 2
LET Register Pair HL = 6202H so as to point to the buffer in RAM to write (skipping over the track and sector bytes).
529C
LD A,(FDRIVS)
Fetch the source drive number from (FDRIVS) and put it into Register A.
529F
LD C,A
LET Register C = the source drive number (held in Register A).
52A0
CALL XWRITE
     [45F7H]
GOSUB to 45F7H to write the bootstrap sector back to diskette.
52A3
POP HL
Restore the buffer pointer from the top of the STACK into Register Pair HL, and then remove the entry from the stack.
52A4
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
52A7
JR RBOOT2
   [52AEH]
JUMP to 52AEH to continue with clearing the count for this backup.


52A9H – Continuation of BACKUP Routine. Jumped here if no more permitted backups can be made.

“RBOOT1”
52A9
LD A,0FFH
LET Register A = 0FFH, which will signify that all permitted backups have been utilized.
52AB
LD (CXFLAG),A
Store the FFH (held in Register A) into the memory location 4E85H which stores the counter flag.
“RBOOT2”
52AE
LD (IX+00H),00H
Store a 00H into memory location pointed to by IX+00H to clear the counter for this backup.
52B2
XOR A
Set the Z FLAG.
52B3
RET
RETurn to the caller.


52B4H – Read the Directory Track into RAM.

“RDIR”
52B4
LD DE,1101H
LET Register Pair DE = 1101H, meaning Register D will hold 11H (Track 17), and Register E will hold 01H (Sector 1).
52B7
LD HL,BUFF
LET Register Pair HL = 6200H, which will be the buffer in RAM
52BA
LD B,06H
LET Register B = 06H, which is the number of grans in a directory.
52BC
LD A,(BSIDES)
Fetch the source side number (stored at memory location 4E81H) and put it into Register A.
52BF
LD (CSIDE),A
Store the source side number (held in Register A) into the memory location 4463H.
NOTE: 4463H is the storage location for the old system disk side number.
“RDIR1”
52C2
CALL RGRAN
     [517DH]
GOSUB to 517DH to READ ONE GRAN.
52C5
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
52C8
CALL GBUMP
     [5240H]
GOSUB to 5240H to advance all the pointers for the next GRAN.
52CB
DJNZ RDIR1
     [52C2H]
LOOP back to 52C2H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
52CD
LD HL,FGAT+FLAW
In preparation for a LDIR Memory Move, LET Register Pair HL = 6160H to point to the flaw table from the destination disk in RAM
52D0
LD DE,BUFF+2+FLAW
LET Register Pair DE = 6262H to point to the flaw table in the GAT in RAM
52D3
LD BC,28H
LET Register Pair BC = 0028H (Decimal: 40) to move 40 bytes.
52D6
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
52D8
LD A,(CXFLAG)
Fetch the limited backup counter (stored at memory location 4E85H) and put it into Register A.
52DB
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
52DC
RET Z
If the Z FLAG (Zero) is set then there are still backups which can be made, so RETurn to the caller.
52DD
XOR A
Set Register A to ZERO and clear all Flags.
52DE
LD (CLFN),A
Store the value held in Register A into the HIT TABLE (held in memory location 4E84H).
52E1
LD DE,1101H
LET Register Pair DE = 1101H, meaning Register D wll hold 11H (Track 17), and Register E will hold 01H (Sector 1).
52E4
LD HL,BUFF
LET Register Pair HL = 6200H, which will be the buffer in RAM
52E7
LD B,06H
LET Register B = 06H, which will be the number of grans to read.
“RDIR2”
52E9
CALL EXMGRN
     [5312H]
GOSUB to 5312H to search the current directory gran for files which are flagged as limited backup.
52EC
CALL GBUMP
     [5240H]
GOSUB to 5240H to move to the next gran to process.
52EF
DJNZ RDIR2
     [52E9H]
LOOP back to 52E9H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
52F1
RET
RETurn to the caller.


52F2H – Write the Directory Track.

“WDIR”
52F2
LD DE,1101H
LET Register Pair DE = 1101H, meaning Register D wll hold 11H (Track 17), and Register E will hold 01H (Sector 1).
52F5
LD HL,BUFF
LET Register Pair HL = 6200H, which will be the buffer in RAM
52F8
LD B,06H
LET Register B = 06H, which is the number of grans in a track.
52FA
LD A,(BSIDED)
Fetch the destination side number (stored at memory location 4E82H) and put it into Register A.
52FD
LD (CSIDE),A
Store the source side number (held in Register A) into the memory location 4463H.
NOTE: 4463H is the storage location for the old system disk side number.
“WDIR1”
5300
CALL WGRAN
     [519AH]
GOSUB to 519AH to write a gran.
5303
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
5306
CALL VGRAN
     [51BBH]
GOSUB to 51BBH to verify the gran which was just written.
5309
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
530C
CALL GBUMP
     [5240H]
GOSUB to 5240H to move to the next gran to process.
530F
DJNZ WDIR1
     [5300H]
LOOP back to 5300H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
5311
RET
RETurn to the caller.


5312H – Examine a Directory Gran for Files which are limited backup.

“EXMGRN”
5312
PUSH BC
Save Register Pair BC to the top of the stack.
5313
PUSH DE
Save Register Pair DE to the top of the stack.
5314
PUSH HL
Save Register Pair HL to the top of the stack.
“EXMGR1”
5315
LD B,DGRAN
LET Register B = 03H, which is the number of sectors in a Gran.
5317
INC HL
INCrement the value stored in Register Pair HL by 1 to skip over the track number.
5318
INC HL
INCrement the value stored in Register Pair HL by 1 to skip over the sector number.
5319
LD A,E
LET Register A = the sector number (held in Register E).
531A
CP GAT
Compare the value held in Register A against 01H to see if this is the first sector (i.e., the GAT sector). Results: If Register A equals 01H, the Z FLAG is set; otherwise the NZ FLAG is set.
531C
JR NZ,EXMGR2
      [5323H]
If this is NOT the first sector, then the NZ FLAG (Not Zero) is set, so JUMP to 5323H.
531E
LD B,01H
If we are here then we are specifically at the gran sector, which is just 1 sector … so LET Register B = 01H, which is the number of sectors to scan.
5320
LD HL,BUFF+(SECTOR*2)+2
LET Register Pair HL = 6402H, which is the applicable buffer in memory.
“EXMGR2”
5323
PUSH BC
Save the sector counter (held in Register Pair BC) to the top of the stack.
5324
PUSH HL
Save the buffer pointer (held in Register Pair HL) to the top of the stack.
5325
LD B,05H
LET Register B = 05H, which is the number of records per directory sector.
“EXMGR3
5327
PUSH BC
Save the entry counter (held in Register Pair BC) to the top of the stack.
5328
LD A,(HL)
Fetch the file attribute byte (held in the memory location pointed to by Register Pair HL) and put it into Register A.
5329
PUSH HL
Save the entry pointer (Register Pair HL) to the top of the stack.
532A
OR A
Set FLAGS based on the attribute status byte (held in Register A). If there is no file in the portion being examined, the Z FLAG will be set.
532B
JR Z,NXTREC
     [5337H]
If file is NOT active the Z FLAG (Zero) is set, so JUMP to 5337H.
532D
BIT 5,(HL)
Test Bit Number 5 (which is the bit indicating if the file has limited backups) of the file attribute byte (held at the memory location pointed to by Register Pair HL). Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
532F
JR Z,NXTREC
     [5337H]
If that bit was 0, then the file is NOT protected/limited, so JUMP to 5337H.

If we did not jump to 5337H because of either of those 2 tests, we wind up here – to flag the file as deleted.

5331
LD (CCFLAG),A
Store the value held in Register A into the memory location 4E86H (which holds the flag that a file was deleted) to indicate that the file is deleted.
5334
CALL DEALOC
     [5351H]
GOSUB to 5351H to delete the file from the directory.
“NXTREC”
5337
POP HL
Restore the directory pointer to Register Pair HL from the top of the STACK.
5338
LD DE,30H
LET Register Pair DE = 0030H, which is the number of bytes in a directory record.
533B
ADD HL,DE
LET Register Pair HL = the pointer to the top of the current directory entry (held in Register Pair HL) + the number of bytes in a directory entry (held in Register DE), so now Register Pair HL is pointing to the next directory entry.
533C
LD A,(CLFN)
Fetch the value stored at memory location 4E84H (i.e., the entry in the HIT table) and put it into Register A.
533F
INC A
INCrement the value stored in Register A by 1 to point to the next entry in the HIT table.
5340
LD (CLFN),A
Store the value held in Register A into the HIT TABLE (held in memory location 4E84H).
5343
POP BC
Restore the records per sector counter from the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5344
DJNZ EXMGR3
     [5327H]
LOOP back to 5327H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
5346
POP HL
Restore the buffer pointer held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5347
POP BC
Restore the gran counter held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5348
CALL BUMP
     [5238H]
GOSUB to 5238H to move to the next sector.
534B
DJNZ EXMGR3
     [5323H]
Process the next directory sector by LOOPing back to 5323H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
534D
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
534E
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
534F
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5350
RET
RETurn to the caller.


5351H – De-Allocate a File which was Protected. On Entry, HL points to the director record to deallocate.

“DEALOC”
5351
PUSH HL
Save the directory record pointer (held in Register Pair HL) to the top of the stack.
5352
LD A,16H
ADD A,L
LD L,A
LET Register Pair HL = Register Pair HL + 16H, so as to point to the file extents/segment descriptors.
“DEALC1”
5356
LD E,(HL)
Fetch a byte of the extent from the value stored at memory location pointed to by Register Pair HL and put it into Register E.
5357
INC HL
INCrement the value stored in Register Pair HL by 1 to point to another extent value.
5358
LD D,(HL)
Fetch a byte of the extent from the value stored at memory location pointed to by Register Pair HL and put it into Register D.

At this point, Register Pair DE holds the next segment descriptor.

5359
LD A,E
LET Register A = the track number (i.e., the first byte of the extent held in Register E).
535A
CP 0FEH
Compare the value held in Register A against 0FEH to see if we have hit the end of the extents. Results:
  • If Register A equals 0FEH, the Z FLAG is set.
  • If A < 0FEH, the CARRY FLAG will be set.
  • if A >= 0FEH, the NO CARRY FLAG will be set.
535C
JR NC,DEALC2
      [5364H]
If the extent byte is either FEH or FFH then the NC FLAG (No Carry) is set then we are done! JUMP to 5364H.
535E
INC HL
INCrement the value stored in Register Pair HL by 1 to now point to the first byte of the next extent.
535F
CALL RELEAS
     [537CH]
GOSUB to 537CH to de-allocate all grans in the extent pointed to by Register Pair HL.
5362
JR DEALC1
   [5356H]
JUMP to 5356H in this routine to loop over all extents.


5364H – Clear the Directory Entry following a De-Allocation.

“DEALC2”
5364
POP HL
Put the directory entry address held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5365
5366
LD D,H
LD E,L
LET Register Pair DE = Register Pair HL.
5367
INC DE
INCrement the value stored in Register Pair DE by 1 so that DE now is the next directory entry.
5368
LD BC,02FH
LET Register Pair BC = 002FH (Decimal: 47) which is the number o bytes in a directory record.
536B
LD (HL),00H
Store a 00H into the first byte of directory entry pointed to by Register Pair HL.
536D
LDIR
Zero the remainder by transferring a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
536F
LD HL,.RES.BUFF+SECTOR+2
LET Register Pair HL = 6302H, which is the start of the HIT TABLE of the directory track in RAM.
5372
LD A,(CLFN)
Fetch the value stored at memory location 4E84H (i.e., the offset in the directory table for the file being dealt with) and put it into Register A.
5375
LD E,A
LET the LSB of Register Pair DE = the offset into the HIT table for the file being dealt with.
5376
LD D,00H
LET the MSB of Register Pair DE = 0.
5378
ADD HL,DE
Set HL to be the hash code for the file by setting Register Pair HL = Register Pair HL (i.e., the beginning of the HIT table) + Register DE (i.e., the offset in the HIT table for the file being dealt with).
5379
LD (HL),00H
Store a 00H into the entry in the HIT table in RAM for the file being dealt with (held at the memory location pointed to by Register Pair HL).
537B
RET
RETurn to the caller.


537CH – De-Allocate All Grans in a Given Extent. On Entry, DE is the segment descriptor.

“RELEAS”
537C
PUSH BC
Save Register Pair BC to the top of the stack.
537D
PUSH DE
Save Register Pair DE to the top of the stack.
537E
PUSH HL
Save Register Pair HL to the top of the stack.
537F
LD L,E
Put the track number of the segment at issue into Register L.
5380
LD H,FGAT.HIGH.
LET the MSB of Register Pair HL = 61H, so that HL now points to 61xx, which is the given tracks memory location in RAM.
5382
LD A,D
Put the number of grans (held in Register D) into Register A.
5383
AND 1FH
MASK the value of Register A against 1FH (0001 1111). This has the effect of turning off bits 7, 6, 5.
5385
LD C,A
LET Register C = the masked Register A.
5386
XOR D
eXclusive OR Register D against Register A. The results are stored in Register A. This isolates the GRAN OFFSET.
5387
5388
5389
RLCA
RLCA
RLCA
We want to shift 7, 6, 5 into 2, 1, 0 so we Rotate the bits in A left (with Bit 7 going into both the CARRY and Bit 0) three times.
538A
LD E,00H
LET Register E = 00H since it will act as an offset counter.
“REL1”
538C
PUSH AF
Save the gran offset of the starting gran (held in Register A) to the top of the stack.
538D
PUSH HL
Save the buffer pointer (held in Register Pair HL) to the top of the stack.
538E
ADD A,E
LET Register A = Gran Offset (held in Register A) + the gran counter (held in Register E).
538F
LD L,A
LET the LSB of Register Pair HL = the offset from the start of the track to the current gran.
5390
LD H,00H
LET the MSB of Register Pair HL = 00, so that HL now contains the offset from the start of the track to the current gran.
5392
LD A,06H
We will want to divide HL by the number of grans in a track (i.e., 6), so first LET Register A = 06H.
5394
CALL DIV
     [4451H]
GOSUB to 4451H to divide HL by A. When done, Register A will hold the bit number and Register L will hold the track offset.
5397
LD D,A
LET Register D = the bit number (held in Register A).
5398
LD A,L
LET Register A = the track offset (held in Register L).
5399
POP HL
Put the GAT TABLE POINTER from the the top of the STACK into Register Pair HL, and then remove the entry from the stack.
539A
PUSH HL
Put the GAT TABLE POINTER (held in Register Pair HL) to the the top of the STACK
539B
539C
ADD A,L
LD L,A
LET Register L = the track offset from the start (held in Register A) + the GAT TABLE POINTER (held in Register L). Register Pair HL will now point to the next track.
539D
LD A,D
LET Register A = the bit number (held in Register D).
539E
LD B,(HL)
Fetch the allocation byte from the GAT TABLE ENTRY (stored at memory location pointed to by Register Pair HL) and put it into Register B.
539F
CALL CLRBIT
     [53ADH]
GOSUB to 53ADH to release one bit, thus deallocating the gran pointed to by Register B.
53A2
LD (HL),B
Store the GAT TABLE ENTRY (held in Register B) into the memory location (i.e., the GAT TABLE ENTRY) pointed to by Register Pair HL.
53A3
POP HL
Restore the GAT POINTER from the top of the STACK into Register Pair HL, and then remove the entry from the stack.
53A4
POP AF
Restore the STARTING GRAN IN TRACK from the top of the STACK into Register Pair AF, and then remove the entry from the stack.
53A5
INC E
INCrement the value stored in Register E by 1 so as to point to the next gran in the extent.
53A6
DEC C
DECrement the value stored in Register C by 1 to indicate that there is one less gran to de-allocate.
53A7
JR NZ,REL1
      [538CH]
If there are still more grans to de-allocate, then the NZ FLAG (Not Zero) will be set. JUMP to 538CH.
53A9
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
53AA
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
53AB
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
53AC
RET
RETurn to the caller.


53ADH – Reset Bit (A) of Register B. On Entry, A contains the bit to reset and B contains the byte to reset.

“CLRBIT”
53AD
AND 07H
MASK the value of Register A against 07H (0000 0111). This has the effect of leaving only bits 2, 1, 0 active.
53AF
RLCA
Rotate the bits in A left (with Bit 7 going into both the CARRY and Bit 0), so A is now 0000 xyz0.
53B0
RLCA
Rotate the bits in A left (with Bit 7 going into both the CARRY and Bit 0), so A is now 000x yz00.
53B1
RLCA
Rotate the bits in A left (with Bit 7 going into both the CARRY and Bit 0), so A is now 00xy z000.
53B2
OR 80H
OR Register A against 80H to generate an OPCODE, so A is now 10xy z000. Register A can now be ONLY 80, 88, 90, 98, A0, A8, B0 or B8H.
53B4
LD (CLRBT2),A
Store the value held in Register A into the memory location 53B8H, which is the 2nd byte of the next instruction.
53B7
RES (CLRBT2),B
RESet (i.e., set as 0) BIT nn of Register B. If A was 80H then this opcode is RES 0,B. If A was 90H then this opcode is RES 2,B. If A was A8H, then this opcode is RES 5,B
53B9
RET
RETurn to the caller.


53BAH – Check to see if we are out of memory. Move to the Next Gran in the Buffer; set C FLAG if none left.

“MEMCHK”
53BA
PUSH BC
Save Register Pair BC to the top of the stack.
53BB
PUSH DE
Save Register Pair DE to the top of the stack.
53BC
PUSH HL
Save Register Pair HL to the top of the stack.
53BD
LD HL,(BUFPNT)
Fetch the START OF THE BUFFER (stored at memory location 4E8CH) and put it into Register HL.
53C0
CALL GBUMP
     [5240H]
GOSUB to 5240H to move to the next gran to process.
53C3
LD (BUFPNT),HL
>Store the new BUFFER POINTER (held in Register HL) into the memory location 4E8CH.
53C6
EX DE,HL
EXchange the value stored in Register Pair HL (i.e., the buffer pointer) with the value stored in Register Pair DE.
53C7
LD HL,(MEMTOP)
Fetch the END OF RAM (i.e., the value stored at memory location 4E8EH) and put it into Register HL.
53CA
PUSH HL
Save the END OF BUFFER (held in Register Pair HL) to the top of the stack.
53CB
OR A
Clear the CARRY FLAG.
53CC
SBC HL,DE
Subtracts the BUFFER POINTER (held in Register Pair DE) from the TOP OF MEMORY (held in Register Pair HL). If the pointer is after the end of the buffer the CARRY FLAG will have been set here.
53CE
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
53CF
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
53D0
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
53D1
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
53D2
RET
RETurn to the caller.


53D3H – Write the Grans from the RAM BUFFER to the DISKETTE.

“MWRIT”
53D3
LD HL,BUFF
LET Register Pair HL = 6200H, which is be the buffer in RAM
53D6
LD (BUFPNT),HL
Store the START OF THE BUFFER (held in Register HL) into the memory location 4E8CH.
53D9
LD A,(BSIDED)
Fetch the DESTINATION SIDE NUMBER (stored at memory location 4E82H) and put it into Register A.
53DC
LD (CSIDE),A
Store the DESTINATION SIDE NUMBER (held in Register A) into the memory location 4463H.
NOTE: 4463H is the storage location for the old system disk side number.
“MWRIT1”
53DF
LD HL,(BUFPNT)
Fetch the BUFFER POINTER (stored at memory location 4E8CH) and put it into Register HL.
53E2
LD A,(HL)
Fetch the sector number (which is stored at memory location pointed to by Register Pair HL) and put it into Register A.
53E3
CP 0FFH
Compare the value held in Register A against 0FFH to see if we are at the end of the disk. If Register A equals 0FFH, the Z FLAG is set; otherwise the NZ FLAG is set.
53E5
SCF
Set the CARRY FLAG
53E6
RET Z
If the byte held at (HL) was FFH, then we are at the end of the data in the buffer so RETurn to the caller with the CARRY FLAG set.
53E7
CALL WGRAN
     [519AH]
GOSUB to 519AH to write the gran to disk.
53EA
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
53ED
CALL VGRAN
     [51BBH]
GOSUB to 51BBH to verify the gran.
53F0
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
53F3
CALL MEMCHK
     [53BAH]
GOSUB to 53BAH to move to the next gran in the buffer (and check for end of memory).
53F6
JR NC,MWRIT1
      [53DFH]
If the NC FLAG (No Carry) is set then we still have more in the buffer so loop back to 53DFH.
53F8
OR A
Clear the CARRY FLAG
53F9
RET
RETurn to the caller.


53FAH – Find the Next Allocated Gran on Diskette.

“FALOC”
53FA
LD HL,SGAT
LET Register Pair HL = 6000H, which is the GAT TABLE in RAM.
“FALOC1”
53FD
LD A,L
LET Register A = the track number (held in Register L).
53FE
CP 28H
See if we are at the end of the diskette by comparing the value held in Register A against 28H (Decimal: 40). Results:
  • If Register A equals track 40, the Z FLAG is set.
  • If A < track 40, the CARRY FLAG will be set.
  • if A >= track 40, the NO CARRY FLAG will be set.
5400
CCF
Invert the state of the CARRY FLAG, so that if we are at or over Track 40, the Carry Flag will be SET instead of cleared.
5401
RET C
If A >= track 40 then the C FLAG (Carry) will be set; RETurn to the caller.
5402
LD A,(HL)
Fetch the allocation byte from the GAT TABLE ENTRY (stored at memory location pointed to by Register Pair HL) and put it into Register A.
5403
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A. If there are no grans allocated then the Z FLAG will be set.
5404
JR NZ,FALOC2
      [5409H]
If there are grans allocated, the NZ FLAG (Not Zero) is set; JUMP to 5409H to process that track.
5406
INC HL
If there are no grans allocated (and the Z FLAG was set) move to the next track by INCrementing the value stored in Register Pair HL by 1.
5407
JR FALOC1
   [53FDH]
JUMP to 53FDH for the entire 40 track diskette.


5409H – Determine Which Track was Allocated.

“FALOC2”
5409
RES 0,(HL)
RESet (i.e., set as 0) BIT 0 of Register (HL), which will clear Gran 0 in the TABLE IN RAM.
540B
LD E,01H
LET Register E = 01H to indicate GRAN 0 on the disk.
540D
BIT 0,A
Test Bit Number 0 of Register A to see if GRAN 0 is allocated. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
540F
JR NZ,FALEXT
      [5435H]
If Gran 0 is allocated the NZ FLAG (Not Zero) will be set; JUMP to 5435H.
5411
RES 1,(HL)
Clear Gran 1 in the table by RESet (i.e., set as 0) BIT 1 of Register (HL).
5413
LD E,04H
LET Register E = 04H to indicate sector 4 (GRAN 1) on the disk.
5415
BIT 1,A
Test Bit Number 1 of Register A to see if GRAN 1 is allocated. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
5417
JR NZ,FALEXT
      [5435H]
If Gran 1 is allocated the NZ FLAG (Not Zero) will be set; JUMP to 5435H.
5419
RES 2,(HL)
Clear Gran 2 in the table by RESet (i.e., set as 0) BIT 1 of Register (HL).
541B
LD E,07H
LET Register E = 07H to indicate sector 7 (GRAN 2) on the disk.
541D
BIT 2,A
Test Bit Number 2 of Register A to see if GRAN 2 is allocated. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
541F
JR NZ,FALEXT
      [5435H]
If the NZ FLAG (Not Zero) is set, JUMP to 5435H.
5421
RES 3,(HL)
Clear Gran 3 in the table by RESet (i.e., set as 0) BIT 1 of Register (HL).
5423
LD E,0AH
LET Register E = 0AH to indicate sector 10 (GRAN 3) on the disk.
5425
BIT 3,A
Test Bit Number 3 of Register A to see if GRAN 3 is allocated. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
5427
JR NZ,FALEXT
      [5435H]
If the NZ FLAG (Not Zero) is set, JUMP to 5435H.
5429
RES 4,(HL)
Clear Gran 4 in the table by RESet (i.e., set as 0) BIT 1 of Register (HL).
542B
LD E,0DH
LET Register E = 0DH to indicate sector 13 (GRAN 4) on the disk.
542D
BIT 4,A
Test Bit Number 4 of Register A to see if GRAN 4 is allocated. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
542F
JR NZ,FALEXT
      [5435H]
If the NZ FLAG (Not Zero) is set, JUMP to 5435H.
5431
RES 5,(HL)
Clear Gran 5 in the table by RESet (i.e., set as 0) BIT 1 of Register (HL).
5433
LD E,10H
LET Register E = 10H to indicate sector 16 (GRAN 5) on the disk.
“FALEXT”
5435
LD D,L
LET Register D = the track number (held in Register L).
5436
OR A
Set FLAGS based on the contents of Register A, which will always clear the CARRY FLAG.
5437
RET
RETurn to the caller.


5438H – Read granules from the source diskette. On exit, the C FLAG will be set if the buffer is full.

“MREAD”
5438
LD HL,BUFF
LET Register Pair HL = 6200H, which will be the buffer in RAM
543B
LD (BUFPNT),HL
>Store the START OF THE BUFFER (held in Register HL) into the memory location 4E8CH.
543E
LD A,(BSIDES)
Fetch the source side number (stored at memory location 4E81H) and put it into Register A.
5441
LD (CSIDE),A
Store the source side number (held in Register A) into the memory location 4463H.
NOTE: 4463H is the storage location for the old system disk side number.
“MREAD1”
5444
CALL 53FAH
     [53FAH]
GOSUB to 53FAH to FIND THE NEXT ALLOCATED GRAN.
5447
JR C,MREAD3
     [545EH]
If the C FLAG (Carry) is set then there are no more allocated Grans so, JUMP to 545EH to set the END OF DISK marker.
5449
544A
LD A,D
ADD A,E
To shortcut trying to test Register Pair DE against 0001H, LET Register A = the MSB of Register Pair DE + the LSB of Register Pair DE.
544B
CP 01H
If Register D + Register E = 1 (hopefully because it was Track 0, Sector 1), the Z FLAG is set; otherwise the NZ FLAG is set.
544D
JR NZ,MREAD2
      [5454H]
If the NZ FLAG (Not Zero) is set then we are probably not at the boot sector; so JUMP to 5454H to skip over the next instructions which specifically apply to the BOOT.
544F
CALL RBOOT
     [5257H]
GOSUB to 5257H to copy the boot sector.
5452
JR NXREAD
   [5457H]
JUMP to 5457H to continue with the next gran.


5454H – Read Granules from RAM to Diskette.

“MREAD2”
5454
CALL RNEXT
     [517AH]
GOSUB to 517AH to READ THE GRAN FROM RAM TO DISK.
“NXREAD”
5457
CALL MEMCHK
     [53BAH]
GOSUB to 53BAH to Check for Memory Full and MOVE TO THE NEXT GRAN.
545A
JR NC,MREAD1
      [5444H]
If the NC FLAG (No Carry) is set then there is more data in the buffer so LOOP BACK to 5444H to process the next gran.
545C
OR A
Set FLAGS based on the contents of Register A, which in all events will clear the CARRY FLAG.
545D
RET
RETurn to the caller.


545EH – Mark the END OF DATA in the BUFFER.

“MREAD3”
545E
LD HL,(BUFPNT)
Fetch the BUFFER POINTER (stored at memory location 4E8CH) and put it into Register HL.
5461
LD (HL),0FFH
Store a FFH terminator into the first byte of the buffer to indicate END OF DISK.
5463
SCF
Set the CARRY FLAG to indicate no more data.
5464
RET
RETurn to the caller.


5465H – Flashing Prompt Routine.

“FWAIT”
5465
PUSH HL
Save the message pointer (held in Register Pair HL) to the top of the stack.
5466
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
5469
POP HL
Restore the message pointer held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
“LOOPY”
546A
LD BC,256H
LET Register Pair BC = 0256H for a delay counter.
“LOOPX”
546D
CALL KBD
     [002BH]
GOSUB to 002BH.
NOTE: 002BH is the Model III ROM Keyboard scanning routine; Register A exits with the ASCII value for the key that was pressed or ZERO if no key was pressed.
5470
CP 0DH
Compare the value held in Register A against 0DH (ASCII: CARRIAGE RETURN). Results: If Register A equals CARRIAGE RETURN, the Z FLAG is set; otherwise the NZ FLAG is set.
5472
JR Z,LINOFF
     [5488H]
If a CARRIAGE RETURN was hit, then the Z FLAG (Zero) is set; JUMP to 5488H to take the message off of the screen and continue.
5474
DEC BC
DECrement the delay counter stored in Register Pair BC by 1.
5475
5476
LD A,B
OR C
Since the Z-80 cannot test Register Pair BC against zero, the common trick is to set Register A to equal to Register B, and then OR A against Register C. Only if both Register B and Register C were zero can the Z FLAG be set.
5477
JR NZ,LOOPX
      [546DH]
If we still have more counter to go, the NZ FLAG (Not Zero) will be set, JUMP to 546DH.
5479
LD A,(FLAG)
Fetch the TOGGLE BYTE stored at memory location 4E83H and put it into Register A.
547C
XOR 01H
Flip the TOGGLE BYTE
547E
LD (FLAG),A
Store the flipped TOGGLE BYTE back into memory location 4E83H.
5481
JR Z,FWAIT
     [5465H]
If the Z FLAG (Zero) is set then we need to redisplay the message, so JUMP to 5465H.
5483
CALL LINOFF
     [5488H]
GOSUB to 5488H to clear the line on the display.
5486
JR LOOPY
   [546AH]
JUMP back to 546AH to start the flashing routine again.


5488H – SUBROUTINE in the Flashing Prompt Routine to clear a line.

“LINOFF”
5488
LD A,1DH
LET Register A = 1DH to go back to the start of the line.
548A
CALL DSP
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
548D
LD A,1EH
LET Register A = 1EH to clear to the end of the line.
548F
JP DSP
   [0033H]
JUMP to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position. Since this was JUMPED to instead of CALLed, the RET at the end of this ROM routine will then RETurn to the caller of this subroutine instead of returning to this place.


5492H – Prompt for the SOURCE DISK (if necessary).

“CKSRC”
5492
LD A,(SINGLE)
Check to see if this is a SINGLE DRIVE BACKUP by fetching the value stored at memory location 4E87H into Register A. This flag identifies whether SOURCE = DESTINATION or not.
5495
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
5496
RET NZ
If the NZ FLAG (Not Zero) is set, then we are using DIFFERENT source and destination disks; so RETurn to the caller.
5497
LD A,(SDFLAG)
Fetch the value stored at memory location 4E7CH (i.e., the memory location indicating if the source disk is in the drive) and put it into Register A.
549A
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
549B
RET Z
If the Z FLAG (Zero) is set then the source disk is already in the drive, so RETurn to the caller.
549C
XOR A
If we are here, then the source disk is NOT in the drive, so set Register A to ZERO and clear all Flags.
549D
LD (SDFLAG),A
Store the value held in Register A into the memory location 4E7CH to indicate that the source disk is in the drive.
“INSRC”
54A0
LD HL,SRCMSG
LET Register Pair HL = 4EF7H so as to point to the message “Insert SOURCE Diskette”
54A3
JR FWAIT
   [5465H]
JUMP to 5465H to flash the message and wait for a key.


54A5H – Prompt User for the Destination Disk.

“CKDES”
54A5
LD A,(SINGLE)
Check to see if this is a SINGLE DRIVE BACKUP by fetching the value stored at memory location 4E87H into Register A. This flag identifies whether SOURCE = DESTINATION or not.
54A8
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
54A9
RET NZ
If the NZ FLAG (Not Zero) is set, then we are using DIFFERENT source and destination disks; so RETurn to the caller.
54AA
LD A,(SDFLAG)
Fetch the value stored at memory location 4E7CH (i.e., the memory location indicating if the destination disk is in the drive) and put it into Register A.
54AD
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
54AE
RET NZ
If the NZ FLAG (Not Zero) is set then the destination disk is already in the drive, so RETurn to the caller.
54AF
LD A,0FFH
LET Register A = 0FFH, which is a flag to indicate that the destination disk is NOT in the drive.
54B1
LD (SDFLAG),A
Put a FFH (stored in Register A) into the memory location 4E7CH (i.e., the memory location indicating if the destination disk is in the drive).
“INDES”
54B4
LD HL,DESMSG
LET Register Pair HL = 4F17H so as to point to the message “Insert DESTINATION Diskette”
54B7
JR FWAIT
   [5465H]
JUMP to 5465H to wait for a key.


54B9H – Check Destination Diskette.

“DGAT”
54B9
CALL CKSRC
     [5492H]
GOSUB to 5492H to prompt for the SOURCE disk, if necessary.
54BC
LD A,(FDRIVS)
Fetch the source drive number (stored at memory location 4E7EH) and put it into Register A.
54BF
LD C,A
LET Register C = the source drive number (stored in Register A).
54C0
CALL RDGAT
     [4A93H]
GOSUB to 4A93H.
NOTE: 4A93H is the SYS00/SYS routine to READ THE GAT sector into RAM (Buffer at 4D00H).
54C3
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
54C6
LD HL,BUFF2
LET Register Pair HL = 4D00H, which is the start of the GAT SECTOR’s RAM Buffer.
54C9
PUSH HL
Save Register Pair HL (i.e., the start of the GAT SECTOR’s RAM Buffer) to the top of the stack.
54CA
LD DE,FGAT
LET Register Pair DE = 6100H as the pointer to the GAT SECTOR’s RAM Buffer.
54CD
LD BC,0100H
LET Register Pair BC = 0100H (Decimal: 256) as the number of bytes in the GAT SECTOR.
54D0
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
54D2
POP HL
Put the the start of the GAT SECTOR’s RAM Buffer (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
54D3
LD DE,SGAT
LET Register Pair DE = 6000H as the destination for a transfer of the GAT TABLE’s RAM Buffer.
54D6
LD BC,29H
Set Register Pair BC to be one higher than the highest track number (i.e., 0029H = Decimal: 41) as the number of bytes in the GAT TABLE.
54D9
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
54DB
CALL CKDES
     [54A5H]
GOSUB to 54A5H to prompt for the DESTINATION diskette.
54DE
LD A,(FDRIVD)
Fetch the destination drive number from the memory location 4E7FH and put it into Register A.
54E1
LD C,A
LET Register C = the destination drive number (held in Register A).
54E2
CALL RDGAT
     [4A93H]
GOSUB to 4A93H.
NOTE: 4A93H is the SYS00/SYS routine to READ THE GAT sector into RAM (Buffer at 4D00H).
54E5
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
54E8
LD HL,BUFF2+FLAW
LET Register Pair HL = 4D60H which is the pointer to the FLAWED TRACK TABLE in the GAT in RAM
54EB
LD DE,FGAT
LET Register Pair DE = 6100H which is the pointer to the GRANULE ALLOCATION TABLE in RAM
54EE
LD B,27H
Set Register Pair B be one lower than the highest track number (i.e., 0027H = Decimal: 39) for a loop of 40 entries to scan.
“DGAT1”
54F0
LD A,(DE)
Check to see if there is a file here by fetching the GRAN ALLOCATION INFORMATION stored at memory location pointed to by Register Pair DE and put it into Register A.
54F1
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
54F2
JR Z,DGAT2
     [54F9H]
If the Z FLAG (Zero) is set then there are no grans allocated at that location, so JUMP to 54F9H.
54F4
LD A,(HL)
Check to see if the destination disk has a flawed track there by fetching the GRAN EXISTENCE INFORMATION stored at memory location pointed to by Register Pair HL and put it into Register A.
54F5
INC A
INCrement the value stored in Register A by 1 to trigger a Z if the value was FFH, meaning “Bad Track”.
54F6
JP Z,ABRT
     [4E4AH]
If the Z FLAG (Zero) is set then that is a bad track, so JUMP to 4E4AH to abort.
“DGAT2”
54F9
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the next entry in the GRANULE EXISTENCE TABLE in RAM.
54FA
INC DE
INCrement the value stored in Register Pair DE by 1 to point to the next entry in the GRANULE ALLOCATION TABLE in RAM.
54FB
DJNZ DGAT1
     [54F0H]
LOOP back to 54F0H so as to read the entire table of 40 entries, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
54FD
LD HL,BUFF2+FLAW
LET Register Pair HL = 4D60H which is the pointer to the the FLAW TABLE in the GAT for the DESTINATION DRIVE in RAM.
5500
LD DE,FGAT+FLAW
LET Register Pair DE = 6160H which is 60H bytes into the GRANULE ALLOCATION TABLE (i.e., the flaw table which will be written to the destination drive) in RAM
5503
LD BC,40H
LET Register Pair BC = 0028H (Decimal: 40) to move 40 bytes (which means 40 tracks).
5506
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
5508
RET
RETurn to the caller.


5509H – Prompt the User for the SYSTEM DISK (if necessary).

“CKSYS”
5509
LD A,(DATDSK)
LET Register A = the flag placed in the memory location put into 550AH-550BH elsewhere in this overlay to indicate if this ia a data disk or not.
550B
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
550C
RET Z
550AH holds a 0 if we do not need to prompt for a SYSTEM disk and a FFH if we do. If the Z FLAG (Zero) is set, the we do NOT need to prompt for the SYSTEM DISK, so RETurn to the caller.
“INSYS”
550D
LD A,0DH
LET Register A = 0DH (ASCII: CARRIAGE RETURN) to move to a new line on the screen.
550F
CALL DSP
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
5512
LD HL,SYSMSG
LET Register Pair HL = 4F3CH, which is the prompt to insert the SYSTEM DISK.
5515
JP FWAIT
   [5465H]
JUMP to 5465H to display the message and wait for a keypress.


5518H – Copy the Source Diskette to the Destination Diskette.

“DOLLAR”
5518
LD A,0FH
LET Register A = 0FH (ASCII: Turn Off Cursor).
551A
LD (BCKFLG),A
Store the 0FH into the memory location 5836H to indicate that this is a backup.
551D
CALL DSP
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
5520
CALL CKDES
     [54A5H]
GOSUB to 54A5H to prompt the user to insert the destination diskette (if necessary).
5523
CALL CHKFOR
     [56B1H]
GOSUB to 56B1H to analyze the diskette to see if it needs to be formatted.
5526
CALL NZ,FOMAT
        [5803H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, so GOSUB to 5803H to format the disk.
5529
CALL RESTRY
     [4E41H]
GOSUB to 4E41H to reset the RETRY COUNTER.
552C
CALL DGAT
     [54B9H]
GOSUB to 54B9H to check the destination diskette.
“DOLOOP”
552F
CALL CKSRC
     [5492H]
GOSUB to 5492H to prompt for the source diskette (if necessary).
5532
CALL MREAD
     [5438H]
GOSUB to 5438H to read the granules from the source diskette.
5535
CALL CKDES
     [54A5H]
GOSUB to 54A5H to prompt for the destination diskette.
5538
CALL MWRIT
     [53D3H]
GOSUB to 53D3H to write the granules to the destination diskette.
553B
JR NC,DOLOOP
      [552FH]
If the NC FLAG (No Carry) is set then there are still more granules to copy; JUMP to 552FH.
553D
CALL CKSRC
     [5492H]
GOSUB to 5492H to prompt for the source diskette.
5540
CALL RDIR
     [52B4H]
GOSUB to 52B4H to read the directory track.
5543
LD HL,FGAT
LET Register Pair HL = 6100H which is the pointer to the Source GRANULE ALLOCATION TABLE in RAM
5546
LD DE,BUFF+2
LET Register Pair DE = 6202H which is the pointer to the 3rd byte of the Destination GRANULE ALLOCATION SECTOR in RAM
5549
LD BC,28H
LET Register Pair BC = 0028H (Decimal: 40), which is the number of tracks on a disk a/k/a the number bytes in the GAT (to move).
554C
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
554E
LD HL,DATBUF
LET Register Pair HL = 4E90H which is the pointer to the DATE in RAM
5551
LD DE,BUFF+0DAH
LET Register Pair DE = 62DAH which is the pointer to the DATE in the GRANULE SECTOR in RAM
5554
LD BC,0008H
LET Register Pair BC = 0008H (Decimal: 8), so as to move the 8 bytes of a date.
5557
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
5559
CALL CKDES
     [54A5H]
GOSUB to 54A5H to prompt for the destination diskette.
555C
CALL WDIR
     [52F2H]
GOSUB to 52F2H to write the DIRECTORY TRACK from RAM to DISKETTE.
555F
RET
RETurn to the caller.


5560H – Start of the backup routine … first Check the Source Diskette.

“BPREP”
5560
CALL CKSRC
     [5492H]
GOSUB to 5492H to prompt for the source diskette (if necessary).
5563
LD A,(FDRIVS)
Fetch the source drive number from memory location 4E7EH and put it into Register A.
5566
LD C,A
LET Register C = the source drive number.
5567
CALL RDHIT
     [4ABAH]
GOSUB to 4ABAH.
NOTE: 4ABAH is the SYS00/SYS routine to read the HIT sector into RAM.
556A
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
556D
LD HL,(BUFF1+0E0H)
Fetch the value stored at memory location 43E0H (which is the SYS0 EXTENT AREA) and put it into Register HL.
5570
INC HL
INCrement the value stored in Register Pair HL by 1 to act as a test to see if that SYS0 EXTENT AREA was holding a FFH.
5571
5572
LD A,H
OR L
Since the Z-80 cannot test Register Pair HL against zero, the common trick is to set Register A to equal to Register H, and then OR A against Register L. Only if both Register H and Register L were zero can the Z FLAG be set.
5573
JR NZ,BPREPX
      [5585H]
If that system extent area was not FFH, then there is a system on the source diskette (and the NZ FLAG is set); JUMP to 5585H.

If we are here, then this is a non-DOS disk.

5575
LD A,(FDRIVS)
Fetch the source drive number from memory location 4E7EH and put it into Register A.
5578
AND 03H
MASK the value of Register A against 03H (0000 0011) to leave only bits 1 and 0 active. If the result is a 0, then we are NOT using the SYSTEM DRIVE as the source.
557A
CALL Z,SETDAT
       [56ABH]
If the Z FLAG (Zero) is set then since this is a data disk we will need to get the SYSTEM DISK back, so GOSUB to 56ABH.
557D
LD A,(FDRIVD)
Fetch the destination drive number from memory location 4E7FH and put it into Register A.
5580
AND 03H
MASK the value of Register A against 03H (0000 0011) to leave only bits 1 and 0 active. If the result is a 0, then we are NOT using the SYSTEM DRIVE as the destination.
5582
CALL Z,SETDAT
       [56ABH]
If the Z FLAG (Zero) is set then since this is a data disk we will need to get the SYSTEM DISK back, so GOSUB to 56ABH.
“BPREPX”
5585
LD HL,SGAT
We are going to use LDIR to clear the buffer at 6000H (which is the source disk GAT). First, LET Register Pair HL = 6000H.
5588
LD DE,SGAT + 1
LET Register Pair DE = 6001H.
558B
LD BC,(SECTOR*2)-1
LET Register Pair BC = 01FFH (Decimal: 511) to clear 512 bytes (which is the SOURCE disk GAT and the DESTINATION disk GAT).
558E
LD (HL),00H
Store the value held in Register 00H into the memory location pointed to by Register Pair HL.
5590
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
5592
LD A,(FDRIVS)
Fetch the source drive number from memory location 4E7EH and put it into Register A.
5595
LD C,A
LET Register C = the source drive number.
5596
CALL RDGAT
     [4A93H]
GOSUB to 4A93H.
NOTE: 4A93H is the SYS00/SYS routine to READ THE GAT sector into RAM (Buffer at 4D00H).
5599
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
559C
LD HL,(BUFF2+DPASS)
Fetch the hashed source disk master pasword from memory location 4DCEH and put it into Register HL.
559F
LD DE,(PTRAP)
Fetch the user provided password from memory location 4E88H and put it into Register DE.
55A3
PUSH HL
Save the hashed source disk master password (held in Register Pair HL) to the top of the stack.
55A4
OR A
Set FLAGS based on the contents of Register A, which, in all cases, clears the CARRY FLAG.
55A5
SBC HL,DE
Subtract the user provided pasword from the source disk master password.
55A7
POP HL
Restore the hashed source disk master password from the top of the STACK into Register Pair HL, and then remove the entry from the stack.
55A8
JR Z,BPREP1
     [55B3H]
If the Z FLAG (Zero) is set then the two passwords match, so JUMP to 55B3H to execute the backup.
55AA
LD HL,INVPAS
LET Register Pair HL = 5031H to point to the INVALID MASTER PASSWORD message.
55AD
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
55B0
JP EXIT
   [4E50H]
JUMP to 4E50H to exit the BACKUP routine.


55B3H – Continuation of the BACKUP routine; Jumped here if the user supplied the correct master password.

“BPREP1”
55B3
LD A,(FDRIVS)
Fetch the source drive number from memory location 4E7EH and put it into Register A.
55B6
ADD A,30H
LET Register A = Register A + 30H. Note: Adding 30H to from Register A will convert decimal number 0-9 into its ASCII equivalent (i.e., 6 + 30H = 36H, which, in ASCII, is 6.
55B8
LD (FDS),A
Store the value held in Register A into the memory location 5152H, which is in the “X” in the middle of the message Source Drive x Destination Drive y’.
55BB
LD A,(FDRIVD)
Fetch the destination drive number from memory location 4E7FH and put it into Register A.
55BE
ADD A,30H
LET Register A = Register A + 30H. Note: Adding 30H to from Register A will convert decimal number 0-9 into its ASCII equivalent (i.e., 6 + 30H = 36H, which, in ASCII, is 6.
55C0
LD (FDD),A
Store the value held in Register A into the memory location 516BH, which is in the “y” in the middle of the message Source Drive x Destination Drive y’.
55C3
LD HL,FDSMSG
LET Register Pair HL = 5145H which is the message “Source Drive x Destination Drive y’“.
55C6
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
55C9
JP DOLLAR
   [5518H]
JUMP to 5518H to execute the backup.


55CCH – Get and Validate the Source Drive Number.

“GETSRC”
55CC
LD HL,(CSAVE)
Fetch the pointer to the command line (which is stored at memory location 4E8AH) and put it into Register HL.
55CF
LD A,(HL)
Fetch the value stored at that memory location and put it into Register A.
55D0
CP 3AH
Compare the value held in Register A against 3AH (ASCII: :). Results: If Register A equals :, the Z FLAG is set; otherwise, the NZ FLAG is set.
55D2
INC HL
INCrement the value stored in Register Pair HL by 1 so as to (hopefully) point to the drive number on the command line.
55D3
PUSH HL
Save Register Pair HL (i.e., the pointer to the drive number in the parameter) to the top of the stack.
55D4
JR Z,GETSR2
     [55E0H]
If the Z FLAG (Zero) is set then we have a colon, so JUMP to 55E0H to process the drivespec.
55D6
POP HL
Restore the the pointer to the drive number in the parameter into Register Pair HL, and then remove the entry from the stack.
“GETSR1”
55D7
PUSH HL
Save Register Pair HL (i.e., the pointer to the drive number in the parameter) to the top of the stack.
55D8
LD HL,SDRV
LET Register Pair HL = 5049H to point to the message “SOURCE Drive Number? “.
55DB
LD B,01H
LET Register B = 01H as B must be the maximum length of line to be accepted when the ROM Call to 0040H is executed as part of the following CALLed routine.
55DD
CALL INPUT
     [5645H]
GOSUB to 5645H to display the message pointed to by Register Pair HL and fetch Register B characters from the user.
“GETSR2”
55E0
LD A,(HL)
Fetch the answer the user gave to that prompt and put it into Register A.
55E1
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
55E2
SUB 30H
SUBtract the value 30H from Register A. Note: Subtracting 30H from from Register A will convert an ASCII number ‘0’-‘9’ to its decimal equivalent (i.e., 6 in ASCII is 36H in Hex; so 36H-30H = 6).
55E4
JR C,GETSR1
     [55D7H]
If the C FLAG (Carry) is set then the user provided a value less than “0”, so JUMP to 55D7H to prompt again.
55E6
LD C,A
LET Register C = the source drive number (held in Register A).
55E7
LD A,(MAXDRV)
Fetch the value stored at memory location 4413H and put it into Register A.
NOTE: 4413H is the storage location for the NUMBER OF DISK DRIVES in the system.
55EA
CP C
Compare the value held in Register A against the value held in Register C. Results:
  • If Register A equals the NUMBER OF DISK DRIVES IN THE SYSTEM, the Z FLAG is set.
  • If A < NUMBER OF DISK DRIVES IN THE SYSTEM, the CARRY FLAG will be set.
  • if A >= NUMBER OF DISK DRIVES IN THE SYSTEM, the NO CARRY FLAG will be set.
55EB
JR C,GETSR1
     [55D7H]
If A < NUMBER OF DISK DRIVES IN THE SYSTEM then the C FLAG (Carry) is set; JUMP to 55D7H.
55ED
LD A,C
LET Register A = the source drive number (held in Register C).
55EE
LD (FDRIVS),A
Store the value held in Register A into the memory location 4E7EH, which holds the source drive number.
55F1
55F2
INC HL
INC HL
INCrement the value stored in Register Pair HL by 2 so as to skip past the ASCII drive number on the parameter line.
55F3
RET
RETurn to the caller.


55F4H – Get and Validate the Destination Drive Number.

“GETDES”
55F4
LD A,(HL)
Fetch the character on the command line stored at the memory location pointed to by Register Pair HL into Register A.
55F5
CP 3AH
Compare the value held in Register A against 3AH (ASCII: :). Results: If Register A equals :, the Z FLAG is set; otherwise, the NZ FLAG is set.
55F7
INC HL
INCrement the value stored in Register Pair HL by 1 so as to (hopefully) point to the drive number.
55F8
JR Z,GETDE2
     [5602H]
If the Z FLAG (Zero) is set then we have a colon, so JUMP to 5602H to process the drivespec.
“GETDE1”
55FA
LD HL,DDRV
LET Register Pair HL = 505FH to point to the message “DESTINATION Drive Number? “.
55FD
LD B,01H
LET Register B = 01H as B must be the maximum length of line to be accepted when the ROM Call to 0040H is executed as part of the following CALLed routine.
55FF
CALL INPUT
     [5645H]
GOSUB to 5645H to display the message pointed to by Register Pair HL and fetch Register B characters from the user.
“GETDE2”
5602
LD A,(HL)
Fetch the answer the user gave to that prompt and put it into Register A.
5603
SUB 30H
SUBtract the value 30H from Register A. Note: Subtracting 30H from from Register A will convert an ASCII number ‘0’-‘9’ to its decimal equivalent (i.e., 6 in ASCII is 36H in Hex; so 36H-30H = 6).
5605
JR C,GETDE1
     [55FAH]
If the C FLAG (Carry) is set then the user provided a value less than “0”, so JUMP to 55FAH to prompt again.
5607
LD C,A
LET Register C = the source drive number (held in Register A).
5608
LD A,(MAXDRV)
Fetch the value stored at memory location 4413H and put it into Register A.
NOTE: 4413H is the storage location for the NUMBER OF DISK DRIVES in the system.
560B
CP C
Compare the value held in Register A against the value held in Register C. Results:
  • If Register A equals the NUMBER OF DISK DRIVES IN THE SYSTEM, the Z FLAG is set.
  • If A < NUMBER OF DISK DRIVES IN THE SYSTEM, the CARRY FLAG will be set.
  • if A >= NUMBER OF DISK DRIVES IN THE SYSTEM, the NO CARRY FLAG will be set.
560C
JR C,GETDE1
     [55FAH]
If A < NUMBER OF DISK DRIVES IN THE SYSTEM then the C FLAG (Carry) is set; JUMP to 55FAH.
“GETDE3”
560E
LD A,C
LET Register A = the destination drive number (held in Register C).
560F
LD (FDRIVD),A
Store the value held in Register A into the memory location 4E7FH, which holds the destination drive number.
5612
CALL SITIT
     [45E9H]
GOSUB to 45E9H.
NOTE: 45E9H is the routine to calculate the DRIVE SELECT CODE to be used.
5615
OR 80H
OR Register A against 80H (1000 0000). This has the effect of turning on bit 7 so as to enable DOUBLE DENSITY.
5617
LD (FDRIVE),A
Store the drive select code (held in Register A) into the memory location 4E7DH.
561A
LD A,(FDRIVS)
Fetch the source drive number from memory location 4E7EH and put it into Register A.
561D
LD B,A
LET Register B = the source drive number.
561E
LD A,(FDRIVD)
Fetch the destination drive number from memory location 4E7FH and put it into Register A.
5621
SUB B
Test to see if the SOURCE and DESTINATION drives are the same by subtracting Register B from Register A. The check is done this way because a “0” placed in 4E87H means “same drive number”.
5622
LD (SINGLE),A
Store the value held in Register A into the memory location 4E87H (which holds the flag for whether the source and destination are the same drive).
5625
RET
RETurn to the caller.


5626H – Get the Number of the Drive for the FORMAT.

“GETFOR”
5626
LD HL,(CSAVE)
Fetch the pointer to the command line (which is stored at memory location 4E8AH) and put it into Register HL.
5629
LD A,(HL)
Fetch the character on the command line (pointed to by Register Pair HL) and put it into Register A.
562A
INC HL
INCrement the value stored in Register Pair HL by 1 so as to (hopefully) point to a drive spec.
562B
CP 3AH
Compare the value held in Register A against 3AH (ASCII: :). Results: If Register A equals :, the Z FLAG is set; otherwise the NZ FLAG is set.
562D
JR Z,GETFO2
     [5637H]
If the character on the parameter line is a :, then we were likely given a drive number on the parameter line and the Z FLAG (Zero) is set; JUMP to 5637H.
“GETFO1”
562F
LD HL,FDRV
LET Register Pair HL = 4FB1H to point to the message “FORMAT WHICH DRIVE? “.
5632
LD B,01H
LET Register B = 01H as B must be the maximum length of line to be accepted when the ROM Call to 0040H is executed as part of the following CALLed routine.
5634
CALL INPUT
     [5645H]
GOSUB to 5645H to display the message pointed to by Register Pair HL and fetch Register B characters from the user.
“GETFO2”
5637
LD A,(HL)
Fetch the answer the user gave to that prompt and put it into Register A.
5638
SUB 30H
SUBtract the value 30H from Register A. Note: Subtracting 30H from from Register A will convert an ASCII number ‘0’-‘9’ to its decimal equivalent (i.e., 6 in ASCII is 36H in Hex; so 36H-30H = 6).
563A
JR C,GETFO1
     [562FH]
If the C FLAG (Carry) is set then the user provided a value less than “0”, so JUMP to 562FH to prompt again.
563C
LD C,A
LET Register C = the drive number (held in Register A).
563D
LD A,(MAXDRV)
Fetch the value stored at memory location 4413H and put it into Register A.
NOTE: 4413H is the storage location for the NUMBER OF DISK DRIVES in the system.
5640
CP C
Compare the value held in Register A against the value held in Register C. Results:
  • If Register A equals the NUMBER OF DISK DRIVES IN THE SYSTEM, the Z FLAG is set.
  • If A < NUMBER OF DISK DRIVES IN THE SYSTEM, the CARRY FLAG will be set.
  • if A >= NUMBER OF DISK DRIVES IN THE SYSTEM, the NO CARRY FLAG will be set.
5641
JR C,GETFO1
     [562FH]
If A < NUMBER OF DISK DRIVES IN THE SYSTEM then the C FLAG (Carry) is set; JUMP to 562FH.
5643
JR GETDE3
   [560EH]
JUMP to 560EH to save the drive number and continue.


5645H – Prompt the user with a message and fetch B characters from the user. On entry, HL points to the text to display and B holds the maximum character count to accept.

“INPUT”
5645
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
5648
LD HL,NAMBUF
LET Register Pair HL = 4EA1H, which is the keyboard buffer.
564B
CALL KEYN
     [0040H]
GOSUB to 0040H.
NOTE: 0040H is the Model III ROM routine to get a full line from the keyboard. In this routine, a line is terminated by a carriage return or BREAK, and characters typed are echoed to the display. On entry, B must be the maximum length of line to be accepted and (HL) must be the storage buffer which should be set to B+1. On Exit, CARRY will be set if the BREAK key was hit, Register B will contain the number of characters entered, and (HL) will contain the line from the keyboard followed by the terminating character. Register paid DE is altered in this routine.
564E
JP C,ABORT
     [4030H]
If the C FLAG (Carry) is set that means we got a BREAK; JUMP to 4030H.
NOTE: 4030H is the OPERATION ABORTED routine. Routine runs, displays an error, and returns to the DOS PROMPT.
5651
RET
RETurn to the caller.


5652H – Prepare to display the prompt for the MASTER PASSWORD.

“GETPSF”
5652
LD HL,PASMES
LET Register Pair HL = 5001H to point to the message “Master Password? ‘ + 03H“.
5655
JR GETPAS
   [565AH]
JUMP to 565AH to get the password and continue.


5657H – Prompt the user for the master password for the source diskette.

“GETPSB”
5657
LD HL,SPASS
LET Register Pair HL = 5013H to point to the message “Master Password?“.
“GETPAS”
565A
LD B,08H
LET Register B = 08H (8 characters to fetch) as B must be the maximum length of line to be accepted when the ROM Call to 0040H is executed as part of the following CALLed routine.
565C
CALL INPUT
     [5645H]
GOSUB to 5645H to display the message pointed to by Register Pair HL and fetch Register B characters from the user.
565F
CALL TRAP
     [57C3H]
GOSUB to 57C3H to hash the password which the user provided.
5662
LD (PTRAP),HL
Store the hashed user provided password (held in Register HL) into the memory location 4E88H.
5665
RET
RETurn to the caller.


5666H – Get the NAME for the DISKETTE to FORMAT and put it in 4E98H-4EA0H.

“GETNAM”
5666
LD HL,NAMMES
LET Register Pair HL = 4FF1H to point to the message “Diskette Name?“.
5669
LD B,08H
LET Register B = 08H (8 characters to fetch) as B must be the maximum length of line to be accepted when the ROM Call to 0040H is executed as part of the following CALLed routine.
566B
CALL INPUT
     [5645H]
GOSUB to 5645H to display the message pointed to by Register Pair HL and fetch Register B characters from the user.
566E
LD A,08H
LET Register A = 08H to test for the number of characters we actually got.
5670
SUB B
LET Register A = Register A – Register B to test for the number of characters we actually got.
5671
JR Z,GETNA2
     [5683H]
If we got 8 characters then the Z FLAG (Zero) is set; JUMP to 5683H since we don’t need any filler.
5673
CP 08H
Compare the value held in Register A against 08H. Results: If Register A equals 08H, the Z FLAG is set; otherwise the NZ FLAG is set.
5675
JR Z,GETNAM
     [5666H]
If we weren’t given ANY filename, then the Z FLAG (Zero) is set, JUMP to the top of this routine (5666H) and retry.
5677
PUSH HL
Save the buffer address pointed to by Register Pair HL to the top of the stack.
5678
LD E,A
LET Register E = the number of spaces needed (held in Register A as a result of the subtraction).
5679
LD A,B
LET Register A = the length of the diskette name (held in Register B).
567A
ADD A,L
LET Register A = Register A + Register L to position Register A to the end of the characters which were provided.
567B
LD L,A
LET Register L = Register A so that Register Pair HL now points to the end of the characters which were provided.
567C
LD B,E
In preparation for a DJNZ loop to fill the missing characters, LET Register B = the number of spaces needed (held in Register E).
“GETNA1”
567D
LD (HL),20H
Store a SPACE into the buffer pointing to the end of the given name (pointed to by Register Pair HL).
567F
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the next character in the name buffer.
5680
DJNZ GETNA1
     [567DH]
LOOP back to 567DH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
5682
POP HL
Put the buffer address held at the top of the STACK (which is the beggining of the disk name) into Register Pair HL, and then remove the entry from the stack.
“GETNA2”
5683
LD DE,NAMEBF
LET Register Pair DE = 4E98H which is the memory location where the diskette name is stored.
5686
LD BC,0008H
LET Register Pair BC = 0008H for a LDIR of 8 bytes to move.
5689
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
568B
RET
RETurn to the caller.


568CH – Generate the Date in ASCII from the SYSTEM CALENDAR.

“GETDAT”
568C
LD HL,DATBUF
LET Register Pair HL = 4E90H, which is where the date is stored.
568F
CALL DATE
     [3033H]
GOSUB to 3033H to Get the Date from the ROM in ASCII.
5692
RET
RETurn to the caller.


5693H – Generate a Formatted Diskette’s GAT TABLE (meaning identify the BOOT and DIRECTORY tracks aas allocated).

“CLRGAT”
5693
LD HL,SGAT
First we need to clear the buffer which will hold the GAT SECTOR. LET Register Pair HL = 6000H, which is the start of the GAT SECTOR BUFFER and associated workspace.
5696
LD DE,SGAT + 1
LET Register Pair DE = 6001H, which is one byte beyond Register Pair HL.
5699
LD BC,(SECTOR*2)-1
LET Register Pair BC = 01FFH (Decimal: 511) to move 512 bytes.
569C
LD (HL),00H
Store a 00H into the memory location pointed to by Register Pair HL.
569E
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
56A0
LD A,01H
LET Register A = 01H, which, when placed as the first byte in the GAT SECTOR, means that the bootstrap gran is allocated.
56A2
LD (FGAT),A
Store the value held in Register A into the memory location 6100H, to indicate that the bootstrap gran is allocated.
56A5
LD A,3FH
LET Register A = 3FH, which, when placed 17 bytes into the GAT SECTOR, means that the directory track (track 17) is allocated.
56A7
LD (FGAT+17),A
Store the value held in Register A into the memory location 6111H.
56AA
RET
RETurn to the caller.


56ABH – Set the flag to prompt for the SYSTEM DISKETTE once the current operation is completed.

“SETDAT”
56AB
LD A,0FFH
LET Register A = FFH.
56AD
LD (DATDSK),A
Store the FFH into the memory location 550AH to indicate that this ia a data disk.
56B0
RET
RETurn to the caller.


56B1H – Analyze the Destination Diskette for a Prior Format.

“CHKFOR”
56B1
LD HL,ANALYZ
LET Register Pair HL = 4EE2H to point to the message “Analyzing Diskette“.
56B4
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
56B7
LD A,(FDRIVD)
Fetch the destination drive number from memory location 4E7FH and put it into Register A.
56BA
LD C,A
LET Register C = the destination drive number as the CALL to 4C6BH will require the drive number to be in Register C.
56BB
PUSH BC
Save Register Pair BC (i.e., the destination drive number) to the top of the stack.
56BC
CALL CHKDRV
     [4C6BH]
GOSUB to 4C6BH to start and check the disk drive number held in Register C.
56BF
POP BC
Put the destination drive number (held at the top of the STACK) into Register Pair BC, and then remove the entry from the stack.
56C0
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, JUMP to 4E00H.
56C3
PUSH BC
Save the destination drive number to the top of the stack.
56C4
LD DE,0001H
We are about to test to see if the diskette already has a format. LET Register D = Track 00 and Register E = Sector 01.
56C7
LD HL,0000H
LET Register Pair HL = 0000H to act as a dummy read location.
56CA
CALL XREAD
     [4675H]
GOSUB to 4675H to check the destination diskette for data.
56CD
POP BC
Put the destination drive number (held at the top of the STACK) into Register Pair BC, and then remove the entry from the stack.
56CE
RET NZ
If the NZ FLAG (Not Zero) is set, then the CALL produced an error, so RETurn to the caller.
56CF
PUSH BC
Save Register Pair BC (i.e., the destination drive number) to the top of the stack.
56D0
CALL RDHIT
     [4ABAH]
GOSUB to 4ABAH.
NOTE: 4ABAH is the SYS00/SYS routine to read the HIT sector into RAM.
56D3
POP BC
Put the destination drive number (held at the top of the STACK) into Register Pair BC, and then remove the entry from the stack.
56D4
RET NZ
If the NZ FLAG (Not Zero) is set, then the CALL produced an error, so RETurn to the caller.
56D5
CALL WRHIT
     [4AC2H]
GOSUB to 4AC2H.
NOTE: 4AC2H is the SYS00/SYS routine to write the HIT sector from RAM to diskette.
56D8
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
“CHKFO0”
56DB
LD HL,4300H
LET Register Pair HL = 4300H, which is the beginning of the buffer holding the HIT TABLE in RAM.
56DE
LD B,50H
LET Register B = 50H (Decimal: 80), which is the maximum number of files on a diskette, for a DJNZ loop of 80 iterations to check 80 HIT entries.
56E0
XOR A
Set Register A to ZERO and clear all flags.
“CHKFO1”
56E1
CP (HL)
Compare the value held in Register A against the value held in the memory location (HL) to see if there is a hash code in that location or not. Results: If Register A equals (HL), then there is NO active file present and the Z FLAG is set; otherwise the NZ FLAG is set.
56E2
JR NZ,CHKFO2
      [56E9H]
If there is an active file present, then the NZ FLAG (Not Zero) was set; JUMP to 56E9H.
56E4
INC HL
If we are here then there was no hash code at that location, so INCrement the value stored in Register Pair HL by 1 to point to the next entry.
56E5
DJNZ CHKFO1
     [56E1H]
LOOP back to 56E1H for the entire 80 byte HIT table, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
56E7
JR CHKFO3
   [56FFH]
JUMP to 56FFH to continue.


56E9H – Continuation of the above ANALYZE A DESTINATION DISKETTE routine; jumnped here if there is an active file present. On Exit A is ZERO if we are not reformatting; and anything else if we are.

“CHKFO2”
56E9
LD HL,DDATA
LET Register Pair HL = 4FC6H to point to the message “Diskette contains DATA. Use Disk or not?“.
56EC
LD B,03H
LET Register B = 03H (3 characters to fetch) as B must be the maximum length of line to be accepted when the ROM Call to 0040H is executed as part of the following CALLed routine.
56EE
CALL INPUT
     [5645H]
GOSUB to 5645H to display the message pointed to by Register Pair HL and fetch Register B characters from the user.
56F1
LD A,(HL)
Fetch the response (held at memory location pointed to by Register Pair HL) and put it into Register A.
56F2
CP 4EH
Compare the value held in Register A against 4EH (ASCII: N). Results: If Register A equals N, the Z FLAG is set; otherwise the NZ FLAG is set.
56F4
JP Z,EXIT
     [4E50H]
If the user indicated to NOT use this disk the Z FLAG (Zero) is set, JUMP to 4E50H to exit the FORMATTING routine.
56F7
CP 59H
Compare the value held in Register A against 59H (ASCII: Y). Results: If Register A equals Y, the Z FLAG is set; otherwise the NZ FLAG is set.
56F9
JR Z,CHKFO3
     [56FFH]
If the user indicated to use this disk the Z FLAG (Zero) is set, JUMP to 56FFH to proceed.
56FB
CP 55H
Compare the value held in Register A against 55H (ASCII: U). Results: If Register A equals U, the Z FLAG is set; otherwise the NZ FLAG is set.
56FD
JR NZ,CHKFO2
      [56E9H]
If user didn’t hit a “U” then the NZ FLAG (Not Zero) is set; JUMP back to 56E9H at the top of this routine and try again.
“CHKFO3”
56FF
LD A,(BCKFLG)
If the user hit a “Y” or a “U” to use this diskette despite it having active files, then we are here. Fetch the value stored at memory location 5836H to see if we are doing a BACKUP or a FORMAT and put it into Register A.
5702
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
5703
RET Z
If the Z FLAG (Zero) is set then we were told to use this disk for a BACKUP and it is already formatted, so RETurn to the caller.
5704
LD HL,REFORM
LET Register Pair HL = 511DH to point to the message “Do you wish to RE-FORMAT the diskette?“.
5707
LD B,03H
LET Register B = 03H (3 characters to fetch) as B must be the maximum length of line to be accepted when the ROM Call to 0040H is executed as part of the following CALLed routine.
5709
CALL INPUT
     [5645H]
GOSUB to 5645H to display the message pointed to by Register Pair HL and fetch Register B characters from the user.
570C
LD A,(HL)
Fetch the user response (stored at memory location pointed to by Register Pair HL) and put it into Register A.
570D
CP 59H
Compare the value held in Register A against 59H (ASCII: Y). Results: If Register A equals Y, the Z FLAG is set; otherwise the NZ FLAG is set.
570F
JR Z,CHKFO4
     [5712H]
If the user requested a reformat, then the Z FLAG (Zero) is set; JUMP to 5712H.
5711
XOR A
Set Register A to ZERO and clear all Flags to indicate that we are NOT reformatting.
“CHKFO4”
5712
OR A
Set FLAGS based on the contents of Register A to indicate that we ARE reformatting.
5713
RET
RETurn to the caller.


5714H – Clear the Screen and Display a Program Name. On Entry, HL points to the middle part of the applicable message.

“DOTITL”
5714
PUSH HL
Save the address of the name to be displayed (held in Register Pair HL) to the top of the stack.
5715
CALL CLS
     [01C9H]
GOSUB to 01C9H.
NOTE: 01C9H is the Model III ROM routine to to CLEAR THE SCREEN and RETurn.
5718
LD HL,TITLE1
LET Register Pair HL = 4F76H to point to the first part of the message … “TRSDOS Model III“.
571B
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
571E
POP HL
Put the address of the name to be displayed (held at the top of the STACK) into Restore Register Pair HL, and then remove the entry from the stack.
571F
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
5722
LD HL,TITLE2
LET Register Pair HL = 4F88H to point to the third party of the message … “Ver 1.3“.
5725
JP 021BH
   [021BH]
JUMP to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found. Since this was JUMPED to instead of CALLed, the RET at the end of this ROM routine will then RETurn to the caller of this subroutine instead of returning to this place.


5728H – Common Routine for both BACKUP and FORMAT – Set up the RAM BUFFERS.

“COMON”
5728
LD (CSAVE),HL
Store the current location in the command line (value held in Register HL) into the memory location 4E8AH.
572B
LD HL,(MEMEND)
Fetch the value stored at memory location 4411H and put it into Register HL.
NOTE: 4411H is the storage location for the MEMORY PROTECT address.
572E
LD DE,-(SECTOR*DGRAN)
LET Register Pair DE = 0FD00H, which is NEGATIVE ONE GRAN.
5731
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE to move one gran backwards from the top of memory.
5732
LD (MEMTOP),HL
Store the value held in Register HL into the memory location 4E8EH to designate the new top of memory.
5735
CALL CLRGAT
     [5693H]
GOSUB to 5693H to generate a clean GAT in RAM.
5738
RET
RETurn to the caller.


5739H – “BACKUP” Utility.

“BACKP”
5739
CALL COMON
     [5728H]
GOSUB to 5728H to set up the RAM BUFFERS.
573C
LD HL,BMSG
LET Register Pair HL = 4F93H to point to the message “Backup Utility“.
573F
CALL DOTITL
     [5714H]
GOSUB to 5714H to display the backup utility name.
5742
CALL GETDAT
     [568CH]
GOSUB to 568CH to generate the date text.
5745
CALL GETSRC
     [55CCH]
GOSUB to 55CCH to get the source drive number.
5748
CALL GETDES
     [55F4H]
GOSUB to 55F4H to get the destination drive number.
574B
CALL GETPSB
     [5657H]
GOSUB to 5657H to prompt for the master password.
574E
CALL BPREP
     [5560H]
GOSUB to 5560H to perform the actual backup.
5751
LD A,0DH
LET Register A = 0DH (ASCII: CARRIAGE RETURN).
5753
CALL DSP
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
5756
LD HL,BCOMP
LET Register Pair HL = 4F5CH to point to the message “** Backup Complete **“.
5759
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
575C
CALL CKSYS
     [5509H]
GOSUB to 5509H to prompt for the SYSTEM DISK if needed.
575F
JP EXIT
   [4E50H]
JUMP to 4E50H to exit the BACKUP routine.


5762H – “FORMAT” Utility.

“FRMAT”
5762
CALL COMON
     [5728H]
GOSUB to 5728H to set up the RAM BUFFERS.
5765
LD HL,4FA2H
LET Register Pair HL = 4FA2H to point to the message “Format Utility“.
5768
CALL DOTITL
     [5714H]
GOSUB to 5714H to display the backup utility name.
576B
CALL GETDAT
     [568CH]
GOSUB to 568CH to generate the date text.
576E
CALL GETFOR
     [5626H]
GOSUB to 5626H to get the drive number to format.
5771
CALL GETNAM
     [5666H]
GOSUB to 5666H to get the diskette name.
5774
CALL GETPSF
     [5652H]
GOSUB to 5652H to get the master password.
5777
CALL CHKFOR
     [56B1H]
GOSUB to 56B1H to analyze the diskette.
577A
LD HL,NAMEBF
LET Register Pair HL = 4E98H, which is the pointer to the DISKETTE NAME in RAM.
577D
LD DE,FGAT+DID
LET Register Pair DE = 61D0H, which is the pointer to the DISKETTE NAME in the GAT SECTOR in RAM.
5780
PUSH DE
Save the pointer to the DISKETTE NAME in the GAT SECTOR in RAM to the top of the stack.
5781
LD BC,0008H
LET Register Pair BC = 0008H for a LDIR of 8 bytes to move from HL to DE.
5784
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
5786
LD HL,DATBUF
LET Register Pair HL = 4E90H, which is the pointer to the DISKETTE DATE in RAM.
5789
LD BC,0008H
LET Register Pair BC = 0008H for a LDIR of 8 bytes to move from HL to DE.
578C
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
578E
POP HL
Put the pointer to the DISKETTE NAME in the GAT SECTOR in RAM (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
578F
5790
DEC HL
DEC HL
DECrement the value stored in Register Pair HL by 2 to now point to the master password in the GAT SECTOR in RAM.
5791
LD DE,(PTRAP)
Fetch the hash of the user provided master password (stored at memory location 4E88H) and put it into Register DE.
5795
LD (HL),E
Store the LSB of DE into the memory location pointed to by Register Pair HL.
5796
INC HL
INCrement the value stored in Register Pair HL by 1.
5797
LD (HL),D
Store the MSB of DE into the memory location pointed to by Register Pair HL.
5798
CALL FOMAT
     [5803H]
GOSUB to 5803H to format the diskette.
579B
CALL 5138H
     [5138H]
GOSUB to 5138H to check the drive select code to see if it is an 81H (DRIVE 0 SELECT and DOUBLE-DENSITY), prompt for the SYSTEM DISK if needed, and return here.
579E
JP EXIT
   [4E50H]
JUMP to 4E50H to exit the FORMAT routine.


57A1H – DOS Entry to the FORMAT and BACKUP Utilities.

“BEGIN”
57A1
PUSH HL
Save the Command Line (pointed to by Register Pair HL) to the top of the stack.
57A2
LD HL,OVLFLG
LET Register Pair HL = 442BH to point to the system overlay flags.
57A5
RES 4,(HL)
RESet (i.e., set as 0) BIT 4 of Register (HL) to indicate that SYS6 is NOT resident in RAM.
57A7
POP HL
Restore the pointer to the Command Line from the top of the STACK into Register Pair HL, and then remove the entry from the stack.
57A8
PUSH AF
Save the OVERLAY FUNCTION CODE (held in Register Pair AF) to the top of the stack.
57A9
LD A,55H
LET Register A = 55H to act as a flag to clear RAM.
57AB
LD (CFLAG),A
Store the value held in Register A into the memory location 42B4H.
57AE
LD A,02H
LET Register A = 02H to signify a maximum of two retries.
57B0
LD (TRY1),A
Store the 02 retry value (held in Register A) into the READ FUNCTION RETRY NUMBER held in memory location 467DH.
57B3
LD (TRY2),A
Store the 02 retry value (held in Register A) into the WRITE FUNCTION RETRY NUMBER held in memory location 460AH.
57B6
POP AF
Restore the OVERLAY FUNCTION CODE held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
57B7
AND 0F0H
MASK the OVERLAY FUNCTION CODE against 0F0H (1111 0000). This has the effect of keeping only bits 7, 6, 5, 4, which is where the routine selection code resides.
57B9
CP 0A0H
Compare the value held in Register A against 0A0H (1010 0000) to see if the FORMAT command was requested. Results: If Register A equals 0A0H, the Z FLAG is set; otherwise the NZ FLAG is set.
57BB
JR Z,FRMAT
     [5762H]
If FORMAT was requested the Z FLAG (Zero) will have been set; JUMP to the main FORMAT routine at 5762H.
57BD
CP 90H
Compare the value held in Register A against 90H (1001 0000) to see if the BACKUP command was requested. Results: If Register A equals 090H, the Z FLAG is set; otherwise the NZ FLAG is set.
57BF
JP Z,BACKP
     [5739H]
If BACKUP was requested the Z FLAG (Zero) will have been set; JUMP to the main FORMAT routine at 5739H.
57C2
RET
RETurn to the caller otherwise.


57C3H – Encode a Password.

“TRAP”
57C3
EX DE,HL
EXchange the value stored in Register Pair HL (i.e., the buffer address of the user entered password) with the value stored in Register Pair DE.
57C4
LD H,D
LET Register H = the MSB of the buffer address with the user entered password (held Register D following that EX).
57C5
LD A,B
LET Register A = the number of characters entered (held in Register B).
57C6
ADD A,E
LET Register A = Register A + the LSB of the buffer address with the user entered password (held Register E following that EX).
57C7
LD L,A
LET Register L = Register A the end of the user entered password.
57C8
LD A,08H
LET Register A = 08H, which is the number of characters we need for a full password
57CA
SUB B
LET Register A = the number of characters we need in a password MINUS the number of characters the user entered (Register B).
57CB
JR Z,NOSPC
     [57D3H]
If the user entered 8 characters then the subtraction would leave a 0 and the Z FLAG (Zero) would be set; JUMP to 57D3H.
57CD
LD B,A
LET Register B = the number of characters we need to pad in the user entered password to get to 8 (held in Register A as a result of that subtraction).
“FILSPC”
57CEH
LD (HL),20H
Store a SPACE onto the end of the user entered password (pointed to by Register Pair HL).
57D0
INC HL
INCrement the value stored in Register Pair HL by 1 to point to the next character in the user entered password.
57D1
DJNZ FILSPC
     [57CEH]
LOOP back to 57CEH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.


57D3H – Password Encode. Encode the password stored in the memory location pointed to by Register Pair DE; results in Register Pair HL.

“NOSPC”
57D3
LD HL,0FFFFH
LET Register Pair HL = 0FFFFH (Decimal: -1) as the default.
57D6
LD B,08H
LET Register B = 08H since a password is 8 characters.

The next few instructions skip to the end of the password (pointed to by Register Pair DE) by adding 7 to the LSB (i.e., Register E).

57D8
LD A,E
LET Register A = Register E.
57D9
ADD A,07H
ADD the value 07H to Register A (Results held in Register A).
57DB
LD E,A
LET Register E = Register A.
57DC
If the NC FLAG (No Carry) is set then we did not move to a new memory page (i.e., need to update D as well), so skip over the next instruction which increments D, and JUMP to 57DFH.
57DE
INC D
Bump the value stored in Register D by 1.

At this point, Register Pair DE is now pointing to the END of the password.

“SETTD2”
57DF
LD A,(DE)
Fetch the value stored at memory location pointed to by Register Pair DE (i.e., 1 character of the 8 character password) and put it into Register A.
57E0
PUSH DE
Save Register DE (i.e., the location in the password string where Register A got the character from) to the top of the stack.
57E1
LD D,A
LET Register D = Register A (i.e., the password character pointed to by (DE)).
57E2
LD E,H
LET Register E = Register H (i.e., the MSB of the password).
57E3
LD A,L
LET Register A = Register L (i.e., the LSB of the password).
57E4
AND 07H
MASK the value of Register A against 07H (0000 0111). This has the effect of turning off bits 7, 6, 5, 4, 3, leaving only bits 2, 1, 0 active.
57E6
57E7
57E8
RRCA
RRCA
Move the bottom 3 bits (2, 1, and 0) to the top 3 bits (7, 6, and 5)
57E9
XOR L
eXclusive OR Register L against Register A to merge the masked Register A with the LSB. The results are stored in Register A.
57EA
LD L,A
LET Register L = Register A (i.e., the new LSB).
57EB
LD H,00H
LET Register H = 00H so that the MSB = 0.
57ED
SBC HL,DE
Let PASSWORD = PASSWORD – DE by subtracting the value stored in Register Pair DE and the carry flag from the value stored in Register Pair HL.
57EF
ADD HL,HL
Let PASSWORD = PASSWORD * 2 by adding the value held in Register Pair HL to Register Pair HL. The results are held in Register Pair HL.
57F0
ADD HL,HL
Let PASSWORD = PASSWORD * 4 by doing that again.
57F1
XOR H
eXclusive OR Register H (i.e., the new MSB) against Register A (i.e., the old LSB). The results are stored in Register A.
57F2
XOR D
eXclusive OR Register D (i.e., the character) against Register A (i.e., the old LSB / new MSB combination). The results are stored in Register A.
57F3
LD D,A
LET Register D = Register A (i.e., the mishmash we just did).
57F4
LD A,L
LET Register A = Register L (i.e., the new MSB).
57F5
ADD HL,HL
Let PASSWORD = PASSWORD * 2 by adding the value held in Register Pair HL to Register Pair HL. The results are held in Register Pair HL.
57F6
XOR H
eXclusive OR Register H (i.e., the NEWER MSB) against Register A (i.e., the prior new MSB). The results are stored in Register A.
57F7
XOR E
eXclusive OR Register E (i.e., the old MSB) against Register A. The results are stored in Register A.
57F8
LD E,A
LET Register E = Register A.
57F9
EX DE,HL
EXchange the value stored in Register Pair HL with the value stored in Register Pair DE so that Register Pair HL now contains the newly encoded password.
57FA
POP DE
Restore Register Pair DE (i.e., the location in the pasword string for the character which was just processed) from the top of the STACK.
57FB
DEC DE
DECrement the value stored in Register Pair DE by 1 to point to the previous character in the password string.
57FC
LOOP back to 57DFH until Register B is ZERO (i.e., all 8 characters of the password have been processed, in reverse).
57FE
57FF
LD A,H
OR L
The Z-80 does not have a way to check a register pair against 0 easily. So a common trick is to let Register A equal one part of the Register Pair and then to OR that against the other part of the Register Pair. Only if both parts of the register pair were 0 will A be 0.
5800
RET NZ
If the NZ FLAG (Not Zero) is set, then Register Pair HL (i.e., the password) was not 0, so RETurn to the caller.
5801
INC L
Bump the value stored in Register L by 1 so we don’t have a password of 0.
5802
RET
RETurn to the caller.


5803H – Format a Diskette.

“FOMAT”
5803
XOR A
Set Register A to ZERO so that we can place a “track 0” into (5BD3H).
5804
LD (DDTRK),A
Store the 00H held in Register A into the memory location 5BD3H.
5807
LD A,(FDRIVE)
Fetch the drive select code (stored at memory location 4E7DH) and put it into Register A.
580A
CALL DSEL0
     [44E0H]
GOSUB to 44E0H to select the drive based on the DRIVE SELECT CODE.
580D
LD A,0CH
LET Register A = 0CH (0000 1100), which is the RESTORE TO TRACK 0 command when sent to Port 0F0H.
580F

When this bit pattern in sent to Port F0H (the Floppy Disk Control Port) and bits 7-4 are 0000, this is a RESTORE command and is a Type I command. Bits 0-1 are the stepping rate (00=6ms, 01=12ms, 10=20ms, 11=30ms), Bit 2 is the Track Number Verify Flag (0=No Verify), and Bit 3 is the Head Load Flag (1=Load Head).

When activated, the Track Register is checked, and if its 0 (meaning at Track 0) an interrupt is generated. If it is not 0, stepping pulses are issued until the TR00 goes to 0, and then an interrupt is generated.
5811
CALL SDELAY
     [4404H]
GOSUB to 4404H.
NOTE: 4404H is the routine which has a slight delay.
5814
LD B,05H
LET Register B = 05H for a DJNZ loop for FIVE revolutions.
5816
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
5818
BIT 1,A
Test Bit Number 1 of Register A. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
581A
JR Z,5816H
     [5816H]
If the Z FLAG (Zero) is set then we haven’t found the index mark yet for this iteration so, JUMP to 5816H.
581C
LD A,(FDRIVE)
Fetch the drive select code (stored at memory location 4E7DH) and put it into Register A.
581F
CALL DSEL0
     [44E0H]
GOSUB to 44E0H to select the drive based on the DRIVE SELECT CODE.
5822
DJNZ 5816H
     [5816H]
LOOP back to 5816H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
“L1OOP”
5824
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
5826
BIT 2,A
Test Bit Number 2 of Register A to check for arrival at track 0. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
5828
JR NZ,L2OOP
      [5832H]
If the NZ FLAG (Not Zero) is set then we have arrived at TRACK 0 so we have no need to position there; JUMP to 5832H to continue with the formatting.
582A
LD A,(FDRIVE)
Fetch the drive select code (stored at memory location 4E7DH) and put it into Register A.
582D
CALL DSEL0
     [44E0H]
GOSUB to 44E0H to select the drive based on the DRIVE SELECT CODE.
5830
JR L1OOP
   [5824H]
JUMP to 5824H until we have hit track 0.


5832H – Continuation of FORMAT routine above; jumped here once we hit track 0.

“L2OOP”
5832
CALL FORM
     [5CBDH]
GOSUB to 5CBDH to format the diskette.
5835
LD A,(BCKFLG)
LET Register A = the value placed into 5836H elsewhere in this overlay. This value will be 0FH if we called a BACKUP routine.
5837
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
5838
JR NZ,BCKFL1
      [5840H]
If the NZ FLAG (Not Zero) is set, meaning that we had called for a BACKUP, skip the next few instructions which display messages and JUMP to 5840H.
583A
LD HL,WRTDIR
LET Register Pair HL = 5B6DH to point to the message “0AH + Writing System Information + 0DH.
583D
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
“BCKFL1”
5840
LD A,0CH
LET Register A = 0CH (0000 1100), which is the RESTORE TO TRACK 0 command when sent to Port 0F0H.
5842

When this bit pattern in sent to Port F0H (the Floppy Disk Control Port) and bits 7-4 are 0000, this is a RESTORE command and is a Type I command. Bits 0-1 are the stepping rate (00=6ms, 01=12ms, 10=20ms, 11=30ms), Bit 2 is the Track Number Verify Flag (0=No Verify), and Bit 3 is the Head Load Flag (1=Load Head).

When activated, the Track Register is checked, and if its 0 (meaning at Track 0) an interrupt is generated. If it is not 0, stepping pulses are issued until the TR00 goes to 0, and then an interrupt is generated.
5844
CALL SDELAY
     [4404H]
GOSUB to 4404H.
NOTE: 4404H is the routine which has a slight delay.
“L3OOP”
5847
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
5849
BIT 2,A
Set Bit Number 2 of Register A to check for arrival at track 0. Z FLAG will be set if that bit is 0, and NZ FLAG will be set if that bit is 1.
584B
JP Z,L3OOP
     [5847H]
If the Z FLAG (Zero) is set then we have not yet arrived at track 0; JUMP to 5847H.
584E
CALL BOTWRI
     [5A53H]
GOSUB to 5A53H to write the Boot / System Information onto the Diskette.
5851
EI
Enable Interrupts.
5852
RET
RETurn to the caller.


4300H – EXACT COPY OF BOOT/SYS … This is what gets dumped onto a disk. The JUMP values do not match the instruction addresses because it will be Relocated

“ENT”
5853
CP 11H
Compare the value held in Register A against 11H (=17). This is the byte which instructs DOS where the directory track is.
“TRYAGN”
5855
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).
5857
OUTput the value held in Register A to port F0H (the Floppy Disk Command/Status Register).
5859
LD HL,0002H
LET Register Pair HL = 0002H, which will mean TRACK 00H, SECTOR 02H.
585C
LD (TRKSAV),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.
585F
XOR A
Set Register A to ZERO and clear all Flags.
5860
LD (EOFBYT),A
Store the value held in Register A (which is now a 0) into the memory location 43ECH.
NOTE: 43ECH is where the EOF BYTE is stored.
“BOTLOP”
5863
GOSUB to 433EH (the READ A BYTE FROM DISKETTE routine).
5866
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.
5868
If the Z FLAG (Zero) is set then we have a DATA BLOCK so JUMP to 4323H to deal with a data block.
586A
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.
586C
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 5855H.
586E
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.
5871
GOSUB to 4335H (the GET AN ADDRESS FROM DISKETTE routine). Note that the routine exits with the address in Register Pair HL.
5874
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.

“CNT1”
5875
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.

“BOTLO1”
5876
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).
5879
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.
587B
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.
587C
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.



587FH – Start of LOOP to read “B” bytes from the diskette and put them into a buffer starting at HL.

“BOTLO2”
587F
Get a byte from diskette by GOSUBing to 433EH (the READ A BYTE FROM DISKETTE routine).
5882
LD (HL),A
Store the byte which was read from diskette into the memory location pointed to by Register Pair HL.
5883
INC HL
Bump Register Pair HL by 1.
5884
DJNZ BOTLO2
LOOP back to 432CH, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.
5886
JUMP to 5863H.


4335H – Get an address from diskette. Basically, this just reads 2 bytes into Register Pair HL; LSB into L and MSB into H.

“GETADD”
5888
GOSUB to 433EH (the READ A BYTE FROM DISKETTE routine).
588B
LD L,A
LET the LSB of Register Pair HL = Register A.
588C
GOSUB to 433EH (the READ A BYTE FROM DISKETTE routine).
588F
LD H,A
LET the MSB of Register Pair HL = Register A.
5890
RET
RETurn to the caller.


433EH – Read a Byte from Diskette

“GETBYT”
5891
PUSH BC
PUSH Register BC to the top of the stack.
5892
PUSH HL
PUSH Register HL to the top of the stack.
5893
LD A,(EOFBYT)
Fetch the value stored at memory location 43ECH and put it into Register A.
NOTE: 43ECH is where the BYTE NUMBER is stored.
5896
OR A
Set FLAGS based on the contents of Register A.
5897
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.

5899
LD B,09H
LET Register B = 09H.


589BH is the start of a loop of 9 tries to get a good sector read.

“GETBY1”
589B
PUSH BC
Save the count by PUSHing Register BC to the top of the stack.
589C
GOSUB to 437FH to read a sector from diskette.
589F
POP BC
RESTORE Register Pair BC from the top of the STACK.
58A0
AND 1DH
MASK the value of Register A against 1DH (0001 1101) to see if we have an error.
58A2
If the Z FLAG (Zero) is set then we have no error so JUMP to 4364H.

… uh oh, we have an error!

58A4
LD A,CTERM
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).
58A6
OUTput the value held in Register A to port F0H (the Floppy Disk Command/Status Register).
58A8
DJNZ GETBY1
LOOP back to 4348H, reducing Register B each time, and continue to LOOP until Register B has been reduced to ZERO, in which case, continue with the next instruction.

At this point we failed 9 times, so its time to error out.

58AA
LD A,17H
LET Register A = 17H (ASCII: DOUBLE SIZED character code).
58AC
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.
58AF
LD HL,DSKERR
LET Register Pair HL = 43EDH to point to the ERROR message.
58B2
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H or 0DH is found.
“GETBAD”
58B5
Keep executing this JUMP forever.


4364H – Jumped to by 434FH if we weren’t originally at the sector we wanted, but we are now.

“GETOK”
58B7
LD HL,(TRKSAV)
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.
58BA
INC L
Bump Register L by 1 so as to point to the next sector.
58BB
LD A,L
LET Register A = Register L for testing.
58BC
CP TRACK+1
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.
58BE
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).

58C0
LD L,01H
LET Register L = 01H to set the sector at 1.
58C2
INC H
Bump Register H by 1 to point to the next track.
“GETOK0”
58C3
LD (TRKSAV),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.
58C6
XOR A
Set Register A to ZERO and clear all Flags.
“GETOK1”
58C7
LD L,A
We need to set HL to point to 4D00H, so first LET Register L = Register A (which is 00H).
58C8
LD H,BUFF2.HIGH.
LET Register H = 4DH.
58CA
INC A
Bump Register A by 1 to point to the next sector.
58CB
LD (EOFBYT),A
Store the value held in Register A into the memory location 43ECH.
NOTE: 43ECH is where the BYTE NUMBER is stored.
58CE
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
58CF
POP HL
RESTORE Register Pair HL from the value held at the stop of the STACK.
58D0
POP BC
RESTORE Register Pair BC from the value held at the stop of the STACK.
58D1
RET
RETurn to the caller.


437FH – Read a Sector from Diskette

“BOTRED”
58D
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.
58D5
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.
58D8
LD A,81H
LET Register A = 81H (1000 0001) to send DRIVE 0 SELECT and DOUBLE-DENSITY to the FLOPPY DISK CONTROLLER.
58DA
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)
58DC
LD D,A
Save the DRIVE SELECT code (held in Register A) into Register D.
58DD
LD HL,BOTINT
LET Register Pair HL = 43B7H to set the interrupt vector to jump to 43B7H once triggered.
58E0
LD (DOS+1),HL
Store the value held in Register HL into the memory location 404AH.
NOTE: 4049H is a NMI Vector.
58E3
LD A,C3H
LET Register A = C3H which is a JP instruction.
58E5
LD (DOS),A
Store the “JP instruction into the memory location 4049H.
NOTE: 4049H is the RST 0 NMI Vector.
58E8
DI
Disable Maskable Interrupts.
58E9
LD A,C0H
LET Register A = C0H (1100 0000) to enable the DRQ and INTRQ interrupts.
58EB
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.
58ED
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.
58EF
LD HL,BUFF2
LET Register Pair HL = 4D00H to point to a buffer in memory starting at 4D00H.
58F2
LD A,84H
LET Register A = 84H (1000 0100).
58F4
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.
58F6
GOSUB to 43E0H to do some PUSHes and POPs and NOPs to cause a span delay.
“FSTDRQ”
58F9
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
58FB
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.
58FC
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.

58FE
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.
5900
LD A,D
Put the DRIVE SELECT CODE of 81H (which was moved to Register D in 4389H) back into Register A.
5901
OR 40H
OR Register A against 40H (0100 0000) to turn on Bit 6 (which is the WAIT SYNC request). This will turn 1000 0001 into 1100 0001.
“RDLOOP”
5903
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)
5905
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.
5907
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.

“BOTINT”
590A
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.
590B
XOR A
Set Register A to ZERO and clear all Flags.
590C
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.
590E
LD A,DOUBLE+1
LET Register A = 81H (1000 0001) to reselect the drive.
5910
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)
5912
GOSUB to 43E6H (a VERY short delay routine; basically a PUSH, a POP, a NOP, and a RET.
5915
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
5917
RET
RETurn to the caller.

43C5H – Routine to position the read head based on the contents of HL (H=Track, L=Sector)

“XSEEK”
5918
LD A,81H
LET Register A = 81H (1000 0001) to select the drive.
591A
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)
591C
LD HL,(TRKSAV)
Fetch the track and sector from 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.
591F
LD A,H
LET Register A = the TRACK NUMBER we want.
5920
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.
5922
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.
5924
OUTput the value held in Register A to port F0H (the Floppy Disk Command/Status Register).
5926
GOSUB to 43E6H (a VERY short delay routine; basically a PUSH, a POP, a NOP, and a RET.
“XSEEK1”
5929
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
592B
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).
592D
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.
592F
LD A,L
LET Register A = the SECTOR NUMBER we want.
5930
OUTput the value held in Register A to Port F2H.
NOTE: Port F2H is the Floppy Disk Controller SECTOR Register.
5932
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.

“DELY”
5933
PUSH AF
Save Register Pair AF to the top of the stack.
5934
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
5935
PUSH AF
Save Register Pair AF to the top of the stack.
5936
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
5937
PUSH AF
Save Register Pair AF to the top of the stack.
5938
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
“STILL”
5939
PUSH AF
Save Register Pair AF to the top of the stack.
593A
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
593B
NOP
No Operation (Do Nothing).
593C
RET
RETurn to the caller.

593DH – MESSAGE and BYTE STORAGE AREA.

“TRKSAV”
593D
DEFW 02H 00H
 
“EOFBYT”
593F
DEFB 00H
 
“DSKERR”
5940
DEFB 17H
 
5941
DEFM …
ERROR + 0DH”.
“S1SER”
5947
DEFB 256-$+ENT-3%0
 
“S1SIDE”
5950
DEFB 00H
 
“TYPES”
5951
DEFB 13H
TRSDOS v1.3
“TRACKS”
5952
DEFB 28H
= 40 Tracks
“SEC3”
5953
DEFB 01
 
“LEFT”
5954
DEFB RIGHT
This is 21
5955
DEFW NOSYS
This is 00 4D

5957H – Display NOT A SYSTEM DISK and Freeze the System.

“NOSYS”
5957
LD A,17H
LET Register A = 17H (ASCII: Double-Sized Characters).
5959
CALL DSP
     [0033H]
GOSUB to 0033H.
NOTE: 0033H is the Model III ROM character print routine; displays the character held in Register A at the current cursor position.
595C
LD HL,SYSTMG
LET Register Pair HL = 4D0DH to point to the message “NOT A SYSTEM DISK“.
595F
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
“NOSYS1”
5962
JR NOSYS1
   [5962H]
Infinite JUMP to this Location.

5964H – MESSAGE and BYTE STORAGE AREA.

“SYSTMG”
5964
DEFM …
NOT A SYSTEM DISK” + 0DH
5976
DEFB 02 02 00 4D
Execute at 4D00H
597A
DEFB E5H x 217
217 E5’s to fill the rest of a sector.

5A53H – Write the Bootstrap, System, and Directory to Diskette.

“BOTWRI”
5A53
LD DE,0001H
LET Register Pair DE = 0001H, which is the bootstrap sector location (Track 00, Sector 01).
5A56
LD HL,BOOT
LET Register Pair HL = 5853H, which is a pointer to the bootstrap image.
5A59
LD A,(FDRIVD)
Fetch the destination drive number from memory location 4E7FH and put it into Register A.
5A5C
LD C,A
LET Register C = the destination drive number.
5A5D
CALL XWRITE
     [45F7H]
GOSUB to 45F7H to write the bootstrap to diskette.
5A60
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
5A63
INC E
INCrement the value stored in Register E by 1 so as to point to Sector 02.
5A64
LD HL,SYST
LET Register Pair HL = 5953H, which is a pointer to a fake system image for disks with NO SYStem to write to diskette.
5A67
CALL XWRITE
     [45F7H]
GOSUB to 45F7H to write the fake system image to diskette.
5A6A
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
5A6D
LD DE,1101H
LET Register Pair DE = 1101H, meaning Register D will hold 11H (Track 17), and Register E will hold 01H (Sector 1).
5A70
LD HL,FGAT
LET Register Pair DE = 6100H as the destination for a transfer of the GAT SECTOR’s RAM Buffer.
5A73
LD A,(FDRIVD)
Fetch the destination drive number from memory location 4E7FH and put it into Register A.
5A76
LD C,A
LET Register C = the destination drive number.
5A77
CALL XWRITE
     [45F7H]
GOSUB to 45F7H to write the GAT SECTOR to diskette.
5A7A
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
“BOTWR1”
5A7D
INC E
INCrement the value stored in Register E by 1 so as to point to the next sector.
5A7E
LD A,E
LET Register A = the current sector number.
5A7F
CP TRACK+1
Compare the value held in Register A against 13H (Decimal: 19) to see if we are done with the directory track. Results:
  • If Register A equals 13H, the Z FLAG is set.
  • If A < sector 19, the CARRY FLAG will be set.
  • if A >= sector 19, the NO CARRY FLAG will be set.
5A81
RET NC
If we have advanced Register E to sector 19 (which is one too many), the the NC FLAG (No Carry) is set; RETurn to the caller.
5A82
LD HL,DUM1
LET Register Pair HL = 5F00H to point to a dummy directory sector image.
5A85
CALL XWRITE
     [45F7H]
GOSUB to 45F7H to write the SECTOR DATA to diskette.
5A88
JP NZ,FATAL
      [4E00H]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E00H.
5A8B
LD A,E
LET Register A = the current sector number (held in Register E).
5A8C
CP 02H
Compare the value held in Register A against 02H, which would be the HIT Table. Results: If Register A 02H, the Z FLAG is set; otherwise the NZ FLAG is set.
5A8E
JR NZ,BOTWR1
      [5A7DH]
If the NZ FLAG (Not Zero) is set, then we have not yet found the HIT sector; so JUMP to 5A7DH.
5A90
PUSH BC
Save Register Pair BC to the top of the stack.
5A91
PUSH DE
Save Register Pair DE to the top of the stack.
5A92
PUSH HL
Save Register Pair HL to the top of the stack.
5A93
LD HL,DUM1+224
LET Register Pair HL = 5FE0H, to prepare to zero out the SYSTEM EXTENTS area to default values.
5A96
LD DE,DUM1+225
LET Register Pair DE = HL + 1.
5A99
LD BC,000FH
LET Register Pair BC = 000FH (Decimal: 15) for a LDIR count of 15 bytes.
5A9C
LD (HL),00H
Store a 00H into the memory location pointed to by Register Pair HL.
5A9E
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
5AA0
LD HL,COPY
LET Register Pair HL = 5BF1H to point to the message “(C) 1980 TANDY“.
5AA3
LD DE,DUM1+240
LET Register Pair DE = 5FF0H to point to the applicable notice area in the sector image.
5AA6
LD BC,0010H
LET Register Pair BC = 0010H (Decimal: 16) for the number of bytes to copy.
5AA9
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
5AAB
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5AAC
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5AAD
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5AAE
JR BOTWR1
   [5A7DH]
LOOP back to 5A7DH to move to the next sector.

5AB0H – Write a Track of Data.

“TRKWRT”
5AB0
LD BC,00F3H
LET Register Pair BC = 00F3H, which sets Register C to be the FDC Data Port of F3H.
5AB3
LD A,(FDRIVE)
Fetch the drive select code (stored at memory location 4E7DH) and put it into Register A.
5AB6
CALL DSEL0
     [44E0H]
GOSUB to 44E0H to select the drive.
5AB9
OR 40H
OR Register A against 40H (0100 0000) to turn on bit 6, which is the WAIT SYNC bit.
5ABB
LD D,A
LET Register D = the masked drive select code (held in Register A).
5ABC
LD A,(DDSID)
Fetch the SIDE of the diskette we want to format (stored at memory location 5BD6H) and put it into Register A.
5ABF
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
5AC0
JR Z,TRKWR1
     [5AC6H]
If the Z FLAG (Zero) is set, then we are formatting side 0, so JUMP to 5AC6H.
5AC2
LD A,10H
If we are here, then we are formatting side 1. LET Register A = 10H (0001 0000) to act as a mask to signify that we are writing to side 1.
5AC4
OR D
OR Register D against Register A to set that bit. The results are stored in Register A.
5AC5
LD D,A
LET Register D = the masked drive select code (held in Register A).
“TRKWR1”
5AC6
CALL BOTNMI
     [459CH]
GOSUB to 459CH to set up interrupts.
5AC9
LD A,0C0H
LET Register A = 0C0H (1100 0000). When applied to port C0H it enables DRQ Interrupt and enables INTRQ Interrupt.
5ACB
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.
5ACD
LD E,02H
LET Register E = 02H (0000 0010) to be a “data request” mask when applied to port 0F0H
5ACF
LD A,0F0H
LET Register A = 0F0H (1111 0000) which is a track write command.
5AD1
When this bit pattern in sent to Port F0H (the Floppy Disk Control Port) and bits 7-4 are 1111, this is a WRITE TRACK command.
5AD3
CALL DELLY
     [4400H]
GOSUB to 4400H for a short delay which is needed between issuing a command to the FDC and polling it.
“IMDRQ1”
5AD6
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
5AD8
AND E
MASK the value of Register A (which we just got from the FDC) against 0000 0010 (held in Register E) to keep only bit 1 to see if it was a data request.
5AD9
JP Z,IMDRQ1
     [5AD6H]
If the Z FLAG (Zero) is set then the FDC is not yet ready for data so JUMP to 5AD6H.
5ADC
OUTI
Write a byte from the memory location pointed to by HL to port C. Register B is DECremented and Register Pair HL is INCremented.
“IMDRQ2”
5ADE
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
5AE0
AND E
MASK the value of Register A against 0000 0010 (held in Register E) to check for a data request.
5AE1
JP Z,IMDRQ2
     [5ADEH]
If the Z FLAG (Zero) is set then the FDC is not yet ready for data so JUMP to 5ADEH.
5AE4
OUTI
Write a byte from the memory location pointed to by HL to port C. Register B is DECremented and Register Pair HL is INCremented.
5AE6
LD A,D
LET Register A = the drive select code (with the WAIT BIT turned on).
“WRLP”
5AE7
OUTput the value held in Register A 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)
5AE9
OUTI
Write a byte from the memory location pointed to by HL to port C. Register B is DECremented and Register Pair HL is INCremented.
5AEB
JP 5AE7H
   [5AE7H]
JUMP to 5AE7H and keep jumping until an Interrupt is triggered.

5AEEH – Verify One Track.

“VERFIT”
5AEE
LD D,12H
LET Register D = 12H (Decimal: 18) to signify that we want to verify 18 sectors.
5AF0
LD A,(FDRIVE)
Fetch the disk select code (stored at memory location 4E7DH) and put it into Register A.
5AF3
CALL DSEL0
     [44E0H]
GOSUB to 44E0H to select the disk drive.
“VER1”
5AF6
LD A,D
LET Register A = the sector number to verify (held in Register D).
5AF7
SUB 13H
SUBtract the value 13H (Decimal: 19) from Register A so that sectors are verified in ascending order.
5AF9
NEG
Negate the subtracted value so that it is a positive number
5AFB
LD (FSVSEC),A
Store the ascending sector number (held in Register A) of the sector being checked (held in Sector D) into the memory location 5B1BH.
5AFE
PUSH BC
Save Register Pair BC to the top of the stack.
5AFF
PUSH DE
Save Register Pair DE to the top of the stack.
5B00
PUSH HL
Save Register Pair HL to the top of the stack.
5B01
LD HL,VERASC
LET Register Pair HL = 5B9AH in preparation for the next call to convert it to ASCII.
5B04
CALL ASCII
     [5B55H]
GOSUB to convert the sector number into text.
5B07
LD A,(CURSOR)
Fetch the value stored at memory location 4020H and put it into Register A.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5B0A
AND 0DFH
MASK the value of Register A against 0DFH (1101 1111). This has the effect of turning off bit 5.
5B0C
OR 1FH
OR Register A against 1FH (0001 1111). This has the effect of turning on bits 4, 3, 2, 1, 0. Now Register A should be pointing to column 31.
5B0E
LD (CURSOR),A
Store the value held in Register A into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5B11
LD HL,VERMSG
LET Register Pair HL = 5B89H to point to the message “Verifying Sector xx“.
5B14
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
5B17
LD HL,BUFF
LET Register Pair HL = 6200H, which will be the buffer in RAM
5B1A
LD E,(FSVSEC)
LET Register E = the value (i.e., the sector number in ascending order) put into 5B1BH elsewhere in this overlay; which is the sector number.
5B1C
LD A,(DDTRK)
Fetch the track number (stored at memory location 5BD3H) and put it into Register A.
5B1F
LD D,A
LET Register D = the track number (held in Register A).
5B20
LD A,(FDRIVD)
Fetch the destination drive number from memory location 4E7FH and put it into Register A.
5B23
LD C,A
LET Register C = destination drive number (held in Register A).
5B24
LD A,(DDSID)
Fetch the side number (stored at memory location 5BD6H) and put it into Register A.
5B27
LD (CSIDE),A
Store the source side number (held in Register A) into the memory location 4463H.
NOTE: 4463H is the storage location for the old system disk side number.
5B2A
CALL XREAD
     [4675H]
GOSUB to 4675H to read the sector.
5B2D
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5B2E
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5B2F
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5B30
RET NZ
If the NZ FLAG (Not Zero) is set then we had an error from the call to READ the sector, so RETurn to the caller.
“VERFI2”
5B31
DEC D
DECrement the value stored in Register D by 1 for the next sector to check.
5B32
JR NZ,VER1
      [5AF6H]
If the NZ FLAG (Not Zero) is set, keep processing the sectors in the track by JUMPing to 5AF6H.
5B34
RET
RETurn to the caller.

5B35H – Position the Diskette Head to the Track held in Register C.

“VERFIT”
5B35
“STEPR”
LD A,(FDRIVE)
Fetch the drive select code (stored at memory location 4E7DH) and put it into Register A.
5B38
CALL DSEL0
     [44E0H]
GOSUB to 44E0H to select the disk.
5B3B
LD A,58H
LET Register A = 58H (0101 1000), which, when sent to 0F0H, sends: STEP IN (010), Track register needs to be updated (1), Load head at the beginning (1), no Verify (0), 6ms stepping (00).
5B3D

Send the bit pattern in sent to Port F0H (the Floppy Disk Control Port). When activated one step pulse is sent in the direction of track 76. Once stepped, and interrupt is generated.
5B3F
CALL CHKBSY
     [4547H]
GOSUB to 4547H.
NOTE: 4547H is a routine to wait for the FDC.
5B42
PUSH BC
Save Register Pair BC to the top of the stack.
5B43
PUSH DE
Save Register Pair DE to the top of the stack.
5B44
PUSH HL
Save Register Pair HL to the top of the stack.
5B45
LD A,(FDRIVD)
Fetch the destination drive number from memory location 4E7FH and put it into Register A.
5B48
LD E,A
LET Register E = the destination drive number (held in Register A).
5B49
LD D,00H
LET Register D = 00H so that Register Pair DE is now the Offset in the disk head position table.
5B4B
LD HL,SEKTRK
LET Register Pair HL = 445BH to point to the DOS TRACK TABLE.
5B4E
ADD HL,DE
LET Register Pair HL = Register Pair HL + Register DE so that HL now points to the appropriate entry in the DOS TRACK TABLE.
5B4F
LD (HL),C
Store the head position (held in Register C) into the appropriate entry in the DOS TRACK TABLE.
5B50
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5B51
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5B52
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
“STEPR1”
5B53
XOR A
Set Register A to ZERO and clear all Flags.
5B54
RET
RETurn to the caller.

5B55H – Convert Register A into a Two Digit Decimal to be stored at (HL).

“ASCII”
5B55
PUSH BC
Save Register Pair BC to the top of the stack.
5B56
LD C,30H
LET Register C = 30H (ASCII: 0) so that the tens digit is a “0” unless changed.
“SUB”
5B58
SUB 0AH
SUBtract the value 0AH from Register A to see if Register A is still positive after subtracting 10.
5B5A
JR C,ADD
     [5B5FH]
If the C FLAG (Carry) is set then subtracting 10 made it negative, so JUMP to 5B5FH.
5B5C
INC C
INCrement the tens digit (stored in Register C) by 1.
5B5D
JR SUB
   [5B58H]
Loop to 5B58H until Register A is less than 10.


5B5FH – Continuation of the routine to convert Register A into a Two Digit Decimal to be stored at (HL), jumped here once we have a remainder.

“ADD”
5B5F
ADD A,3AH
LET Register A = Register A + 3AH to form the one’s digit.
5B61
LD B,A
LET Register B = the one’s digit (the Register A).
5B62
LD (HL),C
Store the ten’s digit (held in Register C) into the memory location pointed to by Register Pair HL.
5B63
INC HL
INCrement the value stored in Register Pair HL by 1 to move to the next memory location.
5B64
LD (HL),B
Store the one’s digit (held in Register B) into the memory location pointed to by Register Pair HL.
5B65
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5B66
RET
RETurn to the caller.

5B67H – Display a Message.

“PDATA”
5B67
PUSH DE
Save Register Pair DE to the top of the stack.
5B68
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
5B6B
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5B6C
RET
RETurn to the caller.

5B6DH – MESSAGE and BYTE STORAGE.

“WRTDIR”
5B6D
DEFM …
0AH + “Writing System Information” + 0DH.
“VERMSG”
5B89
DEFM …
“Verifying Sector “.
“VERASC”
DEFM …
“00” + 03H.
“FORMSG”
5B9D
DEFM …
1DH + “Formatting Track “.
“FORASC”
DEFM …
“00” + 03H.
“TRKNN”
5BB5
DEFW C5H 5BH
Start of Track Data for tracks 00 – MAXTRK, found at “DDTAB” (5BC5H) below.
5BB7
DEFW C8H 5BH
Start of Sector Data, found at “DDREP” (5BC8H) below.
5BB9
DEFW 07H 5CH
Start of End-of-Track Data, found at “DDTRL” (5C07H) below.
5BBB
DEFW 0AH 5CH
Start of Sector Table, found at “SECTAB” (5C0AH) below.
“DDST”
5BBD
DEFW D9H 5BH
Start of Track Data, found at “DDSEC” (5BD9H) below.
5BBF
DEFB 01H
Beginning Sector Number in a Track
5BC0
DEFB 12H
Ending Sector Number in a Track (=18 Decimal)
5BC1
DEFW D3H 5BH
Track Number Structure Address, found at “DDTRK” (5BD3H) below.
5BC3
DEFW ECH 5BH
Double Density Data Sector Table Entry Address, found at “DDDATA” (5BECH) below.

5BC5H – MESSAGE and BYTE STORAGE – Data to generate a track to write to diskette.

“DDTAB”
5BC5
DEFW 40 00 4E
64 x ‘4E’. This is the track header.
“DDREP”
5BC8
DEFW 08 00 00
08 x ’00’. This is the part of the Sector ID Header.
5BCB
DEFW 03 00 F5
03 x ‘F5’. This is the part of the Sector ID Header.
5BCE
DEFW 01 00 FE
01 x ‘FE’. This is an ID Address Mark.
5BD1
DEFW 01 00
01 x …
“DDTRK”
5BD3
DEFB 00
… ’00’. This is the track number.
5BD4
DEFW 01 00
01 x …
“DDSID”
5BD6
DEFB 00
… ’00’. This is the side number.
5BD7
DEFW 01 00
01 x …
“DDSEC”
5BD9
DEFB 00
… ’00’. This is the sector number.
5BDA
DEFW 01 00 00
01 x ’00’. This is the sector number.
5BDD
DEFW 01 00 01
01 x ’01’. This is an 01H.
5BD1
DEFW 01 00 F7
01 x ‘F7’. This the code to write two CRC bytes to the Sector ID Header.
5BE0
DEFW 16 00 4E
22 x ‘4E’. This is part of the user data header.
5BE3
DEFW 0C 00 00
12 x ’00’. This is part of the user data header.
5BE6
DEFW 03 00 F5
03 x ‘F5’. This is part of the user data header.
5BE9
DEFW 01 00 FB
01 x ‘FB’. This is a Data Address Mark.
“DDDATA”
5BEC
DEFW F0 00 E5
240 x ‘E5’. This fills the sector with the empty byte filler of E5.
5BEF
DEFW FF FF
 
“COPY”
5BF1
DEFM ‘(C) 1980 TANDY ‘
This is the copyright message.
5C01
DEFW 01 00 F7
01 x ‘F7’. This the code to write two CRC bytes to the Sector ID Header.
5C04
DEFW 18 00 4E
24 x ‘4E’. This is the trailer bytes.
“DDTRL”
5C07
DEFW 82 03 4E
898 x ‘4E. This is the end of track data.

5C0AH – MESSAGE and BYTE STORAGE – Sector Number Table.

“SECTAB”
5C0A
DEFB …
01 04 07 0A 0D 10 – Interleaved sector numbers.
5C10
DEFB …
02 05 08 0B 0E 11 – Interleaved sector numbers.
5C16
DEFB …
03 06 09 0C 0F 12 – Interleaved sector numbers.
5C1C
DEFB 00H
End of Table.
“CSECTB”
5C1D
DEFW 0AH 5CH
Pointer into the sector number table

5C1FH – Generate the Track Image Area into the Buffer. On Entry, C contains the Track Number.

“TRKIMG”
5C1F
PUSH BC
Save Register Pair BC to the top of the stack.
5C20
PUSH DE
Save Register Pair DE to the top of the stack.
5C21
PUSH HL
Save Register Pair HL to the top of the stack.
5C22
PUSH AF
Save Register Pair AF to the top of the stack.
5C23
PUSH IY
Save Special Index Register IY to the top of the stack.
5C25
LD H,(IX+TRKADD+MSB)
Fetch the MSB of the TRACK NUMBER in track format image into Register H.
5C28
LD L,(IX+TRKADD+LSB)
Fetch the LSB of the TRACK NUMBER in track format image into Register H.
5C2B
LD (HL),C
Store the track number (held in Register C) into the table (i.e. the memory location pointed to by Register Pair HL).
5C2C
LD A,C
LET Register A = the track number.
5C2D
LD (SAVEA),A
Store the track number (held in Register A) into the memory location 5C4DH.
5C30
LD DE,BUFF
LET Register Pair DE = 6200H, which will be the buffer in RAM for the track image.
5C33
CALL TBLBMP
     [5C7BH]
GOSUB to 5C7BH to get the addresses for the table (Part 1).
“TRKIM1”
5C36
CALL EXPAND
     [5C8CH]
GOSUB to 5C8CH to generate the track header field from the table entry.
5C39
JR C,TRKIM1
     [5C36H]
If the HL is less than BC, the C FLAG (Carry) is set, so LOOP back to 5C36H as there is more to generate.
5C3B
CALL TBLBMP
     [5C7BH]
GOSUB to 5C7BH to get the addresses for the table (Part 2).
5C3E
PUSH HL
Save the address of the current table entry (held in Register Pair HL) to the top of the stack.
5C3F
LD HL,SECTAB
LET Register Pair HL = 5C0AH to point to the SECTOR NUMBER TABLE (in interleaved order)
5C42
LD (CSECTB),HL
Reset the SECTOR NUMBER TABLE (held in Register HL) into the memory location 5C1DH (which is the storage location for the pointer into the sector number table).
“TRKIM2”
5C45
LD HL,(CSECTB)
Fetch the position in the sector number table (stored at memory location 5C1DH) and put it into Register HL.
5C48
LD A,(HL)
Fetch the sector number to use based on where HL is pointing and put it into Register A.
5C49
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
5C4A
JR Z,TRKIM4
     [5C6BH]
If the Z FLAG (Zero) is set then we have hit the 00H terminator for the SECTOR NUMBER TABLE, so JUMP to 5C6BH.
5C4C
+1=”SAVEA”
LD A,(SAVEA)
LET Register A = the track number which was put into 5C4DH elsewhere in this overlay.
5C4E
CP 40H
Compare the value held in Register A against 28H (Decimal: 40). Results:
  • If Register A equals track 40, the Z FLAG is set.
  • If A < track 40, the CARRY FLAG will be set.
  • if A >= track 40, the NO CARRY FLAG will be set.
5C50
LD A,(HL)
Fetch the sector number (i.e., the value stored at memory location pointed to by Register Pair HL) and put it into Register A.
5C51
JR C,TRIM21
     [5C55H]
If we are < track 40, then the C FLAG (Carry) is set and we are done, so JUMP to 5C55H.

If we are here, then we are at track 40, which Frank Durda IV referred to as “the secret track”.

5C53
OR 80H
Set the correct sector number for “secret track” by ORing Register A against 80H (1000 0000) to turn on bit 7 of the sector number held in Register A.
“TRIM21”
5C55
INC HL
INCrement the value stored in Register Pair HL by 1 so that it will point to the next entry in the sector number table.
5C56
LD (CSECTB),HL
Store the current pointer to the SECTOR NUMBER TABLE (held in Register HL) into the memory location 5C1DH (which is the storage location for the pointer into the sector number table).
5C59
LD H,(IX+SECADD+MSB)
Fetch the MSB of the SECTOR NUMBER TABLE into Register H.
5C5C
LD L,(IX+SECADD+LSB)
Fetch the LSB of the SECTOR NUMBER TABLE into Register H.
5C5F
LD (HL),A
Store the sector number (i.e., the value held in Register A) into the SECTOR NUMBER TABLE at the memory location pointed to by Register Pair HL.
5C60
POP HL
Put the pointers (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
5C61
PUSH HL
Save the pointers (held in Register Pair HL) to the top of the stack.
“TRKIM3”
5C62
CALL EXPAND
     [5C8CH]
GOSUB to 5C8CH to generate the sector image field.
5C65
JR C,TRKIM3
     [5C62H]
If the C FLAG (Carry) is set then we still have more to process, so jump back to 5C62H.
5C67
POP HL
Put the pointers (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
5C68
PUSH HL
Save the pointers (held in Register Pair HL) to the top of the stack.
5C69
JR TRKIM2
   [5C45H]
LOOP BACK to 5C45H to process the next sector.

5C6BH – Continuation of the Generate the Track Image Area; jumped here when we have reached the end of the SECTOR NUMBER TABLE.

“TRKIM4”
5C6B
POP HL
Clear the Stack.
5C6C
CALL TBLBMP
     [5C7BH]
GOSUB to 5C7BH to get the addresses for the table (Part 3).
“TRKIM5”
5C6F
CALL EXPAND
     [5C8CH]
GOSUB to 5C8CH to generate the trailer field.
5C72
JR C,TRKIM5
     [5C6FH]
If the C FLAG (Carry) is set then we have more to go, so loop back to 5C6FH.
5C74
POP IY
Put the value held at the top of the STACK into Special Index Register IY, and then remove the entry from the stack.
5C76
POP AF
Put the value held at the top of the STACK into Register Pair AF, and then remove the entry from the stack.
5C77
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5C78
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5C79
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5C7A
RET
RETurn to the caller.

5C7BH – Retrieve the Table Addresses.

“TBLBMP”
5C7B
LD H,(IY+BEGADD+MSB)
Fetch the MSB of the START OF THE IMAGE DATA BLOCK into Register H.
5C7E
LD L,(IY+BEGADD+LSB)
Fetch the LSB of the START OF THE IMAGE DATA BLOCK into Register L.
5C81
LD B,(IY+ENDADD+MSB)
Fetch the MSB of the START OF THE NEXT BLOCK into Register B.
5C84
LD C,(IY+ENDADD+LSB)
Fetch the LSB of the START OF THE NEXT BLOCK into Register C.
5C87
5C89
INC IY
INC IY
INCrement the pointer stored in Special Index Register IY by 2 to point to the next table entry.
5C8B
RET
RETurn to the caller.

5C8CH – Use the Track Building Table to fill up the table pointed to by DE.

On entry, HL points to the beginning of the table. On exit, DE = DE + the length of the fill, HL points to the NEXT table entry, and flags are set.

“EXPAND”
5C8C
LD (WORK),A
Store the current sector number (held in Register A) into the memory location 5CBCH.
5C8F
PUSH BC
Save the TABLE END POINTER (held in Register Pair BC) to the top of the stack.
5C90
LD C,(HL)
Fetch the LSB of the Byte Count from the memory location pointed to by Register Pair HL and put it into Register C.
5C91
INC HL
INCrement the value stored in Register Pair HL by 1.
5C92
LD B,(HL)
Fetch the MSB of the Byte Count from the memory location pointed to by Register Pair HL and put it into Register B.
5C93
INC HL
INCrement the value stored in Register Pair HL by 1.
5C94
INC BC
INCrement the value stored in Register Pair BC by 1.
5C95
5C96
LD A,B
OR C
Test for the copyright message. Since the Z-80 cannot test Register Pair BC against zero, the common trick is to set Register A to equal to Register B, and then OR A against Register C. Only if both Register B and Register C were zero can the Z FLAG be set.
5C97
DEC BC
DECrement the value stored in Register Pair BC by 1.
5C98
JR NZ,NOCOPY
      [5CA2H]
If the NZ FLAG (Not Zero) is set, then this is not the copyright message, so JUMP to 5CA2H.
5C9A
LD BC,0010H
LET Register Pair BC = 0010H (Decimal: 16) for the length of the copyright message.
5C9D
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE (i.e., the sector buffer). Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
5C9F
PUSH HL
Save the image data pointer (held in Register Pair HL) to the top of the stack.
5CA0
JR EXPND1
   [5CB1H]
JUMP to 5CB1H to exit.

5CA2H – Continuation of the routine to Use the Track Building Table to fill up the table pointed to by DE; jumped here if we did not hit the copyright message.

“NOCOPY”
5CA2
LD A,(HL)
Fetch a byte of data from the table (stored at memory location pointed to by Register Pair HL) and put it into Register A.
5CA3
INC HL
INCrement the pointer (stored in Register Pair HL) by 1.
5CA4
PUSH HL
Save the pointer (stored in Register Pair HL) to the top of the stack.
5CA5
LD (DE),A
Store the data byte (held in Register A) into the track buffer image (pointed to by Register Pair DE).
5CA6
INC DE
INCrement the pointer in the track image (stored in Register Pair DE) by 1.
5CA7
DEC BC
DECrement the value stored in Register Pair BC (i.e., how many bytes to move) by 1.
5CA8
5CA9
LD A,B
OR C
Since the Z-80 cannot test Register Pair BC against zero, the common trick is to set Register A to equal to Register B, and then OR A against Register C. Only if both Register B and Register C were zero can the Z FLAG be set.
5CAA
JR Z,EXPND1
     [5CB1H]
IF all the bytes have been moved then the Z FLAG (Zero) will be set; so JUMP to 5CB1H.
5CAC
5CAD
PUSH DE
POP HL
Let Register Pair HL = the address of the next character in the track buffer (pointed to by Register Pair DE).
5CAE
DEC HL
DECrement the value stored in Register Pair HL by 1 to point to the prior stored character.
5CAF
LDIR
Fill the track buffer with the character via LDIR which transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
“EXPND1”
5CB1
POP HL
Put the current table entry address (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
5CB2
POP BC
Put the table end address (held at the top of the STACK) into Register Pair BC, and then remove the entry from the stack.
5CB3
PUSH HL
Put the current table entry address (held in Register Pair HL) to the top of the stack.
5CB4
OR A
Set FLAGS based on the contents of Register A and, in all cases, clear the CARRY FLAG..
5CB5
SBC HL,BC
Test to see (and set the CARRY FLAG with the answer) if we are done with this image block, by subtracting the END OF TABLE value (stored in Register Pair BC and the carry flag) from the CURRENT TABLE ADDRESS (value stored in Register Pair HL).
5CB7
POP HL
Restore the current table entry address from the top of the stacke into Register Pair HL.
5CB8
LD A,(WORK)
Fetch current sector number from its safe storage place in 5CBCH into Register A.
5CBB
RET
RETurn to the caller.
“WORK”
5CBC
DEFB 00H
Safe storage place for the current sector number in the above routine.

5CBDH – FORMAT and VERIFY a DISK.

First we need to initialize the hash index buffer to 0’s. A common trick is to set up a pointer to a buffer, the destination is 1 byte higher, and the to put a “0” in the first byte, so the 0 just keeps getting copied from a memory location to the memory location + 1.

“FORM”
5CBD
LD HL,DUM1
LET Register Pair HL = 5F00H to point to a buffer in RAM.
5CC0
LD DE,DUM1 + 1
LET Register Pair DE = one byte beyond HL.
5CC3
LD BC,SECTOR-32
LET Register Pair BC = 00E0H (Decimal = 224) which is the number of bytes we will fill with a 00H in a dummy directory sector.
5CC6
LD (HL),00H
Store a 00H into the memory location pointed to by Register Pair HL.
5CC8
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.

Next, initialize the system extents with a bunch of FFH’s.

5CCA
LD BC,001FH
The prior routine filled 224 bytes with 00’s. Now we need to deal with the remaining 32 bytes. LET Register Pair BC = 001FH (Decimal: 31) for a counter.
5CCD
LD (HL),0FFH
Store a FFH into the memory location pointed to by Register Pair HL.
5CCF
LDIR
Transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.

Next, initialize the track counter.

5CD1
LD C,0FFH
LET Register C = 0FFH (Decimal: 255).
5CD3
LD B,28H
LET Register B = 28H (Decimal: 40 tracks).
5CD5
LD HL,FLAWD
LET Register Pair HL = 6160H, which is a buffer in RAM which will be used to store the GAT Flaws
5CD8
XOR A
Set Register A to ZERO and clear all Flags.
5CD9
LD (FLAWC),A
Store a 00H (held in Register A) into the memory location 4E80H to indicate that we have NO flawed tracks at the moment.
5CDC
LD IX,DDST
LET Special Index Register IX = 5BBDH, which is the SECTOR/TRACK DATA TABLE.
5CE0
LD IY,TRKNN
LET Special Index Register IY = 5BB5H, which is the DOUBLE DENSITY TRACK TABLE.
“FORMDD”
5CE4
INC C
INCrement the track number (stored in Register C) by 1 so as to position the disk head to the next track.
5CE5
CALL NZ,STEPR
        [5B35H]
If we have not hit track 0, GOSUB to 5B35H to Position the Diskette Head to the Track held in Register C.
5CE8
JP NZ,ABRT
      [4E4AH]
If the NZ FLAG (Not Zero) is set, meaning that the prior CALL routine returned because of an ERROR, JUMP to 4E4AH.
5CEB
LD D,04H
LET Register D = 04H, for up to 4 retries.
“RETRY2”
5CED
CALL TRKIMG
     [5C1FH]
GOSUB to 5C1FH to make the track image in RAM to write to diskette.
5CF0
PUSH BC
Save Register Pair BC to the top of the stack.
5CF1
PUSH DE
Save Register Pair DE to the top of the stack.
5CF2
PUSH HL
Save Register Pair HL to the top of the stack.
5CF3
LD A,0D0H
LET Register A = 0D0H (1101 0000). When 1101 0000 is sent to the FDC, we are instructing it to Force Interrupt (1101) on a Not-Ready-to-Ready transition (0000).
5CF5

Send this bit pattern in sent to Port F0H (the Floppy Disk Control Port).
5CF7
LD HL,FORASC
LET Register Pair HL = 5BAFH which is in the middle of the “Formatting Track 00 ” message.
5CFA
LD A,(DDTRK)
Fetch the track number (stored at memory location 5BD3H) and put it into Register A.
5CFD
CALL ASCII
     [5B55H]
GOSUB to 5B55H to encode that decimal track number and put it into that message.
5D00
LD HL,FORMSG
LET Register Pair HL = 5B9DH which points to the “Formatting Track 00 ” message, noting that the 00 has now been filled in.
5D03
CALL PRINT
     [021BH]
GOSUB to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found.
5D06
LD A,(DDTRK)
Fetch the track number (stored at memory location 5BD3H) and put it into Register A.
5D09
CP 16H
Compare the value held in Register A against 16H (Decimal: Track 22). Results:
  • If Register A equals Track 22, the Z FLAG is set.
  • If A < Track 22, the CARRY FLAG will be set.
  • if A >= Track 22, the NO CARRY FLAG will be set.
5D0B
JR C,NOCOMP
     [5D15H]
If A < Track 22 then we do not need write precompensation turned on, so JUMP to 5D15H.
5D0D
LD A,(FDRIVE)
Fetch the disk select code (stored at memory location 4E7DH) and put it into Register A.
5D10
SET 5,A
SET (i.e., set as 1) BIT 5 of Register A to turn on WRITE PRECOMPENSATION.
5D12
LD (FDRIVE),A
Store the updated disk select code (held in Register A) into the memory location 4E7DH.
“NOCOMP”
5D15
LD HL,BUFF
LET Register Pair HL = 6200H, which will be the buffer in RAM for the TRACK FORMAT IMAGE.
5D18
CALL TRKWRT
     [5AB0H]
GOSUB to 5AB0H to WRITE THE TRACK.
5D1B
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5D1C
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5D1D
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5D1E
PUSH BC
Save Register Pair BC to the top of the stack.
5D1F
PUSH DE
Save Register Pair DE to the top of the stack.
5D20
PUSH HL
Save Register Pair HL to the top of the stack.
5D21
CALL VERFIT
     [5AEEH]
GOSUB to 5AEEH to VERIFY the track.
5D24
POP HL
Put the value held at the top of the STACK into Register Pair HL, and then remove the entry from the stack.
5D25
POP DE
Put the value held at the top of the STACK into Register Pair DE, and then remove the entry from the stack.
5D26
POP BC
Put the value held at the top of the STACK into Register Pair BC, and then remove the entry from the stack.
5D27
JR Z,GOOD2
     [5D44H]
If the Z FLAG (Zero) is set then the track is good, so skip over all these resets and JUMP to 5D44H.
“WRTER2”
5D29
CALL TERM
     [4566H]
GOSUB to 4566H.
NOTE: 4566H is the routine which resets the FDC.
5D2C
CALL DELLY
     [4400H]
GOSUB to 4400H for a short delay.
5D2F
CALL TERM
     [4566H]
GOSUB to 4566H.
NOTE: 4566H is the routine which resets the FDC.
5D32
CALL DELLY
     [4400H]
GOSUB to 4400H for a short delay.
5D35
CALL TERM
     [4566H]
GOSUB to 4566H.
NOTE: 4566H is the routine which resets the FDC.
5D38
DEC D
DECrement the retry counter (stored in Register D) by 1.
5D39
JR NZ,RETRY2
      [5CEDH]
If D hasn’t hit ZERO yet, then we still have some retries left, so JUMP to 5CEDH.

If we are here then we tried 4 times to verify the track and have no more retries left.

5D3B
LD A,(FLAWC)
Fetch the flawed track counter (stored at memory location 4E80H) and put it into Register A.
5D3E
INC A
INCrement the number of flawed tracks (stored in Register A) by 1.
5D3F
LD (FLAWC),A
Store the updated number of flawed (held in Register A) into the memory location 4E80H.
5D42
LD (HL),0FFH
Store a 0FFH (meaning a FLAWED TRACK) into the GAT TABLE for that track (i.e., the memory location pointed to by Register Pair HL).
“GOOD2”
5D44
INC HL
Point HL to the next track in the GAT entry.
5D45
DEC B
DECrement the number of tracks remaining to format (stored in Register B) by 1.
5D46
JP NZ,FORMDD
      [5CE4H]
If Register B hasn’t hit ZERO yet, we still have more tracks to go, so JUMP to 5CE4H.
5D49
LD A,(FDRIVE)
Fetch the disk select code (stored at memory location 4E7DH) and put it into Register A.
5D4C
RES 5,A
RESet (i.e., set as 0) BIT 5 of Register A to turn off WRITE PRECOMPENSATION.
5D4E
LD (FDRIVE),A
Store the updated disk select code (held in Register A) into the memory location 4E7DH.
5D51
LD A,(FLAWC)
Fetch the number of flawed tracks (stored at memory location 4E80H) and put it into Register A.
5D54
LD HL,FLAWX
LET Register Pair HL = 5D61H, which is in the middle of the message “nn FLAWED TRACKS.”
5D57
PUSH HL
Save the location in that message (held in Register Pair HL) to the top of the stack.
5D58
CALL ASCII
     [5B55H]
GOSUB to 5B55H to encode the number and put it into that message.
5D5B
POP HL
Restore the location in that message (held at the top of the STACK) into Register Pair HL, and then remove the entry from the stack.
5D5C
DEC HL
DECrement the value stored in Register Pair HL by 1 so as to point to the CARRIAGE RETURN before the start of that message.
5D5D
JP PRINT
   [021BH]
JUMP to 021BH.
NOTE: 021BH is the Model III ROM routine to display the character at (HL) until a 03H is found. Since this was JUMPED to instead of CALLed, the RET at the end of this ROM routine will then RETurn to the caller of this subroutine instead of returning to this place.

5D60H – MESSAGE and BYTE STORAGE – Sector Number Table.

5C60
DEFB 0AH
This is a Carriage Return which gets pointed to when the pointer to FLAWX is decremented by 1 character.
“FLAWX”
5C10
DEFM …
00 FLAWED TRACKS” + 0DH“.
“SPAR_”
5E00
DEFS 0100H
“DUM1”
5F00
DEFS 0100H
“SGAT”
6000
DEFS 256
“FGAT”
6100
DEFS FLAW (60H)
“FLAWD”
6160
DEFS 256-FLAW
“BUFF”
6200
DEFS 256
 
END 57A1H