Model 4P ROM Explained

0000
DI
Start here when Reset switch is pressed.
0001
DB “FDIV”
Frank Durda IV‘s Initials. Since they just load registers, execution of the underlying code is meaningless.
0005
JUMP down to 003EH to skip over all the RST Calls.
0007
NOP
Next are RST vectors — all jump to RAM.

0008-003D – RST Vector Area.

0008
RST 8 (Disk I/O) — will point to a copy of .
000B (4000)
… THIS instruction
000E
NOP
No Operation
000F
NOP
No Operation
0010
RST 10H (Display String) will also point.
0013 (4003)
… THIS instruction
0016
NOP
No Operation
0017
NOP
No Operation
0018
RST 18H (Display Message) — will point to a copy of .
001B (4006)
… THIS instruction
001E
NOP
No Operation
001F
NOP
No Operation
0020
RST 20H (Get Byte).
0023 (4009)
Get a byte from the MODEL%/III file.
0026
NOP
(Vector in RAM is altered for RS-232 boot).
0027
NOP
No Operation
0028
RST 28H (Load Object Code) — will point to a copy of .
002B (400C)
… THIS instruction
002E
NOP
No Operation
002F
NOP
No Operation
0030
RST 30H (Scan Keyboard) — will point to a copy of .
0033 (400F)
… THIS instruction
0036
NOP
No Operation
0037
NOP
No Operation
0038
RST 38H — Mode 1 Interrupts.
003B (4012)
RET
If any interrupts, just ignore them.
003C
NOP
No Operation
003D
NOP
No Operation

003EH – Continue with the code.

003E
XOR A
Initialization continues here. Clear Register A and all flags.
003F
OUT (E4H),A
Send a 0 to Port E4H.
NOTE: Port E4H is the Non-Maskable Interrupt Latch. Sending a 0 to E4 will turn off all Non-Maskable Interrupts.
0041
LD A,50H
Load A with 50H (Binary: 0101 0000); meaning Bit 4 (I/O Bus) and Bit 6 (Clock Speed) are high.
0043
OUT (ECH),A
Output 50H to Port ECH.
NOTE: Port ECH stores miscellaneous controls.
  • Bit 4: I/O bus [0 = disable, 1 = enable]
  • Bit 6: CPU clock speed [0 = 2 mhz, 1 = 4 mhz]

0045H – Move the RST Calls from ROM to RAM. There are 7 RST calls of 3 bytes each, so we set up an outer loop of 7, and an inner loop of 3.

0045
LD B,07H
Next we are going move the RST calls to RAM. First, set up for a loop of 7 times for 7 bytes.
0047
LD HL,000BH
Load HL with the first instruction to copy (which is 000BH).
004A
LD DE,4000H
Load DE with the RAM destination for the relocated RST 08H jump.
004D
LD C,03H
Load C with the number of bytes to copy, which is 3.
004F
LD A,(HL)
Load A with the RAM contents of (HL)
0050
LD (DE),A
Put those RAM contents into the RAM contents of (DE)
0051
INC DE
Bump DE
0052
INC HL
Bump HL
0053
DEC C
Decrement C to keep track of the inner loop of 3
0054
If C is still not zero, jump back to 004FH
0056
LD A,L
If we are here, it is time to move to the next RST call, so load A with L .
0057
ADD A,05H
… add 5 to that.
0059
LD L,A
… and put that back into L so HL is now 5 bytes further along.
005A
LOOP back to 004D until all 7 RST’s are copied.

005CH – End of RST move loop, so we now continue.

005C
LD SP,40A0H
Set up stack pointer to point to 40A0H.
005F
LD C,88H
Load C with 88H (the CRTC Address Register).
0061
JUMP down to 00C1 to skip over all the data.

0063H – Message Storage Area.

0063
DB “III”
Message Storage: “III” which is the extension for ROM image file.
0066
JUMP to 4015H if a NMI triggers.
0069 (4015)
JUMP to 0A48H. This block is copied to RAM 4015H through 4047H.

006CH – Message Storage Area.

006C (4017)
DB ‘MODEL% ‘
Message Storage: Filename for ROM image.

0074H (4020H) – This is the exit point from the ROM, ending with a JUMP to execute the boot sector.

0074 (4020)
XOR A
Zero Register A and all Flags.
NOTE: This ends up at 4020H after a block copy
0075 (4021)
OUT 9CH,A
OUTput a 0 to Port 9CH.
NOTE: Sending a 0 to Port 9CH will switch the 4P boot ROM out.
0077 (4023)
JP 4300H
JUMP to 4300H to start executing boot sector.
007A (4026)
NOP
No Operation
007B (4027)
LD H,(HL)
LD H,H
LD L,C
HALT
Frank Durda IV‘s Initials in lower case. If they execute, though, the computer will freeze.
007F (402B)
NOP
No Operation
0080 (402C)
DB “1(16) 18-Oct-83” + 00H
0090 (403C)
NOP
No Operation
0091 (403D)
XOR A
Zero Register A and all Flags.
NOTE: This ends up at 403EH after a block copy
0092 (403E)
OUT 9CH,A
OUTput a 0 to Port 9CH.
NOTE: Sending a 0 to Port 9CH will switch the 4P boot ROM out.
0095 (4041)
LD HL,(000BH)
Load HL with the memory contents of (000BH)
0098 (4044)
INC A
A = A + 1
0099 (4045)
OUT 9CH,A
OUTPUT A to Port 9CH.
NOTE: Sending a 1 to Port 9CH will switch the 4P boot ROM back in.
009B (4047)
RET
RETURN.

009CH – Message Storage Area.

009C
DB “Boot ROM Version Is” + 00H
00B0
DB 00H,00H,00H,00H,00H
DB 00H,00H,00H,00H,00H
DB 00H,00H,00H,00H,00H
Data for CRTC registers 1 through 15
00C0
NOP
No Operation

00C1H – End of Message Storage Area. This is where we jumped to in 0061H

00C1
IM 1
Set the INTERRUPT MODE to 1 since it was set at 0 initially.

Set up a loop of 15 to fill all 15 CRTC registers with the data from 00B0H.

00C3
LD A,D0H
Load A with D0H
00C5
OUT F0H,A
Send D0H (Binary: 1101 0000) to port F0H.
NOTE: Port F0H is the Floppy Disk Command/Status Register. 1101 0000 is the command to FORCE INTERRUPT (1101) and TERMINATE WITH NO INTERRUPT (0000). This resets the FDC.
00C7
LD B,0FH
Load B with 0FH (Decimal: 15) which is the number of CRTC registers.
00C9
LD HL,00BFH
Load HL with 00BFH, which is the ROM location for CRTC register 15.
00CC
LD A,(HL)
Load A with the contents of the current CRTC register.
00CD
OUT (C),B
OUTput the current register number to the CRTC address register.
NOTE: We entered this routine at 0061H with C being 88BH (the CRTC Address Register).
00CF
OUT 89H,A
OUTput the contents of the current CRTC register to port 89H to send the data to the CRTC data register.
00D1
DEC HL
Decrement HL to point to the next byte of data (i.e., the prior CRTC register data).
00D2
LOOP back to 00CCH for all CRTC registers.

00D4H – End of CRTC register fill loop, so we now continue by testing for a keypress of ..

00D4
LD A,(3820H)
Load A with the memory contents of the 6th row of the keyboard address (holding “89:;,-./”).
00D7
BIT 6,A
Check if BIT 6, which is the . has been pressed.
00D9
If the . was pressed, JUMP to 0CF2H.
NOTE: 0CF2H is the RAM test.

00DCH – If no . was hit, then we zero out both video memory pages.

00DC
LD A,80H
Load A with 80H.
00DE
OUT (84H),A
OUTput 80H (Binary: 1000 0000) to Port 84H.
NOTE: Port 84H handles miscellaneous memory items. Output:
  • 00H: Switch to the first page of video RAM and write protect 0000H-3FFFH
  • 01H: Write enable 0000H-3FFFH
  • 80H: Switch to the second page of video RAM
00E0
GOSUB to 0206H to clear the current page of Video RAM.
00E3
LD A,00H
Load A with 00H.
00E5
OUT (84H),A
OUTput 00H to Port 84H.
NOTE: Port 84H handles miscellaneous memory items. Output:
  • 00H: Switch to the first page of video RAM and write protect 0000H-3FFFH
  • 01H: Write enable 0000H-3FFFH
  • 80H: Switch to the second page of video RAM
00E7
GOSUB to 0206H to clear the current page of Video RAM.

00EAH – Set up to move the 51 bytes at 0069H-009CH to 4015H-4048H.

00EA
LD DE,4015H
To prepare for a LDIR, first set the destination RAM address as 4015H-4048H.
00ED
LD HL,0069H
Set the source ROM address to 0069H-009CH.
00F0
LD BC,0033H
Set the length of the block at 33H (Decimal: 51).
00F3
LDIR
Do the copy from ROM to RAM.

00F5H – Clear RAM from 4055H through 406BH.

00F5
LD HL,4055H
To prepare for a LDIR to clear RAM, first load HL with 4055H.
NOTE: 4055H holds the boot type: 1 for floppy, 2 for HD, 4 for RS-232.
00F8
LD (HL),00H
Clear (4055H).
00FA
LD D,H
LD E,L
Set DE = HL.
00FC
INC DE
Bump DE
00FD
LD BC,0015H
To prepare for a LDIR, load BC with the number of bytes of RAM to clear, minus 1.
0100
LDIR
Clear the RAM

0102H – Continue by scanning the keyboard …

0102
LD BC,7FFFH
Load BC with 7FFFH (Dec: 32767) representing the number of times to scan the keyboard.
0105
We need to scan the keyboard so we call RST 30H.
NOTE: RST 30H jumps to 083EH which scans the keyboard BC times with the output held in AF (+ flags).
0106
PUSH AF
Save AF (which contains the result of the RST 30H Keyboard Scan) to the STACK.
0107
LD A,01H
A = 1 to indicate a floppy disk drive operation.
0109
LD B,04H
B = 4 to indicate a restore command.
010B
We need to do some disk I/O so we call RST 08H which handles such.
NOTE: RST 08H does Input/Output with Z set for success and NZ set for error. RST 08H requires the following settings:
  • A: 1:Floppy, 2:Hard Drive, 4:RS-232
  • B: The command to send to the controller (04H = Restore Drive)
  • C: Sector to read
  • DE: Cylinder to read (D=LSB, E=MSB)
010C
If we have no errors from the RST 08H call, JUMP down a few instructions to 0115H.
010E
LD (4067H),A
If we’re here, then the Disk I/O generated an error, so we store the error (held in A) into the memory location 4067H.
NOTE: 4067H holds the error code from a “floppy restore” command.
0111
CP 06H
Check to see if the error was 06H.
NOTE: Error 06H is “Floppy not available”.
0113
If the error was “Floppy not available” then skip the next 3 instructions.
0115
LD B,32H
If we are here, then the error was NOT “Floppy not available,” so first we will load B with 32H (Binary: 0011 0010).
0117
LD A,01H
… and load A with 01H.
0119
We need to do some disk I/O so we call RST 08H which handles such.
NOTE: RST 08H does Input/Output with Z set for success and NZ set for error. RST 08H requires the following settings:
  • A: 1:Floppy, 2:Hard Drive, 4:RS-232
  • B: The command to send to the controller (32H = Restore drives 1,2,3)
  • C: Sector to read
  • DE: Cylinder to read (D=LSB, E=MSB)
011A
POP AF
Restore AF with the keyboard press code we pushed to the STACK at 0106H.
011B
If no key were pressed, JUMP to 0163H to try all the possibilties, such as ARCNET, etc.
011D
LD A,(4059H)
If we are here, then a key was pressed, so lets get that keypress from (4059H) and put it into A.
NOTE: 4059H holds the boot option selected in the form of 82H-88H.

0120H – This is the code to test for a F1 or 1 keypress at boot and to try a HARD DRIVE BOOT.

0120
CP 86H
Compare the keypress held in A with 86H to test for F1 or 1.
0122
If the keypress was NOT F1 or 1 then skip the next few instructions and JUMP to 0129H to try more keys.
0124
If we are here, then the keypress was F1 or 1 so we GOSUB to 01C0H to try to boot from a hard drive.
NOTE: 01C0H will only RETURN back here if the attempt to boot from hard drive fails, with the resulting error code in A.
0127
If we are here, then the keypress was F1 or 1 AND the hard drive boot failed, so JUMP to 0130H to set the flags on deal with the error.

0129H – This is the code to test for a F2 or 2 keypress at boot and to try a FLOPPY DRIVE BOOT.

0129
CP 87H
Compare the keypress held in A with 87H to test for F2 or 2.
012B
If the keypress was NOT F2 or 2 then skip the next few instructions and JUMP to 0135H to try more keys.
012D
If we are here, then the keypress was F2 or 2 so we GOSUB to 01CAH to try to boot from floppy.
NOTE: 01A0H will only RETURN back here if the attempt to boot from hard drive fails, with the resulting error code in A.

0130H – Boot from Hard Drive and Floppy (as applicable) failed. Error code is in A. If its a 0 then a Model III disk OR a disk with 512 byte sectors was attempted. Otherwise HALT.

0130
OR A
Set the flags for Register A.
NOTE: Register A has the error code returned from the BOOT FROM HARD DRIVE and BOOT FROM FLOPPY DRIVE routines.
0131
If the error is 0 (meaning, a Model III disk was inserted), JUMP down a few instructions to 0137H.
0133
If the error was anything other than a Model III diskette was found, JUMP to 0151H as a fatal error.

0135H – This is the code to test for a F3 or 3 keypress at boot and to try BOOT in MODEL III MODE.

0135
CP 88H
Compare the keypress held in A with 88H to test for F3 or 3.
0137
If we are here, then the keypress was F3 or 3 so we JUMP to 0175H to do a Model III disk boot.

0139H – This is the code to test for a V keypress at boot and to display the boot rom version messages, followed by a HALT.

0139
CP 80H
Compare the keypress held in A with 80H to test for V.
013B
If the keypress was NOT V then JUMP down a few instructions to 014AH.
013D
LD DE,0000H
If the keypress was V, then we need to display the BOOT ROM version number, so first we set DE to 0.
0140
LD HL,009CH
Load HL with the memory location of the message “Boot ROM Version Is ” + 00H.
0143
We need to display a message on screen so we call RST 10H.
NOTE: RST 10H displays a string stored in HL (with a 00H to indicate the end of the string) at the screen position held in DE.
0144
LD HL,0080H
Load HL with the memory location of the boot ROM version message.
0147
We need to display a message on screen so we call RST 10H.
NOTE: RST 10H displays a string stored in HL (with a 00H to indicate the end of the string) at the screen position held in DE.
0148
JUMP to 0160H to HALT the computer since there is nothing left to do after displaying the ROM version message.

014AH – This is the code to test for a RIGHT SHIFT keypress at boot, and to JUMP to 0C1AH if that’s what happened.

014A
CP 83H
Compare the keypress held in A with 83H to test for RIGHT SHIFT.
014C
If we are here, then the keypress was RIGHT SHIFT so we JUMP to 0C1AH to do a RS-232 boot.

0139H – This is the code if none of the above keys were hit!

014F
No other keys were hit, so JUMP back to 00F5H to clear all data and repeat the keybaord scans.

0151H – This is the code for an unsuccessful diskette boot attempt. On entry, Register A holds the error code.

0151
ADD A,A
A = A * 2
0152
LD HL,0273H
Load HL with 0273H.
NOTE: 0273H is the beginning of the list of error messages.
0155
LD D,00H
LD E,A
Put the error code * 2 into DE
0158
ADD HL,DE
HL = HL + DE to add the DE (message offset) to HL (the start of the message table) so as to point to the appropriate error message in the error message list.
0159
LD A,(HL)
Load A with the value held at the memory location held in (HL)
015A
INC HL
Bump HL
015B
LD H,(HL)
Load H with the memory contents held at (HL).
015C
LD L,A
Load L with A
015D
XOR A
Zero A and all flags.
015E
LD E,A
E = A.
NOTE: Now DE is set to 0.
015F
We need to display a message on screen so we call RST 18H.
NOTE: RST 18H jumps to 0255H which displays a message pointed to by HL (with a 00H to indicate the end of the string) at the screen position held in DE if Z is set, or HL otherwise.

0160H – This is the code to HALT the computer and is jumped to on an unsuccessful boot.

0160
JUMP to 4027H to HALT.

0163H – If we are here, then NO keys were pressed at boot time, so we try other things. First, let’s see if there is an ARCNET board.

0163
LD A,”U”
Put a U into A.
0165
LD B,A
B = U.
0166
OUT (B6H),A
Send the U to Port B6H.
NOTE: Port B6H is the ARCNET Board
0168
IN A,(B6H)
INPut a byte from Port B6H.
NOTE: Port B6H is the ARCNET Board
016A
CP B
Compare A (the byte read from port B6H) with U.
016B
If the byte input was a U then we have an ARCNET Board attached, so JUMP to 0C15H to try an ARCNET boot.

016EH – If we are here, then NO keys were pressed at boot time and there is no ARCNET card, so we try other things …

016E
GOSUB to 01C0H to try to boot from a hard drive.
NOTE: 01C0H will only RETURN back here if the attempt to boot from hard drive fails, with the resulting error code in A.
0171
OR A
Set the flags to test for an error (Z).
0172
As long as the error code was 0, GOSUB to 01CAH to try to boot from floppy.
NOTE: 01A0H will only RETURN back here if the attempt to boot from hard drive fails, with the resulting error code in A.

0175H – Model III Disk Boot Routine.

0175
LD A,(4066H)
Load A with the memory contents of 4066H.
NOTE: 4066H tracks whether L was pressed or not (L means to reload the ROM IMAGE even if it tests as present). It is NZ if L was pressed and zero otherwise.
0178
OR A
Set the flags to test for L (NZ).
0179
If L was pressed, skip the next 2 lines and go to 0180H
017B
If we are here then L was NOT pressed, so we GOSUB to 01EBH to check to see if the ROM image is currently in memory.
017E
If the ROM image was already loaded, then skip the next section and JUMP to 01A2H.
0180
LD A,(4067H)
Load A with the memory contents of 4067H.
NOTE: 4067H holds the error code from a “floppy restore” command.
0183
OR A
Set the flags for the error code.
0184
If A is not zero, then we have an error that needs to be displayed and handled, so JUMP to 0151H to display the error message and halt.

0186H – This routine sets the ROM to accept new boot code, and loads the Model III BOOT ROM in.

0186
LD A,01H
If we are here, then there was no error. So first we load A with 01H.
0188
OUT (84H),A
OUTput 01H (Binary: 0000 0001) to Port 84H.
NOTE: Port 84H handles miscellaneous memory items. Output:
  • 00H: Switch to the first page of video RAM and write protect 0000H-3FFFH
  • 01H: Write enable 0000H-3FFFH
  • 80H: Switch to the second page of video RAM
