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

ORG 4E00H

Since DEBUG is going to need to use all registers for itself, but yet leave them undisturbed for the program being debugged, it is necessary to preserve all registers, so the next bunch of steps do just that.

4E00
PUSH AF
Save Register AF to the top of the STACK.
4E01
PUSH IY
Save Register IY to the top of the STACK.
4E03
PUSH IX
Save Register IX to the top of the STACK.
4E05
EX AF,AF’
EXchange the value stored in Register Pair AF’ with the value stored in Register Pair AF.
4E06
EXX
EXchange all Register Pairs for their Alternate
4E07
PUSH HL
Save Register HL to the top of the STACK.
4E08
PUSH DE
Save Register DE to the top of the STACK.
4E09
PUSH BC
Save Register BC to the top of the STACK.
4E0A
PUSH AF
Save Register AF to the top of the STACK.
4E0B
EX AF,AF’
EXchange the value stored in Register Pair AF’ with the value stored in Register Pair AF.
4E0C
EXX
EXchange all Register Pairs for their Alternate
4E0D
PUSH HL
Save Register HL to the top of the STACK.
4E0E
PUSH DE
Save Register DE to the top of the STACK.
4E0F
PUSH BC
Save Register BC to the top of the STACK.
4E10
PUSH AF
Save Register AF to the top of the STACK.

With all the registers now preserved in the STACK, we next copy the STACK to 4108H and on to save them.

4E11
LD HL,0000H
We want to copy the STACK Pointer into HL, but there is no easy way to do that, so we will need to ADD SP to HL. Naturally, we need to first set Register Pair HL = 0000H as a base for math.
4E14
ADD the value held in Register Pair SP to Register Pair HL, so that HL now points to the bottom of the area where the registers are saved. This is setting up to do a LDIR to REALLY save all those registers into an area of RAM.
4E15
LD DE,MEM+8
[4108H]
LET Register Pair DE = 4108H, which is the bottom of the storage area where those registers are going to get preserved.
4E18
LD BC,0018H
LET Register Pair BC = 0018H (Decimal: 24) because there are 24 register pairs to save.
4E1B
LDIR
Move all those registers into 4108H+ via a LDIR which transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
4E1D
LD (MEM+28),HL
[411CH]
Store the value held in Register HL (i.e., the old STACK pointer) into the memory location 411CH for safekeeping.
4E20
LD A,(442BH)
Fetch the value stored at memory location 442BH and put it into Register A.
NOTE: 442BH is the storage location for the OVERLAY FLAG flag.
4E23
RES 4,A
RESet (i.e., set as 0) BIT 4 of Register A to designate that OVERLAY 6 is not in RAM.
4E25
LD (442BH),A
Store the value held in Register A into the memory location 442BH.
NOTE: 442BH is the storage location for the OVERLAY FLAG flag.

Check to see what the OP CODE was when DEBUG was invoked, and also see if it was from a RST 30H call or not.

4E28
LD SP,HL
LET Register Pair SP = Register Pair HL (i.e., the ORIGINAL STACK pointer); to reset the STACK now that the running program’s registers have all been preserved.
4E29
LD HL,(MEM+30)
[411EH]
Fetch the value stored at memory location 411EH (i.e., the Program Counter for the running program) and put it into Register HL.
4E2C
DEC HL
Back up 1 instruction by DECrementing the value stored in Register Pair HL.
4E2D
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the command which was just run) and put it into Register A.
4E2E
CP 0F7H
Compare the value held in Register A against 0F7H (i.e.,. the OPCODE for RST 30H) to see if DEBUG was initiated by a RST 30H call. Results: If Register A equals RST 30H, the Z FLAG is set; otherwise the NZ FLAG is set.
4E30
JR NZ,START2
[4E35H]
If the NZ FLAG (Not Zero) is set then the OPCODE was not RST 30H, meaning that this wasn’t a breakpoint, so JUMP to “START2” (i.e., 4E35H).
4E32
LD (MEM+30),HL
[411EH]
Store the value held in Register HL (i.e., the Program Counter for the running program MINUS 1) into the memory location 411EH.

If this was a RST 30H call, we need to see if DEBUG was involked by a breakpoint.

4E35
“START2”
LD HL,MEM
[4100H]
LET Register Pair HL = 4100H (i.e., a RAM area where the BREAKPOINTS are stored).
4E38
LD B,02H
LET Register B = 02H to indicate that there are TWO possible BREAKPOINTS.

Top of a loop of TWO iterations to check the two possible breakpoint locations for valid data.

4E3A
“START1”
XOR A
Set Register A to ZERO and clear all Flags.
4E3B
LD C,02H
LET Register C = 02H for absolutely no reason.
4E3D
LD E,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the BREAKPOINT storage area) and put it into Register E.
4E3E
LD (HL),A
Store the value held in Register A (i.e., a ZERO) into the memory location pointed to by Register Pair HL; thus clearing that breakpoint.
4E3F
INC HL
Bump the value stored in Register Pair HL by 1 to point to the second of the two possible breakpoints.
4E40
LD D,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the BREAKPOINT storage area) and put it into Register D.
4E41
LD (HL),A
Store the value held in Register A (i.e., a ZERO) into the memory location pointed to by Register Pair HL; thus clearing that breakpoint.
4E42
INC HL
Bump the value stored in Register Pair HL (i.e., the BREAKPOINT storage area) by 1.
4E43
4E44
LD A,E
OR D
Since there is no way to check Register Pair DE against zero, a common trick is to load one-half of the register pair into Register A and then OR that against the other half othe register pair. Only if both halves were 0 will Register A be 0.
4E45
JR Z,START4
[4E4EH]
If the Z FLAG (Zero) is set, meaning that the breakpoint address was ZERO, JUMP to 4E4EH to move to the next breakpoint.
4E47
LD A,(DE)
Since the breakpoint was NOT zero, fetch the value stored at memory location pointed to by Register Pair DE (i.e., the value which was at the breakpoint memory location) and put it into Register A.
4E48
CP 0F7H
Compare the value held in Register A against 0F7H (i.e.,. the OPCODE for RST 30H) to see if DEBUG was initiated by a RST 30H call. Results: If Register A equals RST 30H, the Z FLAG is set; otherwise the NZ FLAG is set.
4E4A
JR NZ,START4
[4E4EH]
If the NZ FLAG (Not Zero) is set then the OPCODE was not RST 30H, so JUMP to 4E4EH to move to the next breakpoint.
4E4C
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the original OPCODE at the location) and put it into Register A.
4E4D
LD (DE),A
Store the value held in Register A (i.e., the original OPCODE at the location) into the memory location pointed to by Register Pair DE (i.e., the call to DEBUG).
4E4E
“START4”
INC HL
Bump the value stored in Register Pair HL by 1 to move to the next breakpoint in the breakpoint storage area.
4E4F
DJNZ START4
[4E3AH]
LOOP back to 4E3AH until Register B is ZERO.

4E51H – Command loop. Set up STACK, turn on cursor, display the screen, and process the DEBUG commands.

4E51
“START5”
LD SP,(MEM+28)
[411CH]
Fetch the value stored at memory location 411CH (i.e., the old STACK pointer) and put it into Register SP. This sets up the SP to be fresh for each command.
4E55
LD A,0B0H
LET Register A = 0B0H (ASCII: BLOCK cursor).
4E57
LD (CURSCR),A
[4023H]
Store the value held in Register A into the memory location 4023H.
NOTE: 4023H is the storage location for the CURSOR CHARACTER.
4E5A
LD A,0EH
LET Register A = 0EH, which is ENABLE cursor.
4E5C
CALL DSP
[0033H]
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
4E5F
EI
Enable Interrupts.
4E60
CALL DISPLY
[4F0FH]
GOSUB to 4F0FH to display the DEBUG screen and all the registers.
4E63
“START6”
LD HL,3FC0H
LET Register Pair HL = 3FC0H, which would be the first character on the 15th line of the display.
4E66
LD (CURSOR),HL
[4020H]
Store the value held in Register HL into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
4E69
EI
Enable Interrupts.
4E6A
CALL KEYLIN
[51F1H]
GOSUB to 51F1H to get character from the keyboard and process accordingly.
4E6D
CP 4AH
Compare the value held in Register A against 4AH (ASCII: J). Results: If Register A equals J, the Z FLAG is set; otherwise the NZ FLAG is set.
4E6F
JP Z,GO
[4FF7H]
If the Z FLAG (Zero) is set, meaning that a J key was pressed, JUMP to 4FF7H.
4E72
CP 47H
Compare the value held in Register A against 47H (ASCII: G). Results: If Register A equals G, the Z FLAG is set; otherwise the NZ FLAG is set.
4E74
JP Z,GO
[4FF7H]
If the Z FLAG (Zero) is set, meaning that a G key was pressed, JUMP to 4FF7H, which is the same jump as above!

All the remaining commands do something that requires returning to the DEBUG screen and entering a new command, so we need to specify that when they exit, they come back to this COMMAND LOOP.

4E77
LD HL,START5
[4E51H]
LET Register Pair HL = 4E51H (i.e., this command loop) as the return address
4E7A
PUSH HL
Save Register HL (i.e., the return address) to the top of the STACK so that the top of the STACK contains the address we want to RETurn to.
4E7B
CP 53H
Compare the value held in Register A against 53H (ASCII: S). Results: If Register A equals S, the Z FLAG is set; otherwise the NZ FLAG is set.
4E7D
JR Z,PAGE
[4EB3H]
If the Z FLAG (Zero) is set, meaning that a S key was pressed, JUMP to 4EB3H.
4E7F
CP 3BH
Compare the value held in Register A against 3BH (ASCII: ;). Results: If Register A equals ;, the Z FLAG is set; otherwise the NZ FLAG is set.
4E81
JR Z,NXTMEM
[4EE3H]
If the Z FLAG (Zero) is set, meaning that a ;). Re key was pressed, JUMP to 4EE3H.
4E83
CP 2DH
Compare the value held in Register A against 2DH (ASCII: ). Results: If Register A equals , the Z FLAG is set; otherwise the NZ FLAG is set.
4E85
JR Z,BCKMEM
[4F0AH]
If the Z FLAG (Zero) is set, meaning that a ). Re key was pressed, JUMP to 4F0AH.
4E88
CP 43H
Compare the value held in Register A against 43H (ASCII: C). Results: If Register A equals C, the Z FLAG is set; otherwise the NZ FLAG is set.
4E8A
JR Z,HERE1
[4E92H]
If the Z FLAG (Zero) is set, meaning that a C key was pressed for a single-step-around-calls function, JUMP to 4E92H.
4E8C
CP 44H
Compare the value held in Register A against 44H (ASCII: D). Results: If Register A equals D, the Z FLAG is set; otherwise the NZ FLAG is set.
4E8E
JR Z,DOIT
[4EC1H]
If the Z FLAG (Zero) is set, meaning that a D key was pressed, JUMP to 4EC1H.
4E90
CP 49H
Compare the value held in Register A against 49H (ASCII: I). Results: If Register A equals I, the Z FLAG is set; otherwise the NZ FLAG is set.
4E92
“HERE1”
JP Z,SINGLE
[50DBH]
If the Z FLAG (Zero) is set, meaning that a I key was pressed, JUMP to 50DBH.
4E95
CP 4DH
Compare the value held in Register A against 4DH (ASCII: M). Results: If Register A equals M, the Z FLAG is set; otherwise the NZ FLAG is set.
4E97
JP Z,MEMORY
[504DH]
If the Z FLAG (Zero) is set, meaning that a M key was pressed, JUMP to 504DH.
4E9A
CP 52H
Compare the value held in Register A against 52H (ASCII: R). Results: If Register A equals R, the Z FLAG is set; otherwise the NZ FLAG is set.
4E9C
JP Z,REGIST
[508AH]
If the Z FLAG (Zero) is set, meaning that a R key was pressed, JUMP to 508AH.
4E9F
CP 55H
Compare the value held in Register A against 55H (ASCII: U). Results: If Register A equals U, the Z FLAG is set; otherwise the NZ FLAG is set.
4EA1
JR Z,UPDATE
[4EB7H]
If the Z FLAG (Zero) is set, meaning that a U key was pressed, JUMP to 4EB7H.
4EA3
CP 58H
Compare the value held in Register A against 58H (ASCII: X). Results: If Register A equals X, the Z FLAG is set; otherwise the NZ FLAG is set.
4EA5
JR Z,OVER
[4EB2H]
If the Z FLAG (Zero) is set, meaning that a X key was pressed, JUMP to 4EB2H.
4EA7
CP 46H
Compare the value held in Register A against 46H (ASCII: F). Results: If Register A equals F, the Z FLAG is set; otherwise the NZ FLAG is set.
4EA9
JP Z,TRA
[52BDH]
If the Z FLAG (Zero) is set, meaning that a F key was pressed, JUMP to 52BDH.
4EAC
CP 51H
Compare the value held in Register A against 51H (ASCII: Q). Results: If Register A equals Q, the Z FLAG is set; otherwise the NZ FLAG is set.
4EAE
JP Z,QUIT
[5286H]
If the Z FLAG (Zero) is set, meaning that a Q key was pressed, JUMP to 5286H.
4EB1
RET

4EB2H – X Command – Half Page Display

4EB2
“OVER”
XOR A
Set Register A to ZERO and clear all Flags.

4EB3H – S Command – Full Page Display

4EB3
“PAGE”
LD (MEM+1),A
[4101H]
Store the value held in Register A (i.e., a S, or really just any non-zero value) into the memory location 4101H.
4EB6
RET

4EB7H – U Command – Continuous Redisplay of Memory until a key is pressed

