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

Overview

General

SYS5 implements the TRSDOS 1.3 DEBUG monitor. It is loaded as an overlay by the DOS loader when the user enters the DEBUG command, or when a running program triggers a breakpoint (RST 30H, OPCODE 0F7H) while the debugger is enabled. The overlay occupies 4E00H through 5562H in RAM, providing the following functions:

KeyRoutineDescription
J / GGO (4FF7H)Jump to or go to a user-supplied address. Both keys invoke the same handler; the difference is whether additional breakpoints are set first.
SPAGE (4EB3H)Switch to full-page (16-row) memory display mode.
XOVER (4EB2H)Switch back to half-page (8-row) memory display mode.
;NXTMEM (4EE3H)Advance the memory display by 16 bytes (half-page mode) or 256 bytes (full-page mode).
-BCKMEM (4F0AH)Back up the memory display by 16 bytes (half-page mode) or 256 bytes (full-page mode).
C / ISINGLE (50DBH)Single-step. C steps over CALL instructions (executes the subroutine in one step); I steps into them.
DDOIT (4EC1H)Prompt for a new memory-display (dump) address.
MMEMORY (504DH)Modify user RAM: prompt for an address, then allow byte-by-byte editing with cursor keys and hex digits.
RREGIST (508AH)Modify a user register: prompt for register name (AF, BC, AF', etc.), then prompt for a new value.
UUPDATE (4EB7H)Continuously redisplay memory until a key is pressed (live view).
FTRA (52BDH)Enter the Disk Utility: prompt for a filespec, open the file via OPEN SVC, and allow browsing/modifying its records.
QQUIT (5286H)Clear the disk-side flag (CSIDE) and return to DOS via SYS1IN.

Memory Map

RangeContents
4E00H–52B8HMain DEBUG monitor code: entry/register save, command dispatch loop, display routines, single-step engine, hex input parser, and shared I/O helpers.
52B9H–52BCHModule ENTRY point called by the DOS loader. Pops the dispatch byte from the stack and JP START.
52BDH–5525HDisk Utility code: filespec prompt, file open, record browsing loop, record-modify engine, error handler, and disk write-back.
5526H–554EHStatic message strings: TITLE (5526H, "Debug Disk Utility Ver 1.3") and BPROMT (5543H, "Filespec: ").
554FH–5562HDisk Utility workspace: WHERE, CURSA, MOVFLG, SLRL, BDCB (8 bytes), DRV, NRN, ERN.
5600HENDBUG floor: the lowest address the user may reach via DUMP or MODIFY commands. Protects SYS5's own code and all SYS0 resident data structures from accidental modification.
4100H–411FHSYS5 register-save area (MEM through MEM+31). Used only while DEBUG is active; physically shares RAM with BASIC's workspace.

Register Save Area (MEM+0 through MEM+31)

When DEBUG is entered, all user registers are preserved in a 24-byte save area starting at MEM+8 (4108H). Additional control variables occupy MEM+0 through MEM+7.

OffsetAddressPurpose
MEM+04100HBreakpoint table base (2 entries, 2 bytes each for target address)
MEM+14101HDisplay-mode flag: 00H = half page (8 rows), non-zero = full page (16 rows)
MEM+34103HMemory-modify (M command) address
MEM+54105HScratch area for breakpoint save (used by single-step engine)
MEM+64106HCurrent memory-display (dump) address
MEM+84108HStart of user-register save area (24 bytes: AF, BC, DE, HL, AF', BC', DE', HL', IX, IY, SP, ...)
MEM+14410EHUser's saved SP (within register save area)
MEM+244118HUser's saved IX
MEM+26411AHUser's saved IY
MEM+28411CHDEBUG's own stack pointer (saved on entry, restored at START5)
MEM+29411DHEnd of user-register save area (last byte)
MEM+30411EHUser's saved PC (where execution will resume)

Self-Modifying Code Locations

SYS5 uses four self-modifying code locations within its overlay space. Each source label marks an operand byte within an instruction whose runtime value is written by other code in SYS5. These addresses are fleeting (they do not persist when SYS5 is unloaded and another overlay reuses the space), so they are NOT tracked in the site-wide RAM addresses index — only within this page's disassembly.

AddressLabelDescription
4F61HCURSAVOperand byte of LD HL,0 inside DISPLY. Set to the current cursor position by the register-display routine, and loaded back when the display shifts down to draw the PC byte line.
5054HSAVCUROperand byte of LD HL,0 inside MEMOR0. Used by both DOIT (dump-address prompt) and MEMORY (modify-memory prompt) to save and restore the cursor position across re-prompts.
545FHNODISKOperand byte of LD A,0 in the BACK1 keyboard-wait loop. Set to 00H = Disk Utility mode (so ENTER writes back to disk), or non-zero = Memory-modify mode (so ENTER returns to DEBUG without a disk write).
5366HCHGBMPInitially a NOP at the top of the LOP1 display loop. After the first successful file read, BREADX patches it to INC HL (0x23) so that subsequent record numbers display correctly as 1-origin rather than 0-origin.

Disk Utility Workspace (554FH–5562H)

AddressLabelDescription
554FHWHERECurrent buffer/position pointer (defaults to BUFF1 = 4300H). Tracks which byte the user is editing within the file record.
5551HCURSASaved screen cursor address (defaults to 3C00H, top-left of screen).
5553HMOVFLGDisplay-block flag: 00H = show data normally, non-zero = also show the block cursor at WHERE.
5554HSLRLThe user's original LRL (Logical Record Length) is saved here before the DCB is overridden for full-sector (256-byte) I/O.
5555HBDCB8-byte DCB (Device Control Block) holding the filespec entered by the user.
555BHDRVDrive number extracted from the filespec (within BDCB context).
555FHNRNNext Record Number: the record currently being displayed.
5561HERNEnd Record Number: the last record in the file (read from the DCB during open).

DOS Entry Points Used

AddressLabelPurpose
002BHKBDPoll keyboard; returns 00H in A if no key is pressed, else the ASCII code
0033HDSPDisplay the character in A at the current cursor position
0040HKEYNRead a full line from the keyboard (up to B chars, terminated by ENTER); BREAK sets carry
0049HKEYWait for a single keyboard character (blocking)
021BHPRINTDisplay the string at (HL) until a 03H terminator is encountered
01C9HCLSClear the screen (ROM routine)
402DHSYS1INNormal return-to-DOS entry point (used by QUIT)
4409HERRORSYS0 error-handler dispatch: PUSH AF then DO 00,4 to load the SYS4 error overlay
4424HOPENSYS0 OPEN SVC (DO 10,2): open an existing file whose filespec is pointed to by DE, buffer at HL, LRL in B
4436HREADSYS0 READ SVC: read one record from the file whose DCB is at DE, into the buffer at HL
4439HWRITESYS0 WRITE SVC: write the current record to the file whose DCB is at DE
443FHREWINDSYS0 REWIND SVC: rewind the file at DE to its first record
4445HBACKSPSYS0 BACKSP SVC: back up one record in the file at DE
4448HPOSEOFSYS0 POSEOF SVC: position the file at DE to its end-of-file record

External RAM Variables Referenced

AddressLabelUsage by SYS5
4020HCURSORSYS0's cursor-position variable. SYS5 reads and writes it during display operations.
4023HCURSCRSYS0's cursor-character variable. SYS5 writes 0B0H (block cursor) at several points to set the display cursor style.
442BHOVLFLGSYS0's overlay-loaded flag. On entry, SYS5 clears bit 4 to indicate SYS6 (Library Commands) is no longer in memory (since SYS5 just displaced it).
4463HCSIDESYS0's current-disk-side variable. QUIT clears it to 0 before returning to DOS, forcing side 0 for the next disk operation.

Single-Step Opcode Tables

The single-step engine (SINGLE, 50DBH) uses three data tables to decode the next instruction and determine where to place a breakpoint:

AddressLabelPurpose
5160HTABLE1"Normal" Z80 opcode table: matches opcode bytes against masks to classify as simple step, relative jump, absolute jump, call, return, or JP (HL)
518EHTABLE2"ED" prefix opcode table: for LDIR, LDDR, RETI, RETN, etc.
5195HTABLE3"DD" and "FD" prefix opcode table: for IX/IY indexed instructions including JP (IX) and JP (IY)

Each table entry is a 3-byte record containing a mask byte, a match byte, and an options byte. The options byte encodes both the instruction length (low nibble) and the branching type (high nibble).

Cross-References and Analysis Notes

  • 545FH label note: This self-modifying operand is labeled NODISK in the SYS5 source (via NODISK EQU $+1). The page consistently uses the source label NODISK for this address.
  • LEFT/RIGHT source-label quirk: In the Disk Utility keyboard dispatch, the source labels LEFT and RIGHT are swapped relative to their behavior. The key-code dispatch compensates (key 09H = right arrow jumps to LEFT, which does INC L; key 08H = left arrow jumps to RIGHT, which does DEC L). Net behavior is correct; source labels are kept verbatim here for traceability.
  • MEM at 4100H is ephemeral: The 32-byte register-save area at 4100H-411FH shares physical RAM with BASIC's workspace and other transient uses. It is valid only while DEBUG is the active foreground routine; for this reason these addresses are not tracked as stable variables in the site-wide RAM addresses index.
  • ENDBUG = 5600H: This is an assemble-time constant (not a RAM variable), baked into the binary at 4ED8H, 4EFEH, and 5067H as LD DE,5600H. Its purpose is to refuse DUMP and MODIFY commands that would reach into SYS5's own code or SYS0's resident data.
  • ENTRY vs START: The DOS loader enters SYS5 at ENTRY (52B9H), which pops the SVC dispatch byte from the stack and then falls through to a JP START (at 52BAH). START (4E00H) is the address where debugger re-entry via RST 30H breakpoints arrives, after SYS0's DEBUG vector at 440DH has pushed AF and loaded SYS5.

Disassembly

4E00H - START - Entry Point

 
ORG 4E00HORG START

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.

4E00START
PUSH AF
Save Register AF to the top of the STACK.
Original Source Code Comment: SAVE ALL REGISTERS
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.
Original Source Code Comment: GET THE STACK POINTER
4E14
ADD HL,SP
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.
Original Source Code Comment: INTO HL
4E15
LD DE,4108HLD DE,MEM+8
LET Register Pair DE = 4108H, which is the bottom of the storage area where those registers are going to get preserved.
Original Source Code Comment: MOVE THE REGISTER SAVES TO
4E18
LD BC,0018H
LET Register Pair BC = 0018H (Decimal: 24) because there are 24 register pairs to save.
Original Source Code Comment: OUR OWN AREA
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 (411CH),HLLD (MEM+28),HL
Store the value held in Register HL (i.e., the old STACK pointer) into the memory location 411CH for safekeeping.
Original Source Code Comment: SAVE THE POINTER TO THE REGISTERS
4E20
LD A,(442BH)LD A,(OVLFLG)
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.
Original Source Code Comment: GET THE OVERLAY 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.
Original Source Code Comment: SHOW SYS6 NOT IN MEMORY
4E25
LD (442BH),ALD (OVLFLG),A
Store the value held in Register A into the memory location 442BH.
NOTE: 442BH is the storage location for the OVERLAY FLAG flag.
Original Source Code Comment: SAVE THE 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.
Original Source Code Comment: SET TOP OF REGISTERS AS STACK
4E29
LD HL,(411EH)LD HL,(MEM+30)
Fetch the value stored at memory location 411EH (i.e., the Program Counter for the running program) and put it into Register HL.
Original Source Code Comment: GET THE USERS PC
4E2C
DEC HL
Back up 1 instruction by DECrementing the value stored in Register Pair HL.
Original Source Code Comment: BACK UP ONE INSTRUCTION
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.
Original Source Code Comment: GET IT
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.
Original Source Code Comment: WAS THIS OUR BREAKPOINT?
4E30
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).
Original Source Code Comment: NO, JUST DISPLAY
4E32
LD (411EH),HLLD (MEM+30),HL
Store the value held in Register HL (i.e., the Program Counter for the running program MINUS 1) into the memory location 411EH.
Original Source Code Comment: YES, SAVE AT USERS PC

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