018A
LD DE,0000H
DE = 0000 to display the message at top of screen.
018D
LD HL,0491H
HL = “Loading ROM Image…”.
0190
We need to display a message on screen so we call RST 18H.
NOTE: RST 18H jumps to 0255H which displays a message pointed to by HL (with a 00H to indicate the end of the string) at the screen position held in DE if Z is set, or HL otherwise.
0191
GOSUB to 0A72H.
NOTE: 0A72H will load the ROM image from floppy disk.
0194
PUSH AF
Save register AF to the STACK.
0195
PUSH HL
Save register HL to the STACK.
0196
GOSUB to 0206H.
NOTE: 0206H clears the screen.
0199
POP HL
Restore register HL from the STACK.
019A
POP AF
Restore register AF from the STACK.
019B
If the NOT ZERO flag is set, we have an error that needs to be displayed and handled, so JUMP to 0151H to display the error message and halt.
019D
LD A,01H
If we are here, then Model III ROM was successfully loaded. A = 1.
019F
LD (4058H),A
Put a 1 into (4058H).
NOTE: I have not found any other use of 4058H so I don’t know why this is done.
01A2
LD (4024H),HL
Put HL into (4024H).
NOTE: HL is the transfer address for the ROM image.
01A5
LD A,(4065H)
Put the memory contents of (4065H) into A.
NOTE: 4065H will be NON ZERO if the P key was pressed (thanks to the routine at 0883H). Pressing the P key on boot will cause the computer to prompt the user to switch disks after booting the Model III ROM image.
01A8
OR A
Set the flags to see if 4065H set Z or NZ.
01A9
If the Z flag is set, then the P was NOT pressed, so JUMP down a few lines to 01B6H to skip over the prompt.
01AB
LD HL,0443H
Point HL to the message ‘ROM image loaded — press ENTER or BREAK’.
01AE
We need to display a message on screen so we call RST 18H.
NOTE: RST 18H jumps to 0255H which displays a message pointed to by HL (with a 00H to indicate the end of the string) at the screen position held in DE if Z is set, or HL otherwise.
01AF
LD A,(3840H)
Load A with the memory contents of the 7th row of the keyboard address (holding ENTER, CLEAR, BREAK, arrows, SPACE).
01B2
AND 05H
MASK that keyboard row with 05H (0000 0101) to test for ENTER or BREAK.
01B4
If the MASK is zero, the JUMP to 01AF to check for BREAK.
01B6
XOR A
Clear A and all registers.
01B7
OUT (84H),A
OUTput 00H to Port 84H.
NOTE: Port 84H handles miscellaneous memory items. Output:
  • 00H: Switch to the first page of video RAM and write protect 0000H-3FFFH
  • 01H: Write enable 0000H-3FFFH
  • 80H: Switch to the second page of video RAM
01B9
LD A,10H
A = 10H (Binary: 0001 0000).
01BB
OUT (ECH),A
Output 0001 0000 to Port ECH to trigger a 2Mhz clock and to enable the I/O Bus.
NOTE: Port ECH stores miscellaneous controls.
  • Bit 4: I/O bus [0 = disable, 1 = enable]
  • Bit 6: CPU clock speed [0 = 2 mhz, 1 = 4 mhz]