4EB7
“UPDATE”
CALL KBD
[002BH]
GOSUB to 002BH (i.e., the ROM Keyboard scanning routine; Register A exits with the ASCII value for the key that was pressed or ZERO if no key was pressed.
4EBA
OR A
Set FLAGS based on the contents of Register A.
4EBB
RET NZ
If the NZ FLAG (Not Zero) is set, meaning a key was pressed, RETurn to the caller.
4EBC
CALL DISPLY
[4F0FH]
GOSUB to 4F0FH to display memory.
4EBF
JR UPDATE
[4EB7H]
LOOP BACK to the top of this routine at 4EB7H.

4EC1H – D Command – Dump Memory

4EC1
“DOIT”
LD HL,(CURSOR)
[4020H]
Fetch the value stored at memory location 4020H and put it into Register HL.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
4EC4
LD (SAVCUR),HL
[5054H]
Store the value held in Register HL (i.e., the CURSOR POSITION ON SCREEN) into the memory location 5054H which is in the middle of a LD HL,nnnnH OPCODE.
4EC7
“DOIT0”
LD HL,(SAVCUR)
[5054H]
Fetch the value stored at memory location 5054H (i.e., the CURSOR POSITION ON SCREEN) and put it into Register HL.
4ECA
LD (CURSOR),HL
[4020H]
Store the value held in Register HL (i.e., the CURSOR POSITION ON SCREEN) into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
4ECD
[4FE7H]
LET Register Pair HL = 4FE7H, which is the pointer to the message “ADDRESS? = “.
4ED0
CALL PRINT
[021BH]
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H is found.
4ED3
[521FH]
GOSUB to 521FH to to get input from the user and store it in Register Pair HL (i.e., to get the DUMP address from the User).
4ED6
RET Z
If the Z FLAG (Zero) is set then that CALL returned an error, so RETurn to the caller.
4ED7
PUSH HL
Save Register HL (i.e., the user entered address) to the top of the STACK.
4ED8
LD DE,ENDBUG
[5600H]
LET Register Pair DE = 5600H, as the lowest memory address which a DUMP is permitted.
4EDB
OR A
Set FLAGS based on the contents of Register A.
4EDC
SBC HL,DE
Subtract the value stored in Register Pair DE (i.e., the lowest DUMPable memory location) and the carry flag from the value stored in Register Pair HL (i.e., the requested DUMP location) to see if we are within the limits of the DUMP command.
4EDE
POP HL
Restore Register Pair HL (i.e., the response from the CALL) from the top of the STACK.
4EDF
JR C,DOIT0
[4EC7H]
If the C FLAG (Carry) is set then we are below the limits, so LOOP back to 4EC7H to try again.
4EE1
JR OUT2
[4EF7H]

4EE3H – ; Command – Advance display to the next line.

4EE3
“NXTMEM”
LD BC,0010H
LET Register Pair BC = 0010H (Decimal 16) to move 16 bytes forward.
4EE6
“NXTME0”
LD HL,(MEM+6)
[4106H]
Fetch the value stored at memory location 4106H (i.e., the current DUMP address) and put it into Register HL.
4EE9
LD A,(MEM+1)
[4101H]
Fetch the value stored at memory location 4101H (i.e., the display mode; ZERO for HALF PAGE and NON-ZERO for FULL PAGE) and put it into Register A.
4EEC
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4EED
JR Z,OUT1
[4EF6H]
If the Z FLAG (Zero) is set then we are at HALF PAGE display so JUMP to 4EF6H to bump the display by 16.

We need to process a full screen.

4EEF
LD C,00H
LET Register C = 00H (wiping out the 16 which was put there in 4EE3) to set up for a 256 byte multiple
4EF1
LD A,B
LET Register A = Register B.
4EF2
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4EF3
JR NZ,OUT1
[4EF6H]
If the NZ FLAG (Not Zero) is set, skip the next instruction and JUMP to 4EF6H.
4EF5
INC B
Bump the value stored in Register B by 1 to increase the MSB.
4EF6
“OUT1”
ADD the value held in Register Pair BC to Register Pair HL, so that HL has the new DUMP address.
4EF7
“OUT2”
LD A,L
LET Register A = Register L to prepare to make sure we have a smooth HL value.
4EF8
AND 0F0H
MASK the value of Register A against 0F0H (1111 0000) to make a round number.
4EFA
LD L,A
LET Register L = the masked/smoothed Register A.
4EFB
“OUT4”
LD (MEM+6),HL
[4106H]
Store the value held in Register HL into the memory location 4106H (i.e., the current DUMP address).
4EFE
LD DE,ENDBUG
[5600H]
LET Register Pair DE = 5600H, as the lowest memory address which a DUMP is permitted.
4F01
OR A
Set FLAGS based on the contents of Register A.
4F02
SBC HL,DE
Subtracts the value stored in Register Pair DE (i.e., the lowest DUMPable memory location) and the carry flag from the value stored in Register Pair HL (i.e., the requested DUMP location) to see if we are within the limits of the DUMP command.
4F04
RET NC
If the NC FLAG (No Carry) is set then we are still good on the dump range so, RETurn to the caller.
4F05
LD (MEM+6),DE
[4106H]
OTHERWISE, we need to set a new dump address, so set it to the floor (held in Register Pair DE) and put that into memory location 4106H (i.e., the current DUMP address).
4F09
RET

4F0AH – - Command – Backspace next line.

4F0A
“BCKMEM”
LD BC,0FFF0H
LET Register Pair BC = 0FFF0H (Decimal: -16).
4F0D
JR NXTME0
[4EE6H]
JUMP to 4EE6H of the prior location to do everything the advance line routine does, but with a negative number.

4F0FH – SUBroutine to display the DEBUG screen

4F0F
“DISPLY”
DI
Disable Interrupts.
4F10
LD A,(MEM+1)
[4101H]
Fetch the value stored at memory location 4101H (i.e., the display mode; ZERO for HALF PAGE and NON-ZERO for FULL PAGE) and put it into Register A.
4F13
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4F14
JP NZ,CURS1
[4F93H]
If the NZ FLAG (Not Zero) is set then we are at HALF PAGE display, so JUMP to 4F93H.

We need to process a FULL SCREEN debug screen.

4F17
LD A,1CH
LET Register A = 1CH (ASCII: Clear Screen).
4F19
CALL DSP
[0033H]
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
4F1C
LD HL,3C00H
LET Register Pair HL = 3C00H (i.e., the first screen location).
4F1F
LD (CURSOR),HL
[4020H]
Set the cursor position by storing the value held in Register HL into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
4F22
CALL ONELNE
[4F80H]
GOSUB to 4F80H to display the memory.
4F25
CALL OUTCR
[5273H]
GOSUB to 5273H to display a carriage return.
4F28
LD HL,(CURSOR)
[4020H]
Fetch the value stored at memory location 4020H (i.e., the cursor location on screen) and put it into Register HL.
4F2B
LD (CURSAV),HL
[4F61H]
Store the value held in Register HL (i.e., the cursor location on screen) into the memory location 4F61H.
4F2E
LD BC,00C0H
LET Register Pair BC = 00C0H (Decimal: 192) as an offset to HL to move the cursor down 3 lines.
4F31
ADD the value held in Register Pair BC (the 3 line offset) to Register Pair HL (the current screen position). The results are held in Register Pair HL.
4F32
LD (CURSOR),HL
[4020H]
Store the value held in Register HL into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
4F35
LD HL,DISPL7
[4FA2H]
LET Register Pair HL = 4FA2H so as to point to the message storage area for “SP PC AF ..”.
4F38
CALL PRINT
[021BH]
GOSUB to 021BH to display that message.
NOTE: 021BH will display the character at (HL) until a 03H is found.
4F3B
CALL OUTCR
[5273H]
GOSUB to 5273H to display a carriage return.
4F3E
LD HL,MEM+8
[4108H]
LET Register Pair HL = 4108H to point to the bottom of the REGISTER SAVE area.
4F41
PUSH HL
Save Register HL (i.e., the pointer to the REGISTER SAVE area) to the top of the STACK. In a few instructions we will have a EXchange command to swap this value.
4F42
LD HL,DISPL7
[4FA2H]
LET Register Pair HL = 4FA2H (i.e., the storage location for the message ” AF BC DE HL AF”).
4F45
LD B,0CH
LET Register B = 0CH (Decimal: 12) since there are 12 register pairs.
4F47
“DISPL0”
EX (SP),HL
EXchange the value stored in Register Pair HL (i.e., the storage location for the message ” AF BC DE HL AF”) with the value stored at the top of the STACK (i.e., the pointer to the REGISTER SAVE area).
4F48
LD E,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the LSB of one of the registers) and put it into Register E.
4F49
INC HL
Bump the value stored in Register Pair HL by 1.
4F4A
LD D,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the LSB of one of the registers) and put it into Register D. Now Register Pair DE contains the value of saved register.
4F4B
INC HL
Bump the value stored in Register Pair HL by 1 to point to the LSB of the next register pair in the REGISTER SAVE area.
4F4C
PUSH HL
Save Register HL (i.e., the pointer to the next register pair in the REGISTER SAVE area) to the top of the STACK.
4F4D
EX DE,HL
EXchange the value stored in Register Pair HL (i.e., the pointer to the next register pair in the REGISTER SAVE area) with the value stored in Register Pair DE (i.e., the value of a saved register pair from the REGISTER SAVE area).
4F4E
LD A,H
LET Register A = Register H so that we can display the MSB of the value held for that Register Pair.
4F4F
CALL OUTBYT
[5258H]
4F52
LD A,L
LET Register A = Register H so that we can display the LSB of the value held for that Register Pair.
4F53
CALL OUTBSP
[526CH]
GOSUB to 526CH to display a byte held in Register A (i.e., that LSB) as a two byte ascii value followed by a space.
4F56
LD A,B
LET Register A = Register B (i.e., the counter for the 12 register pairs to dump).
4F57
AND 0BH
MASK the value of Register A against 0BH (0000 1011). This has the effect of turning off bits 7, 6, 5, 4, 2, leaving only bits 3, 1, 0 active.

The effect of masking the counter by 0BH is as follows

Counter
Binary
AND 00001011
Result
12
00010010
0000 0010
2
11
00010001
0000 0001
1
10
00010000
0000 0000
0
09
00001001
0000 1001
9
08
00001000
0000 1000
8
07
00000111
0000 0011
3
06
00000110
0000 0010
2
05
00000101
0000 0001
1
04
00000100
0000 0000
0
03
00000011
0000 0011
3
02
00000010
0000 0010
2
01
00000001
0000 0001
1
4F59
“DISPL5”
CP 08H
Compare the value held in Register A against 08H. Results:
• If Register A equals 08H, the Z FLAG is set.
• If A < 08H, the CARRY FLAG will be set.
• if A >= 08H, the NO CARRY FLAG will be set.
4F5B
POP HL
Restore Register Pair HL (i.e., the pointer to the next register pair in the REGISTER SAVE area) the from the top of the STACK.
4F5C
EX (SP),HL
EXchange the value stored in Register Pair HL (i.e., the pointer to the next register pair in the REGISTER SAVE area) with the value stored at the top of the STACK (i.e., the storage location for the message ” AF BC DE HL AF”).
4F5D
DJNZ DISPL0
[4F47H]
LOOP back to 4F47H until Register B is ZERO.
4F5F
POP HL
Clear the STACK.
4F60
+1=”CURSAV”
LD HL,[CURSAV]
LET Register Pair HL = a value placed by other locations in this overlay into “CURSAV”.
4F63
LD BC,0040H
LET Register Pair BC = 0040H (Decimal: 64) for an offset of one screen line.
4F66
ADD the value held in Register Pair BC (i.e., one screen line offset) to Register Pair HL (i.e., the saved cursor location). The results are held in Register Pair HL.
4F67
LD (CURSOR),HL
[4020H]
Store the value held in Register HL (i.e., the advanced by one line cursor location) into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
4F6A
LD HL,4FD7H
LET Register Pair HL = 4FD7H, which points to the message PC.
4F6D
CALL PRINT
[021BH]
GOSUB to 021BH to display that message.
NOTE: 021BH will display the character at (HL) until a 03H is found.
4F70
CALL OUTSPC
[526FH]
GOSUB to 526FH to display a space.
4F73
LD HL,(MEM+30)
[411EH]
Fetch the value stored at memory location 411EH (i.e., the Program Counter for the running program MINUS 1) and put it into Register HL.
4F76
LD B,10H
LET Register B = 10H (Decimal: 16) to set up for a loop of 16.
4F78
“CURSA1”
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
4F79
CALL OUTBSP
[526CH]
GOSUB to 526CH to print a byte held in Register A as a two byte ascii value followed by a space.
4F7C
INC HL
Bump Register Pair HL to point to the next byte.
4F7D
DJNZ CURSA1
[4F78H]
LOOP back to 4F78H until Register B is ZERO.
4F7F
RET

4F80H – SUBroutine to display RAM locations.

4F80
“ONELNE”
LD HL,(MEM+6)
[4106H]
Fetch the value stored at memory location 4106H (i.e., the current DUMP ADDRESS) and put it into Register HL.
4F83
LD B,08H
LET Register B = 08H to set up for a DJNZ loop of 8 iterations for 8 rows.
4F85
“LOOP1”
CALL OUTWRD
[5253H]
4F88
CALL OUTSPC
[526FH]
GOSUB to 526FH to display a space.
4F8B
CALL OUTLNE
[51B1H]
GOSUB to 51B1H to display a data line.
4F8E
DJNZ LOOP1
[4F85H]
LOOP back to 4F85H until Register B is ZERO (i.e., 8 iterations).
4F90
JP OUTCLR
[5277H]
JUMP to 5277H to clear the rest of the screen and exit.

4F93H – Continuation of the SUBroutine to display the DEBUG screen, jumped if we need a half Page display

4F93
“CURS1”
LD HL,3C00H
LET Register Pair HL = 3C00H, which is the top of the screen.
4F96
LD (CURSOR),HL
[4020H]
Store the value held in Register HL into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
4F99
LD HL,(MEM+6)
[4106H]
Fetch the value stored at memory location 4106H (i.e., the address to display) and put it into Register HL.
4F9C
LD L,00H
LET Register L = 00H to have a smooth address / even page in HL.
4F9E
LD B,10H
LET Register B = 10H (Decimal: 16) for a loop of 16 rows to display.
4FA0
JP LOOP1
[4F85H]

4FA2H – Message Storage Area

4FA2
“DISPL7”
DEFM
” AF BC DE HL AF’ B C’ DE’ HL’ IX IY SP PC ” + 03H
4FDF
“FLAGS”
DEFM
“SZ1H1POC”
4FE6
DEFM
1EH + ” ADDRESS? = “ + 1EH + 0EH + 03H

4FF7 – Routine to process “G” and “J” by JUMPing to a specified address.