4E35START2
LD HL,4100HLD HL,MEM
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.

4E3AH - "START1" - Top of loop checking breakpoints

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

4E3ASTART1
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
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
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).
4E4ESTART4
INC HL
Bump the value stored in Register Pair HL by 1 to move to the next breakpoint in the breakpoint storage area.
4E4F
LOOP back to 4E3AH until Register B is ZERO.

4E51H - START5 - Command loop

Set up STACK, turn on cursor, display the screen, and process the DEBUG commands.

4E51START5
LD SP,(411CH)LD SP,(MEM+28)
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.
Original Source Code Comment: RESET THE STACK POINTER
4E55
LD A,0B0H
LET Register A = 0B0H (ASCII: BLOCK cursor).
4E57
LD (4023H),ALD (CURSCR),A
Store the value held in Register A into the memory location 4023H.
NOTE: 4023H is the storage location for the CURSOR CHARACTER.
Original Source Code Comment: SET THE CURSOR
4E5A
LD A,0EH
LET Register A = 0EH, which is ENABLE cursor.
Original Source Code Comment: INSURE CURSOR ON
4E5C
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
Original Source Code Comment: OUTPUT IT
4E5F
EI
Enable Interrupts.
Original Source Code Comment: INTERRUPTS ON
4E60
GOSUB to 4F0FH to display the DEBUG screen and all the registers.
Original Source Code Comment: DISPLAY ALL THE REGISTERS

4E63H - "START6" - Main command processing

4E63START6
LD HL,3FC0H
LET Register Pair HL = 3FC0H, which would be the first character on the 15th line of the display.
Original Source Code Comment: RESET THE CURSOR TO MIDDLE LINE
4E66
LD (4020H),HLLD (CURSOR),HL
Store the value held in Register HL into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
Original Source Code Comment: SET CURSOR
4E69
EI
Enable Interrupts.
Original Source Code Comment: INTERRUPTS ON
4E6A
GOSUB to 51F1H to get character from the keyboard and process accordingly.
Original Source Code Comment: GET A COMMAND
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.
Original Source Code Comment: JUMP?
4E6F
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.
Original Source Code Comment: GO?
4E74
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,4E51HLD HL,START5
LET Register Pair HL = 4E51H (i.e., this command loop) as the return address
Original Source Code Comment: PUT A 'RET' ADDRESS ON THE STACK
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.
Original Source Code Comment: FULL SCREEN?
4E7D
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.
Original Source Code Comment: NEXT BLOCK OF MEMORY?
4E81
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.
Original Source Code Comment: BACK UP ONE BLOCK?
4E85
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.
Original Source Code Comment: SINGLE STEP (AROUND CALLS)?
4E8A
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.
Original Source Code Comment: DISPLAY RAM LOCATIONS?
4E8E
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.
Original Source Code Comment: SINGLE STEP?
4E92
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.
Original Source Code Comment: ALTER MEMORY LOCATIONS?
4E97
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.
Original Source Code Comment: CHANGE REGISTER?
4E9C
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.
Original Source Code Comment: UPDATE DISPLAY?
4EA1
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.
Original Source Code Comment: BACK TO NORMAL MODE?
4EA5
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.
Original Source Code Comment: DISK OPERATION?
4EA9
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.
Original Source Code Comment: QUIT DEBUG AND RETURN TO DOS?
4EAE
If the Z FLAG (Zero) is set, meaning that a Q key was pressed, JUMP to 5286H.
4EB1
RET
RETurn to the caller.
Original Source Code Comment: NOTHING SUPPORTED. EXIT AND TRY AGAIN

4EB2H - OVER - X Command - Half Page Display

4EB2OVER
XOR A
Set Register A to ZERO and clear all Flags.
Original Source Code Comment: ENTRY POINT FOR 'X'

4EB3H - PAGE - S Command - Full Page Display

4EB3PAGE
LD (4101H),ALD (MEM+1),A
Store the value held in Register A (i.e., a S, or really just any non-zero value) into the memory location 4101H.
Original Source Code Comment: ENTRY POINT FOR 'S'
4EB6
RET
RETurn to the caller.

4EB7H - UPDATE - U Command - Continuous Redisplay of Memory

Continuous redisplay of memory until a key is pressed