01BD
JUMP to 4020H (to clear A and the flags, switch off the Model 4P Boot ROM, and JUMP to 4300H to execute the loaded ROM.

01C0H – Attempt to boot from a drive.

01C0H – We are in the ATTEMPT TO BOOT FROM DRIVE routine. Here, we set up the variables for HARD DRIVE.

01C0
LD A,02H
A = 02H.
NOTE: This is setting a RST 08H variable to indicate hard drive.
01C2
LD B,01H
B = 01H.
NOTE: This is setting a RST 08H variable to Initialize.
01C4
We need to do some disk I/O so we call RST 08H which handles such.
NOTE: RST 08H does Input/Output with Z set for success and NZ set for error. RST 08H requires the following settings:
  • A: 1:Floppy, 2:Hard Drive, 4:RS-232
  • B: The command to send to the controller (01H = “Restore, Unload Head, No Verify, 12ms stepping rate”)
  • C: Sector to read
  • DE: Cylinder to read (D=LSB, E=MSB)
01C5
RET NZ
If there are any errors, RETURN.
01C6
LD A,02H
A = 02H.
NOTE: This is setting a RST 08H variable to indicate hard drive.
01C8
JUMP to 01D0H.
NOTE: 01D0H attempts to boot from the hard drive.

01CAH – We are in the ATTEMPT TO BOOT FROM DRIVE routine. Here, we test the floppy drive for an error from a “FLOPPY RESTORE” command.

01CA
LD A,(M4067)
Load A with (4067H).
NOTE: 4067H holds the error code from a “floppy restore” command.
01CD
OR A
Set the flags based on the error code from a “floppy restore” command.
01CE
RET NZ
If there are any errors, RETURN.

01CFH – We are in the ATTEMPT TO BOOT FROM DRIVE routine. There was no floppy drive error, so reset the RST 08H variables to point to FLOPPY DISK.

01CF
INC A
Bump A to 1.
NOTE: This is setting a RST 08H variable to indicate floppy drive.

01D0H – We are in the ATTEMPT TO BOOT FROM DRIVE routine. Here is common code for both FLOPPY and HARD DRIVE boots.

01D0
LD BC,0C01H
B = 0CH, C = 01H.
NOTE: This is setting a RST 08H variable to 0CH=Read, 01H=sector to read.
01D3
LD (4055H),A
Store a 1 into (4055H).
NOTE: 4055H holds the boot type: 1 for floppy, 2 for HD, 4 for RS-232.
01D6
LD DE,0000H
DE = 0000.
NOTE: This is setting a RST 08H variable for the cylinder to read.
01D9
LD HL,4300H
HL = 4300H.
NOTE: 4300H is the address of the buffer for the sector data read.
01DC
We need to do some disk I/O so we call RST 08H which handles such.
NOTE: RST 08H does Input/Output with Z set for success and NZ set for error. RST 08H requires the following settings:
  • A: 1:Floppy, 2:Hard Drive, 4:RS-232
  • B: The command to send to the controller (0CH = READ)
  • C: Sector to read
  • DE: Cylinder to read (D=LSB, E=MSB)
01DD
RET NZ
If there are any errors then RETURN.
01DE
LD A,E
If we are here then there were no errors so A = E (which is the length of sector that was read).
01DF
LD (M4056),A
Store A into (4056H).
NOTE: 4056H holds the sector length and is 1 for a 256-byte sectore and 2 for a 512-byte sector.
01E2
DEC A
Decrement A (so that it will be 0 for a 256-byte sector, and 1 for a 512-byte sector).
01E3
If it was a 256-byte sector, GOSUB to 0215H to see if it needs the ROM image.
01E6
If 0215H returned with the ZERO flag set, then the ROM image is NOT needed, so JUMP to 01B6H to protect the ROM, set the ports to Model III, and JUMP to 4020H to complete the boot.
01E8
LD A,00H
If 0215H returned with the NOT ZERO flag set, then we needed the ROM but didn’t get it, so we need to display ‘ROM Image Not Found’. First, A = 0
01EA
RET
and RETURN noting that NZ is currently set.

01EBH – We need to check to see if the ROM image is currently in memory.

01EB
LD HL,3000H
HL = 3000H (as a starting address)
01EE
LD B,0AH
B = 0A to set up for a loop count of 10.
01F0
LD A,C3H
C = C3H.
NOTE: C3H is the opcode for a 3 byte JP instruction.
01F2
CP (HL)
Test the memory location held in HL against a C9.
01F3
RET NZ
If that memory location is not a JP instruction, then there is no ROM image in memory.
01F4
INC HL
INC HL
INC HL
Bump HL 3 times to move to the next JP instruction
01F7
Loop back to 01F2H 10 times.
01F9
If we are here, then all the JUMPs were in place so GOSUB to 403EH (whch was 0092H) to loads HL with (000BH), bump A, put the Model 4P ROM back in, and returns
01FC
XOR A
Zero A and clear all flags.
01FD
LD DE,E9E1H
DE = E9E1H.
NOTE: This is a value that ought to be there for ROM image.
0200
SBC HL,DE
Subtract DE and the CARRY FLAG from HL. This will set Z if ROM image present, else NZ.
0202
LD HL,3015H
HL = 3015H.
NOTE: 3105H is the transfer address if image already loaded.
0205
RET
RETURN

0206H – Clear the screen.

0206
LD A,’ ‘
Put space into A.
0208
LD HL,3C00H
Set HL to the start of video memory.
020B
LD BC,03FFH
Set BC to the length of screen, minus one.
020E
LD (HL),A
Put a space into the memory location held in (HL).
020F
LD D,H
LD E,L
DE = HL
0211
INC DE
DE = DE + 1
0212
LDIR
Do the move.
0214
RET
RETURN

0215H – See if it needs the ROM image.

0215
LD A,(M4064)
Load A with the contents of (4064H).
NOTE: 4064H is the address for recording N key.
0218
OR A
Set the flags to check for a N keypress (=NZ).
0219
If Nwas pressed, we are being told by the user that the ROM IMAGE has been loaded, so just boot a Model III disk without it … so JUMP to 0228H.
021B
LD HL,4300H
HL = 4300H.
NOTE: 4300H is the address of the buffer for the sector data read.
021E
LD B,FEH
B = FEH (Decimal: 254) which is the number of bytes to check.
0220
LD A,CDH
A = the OPCODE for CALL.
0222
CP (HL)
Check the memory contents held at (HL) vs a CALL command.
0223
If there is a CALL command there, JUMP to 023FH.
0225
INC HL
If there is NOT a CALL command there, point to the next byte.
0226
and LOOP back to 0220H to keep looking for a CALL command.

0228H – Check to see if the ROM IMAGE is in RAM.

0228
GOSUB to 01EBH to check to see if the ROM image is in memory.
022B
If the ROM image is NOT in memory, then JUMP to 023DH because we do not need to overwrite the ROM image.

022DH – Overwrite/Destroy the ROM Image.

022D
LD A,01H
A = 01H
022F
OUT (84H),A
OUTput 01H (Binary: 0000 0001) to Port 84H.
NOTE: Port 84H handles miscellaneous memory items. Output:
  • 00H: Switch to the first page of video RAM and write protect 0000H-3FFFH
  • 01H: Write enable 0000H-3FFFH
  • 80H: Switch to the second page of video RAM
0231
LD HL,3000H
Set up for a memory move. First HL = 3000H.
0234
LD D,H
LD E,L
DE = HL
0236
LD (HL),L
Put a 0 into the memory location pointed to by HL.
0237
INC DE
DE = DE + 1
0238
LD BC,001EH
BC = 001EH (Decimal: 30) consecutive bytes.
023B
LDIR
Perform the move from from 3000H to 301DH.
023D
XOR A
Zero A and reset all flags. This also sets the Z flag to indicate that we won’t need to load the ROM image.
023E
RET
RETurn.

023FH – This is jumped to from the middle of the 0215H ROM image test IF a CALL command was found.

023F
INC HL
HL = HL + 1 to point to next byte in boot sector (which is the LSB of the CALL’s destination).
0240
DEC B
B = B – 1 to decrement byte counter.
0241
INC HL
HL = HL + 1 to point to next byte in boot sector (which is the MSB of the CALL’s destination).
0242
DEC B
B = B – 1 to decrement byte counter.
0243
LD A,(HL)
A = the byte held at the memory location (HL).
0244
OR A
Set the flags to see if it was a CALL to page 0 (CALL 00xxH).
0245
If it was not a CALL to page 0, then JUMP back to 0225H to keep looking through the boot sector.
0247
OR L
OR L against A, which will set the NZ. The NZ flag will indicate that we DO need the ROM image.
0248
RET
RETurn.

0255H – RST 10H Code. RST 10H displays a string stored in HL (with a 00H to indicate the end of the string) at the screen position held in DE.

0249
LD A,D
A = D.
024A
OR 3CH
OR A against 0011 1100 (leaving A possible values as Decimal 3C-3F, 7C-7F, BC-BF, and FC-FF) to point DE to video memory.
024C
LD D,A
D = A
024D
LD A,(HL)
Load A with the memory contents pointed to by (HL).
NOTE: HL points to the string to display.
024E
OR A
Set the flags to see if we have hit a 00H (message terminator) byte.
024F
RET Z
If we found a zero, we are done, so RETURN.
0250
LD (DE),A
If we are here, then we still have characters to display, so put the character (held in A) into the memory location pointed to by (DE).
0251
INC HL
HL = HL + 1 to point to the next character in the strong.
0252
INC DE
DE = DE + 1 to point to the next video display position.
0253
LOOP back to 024DH.

0255H – RST 18H Code. RST 18H displays a message pointed to by HL (with a 00H to indicate the end of the string) at the screen position held in DE if Z is set, or HL otherwise.

0255
If Z is set, then DE is already pre-loaded with the appropriate display position, so JUMP to 025BH
0257
LD E,(HL)
Otherwise, we need to put HL into DE so first load E with the memory contents of (HL)
0258
INC HL
HL = HL + 1
0259
LD D,(HL)
Load D with the memory contents of (HL)
025A
INC HL
HL = HL + 1
025B
LD B,H
LD C,L
BC = HL to allow BC to point to the points to the table of strings to display.
025D
LD A,(BC)
Load A with the memory contents of (BC)
025E
INC BC
BC = BC + 1
025F
LD L,A
Load L with A
0260
LD A,(BC)
Load A with the memory contents of (BC)
0261
INC BC
BC = BC + 1
0262
LD H,A
Load H with A
0263
INC A
A = A + 1.
0264
If A (the MSB) is not FFH, then JUMP to 270H to display the string and loop again.
0266
LD A,L
A = L
0267
INC A
A = A + 1.
0268
RET Z
If A (the LSB) = FFH, RETURN because we are done.
0269
INC A
A = A + 1.
026A
If A (the LSB) = is NOT FEH, JUMP to 270H to display the string and loop again.
026C
PUSH BC
If we are here, then HL must be FFFEH. Save BC to the STACK.
026D
POP HL
Restore BC to HL so that the pointer to the table of strings is loaded into HL.
026E
JUMP to 0257H to get the display position for next part of message.
0270
We need to display a message on screen so we call RST 10H.
NOTE: RST 10H displays a string stored in HL (with a 00H to indicate the end of the string) at the screen position held in DE.
0271
Loop back to 025DH for the next value in the table to be displayed.

0273H – Error Message Storage Area.

0273-0274
028D
Points to phrase for Error 0 message.
0275-0276
02B7
Points to phrase for Error 1 message.
0277-0278
02DB
Points to phrase for Error 2 message.
0279-027A
0303
Points to phrase for Error 3 message.
027B-027C
0325
Points to phrase for Error 4 message.
027D-027E
0349
Points to phrase for Error 5 message.
027F-0280
036F
Points to phrase for Error 6 message.
0281-0282
0397
Points to phrase for Error 7 message.
0283-0284
03B1
Points to phrase for Error 8 message.
0285-0286
03D5
Points to phrase for Error 9 message.
0287-0288
03F7
Points to phrase for Error 10 message.
0289-028A
0437
Points to phrase for Error 11 message.
028B-028C
043D
Points to phrase for Error 12 message.

028DH – Error 0 Message Storage Area.

028D-028E
04B7
Points to phrase “The “.
028F-0290
04C5
Points to phrase “ROM Image “.
0291-0292
04D0
Points to phrase “Was Not “.
0293-0294
04D9
Points to phrase “Found on Drive “.
0295-0295
04E9
Points to phrase “0”.
0297-0298
FFFE
Points to END OF MESSAGE.
0299-029A
00C0
Display next part of msg at row 3, col 0.
029B-029C
04C5
Points to phrase “ROM Image “.
029D-029E
05EA
Points to phrase “Nicht “.
029F-02A0
05F1
Points to phrase “Gefunden Auf “.
02A1-02A2
0609
Points to phrase “Laufwerk “.
02A3-02A4
04E9
Points to phrase “0”.
02A5-02A6
FFFE
End of this part of message.
02A7-02A8
0180
Display next part at row 6, col 0.
02A9-02AA
04C9
Points to phrase “Image “.
02AB-02AC
07DD
Points to phrase “ROM “.
02AD-02AE
0700
Points to phrase “Absent”.
02AF-02B0
0707
Points to phrase “e Du “.
02B1-02B2
0771
Points to phrase “Disque”.
02B3-02B4
070D
Points to phrase ” Dans l Unite 0″.
02B5-02B6
FFFF
FFFFH = End of message.

02B7H – Error 1 Message Storage Area.

02B7-02B8
04EB
Points to phrase “Arcnet “.
02B9-02BA
04FE
Points to phrase “Boot “.
02BB-02BC
04F9
Points to phrase “Is Not “.
02BD-02BE
0501
Points to phrase “Available “.
02BF-02C0
FFFE
Points to END OF MESSAGE.
02C1-02C2
00C0
Display next part of msg at row 3, col 0.
02C3-02C4
04EB
Points to phrase “Arcnet “.
02C5-02C6
04F3
Points to phrase “Boot “.
02C7-02C8
05E6
Points to phrase “Ist Nicht “.
02C9-02CA
06F0
Points to phrase “Im System”.
02CB-02CC
FFFE
End of this part of message.
02CD-02CE
0180
Display next part at row 6, col 0.
02CF-02D0
04F3
Points to phrase “Boot “.
02D1-02D2
04EB
Points to phrase “Arcnet “.
02D3-02D4
0700
Points to phrase “Absent”.
02D5-02D6
0708
Points to phrase ” Du “.
02D7-02D8
071D
Points to phrase “Systeme “.
02D9-02DA
FFFF
FFFFH = End of message.

02DBH – Error 2 Message Storage Area.

02DB-02DC
04C5
Points to phrase “ROM Image “.
02DD-02DE
050C
Points to phrase “Can`t Be Loaded – “.
02DF-02E0
051F
Points to phrase “Too Many Extents”.
02E1-02E2
FFFE
Points to END OF MESSAGE.
02E3-02E4
00C0
Display next part of msg at row 3, col 0.
02E5-02E6
04C5
Points to phrase “ROM Image “.
02E7-02E8
0613
Points to phrase “Kann “.
02E9-02EA
05EA
Points to phrase “Nicht “.
02EB-02EC
061D
Points to phrase “Geladen “.
02ED-02EE
0653
Points to phrase “Werden “.
02EF-02F0
051C
Points to phrase “- “.
02F1-02F2
065B
Points to phrase “Zu Viele Bereiche”.
02F3-02F4
FFFE
Points to END OF MESSAGE.
02F5-02F6
0180
Display next part at row 6, col 0.
02F7-02F8
04C9
Points to phrase “Image “.
02F9-02FA
07DD
Points to phrase “ROM “.
02FB-02FC
0726
Points to phrase “Non Chargeable “.
02FD-02FE
05C1
Points to phrase “- “.
02FF-0300
0736
Points to phrase “Segments Trop Numbreux”.
0301-3002
FFFF
FFFFH = End of message.

0303H – Error 3 Message Storage Area.

0303
04B7
Points to phrase “The “.
0305
0538
Points to phrase “Hard Disk “.
0307
04E2
Points to phrase “Drive “.
0309
04F9
Points to phrase “Is Not “.
030B
0550
Points to phrase “Ready “.
030D
FFFE
Points to END OF MESSAGE.
030F
00C0
Display next part of msg at row 3, col 0.
0311
0643
Points to phrase “Die Festplatte “.
0313
05E6
Points to phrase “Ist Nicht “.
0315
066D
Points to phrase “Bereit “.
0317
FFFE
Points to END OF MESSAGE.
0319
0180
Display next part at row 6, col 0.
031B
074D
Points to phrase “Unite “.
031D
0771
Points to phrase “Disque”.
031F
0781
Points to phrase “-Dur “.
0321
0787
Points to phrase “Non Prete “.
0323
FFFF
FFFFH = End of message.

0325H – Error 3 Message Storage Area.

0325
04B7
Points to phrase “The “.
0327
0530
Points to phrase “Floppy “.
0329
053D
Points to phrase “Disk “.
032B
05E2
Points to phrase “Drive “.
032D
04F9
Points to phrase “Is Not “.
032F
0550
Points to phrase “Ready “.
0331
FFFE
Points to END OF MESSAGE.
0333
00C0
Display next part of msg at row 3, col 0.
0335
05FF
Points to phrase “Disketten-Laufwerk “.
0337
05EA
Points to phrase “Nicht “.
0339
066D
Points to phrase “Bereit “.
033B
FFFE
Points to END OF MESSAGE.
033D
0180
Display next part at row 6, col 0.
033F
074D
Points to phrase “Unite “.
0341
0771
Points to phrase “Disque”.
0343
0778
Points to phrase “-Souple “.
0345
0787
Points to phrase “Non Prete “.
0347
FFFF
FFFFH = End of message.

0349H – Error 3 Message Storage Area.

0349
04B7
Points to phrase “The “.
034B
0538
Points to phrase “Hard Disk “.
034D
04E2
Points to phrase “Drive “.
034F
04F9
Points to phrase “Is Not “.
0351
0501
Points to phrase “Available “.
0353
FFFE
Points to END OF MESSAGE.
0355
00C0
Display next part of msg at row 3, col 0.
0357
0643
Points to phrase “Die Festplatte “.
0359
05E6
Points to phrase “Ist Nicht “.
035B
06F0
Points to phrase “Im System”.
035D
FFFE
Points to END OF MESSAGE.
035F
0180
Display next part at row 6, col 0.
0361
074D
Points to phrase “Unite “.
0363
0771
Points to phrase “Disque”.
0365
0781
Points to phrase “-Dur “.
0367
0700
Points to phrase “Absent”.
0369
0708
Points to phrase ” Du “.
036B
071D
Points to phrase “Systeme “.
030C
FFFF
FFFFH = End of message.

036FH – Error 3 Message Storage Area.

036F
04B7
Points to phrase “The “.
0371
0530
Points to phrase “Floppy “.
0373
053D
Points to phrase “Disk “.
0375
04E2
Points to phrase “Drive “.
0377
04F9
Points to phrase “Is Not “.
0379
0501
Points to phrase “Available “.
037B
FFFE
Points to END OF MESSAGE.
037D
00C0
Display next part of msg at row 3, col 0.
037F
05FF
Points to phrase “Disketten-Laufwerk “.
0381
05E6
Points to phrase “Ist Nicht “.
0383
06F0
Points to phrase “Im System”.
0385
FFFE
Points to END OF MESSAGE.
0387
0180
Display next part at row 6, col 0.
0389
074D
Points to phrase “Unite “.
038B
0771
Points to phrase “Disque”.
038D
0778
Points to phrase “-Souple “.
038F
0700
Points to phrase “Absent”.
0391
0708
Points to phrase ” Du “.
0393
071D
Points to phrase “Systeme “.
0395
FFFF
FFFFH = End of message.

0397H – Error 7 Message Storage Area.

0397
0557
Points to phrase “Close “.
0399
04B7
Points to phrase “The “.
039B
0530
Points to phrase “Floppy “.
039D
04E2
Points to phrase “Drive “.
039F
055E
Points to phrase “Door And Try Again “.
032E
FFFE
Points to END OF MESSAGE.
03A3
00C0
Display next part of msg at row 3, col 0.
03A5
05FF
Points to phrase “Disketten-Laufwerk “.
03A7
0675
Points to phrase “Schliessen Und Erneut Starten”.
03A9
FFFE
Points to END OF MESSAGE.
03AB
0180
Display next part at row 6, col 0.
03AD
0792
Points to phrase “Fermez Porte d`Unite Et Reessayez “.
03AF
FFFF
FFFFH = End of message.

03B1H – Error 8 Message Storage Area.

03B1
057D
Points to phrase “CRC “.
03B3
0587
Points to phrase “Error”.
03B5
058D
Points to phrase “, “.
03B7
0567
Points to phrase “Try Again “.
03B9
0590
Points to phrase “Or Use Another “.
03BB
053D
Points to phrase “Disk “.
03BD
FFFE
Points to END OF MESSAGE.
03BF
00C0
Display next part of msg at row 3, col 0.
03C1
057D
Points to phrase “CRC “.
03C3
0698
Points to phrase “Fehler, “.
03C5
06A1
Points to phrase “Neu Starten…”.
03C7
FFFE
Points to END OF MESSAGE.
03C9
0180
Display next part at row 6, col 0.
03CB
07BB
Points to phrase “Erreur “.
03CD
07B5
Points to phrase “CRC, “.
03CF
07AA
Points to phrase “Reessayez “.
03D1
075B
Points to phrase “Ou Utilisez Une Autre Disque”.
03D3
FFFF
FFFFH = End of message.

03D5H – Error 9 Message Storage Area.

03D5
0582
Points to phrase “Seek Error”.
03D7
058D
Points to phrase “, “.
03D9
0569
Points to phrase “Try Again “.
03DB
0590
Points to phrase “Or Use Another “.
03DD
053D
Points to phrase “Disk “.
03DF
FFFE
Points to END OF MESSAGE.
03E1
00C0
Display next part of msg at row 3, col 0.
03E3
06FA
Points to phrase “Such “.
03E5
0698
Points to phrase “Fehler, “.
03E7
06A1
Points to phrase “Neu Starten…”.
03E9
FFFE
Points to END OF MESSAGE.
03EB
0180
Display next part at row 6, col 0.
03ED
07BB
Points to phrase “Erreur “.
03EF
07C3
Points to phrase “De Chercher, “.
03F1
07AA
Points to phrase “Reessayez “.
03F3
075B
Points to phrase “Ou Utilisez Une Autre Disque”.
03F5
FFFF
FFFFH = End of message.

03F7H – Error 10 Message Storage Area.

03F7
04B7
Points to phrase “The “.
03F9
04C5
Points to phrase “ROM Image “.
03FB
050C
Points to phrase “Can`t Be Loaded – “.
03FD
0530
Points to phrase “Floppy “.
03FF
05ED
Points to phrase “Disk “.
0401
04E2
Points to phrase “Drive “.
0403
04F9
Points to phrase “Is Not “.
0405
0550
Points to phrase “Ready “.
0407
FFFE
Points to END OF MESSAGE.
0409
00C0
Display next part of msg at row 3, col 0.
040B
04C5
Points to phrase “ROM Image “.
040D
0613
Points to phrase “Kann “.
040F
05EA
Points to phrase “Nicht “.
0378
061D
Points to phrase “Geladen “.
0413
0653
Points to phrase “Werden “.
0415
051C
Points to phrase “- “.
0417
05FF
Points to phrase “Disketten-Laufwerk “.
0419
FFFE
Points to END OF MESSAGE.
041B
0100
Points to phrase (second line of German text).
041D
05E6
Points to phrase “Ist Nicht “.
041F
066D
Points to phrase “Bereit “.
0421
FFFE
Points to END OF MESSAGE.
0423
0180
Display next part at row 6, col 0.
0425
04C9
Points to phrase “Image “.
0427
07DD
Points to phrase “ROM “.
0429
0726
Points to phrase “Non Chargeable “.
042B
051C
Points to phrase “- “.
042D
074D
Points to phrase “Unite “.
042F
0771
Points to phrase “Disque”.
0431
0778
Points to phrase “-Souple “.
0433
0787
Points to phrase “Non Prete “.
0435
FFFF
FFFFH = End of message.

0437H – Error 11 Message Storage Area.

0437
0572
Points to phrase “Lost Data “.
0439
0587
Points to phrase “Error”.
043B
FFFF
FFFFH = End of message.

043DH – Error 12 Message Storage Area.

043D
05E2
Points to phrase “ID “.
043F
0587
Points to phrase “Error”.
0441
FFFF
FFFFH = End of message.

0443H – Message Storage Area: “ROM image loaded — press ENTER or BREAK”

0443
0000
Prompt message after loading ROM image.
0445
04B7
Points to phrase start at row 0, col 0: “The “
0447
04C5
Points to phrase “ROM Image “
0449
05A0
Points to phrase “Has Been”
044B
0514
Points to phrase ” Loaded – “
044D
05A9
Points to phrase “Switch Disks And “
044F
FFFE
Points to END OF MESSAGE.
0451
0004
(second line of message).
0453
05C7
Points to phrase “Press <ENTER> “
0455
05D6
Points to phrase “Or <Break> “
0457
0543
Points to phrase “When You Are Ready “
0459
FFFE
Points to END OF MESSAGE.
045B
00C0
Display next part of msg at row 3, col 0.
045D
04C5
Points to phrase “ROM Image “
045F
0619
Points to phrase “Ist Geladen “
0461
051C
Points to phrase “- “
0463
0626
Points to phrase “Disketten Wechseln Und Dann “
0465
05CD
Points to phrase “<ENTER> “
0467
FFFE
Points to END OF MESSAGE.
0469
0100
046B
06D7
Points to phrase “Oder “
046D
05D9
Points to phrase “<Break> “
046F
06CE
Points to phrase “Drucken “
0471
FFFE
Points to END OF MESSAGE.
0473
0180
Display next part at row 6, col 0.
0475
07D1
Points to phrase “l`Image “
0477
07DA
Points to phrase “Du ROM “
0479
07E2
Points to phrase “Chargee “
047B
051C
Points to phrase “- “
047D
07EB
Points to phrase “Changez De “
047F
0771
Points to phrase “Disque”
0481
07F7
Points to phrase ” Et Appuyez Sur “
0483
FFFE
Points to END OF MESSAGE.
0485
01C0
No Operation
0487
05CD
Points to phrase “<ENTER> “
0489
0808
Points to phrase “Ou “
048B
04D9
Points to phrase “<Break> “
03C4
080C
Points to phrase “Pour Continuer”
048F
FFFF
FFFFH = End of message.

0491H – Message Storage Area: “Loading ROM Image…”

0491
04BC
Message: ‘Loading ‘.
0493
04C5
‘ROM Image ‘.
0495
051C
‘- ‘.
0497
05BB
‘Please Wait’.
0499
FFFE
Points to END OF MESSAGE.
049B
00C0
Display next part of msg at row 3, col 0.
049D
04C5
‘ROM Image ‘.
049F
06DD
‘Wird ‘.
04A1
061D
‘Geladen ‘.
04A3
051C
‘- ‘.
04A5
06E3
‘Bitte Warten’.
04A7
FFFE
Points to END OF MESSAGE.
04A9
0180
Display next part at row 6, col 0.
04AB
081B
‘Chargement De ‘.
04AD
071D
‘l`Image ‘.
04AF
07DD
‘ROM ‘.
04B1
051C
‘- ‘.
04B3
082A
‘Veuillez Patienter ‘.
04B5
FFFF
FFFFH = End of message.
04B7
DB “The ” + 00H
04BC
DB “Loading ” + 00H
04C5
DB “ROM Image ” + 00H
04C9
DB “Image ” + 00H
04D0
DB “Was Not ” + 00H
04D9
DB “Found on Drive ” + 00H
04E2
DB “Drive ” + 00H
04E9
DB “0” + 00H
04EB
DB “Arcnet ” + 00H
04F3
DB “Boot ” + 00H
04F9
DB “Is Not ” + 00H
04FE
DB “Boot ” + 00H
0501
DB “Available ” + 00H
050C
DB “Can’t Be Loaded – ” + 00H
0514
DB ” Loaded – ” + 00H
051C
DB “- ” + 00H
051F
DB “Too Many Extents” + 00H
0530
DB “Floppy ” + 00H
0538
DB “Hard Disk ” + 00H
053D
DB “Disk ” + 00H
0543
DB “When You Are Ready ” + 00H
0550
DB “Ready ” + 00H
0557
DB “Close ” + 00H
055E
DB “Door And Try Again ” + 00H
0567
DB “Try Again ” + 00H
0572
DB “Lost Data ” + 00H
057D
DB “CRC ” + 00H
0582
DB “Seek Error” + 00H
0587
DB “Error” + 00H
058D
DB “, ” + 00H
0590
DB “Or Use Another ” + 00H
05A0
DB “Has Been” + 00H
05A9
DB “Switch Disks And ” + 00H
05BB
DB “Please Wait” + 00H
05C1
DB “- ” + 00H
05C7
DB “Press <ENTER> ” + 00H
05CD
DB “<ENTER> ” + 00H
05D6
DB “Or <Break> ” + 00H
05D9
DB “<Break> ” + 00H
05E2
DB “Drive ” + 00H
05E2
DB “ID ” + 00H
05E6
DB “Ist Nicht ” + 00H
05EA
DB “Nicht ” + 00H
05ED
DB “Disk ” + 00H
05F1
DB “Gefunden Auf ” + 00H
05FF
DB “Disketten-Laufwerk ” + 00H
0609
DB “Laufwerk ” + 00H
0613
DB “Kann ” + 00H
0619
DB “Ist Geladen ” + 00H
061D
DB “Geladen ” + 00H
0626
DB “Disketten Wechseln Und Dann ” + 00H
0643
DB “Die Festplatte ” + 00H
0653
DB “Werden ” + 00H
065B
DB “Zu Viele Bereiche” + 00H
066D
DB “Bereit ” + 00H
0675
DB “Schlie” + -4H + “sen Und Erneut Starten” + 00H
0692
DB “Durda” + 00H
0698
DB “Fehler, ” + 00H
06A1
DB “Neu Starten Oder Eine Andere Platte Benutzen” + 00H
06CE
DB “Dr” + 0AH + “cken ” + 00H
06D7
DB “Oder ” + 00H
06DD
DB “Wird ” + 00H
06E3
DB “Bitte Warten” + 00H
06F0
DB “Im System” + 00H
06FA
DB “Such ” + 00H
0700
DB “Absent” + 00H
0707
DB “e Du ” + 00H
0708
DB ” Du ” + 00H
070D
DB ” Dans l’ Unit” + 03H + ” 0″ + 00H
071C
DB “Syst” + 0CH + “me ” + 00H
0725
DB “Non Chargeable ” + 00H
0735
DB “Segments Trop Numbreux” + 00H
074C
DB “Unit” + 03H + 00H
0753
DB “Frank ” + 00H
075A
DB “Ou Utilisez Une Autre Disque” + 00H
0770
DB “Disque” + 00H
0777
DB “-Souple ” + 00H
0780
DB “-Dur ” + 00H
0786
DB “Non Pr” + 12H + “te ” + 00H
0791
DB “Fermez Porte d`Unit” + 03H + ” Et R” + 03H + “essayez ” + 00H
07B4
DB “CRC, ” + 00H
07BA
DB “Erreur ” + 00H
07C2
DB “De Chercher, ” + 00H
07D0
DB “l’Image ” + 00H
07D9
DB “Du ROM ” + 00H
07DC
DB “ROM ” + 00H
07E1
DB “Charg” + 03H + “e ” + 00H
07EA
DB “Changez De ” + 00H
07F7
DB “Et Appuyez Sur ” + 00H
0807
DB “Ou ” + 00H
080B
DB “Pour Continuer “
081A
DB “Chargement De ” + 00H
0829
DB “Veuillez Patienter ” + 00H
083B
DB ” ” + 00H

083EH – RST 30H Vector – Scan the Keyboard. On entry BC must hold the number of times to scan the keyboard.

083E
LD A,(3840H)
Load A with the memory contents of the 7th row of the keyboard address (holding ENTER, CLEAR, BREAK, arrows, SPACE).
0841
RRCA
Rotate the bits in A right copying BIT 0 to both BIT 7 and CARRY.
0842
Loop back 2 instructions until the <ENTER> key is no longer being pressed.
0844
LD A,(3801H)
Load A with the memory contents of the 1st row (Decimal: 14337) of the keyboard address (holding “@ABCDEFG”).
0847
AND FEH
MASK A with 1111 1110 to check for “ABCDEFG” (i.e., everything except “@”).
0849
If the “@” was pressed (i.e., a key on line 3801H was pressed but not “ABCDEFG”) JUMP down to 0857H
084B
LD D,0FFH
D = -1
084D
INC D
D = D + 1
084E
RRCA
Rotate the bits in A right copying BIT 0 to both BIT 7 and CARRY.
084F
Loop back to 084D until we find out which keyboard column was pressed.
0851
LD A,’@’
Load A with “@” as the character below the ASCII value of “A”.
0853
ADD A,D
A = A + D (so the keypress will be turned into ASCII for “A”-“G” representing the ROM image file selected).
0854
LD (401DH),A
Put the ASCII code in name of ROM image file into the memory location 401DH.
0857
LD A,(3840H)
Load A with the memory contents of the 7th row of the keyboard address (holding ENTER, CLEAR, BREAK, arrows, SPACE).
085A
BIT 2,A
Check BIT 2.
NOTE: BIT 2 of 3840H would be a BREAK keypress.
085C
If BREAK was NOT pressed, then skip over the next instruction.
085E
LD (405BH),A
If we are here, the BREAK key WAS pressed, so put a non-zero value into (405BH). I do not show that 405BH is ever read or used.
0861
BIT 0,A
Check BIT 2.
NOTE: BIT 2 of 3840H would be a ENTER keypress.
0863
if ENTER was pressed, then JUMP to 08B0H to exit the keyboard scan routine.
0865
LD A,(3802H)
Load A with the memory contents of the 2nd row (Decimal: 14338) of the keyboard address (holding “HIJKLMNO”).
0868
BIT 6,A
Check BIT 6.
NOTE: BIT 6 of 3802H would be a N keypress.
086A
Skip the next instruction of a N was not pressed.
086C
LD (M4064),A
If N was pressed, then store a non-zero value in 4064H.
086F
BIT 4,A
Check BIT 4.
NOTE: BIT 4 of 3802H would be a L keypress.
0871
Skip the next instruction if a L was not pressed.
0873
LD (M4066),A
If L was pressed, then store a non-zero value in 4066H.
NOTE: 4066H tracks whether L was pressed or not. It is NZ if L was pressed and zero otherwise.
0876
LD D,80H
D = 80H (Decimal: 128; Binary: 1000 0000).
NOTE: 80H and greater shows the type of boot requested.
0878
LD A,(3804H)
Load A with the memory contents of the 3rd row (Decimal: 14340) of the keyboard address (holding “PQRSTUVW”).
087B
BIT 6,A
Check BIT 6.
NOTE: BIT 6 of 3804H would be a V keypress.
087D
If V was pressed, JUMP down to 08A7 since we can’t use any other options.
087F
BIT 0,A
Check BIT 6.
NOTE: BIT 6 of 3804H would be a P keypress.
0881
Skip the next instruction if a P was not pressed
0883
LD (M4065),A
If P was pressed, then store a non-zero value in 4065H.
0886
INC D
D = D + 1 (to be 81H).
0887
INC D
D = D + 1 (to be 82H).
0888
LD A,(3880H)
Load A with the memory contents of the 8th row (Decimal: 14464) of the keyboard address (holding “LEFT SHIFT RIGHT SHIFT CONTROL CAPS F1 F2 F3“).
088B
OR A
Set the flags to see if any of those keys were hit (Z = none).
088C
If none of those special keys were pressed, JUMP down to 0894H.
088E
RRCA
Rotate the bits in A right copying BIT 0 to both BIT 7 and CARRY. This has the effect of adding the row number to D.
088F
Once the row has been added, JUMP to 08A7H.
0891
INC D
D = D + 1. This has the effect of making “LEFT SHIFT=82H, RIGHT SHIFT=83H, CONTROL=84H, CAPS=85H, F1=86H, F2=87H, and F3=88H.
0892
Loop back to 088EH.
0894
LD A,(3810H)
Load A with the memory contents of the 5th row (Decimal: 14352) of the keyboard address (holding “01234567”).
0897
LD D,86H
D = 86H
0899
BIT 1,A
Check BIT 1.
NOTE: BIT 1 of 3810H would be a 1 keypress.
089B
If 1 was pressed, JUMP to 08A7H with D=86H.
089D
INC D
D = D + 1
089E
BIT 2,A
Check BIT 2.
NOTE: BIT 1 of 3810H would be a 2 keypress.
08A0
If 1 was pressed, JUMP to 08A7H with D=87H.
08A2
INC D
D = D + 1
08A3
BIT 3,A
Check BIT 3.
NOTE: BIT 3 of 3810H would be a 3 keypress.
08A5
If 3 was NOT pressed, JUMP to 08ABH with D=88H.
08A7
LD A,D
A = D. At this point, D is 82H-88H representing the value for the boot option selected based on the key press.
08A8
LD (4059H),A
Store the boot option selected (82H-88H) into 4059H where 011DH will pick it up.
NOTE: 4059H holds the boot option selected in the form of 82H-88H.
08AB
DEC BC
BC = BC – 1.
NOTE: BC held the number of times to scan the keyboard within a RST 30H call.
08AC
LD A,B
OR C
The easiest way to test a register pair for 0 is to LOAD the LSB and then OR the MSB. Z will be set only if both were 0.
08AE
If BC hasn’t hit 0, then there are more scans to be had within the RST 30H call, so JUMP back to 0844H to take another keyboard scan.
08B0
LD A,(4059H)
If we are here, the RST 30H has taken in all the keys it was supposed to take in, so put the boot option selected into A.
NOTE: 4059H holds the boot option selected in the form of 82H-88H.
08B3
OR A
Set the flags. If no options were chosen, then Z will be set.
08B4
RET
RETURN from the RST 30H Call.

08B5H – RST 08H Vector – Disk I/O.

On entry the following settings are needed:

  • A: 1:Floppy, 2:Hard Drive, 4:RS-232
  • B:
    • 01H = Initialize and Restore
    • 04H = Restore Drive
    • 0CH = Read
    • 32H = Restore drives 1,2,3 (if possible)
    • 70H = Seek
  • C: Sector to read
  • DE: Cylinder to read (D=LSB, E=MSB)

On exit, if there was an error then NZ will be set and A will contain the error code.

08B5
DEC A
A = A – 1. This will turn a 1 into a 0 for flag purposes.
08B6
If the ZERO FLAG is set, then A was 1, which means we are working on a floppy disk, so JUMP to 096FH.
08B9
LD A,B
If we are here, then A not a 1, which means we are working on a hard disk. A = B
08BA
CP 01H
We need to figure out what we were asked to do to the hard drive. Test A against 01 (which would be “initialize and restore”).
08BC
If the command was NOT “initialize and restore”, then skip next 2 lines.
08BE
If we are here, the command was “initialize and restore” so GOSUB to 0956H to reset the HD controller board.
08C1
LD B,04H
Now that we initialized, we need to “restore”, so set B to 04H (which is “restore drive”).
08C3
LD A,C
Put the sector to read into A.
08C4
OUT (CBH),A
OUTPUT the sector (held in A, from C) to Port CBH.
NOTE: Port CBH is Register 3 for WD1010 Winchester Disk Controller Chip which is the Hard Disk Sector Number Register.
08C6
IN A,(CBH)
Poll Port CBH and put the results into A.
NOTE: Port CBH is Register 3 for WD1010 Winchester Disk Controller Chip which is the Hard Disk Sector Number Register.
08C8
CP C
Compare A vs C. They SHOULD be identical. If they are not identical then there is a problem, which will be interpreted to mean no Hard Drive is attached.
08C9
LD A,05H
Load A with code 05H which means “Hard Drive Not Available”.
08CB
If A was not equal to C then JUMP to 08EEH to display the error associated with A = 05H.
08CD
XOR A
If we are here, then we have a hard drive, so zero A and clear the flags.
NOTE: A = 0 means Drive 1, Head 0, 256-byte sectors.
08CE
OUT (CEH),A
OUTPUT the contents of A to Port CEH.
NOTE: Port CEH is Register 6 for WD1010 Winchester Disk Controller Chip which is the register contaning Hard Disk Sector Size / Drive # / Head # as follows:
  • Bits 0-2: Head Number (0-7)
  • Bits 3-4: Drive Number (00=#1, 01=#2, 10=#3, 11=#4)
  • Bits 5-6: Sector Size (00=256, 01=512, 10=1024, 11=128)
  • Bit 7: Extension (if this is set, Error Checking and Correction codes are in use and the R/W data [sector length + 7 bytes] do not check or generate CRC)
08D0
LD A,D
A = D. D contains the LSB of the cylinder to read.
08D1
OUT (CDH),A
OUTPUT the LSB of the cylinder to ready (held in A, from D) to Port CDH.
NOTE: Port CDH is Register 5 for WD1010 Winchester Disk Controller Chip which is the Hard Disk Cylinder LSB.
08D3
LD A,E
A = D. D contains the MSB of the cylinder to read.
08D4
OUT (CCH),A
OUTPUT the contents of A to Port CCH.
NOTE: Port CCH is Register 4 for WD1010 Winchester Disk Controller Chip which is the Hard Disk Cylinder MSB.
08D6
PUSH BC
Save the FUNCTION and SECTOR to the STACK.

08D7H – Inside the RST 08H Routine. Check for DRIVE READY from the hard drive 524,280 times.

08D7
LD D,08H
D = 8. D will act as the counter for the OUTER loop.
08D9
LD BC,0000H
BC = 0. BC will act as the counter or the INNER loop.
08DC
IN A,(CFH)
Poll Port CFH and put the result into A.
NOTE: Port CCH is Register 7 for WD1010 Winchester Disk Controller Chip and is the Hard Disk Error Status Register when used for INPut.
08DE
BIT 6,A
Check Bit 6 of the Hard Driver Error Code.
NOTE: Bit 6 is “drive ready”.
08E0
If the drive is READY, JUMP to 08F0H.
08E2
DEC BC
If we are here, the drive was not READY, so BC = BC – 1
08E3
LD A,B
OR C
Test BC for 0.
08E5
If BC is not zero, then loop back to 08DC and keep polling the drive for a “drive ready” status.
08E7
DEC D
D = D – 1.
08E8
If D is not zero, then LOOP back to 08D9H.
08EA
POP BC
If we are here, a loop of 8 x 65,535 counted down without a drive ready, so restore BC from the STACK.
08EB
LD D,03H
Load D with code 03H which means “Hard Drive Not Ready”.
08ED
LD A,D
Put the error code from D into A.
08EE
OR A
Set the flags (including setting NZ to indicate that an error is present).
08EF
RET
RETURN out of the RST 08H.

08F0H – Inside the RST 08H Routine. We have DRIVE READY.

08F0
POP BC
Restore BC from the STACK. B will hold the function, and C will hold the sector number.
08F1
LD A,B
A = B (so that the function is now in A).
08F2
LD D,16H
D = 16H.
NOTE: 16H is the WDC “restore” command.
08F4
CP 04H
Compare A (the function) against 04H.
NOTE: 04H is the RESTORE DRIVE command.
08F6
If A = 04H then JUMP to 08FAH to handle the RESTORE DRIVE function.
08F8
LD D,70H
D = 70H.
NOTE: 70H is the WDC “SEEK” command.

08FAH – Inside the RST 08H Routine. Process a RESTORE DRIVE function.

08FA
LD A,D
A = D. A could be 16H for RESTORE or 70H for SEEK.
08FB
OUT CFH,A
OUTput A to Port CFH.
NOTE: Port CCH is Register 7 for WD1010 Winchester Disk Controller Chip and is the Hard Disk Error Command Register when used for OUTput. 70H is “Seek with a 35 milisecond stepping rate”. 16H is “Restore with a 3 milisecond stepping rate”
08FD
GOSUB to 0962H to wait until the drive is not busy, the seek is complete, and to put NZ if there are errors and Z if there are none.
0900
If there are no errors, JUMP down to 0935H.
0902
LD A,B
If we are here, then there were errors. Load the function (held in B) into A again.
0903
CP 0CH
Compare the function to 0CH.
0905
If the function wasn’t “READ SECTOR” then JUMP to 0933H to clear A and all flags, and RETURN.
0907
LD A,20H
If the function WAS “READ SECTOR” then load A with 20H (Binary: 0010 0000) which is the command to “READ SINGLE SECTOR with interrupt when data request line is enabled”.
0909
LD E,00H
E = 00H. E will be the counter for sector length.
090B
OUT CFH,A
OUTput the 20H command out to Port CFH (the Hard Disk Error Command Register).
090D
GOSUB to 0962 to wait until the drive is not busy, the seek is complete, and to put NZ if there are errors and Z if there are none.
0910
If there are no errors, JUMP to 092DH.
0912
LD D,C
If we are here, then the READ SECTOR command generated an error. Save the sector number (held in C) into D.
0913
GOSUB to 094C to poll the Hard Drive Register, with the result in Register C.
0916
BIT 4,C
Test Bit 4 of Register C.
NOTE: Bit 4 is “ID NOT FOUND”. It is considered a soft error.
0918
If Bit 4 was off, then we have a more serious error, so JUMP to 0938H. Otherwise, let us see if this is a 512-byte sector.
091A
LD A,20H
A = 20H (Binary: 0010 0000).
NOTE: This binary pattern selects HEAD 0, DRIVE 0, 512-byte SECTOR SIZE).
091C
OUT (CEH),A
OUTPUT the contents of A to Port CEH.
NOTE: Port CEH is Register 6 for WD1010 Winchester Disk Controller Chip which is the register contaning Hard Disk Sector Size / Drive # / Head # as follows:
  • Bits 0-2: Head Number (0-7)
  • Bits 3-4: Drive Number (00=DSEL1, 01=DSEL2, 10=DSEL3, 11=DSEL 4)
  • Bits 5-6: Sector Size (00=256, 01=512, 10=1024, 11=128)
  • Bit 7: Extension (if this is set, Error Checking and Correction codes are in use and the R/W data [sector length + 7 bytes] do not check or generate CRC)
091E
LD A,D
Load A with the sector number which was saved into D.
091F
OUT (CBH),A
OUTPUT the sector (held in A, from C) to Port CBH.
NOTE: Port CBH is Register 3 for WD1010 Winchester Disk Controller Chip which is the Hard Disk Sector Number Register.
0921
LD A,20H
A = 20H (Binary: 0010 0000).
NOTE: This binary pattern is the command to “READ SINGLE SECTOR with interrupt when data request line is enabled”.
0923
OUT CFH,A
OUTput the 20H command out to Port CFH (the Hard Disk Error Command Register).
0925
GOSUB to 0962 to wait until the drive is not busy, the seek is complete, and to put NZ if there are errors and Z if there are none.
0928
If there are errors, JUMP to 0935H.
092A
If there are no errors, then we have a 512-byte sector, so we need to get 256 bytes twice.
092D
LD BC,00C8H
B = 00 (as byte counter) and C=C8H (the Hard Disk Data Register port).
0930
INIR
Get 256 bytes from WDC sector buffer.
0932
INC E
E = E + 1 (E is the MSB of the byte counter).
0933
XOR A
Indicate no errors.
0934
RET
RETURN out of RST 08H.

0935H – Inside the RST 08H Routine. If we are here then there were no errors from the wait-until-ready CALL at 0962H.

0935
GOSUB to 094C to poll the Hard Drive Register, with the results in Registers C and A.
0938
LD D,08H
D = 08H (Binary: 0000 1000). When reading from Port F0H, 08H is a CRC Error.
093A
BIT 6,A
Test Bit 6 of A.
NOTE: Bit 6 when read from the ERROR REGISTER at Port C9H signals a CRC ERROR in the DATA FIELD.
093C
If the error was a “CRC – Data Field” error, JUMP to 08EDH.
093E
BIT 5,A
Test Bit 5 of A.
NOTE: Bit 5 when read from the ERROR REGISTER at Port C9H signals a CRC ERROR in the ID FIELD.
0940
If the error was a “CRC – ID Field” error, JUMP to 08EDH.
0942
LD D,0CH
D = 0CH to indicate an ID ERROR.
0944
BIT 4,A
Test Bit 4 of A.
NOTE: Bit 4 when read from the ERROR REGISTER at Port C9H signals a ID NOT FOUND error.
0946
If the error was “ID NOT FOUND” then JUMP to 08EDH.
0948
LD D,09H
D = 09H to indicate a SEEK ERROR.
094A
JUMP to 08EDH

094CH – Inside the RST 08H Routine. Poll the WDC error register, results into C (and A).

094C
BIT 1,A
Check Bit 1 of A.
NOTE: Bit 1 when read from Port Port CFH (Hard Disk Error Status Register) means “COMMAND IN PROGRESS”.
094E
LD B,A
B = A
094F
If Bit 1 was high, then there is a command in process when there shouldn’t be one, so GOSUB to 0959H to reset the HD controller board.
0952
IN A,0C9H
Poll Port C9H and put the results into A.
NOTE: Port C9H is Register 1 for WD1010 Winchester Disk Controller Chip which, on input, is the ERROR REGISTER
  • Bit 0: DAM Not Found
  • Bit 1: Track 0 Error
  • Bit 2: Aborted Command
  • Bit 4: ID Not Found
  • Bit 5: CRC Error-ID Field
  • Bit 6: CRC Error-Data Field
  • Bit 7: Bad Block Detected
0954
LD C,A
Put that error code into C.
0955
RET
RETURN

0956H – Inside the RST 08H Routine. Reset the HD controller board.

0956
XOR A
Zero A and clear all flags
0957
OUT (C1H),A
OUTput a 0 to Port C1H.
NOTE: Port C1H is the hard drive controller board control register. Sending a 0 resets the hard drive controller board.
0959
LD A,10H
A = 10H (Binary: 0001 0000)
095B
OUT (C1H),A
OUTput a 10H (i.e., Bit 4 is high) to Port C1H to reset the controller board.
095D
LD A,0CH
A = 0CH (Binary: 0000 1100)
095F
OUT (C1H),A
OUTput a 0CH (i.e., Bit 3 is high) to Port C1H to enable the controller board.
0961
RET
RETURN

0962H – Inside the RST 08H Routine. This is a subroutine to wait until drive not busy and seek complete. On exit A will contain the value of the Hard Disk Error Status Register.

0962
IN A,(CFH)
Poll Port CFH and put the result into A.
NOTE: Port CCH is Register 7 for WD1010 Winchester Disk Controller Chip and is the Hard Disk Error Status Register when used for INPut.
0964
BIT 7,A
Test Bit 7 of A. Bit 7 high means the drive is BUSY.
0966
If the drive is busy, then loop back 2 instructions and poll again.
0968
BIT 4,A
If we are here, then the drive is no longer busy. Test Bit 4 of A. Bit 4 high means SEEKS COMPLETE.
096A
If the seek is not complete, loop back to the top of the routine and start again.
096C
BIT 0,A
If we are here then the drive is not busy and the seek is complete. Test Bit 0 of A. Bit 0 high means there is an error. This sets NZ if there is an error and Z if there is no error.
096E
RET
RETURN

096FH – Inside the RST 08H Routine. This is the subroutine to send the commands to the floppy drive.

096F
LD A,D0H
A = D0H.
0971
OUT F0H,A
OUTput D0H (Binary: 1101 0000) to Port F0H.
NOTE: Port F0H is the Floppy Disk Command/Status Register. 1101 0000 is the command to FORCE INTERRUPT (1101) and TERMINATE WITH NO INTERRUPT (0000). This resets the FDC.
0973
GOSUB to 0A58 to cause a 800 millisecond delay.
0976
LD A,81H
A = 81H (Binary: 10000001). Although explained in further detail below, this is Drive 0 Select (Bit 0 high), Side 0 Select (Bit 4 low), Double Density (Bit 7 high).
0978
OUT (F4H),A
OUTput 81H (Binary: 10000001) 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)
097A
LD A,C
A = C (C should hold the sector on entry to RST 08H).
097B
OUT (F2H),A
OUTput Register A to Port F2H.
NOTE: Port F2H is the Floppy Disk Sector Register.
097D
LD A,B
A = B (B should hold the function on entry to RST 08H).
097E
CP 05H
Compare the function held in A against 05H to make sure it is greater than 4.
0980
If the function is greater than 4, JUMP to 09A2H to handle those responses.