4FF7
“GO”
[4FE7H]
LET Register Pair HL = 4FE7H, which is the pointer to the message “ADDRESS? = “.
4FFA
CALL PRINT
[021BH]
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H is found.
4FFD
LD B,02H
LET Register B = 02H, as there are two breakpoint locations.
4FFF
LD DE,MEM+5
[4105H]
LET Register Pair DE = 4105H to point to the breakpoint storage area.
5002
[521FH]
GOSUB to 521FH to to get input from the user and store it in Register Pair HL (i.e., the JUMP address).
5005
JR Z,GO1
[500AH]
If the Z FLAG (Zero) is set, meaning that no address was given, we will default to the PROGRAM COUNTER, so JUMP to 500AH.
5007
LD (MEM+30),HL
[411EH]
If we are here, we were given a JUMP ADDRESS, so store the value held in Register HL into the memory location 411EH (i.e., the Program Counter for the running program MINUS 1).
500A
“GO1”
JR C,GO2
[5016H]
If the C FLAG (Carry) is set then we are out of input, JUMP to 5016H.
500C
[521FH]
GOSUB to 521FH to get input from the user and store it in Register Pair HL (i.e., the breakpoint).
500F
PUSH AF
Save Register AF to the top of the STACK.
5010
CALL NZ,SET
[503CH]
If the NZ FLAG (Not Zero) is set then we need to save the breakpoint into a table, so GOSUB to 503CH.
5013
POP AF
Restore Register Pair AF from the top of the STACK.
5014
DJNZ GO1
[500AH]
LOOP back to 500AH until Register B is ZERO (i.e., both breakpoints have been processed).
5016
“GO2”
“MISS1”
LD HL,MEM+29
[411DH]
LET Register Pair HL = 411DH to point to the REGISTER SAVE AREA
5019
LD B,0BH
LET Register B = 0BH (Decimal: 11) for a loop of 11 Register Pairs.
501B
“GO3”
LD D,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the MSB byte of any of the 12 register pairs) and put it into Register D.
501C
DEC HL
DECrement the value stored in Register Pair HL by 1 so as to point to the LSB of that register pair.
501D
LD E,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the LSB byte of any of the 12 register pairs) and put it into Register E.
501E
DEC HL
DECrement the value stored in Register Pair HL by 1 so as to point to the MSB of the next register pair.
501F
PUSH DE
Save Register DE to the top of the STACK.
5020
DJNZ GO3
[501BH]
LOOP back to 501BH until all 12 register pairs have been retrieved from RAM and put into the STACK.

Restore all the registers

5022
POP AF
Restore Register Pair AF from the top of the STACK.
5023
POP BC
Restore Register Pair BC from the top of the STACK.
5024
POP DE
Restore Register Pair DE from the top of the STACK.
5025
POP HL
Restore Register Pair HL from the top of the STACK.
5026
EX AF,AF’
EXchange the value stored in Register Pair AF’ with the value stored in Register Pair AF.
5027
EXX

5028
POP AF
Restore Register Pair AF from the top of the STACK.
5029
POP BC
Restore Register Pair BC from the top of the STACK.
502A
POP DE
Restore Register Pair DE from the top of the STACK.
502B
POP HL
Restore Register Pair HL from the top of the STACK.
502C
EX AF,AF’
EXchange the value stored in Register Pair AF’ with the value stored in Register Pair AF.
502D
EXX

502E
POP IX
Restore Register Pair IX from the top of the STACK.
5030
POP IY
Restore Register Pair IY from the top of the STACK.
5032
POP HL
Restore Register Pair HL from the top of the STACK.
5033
LD SP,HL
LET Register Pair SP = Register Pair HL.
5034
LD HL,(MEM+30)
[411EH]
Fetch the value stored at memory location 411EH (i.e., the Program Counter for the running program MINUS 1) and put it into Register HL.
5037
PUSH HL
Save Register HL (i.e., the Program Counter for the running program MINUS 1) to the top of the STACK.
5038
LD HL,(MEM+14)
[410EH]
Fetch the value stored at memory location 410EH (i.e., the saved value for Register Pair HL) and put it into Register HL.
503B
RET
Run the calling program.

503CH – SUBroutine to Save the Breakpoint into a Table (done backwards)

503C
“SET”
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., which would be an OPCODE) and put it into Register A.
503D
LD (DE),A
Store the value held in Register A (i.e., the OPCODE) into the memory location pointed to by Register Pair DE (i.e., the BREAKPOINT STORAGE TABLE).
503E
DEC DE
DECrement the value stored in Register Pair DE by 1 to back up one byte in the table
503F
LD A,0F7H
LET Register A = 0F7H (OPCODE: RST 30H).
5041
LD (HL),A
Store the value held in Register A (i.e., RST 30H) into the memory location pointed to by Register Pair HL (i.e., to overwrite the existing OPCODE).
5042
CP (HL)
Compare the value held in Register A against the value held in the memory location (HL) to verify it was written correctly. Results: If Register A equals (HL), the Z FLAG is set; otherwise the NZ FLAG is set.
5043
JP NZ,START2
[4E35H]
If the NZ FLAG (Not Zero) is set then the byte was not written to RAM correctly, so JUMP to 4E35H.
5046
LD A,H
LET Register A = Register H (i.e., the MSB of the breakpoint address).
5047
LD (DE),A
Store the value held in Register A (i.e., the MSB of the breakpoint address) into the memory location pointed to by Register Pair DE.
5048
DEC DE
DECrement the value stored in Register Pair DE by 1 to back up one byte in the table.
5049
LD A,L
LET Register A = Register L (i.e., the LSB of the breakpoint address).
504A
LD (DE),A
Store the value held in Register A (i.e., the LSB of the breakpoint address) into the memory location pointed to by Register Pair DE.
504B
DEC DE
DECrement the value stored in Register Pair DE by 1 to back up one byte in the table.
504C
RET

504DH – Routine to MODIFY AND DISPLAY RAM – the “M” option.

504D
“MEMORY”
LD HL,(CURSOR)
[4020H]
Fetch the cursor position (i.e., stored at memory location 4020H) and put it into Register HL.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5050
LD (SAVCUR),HL
[5054H]
Store the value held in Register HL (i.e., the cursor position on screen) into the memory location 5054H.
5053
+1=”MEMOR0″
LD HL,”MEMOR0″
LET Register Pair HL = nnnnH. Other locations in this routine set this value to be the CURSOR LOCATION ON SCREEN. 5054H is referred to as “SAVCUR”
5056
LD (SAVCUR),HL
[5054H]
Store the value held in Register HL (i.e., the cursor position on screen) into the memory location 5054H.
5059
[4FE7H]
LET Register Pair HL = 4FE7H so as to point to the “ADDRESS” message.
505C
CALL PRINT
[021BH]
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H is found.
505F
LD HL,(MEM+3)
[4103H]
Fetch the value stored at memory location 4103H (i.e., the old dump address) and put it into Register HL just in case we get a NULL answer.
5062
[521FH]
GOSUB to 521FH to get input from the user and store it in Register Pair HL (i.e., the new address).
5065
RET C
If the C FLAG (Carry) is set then we got a value which is invalid so, RETurn to the caller.
5066
PUSH HL
Save Register HL (i.e., the address we got from the user) to the top of the STACK.
5067
LD DE,ENDBUG
[5600H]
LET Register Pair DE = 5600H, as the lowest memory address which a DUMP is permitted.
506A
OR A
Set FLAGS based on the contents of Register A.
506B
SBC HL,DE
Subtract the value stored in Register Pair DE (i.e., the lowest DUMPable memory location) and the carry flag from the value stored in Register Pair HL (i.e., the requested DUMP location) to see if we are within the limits of the DUMP command.
506D
POP HL
Restore Register Pair HL (i.e., the response from the user) from the top of the STACK.
506E
JR C,MEMOR0
[5053H]
If the C FLAG (Carry) is set then we are below the limits, so LOOP back to 5053H to try again.
5070
LD (WHERE),HL
[554FH]
Store the value held in Register HL (i.e., the response from the user) into the memory location 554FH.
5073
LD L,00H
LET Register L = 00H so that Register Pair HL is smooth (i.e., nn00H)
5075
LD (MEM+3),HL
[4103H]
Store the value held in Register HL (i.e., the smoothed response from the user) into the memory location 4103H (i.e., the new default).
5078
LD A,H
LET Register A = Register H (i.e., the MSB of the smoothed response from the user).
5079
LD (NRN),A
[555FH]
Store the value held in Register A into the memory location 555FH.

We need to set some flags to indicate that this is a MEMORY routine and not a DISK routine.

507C
XOR A
Set Register A to ZERO and clear all Flags.
507D
LD (NRN+1),A
[5560H]
Store the value held in Register A (i.e., a ZERO) into the memory location 5560H.
5080
DEC A
DECrement the value stored in Register A by 1, thus tripping the NZ Flag and setting Register A to FFH.
5081
LD (MODDSK),A
[545FH]
Store the value held in Register A (i.e., FFH) into the memory location 545FH to indicate that MEMORY is being changed. 545FH is in the middle of a LD A,(nn)” OPCODE, with FF=Memory and anything else =Disk
5084
LD (MOVFLG),A
[5553H]
Store the value held in Register A (i.e., FFH) into the memory location 5553H to indicate that we need to display the cursor.
5087
JP BACK
[544FH]

508AH – Command “R” – Modify the User Registers

508A
REGIST
CALL KEYLIN
[51F1H]
GOSUB to 51F1H to get character from the keyboard and process accordingly.
508D
RET Z
If the Z FLAG (Zero) is set then we had an unusable response from the user from that CALL, so RETurn to the caller.
508E
LD C,A
LET Register C = Register A (i.e., the first character of the desired register name).
508F
CALL KEYLIN
[51F1H]
GOSUB to 51F1H to get character from the keyboard and process accordingly..
5092
RET Z
If the Z FLAG (Zero) is set, then we got a null character, so RETurn to the caller.
5093
LD D,A
LET Register D = Register A (i.e., the second character of the user desired register name).
5094
LD E,20H
LET Register E = 20H (ASCII: SPACE) so that the default for the third character will be a SPACE.
5096
CALL KEYLIN
[51F1H]
GOSUB to 51F1H to get character from the keyboard and process accordingly..
5099
RET C
If the C FLAG (Carry) is set then the result is NOT a SPACE so RETurn to the caller.
509A
JR Z,REG1
[50A2H]
If the Z FLAG (Zero) is set, meaning that the result is not a SPACE, JUMP to 50A2H.
509C
LD E,A
LET Register E = Register A (i.e., the third character of the user desired register name).
509D
CALL KEYLIN
[51F1H]
GOSUB to 51F1H to get character from the keyboard and process accordingly..
50A0
RET NZ
If the NZ FLAG (Not Zero) is set, meaning that the result is not a SPACE, so RETurn to caller with the NZ FLAG set (to signify an error).
50A1
RET C
If the C FLAG (Carry) is set, meaning that the result is not a SPACE, RETurn to the caller.
50A2
“REG1”
LD HL,DISPL7+1
[4FA3H]
LET Register Pair HL = 4FA3H, which is the pointer to the message “AF BC DE HL AF”. The reason it is +1 is that this message normally starts with a space, which is being skipped here.
50A5
LD B,0CH
LET Register B = 0CH (Decimal: 12) since there are 12 register pairs.
50A7
“REG2”
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., an entry from the REGISTER STORAGE table) and put it into Register A.
50A8
CP C
Compare the value held in Register A (i.e., an entry from the REGISTER STORAGE table) against the value held in Register C (i.e., the first character received from the user for the desired register name) . Results: If Register A equals C, the Z FLAG is set; otherwise the NZ FLAG is set.
50A9
JR Z,REG5
[50B6H]
If the Z FLAG (Zero) is set then the first character requested by the user matches the character found in the REGISTER STORAGE table, so JUMP to 50B6H.

While there is one INC HL which is definitely used, the following two INC HL’s are jump points; this is all to advance HL to the next entry in the REGISTER STORAGE TABLE, which may be 3, 2, or 1 character away.

50AB
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next record in the REGISTER STORAGE TABLE.
50AC
“REG3”
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next record in the REGISTER STORAGE TABLE.
“REG4”
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next record in the REGISTER STORAGE TABLE.
50AE
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., an entry from the REGISTER STORAGE table) and put it into Register A.
50AF
CP 20H
Compare the value held in Register A against 20H (i.e., an ASCII SPACE. Results: If Register A equals SPACE, the Z FLAG is set; otherwise the NZ FLAG is set.
50B1
JR Z,REG4
If the Z FLAG (Zero) is set then we had a SPACE, JUMP back to the INC HL’s to skip forward.
50B3
DJNZ REG2
[50A7H]
LOOP back to 50A7H until all 12 register pairs have been handled (i.e., Register B is ZERO).
50B5
RET

50B6H – Continuation of the “R” Command. Jumped here when we have a first character match between the user requested register and the register storage table.

50B6
“REG5”
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next character in the REGISTER STORAGE TABLE.
50B7
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., next character in the REGISTER STORAGE TABLE) the and put it into Register A.
50B8
CP D
Compare the value held in Register A (i.e., next character in the REGISTER STORAGE TABLE) against the value held in Register D (i.e., the second character of the user desired register name). Results: If Register A equals D, the Z FLAG is set; otherwise the NZ FLAG is set.
50B9
JR NZ,REG3
[50ACH]
If the NZ FLAG (Not Zero) is set then we do NOT have a match on the 2nd character, so JUMP to 50ACH to skip forward a sufficient number of entries in the REGISTER STORAGE TABLE and continue processing.
50BB
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next character in the REGISTER STORAGE TABLE.
50BC
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., next character in the REGISTER STORAGE TABLE) and put it into Register A.
50BD
CP E
Compare the value held in Register A (i.e., next character in the REGISTER STORAGE TABLE) against the value held in Register E (i.e., the third character of the user desired register name). Results: If Register A equals E, the Z FLAG is set; otherwise the NZ FLAG is set.
50BE
JR NZ,REG4
If the NZ FLAG (Not Zero) is set, then the THIRD character in the user desired register was NOT a match, so JUMP to 50ADH to skip forward a sufficient number of entries in the REGISTER STORAGE TABLE and continue processing.

If we are here then all 3 of the characters entered by the user for the desired register to modify have been found. With this, we need to do some math to find the location of the matched register pair with the stored value for that register pair. Register B holds the counter where we stopped parsing register pairs.