4EB7UPDATE
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.
Original Source Code Comment: TRY FOR A KEYBOARD CHAR
4EBA
OR A
Set FLAGS based on the contents of Register A.
Original Source Code Comment: ANY THERE?
4EBB
RET NZ
If the NZ FLAG (Not Zero) is set, meaning a key was pressed, RETurn to the caller.
Original Source Code Comment: YES, EXIT
4EBC
GOSUB to 4F0FH to display memory.
Original Source Code Comment: NO, DISPLAY MEMORY
4EBF
LOOP BACK to the top of this routine at 4EB7H.
Original Source Code Comment: AND CONTINUE LOOKING FOR KEYBOARD

4EC1H - DOIT - D Command - Dump Memory

4EC1DOIT
LD HL,(4020H)LD HL,(CURSOR)
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.
Original Source Code Comment: GET THE CURSOR POSITION
4EC4
LD (5054H),HLLD (SAVCUR),HL
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.
Original Source Code Comment: SAVE IT
4EC7DOIT0
LD HL,(5054H)LD HL,(SAVCUR)
Fetch the value stored at memory location 5054H (i.e., the CURSOR POSITION ON SCREEN) and put it into Register HL.
Original Source Code Comment: GET THE CURSOR
4ECA
LD (5054H),HLLD (CURSOR),HL
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.
Original Source Code Comment: RESET IT
4ECD
LD HL,4020HLD HL,ADDR
LET Register Pair HL = 4FE7H, which is the memory location of the "ADDRESS? = ".
Original Source Code Comment: HL => 'ADDRESS' MSB
4ED0
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H is found.
Original Source Code Comment: DISPLAY IT
4ED3
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).
Original Source Code Comment: GET THE ADDRESS
4ED6
RET Z
If the Z FLAG (Zero) is set then that CALL returned an error, so RETurn to the caller.
Original Source Code Comment: EXIT IF SILLY ANSWER
4ED7
PUSH HL
Save Register HL (i.e., the user entered address) to the top of the STACK.
Original Source Code Comment: SAVE ADDR POINTER
4ED8
LD DE,5600HLD DE,ENDBUG
LET Register Pair DE = 5600H, as the lowest memory address which a DUMP is permitted.
Original Source Code Comment: DE => LOWEST LEGAL ADDRESS
4EDB
OR A
Set FLAGS based on the contents of Register A.
Original Source Code Comment: CLEAR CARRY
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.
Original Source Code Comment: SEE IF LEGAL ADDR
4EDE
POP HL
Restore Register Pair HL (i.e., the response from the CALL) from the top of the STACK.
Original Source Code Comment: GET ADDR BACK
4EDF
If the C FLAG (Carry) is set then we are below the limits, so LOOP back to 4EC7H to try again.
Original Source Code Comment: NO, TRY IT AGAIN
4EE1
JUMP to 4EF7H to store the answer and continue the DUMP command.
Original Source Code Comment: ELSE STORE THE ANSWER

4EE3H - NXTMEM - ; Command - Advance display to the next line

4EE3NXTMEM
LD BC,0010H
LET Register Pair BC = 0010H (Decimal 16) to move 16 bytes forward.
Original Source Code Comment: SET FOR + 16 BYTES
4EE6NXTME0
LD HL,(4106H)LD HL,(MEM+6)
Fetch the value stored at memory location 4106H (i.e., the current DUMP address) and put it into Register HL.
Original Source Code Comment: GET THE CURRENT DISPLAY ADDRESS
4EE9
LD A,(4101H)LD A,(MEM+1)
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.
Original Source Code Comment: ARE WE IN FULL PAGE MODE?
4EEC
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4EED
If the Z FLAG (Zero) is set then we are at HALF PAGE display so JUMP to 4EF6H to bump the display by 16.
Original Source Code Comment: NO, BUMP 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
Original Source Code Comment: YES, DISTROY THE '16'
4EF1
LD A,B
LET Register A = Register B.
Original Source Code Comment: IS THE AMOUNT 256
4EF2
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4EF3
If the NZ FLAG (Not Zero) is set, skip the next instruction and JUMP to 4EF6H.
Original Source Code Comment: YES, UPDATE ADDRESS
4EF5
INC B
Bump the value stored in Register B by 1 to increase the MSB.
Original Source Code Comment: NO, MAKE IT 256
4EF6OUT1
ADD HL,BC
ADD the value held in Register Pair BC to Register Pair HL, so that HL has the new DUMP address.
Original Source Code Comment: ADD THE OFFSET TO OLD ADDRESS
4EF7OUT2
LD A,L
LET Register A = Register L to prepare to make sure we have a smooth HL value.
Original Source Code Comment: GET THE LSB OF THE ADDRESS
4EF8
AND 0F0H
MASK the value of Register A against 0F0H (1111 0000) to make a round number.
Original Source Code Comment: FORCE IT TO 0 BOUNDARY
4EFA
LD L,A
LET Register L = the masked/smoothed Register A.
Original Source Code Comment: NEW LSB
4EFBOUT4
LD (4106H),HLLD (MEM+6),HL
Store the value held in Register HL into the memory location 4106H (i.e., the current DUMP address).
Original Source Code Comment: SAVE THE NEW DISPLAY ADDRESS
4EFE
LD DE,5600HLD DE,ENDBUG
LET Register Pair DE = 5600H, as the lowest memory address which a DUMP is permitted.
Original Source Code Comment: LOWEST USER RAM ALLOWED
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.
Original Source Code Comment: WITHIN RANGE?
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.
Original Source Code Comment: YES, EXIT
4F05
LD (4106H),DELD (MEM+6),DE
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).
Original Source Code Comment: NO, SET DEFAULT MEMORY
4F09
RET
RETurn to the caller.
Original Source Code Comment: DONE

4F0AH - BCKMEM - - Command - Backspace next line

4F0ABCKMEM
LD BC,0FFF0H
LET Register Pair BC = 0FFF0H (Decimal: -16).
Original Source Code Comment: SET FOR -16
4F0D
JUMP to 4EE6H of the prior location to do everything the advance line routine does, but with a negative number.
Original Source Code Comment: AND CONTINUE

4F0FH - DISPLY - SUBroutine to display the DEBUG screen

4F0FDISPLY
DI
Disable Interrupts.
Original Source Code Comment: INTERRUPTS OFF
4F10
LD A,(4101H)LD A,(MEM+1)
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.
Original Source Code Comment: WE IN FULL PAGE MODE?
4F13
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
4F14
If the NZ FLAG (Not Zero) is set then we are at HALF PAGE display, so JUMP to 4F93H.
Original Source Code Comment: YES, DISPLAY FULL PAGE

We need to process a FULL SCREEN debug screen.

4F17
LD A,1CH
LET Register A = 1CH (ASCII: Clear Screen).
Original Source Code Comment: HOME CURSOR
4F19
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
Original Source Code Comment: OUT TO THE DISPLAY
4F1C
LD HL,3C00H
LET Register Pair HL = 3C00H (i.e., the first screen location).
Original Source Code Comment: TOP OF THE SCREEN
4F1F
LD (4020H),HLLD (CURSOR),HL
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.
Original Source Code Comment: SET THE CURSOR POSITION
4F22
GOSUB to 4F80H to display the memory.
Original Source Code Comment: DISPLAY THE MEMORY
4F25
GOSUB to 5273H to display a carriage return.
Original Source Code Comment: OUTPUT A CR
4F28
LD HL,(4020H)LD HL,(CURSOR)
Fetch the value stored at memory location 4020H (i.e., the cursor location on screen) and put it into Register HL.
Original Source Code Comment: GET THE PRESENT CURSOR LOCATION
4F2B
LD (4F61H),HLLD (CURSAV),HL
Store the value held in Register HL (i.e., the cursor location on screen) into the memory location 4F61H.
Original Source Code Comment: AND SAVE IT FOR LATER
4F2E
LD BC,00C0H
LET Register Pair BC = 00C0H (Decimal: 192) as an offset to HL to move the cursor down 3 lines.
Original Source Code Comment: MOVE THE CURSOR DOWN 3 LINES
4F31
ADD HL,BC
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.
Original Source Code Comment: HL = NEW CURSOR POSITION
4F32
LD (4020H),HLLD (CURSOR),HL
Store the value held in Register HL into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
Original Source Code Comment: SET IT
4F35
LD HL,4FA2HLD HL,DISPL7
LET Register Pair HL = 4FA2H so as to point to the message storage area for "SP PC AF ..".
Original Source Code Comment: HL => 'SP PC AF ETC' MSG
4F38
GOSUB to 021BH to display that message.
NOTE: 021BH will display the character at (HL) until a 03H is found.
Original Source Code Comment: DISPLAY IT
4F3B
GOSUB to 5273H to display a carriage return.
Original Source Code Comment: AND A CR
4F3E
LD HL,4108HLD HL,MEM+8
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,4FA2HLD HL,DISPL7
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.
Original Source Code Comment: SET FOR 12 REGISTER PAIRS
4F47DISPL1
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
JUMP to 5258H to convert that MSB to ASCII and display
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
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