096FH – Inside the RST 08H Routine Subroutine to send the commands to the floppy drive – If we are here, then the function passed is greater than 4 leaving it to mean “RESTORE”.

0982
LD A,0CH
A = 0CH. This is the command to Restore — verify track, 6 ms step.
0984
OUT F0H,A
OUTput 0CH (Binary: 0000 1100) to Port F0H.
NOTE: Port F0H is the Floppy Disk Command/Status Register. 0000 1100 is the command to RESTORE (0000) with the options of load head at beginning (1), verify on destination track (1), 6 ms stepping rate (00).
0986
GOSUB to 0A64H to wait until the floppy drive is not busy or not ready and put status in C and A.
0989
LD B,A
B = A (save the status)
098A
AND DFH
AND against 1101 1111 to ignore bit 5 (“head loaded”).
098C
CP 81H
Compare the MASKed Register A against 81H (Binary: 1000 0001) to test for “NOT READY” (Bit 7) and “BUSY” (Bit 0).
098E
If we have NOT READY and BUSY, the JUMP to 09E2 to set up for a “SEEK ERROR” and process that error.
0990
LD A,C
A = C (to get the Floppy Status before the NOT READY).
0991
AND 9EH
MASK A against 9EH (Binary: 1001 1110) to check only bits 1 (Index/DRQ), 2 (Track 0/Data Lost), 3 (CRC Error), 4 (Seek Error/Record Not Found), and 7 (Not Ready). This leaves us with a ZERO if the drive is READY, NOT TRACK 0, and NO INDEX.
0993
LD D,06H
D = 06H which is the error “Floppy Drive Not Available”.
0995
If we have READY, NOT TRACK 0, and NO INDEX then the floppy drive is not available.
0997
LD D,04H
D = 04H which is the error “Floppy Drive Not Ready”.
0999
CP 06H
Compare A against 06H (Binary: 0000 0110) to see if Bit 1 (Index) is high. If we are here and INDEX is high, there is no disk in the drive.
099B
If so, then the drive is not ready and JUMP to 099FH
099D
LD D,07H
If we are here, then there was no INDEX and that would be because the disk is not turning (i.e., the door is open), so D = 07H for “Door Open”.
099F
LD A,D
A = D (D has the error code)
09A0
OR A
Set the flags (so NZ would mean there is an error).
09A1
RET
RETURN out of RST 08H.