50C0
LD A,18H
LET Register A = 18H (Decimal: 24).
50C2
SUB B
SUBtract the value held in Register B (i.e., the stopping point of the backwards countdown searching for register name matches in the REGISTER STORAGE TABLE) from Register A.
50C3
SUB B
SUBtract the value held in Register B (i.e., the stopping point of the backwards countdown searching for register name matches in the REGISTER STORAGE TABLE) from Register A.
50C4
LD C,A
LET Register C = Register A (i.e., 24 – B*2).
50C5
LD B,00H
LET Register B = 00H so that Register Pair BC = Register C.
50C7
LD HL,MEM+8
[4108H]
LET Register Pair HL = 4108H to point to the bottom of the REGISTER SAVE area.
50CA
ADD the value held in Register Pair BC (i.e., 24 – 2 x the stopping point of the register name search) to Register Pair HL (i.e., the bottom of the REGISTER SAVE are). The results are held in Register Pair HL.
50CB
PUSH HL
Save Register HL (i.e., the location of the VALUE of the register sought) to the top of the STACK.
50CC
LD A,1EH
LET Register A = 1EH (ASCII: to erase to end of line)
50CE
CALL DSP
[0033H]
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
50D1
POP DE
Restore the top of the STACK (i.e., the location of the VALUE of the register sought) into Register Pair DE.
50D2
[521FH]
GOSUB to 521FH to get input from the user and store it in Register Pair HL (i.e., the new value for the register pair).
50D5
RET Z
If the Z FLAG (Zero) is set, meaning we didn’t get anything from the user, RETurn to the caller.
50D6
EX DE,HL
EXchange the value stored in Register Pair HL (i.e., the user supplied new value for the register pair) with the value stored in Register Pair DE (i.e., the location of the VALUE of the register sought).
50D7
LD (HL),E
Store the value held in Register E (i.e., the LSB of the user supplied new value for the register pair) into the memory location pointed to by Register Pair HL (i.e., the location of the VALUE of the register sought).
50D8
INC HL
Bump the value stored in Register Pair HL by 1.
50D9
LD (HL),D
Store the value held in Register D (i.e., the MSB of the user supplied new value for the register pair) into the memory location pointed to by Register Pair HL (i.e., the location of the VALUE of the register sought).
50DA
RET

50DBH – “I” and “C” Commands – Instruction Step / Call Step Single Step Routines

50DB
“SINGLE”
PUSH AF
Save Register AF (i.e., the COMMAND issued; either “I” or “C”) to the top of the STACK.
50DC
LD DE,(MEM+30)
[411EH]
Fetch the value stored at memory location 411EH (i.e., the Program Counter for the running program MINUS 1) and put it into Register DE.
50E0
LD A,(DE)
Fetch the value stored (i.e., the OPCODE which was to run next) at memory location pointed to by Register Pair DE (i.e., the Program Counter for the running program MINUS 1) and put it into Register A.
50E1
LD HL,TABLE3
[5195H]
LET Register Pair HL = 5195H, which is the pointer to the “IX”/”IY” OPCODE table.
50E4
CP 0DDH
Compare the value held in Register A (i.e., the OPCODE which was to run next) against 0DDH (i.e., IX OPCODE). Results: If Register A equals 0DDH (i.e., IX OPCODE), the Z FLAG is set; otherwise the NZ FLAG is set.
50E6
JR Z,SINGL1
[50F6H]
If the Z FLAG (Zero) is set then we have an (i.e., IX OPCODE), so JUMP to 50F6H.
50E8
CP 0FDH
Compare the value held in Register A (i.e., the OPCODE which was to run next) against 0FDH (i.e., IY OPCODE). Results: If Register A equals 0FDH (i.e., IY OPCODE), the Z FLAG is set; otherwise the NZ FLAG is set.
50EA
JR Z,SINGL1
[50F6H]
If the Z FLAG (Zero) is set then we have an IY OPCODE, so JUMP to 50F6H.
50EC
LD HL,TABLE1
[5160H]
LET Register Pair HL = 5160H, which is the pointer to the “NORMAL” OPCODE table.
50EF
CP 0EDH
Compare the value held in Register A (i.e., the OPCODE which was to run next) against 0EDH (i.e., MISC OPCODE). Results: If Register A equals 0EDH (i.e., MISC OPCODE), the Z FLAG is set; otherwise the NZ FLAG is set.
50F1
JR NZ,SINGL2
[50F9H]
If the NZ FLAG (Not Zero) is set, then we do not have a MISC OPCODE, so JUMP to 50F9H.
50F3
LD HL,TABLE2
[518EH]
LET Register Pair HL = 518EH, which is the pointer to the “MISC” OPCODE table.
50F6
“SINGL1”
INC DE
Bump the value stored in Register Pair DE by 1 so as to point to the next byte of the the OPCODE which was to run next.
50F7
LD A,(DE)
Fetch the value stored at memory location pointed to by Register Pair DE (i.e., the second byte of the the OPCODE which was to run next) and put it into Register A.
50F8
DEC DE
DECrement the value stored in Register Pair DE by 1 so as to point to the first opcode which was next to run.
50F9
“SINGL2”
LD C,A
LET Register C = Register A (i.e., the second byte of the the OPCODE which was to run next).
50FA
“SINGL3”
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the bit mask stored in the OPCODE LOOKUP TABLE) and put it into Register A.
50FB
AND C
MASK the value of Register A (i.e., the bit mask stored in the OPCODE LOOKUP TABLE) against the value held in Register C (i.e., the second byte of the the OPCODE which was to run next).
50FC
INC HL
Bump the value stored in Register Pair HL by 1 so as to point to the next entry in the OPCODE LOOKUP TABLE.
50FD
CP (HL)
Compare the value held in Register A (i.e., the bit masked second byte of the OPCODE which was next to bne run) against the value held in the memory location (HL) to determine if this was the correct class of OPCODE. Results:
• If Register A equals (HL), the Z FLAG is set.
• If A < (HL), the CARRY FLAG will be set.
• if A >= (HL), the NO CARRY FLAG will be set.
50FE
INC HL
Bump the value stored in Register Pair HL by 1 so as to point to the next byte in the OPCODE LOOKUP TABLE.
50FF
JR Z,SINGL4
[5107H]
If the Z FLAG (Zero) is set, then we did have the correct class, so JUMP to 5107H.
5101
INC HL
Bump the value stored in Register Pair HL by 1 so as to point to the next byte in the OPCODE LOOKUP TABLE.
5102
LD A,(HL)
Fetch the value stored at memory location (i.e., the OPTIONS BYTE) pointed to by Register Pair HL (i.e., a byte in the OPCODE LOOKUP TABLE) and put it into Register A.
5103
CP 05H
Compare the value held in Register A against 05H, which is the delimter to indicate the end of the applicable OPCODE TABLE. Results:
• If Register A equals 05H, the Z FLAG is set.
• If A < 05H, the CARRY FLAG will be set.
• if A >= 05H, the NO CARRY FLAG will be set.
5105
JR NC,SINGL3
[50FAH]
If the NC FLAG (No Carry) is set, then we have not yet reached the end of the applicable OPCODE TABLE, so LOOP BACK to 50FAH.
5107
SINGL4
LD A,(HL)
Fetch the value stored at memory location (i.e., the OPTIONS BYTE) pointed to by Register Pair HL (i.e., a byte in the OPCODE LOOKUP TABLE) and put it into Register A.
5108
LD B,A
LET Register B = Register A (i.e., the OPTIONS BYTE).
5109
AND 0FH
MASK the value of Register A against 0FH (0000 1111). This has the effect of turning off bits 7, 6, 5, 4, leaving only bits 3, 2, 1, 0 active so as to enable us to determine the length of the instruction.
510B
LD L,A
LET Register L = Register A (i.e., the masked OPTIONS BYTE).
510C
LD H,00H
LET Register H = 00H, so that Register Pair HL = Register A (i.e., the masked OPTIONS BYTE).
510E
ADD the value held in Register Pair DE to Register Pair HL so that HL will now point to the first breakpoint.
510F
PUSH DE
Save Register DE to the top of the STACK because we are about to use Register Pair DE for something else.
5110
LD DE,MEM+5
[4105H]
LET Register Pair DE = 4105H to point to the breakpoint storage area.
5113
CALL SET
[503CH]
GOSUB to 503CH to save the breakpoint into a Table.
5116
POP HL
Restore the contents the top of the STACK (i.e., the breakpoint address) into Register Pair HL.
5117
LD A,B
LET Register A = Register B (i.e., the OPTIONS BYTE).
5118
AND 0F0H
MASK the value of Register A against 0F0H (1111 0000). This has the effect of turning off bits 7, 6, 5, 4, leaving only bits 3, 2, 1, 0 active so as to enable us to determine the branching option.
511A
JR Z,SINGL5
[5132H]
If the Z FLAG (Zero) is set then there was no branching portion of that OPCODE so JUMP to 5132H.
511C
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next table byte.
511D
CP 20H
Compare the value held in Register A against 20H to look for a JP (regname) command. Results:
• If Register A equals 20H, the Z FLAG is set.
• If A < 20H, the CARRY FLAG will be set.
• if A >= 20H, the NO CARRY FLAG will be set.
511F
JR C,SINGLA
[5158H]
If the C FLAG (Carry) is set then we have a JP (HL) situation, so JUMP to 5158H.
5121
JR Z,SINGL9
[514CH]
If the Z FLAG (Zero) is set then we have a JP (IX) or JP (IY) situation, so JUMP to 514CH.
5123
CP 40H
Compare the value held in Register A against 40H to look for a JP or JR command. Results:
• If Register A equals 40H, the Z FLAG is set.
• If A < 40H, the CARRY FLAG will be set.
• if A >= 40H, the NO CARRY FLAG will be set.
5125
JR C,SING70
[5140H]
If the C FLAG (Carry) is set we have a JR command, so JUMP to 5140H.
5127
JR Z,SINGL7
[5138H]
If the Z FLAG (Zero) is set we have a JP, so JUMP to 5138H.
5129
CP 60H
Compare the value held in Register A against 60H to look for a RET or CALL command. Results:
• If Register A equals 60H, the Z FLAG is set.
• If A < 60H, the CARRY FLAG will be set.
• if A >= 60H, the NO CARRY FLAG will be set.
512B
JR C,SINGL6
[5135H]
If the C FLAG (Carry) is set we have a RET command, so JUMP to 5135H.
512D
POP AF
If we are here, we have a CALL command. Restore Register Pair AF (i.e., the user command of either “C” or “I”) from the top of the STACK.
512E
CP 49H
Compare the value held in Register A against 49H (ASCII: I). Results: If Register A equals I, the Z FLAG is set; otherwise the NZ FLAG is set.
5130
JR Z,SINGL7
[5138H]
If the Z FLAG (Zero) is set, then we had an I command, so JUMP to 5138H.
5132
“SINGL5”
JP MISS1
[5016H]

5135H – Continuation of the “I”/”C” routine – Set a BREAKPOINT for either RET or JP.

If the next opcode was a RET

5135
“SINGL6”
LD HL,(MEM+28)
[411CH]
Fetch the value stored at memory location 411CH (i.e., the old STACK POINTER) and put it into Register HL.

If the next opcode was a JP or CALL.

5138
“SINGL7”
PUSH AF
Save Register AF to the top of the STACK.
5139
LD A,(HL)
Fetch the value stored at memory location (i.e., the LSB byte from the return address contained in the old STACK POINTER) pointed to by Register Pair HL (i.e., the old STACK POINTER) and put it into Register A.
513A
INC HL
Bump the value stored in Register Pair HL (i.e., the old STACK POINTER) by 1.
513B
LD H,(HL)
Fetch the value stored at memory location (i.e., the MSB byte from the return address contained in the old STACK POINTER) pointed to by Register Pair HL (i.e., the old STACK POINTER) and put it into Register H.
513C
LD L,A
LET Register L = Register A (i.e., the LSB byte from the return address contained in the old STACK POINTER).
513D
POP AF
Restore Register Pair AF from the top of the STACK.
513E
JR SINGLB
[515BH]

5140H – Continuation of the “I”/”C” routine – Set a BREAKPOINT for either RET or JP.

5140
“SING70”
LD C,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register C.
5141
XOR A
Set Register A to ZERO and clear all Flags as we are about to do some math.
5142
BIT 7,C
Test Bit 7 of Register C to see if the offset is backwards of forwards.
5144
JR Z,SINGL8
[5147H]
If the Z FLAG (Zero) is set, then the offset is BACKWARDS, so skip the next instruction and JUMP to 5147H.
5146
CPL
Complement Register A (i.e., rotated the bits right one bit position, with Bit 0 copied to the CARRY FLAG, and the previous contents of the CARRY FLAG are copied to bit 7). This has the effect of making the MSB into a 0FFH.
5147
“SINGL8”
LD B,A
LET Register B = Register A (i.e., the MSB).
5148
INC HL
Bump the value stored in Register Pair HL by 1.
5149
ADD the value held in Register Pair BC (i.e., the displacement) to Register Pair HL. The results are held in Register Pair HL.
514A
JR SINGLB
[515BH]

514CH – Continuation of the “I”/”C” routine – Set a BREAKPOINT for either JP (IX) or JP (IY).

514C
“SINGL9”
LD HL,(MEM+24)
[4118H]
Fetch the value stored at memory location 4118H (i.e., the saved IX) and put it into Register HL.
514F
BIT 5,C
Test Bit 5 of Register C to make sure we are using IX.
5151
JR Z,SINGLB
[515BH]
If the Z FLAG (Zero) is set, then we are using IX, so JUMP to 515BH to set a breakpoint and continue.
5153
LD HL,(MEM+26)
[411AH]
Fetch the value stored at memory location 411AH (i.e., the saved IY) and put it into Register HL.
5156
JR SINGL5
[515BH]

5158H – Continuation of the “I”/”C” routine – Set a BREAKPOINT for either JP (HL).

5158
“SINGLA”
LD HL,(MEM+14)
[410EH]
Fetch the value stored at memory location 410EH (i.e., the saved HL) and put it into Register HL.
515B
“SINGLB”
CALL SET
[503CH]
GOSUB to 503CH to save HL as the breakpoint address.
515E
JR SINGL5
[5132H]

5160H – OPCODE TABLE – “NORMAL” OPCODES

OPCODE
Option
Coded
Value
5160
“TABLE1”
RET CC
RET
51
5163
RET
RET
51
5166
JP (HL)
JP (HL)
11
5169
LD dd,nnnn

03
516C
LD R,(nnnn)

03
516F
JP cc,nnnn
JP
43
5172
JP nnnn
JP
63
5175
CALL cc,nnnn
CALL
63
5178
CALL nnnn
CALL
63
517B
LD R,nn

02
517E
OUT (nn),A

02
5181

02
5184
BIT nn,R

02
5187
DJNZ or JR
JR
32
518A
JR cc,dis
JR
32
518D
END OF TABLE