4F59
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
LOOP back to 4F47H until Register B is ZERO.
4F5F
POP HL
Clear the STACK.
4F60
LD HL,[CURSAV]
LET Register Pair HL = a value placed by other locations in this overlay into "CURSAV".
Original Source Code Comment: CURSOR SAVED HERE
4F63
LD BC,0040HLD BC,KEYN
LET Register Pair BC = 0040H (Decimal: 64) for an offset of one screen line.
Original Source Code Comment: BUMP DOWN ONE LINE
4F66
ADD HL,BC
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.
Original Source Code Comment: HL = NEW CURSOR
4F67
LD (4020H),HLLD (CURSOR),HL
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.
Original Source Code Comment: SET IT
4F6A
LD HL,4FD7HLD HL,PC
LET Register Pair HL = 4FD7H, which points to the message PC.
Original Source Code Comment: HL => 'PC' MSG
4F6D
GOSUB to 021BH to display that message.
NOTE: 021BH will display the character at (HL) until a 03H is found.
Original Source Code Comment: DISPLAY IT
4F70
GOSUB to 526FH to display a space.
Original Source Code Comment: AND A SPACE
4F73
LD HL,(411EH)LD HL,(MEM+30)
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.
Original Source Code Comment: HL => USERS PC AREA
4F76
LD B,10H
LET Register B = 10H (Decimal: 16) to set up for a loop of 16.
Original Source Code Comment: SET FOR 16 BYTES
4F78
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
Original Source Code Comment: GET A BYTE
4F79
GOSUB to 526CH to print a byte held in Register A as a two byte ascii value followed by a space.
Original Source Code Comment: OUTPUT IT AS TWO BYTE ASCII AND SPACE
4F7C
INC HL
Bump Register Pair HL to point to the next byte.
Original Source Code Comment: BUMP TO NEXT BYTE
4F7D
LOOP back to 4F78H until Register B is ZERO.
Original Source Code Comment: LOOP FOR COUNT
4F7F
RET
RETurn to the caller.
Original Source Code Comment: DONE WITH DISPLAY

4F80H - ONELNE - SUBroutine to display RAM locations

4F80ONELNE
LD HL,(4106H)LD HL,(MEM+6)
Fetch the value stored at memory location 4106H (i.e., the current DUMP ADDRESS) and put it into Register HL.
Original Source Code Comment: GET THE MEMORY POINTER
4F83
LD B,08H
LET Register B = 08H to set up for a DJNZ loop of 8 iterations for 8 rows.
Original Source Code Comment: SET FOR 8 ROWS
4F85LOOP1
GOSUB to 5253H to display the address in hexadecimal.
Original Source Code Comment: OUTPUT THE ADDRESS ON SCREEN
4F88
GOSUB to 526FH to display a space.
Original Source Code Comment: AND A SPACE
4F8B
GOSUB to 51B1H to display a data line.
Original Source Code Comment: DISPLAY ONE LINE
4F8E
LOOP back to 4F85H until Register B is ZERO (i.e., 8 iterations).
Original Source Code Comment: LOOP FOR COUNT
4F90
JUMP to 5277H to clear the rest of the screen and exit.
Original Source Code Comment: AND CLEAR THE REST OF THE SCREEN

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

4F93CURS1
LD HL,3C00H
LET Register Pair HL = 3C00H, which is the top of the screen.
Original Source Code Comment: HL = TOP OF SCREEN ADDRESS
4F96
LD (4020H),HLLD (CURSOR),HL
Store the value held in Register HL into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
Original Source Code Comment: SET IT AS CURSOR POSITION
4F99
LD HL,(4106H)LD HL,(MEM+6)
Fetch the value stored at memory location 4106H (i.e., the address to display) and put it into Register HL.
Original Source Code Comment: HL => ADDRESS TO DISPLAY
4F9C
LD L,00H
LET Register L = 00H to have a smooth address / even page in HL.
Original Source Code Comment: INSURE EVEN BOUNDARY
4F9E
LD B,10H
LET Register B = 10H (Decimal: 16) for a loop of 16 rows to display.
Original Source Code Comment: SET FOR 16 ROWS
4FA0
JUMP to 4F85H.
Original Source Code Comment: AND DISPLAY IT

4FA2H - DISPL7 - Message Storage Area

4FA2DISPL7
DEFM
" AF BC DE HL AF' B C' DE' HL' IX IY SP PC " + 03H
4FDFFLAGS
DEFM
"SZ1H1POC"
4FE6
DEFM
1EH + " ADDRESS? = " + 1EH + 0EH + 03H

4FF7H - GO - Routine to process "G" and "J" by JUMPing to a specified address

4FF7GO
LD HL,4FE7HLD HL,ADDR
LET Register Pair HL = 4FE7H, which is the pointer to the message "ADDRESS? = ".
4FFA
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,4105HLD DE,MEM+5
LET Register Pair DE = 4105H to point to the breakpoint storage area.
5002
GOSUB to 521FH to to get input from the user and store it in Register Pair HL (i.e., the JUMP address).
5005
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 (411EH),HLLD (MEM+30),HL
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).
500AGO1
If the C FLAG (Carry) is set then we are out of input, JUMP to 5016H.
500C
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
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
LOOP back to 500AH until Register B is ZERO (i.e., both breakpoints have been processed).
5016GO2
LD HL,411DHLD HL,MEM+29
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.
501BGO3
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
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,(411EH)LD HL,(MEM+30)
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,(410EH)LD HL,(MEM+14)
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 - SET - SUBroutine to Save the Breakpoint into a Table (done backwards)

503CSET
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
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
RETurn to the caller.

504DH - MEMORY - Routine to MODIFY AND DISPLAY RAM - the "M" option

504DMEMORY
LD HL,(4020H)LD HL,(CURSOR)
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 (5054H),HLLD (SAVCUR),HL
Store the value held in Register HL (i.e., the cursor position on screen) into the memory location 5054H.
5053MEMOR0
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 (5054H),HLLD (SAVCUR),HL
Store the value held in Register HL (i.e., the cursor position on screen) into the memory location 5054H.
5059
LD HL,4FE7HLD HL,ADDR
LET Register Pair HL = 4FE7H so as to point to the "ADDRESS" message.
505C
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H is found.
505F
LD HL,(4103H)LD HL,(MEM+3)
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
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,5600HLD DE,ENDBUG
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
If the C FLAG (Carry) is set then we are below the limits, so LOOP back to 5053H to try again.
5070
LD (554FH),HLLD (WHERE),HL
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 (4103H),HLLD (MEM+3),HL
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 (555FH),ALD (NRN),A
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 (5560H),ALD (NRN+1),A
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 (545FH),ALD (NODISK),A
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 (5553H),ALD (MOVFLG),A
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
JUMP to 544FH to display and get the changes.

508AH - REGIST - Command "R" - Modify the User Registers

508AREGIST
REGIST
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
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
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
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
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.
50A2REG1
LD HL,4FA3HLD HL,DISPL7+1
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.
50A7REG2
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
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.
50ACREG3
INC HL
Bump the value stored in Register Pair HL by 1 to point to the next record in the REGISTER STORAGE TABLE.
50ADREG4
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
If the Z FLAG (Zero) is set then we had a SPACE, JUMP back to the INC HL's to skip forward.
50B3
LOOP back to 50A7H until all 12 register pairs have been handled (i.e., Register B is ZERO).
50B5
RET
RETurn to the caller.

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