09A2AH – Inside the RST 08H Routine. The RST 08H call was for a FLOPPY DRIVE and the command function was greater than 4. A holds the RST 08H function requested.

09A2
CP 32H
Check A against 32H (Binary: 0011 0010) which is “RESTORE ALL”.
09A4
If the requested function was not “RESTORE ALL” then JUMP to 09CDH to process a SEEK or READ SECTOR command.
09A6
LD B,03H
If we are here, then the command was RESTORE ALL so set B for 03H (the number of drives).
09A8
LD D,02H
D = 02H to select drive :1
09AA
LD A,D0H
A = D0H for TERMINATE COMMAND WITHOUT INTERRUPT.
09AC
OUT F0H,A
OUTput D0H (Binary: 1101 0000) to Port F0H.
NOTE: Port F0H is the Floppy Disk Command/Status Register. 1101 0000 is the command to FORCE INTERRUPT (1101) and TERMINATE WITH NO INTERRUPT (0000). This resets the FDC.
09AE
GOSUB to 0A58 to cause a 800 millisecond delay.
09B1
LD A,D
A = D (the select drive value)
09B2
OUT (F4H),A
OUTput 02H (Binary: 0000 0010) 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)
09B4
RLCA
Rotate one bit to the left (which will change BIT 1 high to BIT 2 high), selecting the next drive.
09B5
LD D,A
D = A
09B6
IN A,(F0H)
INput from Port F0H.
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
09B8
AND 20H
MASK A against 20H (Binary: 0010 0000) so that only BIT 5 (Head Loaded) is live.
09BA
If the head is not loaded, then JUPM to 09CAH to skip to the next floppy drive.
09BC
XOR A
If we are here, then head is loaded. Zero A and clear all flags.
09BD
OUT F0H,A
OUTput 00H (Binary: 0000 0000) to Port F0H.
NOTE: Port F0H is the Floppy Disk Command/Status Register. 0000 0000 is the command to RESTORE (0000), unload head (0), no verify (0), 6 ms stepping rate (00).
09BF
GOSUB to 0A5DH to cause a 60 millisecond delay.
09C2
IN A,(F0H)
INput from Port F0H.
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
09C4
XOR 01H
XOR A against 01H (Binary: 0000 0001) to flip Bit 1 (the “BUSY” bit).
09C6
AND 05H
MASK A against 05H (Binary: 0000 0101) to keep only Bits 0 (BUSY if high) and 2 (TRACK 0 if high).
09C8
If the floppy drive controller reports that a command is in progress (BUSY) and that it is not on track zero, then LOOP back to 09C2 until its done.
09CA
LOOP back to 09AAH for drives :2 and :3
09CC
RET
RETURN out of RST 08H.

09CDH – Inside the RST 08H Routine. The RST 08H call was for a FLOPPY DRIVE and the command function was to SEEK or READ SECTOR.

09CD
LD A,E
A = E (E holds the cylinder to read from the RST 08H call).
09CE
OUT F3H,A
Output the cylinder to Port F3H.
NOTE: Port F3H is fhe FDC Data Register and will supply it with the destination to seek.
09D0
LD A,1CH
A = 1CH (Binary: 0001 1100).
09D2
OUT (F0H),A
OUTput 1CH (Binary: 0001 1100) to Port F0H.
NOTE: Port F0H is the Floppy Disk Command/Status Register. 0001 1100 is the command to SEEK (0001), load head at beginning (1), verify on destination track (1), 6 ms stepping rate (00).
09D4
GOSUB to 0A64H to wait until the floppy drive is not busy or not ready and put status from Port F0H in C and A.
NOTE: Port F0H is the FDC Status port on input. Input Results:
  • Bit 0 (01H): Busy
  • Bit 1 (02H): Index/DRQ
  • Bit 2 (04H): Track 0/Data Lost
  • Bit 3 (08H): CRC error
  • Bit 4 (10H): Seek error/Record not found
  • Bit 5 (20H): If Reading, Record Type, if Writing, Write Fault/Head loaded
  • Bit 6 (40H): Write Protect
  • Bit 7 (80H): Not ready
09D7
LD D,A
Save the STATUS into Register D.
09D8
AND 98H
MASK the STATUS against 98H (Binary: 1001 1000) to keep only bits 3 (CRC error), 4 (Seek error), and 7 (Not ready).
09DA
If NZ is set, then at least one of NOT READY, SEEK ERROR, or CRC ERROR was set, so do not try to read the sector. Instead JUMP to 09E1 to put the floppy disk controller status into Register B and then process a “SEEK ERROR.”
09DC
LD A,B
A = B (B holds the function requested in the RST 08H call).
09DD
CP 0CH
Compare the function against 0CH (which is READ SECTOR).
09DF
If the command was READ SECTOR, then JUMP to 0A00H.

09E1H – Inside the RST 08H Routine. Put the floppy disk controller status into B and then set up for a “SEEK ERROR” error.

09E1
LD B,D
B = D (D held the floppy disk controller status).

096FH – Inside the RST 08H Routine. This will set up for a “SEEK ERROR” error.

09E2
LD D,09H
D = 09H. 09H will be “Seek Error”.
09E4
JUMP to 09EEH (Continue with error routine.
09E6
LD D,0BH
D = 0BH. 0BH will be “Lost Data”.
09E8
BIT 2,B
Test Bit 2 of B to see if we lost any data.
09EA
If we did lose data, JUMP to 099FH (which is just a RETURN) with the error in A and NZ set.
09EC
LD D,0CH
D = 0CH. 0CH will be “ID Error”.

09EEHH – Inside the RST 08H Routine. This is the error routine for a floppy disk error.

09EE
BIT 4,B
Test Bit 4 of B to see if “RECORD NOT FOUND”.
09F0
If “RECORD NOT FOUND”, the JUMP back to 099F holding the error of “SEEK ERROR” if the command was seek and “ID ERROR” if the command was read.
09F2
LD D,08H
D = 08H. 08H will be “CRC ERROR”.
09F4
BIT 3,B
Test Bit 4 of B to see if “CRC ERROR”.
09F6
If we have a “CRC ERROR” then JUMP to 099FH (which is just a RETURN) with the error in A and NZ set.
09F8
LD D,04H
D = 04H. 04H will be “FLOPPY DRIVE NOT READY”.
09FA
BIT 7,B
Test Bit 4 of B to see if “FLOPPY DRIVE NOT READY”.
09FC
If “FLOPPY DRIVE NOT READY”, then JUMP to 099FH (which is just a RETURN) with the error in A and NZ set.
09FE
XOR A
If we are here, then there were no errors so zero A and clear all flags.
09FF
RET
RETURN

0A00HH – Inside the RST 08H Routine. The RST 08H call was for FLOPPY DRIVE and the command was READ SECTOR.

0A00
LD A,(405CH)
A = the memory contents of 405CH.
NOTE: 405CH holds the lowest sector number and should be either 0 or 1.
0A03
LD B,A
B = A (lowest sector number)
0A04
LD D,81H
D = 81H (Binary: 1000 0001) which would be DRIVE 0 (Bit 0 High), SIDE 0 (Bit 4 low), and DOUBLE DENSITY (Bit 7 High)
0A06
LD C,86H
C = 86H (Binary: 1000 0110) which would be READ SECTOR and COMPARE FOR SIDE 0.
0A08
IN A,F2H
INput the results of Port F2H into A.
NOTE: Port F2H is the Floppy Drive Controller Sector Register (i.e., the sector to read).
0A0A
CP 12H
Compare A (the sector to read) against 12H (Decimal: 18) to make sure the sector number is less than 18.
0A0C
If the sector number is less than 18, then this must be a SINGLE SIDED disk, so JUMP to 0A14H.
0A0E
SUB 12H
If we are here, then it is a DOUBLE SIDED disk, so subtract 12H (Decimal: 18) from the sector number.
0A10
SET 4,D
Set Bit 4 of D. This will set the drive select to SIDE 1.
0A12
SET 3,C
Set Bit 3 of C. This will set the Floppy Disk Controller to COMPARE FOR SIDE 1.

0A14HH – Inside the RST 08H Routine. The RST 08H call was for FLOPPY DRIVE and the command was READ SECTOR but the SECTOR NUMBER is less than 18.

0A14
ADD A,B
Add 1 to A if it is a TRSDOS 1.3 disk.
0A15
OUT (F2H),A
OUTput Register A to Port F2H to select the sector number (1 for TRSDOS 1.3, 0 for everything else).
NOTE: Port F2H is the Floppy Disk Sector Register.
0A17
LD A,D
A = D (D was holding the drive select value).
0A18
OUT (F4H),A
OUTput D (which was holding the drive select value) 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)
0A1A
LD B,00H
B = 0. B will be the LSB of the counter for the number of bytes read.
0A1C
LD E,B
E = B = 0. E will be the MSB of the counter for the number of bytes read.
0A1D
LD A,C
A = C (C was holding the command passed upon entry to the RST 08H function).
0A1E
LD C,F3H
C = F3H (the Floppy Drive Controller Data Register; needed for an INI call).
0A20
OUT F0H,A
Send the command held in A to port F0H.
NOTE: Port F0H is the Floppy Disk Controller Command/Status Port.
0A22
LD A,80H
A = 80H (Binary: 1000 0000). Sending a Bit 7 High to E4 will enable INTRQ Interrupts.
0A24
OUT (E4H),A
Send a 80H to Port E4H.
NOTE: Port E4H is the Non-Maskable Interrupt Latch.
0A26
GOSUB to 0A5DH to cause a 60 millisecond delay.
0A29
LD A,D
A = D (D was holding the drive select value).
0A2A
OUT (F4H),A
OUTput Register D 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)
0A2C
IN A,(F0H)
INput from Port F0H.
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
0A2E
BIT 1,A
Test Bit 1 to see if the Floppy Disk Controller has data.
0A30
If Bit 1 is NOT ZERO, then we have data, so skip the next 3 instructions and jump to 0A39H.
0A33
RLCA
Rotate the bits in A left (with Bit 7 going into both the CARRY and Bit 0). This will double as a test of Bit 7 since that is now sitting in the CARRY.
0A34
If Bit 7 is low, then the drive is not NOT READY (i.e., the drive is ready) so JUMP back to 0A2C to wait for the DRQ.
0A37
If Bit 7 is not low, then we have an error, so JUMP to 0A4D to clean up and return.

0A39H – Inside the RST 08H Routine. The RST 08H call was for FLOPPY DRIVE and the command was READ SECTOR, and the Floppy Controller Indicated it has Data.

0A39
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 � 1 = 0; otherwise it is reset.
0A3B
LD A,D
A = D (D was holding the drive select value).
0A3C
OR 40H
OR A against 40H (Binary: 0100 0000) to turn on Bit 6 thus enabling “Wait State Generation”.
0A3E
OUT (F4H),A
OUTput Bit 6 High 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)
0A40
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 � 1 = 0; otherwise it is reset.
0A42
If we do not yet have 256 bytes (because B’s status didn’t trigger Z), JUMP to 0A3E to get next one.
0A44
INC E
If we are here then we have hit 256 bytes, so we need to increase the MSB (the LSB will zero itself on the next rotation) so … E = E + 1 to increase the MSB of the byte counter.
0A45
JUMP to 0A3EH and keep going until NMI.

0A48HH – Inside the RST 08H Routine. This is the NMI Jump Location.

0A48
POP IY
If we are here then the NMI triggered, so toss the return address held in IY.
0A4A
XOR A
Zero A and clear all registers
0A4B
OUT (E4H),A
Stop all NMI’s so send a 0 to Port E4H.
NOTE: Port E4H is the Non-Maskable Interrupt Latch. Sending a 0 to E4 will turn off all Non-Maskable Interrupts.

0A4DHH – Inside the RST 08H Routine. Clean Up and RETurn out of the RST 18H

0A4D
IN A,(F0H)
INput from Port F0H.
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
0A4F
LD B,A
Put the Floppy Drive Controller status into B.
0A50
LD C,B
Put the Floppy Drive Controller status into B.
0A51
GOSUB to 0A56H to call a RETN (return from nonmaskable interrupt) and return to next line.
0A54
JUMP to 09E6 to set the error code and return from the RST 08H.
0A56
RETN
Return from nonmaskable interrupt.

0A58H / 0A5DH – Delay Routines After Sending a Command to the Floppy Disk Controller

0A58H – General routine in RST 08H to delay for 800 milliseconds after sending a command to the Floppy Drive Controller.

0A58
PUSH BC
Save BC to the STACK.
0A59
LD B,00H
B = 00H (a delay of about 800 milliseconds).
0A5B
JUMP to 0A60H to continue.

0A5DH – General routine in RST 08H to delay for 60 milliseconds after sending a command to the Floppy Drive Controller.

0A5D
PUSH BC
Save BC to the STACK.
0A5E
LD B,12H
B = 12H (a delay of about 60 milliseconds).
0A60
LOOP back to 0A60H until B is zero.
0A62
POP BC
Restore BC from the STACK.
0A63
RET
RETURN

0A64H – Routine to wait until the floppy drive is not busy and not ready.

0A64
GOSUB to 0A5DH to cause a 60 millisecond delay.
0A67
IN A,(F0H)
INput from Port F0H.
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
0A69
BIT 0,A
Test Bit 0 of A. If Bit 0 is high the drive is busy, and if its low the drive is NOT busy.
0A6B
RET Z
If the drive is NOT BUSY then RETURN.
0A6C
BIT 7,A
Test Bit 7 of A. If Bit 7 is high the drive is NOT READY, and if its low the drive is READY.
0A6E
RET NZ
If the drive is NOT READY then RETURN.
0A6F
LD C,A
If we are here then the drive is BUSY and READY, so C = A to save the Floppy Disk Controller Status.
0A70
Loop back to 0A67H until the drive is not busy or not ready.

0A72H – Load the Model%/III ROM image from floppy disk.

0A72
LD A,(M4067)
A = the memory contents of 4067H.
NOTE: 4067H holds the error code from a “floppy restore” command.
0A75
OR A
Set the flags from the floppy drive restore command to check for errors (Z = no errors).
0A76
If there was an error from the floppy drive restore command, JUMP to 0AD8H
0A78
LD A,01H
A = 1 (for sector 1)
0A7A
LD E,00H
E = 0 (for cylinder 0)
0A7C
GOSUB to 0C0BH to read cylinder E, sector A into the sector buffer at 4300H.
NOTE: 4300H is the address of the buffer for the sector data read.
0A7F
If there are errors from reading it into sector buffer, JUMP down to 0AD8H.
0A81
LD A,E
A = E (E holds the length of the sector we just read).
0A82
CP 01H
Compare A against 01H (Binary: 0000 0001). It will be 1 if the length is 256 bytes and will be 2 if the length is 512 bytes.
0A84
If the length is not 256 bytes then JUMP down to 0A8EH to set up for a ROM IMAGE NOT FOUND error.
0A86
LD A,(4300H)
A = the memory contents of (4300H) which is the first byte of the sector.
NOTE: 4300H is the address of the buffer for the sector data read.
0A89
OR A
Set the flags. Z should set for 5.x/6.x disks.
0A8A
If Z is set (meaning we have 5.x/6.x disks) then skip the next 3 instructions to skip setting the variables for a TRSDOS v1.3 disk and the resulting ROM IMAGE NOT FOUND error.
0A8C
CP 0FEH
If we do not have 5.x/6.x disks, see if that byte is FEH (which would mean it is a TRSDOS 1.3 disk)

0A8EH – Inside the LOAD MODEL%/III ROM IMAGE FROM FLOPPY routine. If we are here, the ROM image was needed, but not found.

0A8E
LD A,00H
If we are here then we have a “ROM Image Not Found” situation so A=0.
0A90
RET NZ
If we have any disk other than TRSDOS v1.3, return with an error.

0A91H – Inside the LOAD MODEL%/III ROM IMAGE FROM FLOPPY routine. If we are here, then we have a 5.x/6.x or TRSDOS 1.3 DOS.

0A91
LD A,C
A = C (C held the Floppy Disk Controller status from the READ SECTOR routine).
0A92
AND 20H
MASK A against 20H (Binary: 0010 0000) to set up to get the record type (Data Address Mark). A NZ here would indicate a “deleted” DAM and would thus indicate we have a TRSDOS 1.3 disk.
0A94
LD C,01H
C = 1 (as we are assuming TRSDOS 1.3, so the first sector would be 1).
0A96
LD B,03H
B = 3 (as there are three sectors per granule).
0A98
LD HL,(4301H)
HL = Bytes 01 and 02 from the boot sector.
0A9B
LD A,L
A = L (Byte 1 of the boot sector holds the directory cylendar, so store that into A).
0A9C
If we have a “deleted” DAM (TRSDOS 1.3 disk) skip the next 3 instructions to 0AA2H.
0A9E
LD A,H
If we are here, then we have a 5.x/6.x disk, so A = H (because the directory cylinder for 5.x/6.x disks is in Byte 02 instead of Byte 01).
0A9F
DEC C
If we are here, then we have a 5.x/6.x disk, so we also need to set the lowest sector number to 0 (it was 1 above).
0AA0
LD B,06H
If we are here, then we have a 5.x/6.x disk, so we also need to set B to 6 as there are 6 sectors per granule.

0AA2H – Inside the LOAD MODEL%/III ROM IMAGE FROM FLOPPY routine. If we are here, then we have a 5.x/6.x or TRSDOS 1.3 DOS and have properly set C as the first sector on a track, B as the numer of sectors per granule, and A holds the directory cylinder.

0AA2
LD (405DH),A
Store the directory cylinder (held in A) into (405DH).
NOTE: 405DH holds the directory cylinder.
0AA5
LD E,A
E = A (so now E holds the directory cylinder).
0AA6
LD A,B
A = B (so now A holds the number of sectors per granule).
0AA7
LD (M4063),A
Store the number of sectors per granule (held in A) into (4063H).
NOTE: 4063H holds the number of sectors per granule.
0AAA
LD A,C
A = C (so now A holds the lowest sector number per track).
0AAB
LD (405CH),A
Store the lowest sector number per track (held in A) into (405CH).
NOTE: 405CH holds the lowest sector number per track.
0AAE
LD A,(405CH)
A = lowest sector number per track.
0AB1
OR A
Set the flags. Only TRSDOS 1.3 has a 1 here so NZ = TRSDOS 1.3.
0AB2
If its not zero, then we have TRSDOS v1.3 (which is always single-sided) so JUMP to 0AC4H.
0AB4
XOR A
Zero A and clear all flags, since we know that it is a 5.x/6.x disk.
0AB5
GOSUB to 0C0BH to read cylinder E, sector A into the sector buffer at 4300H (in this case, the Granule Allocation Table held at Sector 0 of the Directory Cylinder).
0AB8
If there are any errors from the 0C0BH read command, JUMP to 0AD8H.
0ABA
LD A,(43CDH)
A = the memory contents of (43CDH).
NOTE: 43CDH holds the configuration byte (GAT+x’CD’).
0ABD
AND 20H
MASK the configuration byte with 0010 0000 to isolate the number of sides.
0ABF
LD A,01H
A = 01 (for single-sided).
0AC1
If the MASK indicated single sided then skip the next instruction and JUMP to 0AC4H
0AC3
INC A
If we are here, the disk is two-sided so A = A + 1 (so A=2).