01

518EH – OPCODE TABLE – “ED” OPCODES

OPCODE
Option
Coded
Value
518E
LD dd,(nnnn)

04
5191
RETI,RETN
RET
52
5194
END OF TABLE

02

5195H – OPCODE TABLE – “DD” and “FD” OPCODES

OPCODE
Option
Coded
Value
5195
INC

03
5198
LD

03
519B

03
519E
LD

04
51A1
LD

04
51A4
LD

04
51A7
LD

04
51AA
BIT

04
JP (IX),JP (IY)
JP (IX),JP (IY)
22
51B0
END OF TABLE

01

51B1H – Display One Line of Memory

51B1
“OUTLNE”
PUSH BC
Save Register Pair BC (i.e., the counter) to the top of the STACK.
51B2
PUSH HL
Save Register Pair HL (i.e., the RAM DATA pointer) to the top of the STACK.
51B3
LD B,08H
LET Register B = 08H for an 8 byte DJNZ loop
51B5
“OUTLN1”
CALL OUTSPC
[526FH]
GOSUB to 526FH to display a SPACE.
51B8
CALL OUTLOC
[524FH]
GOSUB to 524FH to display the MSB of the address.
51BB
CALL OUTLOC
[524FH]
GOSUB to 524FH to display the LSB of the address.
51BE
LD A,B
LET Register A = Register B (i.e., the counter).
51BF
CP 05H
Compare the value held in Register A against 05H to see if we are in the middle of the screen. Results: If Register A equals 05H, the Z FLAG is set; otherwise the NZ FLAG is set.
51C1
CALL Z,OUTSPC
[526FH]
If the Z FLAG (Zero) is set then we are at the middle of the screen so display one extra SPACE by GOSUB to 526FH.
51C4
DJNZ OUTLN1
[51B5H]
LOOP back to 51B5H until Register B is ZERO.
51C6
POP HL
Restore Register Pair HL (i.e., the RAM DATA pointer) from the top of the STACK.
51C7
GOSUB to 526FH to display a SPACE.
51CA
LD B,10H
LET Register B = 10H (Decimal: 16) to prepare for a loop of 16 characters.
51CC
“OUTLN2”
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
51CD
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE). Results:
• If Register A equals a SPACE, the Z FLAG is set.
• If A < 20H, the CARRY FLAG will be set.
• if A >= 20H, the NO CARRY FLAG will be set.
51CF
JR C,PERIOD
[51D5H]
If the C FLAG (Carry) is set then we have a CONTROL CHARACTER we need to alter it by JUMPing to 51D5H.
51D1
CP 7BH
Compare the value held in Register A against 7BH (ASCII: The first graphic character). Results:
• If Register A equals 7BH, the Z FLAG is set.
• If A < 7BH, the CARRY FLAG will be set.
• if A >= 7BH, the NO CARRY FLAG will be set.
51D3
JR C,OUTLN3
[51D7H]
If the C FLAG (Carry) is set then we do NOT have a graphic character, so skip 1 instruction and JUMP to 51D7H to display it.
51D5
“PERIOD”
LD A,2EH
LET Register A = 2EH (ASCII: .).
51D7
“OUTLN3”
CALL 0033H
[CALL DSP]
GOSUB to 0033H to display the character.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
51DA
INC HL
Bump HL so that it points to the next character in the RAM DATA area.
51DB
DJNZ OUTLN2
[51CCH]
LOOP BACK to 51CCH for 16 iterations (i.e., until Register B is ZERO).
51DD
PUSH HL
Save Register HL (i.e., the RAM DATA POINTER) to the top of the STACK.
51DE
LD HL,(CURSOR)
[4020H]
Fetch the value stored at memory location 4020H and put it into Register HL.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
51E1
LD BC,3FE0H
LET Register Pair BC = 3FE0H, which is the last row on the screen
51E4
OR A
Set FLAGS based on the contents of Register A.
51E5
SBC HL,BC
Subtracts the value stored in Register Pair BC (i.e., the last row on the screen) and the carry flag from the value stored in Register Pair HL (i.e., the cursor position).
51E7
POP HL
Restore Register Pair HL (i.e., the RAM DATA POINTER) from the top of the STACK.
51E8
JR NC,OUTLN4
[51EFH]
If the NC FLAG (No Carry) is set, then BC-HL didn’t result in a CARRY, meaning that we on the last row of the screen, so JUMP to 51EFH to skip displaying a carriage return.
51EA
LD A,0DH
LET Register A = 0DH (ASCII: CARRIAGE RETURN).
51EC
CALL DSP
[0033H]
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
51EF
“OUTLN4”
POP BC
Restore Register Pair BC (i.e., the counter) from the top of the STACK.
51F0
RET

51F1H – SUBROUTINE to get a character from the keyboard and process accordingly.

51F1
“KEYLIN”
PUSH DE
Save Register DE to the top of the STACK.
51F2
“KEYLN0”
CALL KEY
[0049H]
GOSUB to 0049H in the ROM to get a character from the keyboard.
51F5
CP 0DH
Compare the value held in Register A against 0DH (ASCII: CARRIAGE RETURN). Results: If Register A equals CARRIAGE RETURN, the Z FLAG is set; otherwise the NZ FLAG is set.
51F7
JR Z,KEYLN1
[5217H]
If the Z FLAG (Zero) is set then we have a CARRIAGE RETURN, so JUMP to 5217H.
51F9
CP 08H
Compare the value held in Register A against 08H (ASCII: ). Results: If Register A equals LEFT ARROW, the Z FLAG is set; otherwise the NZ FLAG is set.
51FB
JR Z,KEYLN1
[5217H]
If the Z FLAG (Zero) is set then we have a LEFT ARROW, so JUMP to 5217H.
51FD
CP 0AH
Compare the value held in Register A against 0AH (ASCII: ). Results: If Register A equals DOWN ARROW, the Z FLAG is set; otherwise the NZ FLAG is set.
51FF
JR Z,KEYLN1
[5217H]
If the Z FLAG (Zero) is set then we have a DOWN ARROW, so JUMP to 5217H.
5201
CP 09H
Compare the value held in Register A against 09H (ASCII: ). Results: If Register A equals RIGHT ARROW, the Z FLAG is set; otherwise the NZ FLAG is set.
5203
JR Z,KEYLN3
[521AH]
If the Z FLAG (Zero) is set then we have a RIGHT ARROW, so JUMP to 521AH.
5205
CP 5BH
Compare the value held in Register A against 5BH (ASCII: ). Results: If Register A equals UP ARROW, the Z FLAG is set; otherwise the NZ FLAG is set.
5207
JR Z,KEYLN1
[5217H]
If the Z FLAG (Zero) is set then we have a UP ARROW, so JUMP to 5217H.
5209
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE. Results:
• If Register A equals 20H, the Z FLAG is set.
• If A < 20H, the CARRY FLAG will be set.
• if A >= 20H, the NO CARRY FLAG will be set.
520B
JR C,KEYLN0
[51F2H]
If the C FLAG (Carry) is set, then we are below 20H meaning we have a control characters, so JUMP to 51F2H to ignore it.
520D
CALL DSP
[0033H]
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
5210
POP DE
Restore Register Pair DE from the top of the STACK.
5211
CP 2CH
Compare the value held in Register A against 2CH (ASCII: ,). Results:
• If Register A equals ,, then we have a breakpoint specifier and the Z FLAG is set.
• If A < 2CH, the CARRY FLAG will be set.
• if A >= 2CH, the NO CARRY FLAG will be set.
5213
RET Z
If the Z FLAG (Zero) is set then we have a breakpoint specifier so, RETurn to the caller with Z FLAG set.
5214
“KEYOUT”
CP 20H
Compare the value held in Register A against 20H (ASCII: SPACE). Results:
• If Register A equals 20H, the Z FLAG is set.
• If A < 20H, the CARRY FLAG will be set.
• if A >= 20H, the NO CARRY FLAG will be set.
5216
RET
RETurn to the caller with Z FLAG set only if a SPACE was present, otherwise NZ is set.

5217H – Continuation of the routine to get a character from the user, jumped if the key was a CARRIAGE RETURN, , , or .

5217
“KEYLN1”
POP DE
Restore Register Pair DE from the top of the STACK.
5218
SCF
We need to show that a control character was set (and we are at the end of our input), so we SET the CARRY FLAG.
5219
RET

521AH – Continuation of the routine to get a character from the user, jumped if the key was a .

521A
“KEYLN3”
LD A,20H
Let Register A = 20H (ASCII: SPACE).
521C
POP DE
Restore Register Pair DE from the top of the STACK.
521D
JR KEYOUT
[5214H]

521FH – Get hexadecimal input from the user and store it in Register Pair HL.

521F
CALL KEYLIN
[51F1H]
GOSUB to 51F1H to get character from the keyboard and process accordingly.
5222
RET Z
If the Z FLAG (Zero) is set then we had a CARRIAGE RETURN or an ARROW, RETurn to the caller.
5223
CP 08H
Compare the value held in Register A against 08H (ASCII: BACK ARROW). Results:
• If Register A equals BACK ARROW, the Z FLAG is set.
• If A < 08H, the CARRY FLAG will be set.
• if A >= 08H, the NO CARRY FLAG will be set.
5225
RET Z
If the Z FLAG (Zero) is set then we have a , so RETurn to the caller.
5226
LD HL,0000H
LET Register Pair HL = 0000H to prepare for some math.
5229
[523EH]
GOSUB to 523EH to get a hex digit’s value.
522C
JP C,START5
[4E51H]
If the C FLAG (Carry) is set then we got an unusable response from the user, so JUMP to 4E51H to re-enter the DEBUG COMMAND LOOP.

The next instructions are the magic instructions to convert HEX to ASCII – First move the old value left 4 bits, and then add in the second digit.

522F
5230
5231
5232
LET HL = HL + 16
5233
OR L
OR Register L against Register A. The results are stored in Register A.
5234
LD L,A
LET Register L = Register A.
5235
CALL KEYLIN
[51F1H]
GOSUB to 51F1H to get character from the keyboard and process accordingly.
5238
[5229H]
523A
RRA
Rotate Register A rotated right one bit position, with Bit 0 going to the CARRY FLAG and the previous contents of the CARRY FLAG going to bit 7.
523B
Add 129 to to the rotated Register A.
523D
RET

523EH – SUBroutine called from the prior routine to get a hex digit’s value.

523E
SUB 30H
SUBtract the value 30H from Register A. If Register A is 29H or less, then the CARRY FLAG will be set as follows
Character in A
-30H
RESULT
One Below “0”
2FH
A=FFH + CARRY
“0”
30H
A=00H + NO CARRY
“9”
39H
A=09H + NO CARRY
“A”
41H
A=11H + NO CARRY
“F”
46H
A=16H + NO CARRY
One Higher than “F”
47H
A=17H + NO CARRY
5240
RET C
If the C FLAG (Carry) is set, then Register A is lower than 0, which is not a valid hex number, so RETurn to the caller.
5241
ADD the value 0E9H to Register A (Results held in Register A). This tests to see if the original number was any higher than 46H (ASCII: F) as follows
Character in A
A
A+0E9H
One Below “0”
N/A
N/A – We jumped away
“0”
A=00H
A=E9H + NO CARRY
“9”
A=09H
A=F2H + NO CARRY
“A”
A=11H
A=FAH + NO CARRY
“F”
A=16H
A=FFH + NO CARRY
One Higher than “F”
A=17H
A = 100H + CARRY
5243
RET C
If the C FLAG (Carry) is set then Register A is higher than F, which is not a valid hex number, so RETurn to the caller.
5244
ADD the value 06H to Register A (Results held in Register A).
Character in A
A
A+06H
One Below “0”
N/A
N/A – We jumped away
“0”
A=E9H
A=EFH + NO CARRY
“9”
A=F2H
A=F8H + NO CARRY
“A”
A=FAH
A=100H + CARRY
“F”
A=FFH
A=105H + CARRY
One Higher than “F”
N/A
N/A – We jumped away
5246
[524BH]
If the C FLAG (Carry) is set, then we have AF, so JUMP to 524BH.
5248
ADD the value 07H to Register A (Results held in Register A).
Character in A
A
A+07H
One Below “0”
N/A
N/A – We jumped away
“0”
A=EFH
A=F6H + NO CARRY
“9”
A=F8H
A=FFH + NO CARRY
“A”
A=FAH
N/A – We jumped away
“F”
A=FFH
N/A – We jumped away
One Higher than “F”
N/A
N/A – We jumped away
524A
RET C
If the C FLAG (Carry) is set then our number is too low, so RETurn to the caller.
524B
ADD the value 0AH to Register A (Results held in Register A).
Character in A
A
A+0AH
One Below “0”
N/A
N/A – We jumped away
“0”
A=F6H
A=100H or 00H
“9”
A=FFH
A=109H or 09H
“A”
A=100H
A=10AH or 0AH
“F”
A=105H
A=10FH or 0FH
One Higher than “F”
N/A
N/A – We jumped away
524D
OR A
Set FLAGS based on the contents of Register A.
524E
RET

524FH – SUBroutine to Display Bytes Held in (HL) In Hexadecimal.

524F<
“OUTLOC”
LD A,(HL)
Fetch the value stored at memory location (i.e., the byte to display in hex) pointed to by Register Pair HL and put it into Register A.
5250
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next byte.
5251
JR OUTBYT
[5258H]
JUMP to 5258H to convert the byte held in Register A to ASCII and display.

5253H – SUBROUTINE inside the DISPLAY DEBUG ROUTINE to display the address pointed to by Register Pair HL in hexadecimal.

5253
“OUTWRD”
LD A,H
LET Register A = Register H (i.e., the MSB of a 2 byte address held in the memory location pointed to by Register Pair HL).
5254
CALL OUTBYT
[5258H]
GOSUB to 5258H to convert the byte held in Register A to ASCII and display.
5257
LD A,L
LET Register A = Register L (i.e., the LSB of a 2 byte address held in the memory location pointed to by Register Pair HL).

This is the commonly jumped to OUTBYT, which converts Register A to ASCII and displays it.