50B6REG5
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
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
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,4108HLD HL,MEM+8
LET Register Pair HL = 4108H to point to the bottom of the REGISTER SAVE area.
50CA
ADD HL,BC
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
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
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
RETurn to the caller.

50DBH - SINGLE - "I" and "C" Commands - Instruction Step / Call Step Single Step Routines

50DBSINGLE
PUSH AF
Save Register AF (i.e., the COMMAND issued; either "I" or "C") to the top of the STACK.
50DC
LD DE,(411EH)LD DE,(MEM+30)
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,5195HLD HL,TABLE3
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
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
If the Z FLAG (Zero) is set then we have an IY OPCODE, so JUMP to 50F6H.
50EC
LD HL,5160HLD HL,TABLE1
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
If the NZ FLAG (Not Zero) is set, then we do not have a MISC OPCODE, so JUMP to 50F9H.
50F3
LD HL,518EHLD HL,TABLE2
LET Register Pair HL = 518EH, which is the pointer to the "MISC" OPCODE table.
50F6SINGL1
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.
50F9SINGL2
LD C,A
LET Register C = Register A (i.e., the second byte of the the OPCODE which was to run next).
50FASINGL3
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
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
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.
5107SINGL4
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 HL,DE
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,4105HLD DE,MEM+5
LET Register Pair DE = 4105H to point to the breakpoint storage area.
5113
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
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
If the C FLAG (Carry) is set then we have a JP (HL) situation, so JUMP to 5158H.
5121
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
If the C FLAG (Carry) is set we have a JR command, so JUMP to 5140H.
5127
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
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
If the Z FLAG (Zero) is set, then we had an I command, so JUMP to 5138H.
5132SINGL5
JUMP to 5016H to execute the next instruction.

5135H - SINGL6 - Continuation of the "I"/"C" routine - Set a BREAKPOINT for either RET or JP

If the next opcode was a RET ...

5135SINGL6
LD HL,(411CH)LD HL,(MEM+28)
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.

5138SINGL7
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
JUMP to 515BH to set a breakpoint and continue.

5140H - SING70 - Continuation of the "I"/"C" routine - Set a BREAKPOINT for either RET or JP

5140SING70
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
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.
5147SINGL8
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 HL,BC
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
JUMP to 515BH to set a breakpoint and continue.

514CH - SINGL9 - Continuation of the "I"/"C" routine - Set a BREAKPOINT for either JP (IX) or JP (IY)

514CSINGL9
LD HL,(4118H)LD HL,(MEM+24)
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
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,(411AH)LD HL,(MEM+26)
Fetch the value stored at memory location 411AH (i.e., the saved IY) and put it into Register HL.
5156
JUMP to 515BH to set a breakpoint and continue.

5158H - SINGLA - Continuation of the "I"/"C" routine - Set a BREAKPOINT for either JP (HL)

5158SINGLA
LD HL,(410EH)LD HL,(MEM+14)
Fetch the value stored at memory location 410EH (i.e., the saved HL) and put it into Register HL.
515BSINGLB
GOSUB to 503CH to save HL as the breakpoint address.
515E
JUMP to 5132H to set a breakpoint and continue.

5160H - TABLE1 - OPCODE TABLE - "NORMAL" OPCODES

5160TABLE1
RET CC
RET
5163
RET
RET
5166
JP (HL)
JP (HL)
5169
LD dd,nnnn
 
516C
LD R,(nnnn)
 
516F
JP cc,nnnn
JP
5172
JP nnnn
JP
5175
CALL cc,nnnn
CALL
5178
CALL nnnn
CALL
517B
LD R,nn
 
517E
OUT (nn),A
 
5181
ADD A,nn
 
5184
BIT nn,R
 
5187
DJNZ or JR
JR
518A
JR cc,dis
JR
518D
END OF TABLE
 

518EH - TABLE2 - OPCODE TABLE - "ED" OPCODES

518ETABLE2
LD dd,(nnnn)
 
5191
RETI,RETN
RET
5194
END OF TABLE
 

5195H - TABLE3 - OPCODE TABLE - "DD" and "FD" OPCODES

5195TABLE3
INC
 
5198
LD
 
519B
ADD
 
519E
LD
 
51A1
LD
 
51A4
LD
 
51A7
LD
 
51AA
BIT
 
51AD
JP (IX),JP (IY)
JP (IX),JP (IY)
51B0
END OF TABLE
 

51B1H - OUTLNE - Display One Line of Memory

51B1OUTLNE
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
GOSUB to 526FH to display a SPACE.
51B8
GOSUB to 524FH to display the MSB of the address.
51BB
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
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
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
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
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
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
LD A,2EH
LET Register A = 2EH (ASCII: .).
51D7
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
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,(4020H)LD HL,(CURSOR)
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
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
GOSUB to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.
51EF
POP BC
Restore Register Pair BC (i.e., the counter) from the top of the STACK.
51F0
RET
RETurn to the caller.

51F1H - KEYLIN - SUBROUTINE to get a character from the keyboard and process accordingly

51F1KEYLIN
PUSH DE
Save Register DE to the top of the STACK.
51F2
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
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
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
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
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
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
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
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
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 - KEYLN1 - Continuation of the routine to get a character from the user, jumped if the key was a CARRIAGE RETURN, , , or

5217KEYLN1
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
RETurn to the caller.

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

521AKEYLN3
LD A,20H
Let Register A = 20H (ASCII: SPACE).
521C
POP DE
Restore Register Pair DE from the top of the STACK.
521D
JUMP to 5214H to return with the Z FLAG set.

521FH - ADJUST - Get hexadecimal input from the user and store it in Register Pair HL

521FADJUST
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.
5226ADJ0
LD HL,0000H
LET Register Pair HL = 0000H to prepare for some math.
5229
GOSUB to 523EH to get a hex digit's value.
522C
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
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
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
GOSUB to 51F1H to get character from the keyboard and process accordingly.
5238
If the NZ FLAG (Not Zero) is set, JUMP to 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
ADC A,81H
Add 129 to to the rotated Register A.
523D
RET
RETurn to the caller.

523EH - ADJ1 - SUBroutine called from the prior routine to get a hex digit's value

523EADJ1
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
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 A,0E9H
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
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 A,06H
ADD the value 06H to Register A (Results held in Register A).
5246
If the C FLAG (Carry) is set, then we have A-F, so JUMP to 524BH.
5248
ADD A,07H
ADD the value 07H to Register A (Results held in Register A).
524A
RET C
If the C FLAG (Carry) is set then our number is too low, so RETurn to the caller.
524BADJ2
ADD A,0AH
ADD the value 0AH to Register A (Results held in Register A).
524D
OR A
Set FLAGS based on the contents of Register A.
524E
RET
RETurn to the caller.

524FH - OUTLOC - SUBroutine to Display Bytes Held in (HL) In Hexadecimal

524FOUTLOC
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
JUMP to 5258H to convert the byte held in Register A to ASCII and display.

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

5253OUTWRD
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
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.

5258OUTBYT
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
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.
5261HEX1
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 A,90H
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
ADC A,40H
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.
5269VIDEO
JUMP to 0033H.
NOTE: 0033H is the character print routine, to put the character held in Register A at the current cursor position.

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