0AC4H – Inside the LOAD MODEL%/III ROM IMAGE FROM FLOPPY routine. If we are here, A holds the number of sides.

0AC4
LD (405FH),A
Store the number of sides (held in A) into (405FH).
NOTE: 405FH holds the number of sides.
0AC7
LD A,02H
A = 02H (to indicate sector 2 of the directory).
0AC9
LD (405EH),A
Store 02H into the memory location held at (405EH).
NOTE: 405EH holds the next sector to read.
0ACC
LD HL,(405DH)
HL = the memory contents of (405DH).
NOTE: 405DH holds the directory cylinder and 405EH is the sector number to read.
0ACF
LD E,L
E = the directory cylinder to read.
0AD0
LD A,H
A = the sector number to read.
0AD1
GOSUB to 0C0BH to read cylinder E, sector A into the sector buffer at 4300H.
NOTE: 4300H is the address of the buffer for the sector data read.
0AD4
LD A,00H
A = 00H to prepare for “ROM Image Not Found”.
0AD6
If there are no errors, skip the rest of this routine and JUMP to 0AE0H.

0AD8H – Inside the LOAD MODEL%/III ROM IMAGE FROM FLOPPY routine. If we are here, there was an error from the floppy read/restore command. A will hold the assigned error number.

0AD8
CP 04H
Compare A against 04H (Binary: 0000 0100) to denote “Floppy Drive Not Ready” while loading a ROM image.
0ADA
If that is not the case, JUMP down to ADFH.
0ADC
LD A,0AH
If that IS the case, change the error to “Can’t Load Image – Not Ready”.
0ADE
OR A
Set the flags. Z will be “Image Not Found”).
0ADF
RET
RETURN

0AE0H – Inside the LOAD MODEL%/III ROM IMAGE FROM FLOPPY routine. If we are here, there were NO errors, so let’s search the directory for the MODEL%/III file.

0AE0
LD IX,4300H
IX = 4300H.
NOTE: 4300H is the address of the buffer for the sector data read.
0AE4
LD A,(IX+00H)
A = the first byte at 4300H
0AE7
BIT 7,A
Check Bit 7 of A to see if this is an extended directory record. It will be NZ if this is an extended directory record.
0AE9
If it is an extended directory record, JUMP down to 0B11H to skip it.
0AEB
BIT 4,A
Check Bit 4 of A to see if the record is in use.
0AED
If the record is not in use, JUMP down to 0B11H to skip it.
0AEF
PUSH IX
Save IX to the STACK.
0AF1
POP HL
Retrieve IX into HL.
0AF2
LD DE,0005H
DE = 05H (which would be the DIRECTORY + 5, or the FILE NAME)
0AF5
ADD HL,DE
HL = HL + 13, or DIR+13, which is the FILE NAME.
0AF6
LD DE,4018H
DE = 4018H, which should be “‘MODEL% ‘ (or MODELA – MODELG).
0AF9
LD B,08H
B = 8 to compare eight bytes of a filename.
0AFB
GOSUB to 0BF6H to test against that filename in the directory entry.
0AFE
If there was no match, JUMP to 0B11H to skip to the next directory entry.
0B00
PUSH IX
Save IX to the STACK (IX still points to the start of the directory entry).
0B02
POP HL
Retrieve IX into HL.
0B03
LD DE,000DH
DE = 000DH (Decimal: 13)
0B06
ADD HL,DE
HL = HL + 13, or DIR+13, which is the FILE EXTENSION.
0B07
LD B,03H
B = 3 to compare 3 bytes of a file extension.
0B09
LD DE,0063H
DE = 0063H which is the memory pointed to “III”.
0B0C
GOSUB to 0BF6H to Compare HL (the file extension in memory) against “III”
0B0F
If Z is set, then they match, meaning we have found the directory entry for the file. JUMP to 0B36H.

0B11H – Inside the LOAD MODEL%/III ROM IMAGE FROM FLOPPY routine. If we are here, the current directory entry didn’t have MODEL%/III so we need to move the pointers to the next directory entry and try again.

0B11
PUSH IX
Save IX to the STACK (IX still points to the start of the directory entry).
0B13
POP HL
Retrieve IX into HL.
0B14
LD DE,0020H
DE = 0020H which is the length of a directory entry.
0B17
ADD HL,DE
HL = HL + 20H, or DIR+20H, which is the start of the next directory entry.
0B18
LD A,(405CH)
A = the memory contents of 405CH.
NOTE: 405CH holds the lowest sector number and should be either 0 or 1.
0B1B
OR A
Set the flags to test to see if the lowest sector number is Z (5.x/6.x) or NZ (TRSDOS 1.3)
0B1C
If Z is set, then it’s 5.x/6.x and JUMP to 0B22H
0B1E
LD DE,0010H
If we are here, then its TRSDOS v1.3 so first change DE to 10H
0B21
ADD HL,DE
HL = HL + 10H, or DIR+30H, because TRSDOS v1.3 has 30H bytes between directory entries.
0B22
PUSH HL
Save the number of bytes between directory entries to the STACK.
0B23
POP IX
Restore the number of bytes between directory entries from the STACK, so IX will point to the next directory entry.
0B25
LD A,L
A = L.
0B26
OR A
Set the flags. If Z is set, the pointer is at next page of memory.
0B27
If the pointer is at next page of memory, JUMP to 0B2DH.
0B29
CP F0H
Compare A against F0H. F0H is past the last directory entry on TRSDOS 1.3.
0B2B
If we are not past F0H, JUMP to 0AE3H.

0B2DH – Inside the LOAD MODELx/III ROM IMAGE FROM FLOPPY routine. If we are here, we have reached the end of the current directory sector, so we need to move to the next one.

0B2D
LD A,(405EH)
Load A with the memory contents of (405EH).
NOTE: 405EH holds the next sector to read.
0B30
INC A
A = A + 1 to point to the next sector.
0B31
LD (405EH),A
Load the memory contents of (405EH) with A.
NOTE: 405EH holds the next sector to read.
0B34
JUMP to 0ACCH to read and process the new sector.

0B36H – Inside the LOAD MODELx/III ROM IMAGE FROM FLOPPY routine. If we are here, we have found the directory entry for MODELx/III.

0B36
LD DE,40A2H
DE = 40A2H.
NOTE: 40A2H will be the target buffer for the directory entry holding of MODELx/III.
0B39
PUSH IX
Push IX (the directory entry holding MODELx/III) to the STACK.
0B3B
POP HL
Retrieve IX into HL so HL has the start address of the directory entry holding MODELx/III.
0B3C
LD BC,0030H
BC = 30H signifying 30H bytes to copy.
0B3F
LDIR
Copy the directory record for MODELx/III to the buffer starting atg 40A2H.
0B41
LD A,FEH
A = FEH to act as a search termination byte.
0B43
LD (DE),A
Put a FEH into the first byte after the directory record.
0B44
LD IX,40B6H
IX = 40B6H. 40B6H would be the memory location with the first extent field in a directory entry starting at 40A2H.

0B48H – RST 28H – Load Object Code.

0B48
LD E,00H
We will need to get the first byte of the MODELx/III file which will be accomplished through a RST 20H call. To prepare for that call, we need to set E with the byte offset of the MODELx/III file, so load it with a 0.
0B4A
RST 20H
Get the byte pointed to by E from the MODELx/III file.
0B4B
RET NZ
If we failed to get a byte, RETURN.
0B4C
DEC A
A = A – 1.
0B4D
If A was 01H (signifying the load block), JUMP to 0B5AH.
0B4F
DEC A
A = A – 1.
0B50
If A was 02H (signifying a transfer address), JUMP to 0B6BH.
0B52
RST 20H
If the byte wasn’t a 0, 1, or 2, then get another byte which should be the length of block.
0B53
LD B,A
B = A to use as a counter for the comment block.
0B54
RST 20H
Get another byte, and toss it
0B55
RET NZ
If there was an error getting the byte, RETURN
0B56
LOOP back two instructions to 0B54 to keep reading until we have read all of the block.
0B58
If we are here, then we have hit the end of the block, so JUMP to 0B4AH to get the next block.

0B5AH – Inside the LOAD MODELx/III ROM IMAGE FROM FLOPPY routine. If we are here, we have found the LOAD BLOCK of the directory entry for MODELx/III.

0B5A
RST 20H
Get a byte (which should be the block length).
0B5B
RET NZ
If NZ is set, we have an error, so RETURN.
0B5C
DEC A
DEC A
A = A – 2 to allow for load address.
0B5E
LD B,A
B = A (the number of bytes to load).
0B5F
GOSUB to 0B6DH to get the address for loading into HL.
0B62
RET NZ
If NZ is set, we have an error, so RETURN.
0B63
RST 20H
Get the byte to load.
0B64
RET NZ
If NZ is set, we have an error, so RETURN.
0B65
LD (HL),A
Otherwise, we have a valid byte, so put it into the memory location pointed to by HL.
0B66
INC HL
HL = HL + 1 to advance the buffeer.
0B67
LOOP back to 0B63 until the whole block has been read into the buffer pointed to by HL.
0B69
If we are here, then the whole block is in the buffer pointed to by HL so JUMP back to 0B4A to get the next block in file.

0B6BH – Inside the LOAD MODELx/III ROM IMAGE FROM FLOPPY routine. If we are here, we have found the TRANSFER ADDRESS of the directory entry for MODELx/III.

0B6B
RST 20H
Get the byte.
0B6C
RET NZ
If there was an error getting the byte, RETURN
0B6D
RST 20H
Get the byte, which will be the LSB of the desired address.
0B6E
RET NZ
If there was an error getting the byte, RETURN
0B6F
LD L,A
L = A (the LSB of the desired address).
0B70
RST 20H
Get the byte, which will be the MSB of the desired address.
0B71
RET NZ
If there was an error getting the byte, RETURN
0B72
LD H,A
H = A (the MSB of the desired address).
0B73
RET
RETURN with the TRANSFER ADDRESS in HL.

0B74H – RST 20H – Get a byte from the MODELx/III File. On entry E should contain the byte offset of the MODELx/III File.

0B74
PUSH BC
Save BC to the STACK.
0B75
PUSH HL
Save HL to the STACK.
0B76
LD A,E
A = byte offset in current sector.
0B77
OR A
Set the flags
0B78
If A is NOT ZERO, then we do not need to read a sector so JUMP to 0B82H.
0B7A
If A is ZERO, GOSUB 0B88H to read the next sector of the file.
0B7D
If there was an error from next sector read, JUMP to 0B85H.
0B7F
LD DE,4300H
If there was no error, set DE to point to 4300H which is the start of the sector we just read.
0B82
XOR A
Zero A and clear all flags. Z will indicate success on the RETURN.
0B83
LD A,(DE)
A = the byte held in the memory location pointed to by (DE) (i.e., the sector buffer).
0B84
INC DE
DE = DE + 1 to point to the next byte in the sector buffer.
0B85
POP HL
Restore HL from the STACK.
0B86
POP BC
Restore BC from the STACK.
0B87
RET
RETURN

0B88H – Inside RST 20H Routine. If we are here we need to read the next sector of the MODELx/III file.

0B88
LD HL,4060H
HL = 4060H.
NOTE: 4060H is the memory location holding the number of sectors remaining in the current extent.
0B8B
LD A,(HL)
A = the number of sectors remaining in the current extent.
0B8C
OR A
Set the flags to see if there are still sectors remaining in the current extent (Z = none left)
0B8D
If there are still additional sectors in the current extent then JUMP to 0B93H.
0B8F
If there are no additional sectors in the current extent then CALL 0BB7 to calculate the next extent.
0B92
RET NZ
If there is an error, RETURN.
0B93
DEC (HL)
If there is no error, then reduce the number of sectors in the extent by 1.
0B94
LD B,12H
B = 12H (Decimal: 18) which is one more than highest sector number.
0B96
LD A,(405FH)
Load A with the number of sides of the disk.
NOTE: 405FH holds the number of sides.
0B99
DEC A
A = A – 1
0B9A
If A is 0, then we have a single-sided disk, so JUMP to 0B9EH
0B9C
LD B,24H
B = 24H (Decimal: 36) which is the new limit for sector number.
0B9E
LD A,(405EH)
A = the number of the last sector we read.
NOTE: 405EH holds the next sector to read.
0BA1
CP B
Compare the last sector we read with Register B (which holds the highest sector number per track).
0BA2
If we have not hit the sector per track cap, skip down 4 lines to 0BACH.
0BA4
LD A,(M4062)
If we are here then we hit the sector per track cap and need to get the next cylinder, so first load A with the memory contents of (4062H).
NOTE: 4062H holds the current cylinder to read.
0BA7
INC A
A = A + 1 to point to the next cylinder.
0BA8
LD (M4062),A
Put the new cylinder back into (4062H).
0BAB
XOR A
Zero A and clear the flags. This also sets A to the next sector to read.
0BAC
LD C,A
C = A to store the last sector read.
0BAD
INC A
A = A + 1 to point to the next sector.
0BAE
LD (405EH),A
Put the pointer to the next sector into (405EH).
NOTE: 405EH holds the next sector to read.
0BB1
LD A,(M4062)
A = the cylinder number to read.
NOTE: 4062H holds the current cylinder to read.
0BB4
LD E,A
E = A so now E holds the cylinder number to read.
0BB5
JUMP to 0C0CH to read the sector at Cylinder Number E and Sector Number A and RETURN.
0BB7
INC IX
We need to find the next extent for the file, so we have to move 2 bytes forward so … IX = IX + 1
0BB9
INC IX
IX = IX + 1
0BBB
LD A,(IX+00H)
A = the first byte of (new) extent field.
0BBE
LD B,A
B = A so now B = the first byte of (new) extent field.
0BBF
AND 0FEH
MASK A against FEH (Binary: 1111 1110) to drop Bit 0.
0BC1
CP FEH
Test the MASKed A against 0FEH to see if it is 0FEH or 0FFH.
0BC3
If A is less than FEH, JUMP to 0BC9H.
0BC5
LD A,02H
If A is FEH or FFH then we have too many extents so A = 02H to prepare for “Too Many Extents” error.
0BC7
OR A
Set the flags. Since A is 2, NZ will be set, indicating an error.
0BC8
RET
RETURN

0BC9H – Inside RST 20H Routine. If we are here he first byte of the new extent field was not FEH or FFH.

0BC9
LD A,B
A = the first byte of (new) extent field (which is the cylinder of the extent).
0BCA
LD (M4062),A
Put the cylinder of the current extent into (4062H).
NOTE: 4062H holds the current cylinder to read.
0BCD
LD A,(IX+01H)
A = the second byte of extent field.
0BD0
LD E,A
E = the second byte of extent field.
0BD1
AND 0E0H
MASK A against E0H (Binary: 1110 0000) to keep only Bits 5, 6, and 7, which are the relative gran in the cylinder.
0BD3
RLCA
RLCA
RLCA
Rotate A left 3 Bits to take Bits 5, 6, and 7 and make them Bits 2, 1, and 0 (Decimal: 0-7).
0BD6
LD B,A
Store the rotated A in B.
0BD7
LD A,(M4063)
Load A with the sectors per granule value.
NOTE: 4063H holds the number of sectors per granule.
0BDA
GOSUB to 0C02H to do some multiplication to determine the actual starting sector.
0BDD
LD (405EH),A
Store A as the last sector we read into (405EH).
NOTE: 405EH holds the next sector to read.
0BE0
LD A,E
A = E (which is the second byte of extent field).
0BE1
AND 1FH
MASK A against 0001 1111 to keep only Bits 0-4 which are the number of grans in the extent (Result will be in the range of decimal: 0-15).
0BE3
LD B,A
B = the number of grans in the extent.
0BE4
LD A,(405CH)
Load A with the flag for disk type.
NOTE: 405CH holds the lowest sector number and should be either 0 or 1.
0BE7
XOR 01H
XOR A with 01H to change to 0 for TRSDOS 1.3, 1 for 5.x/6.x.
0BE9
ADD A,B
Add the number of grans in the extent to the masked A because 5.x/6.x uses 0 to indicate 1 gran
0BEA
LD B,A
B = the number of grans in the extent.
0BEB
LD A,(M4063)
A = the number of sectors per granule.
NOTE: 4063H holds the number of sectors per granule.
0BEE
GOSUB to 0C02H to multiply the number of sectors per granule (held in A) by the number of granules in the extent (held in B) to give us the number of sectors in the extent.
0BF1
LD (M4060),A
Store the number of sectors in the extent into 4060H.
NOTE: 4060H is the memory location holding the number of sectors remaining in the current extent.
0BF4
XOR A
Zero A and clear all flags, which sets Z for success (as we found next granule).
0BF5
RET
RETURN

0BF6H – Inside RST 20H Routine. Test the filename in the current directory entry vs “MODELx”. On Entry DE = the constant “Model%”, B=8, and HL points to the filename as held in the current directory record.

0BF6
LD A,(DE)
A = the chracter in the filename as pointed to by DE.
0BF7
CP ‘%’
Compare against a “%” (which is designated as a wildcard)
0BF9
If the character is a “%” then everything is good so JUMP to 0BFH to move to the next character.
0BFB
CP (HL)
If the character is not a wildcard then we actually have to test it, so compare A (the current character constant filename we want) vs the character held in (HL).
0BFC
RET NZ
If they do not match, RETURN (and NZ will be set).
0BFD
INC DE
INC HL
If they do match, then we need to move to the next character of both.
0BFF
Loop back to the top of this subroutine for 8 passes.
0C01
RET
RETURN (and Z will be set if success).

0C02H – Inside RST 20H Routine. A = A * B.

0C02
LD C,A
C = A
0C03
LD A,B
A = B
0C04
OR A
Set the flags to see if B is zero.
0C05
RET Z
If B is zero then A is already zero, so RETURN.
0C06
XOR A
Zero A and clear the flags.
0C07
ADD A,C
A = A + C
0C08
Loop back to the immediately preceding instructions B times.
0C0A
RET
RETURN

0C0BH – Inside RST 20H Routine. Read Cylinder E, Sector A into a buffer starting at 4300H.

0C0B
LD C,A
C = the sector number.
0C0C
LD HL,4300H
HL = the address of the sector buffer.
0C0F
LD B,0CH
B = 0CH, which is the function READ SECTOR.
0C11
LD A,01H
A = 01H, which is the code for FLOPPY DISK.
0C13
Call RST 08H to read the sector.
NOTE: RST 08H does Input/Output with Z set for success and NZ set for error. RST 08H requires the following settings:
  • A: 1:Floppy, 2:Hard Drive, 4:RS-232
  • B:
    • 01H = Initialize and Restore
    • 04H = Restore Drive
    • 0CH = Read
    • 32H = Restore drives 1,2,3 (if possible)
    • 70H = Seek
  • C: Sector to read
  • DE: Cylinder to read (D=LSB, E=MSB)
0C14
RET
RETURN.

0C15H – This is the code for a ARCNET Boot.

0C15
LD A,01H
A = 01 for an error, since we are trying to boot from ARCNET but this isn’t an ARCNET boot ROM!
0C17
JUMP back ot 0151H to give Error 01 and HALT.