5258
“OUTBYT”
PUSH AF
Save Register AF (i.e., the byte to be displayed) to the top of the STACK.
5259
525A
525B
525C
RRA
RRA
RRA
RRA
Rotate Register A Right 4 times so that the highest 4 bytes are now the lowest 4 bytes
525D
CALL HEX1
[5261]
GOSUB to 5261H to convert the lowest 4 bits in Register A into ASCII and display.
5260
POP AF
Restore Register Pair AF (i.e., the byte to be displayed) from the top of the STACK.
5261
“HEX1”
AND 0FH
MASK the value of Register A against 0FH (0000 1111). This has the effect of turning off bits 7, 6, 5, 4, leaving only bits 3, 2, 1, 0 active, since are dealing in lower-4-bit patterns here.

What is next is a clever way to manipulate a 4 bit byte into ASCII. Point to remember is that 0-F are contained in 4 bits, so that’s the range.

5263
ADD the value 90H to Register A (Results held in Register A), so that 00H-00FH are now 1001 + nnnn (what they were).
5265
DAA
Adjust Register A for BCD addition and subtraction operations. DAA is way too complicated to go into here, but if the low 4 bits are greater than 9, the H FLAG is set and 06H is addded to Register A and if the high 4 bits are greater than 9, the C FLAG is set and 60H is added to Register A.
5266
Add 40H and the carry to register A.
5268
DAA
Adjust Register A for BCD addition and subtraction operations. Once this has run, Register A will contain 30H-39H for 0-9, and 41H-46H for A-F.
Original
Nybble
40H +
Nybble
+06H if > 09
00
0011 0000
30H
01
0011 0001
31H
02
0011 0010
32H
03
0011 0011
33H
04
0011 0100
34H
05
0011 0101
35H
06
0011 0110
36H
07
0011 0111
37H
08
0011 1000
38H
09
0011 1001
39H
0A
0100 0001
41H
0B
0100 0010
42H
0C
0100 0011
43H
0D
0100 0100
44H
0E
0100 0101
45H
0F
0100 0110
46H
5269
“VIDEO”
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.

526CH – SUBROUTINE to display a byte held in Register A as a two-byte ascii value followed by a space.