526COUTBSP
GOSUB to 5258H to convert the byte held in Register A to ASCII and display.
526FOUTSPC
LD A,20H
LET Register A = 20H (ASCII: SPACE.
5271
JUMP to 5269H to display the character held in Register A (i.e., a SPACE).

5273H - OUTCR - Display a CARRIAGE RETURN and continue at 5269H

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

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

5277OUTCLR
LD A,1FH
LET Register A = 1FH (ASCII: CLEAR TO END OF SCREEN.
5279
JUMP to 0033H.
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 - OUT3 - Display the 3 characters pointed to by (HL), (HL+1), and (HL+2), and then RETurn

527COUT3
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
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.
5282DSPR
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
JUMP to 5269H which JUMPs to 0033H in the ROM to display the character held in Register A on the screen and RETurn.

5286H - QUIT - "Q" Option - Quit the Utility

5286QUIT
XOR A
Set Register A to ZERO and clear all Flags.
Original Source Code Comment: SET FOR SIDE 1
5287
LD (4463H),ALD (CSIDE),A
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
JUMP to "DOS READY" via 402DH.
Original Source Code Comment: AND EXIT TO DOS

528DH - CHKNUM - Validate a Decimal Digit and Convert to Binary

528DCHKNUM
SUB 30H
SUBtract the value 30H from Register A, thus converting an ASCII number to Binary.
Original Source Code Comment: MASK OFF ASCII
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.
Original Source Code Comment: WASN'T NUMBER
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.

Original Source Code Comment: GREATER THAN NUMBER?
5292
CCF
Invert the state of the CARRY FLAG so that GREATER than 10 has CARRY FLAG set, to indicate an error.
5293
RET
RETurn to the caller.

5294H - GETHEX - Validate a Hexidecimal digit and Convert to Binary

5294GETHEX
5295
PUSH HL
POP IX
Let IX = HL (i.e., the hexidecimal data).
Original Source Code Comment: MOVE THE POINTER TO IX
5297
LD HL,0000H
LET Register Pair HL = 0000H to prepare for some math.
Original Source Code Comment: CLEAR A 16 BIT ACCUMULATOR
529AGETHE1
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.
Original Source Code Comment: GET A DIGIT
529D
INC IX
Bump the value stored in Register Pair IX by 1 to point to the next character to be checked.
Original Source Code Comment: BUMP TO NEXT CHARACTER
529F
SUB 30H
SUBtract the value 30H from Register A, thus converting an ASCII number to Binary.
Original Source Code Comment: MASK OFF ASCII
52A1
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).
Original Source Code Comment: EXIT IF END OF NUMBER
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.

Original Source Code Comment: ALPHA?
52A5
If the C FLAG (Carry) is set then A < A, so we have bad value, so JUMP to 52A9H.
Original Source Code Comment: NO, IS NUMBER
52A7
SUB 07H
Convert "A"-"F" to 10-15 by SUBtracting the value 07H from Register A.
Original Source Code Comment: CORRECT FOR ALPHAS
52A9GETHE2
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.

Original Source Code Comment: DUMB ANSWER
52AB
If the NC FLAG (No Carry) is set then the value is too large, so JUMP to 52B7H.
Original Source Code Comment: YES, EXIT
52AD
52AE
52AF
52B0
ADD HL,HL
ADD HL,HL
ADD HL,HL
ADD HL,HL
LET HL = HL + 16, shifting the nybble
Original Source Code Comment: OLD DIGIT TIMES 16
52B1
LD E,A
LET Register E = Register A (i.e., the value of the digit).
Original Source Code Comment: NEW DIGIT INTO DE
52B2
LD D,00H
LET Register D = 00H so that Register Pair DE holds the value of the digit.
52B4
ADD HL,DE
ADD the value held in Register Pair DE to Register Pair HL. The results are held in Register Pair HL.
Original Source Code Comment: ADD IT IN
52B5
LOOP to 529AH for the next hex value.
Original Source Code Comment: GO GET ANOTHER DIGIT

52B7H - GETHE3 - Jump point from the prior routine if the value received is less than 0

52B7GETHE3
LD A,L
LET Register A = Register L (i.e., the LSB).
Original Source Code Comment: GET THE LSB
52B8
RET
RETurn to the caller.

52B9H - ENTRY - DEBUG routine entry from DOS Loader

52B9ENTRY
POP AF
Restore Register Pair AF from the top of the STACK.
Original Source Code Comment: GET SYSTEM VECTOR OFF STACK
52BA
JUMP to 4E00H (i.e., the start of this overlay).

52BDH - TRA - Disk File Display/Modify Routine

52BDTRA
LD A,0B0H
LET Register A = 0B0H (ASCII: Block Cursor).
Original Source Code Comment: SET THE CURSOR BACK TO DEFAULT
52BF
LD (4023H),ALD (CURSCR),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,5526HLD HL,TITLE
LET Register Pair HL = 5526H, to point to the message storage area for 1CH + 1FH + "Debug Disk Utility Ver 1.3" + 0DH + 0AH.
Original Source Code Comment: HL => 'DISK UTILITY' MSG
52C5
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H or 0AH is found.
Original Source Code Comment: DISPLAY IT
52C8CONT1
LD HL,5543HLD HL,BPROMT
LET Register Pair HL = 5543H, to point to the message storage area for 0AH + "Filespec: " + 03H
Original Source Code Comment: HL => 'PROMPT'
52CB
GOSUB to 021BH.
NOTE: 021BH will display the character at (HL) until a 03H or 0AH is found.
Original Source Code Comment: DISPLAY IT
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).
Original Source Code Comment: SET FOR 31 CHARACTERS
52D0
LD HL,5555HLD HL,BDCB
LET Register Pair HL = 5555H to point to a memory buffer for the input.
Original Source Code Comment: PLACE TO STORE ANSWER
52D3
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.
Original Source Code Comment: CALL KEYBOARD LINE
52D6
If the C FLAG (Carry) is set, then the BREAK was just so JUMP to 5286H.
Original Source Code Comment: IF 'BREAK', EXIT TO DOS
52D8
LD HL,4300HLD HL,BUFF1
LET Register Pair HL = 4300H, which is DOS Buffer 1.
Original Source Code Comment: HL => BUFFER
52DB
LD DE,5555HLD DE,BDCB
LET Register Pair DE = 5555H, which is the Buffer holding the filename just entered.
Original Source Code Comment: DE => DCB
52DE
LD B,00H
LET Register B = 00H (0000 0000).
Original Source Code Comment: LRL OF 256
52E0
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.
Original Source Code Comment: OPEN THE FILE
52E3
If the NZ FLAG (Not Zero) is set, then that CALL returned an error, so JUMP to 5405H to handle the diskette-related error.
Original Source Code Comment: EXIT IF ERROR

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

52E6
LD IX,5555HLD IX,BDCB
LET Register Pair IX = 5555H to point to a memory buffer for the filename we just got from the user.
Original Source Code Comment: IX => DCB
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".
Original Source Code Comment: SET FOR LRL OF 256
52EE
LD (IX+09H),00H
Store a 00H in IX+09H (i.e., the LRL of the DCB) to signify a 256 byte file.
Original Source Code Comment: SET LRL FOR 256
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.
Original Source Code Comment: GET THE EOF
52F5
LD (IX+08H),00H
Store the value held in Register 00H into the memory location IX+08H to zero out the file.
Original Source Code Comment: CLEAR ANY EOF
52F9
OR A
Set FLAGS based on the contents of Register A to see if it actually was zero (i.e., an even boundary).
Original Source Code Comment: EOF ON EVEN BOUNDARY?
52FA
If the Z FLAG (Zero) is set then we can skip ahead and we JUMP to 5303H.
Original Source Code Comment: YES, CONTINUE
52FC
LD HL,(5561H)LD HL,(ERN)
Fetch the value stored at memory location 5561H (i.e., the EOF Sector or Last Page of Memory) and put it into Register HL.
Original Source Code Comment: GET THE ERN
52FF
INC HL
Bump the value stored in Register Pair HL (i.e., the EOF Sector) by 1.
Original Source Code Comment: CORRECT FOR THE EOF
5300
LD (5561H),HLLD (ERN),HL
Store the value held in Register HL (i.e., the EOF Sector) into the memory location 5561H.
Original Source Code Comment: SAVE NEW VALUE
5303BREADX
LD DE,5555HLD DE,BDCB
LET Register Pair DE = 5555H to point to a memory buffer for the filename we just got from the user.
Original Source Code Comment: DE => DCB
5306
LD HL,4300HLD HL,BUFF1
LET Register Pair HL = 4300H, which is DOS Buffer 1.
Original Source Code Comment: HL => INTERNAL BUFFER
5309
GOSUB to 4448H which is the POSEOF Vector stored in Overlay 0. This will position to the last record.
Original Source Code Comment: INIT THE POINTERS
530C
GOSUB to 4436H which is the READ Vector stored in Overlay 0. This will read that last record.
Original Source Code Comment: READ IN THE LAST SECTOR
530F
GOSUB to 443FH which is the REWIND Vector stored in Overlay 0. This will rewind the file.
Original Source Code Comment: NOW TO THE FRONT
5312
LD A,23H
LET Register A = 23H to an OPCODE MASK so as to adjust the record number.
Original Source Code Comment: 'INC HL' INSTRUCTION
5314
LD (5366H),ALD (CHGBMP),A
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