0C1AH – This is the code for a RS-232 Boot (from holding down RIGHT SHIFT at Boot).

0C1A
LD A,04H
A = 04H.
0C1C
LD (4055H),A
Put 04H into 4055H.
NOTE: 4055H holds the boot type: 1 for floppy, 2 for HD, 4 for RS-232.
0C1F
LD A,64H
A = 64H (Binary: 0110 0100).
0C21
OUT EAH,A
OUTput 0110 0100 to Port EAH (8/N/1 DTR on, RTS on).
NOTE: Port EAH is the RS-232 UART Control Register/Status Register. For output:
  • Bit 0: Data Terminal Ready
  • Bit 1: Request to End
  • Bit 2: Break
  • Bit 3: Parity Enable
  • Bit 4: Stop Bits
  • Bit 5: Select
  • Bit 6: Word Length
  • Bit 7: Parity (0=Odd, 1=Even)
0C23
OR A
Set the flags. Since A is not zero, NZ is set, which will trigger a routine to get the screen address for a message.
0C24
LD HL,0CD4H
HL = 0CD4H which points to the phrase “Not Ready “
0C27
We need to display the “Not Ready Message” pointe to by HL so we call RST 18H.
NOTE: RST 18H jumps to 0255H which displays a message pointed to by HL (with a 00H to indicate the end of the string) at the screen position held in DE if Z is set, or HL otherwise.
0C28
IN A,(E8H)
Poll the modem status Port E8H and put the result into A.
NOTE: Port E8H is the RS-232 Status Register & Master Reset. Input:
  • Bit 4: Ring Indicator
  • Bit 5: Carrier Detect
  • Bit 6: Data Set Ready
  • Bit 7: Clear to Send
0C2A
AND 20H
MASK the Modem Status in A with 20H (Binary: 0010 0000) to kill every bit other than Bit 5 (Carrier Detect).
0C2C
Loop back to the RS-232 Poll in 0C28H until we have carrier.
0C2E
LD DE,0000H
If we are here, we have carrier, so we need to set up for a RST 10H call. DE = Top left corner of the screen.
0C31
LD HL,0CDCH
HL = ” ” to cover up the word “Not”.
0C34
Display the ” ” to cover up “Not” in “Not Ready”.
0C35
LD HL,0CA4H
We are now going to need to set up for a RST 20H call. First, HL = the “Get byte from RS-232” routine.
0C38
LD (400AH),HL
Put the “Get byte from RS-232” routine vector into (400AH) to make a RST 20H call go there instead.
0C3B
LD HL,4057H
HL = 4057H.
NOTE: 4057H holds the baud rate.
0C3E
LD A,FFH
A = FFH (1111 1111) for 19.2K bits per second.
0C40
LD (HL),A
Put 1111 1111 into the baud rate storate memory location.
0C41
OUT (E9H),A
Output 1111 1111 to Port E9H.
NOTE: Port E9H is the RS-232 Baud Rate Select:
Output:
  • Bits 0-3 = Receive Baud Rate (50-19200)
  • Bits 4-7 = Transmit Baud Rate (50-19200)
0C43
OUT (E8H),A
Output A to Port E8H.
NOTE: Port E8H is the RS-232 Status Register and Master Reset. Outputting ANYTHING to this port will reset the RS-232.
0C45
LD B,0AH
B=0AH (Decimal: 10) to set up for a loop of 10 tries to receive a byte.
0C47
RST 20H
Call RST 20H which now points to the “Get Byte from RS-232” routine. That routine will return a successful read in A with Z set, or a NZ to indicate an error.
0C48
If unsuccessful then NZ will be set, and JUMP forward 3 instructions to 0C4EH.
0C4A
CP ‘U’
If we are here then we got a byte. Test to see if it is a U.
0C4C
If that byte is a U then JUMP to 0C57H to continue.
0C4E
If we are here, then it wasn’t a U so we keep retrying up to 10 times.
0C50
LD A,(HL)
If we are here then we didn’t get a U after 10 tries, so load A with the baud rate held in (HL).
0C51
SUB 11H
Subtract 11H (Binary: 0001 0001) from A to set the baud rate to the next lower rate.
0C53
If that subtraction didn’t result in a CARRY (meaning, the slowest possible rate), then JUMP back up and the try the loop again at the current reduced baud rate.
0C55
If we are here, then we fell through the bottom of possible baud rates, so JUMP to 0C3EH to start again at 19.2K bps.

0C57 – Inside the RS-232 BOOT Routine. If we are here then the UART gave us the byte we wanted so we are clear to read from it.

0C57
LD B,0AH
Set up B with 0AH (Decimal: 10) as the number of bytes to receive.
0C59
RST 20H
Call RST 20H which now points to the “Get Byte from RS-232” routine. That routine will return a successful read in A with Z set, or a NZ to indicate an error.
0C5A
If the RST 20H routine gave us a NZ, then we have an error and we need to JUMP back to 0C3EH to start all over again.
0C5C
CP ‘U’
Test the character we got to see if we got a U.
0C5E
If we did not get a U, JUMP back to 0C3EH to start all over again.
0C60
If we did get a U, LOOP back to 0C57H 10 times to get more bytes.
0C62
LD A,(HL)
If we are here, then we got 10 U‘s so load A with the baud rate held in (HL).
0C63
AND 0FH
MASK the baud rate with 0FH (Binary: 0000 1111) to isolate Bits 0-3 which hold the Receive Baud Rate.
0C65
GOSUB to 0CBE to convert the Receive Baud Rate stored in A to ASCII and store it in (4068H) … also set NZ.
0C68
LD HL,0CE0H
In preparation for a RST 18H call to display a message, point HL to “Found Baud Rate ” + character.
0C6B
Display the message.
NOTE: RST 18H jumps to 0255H which displays a message pointed to by HL (with a 00H to indicate the end of the string) at the screen position held in DE if Z is set, or HL otherwise.
0C6C
LD HL,0CC4H
Point HL to the message “Found Baud Rate “
0C6F
GOSUB to 0CB0 to transmit “Found Baud Rate ” over the RS-232.
0C72
IN A,EBH
Poll Port EBH to A.
NOTE: Port EBH is the RS-232C Data Register. It contains the data received from the RS-232C.
0C74
RST 20H
Call RST 20H which now points to the “Get Byte from RS-232” routine. That routine will return a successful read in A with Z set, or a NZ to indicate an error.
0C75
If NZ is set, then we have an error, so JUMP to 0C8BH which is the RS-232 error routine.
0C77
CP FFH
If Z was set then we had no error and there is a byte in A. Check that byte against FFH?.
0C79
If the byte was NOT FFH, JUMP back to 0C74 to keep reading until we get one.
0C7B
LD DE,0244H
If we are here then we got a FFH from the RS-232, so to prepare for a RST 10H call, set DE to display at row 9, col 0.
0C7E
LD HL,04BCH
Set HL to point to “Loading “.
0C81
PUSH HL
Save HL to the STACK.
0C82
We need to display a message on screen so we call RST 10H.
NOTE: RST 10H displays a string stored in HL (with a 00H to indicate the end of the string) at the screen position held in DE.
0C83
POP HL
Restore HL from the STACK (still pointing to “Loading “
0C84
GOSUB to 0CB0H to send the message stored in HL to the RS-232.
0C87
We need to receive a file from the RS-232 and load it into memory so we call RST 28H (Load Object Code).
0C88
If the RST 28H returned NZ then we have an error, so JUMP to 0C8BH which is the RS-232 error routine.
0C8A
JP (HL)
If we had no error, then execute the file we received by JUMPing to (HL).

0C8BH – Inside the RS-232 BOOT Routine. If we are here then we have a RS-232 Error.

0C8B
RRCA
RRCA
RRCA
Rotate A (which is the UART Status) right 3 times. Doing so will set Bit 0 to overrun, Bit 1 to framing and Bit 2 to parity.
0C8E
GOSUB to 0CBE to convert the Receive Baud Rate stored in A to ASCII and store it in (4068H) … also set NZ.
0C91
GOSUB to 0206H to clear the screen and set BC = 0.
0C94
PUSH BC
Save BC to the STACK.
0C95
LD HL,0CE8H
Point HL to “Error ” + character for error encountered.
0C98
Display it.
NOTE: RST 18H jumps to 0255H which displays a message pointed to by HL (with a 00H to indicate the end of the string) at the screen position held in DE if Z is set, or HL otherwise.
0C99
LD HL,0587H
Point HL to “Error”
0C9C
GOSUB to 0CB0 to transmit “Error” over the RS-232.
0C9F
POP BC
Restore BC from the STACK. BC is still 0 which will set up a RST 30H call for 65,536 tries.
0CA0
We need to scan the keyboard so we call RST 30H. This is done here in hopes that 65,536 tries will cause the system on the other end of the RS-232 to time out.
NOTE: RST 30H jumps to 083EH which scans the keyboard BC times with the output held in AF (+ flags).
0CA1
JUMP to the top (almost) of the RS-232 BOOT Routine to try again.

0CA4H – Inside the RS-232 BOOT Routine. “Get A Byte From The RS-232 Routine”. RST 20H is re-routed here. It will return a successfully read character in Register A with Z set, or NZ for an error.

0CA4
IN A,(EAH)
Poll Port EAH into A.
NOTE: Port EAH is the RS-232 UART Control Register/Status Register. Input:
  • Bit 3: Parity error (1=True)
  • Bit 4: Framing Error (1=True)
  • Bit 5: Overrun (1=True)
  • Bit 6: Data Sent (1=True)
  • Bit 7: Data Ready (1=True)
0CA6
BIT 7,A
Test Bit 7 of A to see if we received a character?.
0CA8
If Bit 7 was low, we did not get a character, so loop back 2 instructions to poll again.
0CAA
AND 38H
If we are here, then we have a character, so we MASK it against 0011 1000 to keep only Bits 3-5 to test for Parity Error (Bit 3 High), Framing Error (Bit 4 High), and Overrun (Bit 5 High).
0CAC
RET NZ
If NZ is set then at least one of those errors occurred, so RETURN
0CAD
IN A,EBH
If we are here then we had no errors, so Poll Port EBH to A.
NOTE: Port EBH is the RS-232C Data Register. It contains the data received from the RS-232C.
0CAF
RET
RETURN with A holding the character and Z set to indicate no error.

0CB0H – Inside the RS-232 BOOT Routine. Transmit a message pointed to by HL (and terminated by 00H) over the RS-232.

0CB0
IN A,(EAH)
Poll Port EAH into A.
NOTE: Port EAH is the RS-232 UART Control Register/Status Register. Input:
  • Bit 3: Parity error (1=True)
  • Bit 4: Framing Error (1=True)
  • Bit 5: Overrun (1=True)
  • Bit 6: Data Sent (1=True)
  • Bit 7: Data Ready (1=True)
0CB2
AND 40H
MASK the result of the UART Status against 40H (Binary: 0100 0000) to isolate only Bit 6, which is “Data Sent” (1=True), which then indicates that the transmit register is empty.
0CB4
If DATA SENT is not high then keep looping back 2 instructions until it is.
0CB6
LD A,(HL)
If we are here, then the transmit buffer is empty, so A = the character held in the memory location pointed to by HL.
0CB7
OR A
Set the flags. Is the character 00H?
0CB8
RET Z
If it is a 00H then we are done, so RETURN.
0CB9
OUT (EBH),A
If it is not a 00H then send it out of Port EBH.
NOTE: Port EBH is the RS-232C Data Register. It contains the data to be sent to the RS-232C.
0CBB
INC HL
HL = HL + 1 to point to the next character to send.
0CBC
Loop back to 0CB0H until a 00H character appears in the HL message.

0CBEH – Inside the RS-232 BOOT Routine. Convert the character stored in A to ASCII, store it in (4068H), and set NZ.

0CBE
ADD A,41H
Add 41H to A. 41H is ASCII for “A”, so if A is 0 then it will be A; if A=1 is then it will be B, etc.
0CC0
LD (M4068),A
Store the ASCII-fied version of A into memory location 4068H.
0CC3
RET
RETURN

0CC4H – Message Storage.

0CC4
DB ‘Found Baud Rate ‘
“Found Baud Rate “
0CD4
0000
0000H (meaning to display at top of screen).
0CD6
04D4
Point to 04D4H which contains the phrase “Not “
0CD8
0550
Point to 0550H which contains the phrase “Ready “
0CDA
FFFF
FFFFH (meaning end of message).
0CDC
202020
” ” (three spaces)
0CDF
00
00
0CE0
0184
0184H (meaning display at row 6, col 0).
0CE2
0CC4
Point to 0CC4H which contains the phrase “Found Baud Rate “
0CE4
4068
Point to 4068H which contains the ASCII character for baud rate (“A”-“P”)
0CE6
FFFF
FFFFH (meaning end of message).
0CE8
03C4
03C4H (meaning display at bottom left corner of screen).
0CEA
0587
Point to 0587H which contains the phrase “Error”
0CEC
058D
Point to 058DH which contains the phrase “, “
0CEE
4068
Point to 4068H which contains the character for error.
0CF0
FFFF
FFFFH (meaning end of message).

0CF2H – RAM Test – Jumped Here if . Selected At Bootup.

0CF2
LD SP,3FFEH
Stack Pointer = 3FFEH (Video memory – 1).
0CF5
LD IY,3C80H
IY = 3C80H (Row 2, column 0 of the screen).
0CF9
LD A,08H
A = 08H (Binary: 0000 1000) which turns ON the alternate character set and turns off everything else Port ECH controls.
0CFB
OUT (ECH),A
Output A to Port ECH.
NOTE: Port ECH is the Miscellaneous Controls port. Output:
  • Bit 1: Cass motor [0 = on, 1 = off]
  • Bit 2: Double width [0 = normal, 1 = double]
  • Bit 3: Alt. char. [0 = disable, 1 = enable]
  • Bit 4: I/O bus [0 = disable, 1 = enable]
  • Bit 5: Video waits [0 = disable, 1 = enable]
  • Bit 6: CPU clock speed [0 = 2 mhz, 1 = 4 mhz]
  • Bit 7: not used
0CFD
XOR A
Zero A and clear registers.
0CFE
OUT (84H),A
OUTput 01H (Binary: 0000 0001) to Port 84H.
NOTE: Port 84H handles miscellaneous memory items. Output:
  • 00H: Switch to the first page of video RAM and write protect 0000H-3FFFH
  • 01H: Write enable 0000H-3FFFH
  • 80H: Switch to the second page of video RAM
0D00
LD IX,0D14H
IX = 0D14H as the address to go to after clearing the screen.

0D04H – Inside the RAM TEST Routine. Clears the screen and then JUMPs to wherever the IX register points.

0D04
LD A,’ ‘
Load A with a SPACE.
0D06
LD DE,3C00H
DE = 3C00H, the start of the video RAM.
0D09
LD (DE),A
Put a SPACE into (DE)
0D0A
LD H,D
LD L,E
HL = DE
0D0C
LD BC,03FFH
BC = 03FFH (Decimal: 1023), the length of the video RAM.
0D0F
INC DE
DE = DE + 1
0D10
LDIR
LDIR to move the byte of data pointed to in (HL) to (DE) and then BUMPing HL and DE and DECrementing BC until BC is 0.
0D12
JP (IX)
Exit by JUMPing to wherever the (IX) register points.

0D14H – Inside the RAM TEST Routine. Once we clear the screen the first time, we jump here to display what we will display, and wait for an ENTER key to start.

0D14
LD HL,0ED2H
Load HL with the address of the message “Dynamic RAM Test”
0D17
LD DE,3C00H
DE = 3C00H (the top of the screen).
0D1A
GOSUB to 0249H to display the message pointed to by HL on the screen at the position held by DE.
0D1D
LD HL,0EE3H
Load HL with the address of the message “Press <ENTER> To Begin and RESET To EXIT”
0D20
LD DE,3C40H
DE = 3C40H (the next line on the screen).
0D23
GOSUB to 0249H to display the message pointed to by HL on the screen at the position held by DE.
0D26
LD HL,0F0CH
Load HL with the address of the message “Any Errors Detected Will Be Displayed” + 00H
0D29
LD DE,0C11H
DE = 0C11H (the next line on the screen).
0D2C
GOSUB to 0249H to display the message pointed to by HL on the screen at the position held by DE.
0D2F
LD A,(3840H)
Load A with the memory contents of the 7th row of the keyboard address (holding ENTER, CLEAR, BREAK, arrows, SPACE).
0D32
CP 01H
Compare A with 01H to see if ENTER was pressed.
0D34
Loop back 2 instructions to keep polling the keyboard until ENTER is pressed.
0D36
LD IX,0D3DH
IX = 0D3DH (which is the address of next part of test).
0D3A
JUMP to 0D04H to Clear the screen and then JUMP to wherever IX is pointing.

0D3DH – Inside the RAM TEST Routine. We have the initial ENTER key to start the RAM test.

0D3D
LD HL,0F32H
HL = 0F32H (the column headings for display = “Address Retry Read Written Mask”).
0D40
LD DE,3C80H
DE = 3C80H (row 2, col 0 of the screen).
0D43
GOSUB to 0249H to display the message pointed to by HL on the screen at the position held by DE.
0D46
LD HL,0F92H
Set HL to point to the message “Stack”
0D49
LD DE,03F4H
Set DL to 03F4H (row 15, column 52 of the screen).
0D4C
GOSUB to 0249H to display the message pointed to by HL on the screen at the position held by DE.
0D4F
LD HL,0F56H
Set HL to point to the message “Test Pattern is 55h”
0D52
LD DE,3C40H
Set DL to 3C40H (row 1, column 0 of the screen).
0D55
GOSUB to 0249H to display the message pointed to by HL on the screen at the position held by DE.

0D58H – Inside the RAM TEST Routine. Fill 4000H to FFFFH with 55H.

0D58
LD HL,4000H
Prepare for a LDIR to fill memory. First set HL = 4000H (the starting point of the memory test).
0D5B
LD D,H
LD E,L
DE = HL
0D5D
LD BC,BFFFH
Set BC = BFFFH which is the number of bytes needed to fill from 4000H to FFFFH.
0D60
LD A,55H
A = 55H (Binary: 0101 0101).
0D62
LD (DE),A
Put a 55H into the memory location pointed to by (DE).
0D63
INC DE
Bump DE
0D64
LDIR
LDIR to move the byte of data pointed to in (HL) to (DE) and then BUMPing HL and DE and DECrementing BC until BC is 0.

0D66H – Inside the RAM TEST Routine. Check 4000H to FFFFH for 55H.

0D66
LD HL,4000H
Set HL = 4000H (the starting point of the memory test).
0D69
LD BC,BFFFH
Set BC = BFFFH which is the number of bytes needed to fill from 4000H to FFFFH.
0D6C
LD A,55H
A = 55H (Binary: 0101 0101).
0D6E
LD E,(HL)
E = the contents of the memory byte pointed to by (HL).
0D6F
CP E
Test A vs E. Z = they match, NZ = they do not match.
0D70
LD IX,0D77H
IX = 0D77H as the resume if we jump.
0D74
If the memory check showed an error, JUMP to 0E0AH to display the error.
0D77
DEC BC
BC = BC – 1 (as there is 1 less byte the check).
0D78
INC HL
HL = HL + 1 (to point to the next byte to check).
0D79
LD A,C
OR B
Check BC for 0 by doing the LD A,C / OR B trick. A will be 0 only if B and C were both 0.
0D7B
If BC is not zero, then we still have more bytes to check so JUMP to back to 0D6CH to test the next byte.

0D7DH – Inside the RAM TEST Routine. If we are here, the first round of memory check, for byte 55H, passed, so lets move on to AAH.

0D7D
LD HL,0F6AH
Set HL to point to the message “AAh”.
0D80
LD DE,3C50H
Set BC to 3C50H (row 1, column 16 of the screen).
0D83
GOSUB to 0249H to display the message pointed to by HL on the screen at the position held by DE.
0D86
LD HL,4000H
Set HL = 4000H (the starting point of the memory test).
0D89
LD D,H
LD E,L
DE = HL
0D8B
LD BC,BFFFH
Set BC = BFFFH which is the number of bytes needed to fill from 4000H to FFFFH.
0D8E
LD A,0AAH
Load A with AAH (Binary: 1010 1010).
0D90
LD (DE),A
Put a AAH into the memory location pointed to by (DE).
0D91
INC DE
Bump DE
0D92
LDIR
LDIR to move the byte of data pointed to in (HL) to (DE) and then BUMPing HL and DE and DECrementing BC until BC is 0.

0D94H – Inside the RAM TEST Routine. If we are here, AAH has been written to 4000H-FFFH and now we need to read it back to see it it matches.

0D94
LD HL,4000H
Set HL = 4000H (the starting point of the memory test).
0D97
LD BC,BFFFH
Set BC = BFFFH which is the number of bytes needed to fill from 4000H to FFFFH.
0D9A
LD A,0AAH
Load A with AAH (Binary: 1010 1010).
0D9C
LD E,(HL)
E = the contents of the memory byte pointed to by (HL).
0D9D
CP E
Test A vs E. Z = they match, NZ = they do not match.
0D9E
LD IX,0DA5H
IX = 0DA5H as the resume if we jump.
0DA2
If the memory check showed an error, JUMP to 0E0AH to display the error.
0DA5
DEC BC
BC = BC – 1 (as there is 1 less byte the check).
0DA6
INC HL
HL = HL + 1 (to point to the next byte to check).
0DA7
LD A,C
OR B
Check BC for 0 by doing the LD A,C / OR B trick. A will be 0 only if B and C were both 0.
0DA9
Loop back to 0D9AH until all the bytes have been tested.

0DACH – Inside the RAM TEST Routine. If we are here, the second round of memory check (byte AAH) passed, so lets move on to the Modified Address Test. First, put the messages and the mask on the screen.

0DAC
LD D,00H
D = 0 as the mask for testing each byte.
0DAE
LD B,D
B = D. This is where we will jump back to in the memory test to test from 00H to FFH
0DAF
LD HL,0F6EH
Set HL to point to the message “Modified Address Test ld (hl),mask”
0DB2
LD DE,3C40H
Set BC to 3C40H (row 2 of the screen).
0DB5
GOSUB to 0249H to display the message pointed to by HL on the screen at the position held by DE.
0DB8
LD H,D
LD L,E
HL = DE
0DBA
LD D,B
D = B to put the mask back into D.
0DBB
INC HL
Bump HL to point to the next space on screen.
0DBC
RRA
RRA
RRA
RRA
We need to move the upper nybble of the mask value in A to the lower nybble so we rotate the contents of 4 right (with Bit 0 going to Carry and Carry going to Bit 7) 4 times.
0DC0
AND 0FH
MASK the rotated A against 0FH (0000 1111) to isolate the lower (formerly upper) 4 bits only.
0DC2
ADD A,90H
A = A + 90H (Decimal: 144).
0DC4
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0DC5
ADC A,40H
Add 40H and the CARRY FLAG to A to display the top half of the MASK.
0DC7
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0DC8
LD (HL),A
Put Register A (which is the 1st character of the MASK value) onto the screen at the location held in HL.
0DC9
INC HL
Bump HL to point to the next space on screen.
0DCA
LD A,D
A = D (the MASK value).
0DCB
AND 0FH
MASK A against 0FH (0000 1111) to isolate the lower (formerly upper) 4 bits only.
0DCD
ADD A,90H
A = A + 90H (Decimal: 144).
0DCF
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0DD0
ADC A,’@’
Add 40H and the CARRY FLAG to A to display the top half of the MASK.
0DD2
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0DD3
LD (HL),A
Put Register A (which is the 2nd character of the MASK value) onto the screen at the location held in HL.

0DD4H – Inside the RAM TEST Routine – Modified Address Test. Now that the messages are on the screen, start the test, first write the values.

0DD4
LD HL,4000H
HL = 4000H, which is the start of the memory to be tested.
0DD7
LD BC,BFFFH
BC = BFFFH which is the number of bytes to test from 4000H through FFFFH.
0DDA
LD A,D
A = D (the mask value)
0DDB
XOR L
XOR A with the LSB of the current memory address being tested.
0DDC
XOR H
XOR A with the MSB of the current memory address being tested.
0DDD
LD (HL),A
Put A (the double XOR’d mask value) into the memory address.
0DDE
INC HL
HL = HL + 1.
0DDF
DEC BC
BC = BC – 1
0DE0
LD A,C
OR B
We need to test BC for zero so we use the shortcut of LD A,C / OR B, as the only way that will set the ZERO FLAG is if both B and C are zero.
0DE2
JUMP back to 0DDAH until we have tested them all (i.e. BC = 0).
0DE4
LD A,D
A = D (the mask value).
0DE5
AND 03H
AND A against 03H to see if it is divisible by 4.
0DE7
If A is not divisible by 4 then skip the next 2 instructions and JUMP down to 0DEDH.
0DE9
LD A,40H
A = 40H (Binary: 0100 0000) for Bit 6 high.
0DEB
OUT (F4H),A
OUTput 40H (Binary: 0100 0000) to Port F4H to enable Wait State Generation.
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)