526C
“OUTBSP”
CALL OUTBYT
[5258H]
GOSUB to 5258H to convert the byte held in Register A to ASCII and display.
526F
“OUTSPC”
LD A,20H
LET Register A = 20H (ASCII: SPACE.
5271
JR VIDEO
[5269H]
JUMP to 5269H to display the character held in Register A (i.e., a SPACE).

5273H – Display a CARRIAGE RETURN and continue at 5269H.

5273
“OUTCR”
LD A,0DH
LET Register A = 0DH (ASCII: CARRIAGE RETURN.
5275
JR VIDEO
[5269H]
JUMP to 5269H to display the character held in Register A (i.e., a CARRIAGE RETURN).

5277H – Clear to the End of Screen via a ROM CALL and RETURN

5277
“OUTCLR”
LD A,1FH
LET Register A = 1FH (ASCII: CLEAR TO END OF SCREEN.
5279
NOTE: 0033H is the character print routine, to put the character held in Register A (i.e., the ASCII code for CLEAR TO END OF SCREEN) at the current cursor position.

527CH – Display the 3 characters pointed to by (HL), (HL+1), and (HL+2), and then RETurn

527C
“OUT3”
CALL DSPR
[5282H]
GOSUB to 5282H to put the character pointed to by Register Pair HL into Register A, Bump HL to point to the next character, displays the character on screen, and RETurns.
527F
CALL DSPR
[5282H]
GOSUB to 5282H to put the character pointed to by Register Pair HL into Register A, Bump HL to point to the next character, displays the character on screen, and RETurns.
5282
“DSPR”
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
5283
INC HL
Bump the value stored in Register Pair HL by 1.
5284
JR VIDEO
[5269H]
JUMP to 5269H which JUMPs to 0033H in the ROM to display the character held in Register A on the screen and RETurn.

5286H – “Q” Option – Quit the Utility.

5286
“QUIT”
XOR A
Set Register A to ZERO and clear all Flags.
5287
LD (CSIDE),A
[4463H]
Store the value held in Register A into the memory location 4463H.
NOTE: 4463H is the storage location for the old system disk side number.
528A

528DH – Validate a Decimal Digit and Convert to Binary

528D
“CHKNUM”
SUB 30H
SUBtract the value 30H from Register A, thus converting an ASCII number to Binary.
528F
RET C
If the C FLAG (Carry) is set then the value was lower than a “0”, which is not permitted, so RETurn to the caller.
5290
CP 0AH
Compare the value held in Register A against 0AH (Decimal: 10). Results:
• If Register A equals 0AH, the Z FLAG is set.
• If A < 0AH, the CARRY FLAG will be set.
• if A >= 0AH, the NO CARRY FLAG will be set.
5292
CCF
Invert the state of the CARRY FLAG so that GREATER than 10 has CARRY FLAG set, to indicate an error.
5293
RET

5294H – Validate a Hexidecimal digit and Convert to Binary

5294
“GETHEX”
5295
PUSH HL
POP IX
Let IX = HL (i.e., the hexidecimal data).
5297
LD HL,0000H
LET Register Pair HL = 0000H to prepare for some math.
529A
“GETHE1”
LD A,(IX+00H)
Fetch the value stored at the memory location pointed to by IX+00H (i.e., the first character to be checked) and put it into Register A.
529D
INC IX
Bump the value stored in Register Pair IX by 1 to point to the next character to be checked.
529F
SUB 30H
SUBtract the value 30H from Register A, thus converting an ASCII number to Binary.
52A1
JR C,GETHE3
[52B7H]
If the C FLAG (Carry) is set then the value was lower than a “0”, which is not permitted, so JUMP to 52B7H to put the LSB into Register A and return (with the CARRY FLAG set).
52A3
CP 0AH
Compare the value held in Register A against 0AH (ASCII: A). Results:
• If Register A equals A, the Z FLAG is set.
• If A < A, the CARRY FLAG will be set.
• if A >= A, the NO CARRY FLAG will be set.
52A5
JR C,GETHE2
[52A9H]
If the C FLAG (Carry) is set then A < A, so we have bad value, so JUMP to 52A9H.
52A7
SUB 07H
SUBtract the value 07H from Register A to adjust the value.
52A9
“GETHE2”
CP 10H
Compare the value held in Register A against 10H (which would be a value which is too large to be good). Results:
• If Register A equals 10H, the Z FLAG is set.
• If A < 10H, the CARRY FLAG will be set.
• if A >= 10H, the NO CARRY FLAG will be set.
52AB
JR NC,GETHE3
[52B7H]
If the NC FLAG (No Carry) is set then the value is too large, so JUMP to 52B7H.
52AE
52AF
52B0
LET HL = HL + 16, shifting the nybble
52B1
LD E,A
LET Register E = Register A (i.e., the value of the digit).
52B2
LD D,00H
LET Register D = 00H so that Register Pair DE holds the value of the digit.
52B4
ADD the value held in Register Pair DE to Register Pair HL. The results are held in Register Pair HL.
52B5
JR GETHE1
[529AH]
LOOP to 529AH for the next hex value.

52B7H – Jump point from the prior routine if the value received is less than 0.

52B7
“GETHE3”
LD A,L
LET Register A = Register L (i.e., the LSB).
52B8
RET

52B9H – DEBUG routine entry from DOS Loader

52B9
“ENTRY”
POP AF
Restore Register Pair AF from the top of the STACK.
52BA
JP START
[4E00H]

52BDH – Disk File Display/Modify Routine

52BD
“TRA”
LD A,0B0H
LET Register A = 0B0H (ASCII: Block Cursor).
52BF
LD (4023H),A
Store the value held in Register A into the memory location 4023H.
NOTE: 4023H is the storage location for the CURSOR CHARACTER.
52C2
LD HL,TITLE
[5526H]
LET Register Pair HL = 5526H, to point to the message storage area for 1CH + 1FH + “Debug Disk Utility Ver 1.3” + 0DH + 0AH.
52C5
CALL PRINT
[021BH]
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H or 0AH is found.
52C8
LD HL,BPROMT
[5543H]
LET Register Pair HL = 5543H, to point to the message storage area for 0AH + “Filespec: “ + 03H
52CB
CALL PRINT
[021BH]
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H or 0AH is found.
52CE
LD B,1FH
LET Register B = 1FH (Decimal: 31), so as to prepare to read up to 31 characters from the keyboard (as a filespec).
52D0
LD HL,BDCB
[5555H]
LET Register Pair HL = 5555H to point to a memory buffer for the input.
52D3
CALL KEYN
[0040H]
GOSUB to 0040H in the ROM to read a full line from the KEYBOARD until ENTER or BREAK. If a BREAK is hit, the CARRY FLAG is set.
52D6
JR C,QUIT
[5286H]
If the C FLAG (Carry) is set, then the BREAK was just so JUMP to 5286H.
52D8
LD HL,BUFF1
[4300H]
LET Register Pair HL = 4300H, which is DOS Buffer 1.
52DB
LD DE,BDCB
[5555H]
LET Register Pair DE = 5555H, which is the Buffer holding the filename just entered.
52DE
LD B,00H
LET Register B = 00H (0000 0000).
52E0
CALL OPEN
[4424H]
GOSUB to 4424H from OVERLAY 00 (which opens a disk file for use) by setting an OVERLAY CALL of 92H (Routine 1 of Overlay 2) and then calling RST 28H.
52E3
JP NZ,BERR
[5405H]
If the NZ FLAG (Not Zero) is set, then that CALL returned an error, so JUMP to 5405H to handle the diskette-related error.

If we have an open file, we now need to adjust the DCB for the file.

52E6
LD IX,BDCB
[5555H]
LET Register Pair IX = 5555H to point to a memory buffer for the filename we just got from the user.
52EA
RES 7,(IX+01H)
RESet (i.e., set as 0) BIT 7 of Register (IX+01H) to set the DCB for “SECTOR I/O”.
52EE
LD (IX+09H),00H
Store a 00H in IX+09H (i.e., the LRL of the DCB) to signify a 256 byte file.
52F2
LD A,(IX+08H)
Fetch the value stored at the memory location pointed to by IX+08H (i.e., the position in the DCB for the EOF byte) and put it into Register A.
52F5
LD (IX+08H),00H
Store the value held in Register 00H into the memory location IX+08H to zero out the file.
52F9
OR A
Set FLAGS based on the contents of Register A to see if it actually was zero (i.e., an even boundary).
52FA
[5303H]
If the Z FLAG (Zero) is set then we can skip ahead and we JUMP to 5303H.
52FC
LD HL,(ERN)
[5561H]
Fetch the value stored at memory location 5561H (i.e., the EOF Sector or Last Page of Memory) and put it into Register HL.
52FF
INC HL
Bump the value stored in Register Pair HL (i.e., the EOF Sector) by 1.
5300
LD (ERN),HL
[5561H]
Store the value held in Register HL (i.e., the EOF Sector) into the memory location 5561H.
5303
LD DE,BDCB
[5555H]
LET Register Pair DE = 5555H to point to a memory buffer for the filename we just got from the user.
5306
LD HL,BUFF1
[4300H]
LET Register Pair HL = 4300H, which is DOS Buffer 1.
5309
GOSUB to 4448H which is the POSEOF Vector stored in Overlay 0. This will position to the last record.
530C
GOSUB to 4436H which is the READ Vector stored in Overlay 0. This will read that last record.
530F
GOSUB to 443FH which is the REWIND Vector stored in Overlay 0. This will rewind the file.
5312
LD A,23H
LET Register A = 23H to an OPCODE MASK so as to adjust the record number.
5314
LD (CHGBMP),A
[5366H]
Store the value held in Register A (i.e., a INC HL OPCODE) into the memory location 5366H, which is currently a NOP.

The next few instructions clear Buffer # 1

5317
LD HL,BUFF1
[4300H]
LET Register Pair HL = 4300H, which is DOS Buffer 1.
531A
LD DE,BUFF+1
LET Register Pair DE = 4301H, which is DOS Buffer 1 + 1.
531D
LD BC,00FFH
LET Register Pair BC = 00FFH (Decimal: 256) to clear 256 bytes.
5320
LD (HL),00H
Get the ball rolling by putting a 00H into the memory location pointed to by Register Pair HL.
5322
LDIR
Cascade that 00H all the way down via a LDIR, which transfers a byte of data from the memory location pointed to by HL to the memory location pointed to by DE. Then HL and DE are incremented and BC is decremented. If BC is not zero, this operation is repeated. Interrupts can trigger while this instruction is processing.
5324
LD DE,BDCB
[5555H]
LET Register Pair DE = 5555H, to point to the specified file.
5327
GOSUB to 4436H which is the READ Vector stored in Overlay 0. This will read the first sector of the specified file.
532A
JP NZ,BERR
[5405H]
If the NZ FLAG (Not Zero) is set then that CALL resulted in an ERROR, so JUMP to JUMP to 5405H to handle the diskette-related error.
532D
GOSUB to 4445H which is the BACKSPACE VECTOR (i.e., Back Up To the Previous Record in a File) in Overlay 1.
5330
“CONT0”
XOR A
Set Register A to ZERO and clear all Flags.
5331
LD (MOVFLG),A
[5553H]
Store the value held in Register A into the memory location 5553H to indicate that we are reading data from diskette.
5334
LD (MODDSK),A
[545FH]
Store the value held in Register A into the memory location 545FH to clear the modify mode. 545FH is in the middle of a LD A,(nn)” OPCODE, with FF=Memory and anything else =Disk
5337
CALL CONT2
[533CH]
GOSUB to 533CH to display the page for modification.
533A
JR SCAN
[53AEH]

533CH – Display the Page for Modification

533C
“CONT2”
LD A,0B0H
LET Register A = 0B0H (ASCII: BLOCK cursor).
533E
LD (CURSCR),A
[4023H]
Store the value held in Register A into the memory location 4023H.
NOTE: 4023H is the storage location for the CURSOR CHARACTER.
5341
LD A,0FH
LET Register A = 0FH to indicate CURSOR ON.
5343
CALL DSP
[0033H]
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
5346
LD A,(MODDSK)
[545FH]
Fetch the value stored at memory location 545FH to see if we are dumping a memory file or a disk file, and put it into Register A. 545FH is in the middle of a LD A,(nn)” OPCODE, with FF=Memory and anything else =Disk
5349
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
534A
JR Z,GETBUF
[5351H]
If the Z FLAG (Zero) is set, then we are working on a DISK file, so JUMP to 5351H.
534C
LD HL,(MEM+3)
[4103H]
If we are here, then we are dealing with MEMORY, so fetch the value stored at memory location 4103H (i.e., the old dump address) and put it into Register HL.
534F
JR CNT00
[5354H]

5351H – Display Data

5351
“GETBUF”
LD HL,BUFF1
[4300H]
LET Register Pair HL = 4300H, which is DOS Buffer 1.
5354
“CONT00”
LD DE,3C00H
LET Register Pair DE = 3C00H, which is the top of the screen.
5357
“LOP1”
LD B,08H
LET Register B = 08H to signify 16 bytes to display.
5359
PUSH HL
Save Register HL (i.e., the data address) to the top of the STACK.
535A
LD A,(DRV)
[555BH]
Fetch the value stored at memory location 555BH (i.e., the disk drive number) and put it into Register A.
535D
ADD the value 30H to Register A (Results held in Register A) to turn the hex drive number into its ASCII equivalent.
535F
CALL DISP
[5402H]
GOSUB to 5402H to display a character.
5362
PUSH HL
Save Register HL (i.e., the data address) to the top of the STACK.
5363
LD HL,(NRN)
[555FH]
Fetch the value stored at memory location 555FH (i..e, the sector number) and put it into Register HL.
5366
NOP
No Operation (Do Nothing) -or- INC HL, depending on what OPCODE was put into this address.
5367
LD A,H
LET Register A = Register H (i.e., the MSB of HL).
5368
ADD the value 30H to Register A (Results held in Register A) to turn the hex drive number into its ASCII equivalent.
536A
CALL DISP
[5402H]
GOSUB to 5402H to display a character.
536D
LD A,L
LET Register A = Register L (i.e., the LSB of HL).
536E
CALL HEX
[53EDH]
GOSUB to 53EDH to display the low byte in ASCII (2 characters).
5371
POP HL
Restore Register Pair HL (i.e., the buffer pointer) from the top of the STACK.
5372
LD A,L
LET Register A = Register L (i.e., the line start address).
5373
CALL HEX
[53EDH]
GOSUB to 53EDH to display the low byte in ASCII (2 characters).
5376
LD A,3AH
LET Register A = 3AH (ASCII: :).
5378
CALL DISP
[5402H]
GOSUB to 5402H to display a character.
537B
“LOOP2”
LD A,20H
LET Register A = 20H (ASCII: SPACE).
537D
CALL DISP
[5402H]
GOSUB to 5402H to display a character.
5380
CALL CHECK
[5423H]
GOSUB to 5423H to see if we are at the cursor position.
5383
JR C,LOP3
[5389H]
If the C FLAG (Carry) is set then we are at the proper cursor position, so JUMP to 5389H.
5385
“LOP2”
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
5386
CALL HEX
[53EDH]
GOSUB to 53EDH to display the low byte in ASCII (2 characters).
5389
“LOP3”
INC L
Bump the value stored in Register L by 1.
538A
CALL CHECK
[5423H]
GOSUB to 5423H to see if we are at the cursor position.
538D
JR C,LOP4
[5393H]
538F
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
5390
CALL HEX
[53EDH]
GOSUB to 53EDH to display the low byte in ASCII (2 characters).
5393
“LOP4”
INC L
Bump the value stored in Register L by 1.
5394
DJNZ LOOP2
[537BH]
LOOP back to 537BH until Register B is ZERO.
5396
LD A,20H
LET Register A = 20H (ASCII: SPACE).
5398
CALL DISP
[5402H]
GOSUB to 5402H to display a character.
539B
POP HL
Restore Register Pair HL (i.e., the data address) from the top of the STACK.
539C
LD B,10H
LET Register B = 10H (Decimal: 16) to prepare for a loop of 16.
539E
“LOOP3”
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL (i.e., the data to display) and put it into Register A.
539F
CP 20H
Compare the value held in Register A against 20H to see if we have a control character. Results:
• If Register A equals 20H, the Z FLAG is set.
• If A < 20H, the CARRY FLAG will be set.
• if A >= 20H, the NO CARRY FLAG will be set.
53A1
JR NC,CONT4
[53A5H]
If the NC FLAG (No Carry) is set, then we have a control characters, so JUMP to 53A5H.
53A3
LD A,2EH
LET Register A = 2EH (ASCII: :).
53A5
CALL DISP
[5402H]
GOSUB to 5402H to display a character.
53A8
INC L
Bump the value stored in Register L by 1 to point to the next byte to display.
53A9
RET Z
If the Z FLAG (Zero) is set then we are at the end of the page, so RETurn to the caller.
53AA
DJNZ LOOP3
[539EH]
LOOP back to 539EH until Register B is ZERO.
53AC
JR LOP1
[5357H]

53AEH – Scan the Keyboard for Display Mode Commands

53AE
“SCAN”
DI
Disable Interrupts.
53AF
CALL KEY
[0049H]
GOSUB to 0049H to wait for a key to be pressed.
53B2
CP 01H
Compare the value held in Register A against 01H (i.e., BREAK). Results: If Register A equals BREAK, the Z FLAG is set; otherwise the NZ FLAG is set.
53B4
JP Z,TRA
[52BDH]
If the Z FLAG (Zero) is set then the BREAK was set, so JUMP to 52BDH to restart the routine.
53B7
CP 3BH
Compare the value held in Register A against 3BH (i.e., ;). Results: If Register A equals ;, the Z FLAG is set; otherwise the NZ FLAG is set.
53B9
JR Z,UP
[53CEH]
If the Z FLAG (Zero) is set then we got a ;, so JUMP to 53CEH to go to the next page.
53BB
CP 2BH
Compare the value held in Register A against 2BH (i.e., +). Results: If Register A equals +, the Z FLAG is set; otherwise the NZ FLAG is set.
53BD
JR Z,UP
[53CEH]
If the Z FLAG (Zero) is set then we got a +, so JUMP to 53CEH to go to the next page.
53BF
CP 2DH
Compare the value held in Register A against 2DH (i.e., -). Results: If Register A equals -, the Z FLAG is set; otherwise the NZ FLAG is set.
53C1
JR Z,DN
[53E2H]
If the Z FLAG (Zero) is set then we got a -, so JUMP to 53E2H to go to the previous page.
53C3
CP 3DH
Compare the value held in Register A against 3DH (i.e., =). Results: If Register A equals =, the Z FLAG is set; otherwise the NZ FLAG is set.
53C5
JR Z,DN
[53E2H]
If the Z FLAG (Zero) is set then we got a =, so JUMP to 53E2H to go to the previous page.
53C7
CP 4DH
Compare the value held in Register A against 4DH (i.e., M). Results: If Register A equals M, the Z FLAG is set; otherwise the NZ FLAG is set.
53C9
JP Z,MOVE
[5445H]
If the Z FLAG (Zero) is set then we got a M, so JUMP to 5445H to go to modify mode.
53CC
JR SCAN
[53AEH]

53CEH – Advance to the Next Page of the Display

53CE
“UP”
LD BC,(NRN)
[555FH]
Fetch the value stored at memory location 555FH (i.e., the page or sector number) and put it into Register BC.
53D2
INC BC
Bump the value stored in Register Pair BC by 1 to point to the next page or sector.
53D3
LD HL,(ERN)
[5561H]
Fetch the value stored at memory location 5561H (i.e., the EOF Sector or Last Page of Memory) and put it into Register HL.
53D6
XOR A
Set Register A to ZERO and clear all Flags.
53D7
SBC HL,BC
Subtracts the value stored in Register Pair BC and the carry flag from the value stored in Register Pair HL.
53D9
JR Z,SCAN
[53AEH]
If the Z FLAG (Zero) is set then we need to try again, so JUMP to the command loop for DISPLAY MODE commands at 53AEH.
53DB
“POS”
LD (NRN),BC
[555FH]
Store the value held in Register BC (i.e., the page or sector number) into the memory location 555FH (i.e., the storage for the sector number).
53DF
[5317H]

53E2H – Back up to the Previous Page of the Display

53E2
“DN”
LD BC,(NRN)
[555FH]
Fetch the value stored at memory location 555FH (i.e., the page or sector number) and put it into Register BC.
53E6
53E7
LD A,B
OR C
Since the Z-80 cannot test Register Pair BC against zero, the common trick is to set Register A to one, and Or the other. Only if every single bit was off in both will the Z FLAG be set.
53E8
JR Z,SCAN
[53AEH]
If the Z FLAG (Zero) is set then we need to try again, so JUMP to the command loop for DISPLAY MODE commands at 53AEH.
53EA
DEC BC
DECrement the value stored in Register Pair BC by 1 so as to move to the previous page or sector number.
53EB
JR POS
[53DBH]
JUMP to 53DBH to save the new page or sector number and continue.

53EDH – Display a Byte in Two Digit Hexadecimal

53ED
“HEX”
LD C,A
LET Register C (i.e., the LSB) = Register A.
53EE
53F0
53F2
53F4
SRL A
SRL A
SRL A
SRL A
Put the high nybble into the low nybble
53F6
CALL TEST
[53FAH]
GOSUB to 53FAH to convert the byte to ASCII and display it.
53F9
LD A,C
LET Register A = Register C (i.e., the original, unmodified LSB).
53FA
“TEST”
AND 0FH
MASK the value of Register A against 0FH (0000 1111). This has the effect of turning off bits 7, 6, 5, 4, leaving only bits 3, 2, 1, 0 active, thus isolating the low nybble.

What is next is a clever way to manipulate a 4 bit byte into ASCII. Point to remember is that 0-F are contained in 4 bits, so that’s the range.

53FC
ADD the value 90H to Register A (Results held in Register A), so that 00H-00FH are now 1001 + nnnn (what they were).
53FE
DAA
Adjust Register A for BCD addition and subtraction operations. DAA is way too complicated to go into here, but if the low 4 bits are greater than 9, the H FLAG is set and 06H is addded to Register A and if the high 4 bits are greater than 9, the C FLAG is set and 60H is added to Register A.
53FF
Add 40H and the carry to register A.
5401
DAA
Adjust Register A for BCD addition and subtraction operations. Once this has run, Register A will contain 30H-39H for 0-9, and 41H-46H for A-F.
5402
“DISP”
LD (DE),A
Store the value held in Register A (i.e., the BCD result) into the memory location pointed to by Register Pair DE.
5403
INC DE
Bump the value stored in Register Pair DE by 1 to point to the next byte.
5404
RET

5405H – This routine is JUMPed to if a CALL to open a disk file returned an error.

5405
“BERR”
LD B,A
LET Register B = Register A (i.e., the error code returned).
5406
AND 0FEH
MASK the value of Register A against 0FEH (1111 1110). This has the effect of turning off bit 0.
5408
CP 1CH
Compare the value held in Register A against 1CH (i.e., an END OF FILE error). Results: If Register A equals 1CH, the Z FLAG is set; otherwise the NZ FLAG is set.
540A
JR NZ,BERR1
[5415H]
If the NZ FLAG (Not Zero) is set, then we do not have an END OF FILE error, so JUMP to 5415H to deal with other errors.
540C
LD HL,(ERN)
[5561H]
Fetch the value stored at memory location 5561H (i.e., the EOF Sector or Last Page of Memory) and put it into Register HL.
540F
LD (NRN),HL
[555FH]
Store the value held in Register HL into the memory location 555FH (i.e., the storage for the sector number).
5412
JP CONT0
[5330H]

5415H – This routine is JUMPed to if a CALL to open a disk file returned an error that was not EOF Error

5415
“BERR1”
LD A,B
LET Register A = Register B (i.e., the error code returned).
5416
PUSH AF
Save Register AF (i.e., the error code returned) to the top of the STACK.
5417
GOSUB to 01C9H in the ROM to clear the screen.
541A
POP AF
Restore Register Pair AF (i.e., the error code returned) from the top of the STACK.
541B
OR 0C0H
OR Register A against 0C0H, so as to enable the LONG ERROR MESSAGE bits.
541D
GOSUB to 4409H in Overlay 1 to Display the Error Message.
5420
JP CONT1
[52C8H]
JUMP to 52C8H to get a new filespec from the user and continue.

5423H – Subroutine to check to see if we are at the cursor position

5423
“CHECK”
LD A,(MOVFLG)
[5553H]
Fetch the value stored at memory location 5553H (i.e., the memory locaiton signifying if the cursor is active) and put it into Register A.
5426
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
5427
RET Z
If the Z FLAG (Zero) is set, then the cursor is NOT active, so RETurn to the caller.
5428
PUSH DE
Save Register DE to the top of the STACK.
5429
PUSH HL
Save Register HL to the top of the STACK.
542A
LD DE,(WHERE)
[554FH]
Fetch the value stored at memory location 554FH (i.e., the location where we store the cursor location) and put it into Register DE.
542E
OR A
Set FLAGS based on the contents of Register A.
542F
SBC HL,DE
Subtracts the value stored in Register Pair DE and the carry flag from the value stored in Register Pair HL to see if we are at the cursor location.
5431
POP HL
Restore Register Pair HL from the top of the STACK.
5432
POP DE
Restore Register Pair DE from the top of the STACK.
5433
JR Z,CHECK1
[5437H]
If the Z FLAG (Zero) is set then we are actually where we want to be, so JUMP to 5437H.
5435
OR A
Set FLAGS based on the contents of Register A.
5436
RET

5437H – Continuation of the above routine if the cursor is properly positioned

5437
“CHECK1”
LD (CURSA),DE
[5551H]
Store the value held in Register DE into the memory location 5551H (i.e., the cursor position).
543B
LD A,8FH
LET Register A = 8FH (ASCII: Display Cursor).
543D
CALL DISP
[5402H]
GOSUB to 5402H to display a character.
5440
CALL DISP
[5402H]
GOSUB to 5402H to display a character.
5443
SCF
Set the CARRY FLAG
5444
RET

5445H – Enter Modify Mode

5445
“MOVE”
LD HL,BUFF1
[4300H]
LET Register Pair HL = 4300H, which is DOS Buffer 1.
5448
LD (WHERE),HL
[554FH]
LD (554FH),HL]
Store the value held in Register HL (i.e., DOS Buffer 1) into the memory location 554FH.
544B
LD A,H
LET Register A = Register H (i.e., 43H).
544C
LD (MOVFLG),A
[5553H]
Store the value held in Register A into the memory location 5553H to signify that the cursor is active.

544FH – Display Data for the MODIFY COMMAND

544F
“BACK”
LD HL,(WHERE)
[554FH]
Fetch the value stored at memory location 554FH (i.e., the applicable data) and put it into Register HL.
5452
PUSH HL
Save Register HL (i.e, the address) to the top of the STACK.
5453
CALL CONT2
[533CH]
GOSUB to 533CH to display a page of data.
5456
POP HL
Restore Register Pair HL (i.e, the address) from the top of the STACK.

5457H – Command Loop for the MODIFY COMMAND

5457
“BACK1”
CALL GETKEY
[54FEH]
GOSUB to 54FEH to get the command.
545A
CP 0DH
Compare the value held in Register A against 0DH (ASCII: ENTER). Results: If Register A equals ENTER, the Z FLAG is set; otherwise the NZ FLAG is set.
545C
JR NZ,BACK2
[5467H]
If the NZ FLAG (Not Zero) is set, then we did not get an ENTER, so JUMP to 5467H.
545E
LD A,nn
LET Register A = (545FH). Note: This is set to FF for Memory I/O and and anything else for Disk I/O by a number of places in this routine.
5460
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
5461
JP Z,BWRITE
[550FH]
If the Z FLAG (Zero) is set, the we are doing DISK I/O, so JUMP to 550FH.
5464
JP START5
[4E51H]

5467H – Continuation of the Command Loop for the MODIFY COMMAND (to handle a BREAK key)

5467
“BACK2”
CP 01H
Compare the value held in Register A against 01H so as to test for a BREAK. Results: If Register A equals 01H, the Z FLAG is set; otherwise the NZ FLAG is set.
5469
JR NZ,BACK3
[5475H]
If the NZ FLAG (Not Zero) is set, then we did NOT get a BREAK, so JUMP to 5475H.
546B
LD A,(MODDSK)
[545FH]
Fetch the value stored at memory location 545FH and put it into Register A so as to test if the data was from disk or RAM. 545FH is in the middle of a LD A,(nn)” OPCODE, with FF=Memory and anything else =Disk
546E
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
546F
JP Z,CONT0
[5330H]
If the Z FLAG (Zero) is set, then we were doing DISK I/O, so JUMP to 5330H to get a new file.
5472
JP START5
[4E51H]

5475H – Continuation of the Command Loop for the MODIFY COMMAND

5475
“BACK3”
CP 0AH
Compare the value held in Register A against 0AH (ASCII: LINE FEED). Results: If Register A equals 0AH, the Z FLAG is set; otherwise the NZ FLAG is set.
5477
JR Z,UP1
[54ACH]
If the Z FLAG (Zero) is set, then we got a LINE FEED, so JUMP to 54ACH.
5479
CP 5BH
Compare the value held in Register A against 5BH (ASCII: UP ARROW). Results: If Register A equals 5BH, the Z FLAG is set; otherwise the NZ FLAG is set.
547B
JR Z,DWN1
[54A3H]
If the Z FLAG (Zero) is set then we got a UP ARROW so JUMP to 54A3H to move up.
547D
CP 09H
Compare the value held in Register A against 09H (ASCII: RIGHT ARROW). Results: If Register A equals 09H, the Z FLAG is set; otherwise the NZ FLAG is set.
547F
JR Z,RIGHT
[549DH]
If the Z FLAG (Zero) is set then we got a RIGHT ARROW, so JUMP to 549DH to move right.
5481
CP 08H
Compare the value held in Register A against 08H (ASCII: BACKSPACE). Results: If Register A equals 08H, the Z FLAG is set; otherwise the NZ FLAG is set.
5483
JR Z,LEFT
[5497H]
If the Z FLAG (Zero) is set then we got a BACKSPACE so JUMP to 5497H to move left.
5485
CP 30H
Compare the value held in Register A against 30H (ASCII: 0). Results:
• If Register A equals 30H, the Z FLAG is set.
• If A < 30H, the CARRY FLAG will be set.
• if A >= 30H, the NO CARRY FLAG will be set.
5487
JR C,BACK1
[5457H]
If the C FLAG (Carry) is set then A < 0, which would be invalid, so LOOP BACK to to the top of the command loop for the Modify Command at 5457H.
5489
CP 3AH
Compare the value held in Register A against 3AH (ASCII: 1 more than 9). Results:
• If Register A equals 1 more than 9, the Z FLAG is set.
• If A < 1 more than 9, the CARRY FLAG will be set.
• if A >= 1 more than 9, the NO CARRY FLAG will be set.
548B
JR C,DIGIT
[54B8H]
If A < 1 more than 9 the C FLAG (Carry) will be is set, so JUMP to 54B8H.
548D
CP 41H
Compare the value held in Register A against 41H (ASCII: A). Results:
• If Register A equals A, the Z FLAG is set.
• If A < A, the CARRY FLAG will be set.
• if A >= A, the NO CARRY FLAG will be set.
548F
JR C,BACK1
[5457H]
If A < A, then the the C FLAG (Carry) will be set, so LOOP BACK to to the top of the command loop for the Modify Command at 5457H.
5491
CP 47H
Compare the value held in Register A against 47H (ASCII: 1 more than F). Results:
• If Register A equals 1 more than F, the Z FLAG is set.
• If A < 1 more than F, the CARRY FLAG will be set.
• if A >= 1 more than F, the NO CARRY FLAG will be set.
5493
JR C,DIGIT
[54B8H]
If A < 1 more than F then the C FLAG (Carry) will be set, so JUMP to 54B8H.
5495
JR BACK1
[5457H]
LOOP BACK to to the top of the command loop for the Modify Command at 5457H.

5497H – Continuation of the Command Loop for the MODIFY COMMAND – Process a BACKSPACE

5497
“LEFT”
LD HL,(WHERE)
[554FH]
Fetch the value stored at memory location 554FH (i.e., the CURSOR POSITION) and put it into Register HL.
549A
DEC L
DECrement the value stored in Register L (i.e., the CURSOR POSITION) by 1.
549B
JR DONE
[54B3H]

549DH – Continuation of the Command Loop for the MODIFY COMMAND – Process a RIGHT ARROW

549D
“RIGHT”
LD HL,(WHERE)
[554FH]
Fetch the value stored at memory location 554FH (i.e., the CURSOR POSITION) and put it into Register HL.
54A0
INC L
Bump the value stored in Register L (i.e., the CURSOR POSITION) by 1.
54A1
JR DONE
[54B3H]

54A3H – Continuation of the Command Loop for the MODIFY COMMAND – Process a UP ARROW

54A3
“DWN1”
LD HL,(WHERE)
[554FH]
Fetch the value stored at memory location 554FH (i.e., the CURSOR POSITION) and put it into Register HL.
54A6
LD A,L
LET Register A = Register L (i.e., the CURSOR POSITION).
54A7
SUB 10H
SUBtract the value 10H (Decimal: 16) from Register A (i.e., the CURSOR POSITION) to move 1 row up.
54A9
LD L,A
LET Register L = Register A (i.e., the CURSOR POSITION – 16).
54AA
JR DONE
[54B3H]

54ACH – Continuation of the Command Loop for the MODIFY COMMAND – Process a LINE FEED

54AC
“UP1”
LD HL,(WHERE)
[554FH]
Fetch the value stored at memory location 554FH (i.e., the CURSOR POSITION) and put it into Register HL.
54AF
LD A,L
LET Register A = Register L (i.e., the CURSOR POSITION).
54B0
ADD the value 10H (Decimal: 16) to Register A (i.e., the CURSOR POSITION) to move 1 row down.
54B2
LD L,A
LET Register L = Register A (i.e., the CURSOR POSITION + 16).
54B3
“DONE”
LD (WHERE),HL
[554FH]
Store the value held in Register HL into the memory location 554FH (i.e., the CURSOR POSITION).
54B6
JP BACK
[544FH]

54B8H – Modify RAM

54B8
“DIGIT”
LD DE,(CURSA)
[5551H]
Fetch the value stored at memory location 5551H (i.e., the cursor position) and put it into Register DE.
54BC
CALL DISP
[5402H]
GOSUB to 5402H to display a character.
54BF
LD (CURSA),DE
[5551H]
Store the value held in Register DE into the memory location 5551H (i.e., the cursor position).
54C3
CALL MAKHEX
[551EH]
GOSUB to 551EH to convert a Hexidecimal Number (stored in A) to Decimal (stored in A). On Entry Register E holds the LSB of the cursor position, which is increased by 1.
54C6
54C8
54CA
54CC
SLA A
SLA A
SLA A
SLA A
Move the nybble 4 bits left to make the LSB the MSB
54CE
LD B,A
LET Register B = Register A (i.e., the nybble rotated decimal value).
54CF
PUSH BC
Save Register BC, which includes the nybble rotated decimal value, to the top of the STACK.
54D0
“DIGIT1”
CALL GETKEY
[54FEH]
GOSUB to 54FEH to get the next character.
54D3
CP 30H
Compare the value held in Register A against 30H (ASCII: 0). Results:
• If Register A equals 0, the Z FLAG is set.
• If A < 0, the CARRY FLAG will be set.
• if A >= 0, the NO CARRY FLAG will be set.
54D5
JR C,DIGIT1
[54D0H]
If the C FLAG (Carry) is set because A < 0, then the character is too low, so JUMP back to 54D0H.
54D7
CP 3AH
Compare the value held in Register A against 3AH (ASCII: 1 more than 9). Results:
• If Register A equals 1 more than 9, the Z FLAG is set.
• If A < 1 more than 9, the CARRY FLAG will be set.
• if A >= 1 more than 9, the NO CARRY FLAG will be set.
54D9
JR C,DIGIT2
[54E3H]
If the C FLAG (Carry) is set because A < 1 more than 9, then we have a digit, so JUMP to 54E3H.
54DB
CP 41H
Compare the value held in Register A against 41H (ASCII: A). Results:
• If Register A equals A, the Z FLAG is set.
• If A < A, the CARRY FLAG will be set.
• if A >= A, the NO CARRY FLAG will be set.
54DD
JR C,DIGIT1
[54D0H]
If the C FLAG (Carry) is set because A < A, then the character is too low (because we already know its not a digit, and everything else down there is invalid), so JUMP back to 54D0H.
54DF
CP 47H
Compare the value held in Register A against 47H (ASCII: 1 more than F). Results:
• If Register A equals 1 more than F, the Z FLAG is set.
• If A < 1 more than F, the CARRY FLAG will be set.
• if A >= 1 more than F, the NO CARRY FLAG will be set.
54E1
JR NC,DIGIT1
[54D0H]
If the NC FLAG (No Carry) is set because A >= 1 more than F, then the character is too high, so JUMP back to 54D0H.

If we are here, then we know the rotated register A is 0-9 or A-F.

54E3
“DIGIT2”
LD DE,(CURSA)
[5551H]
Fetch the value stored at memory location 5551H (i.e., the cursor position) and put it into Register DE.
54E7
CALL DISP
[5402H]
GOSUB to 5402H to display the entered character.
54EA
LD (CURSA),DE
[5551H]
Store the value held in Register DE into the memory location 5551H (i.e., the cursor position).
54EE
CALL MAKHEX
[551EH]
GOSUB to 551EH to convert a Hexidecimal Number (stored in A) to Decimal (stored in A). On Entry Register E holds the LSB of the cursor position, which is increased by 1.
54F1
POP BC
Restore Register Pair BC (i.e., the nybble rotated decimal value) the from the top of the STACK.
54F2
ADD the value held in Register B to Register A (Results held in Register A) to reconstitute the byte.
54F3
LD HL,(WHERE)
[554FH]
Fetch the value stored at memory location 554FH (i.e., the data address to modify) and put it into Register HL.
54F6
LD (HL),A
Store the value held in Register A (i.e., the reconstituted byte received from the user) into the memory location pointed (i.e., the data address to modify) to by Register Pair HL.
54F7
INC L
Bump the value stored in Register L by 1 to point to the next byte.
54F8
LD (WHERE),HL
[554FH]
Store the value held in Register HL into the memory location 554FH (i.e., the next data address).
54FB
JP BACK
[544FH]

54FEH – Get a Character from the User

54FE
“GETKEY”
PUSH HL
Save Register HL to the top of the STACK.
54FF
LD HL,(CURSA)
[5551H]
Fetch the value stored at memory location 5551H (i.e., the cursor position) and put it into Register HL.
5502
LD (CURSOR),HL
[4020H]
Store the value held in Register HL into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
5505
POP HL
Restore Register Pair HL from the top of the STACK.
5506
LD A,0FH
LET Register A = 0FH to indicate CURSOR ON.
5508
CALL DSP
0033H
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
550B
EI
Enable Interrupts.
550C
JP KEY
[0049H]
JUMP to 0049H in the ROM to wait for a keyboard response and RETURN.

550FH – Write a Diskette File Page to Diskette

550F
“BWRITE”
LD DE,BDCB
[5555H]
LET Register Pair DE = 5555H (i.e., the FCB).
5512
GOSUB to 4439H in OVERLAY 1 which is the WRITE VECTOR.
5515
JP NZ,BERR
[5405H]
If the NZ FLAG (Not Zero) is set, then the WRITE VECTOR call produced an error, so JUMP to 5405H to handle the diskette-related error.
5518
GOSUB to 4445H which is the BACKSPACE VECTOR (i.e., Back Up To the Previous Record in a File) in Overlay 1.
551B
JP CONT0
[5330H]

551EH – Convert an ASCII Hexidecimal Number (stored in A) to Decimal (stored in A). On Entry Register E holds the LSB of the cursor position and on exit that is increased by 1.

551E
“MAKHEX”
SUB 30H
SUBtract the value 30H from Register A, thus converting an ASCII number to Decimal.
5520
CP 0AH
Compare the value held in Register A against 0AH (Decimal: 10). Results:
• If Register A equals 10, the Z FLAG is set.
• If A < 10, the CARRY FLAG will be set.
• if A >= 0AH, the NO CARRY FLAG will be set.
5522
RET C
If A < 10 then the C FLAG (Carry) will be set and we need to RETurn to the caller.
5523
SUB 07H
Convert “A”-“F” to 10-15 by SUBtracting the value 07H from Register A.
5525
RET

5526H – Message Storage Area

5526
“TITLE”
DEFW
1CH + 1FH + “Debug Disk Utility Ver 1.3” + 0DH.
5544
“BPROMT”
DEFW
0AH + “Filespec: “ + 03H.
5550
“BUFF1”
DEFW 4300H

5551
“CURSA”
DEFW 3C00H

5553
“MOVFLG”
DEFB 00H

5555
“BDCB”
DEFW 00H
DEFW 00H
DEFW 00H

555B
“DRV”
DEFW 00H
DEFW 00H

555F
“NRN”
DEFW 00H

5561
“ERN”
DEFW 00H

END 4E00H