5317BREAD
LD HL,4300HLD HL,BUFF1
LET Register Pair HL = 4300H, which is DOS Buffer 1.
Original Source Code Comment: PLACE WHERE DATA WILL BE STORED
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.
Original Source Code Comment: CLEAR IT OUT
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,5555HLD DE,BDCB
LET Register Pair DE = 5555H, to point to the specified file.
Original Source Code Comment: DE => DCB
5327
GOSUB to 4436H which is the READ Vector stored in Overlay 0. This will read the first sector of the specified file.
Original Source Code Comment: READ A RECORD
532A
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.
Original Source Code Comment: EXIT IF ERROR
532D
GOSUB to 4445H which is the BACKSPACE VECTOR (i.e., Back Up To the Previous Record in a File) in Overlay 1.
Original Source Code Comment: BACK UP TO THE RECORD
5330CONT0
XOR A
Set Register A to ZERO and clear all Flags.
5331
LD (5553H),ALD (MOVFLG),A
Store the value held in Register A into the memory location 5553H to indicate that we are reading data from diskette.
5334
LD (545FH),ALD (NODISK),A
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
GOSUB to 533CH to display the page for modification.
533A
JUMP to the command loop at 53AEH.

533CH - CONT2 - Display the Page for Modification

533CCONT2
LD A,0B0H
LET Register A = 0B0H (ASCII: BLOCK cursor).
Original Source Code Comment: SET DEFAULT CURSOR
533E
LD (4023H),ALD (CURSCR),A
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.
Original Source Code Comment: INSURE CURSOR OFF
5343
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,(545FH)LD A,(NODISK)
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
Original Source Code Comment: IS THIS DISK CALLING?
5349
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
534A
If the Z FLAG (Zero) is set, then we are working on a DISK file, so JUMP to 5351H.
Original Source Code Comment: YES, GET BUFFER ADDRESS
534C
LD HL,(4103H)LD HL,(MEM+3)
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.
Original Source Code Comment: NO, IS MEMORY. GET MEMORY ADDRESS
534F
JUMP to 5354H to continue.
Original Source Code Comment: AND DISPLAY RAM LOCATIONS

5351H - GETBUF - Display Data

5351GETBUF
LD HL,4300HLD HL,BUFF1
LET Register Pair HL = 4300H, which is DOS Buffer 1.
Original Source Code Comment: GET THE DISK BUFFER
5354CNT00
LD DE,3C00H
LET Register Pair DE = 3C00H, which is the top of the screen.
5357LOP1
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,(555BH)LD A,(DRV)
Fetch the value stored at memory location 555BH (i.e., the disk drive number) and put it into Register A.
535D
ADD A,30H
ADD the value 30H to Register A (Results held in Register A) to turn the hex drive number into its ASCII equivalent.
535F
GOSUB to 5402H to display a character.
5362
PUSH HL
Save Register HL (i.e., the data address) to the top of the STACK.
Original Source Code Comment: SAVE THE POINTER
5363
LD HL,(555FH)LD HL,(NRN)
Fetch the value stored at memory location 555FH (i..e, the sector number) and put it into Register HL.
Original Source Code Comment: GET THE NRN
5366CHGBMP
NOP
No Operation (Do Nothing) -or- INC HL, depending on what OPCODE was put into this address.
Original Source Code Comment: CORRECT FOR 1'S OFFSET
5367
LD A,H
LET Register A = Register H (i.e., the MSB of HL).
Original Source Code Comment: GET THE MSB
5368
ADD A,30H
ADD the value 30H to Register A (Results held in Register A) to turn the hex drive number into its ASCII equivalent.
536A
GOSUB to 5402H to display a character.
536D
LD A,L
LET Register A = Register L (i.e., the LSB of HL).
Original Source Code Comment: GET THE LSB
536E
GOSUB to 53EDH to display the low byte in ASCII (2 characters).
Original Source Code Comment: OUTPUT AS HEX VALUE
5371
POP HL
Restore Register Pair HL (i.e., the buffer pointer) from the top of the STACK.
Original Source Code Comment: GET THE BUFFER POINTER BACK
5372
LD A,L
LET Register A = Register L (i.e., the line start address).
5373
GOSUB to 53EDH to display the low byte in ASCII (2 characters).
5376
LD A,3AH
LET Register A = 3AH (ASCII: :).
5378
GOSUB to 5402H to display a character.
537BLOOP2
LD A,20H
LET Register A = 20H (ASCII: SPACE).
537D
GOSUB to 5402H to display a character.
5380
GOSUB to 5423H to see if we are at the cursor position.
5383
If the C FLAG (Carry) is set then we are at the proper cursor position, so JUMP to 5389H.
5385LOP2
LD A,(HL)
Fetch the value stored at memory location pointed to by Register Pair HL and put it into Register A.
5386
GOSUB to 53EDH to display the low byte in ASCII (2 characters).
5389LOP3
INC L
Bump the value stored in Register L by 1.
538A
GOSUB to 5423H to see if we are at the cursor position.
538D
If the C FLAG (Carry) is set, JUMP to 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
GOSUB to 53EDH to display the low byte in ASCII (2 characters).
5393LOP4
INC L
Bump the value stored in Register L by 1.
5394
LOOP back to 537BH until Register B is ZERO.
5396
LD A,20H
LET Register A = 20H (ASCII: SPACE).
Original Source Code Comment: OUTPUT A SPACE
5398
GOSUB to 5402H to display a character.
Original Source Code Comment: TO THE SCREEN
539B
POP HL
Restore Register Pair HL (i.e., the data address) from the top of the STACK.
Original Source Code Comment: GET BUFFER POINTER BACK
539C
LD B,10H
LET Register B = 10H (Decimal: 16) to prepare for a loop of 16.
Original Source Code Comment: SET FOR 16 CHARACTERS
539ELOOP3
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.
Original Source Code Comment: GET A BYTE
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
If the NC FLAG (No Carry) is set, then we have a control characters, so JUMP to 53A5H.
53A3DOT
LD A,2EH
LET Register A = 2EH (ASCII: :).
53A5CONT4
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.
Original Source Code Comment: BUMP TO NEXT LOCATION
53A9
RET Z
If the Z FLAG (Zero) is set then we are at the end of the page, so RETurn to the caller.
Original Source Code Comment: EXIT IF ALL OF BUFFER
53AA
LOOP back to 539EH until Register B is ZERO.
Original Source Code Comment: ELSE, LOOP FOR COUNT
53AC
JUMP to 5357H to go to the next line.
Original Source Code Comment: AND DO ANOTHER ROW

53AEH - SCAN - Scan the Keyboard for Display Mode Commands

53AESCAN
DI
Disable Interrupts.
Original Source Code Comment: INTERRUPTS OFF
53AF
GOSUB to 0049H to wait for a key to be pressed.
Original Source Code Comment: GET A KEYBOARD CHAR
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
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
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
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
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
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
If the Z FLAG (Zero) is set then we got a M, so JUMP to 5445H to go to modify mode.
53CC
JUMP to the command loop for DISPLAY MODE commands at 53AEH.

53CEH - UP - Advance to the Next Page of the Display

53CEUP
LD BC,(555FH)LD BC,(NRN)
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.
Original Source Code Comment: BUMP FOR THE NEXT RECORD
53D3
LD HL,(5561H)LD HL,(ERN)
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
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.
Original Source Code Comment: IF EQUAL ALSO
53DBPOS
LD (555FH),BCLD (NRN),BC
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).
Original Source Code Comment: SAVE THE NRN
53DF
JUMP to 5317H to get the new page.
Original Source Code Comment: GO DO THE READ

53E2H - DN - Back up to the Previous Page of the Display

53E2DN
LD BC,(555FH)LD BC,(NRN)
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.
Original Source Code Comment: WE ON 1ST ONE
53E8
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.
53E8
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.
Original Source Code Comment: BACK UP ONE RECORD
53EB
JUMP to 53DBH to save the new page or sector number and continue.

53EDH - HEX - Display a Byte in Two Digit Hexadecimal

53EDHEX
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
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).
53FATEST
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 A,90H
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
ADC A,40H
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.
5402DISP
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
RETurn to the caller.

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