0DEDH – Inside the RAM TEST Routine – Modified Address Test. Verify the written values.

0DED
LD HL,4000H
HL = 4000H, which is the start of the memory to be tested.
0DF0
LD BC,BFFFH
BC = BFFFH which is the number of bytes to test from 4000H through FFFFH.
0DF3
LD A,D
A = D (the mask value)
0DF4
XOR L
XOR A with the LSB of the current memory address being tested.
0DF5
XOR H
XOR A with the MSB of the current memory address being tested.
0DF6
LD E,(HL)
E = the value currently at the memory address being tested.
0DF7
CP E
Compare A (the value that SHOULD be there) vs E (the value that IS there).
0DF8
LD IX,0DFEH
IX = 0DFEH as the JUMP point if there is an error.
0DFC
If the memory check showed an error, JUMP to 0E0AH to display the error.
0DFE
INC HL
HL = HL + 1.
0DFF
DEC BC
BC = BC – 1
0E00
LD A,C
OR B
We need to test BC for zero so we use the shortcut of LD A,C / OR B, as the only way that will set the ZERO FLAG is if both B and C are zero.
0E02
JUMP back to 0DF3H until we have tested them all (i.e. BC = 0).
0E04
INC D
D = D + 1 (to increment the mask).
0E05
If D hasn’t rotated all the way to 00H, then we need to test again (by JUMPING back to 0DAEH), but with the mask 1 byte higher.
0E07
If D did hit 00H then we have tested 00H-FFH, then JUMP back to 0D4FH and redo the memory test … forever.

0E0AH – Display a MEMORY TEST error. On entry, HL has the memory address of the bad byte, and IX has the routine exit jump address.

0E0A
EX AF,AF’
Exchange AF with AF’.
0E0B
EXX
Exchange BC, DE and HL with BC’, DE’, and HL’.
0E0C
LD BC,0040H
BC = 40H (Decimal: 64) which is the number of characters on one line of the screen.
0E0F
ADD IY,BC
IY = IY + BC to point to next line on screen (as IY has been holding the value 3C80H which is row 2, column 0 of the screen).
0E11
LD BC,C040H
BC = C040H (Decimal: 49216). Note: C040H is the same as -3FC0H (Decimal: 16320) since 65,536 – 49,216 = 16,320.
0E14
ADD IY,BC
IY = IY + -3FC0H, which will set the CARRY if IY pointed to the last line of the screen, and NO CARRY if it didn’t.
0E16
Skip the next instruction (which resets IY to point to the top of the screen) if we didn’t fall off the screen.
0E18
LD IY,0000H
IY = 0000H to indicate we are starting at the top of the screen.
0E1C
LD BC,3FC0H
BC = 3FC0H (Decimal: 16320) to start undoing that subtraction.
0E1F
ADD IY,BC
IY = IY + 3FC0H to restore IY
0E21
EXX
Exchange BC, DE and HL with BC’, DE’, and HL’.

0E22H – Inside the RAM TEST ERROR DISPLAY Routine – Display defective RAM Address in Cols 1-4. Process the upper nybble of the MSB of the defective RAM address and put it on the screen at column 1 of the current screen row.

0E22
LD A,H
A = the MSB of the defective byte.
0E23
RRA
RRA
RRA
RRA
We need to move the upper nybble of the mask value in A to the lower nybble so we rotate the contents of 4 right (with Bit 0 going to Carry and Carry going to Bit 7) 4 times.
0E27
AND 0FH
MASK the rotated A against 0FH (0000 1111) to isolate the lower (formerly upper) 4 bits only.
0E29
ADD A,90H
A = A + 90H (Decimal: 144).
0E2B
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E2C
ADC A,40H
Add 40H and the CARRY FLAG to A to display the top half of the MASK.
0E2E
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E2F
LD (IY+01H),A
Put the converted A under the “ADDRESS” heading at column 1 of the current row on the screen.

0E32H – Inside the RAM TEST ERROR DISPLAY Routine – Display defective RAM Address in Cols 1-4. Process the lower nybble of the MSB of the defective RAM address and put it on the screen at column 1 of the current screen row.

0E32
LD A,H
A = the MSB of the defective byte.
0E33
AND 0FH
MASK the UNrotated A against 0FH (0000 1111) to isolate the actual lower 4 bits only.
0E35
ADD A,90H
A = A + 90H (Decimal: 144).
0E37
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E38
ADC A,40H
Add 40H and the CARRY FLAG to A to display the top half of the MASK.
0E3A
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E3B
LD (IY+02H),A
Put the converted A on column 2 of the current row on the screen.

0E3EH – Inside the RAM TEST ERROR DISPLAY Routine – Display defective RAM Address in Cols 1-4. Process the upper nybble of the LSB of the defective RAM address and put it on the screen at column 1 of the current screen row.

0E3E
LD A,L
A = the LSB of the defective byte.
0E3F
RRA
RRA
RRA
RRA
We need to move the upper nybble of the mask value in A to the lower nybble so we rotate the contents of 4 right (with Bit 0 going to Carry and Carry going to Bit 7) 4 times.
0E43
AND 0FH
MASK the rotated A against 0FH (0000 1111) to isolate the lower (formerly upper) 4 bits only.
0E45
ADD A,90H
A = A + 90H (Decimal: 144).
0E47
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E48
ADC A,40H
Add 40H and the CARRY FLAG to A to display the top half of the MASK.
0E4A
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E4B
LD (IY+03H),A
Put the converted A on column 3 of the current row on the screen.

0E4EH – Inside the RAM TEST ERROR DISPLAY Routine – Display defective RAM Address in Cols 1-4. Process the lower nybble of the LSB of the defective RAM address and put it on the screen at column 1 of the current screen row.

0E4E
LD A,L
A = the LSB of the defective byte.
0E4F
AND 0FH
MASK the UNrotated A against 0FH (0000 1111) to isolate the lower (formerly upper) 4 bits only.
0E51
ADD A,90H
A = A + 90H (Decimal: 144).
0E53
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E54
ADC A,40H
Add 40H and the CARRY FLAG to A to display the top half of the MASK.
0E56
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E57
LD (IY+04H),A
Put the converted A on column 4 of the current row on the screen.

0E5AH – Inside the RAM TEST ERROR DISPLAY Routine – Display defective RAM CONTENTS in Cols 10-11 (“RETRY”). Process the lower nybble of the value NEWLY read from the defective RAM address and put it on the screen at columns 10 and 11 of the current screen row.

0E5A
LD A,(HL)
A = the contents of the defective memory address.
0E5B
LD I,A
I = A.
0E5D
RRA
RRA
RRA
RRA
We need to move the upper nybble of the mask value in A to the lower nybble so we rotate the contents of 4 right (with Bit 0 going to Carry and Carry going to Bit 7) 4 times.
0E61
AND 0FH
MASK the rotated A against 0FH (0000 1111) to isolate the lower (formerly upper) 4 bits only.
0E63
ADD A,90H
A = A + 90H (Decimal: 144).
0E65
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E66
ADC A,40H
Add 40H and the CARRY FLAG to A.
0E68
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E69
LD (IY+0AH),A
Put the converted A on column 10 of the current row on the screen.

0E6CH – Inside the RAM TEST ERROR DISPLAY Routine – Display defective RAM CONTENTS in Cols 10-11. Process the upper nybble of the defective RAM CONTENTS and put it on the screen at column 11 of the current screen row.

0E6C
LD A,I
Restore A from I
0E6E
AND 0FH
MASK the UNrotated A against 0FH (0000 1111) to actual lower 4 bits only.
0E70
ADD A,90H
A = A + 90H (Decimal: 144).
0E72
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E73
ADC A,40H
Add 40H and the CARRY FLAG to A.
0E75
DAA
Display under ‘Retry’ heading.
0E76
LD (IY+0BH),A
Put the converted A on column 11 of the current row on the screen.

0E79H – Inside the RAM TEST ERROR DISPLAY Routine – Display defective RAM CONTENTS in Cols 17-18 (“READ”). Process the upper nybble of the value ORIGINALLY read from the defective RAM address.

0E79
LD A,E
A = E (which is the value originally read from problem address).
0E7A
RRA
RRA
RRA
RRA
We need to move the upper nybble of the mask value in A to the lower nybble so we rotate the contents of 4 right (with Bit 0 going to Carry and Carry going to Bit 7) 4 times.
0E7E
AND 0FH
MASK the rotated A against 0FH (0000 1111) to isolate the lower (formerly upper) 4 bits only.
0E80
ADD A,90H
A = A + 90H (Decimal: 144).
0E82
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E83
ADC A,40H
Add 40H and the CARRY FLAG to A.
0E85
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E86
LD (IY+11H),A
Put the converted A on column 17 of the current row on the screen.

0E89H – Inside the RAM TEST ERROR DISPLAY Routine – Display defective RAM CONTENTS in Cols 17-18 (“READ”). Process the lower nybble of the value ORIGINALLY read from the defective RAM address.

0E89
LD A,E
A = E (which is the value originally read from problem address).
0E8A
AND 0FH
MASK the UNrotated A against 0FH (0000 1111) to isolate the actual lower 4 bits only.
0E8C
ADD A,90H
A = A + 90H (Decimal: 144).
0E8E
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E8F
ADC A,40H
Add 40H and the CARRY FLAG to A.
0E91
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0E92
LD (IY+12H),A
Put the converted A on column 18 of the current row on the screen.

0E95H – Inside the RAM TEST ERROR DISPLAY Routine – Display what was written to the defective RAM address in Cols 23-24 (“WRITTEN”). Process the upper nybble.

0E95
EX AF,AF’
Exchange AF with AF’ to restore the original AF register.
0E96
LD I,A
I = A.
0E98
RRA
RRA
RRA
RRA
We need to move the upper nybble of the mask value in A to the lower nybble so we rotate the contents of 4 right (with Bit 0 going to Carry and Carry going to Bit 7) 4 times.
0E9C
AND 0FH
MASK the rotated A against 0FH (0000 1111) to isolate the lower (formerly upper) 4 bits only.
0E9E
ADD A,90H
A = A + 90H (Decimal: 144).
0EA0
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0EA1
ADC A,40H
Add 40H and the CARRY FLAG to A.
0EA3
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0EA4
LD (IY+17H),A
Put the converted A on column 23 of the current row on the screen.

0EA7H – Inside the RAM TEST ERROR DISPLAY Routine – Display what was written to the defective RAM address in Cols 23-24 (“WRITTEN”). Process the lower nybble.

0EA7
LD A,I
Restore A from I.
0EA9
AND 0FH
MASK the UNrotated A against 0FH (0000 1111) to isolate the actual lower 4 bits only.
0EAB
ADD A,90H
A = A + 90H (Decimal: 144).
0EAD
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0EAE
ADC A,40H
Add 40H and the CARRY FLAG to A.
0EB0
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0EB1
LD (IY+18H),A
Put the converted A on column 24 of the current row on the screen.

0EB4H – Inside the RAM TEST ERROR DISPLAY Routine – Display what was the MASK VALUE used at the defective RAM address in Cols 32-33 (“MASK”). Process the upper nybble.

0EB4
LD A,D
A = D (which is the mask value used at defective RAM address).
0EB5
RRA
RRA
RRA
RRA
We need to move the upper nybble of the mask value in A to the lower nybble so we rotate the contents of 4 right (with Bit 0 going to Carry and Carry going to Bit 7) 4 times.
0EB9
AND 0FH
MASK the rotated A against 0FH (0000 1111) to isolate the lower (formerly upper) 4 bits only.
0EBB
ADD A,90H
A = A + 90H (Decimal: 144).
0EBD
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0EBE
ADC A,40H
Add 40H and the CARRY FLAG to A.
0EC0
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0EC1
LD (IY+20H),A
Put the converted A on column 32 of the current row on the screen.

0EC4H – Inside the RAM TEST ERROR DISPLAY Routine – Display what was the MASK VALUE used at the defective RAM address in Cols 32-33 (“MASK”). Process the lower nybble.

0EC4
LD A,D
A = D (which is the mask value used at defective RAM address).
0EC5
AND 0FH
MASK the UNrotated A against 0FH (0000 1111) to isolate the ACTUAL lower 4 bits only.
0EC7
ADD A,90H
A = A + 90H (Decimal: 144).
0EC9
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0ECA
ADC A,40H
Add 40H and the CARRY FLAG to A.
0ECC
DAA
Convert A to ASCII using the DAA command (which adjusts A for BCD addition and subtraction).
0ECD
LD (IY+21H),A
Put the converted A on column 33 of the current row on the screen.

0ED0H – Inside the RAM TEST ERROR DISPLAY Routine. Exit to the location set on entry in (IX).

0ED0
JP (IX)
Resume test at address in IX.

0ED2H – Message Storage.

0ED2
Message Storage
“Dynamic RAM Test” + 00H
0EE3
Message Storage
“Press <ENTER> To Begin And RESET To Exit” + 00H
0F0C
Message Storage
“Any Errors Detected Will Be Displayed” + 00H
0F32
Message Storage
“Address Retry Read Written Mask” + 00H
0F56
Message Storage
“Test Pattern is 55h” + 00H
0F6A
Message Storage
“AAh” + 00H
0F6E
Message Storage
“Modified Address Test ld (hl),ask”H + 00H
0F92
Message Storage
“Stack” + 00H
0F98-0FEA
NOP
0FEB-0FFF
Message Storage
DB “(c) 1983, Tandy Corp.”