5405BERR
LD B,A
LET Register B = Register A (i.e., the error code returned).
Original Source Code Comment: ERROR INTO B
5406
AND 0FEH
MASK the value of Register A against 0FEH (1111 1110). This has the effect of turning off bit 0.
Original Source Code Comment: MASK ROR TO EOF
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.
Original Source Code Comment: END OF FILE?
540A
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.
Original Source Code Comment: NO, ANOTHER ERROR
540C
LD HL,(5561H)LD HL,(ERN)
Fetch the value stored at memory location 5561H (i.e., the EOF Sector or Last Page of Memory) and put it into Register HL.
Original Source Code Comment: GET THE ERN
540F
LD (555FH),HLLD (NRN),HL
Store the value held in Register HL into the memory location 555FH (i.e., the storage for the sector number).
Original Source Code Comment: SET AS NRN
5412
JUMP to 5330H to continue.
Original Source Code Comment: AND CONTINUE

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

5415BERR1
LD A,B
LET Register A = Register B (i.e., the error code returned).
Original Source Code Comment: GET THE ERROR CODE BACK
5416
PUSH AF
Save Register AF (i.e., the error code returned) to the top of the STACK.
Original Source Code Comment: SAVE IT
5417
GOSUB to 01C9H in the ROM to clear the screen.
Original Source Code Comment: CLEAR THE SCREEN
541A
POP AF
Restore Register Pair AF (i.e., the error code returned) from the top of the STACK.
Original Source Code Comment: GET THE ERROR CODE BACK
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
JUMP to 52C8H to get a new filespec from the user and continue.

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

5423CHECK
LD A,(5553H)LD A,(MOVFLG)
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,(554FH)LD DE,(WHERE)
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
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
RETurn to the caller.

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

5437CHECK1
LD (5551H),DELD (CURSA),DE
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).
Original Source Code Comment: GRAPHICS BLOCK
543D
GOSUB to 5402H to display a character.
Original Source Code Comment: DISPLAY IT
5440
GOSUB to 5402H to display a character.
5443
SCF
Set the CARRY FLAG
5444
RET
RETurn to the caller.

5445H - MOVE - Enter Modify Mode

5445MOVE
LD HL,4300HLD HL,BUFF1
LET Register Pair HL = 4300H, which is DOS Buffer 1.
5448
LD (554FH),HLLD (WHERE),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 (5553H),ALD (MOVFLG),A
Store the value held in Register A into the memory location 5553H to signify that the cursor is active.

544FH - BACK - Display Data for the MODIFY COMMAND

544FBACK
LD HL,(554FH)LD HL,(WHERE)
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
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 - BACK1 - Command Loop for the MODIFY COMMAND

5457BACK1
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.
Original Source Code Comment: CR
545C
If the NZ FLAG (Not Zero) is set, then we did not get an ENTER, so JUMP to 5467H.
Original Source Code Comment: NO
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.
Original Source Code Comment: DISK CALLING?
5461
If the Z FLAG (Zero) is set, the we are doing DISK I/O, so JUMP to 550FH.
Original Source Code Comment: YES, DO THE WRITE
5464
JUMP to 4E51H to re-enter the DEBUG COMMAND LOOP.
Original Source Code Comment: NO, EXIT

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

5467BACK2
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
If the NZ FLAG (Not Zero) is set, then we did NOT get a BREAK, so JUMP to 5475H.
Original Source Code Comment: NO
546B
LD A,(545FH)LD A,(NODISK)
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
Original Source Code Comment: DISK CALLING?
546E
OR A
Since a LD command does not set any FLAGS, Set FLAGS based on the contents of Register A.
546F
If the Z FLAG (Zero) is set, then we were doing DISK I/O, so JUMP to 5330H to get a new file.
Original Source Code Comment: YES, DO IT
5472
JUMP to 4E51H to re-enter the DEBUG COMMAND LOOP.
Original Source Code Comment: NO, EXIT

5475H - BACK3 - Continuation of the Command Loop for the MODIFY COMMAND

5475BACK3
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
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
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
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
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
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
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
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
If A < 1 more than F then the C FLAG (Carry) will be set, so JUMP to 54B8H.
5495
LOOP BACK to to the top of the command loop for the Modify Command at 5457H.

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

5497RIGHT
LD HL,(554FH)LD HL,(WHERE)
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
JUMP to 54B3H to save the new cursor position and continue.

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

549DLEFT
LD HL,(554FH)LD HL,(WHERE)
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
JUMP to 54B3H to save the new cursor position and continue.

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

54A3DWN1
LD HL,(554FH)LD HL,(WHERE)
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
JUMP to 54B3H to save the new cursor position and continue.

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

54ACUP1
LD HL,(554FH)LD HL,(WHERE)
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 A,10H
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).
54B3DONE
LD (554FH),HLLD (WHERE),HL
Store the value held in Register HL into the memory location 554FH (i.e., the CURSOR POSITION).
54B6
JUMP to 544FH to display and get the changes.

54B8H - DIGIT - Modify RAM

54B8DIGIT
LD DE,(5551H)LD DE,(CURSA)
Fetch the value stored at memory location 5551H (i.e., the cursor position) and put it into Register DE.
54BC
GOSUB to 5402H to display a character.
54BF
LD (5551H),DELD (CURSA),DE
Store the value held in Register DE into the memory location 5551H (i.e., the cursor position).
54C3
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.
54D0DIGIT1
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
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
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
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
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.

54E3DIGIT2
LD DE,(5551H)LD DE,(CURSA)
Fetch the value stored at memory location 5551H (i.e., the cursor position) and put it into Register DE.
54E7
GOSUB to 5402H to display the entered character.
54EA
LD (5551H),DELD (CURSA),DE
Store the value held in Register DE into the memory location 5551H (i.e., the cursor position).
54EE
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 A,B
ADD the value held in Register B to Register A (Results held in Register A) to reconstitute the byte.
54F3
LD HL,(554FH)LD HL,(WHERE)
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 (554FH),HLLD (WHERE),HL
Store the value held in Register HL into the memory location 554FH (i.e., the next data address).
54FB
JUMP to 544FH to display and get the changes.

54FEH - GETKEY - Get a Character from the User

54FEGETKEY
PUSH HL
Save Register HL to the top of the STACK.
Original Source Code Comment: SAVE POINTER
54FF
LD HL,(5551H)LD HL,(CURSA)
Fetch the value stored at memory location 5551H (i.e., the cursor position) and put it into Register HL.
Original Source Code Comment: GET THE SAVED CURSOR POSITION
5502
LD (4020H),HLLD (CURSOR),HL
Store the value held in Register HL into the memory location 4020H.
NOTE: 4020H is the storage location for the CURSOR POSITION ON SCREEN.
Original Source Code Comment: MAKE IT THE TRUE CURSOR POSITION
5505
POP HL
Restore Register Pair HL from the top of the STACK.
Original Source Code Comment: GET THE POINTER BACK
5506
LD A,0FH
LET Register A = 0FH to indicate CURSOR ON.
Original Source Code Comment: INSURE CURSOR OFF
5508
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.
Original Source Code Comment: INSURE INTERRUPTS ON
550C
JUMP to 0049H in the ROM to wait for a keyboard response and RETURN.
Original Source Code Comment: GET A KEYBOARD CHAR

550FH - BWRITE - Write a Diskette File Page to Diskette

550FBWRITE
LD DE,5555HLD DE,BDCB
LET Register Pair DE = 5555H (i.e., the FCB).
5512
GOSUB to 4439H in OVERLAY 1 which is the WRITE VECTOR.
5515
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.
Original Source Code Comment: BACK UP TO SAME RECORD
551B
JUMP to 5330H to re-display the current page and continue.

551EH - MAKHEX - 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

551EMAKHEX
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
RETurn to the caller.

5526H - TITLE - Message Storage Area

5526TITLE
DEFW
1CH + 1FH + "Debug Disk Utility Ver 1.3" + 0DH.
5544
DEFW
0AH + "Filespec: " + 03H.
5550
DEFW 4300H
 
5551CURSA
DEFW 3C00H
 
5553MOVFLG
DEFB 00H
 
5555BDCB
DEFW 00H
DEFW 00H
DEFW 00H
 
555BDRV
DEFW 00H
DEFW 00H
 
555FNRN
DEFW 00H
 
5561ERN
DEFW 00H
 
 
END 4E00HEND START