                    0001  ; **********************************************************************
                    0002  ; **  Small Computer Monitor (SCMonitor)        by Stephen C Cousins  **
                    0003  ; **                                                                  **
                    0004  ; **  Developed with Small Computer Workshop (IDE)     www.scc.me.uk  **
                    0005  ; **********************************************************************
                    0006  
                    0007  ; Only one build can be defined so comment out the others
                    0008  ; 1st character (major identifier): letter=official, number=user/custom
                    0009  ; 2nd character (minor identifier): 1-9=official, 0=user/custom
                    0010  ;
                    0011  ;#DEFINE     BUILD 00            ;Complete custom/user build
                    0012  #DEFINE     BUILD 01
                    0013  
                    0014  ;#DEFINE    BUILD L1            ;LiNC80 SBC1 standard 32k ROM
                    0015  
                    0016  ;#DEFINE    BUILD R1            ;RC2014 08K ROM 32K RAM standard
                    0017  ;#DEFINE    BUILD R2            ;RC2014 16K ROM 48K RAM standard
                    0018  ;#DEFINE    BUILD R3            ;RC2014 32K ROM 32/64K RAM paged
                    0019  ;#DEFINE    BUILD R4            ;RC2014 16K ROM 32/64K RAM paged
                    0020  
                    0021  ;#DEFINE    BUILD S1            ;SC_S1  standard ROM (SC101)
                    0022  ;#DEFINE    BUILD S2            ;SC_S2  standard ROM (SC114 etc)
                    0023  ;#DEFINE    BUILD S3            ;SC_S3  standard ROM (SC108 etc)
                    0024  ;#DEFINE    BUILD S4            ;SC_S4  standard ROM (SC111 etc)
                    0025  ;
                    0026  ;#DEFINE    BUILD T1            ;TomsSBC standard ROM
                    0027  
                    0028  ;#DEFINE    BUILD W1            ;SCWorkshop simulator - standard
                    0029  
                    0030  ;#DEFINE    BUILD Z1            ;Z280RC by Bill Shen 
                    0031  ;#DEFINE    BUILD Z2            ;Z80SBCRC by Bill Shen (framework only)
                    0032  
                    0033  
                    0034  ; **********************************************************************
                    0035  ; For each value of BUILD include a suitable Build.asm file
                    0036  
                    0037  #IF         BUILD = "00"
                    0038  #INCLUDE    Hardware\Custom\Build.asm
                    0039  #ENDIF
                    0040  
                    0041  #IF         BUILD = "01"
                    0042  #INCLUDE    Hardware\Custom_cpm\Build.asm
                    0001  ; **********************************************************************
                    0002  ; **  Build Small Computer Monitor Configuration CPM                  **
                    0003  ; **********************************************************************
                    0004  
                    0005  #IFNDEF     BUILD
                    0006  #DEFINE     BUILD CPM
                    0007  #ENDIF
                    0008  
                    0009  #INCLUDE    Monitor\Begin.asm
                    0001  ; **********************************************************************
                    0002  ; **  Small Computer Monitor (SCMonitor)        by Stephen C Cousins  **
                    0003  ; **                                                                  **
                    0004  ; **  Developed with Small Computer Workshop (IDE)     www.scc.me.uk  **
                    0005  ; **********************************************************************
                    0006  
                    0007  ; Configure assembler to generate Z80 code from Zilog mnemonics
                    0008              .PROC Z80           ;Select processor for SCWorkshop
                    0009  
                    0010  
                    0010  
                    0011  #INCLUDE    Hardware\Custom_CPM\Config.asm
                    0001  ; **********************************************************************
                    0002  ; **  Config: 01 = CP/M                               by Armin Diehl  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; Target hardware
0001:               0006  kHardID:    .EQU 01             ;Hardware ID number
                    0007  
                    0008  
                    0009  ; **********************************************************************
                    0010  ; TODO change ID to 11
                    0011  
                    0012  
                    0013  ; Build variations:
                    0014  
                    0015  ; Standard build: 32k ROM 
                    0016  ; Paged ROM board set for 32k page size
                    0017  ; 64k RAM board set to page enabled
                    0018  #IF         BUILD = "01"
1BD7:               0019  kConfMinor:
                    0019  kConfMinor: .EQU '0'            ;Config: 1 to 9 = official, 0 = user
0100:               0020  kCode:      .EQU 0x0100         ;Typically 0x0000 or 0xE000
A000:               0021  kData:      .EQU 0xA000         ;Typically 0xFC00 (to 0xFFFF)
0000:               0022  kROMBanks:  .EQU 0              ;Number of software selectable ROM banks
007F:               0023  kROMTop:    .EQU 0x7F           ;Top of banked ROM (hi byte only)
                    0024  #ENDIF
                    0025  
                    0026  ; Common to all builds for this hardware:
                    0027  
                    0028  ; Configuration identifiers
1BD7:               0029  kConfMajor:
                    0029  kConfMajor: .EQU '1'            ;Config: Letter = official, number = user
                    0030  ;kConfMinor: .EQU '1'           ;Config: 1 to 9 = official, 0 = user
                    0031  
                    0032  ; Code assembled here (ROM or RAM)
                    0033  ; Address assumed to be on a 256 byte boundary
                    0034  ; Space required currently less than 0x1E00 bytes
                    0035  ;kCode:     .EQU 0x0000         ;Typically 0x0000 or 0xE000
                    0036  
                    0037  ; Data space here (must be in RAM)
                    0038  ; Address assumed to be on a 256 byte boundary
                    0039  ; Space required currently less 0x0400 bytes
                    0040  ;kData:     .EQU 0xFC00         ;Typically 0xFC00 (to 0xFFFF)
                    0041  
                    0042  ; Default values written to fixed locations in ROM for easy modification
0001:               0043  kConDef:    .EQU 1              ;Console device 1 is SIOA or 68B50
0096:               0044  kBaud1Def:  .EQU 0x96           ;Console device 1 default baud rate 
0096:               0045  kBaud2Def:  .EQU 0x96           ;Console device 2 default baud rate 
                    0046  
                    0047  ; ROM Filing System
                    0048  ;kROMBanks: .EQU 2              ;Number of software selectable ROM banks
                    0049  ;kROMTop:   .EQU 0x3F           ;Top of banked ROM (hi byte only)
                    0050  
                    0051  ; Timing
0132:               0052  kDelayCnt:  .EQU 306            ;Loop count for 1 ms delay at 7.3728 MHz
                    0053  
                    0054  ; Optional ROM filing system information
                    0055  ; #DEFINE     ROMFS_Monitor_EXE   ;Monitor.EXE
                    0056  
                    0057  ; Optional features (comment out or rename unwanted features)
                    0058  ; Excluding any of these may result in bugs as I don't test every option
                    0059  ; Exporting functions:
                    0060  #DEFINE     IncludeAPI          ;Application Programming Interface (API)
                    0061  ; #DEFINE     IncludeFDOS         ;Very limited CP/M style FDOS support
                    0062  ; Support functions:
                    0063  #DEFINE     IncludeStrings      ;String support (needs utilities)
                    0064  #DEFINE     IncludeUtilities    ;Utility functions (needs strings)
                    0065  ; Monitor functions:
                    0066  #DEFINE     IncludeMonitor      ;onitor essentials
                    0067  #DEFINE     IncludeAssembler    ;Assembler (needs disassembler)
                    0068  ;#DEFINE    IncludeBaud         ;Baud rate setting
                    0069  #DEFINE     IncludeBreakpoint   ;Breakpoint and single stepping
                    0070  #DEFINE     IncludeCommands     ;Command Line Interprester (CLI)
                    0071  #DEFINE     IncludeDisassemble  ;Disassembler 
                    0072  #DEFINE     IncludeHelp         ;Extended help text
                    0073  #DEFINE     IncludeHexLoader    ;Intel hex loader
                    0074  ;#DEFINE     IncludeMiniTerm     ;Mini terminal support
                    0075  ;#DEFINE    IncludeTrace        ;Trace execution
                    0076  ; Extensions:
                    0077  ;#DEFINE     IncludeRomFS        ;ROM filing system
                    0078  ;#DEFINE    IncludeScripting    ;Simple scripting (needs monitor)
                    0079  ;#DEFINE     IncludeSelftest     ;Self test at reset
                    0080  
                    0081  ; DEFINES for any hardware options would go here
                    0082  
                    0083  ; **********************************************************************
                    0084  ; **  End of configuration details                                    **
                    0085  ; **********************************************************************
                    0086  
                    0012  
                    0013  #INCLUDE    Monitor\Core.asm
                    0001  ; **********************************************************************
                    0002  ; **  Include SCM core modules                  by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; Source code version number: Major.Minor.Revision (.Touch)
                    0006  ; This is the version number of the core code and does not include
                    0007  ; the hardware drivers. 
                    0008  ; This version number is only changed when the source code no longer
                    0009  ; produces the same binary code for all existing builds.
                    0010  ; Cosmetic changes to the source and changes only affecting new
                    0011  ; hardware do not require the version number to change, only the
                    0012  ; 'Touch' date (which is an invisible part of the version number).
                    0013  ; Hardware drivers have their own configuration code and revision
                    0014  ; numbers: kConfMajor, kConfMinor and kConfRevis
1BD7:               0015  kVersMajor:
                    0015  kVersMajor: .EQU 1
1BD7:               0016  kVersMinor:
                    0016  kVersMinor: .EQU 0
1BD7:               0017  kVersRevis:
                    0017  kVersRevis: .EQU 0
                    0018  ;VersTouch: .EQU 20190124       ;Last date core code touched
                    0019  
                    0020  
                    0021  
1BD7:               0022  StartOfMonitor:
                    0023              .EQU kCode          ;Start of monitor code
                    0024  
                    0025  ; Essential modules
                    0026  
                    0027  ; Core OS functions
                    0028  #INCLUDE    Monitor\Alpha.asm   ;This must be the first #include
                    0001  ; **********************************************************************
                    0002  ; **  Alpha module                              by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides the following:
                    0006  ;   Defines the memory map (except kCode and kData)
                    0007  ;   Reset code / Cold start command line interpreter
                    0008  ;   Warm start command line interpreter
                    0009  ;
                    0010  ; Public functions provided:
                    0011  ;   ColdStart             Cold start monitor
                    0012  ;   WarmStart             Warm start monitor
                    0013  ;   InitJumps             Initialise jump table with vector list
                    0014  ;   ClaimJump             Claim jump table entry
                    0015  ;   ReadJump              Read jump table entry
                    0016  ;   MemAPI                Call API with parameters in RAM
                    0017  ;   SelConDev             Select console in/out device
                    0018  ;   SelConDevI            Select console input device
                    0019  ;   SelConDevO            Select console output device
                    0020  ;   DevInput              Input from specified console device
                    0021  ;   DevOutput             Output to specified console device
                    0022  ;   Delay                 Delay by sepecified number of millseconds
                    0023  ;   GetConDev             Get current console device numbers
                    0024  ;   GetMemTop             Get top of free memory
                    0025  ;   SetMemTop             Set top of free memory
                    0026  ;   GetVersion            Get version and configuration details
                    0027  ;   OutputMessage         Output specified embedded message
                    0028  ;   SetBaud               Set baud rate for console devices
                    0029  ;   SysReset              System reset
                    0030  
                    0031  
                    0032  ; **********************************************************************
                    0033  ; **  Constants                                                       **
                    0034  ; **********************************************************************
                    0035  
                    0036  ; Memory map (ROM or RAM)
0000:               0037  Reset:      .EQU 0x0000         ;Z80 reset location
                    0038  
                    0039  ; Memory map (RAM)
                    0040  ; 0xFC00 to 0xFCBF  User stack
                    0041  ; 0xFCC0 to 0xFCFF  System stack
                    0042  ; 0xFD00 to 0xFD7F  Line input buffer
                    0043  ; 0xFD80 to 0xFDFF  String buffer
                    0044  ; 0xFE00 to 0xFE5F  Jump table
                    0045  ; 0xFE60 to 0xFEFF  Workspace (currently using to about 0xFEAF)
                    0046  ; 0xFF00 to 0xFFFF  Pass info between apps and memory banks:
                    0047  ; 0xFF00 to 0xFF7F    Transient data area
                    0048  ; 0xFF80 to 0xFFEF    Transient code area
                    0049  ; 0xFFD0 to 0xFFDF    ROMFS file info block 2
                    0050  ; 0xFFE0 to 0xFFEF    ROMFS file info block 1
                    0051  ; 0xFFF0 to 0xFFFF    System variables
A0C0:               0052  kSPUsr:     .EQU kData+0x00C0   ;Top of stack for user program
A100:               0053  kSPSys:     .EQU kData+0x0100   ;Top of stack for system
1BD7:               0054  kInputBuff:
                    0054  kInputBuff: .EQU kData+0x0100   ;Line input buffer start    (to +0x017F)
1BD7:               0055  kInputSize:
                    0055  kInputSize: .EQU 128            ;Size of input buffer
1BD7:               0056  kStrBuffer:
                    0056  kStrBuffer: .EQU kData+0x0180   ;String buffer              (to +0x01FF)
0080:               0057  kStrSize:   .EQU 128            ;Size of string buffer
A200:               0058  kJumpTab:   .EQU kData+0x0200   ;Redirection jump table     (to +0x025F)
                    0059  ;kWorkspace:                    .EQU kData+0x0260;Space for data & variables (to +0x02FF)
                    0060  ; Pass information between apps and memory banks 0xFF00 to 0xFFFF
FF00:               0061  kPassData   .EQU 0xFF00         ;0xFF00 to 0xFF7F Transient data area
FF80:               0062  kPassCode:  .EQU 0xFF80         ;0xFF80 to 0xFFEF Transient code area
FFF0:               0063  kPassInfo:  .EQU 0xFFF0         ;0xFFF0 to 0xFFFF Variable passing area
FFF0:               0064  kPassCtrl:  .EQU kPassInfo+0x00 ;Pass control / paging information
FFF2:               0065  kPassAF:    .EQU kPassInfo+0x02 ;Pass AF to/from API
FFF4:               0066  kPassBC:    .EQU kPassInfo+0x04 ;Pass BC to/from API
FFF6:               0067  kPassDE:    .EQU kPassInfo+0x06 ;Pass DE to/from API
FFF8:               0068  kPassHL:    .EQU kPassInfo+0x08 ;Pass HL --/from API
FFFA:               0069  kPassDevI:  .EQU kPassInfo+0x0A ;Pass current input device
FFFB:               0070  kPassDevO:  .EQU kPassInfo+0x0B ;Pass current output device
                    0071  
                    0072  
                    0073  ; Common constants
0000:               0074  kNull       .EQU 0              ;Null character/byte (0x00)
0005:               0075  kNewLine    .EQU 5              ;New line character (0x05)
1BD7:               0076  kBackspace:
                    0076  kBackspace: .EQU 8              ;Backspace character (0x08)
000A:               0077  kLinefeed:  .EQU 10             ;Line feed character (0x0A)
000D:               0078  kReturn:    .EQU 13             ;Return character (0x0D)
001B:               0079  kEscape:    .EQU 27             ;Escape character (0x1B)
0020:               0080  kSpace:     .EQU 32             ;Space character (0x20)
1BD7:               0081  kApostroph:
                    0081  kApostroph: .EQU 39             ;Apostrophe character (0x27)
002C:               0082  kComma:     .EQU 44             ;Comma character (0x2C)
002E:               0083  kPeriod:    .EQU 46             ;Period character (0x2E)
003A:               0084  kColon:     .EQU 58             ;Colon character (0x3A)
1BD7:               0085  kSemicolon:
                    0085  kSemicolon: .EQU 59             ;Semicolon character (0x3B)
007F:               0086  kDelete:    .EQU 127            ;Delete character (0x7F)
                    0087  
                    0088  ; The jump table contains a number of "JP nn" instructions which are
                    0089  ; used to redirect functions. Each entry in the table takes 3 bytes.
                    0090  ; The jump table is created in RAM on cold start of the monitor.
                    0091  ; Jump table constants - jump number (0 to n)
0000:               0092  kFnNMI:     .EQU 0x00           ;Fn 0x00: non-maskable interrupt handler
0001:               0093  kFnRST08:   .EQU 0x01           ;Fn 0x01: restart 08 handler
0002:               0094  kFnRST10:   .EQU 0x02           ;Fn 0x02: restart 10 handler
0003:               0095  kFnRST18:   .EQU 0x03           ;Fn 0x03: restart 18 handler
0004:               0096  kFnRST20:   .EQU 0x04           ;Fn 0x04: restart 20 handler
0005:               0097  kFnRST28:   .EQU 0x05           ;Fn 0x05: restart 18 breakpoint
0006:               0098  kFnRST30:   .EQU 0x06           ;Fn 0x06: restart 30 API handler
0007:               0099  kFnINT:     .EQU 0x07           ;Fn 0x07: restart 38 interrupt handler
0008:               0100  kFnConIn:   .EQU 0x08           ;Fn 0x08: console input character
0009:               0101  kFnConOut:  .EQU 0x09           ;Fn 0x09: console output character
                    0102  ;FnConISta: .EQU 0x0A           ;Fn 0x0A: console get input status
                    0103  ;FnConOSta: .EQU 0x0B           ;Fn 0x0B: console get output status
000C:               0104  kFnIdle:    .EQU 0x0C           ;Fn 0x0C: Jump to idle handler
000D:               0105  kFnTimer1:  .EQU 0x0D           ;Fn 0x0D: Jump to timer 1 handler
000E:               0106  kFnTimer2:  .EQU 0x0E           ;Fn 0x0E: Jump to timer 2 handler
000F:               0107  kFnTimer3:  .EQU 0x0F           ;Fn 0x0F: Jump to timer 3 handler
                    0108  ;FnDevN:    .EQU 0x10           ;Fn 0x10: device 1 to n input & output
0010:               0109  kFnDev1In:  .EQU 0x10           ;Fn 0x10: device 1 input
1BD7:               0110  kFnDev1Out:
                    0110  kFnDev1Out: .EQU 0x11           ;Fn 0x11: device 1 output
                    0111  ;kFnDev2In: .EQU 0x12           ;Fn 0x12: device 2 input
                    0112  ;FnDev2Out: .EQU 0x13           ;Fn 0x13: device 2 output
0014:               0113  kFnDev3In:  .EQU 0x14           ;Fn 0x14: device 3 input
                    0114  ;FnDev3Out: .EQU 0x15           ;Fn 0x15: device 3 output
                    0115  ;FnDev4In:  .EQU 0x16           ;Fn 0x16: device 4 input
                    0116  ;FnDev4Out: .EQU 0x17           ;Fn 0x17: device 4 output
                    0117  ;FnDev5In:  .EQU 0x18           ;Fn 0x18: device 5 input
                    0118  ;FnDev5Out: .EQU 0x19           ;Fn 0x19: device 5 output
001A:               0119  kFnDev6In:  .EQU 0x1A           ;Fn 0x1A: device 6 input
                    0120  ;FnDev6Out: .EQU 0x1B           ;Fn 0x1B: device 6 output
                    0121  
                    0122  ; Message numbers
0000:               0123  kMsgNull:   .EQU 0              ;Null message
1BD7:               0124  kMsgProdID:
                    0124  kMsgProdID: .EQU 1              ;Product identifier
1BD7:               0125  kMsgDevice:
                    0125  kMsgDevice: .EQU 2              ;="Devices:"
0003:               0126  kMsgAbout:  .EQU 3              ;About SCMonitor inc version
1BD7:               0127  kMsgDevLst:
                    0127  kMsgDevLst: .EQU 4              ;Device list
1BD7:               0128  kMsgLstSys:
                    0128  kMsgLstSys: .EQU 4              ;Last system message number
                    0129  
                    0130  ; Page zero use 
                    0131  ; SCMonitor: page zero can be in RAM or ROM
                    0132  ; CP/M: page zero must be in RAM
                    0133  ; <Address>   <Z80 function>   <Monitor>   <CP/M 2>
                    0134  ; 0000-0002   RST 00 / Reset   Cold start  Warm boot
                    0135  ; 0003-0004                    Warm start  IOBYTE / drive & user
                    0136  ; 0005-0007                    As CP/M     FDOS entry point
                    0137  ; 0008-000B   RST 08           Char out    Not used
                    0138  ; 000C-000F                    CstartOld   Not used
                    0139  ; 0010-0013   RST 10           Char in     Not used
                    0140  ; 0014-0017                    WstartOld   Not used
                    0141  ; 0018-001F   RST 18           In status   Not used
                    0142  ; 0020-0027   RST 20           Not used    Not used
                    0143  ; 0028-002F   RST 28           Breakpoint  Debugging
                    0144  ; 0030-0037   RST 30           API entry   Not used
                    0145  ; 0038-003F   RST 38 / INT     Interrupt   Interrupt mode 1 handler
                    0146  ; 0040-005B                    Options     Not used
                    0147  ; 005C-007F                    As CP/M     Default FCB
                    0148  ; 0066-0068   NMI              or Non-maskable interrupt (NMI) handler
                    0149  ; 0080-00FF                    As CP/M     Default DMA
                    0150  
                    0151  
                    0152  ; **********************************************************************
                    0153  ; **  Initialise memory sections                                      **
                    0154  ; **********************************************************************
                    0155  
                    0156  ; Initialise data section
                    0157              .DATA
                    0158  
                    0159              .ORG  kData
                    0160  
                    0161              .ORG kJumpTab
                    0162  
A200: C3 00 00      0163  JpNMI:      JP   0              ;Fn 0x00: Jump to non-maskable interrupt
A203: C3 00 00      0164  JpRST08:    JP   0              ;Fn 0x01: Jump to restart 08 handler
A206: C3 00 00      0165  JpRST10:    JP   0              ;Fn 0x02: Jump to restart 10 handler
A209: C3 00 00      0166  JpRST18:    JP   0              ;Fn 0x03: Jump to restart 18 handler
A20C: C3 00 00      0167  JpRST20:    JP   0              ;Fn 0x04: Jump to restart 20 handler
A20F: C3 00 00      0168  JpBP:       JP   0              ;Fn 0x05: Jump to restart 28 breakpoint
A212: C3 00 00      0169  JpAPI:      JP   0              ;Fn 0x06: Jump to restart 30 API handler
A215: C3 00 00      0170  JpINT:      JP   0              ;Fn 0x07: Jump to restart 38 interrupt handler
A218: C3 00 00      0171  JpConIn:    JP   0              ;Fn 0x08: Jump to console input character
A21B: C3 00 00      0172  JpConOut:   JP   0              ;Fn 0x09: Jump to console output character
A21E: C3 00 00      0173              JP   0              ;Fn 0x0A: Jump to console get input status
A221: C3 00 00      0174              JP   0              ;Fn 0x0B: Jump to console get output status
A224: C3 00 00      0175  JpIdle:     JP   0              ;Fn 0x0C: Jump to idle handler
A227: C3 00 00      0176  JpTimer1:   JP   0              ;Fn 0x0D: Jump to timer 1 handler
A22A: C3 00 00      0177  JpTimer2:   JP   0              ;Fn 0x0E: Jump to timer 2 handler
A22D: C3 00 00      0178  JpTimer3:   JP   0              ;Fn 0x0F: Jump to timer 3 handler
                    0179              ;Fn 0x10: Start of console device jumps
A230: C3 00 00      0180              JP   0              ;Jump to device 1 input character
A233: C3 00 00      0181              JP   0              ;Jump to device 1 output character
A236: C3 00 00      0182              JP   0              ;Jump to device 2 input character
A239: C3 00 00      0183              JP   0              ;Jump to device 2 output character
A23C: C3 00 00      0184              JP   0              ;Jump to device 3 input character
A23F: C3 00 00      0185              JP   0              ;Jump to device 3 output character
A242: C3 00 00      0186              JP   0              ;Jump to device 4 input character
A245: C3 00 00      0187              JP   0              ;Jump to device 4 output character
A248: C3 00 00      0188              JP   0              ;Jump to device 5 input character
A24B: C3 00 00      0189              JP   0              ;Jump to device 5 output character
A24E: C3 00 00      0190              JP   0              ;Jump to device 6 input character
A251: C3 00 00      0191              JP   0              ;Jump to device 6 output character
                    0192  
A254: FF FF FF FF   0193              .DS   12            ;Workspace starts at kJumpTab + 0x60
A258: FF FF ...     0372  
                    0194  ;           .ORG  kWorkspace
                    0195  
                    0196  ; Initialise code section
                    0197              .CODE
                    0198              .ORG  kCode
                    0199  
                    0200  
                    0201  ; **********************************************************************
                    0202  ; **  Page zero default vectors etc, copied to RAM if appropriate     **
                    0203  ; **********************************************************************
                    0204  
                    0205  ; Reset / power up here
0000:               0206  Page0Strt:
0100: C3 BD 01      0207  ColdStart:  JP   ColdStrt       ;0x0000  CP/M 2 Warm boot
0103: 18 0F         0208  WarmStart:  JR   WStrt          ;0x0003  CP/M 2 IOBYTE / drive & user
0105: C3 1A 02      0209              JP   FDOS           ;0x0005  CP/M 2 FDOS entry point
0108: C3 03 A2      0210              JP   JpRST08        ;0x0008  RST 08 Console character out
010B: 00            0211              .DB  0              ;0x000B
010C: C3 BD 01      0212              JP   ColdStrt       ;0x000C  Cold start (unofficial entry)
010F: 00            0213              .DB  0              ;0x000F
0110: C3 06 A2      0214              JP   JpRST10        ;0x0010  RST 10 Console character in
0113: 00            0215              .DB  0              ;0x0013
0114: C3 11 02      0216  WStrt:      JP   WarmStrt       ;0x0014  Warm start (unofficial entry)
0117: 00            0217              .DB  0              ;0x0017
0118: C3 09 A2      0218              JP   JpRST18        ;0x0018  RST 18 Console input status
011B: 00 00 00 00   0219              .DB  0,0,0,0,0      ;0x001B
011F: 00            0398  
0120: C3 0C A2      0220              JP   JpRST20        ;0x0020  RST 20 Not used
0123: 00 00 00 00   0221              .DB  0,0,0,0,0      ;0x0023
0127: 00            0400  
0128: C3 0F A2      0222              JP   JpBP           ;0x0028  RST 28 Our debugging breakpoint
012B: 00 00 00 00   0223              .DB  0,0,0,0,0      ;0x002B         and CP/M debugging tools
012F: 00            0402  
0130: C3 12 A2      0224              JP   JpAPI          ;0x0030  RST 30 API entry point
0133: 00            0225              .DB  0              ;0x0033         parameters in registers
0134: C3 43 02      0226              JP   MemAPI         ;0x0034  API call with
0137: 00            0227              .DB  0              ;0x0037         parameters in memory 
0138: C3 15 A2      0228              JP   JpINT          ;0x0038  RST 38 Interrupt mode 1 handler
013B: 00 00 00 00   0229              .DB  0,0,0,0,0      ;0x003B
013F: 00            0408  
0140: 01            0230  kaConDev:   .DB  kConDef        ;0x0040  Default console device (1 to 6)
0141:               0231  kaBaud1Def:
0141: 96            0231  kaBaud1Def: .DB  kBaud1Def      ;0x0041  Default device 1 baud rate
0142:               0232  kaBaud2Def:
0142: 96            0232  kaBaud2Def: .DB  kBaud2Def      ;0x0042  Default device 2 baud rate
0143: 00            0233              .DB  0              ;0x0043  Not used
0144: 00 00 00 00   0234              .DW  0,0            ;0x0044  Not used
0148: 00 00 00 00   0235              .DW  0,0,0,0        ;0x0048  Not used
014C: 00 00 00 00   0414  
0150: 00 00 00 00   0236              .DW  0,0,0,0        ;0x0050  Not used
0154: 00 00 00 00   0415  
0158: 00 00 00 00   0237              .DW  0,0            ;0x0058  Not used
015C: 00 00 00 00   0238              .DW  0,0            ;0x005C  CP/M 2 Default FCB
0160: 00 00 00 00   0239              .DW  0,0,0          ;0x0060         from 0x005C to 0x007F
0164: 00 00         0418  
0166: C3 00 A2      0240              JP   JpNMI          ;0x0066  Non-maskable interrupt handler
0000:               0241  Page0End:
                    0242  
                    0243  
                    0244  ; **********************************************************************
                    0245  ; **  Jump table defaults to be copied to RAM                         **
                    0246  ; **********************************************************************
                    0247  
0169: C3 1D 02      0248  JumpStrt:   JP   TrapNMI        ;Fn 0x00: non-maskable interrupt
016C: C3 D1 04      0249              JP   OutputChar     ;Fn 0x01: restart 08 output character
016F: C3 EB 03      0250              JP   InputChar      ;Fn 0x02: restart 10 input character
0172: C3 01 04      0251              JP   InputStatus    ;Fn 0x03: restart 18 get input status
0175: C3 1A 02      0252              JP   TrapCALL       ;Fn 0x04: restart 20 handler
0178: C3 B5 0E      0253              JP   BPHandler      ;Fn 0x05: restart 28 breakpoint handler
017B: C3 C3 05      0254              JP   APIHandler     ;Fn 0x06: restart 30 API handler
017E: C3 1B 02      0255              JP   TrapINT        ;Fn 0x07: restart 38 interrupt handler
0181: C3 1A 02      0256              JP   TrapCALL       ;Fn 0x08: console input character
0184: C3 1A 02      0257              JP   TrapCALL       ;Fn 0x09: console output character
0187: C3 1A 02      0258              JP   TrapCALL       ;Fn 0x0A: console get input status
018A: C3 1A 02      0259              JP   TrapCALL       ;Fn 0x0B: console get output status
018D: C3 1A 02      0260              JP   TrapCALL       ;Fn 0x0C: Jump to idle handler
0190: C3 1A 02      0261              JP   TrapCALL       ;Fn 0x0D: Jump to timer 1 handler
0193: C3 1A 02      0262              JP   TrapCALL       ;Fn 0x0E: Jump to timer 2 handler
0196: C3 1A 02      0263              JP   TrapCALL       ;Fn 0x0F: Jump to timer 3 handler
0199: C3 1F 02      0264              JP   DevNoIn        ;Fn 0x10: Device 1 input character
019C: C3 1F 02      0265              JP   DevNoOut       ;Fn 0x11: Device 1 output character
019F: C3 1F 02      0266              JP   DevNoIn        ;Fn 0x10: Device 2 input character
01A2: C3 1F 02      0267              JP   DevNoOut       ;Fn 0x11: Device 2 output character
01A5: C3 1F 02      0268              JP   DevNoIn        ;Fn 0x10: Device 3 input character
01A8: C3 1F 02      0269              JP   DevNoOut       ;Fn 0x11: Device 3 output character
01AB: C3 1F 02      0270              JP   DevNoIn        ;Fn 0x10: Device 4 input character
01AE: C3 1F 02      0271              JP   DevNoOut       ;Fn 0x11: Device 4 output character
01B1: C3 1F 02      0272              JP   DevNoIn        ;Fn 0x10: Device 5 input character
01B4: C3 1F 02      0273              JP   DevNoOut       ;Fn 0x11: Device 5 output character
01B7: C3 1F 02      0274              JP   DevNoIn        ;Fn 0x10: Device 6 input character
01BA: C3 1F 02      0275              JP   DevNoOut       ;Fn 0x11: Device 6 output character
0000:               0276  JumpEnd:
                    0277  
                    0278  
                    0279  ; **********************************************************************
                    0280  ; **  Reset code                                                      **
                    0281  ; **********************************************************************
                    0282  
                    0283  ; Cold start Command Line Interpreter
01BD: F3            0284  ColdStrt:   DI                  ;Disable interrupts
01BE: 31 00 A1      0285              LD   SP,kSPSys      ;Initialise system stack pointer
                    0286  ; Self test included?
                    0287  #IFDEF      IncludeSelftest
                    0288  ; This indicates status on the default output port (LEDs)
                    0289  ; At the end of a sucessful self test the default output port is cleared 
                    0290  ; to zero, otherwise the default output port indicates the failure
                    0291  #IF         BUILD = "S2"
                    0292  #INCLUDE    Hardware\SC_S2\Selftest.asm
                    0293  #DEFINE     CUSTOM_SELFTEST
                    0294  #ENDIF
                    0295  #IFNDEF     CUSTOM_SELFTEST
                    0296  #INCLUDE    Monitor\Selftest.asm  ;Include self test functions
                    0297  #ENDIF
                    0298  #ENDIF
                    0299  ; Copy vectors etc to page zero in case code is elsewhere
01C1: 11 00 00      0300              LD   DE,0x0000      ;Copy vectors etc to here
01C4: 21 00 01      0301              LD   HL,Page0Strt   ;Copy vectors etc from here
01C7: 01 69 00      0302              LD   BC,Page0End-Page0Strt  ;Number of bytes to copy
01CA: ED B0         0303              LDIR                ;Copy bytes
                    0304  ; Initialise jump table, other than console devices
01CC: 11 00 A2      0305              LD   DE,kJumpTab    ;Copy jump table to here
01CF: 21 69 01      0306              LD   HL,JumpStrt    ;Copy jump table from here
01D2: 01 54 00      0307              LD   BC,JumpEnd-JumpStrt  ;Number of bytes to copy
01D5: ED B0         0308              LDIR                ;Copy bytes
                    0309  ; Initialise top of memory value
01D7: 21 FF 9F      0310              LD   HL,kData-1     ;Top of free memory
01DA: 22 60 A2      0311              LD   (iMemTop),HL   ;Set top of free memory
                    0312  ; Initialise ports module for default I/O ports
                    0313  ; This will turn off all outputs at the default output port (LEDs)
01DD: 3E 00         0314              LD   A,kPrtOut      ;Default output port address
01DF: CD 6B 05      0315              CALL PrtOInit       ;Initialise output port
01E2: 3E 00         0316              LD   A,kPrtIn       ;Default input port address
01E4: CD 99 05      0317              CALL PrtIInit       ;Initialise input port
                    0318  ; Initialise hardware and set up required jump table entries
                    0319  ; This may indicate an error at the default output port (LEDs)
01E7: CD 54 1B      0320              CALL Hardware_Initialise
                    0321  ; Initialise default console device to first physical device
01EA: 3A 40 01      0322              LD   A,(kaConDev)   ;Default device number
01ED: CD 79 02      0323              CALL SelConDev      ;Select console device
                    0324  ; Initialise rest of system
01F0: CD B4 03      0325              CALL ConInitialise  ;Initialise the console
                    0326  #IFDEF      IncludeScripting
                    0327              CALL ScrInitialise  ;Initialise script language
                    0328  #ENDIF
                    0329  #IFDEF      IncludeRomFS
                    0330              CALL RomInitialise  ;Initialise ROM filing system
                    0331  #ENDIF
                    0332  ; Output sign-on message
01F3: CD E6 04      0333              CALL OutputNewLine  ;Output new line
01F6: CD E6 04      0334              CALL OutputNewLine  ;Output new line
01F9: 3E 01         0335              LD   A,kMsgProdID   ;="Small Computer Monitor"
01FB: CD E9 02      0336              CALL OutputMessage  ;Output message
01FE: 3E 2D         0337              LD   A,'-'          ;="-"
0200: CD D1 04      0338              CALL OutputChar     ;Output character
0203: 3E 20         0339              LD   A,kSpace       ;=" "
0205: CD D1 04      0340              CALL OutputChar     ;Output character
0208: 11 50 1B      0341              LD   DE,szStartup   ;="<hardware>"
020B: CD EE 04      0342              CALL OutputZString  ;Output message at DE
020E: CD E6 04      0343              CALL OutputNewLine  ;Output new line
                    0344  #IFNDEF     IncludeCommands
                    0345              CALL OutputNewLine  ;Output new line
                    0346              LD   A,kMsgAbout    ;="Small Computer Monitor ..."
                    0347              CALL OutputMessage  ;Output message A
                    0348              CALL OutputNewLine  ;Output new line
                    0349              LD   A,kMsgDevice   ;="Devices:"
                    0350              CALL OutputMessage  ;Output message A
                    0351              LD   A,kMsgDevLst   ;="<device list>"
                    0352              CALL OutputMessage  ;Output message A
                    0353  #ENDIF
                    0354  
                    0355  ; Warm start Command Line Interpreter
0000:               0356  WarmStrt:
0211: 31 00 A1      0357              LD   SP,kSPSys      ;Initialise system stack pointer
                    0358  #IFDEF      IncludeBreakpoint
0214: CD A2 0E      0359              CALL BPInitialise   ;Initialise breakpoint module
                    0360  #ENDIF
                    0361  #IFDEF      IncludeCommands
0217: C3 15 10      0362              JP   CLILoop        ;Command Line Interpreter main loop
                    0363  #ELSE
                    0364  @Halt:      JR   @Halt          ;Halt here if no CLI
                    0365  #ENDIF
                    0366  
                    0367  ; Trap unused entry points
                    0368  #IFNDEF     IncludeAPI
                    0369  API:
                    0370  #ENDIF
                    0371  #IFNDEF     IncludeFDOS
0000:               0372  FDOS:
                    0373  #ENDIF
                    0374  #IFNDEF     IncludeBreakpoint
                    0375  BPHandler:
                    0376  #ENDIF
021A: C9            0377  TrapCALL:   RET                 ;Return from entry point
                    0378  
                    0379  ; Trap unused mode 1 interrupt
021B: ED 4D         0380  TrapINT:    RETI                ;Return from interrupt
                    0381  
                    0382  ; Trap unused non-maskabler interrupt
021D: ED 45         0383  TrapNMI:    RETN                ;Return from interrupt
                    0384  
                    0385  ; Default console device routines
0000:               0386  DevNoIn:
021F: AF            0387  DevNoOut:   XOR   A             ;Z flagged as no input or output
0220: C9            0388              RET                 ;Return have done nothing
                    0389  
                    0390  
                    0391  ; **********************************************************************
                    0392  ; **  Public functions                                                **
                    0393  ; **********************************************************************
                    0394  
                    0395  
                    0396  ; System: Initialise jump table entries
                    0397  ;   On entry: A = First jump table entry to initialise
                    0398  ;             B = Number of entries to be initialised
                    0399  ;             HL = Pointer to list of vectors
                    0400  ;   On exit:  C IX IY I AF' BC' DE' HL' preserved
0221: 5E            0401  InitJumps:  LD   E,(HL)         ;Get lo byte of vector
0222: 23            0402              INC  HL             ;Point to hi byte of vector
0223: 56            0403              LD   D,(HL)         ;Get lo byte of vector
0224: 23            0404              INC  HL             ;Point to next vector
0225: CD 2C 02      0405              CALL ClaimJump      ;Claim jump table entry
0228: 3C            0406              INC  A              ;Increment entry number
0229: 10 F6         0407              DJNZ InitJumps      ;Repeat until done
022B: C9            0408              RET
                    0409  
                    0410  
                    0411  ; System: Claim system jump table entry
                    0412  ;   On entry: A = Entry number (0 to n)
                    0413  ;             DE = Address of function
                    0414  ;   On exit:  No parameters returned
                    0415  ;             AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0416  ; Some system functions, such as console in and console out, are 
                    0417  ; redirected through a jump table. By claiming a jump table entry the
                    0418  ; function can be handled by any required code. This might allow
                    0419  ; swapping output to a different device, such as a printer.
022C: F5            0420  ClaimJump:  PUSH AF
022D: C5            0421              PUSH BC
022E: E5            0422              PUSH HL
022F: 21 00 A2      0423              LD   HL,kJumpTab    ;Start of jump table
0232: 06 00         0424              LD   B,0            ;Calculate offset and store in BC..
0234: 4F            0425              LD   C,A            ;C = 3 times A..
0235: 87            0426              ADD  A              ;x2
0236: 81            0427              ADD  C              ;x3
0237: 4F            0428              LD   C,A
0238: 09            0429              ADD  HL,BC          ;Find location in table...
                    0430  ; Write jump table entry to memory
0239: 36 C3         0431              LD   (HL),0xC3      ;Store jump instruction
023B: 23            0432              INC  HL
023C: 73            0433              LD   (HL),E         ;Store routine address lo byte
023D: 23            0434              INC  HL
023E: 72            0435              LD   (HL),D         ;Store routine address hi byte
023F: E1            0436              POP  HL
0240: C1            0437              POP  BC
0241: F1            0438              POP  AF
0242: C9            0439              RET
                    0440  
                    0441  
                    0442  ; System: API call with parameters passed via memory
                    0443  ;   On entry: Memory locations kPassXX contain register values
                    0444  ;   On exit:  Memory locations kPassXX contain register values
0243: 2A F2 FF      0445  MemAPI:     LD   HL,(kPassAF)   ;Get AF parameter from RAM
0246: E5            0446              PUSH HL             ;Pass AF parameter via stack
0247: F1            0447              POP  AF             ;Get AF parameter from stack
0248: ED 4B F4 FF   0448              LD   BC,(kPassBC)   ;Get BC parameter from RAM
024C: ED 5B F6 FF   0449              LD   DE,(kPassDE)   ;Get DE parameter from RAM
0250: 2A F8 FF      0450              LD   HL,(kPassHL)   ;Get HL parameter from RAM
0253: F7            0451              RST  0x30           ;Call API
0254: F5            0452              PUSH AF             ;Pass AF result via stack
0255: E1            0453              POP  HL             ;Get AF result from stack
0256: 22 F2 FF      0454              LD   (kPassAF),HL   ;Store AF result in RAM
0259: 22 F8 FF      0455              LD   (kPassHL),HL   ;Store HL result in RAM
025C: ED 53 F6 FF   0456              LD   (kPassDE),DE   ;Store DE result in RAM
0260: ED 43 F4 FF   0457              LD   (kPassBC),BC   ;Store BC result in RAM
0264: C9            0458              RET
                    0459  
                    0460  
                    0461  ; System: Read system jump table entry
                    0462  ;   On entry: A = Entry number (0 to n)
                    0463  ;   On exit:  DE = Address of function
                    0464  ;             AF BC HL IX IY I AF' BC' DE' HL' preserved
                    0465  ; Some system functions, such as console in and console out, are 
                    0466  ; redirected through a jump table. By claiming a jump table entry the
                    0467  ; function can be handled by any required code. This might allow
                    0468  ; swapping output to a different device, such as a printer.
0265: F5            0469  ReadJump:   PUSH AF
0266: C5            0470              PUSH BC
0267: E5            0471              PUSH HL
0268: 21 01 A2      0472              LD   HL,kJumpTab+1  ;Start of jump table + 1
026B: 06 00         0473              LD   B,0            ;Calculate offset and store in BC..
026D: 4F            0474              LD   C,A            ;C = 3 times A..
026E: 87            0475              ADD  A              ;x2
026F: 81            0476              ADD  C              ;x3
0270: 4F            0477              LD   C,A
0271: 09            0478              ADD  HL,BC          ;Find location in table...
                    0479  ; Write jump table entry to memory
0272: 5E            0480              LD   E,(HL)         ;Store routine address lo byte
0273: 23            0481              INC  HL
0274: 56            0482              LD   D,(HL)         ;Store routine address hi byte
0275: E1            0483              POP  HL
0276: C1            0484              POP  BC
0277: F1            0485              POP  AF
0278: C9            0486              RET
                    0487  
                    0488  
                    0489  ; System: Select console device
                    0490  ;   On entry: A = New console device number (1 to n)
                    0491  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0492  ; The console device list starts at jump table entry kFnDevN.
                    0493  ; Each device has two entries: input and output
                    0494  ; SelConDev  = Select both input and output device
                    0495  ; SelConDevO = Select output device only
                    0496  ; SelConDevI = Select input device only
0279: CD 8F 02      0497  SelConDev:  CALL SelConDevI     ;Select console input device
                    0498  ;           JP   SelConDevO     ;Select console output device
                    0499  ; Select output device
027C:               0500  SelConDevO:
027C: F5            0500  SelConDevO: PUSH AF
027D: D5            0501              PUSH DE
027E: 32 FB FF      0502              LD   (kPassDevO),A  ;Store output device number
0281: 87            0503              ADD  A,A            ;Double as two entries each
0282: C6 0F         0504              ADD  kFnDev1Out-2   ;Function number for device zero
0284: CD 65 02      0505              CALL ReadJump       ;Read source entry
0287: 3E 09         0506              LD   A,kFnConOut    ;Destination device entry number
0289: CD 2C 02      0507              CALL ClaimJump      ;Write destination entry
028C: D1            0508              POP  DE
028D: F1            0509              POP  AF
028E: C9            0510              RET
                    0511  ; Select input device
028F:               0512  SelConDevI:
028F: F5            0512  SelConDevI: PUSH AF
0290: D5            0513              PUSH DE
0291: 32 FA FF      0514              LD   (kPassDevI),A  ;Store input device number
0294: 87            0515              ADD  A,A            ;Double as two entries each
0295: C6 0E         0516              ADD  kFnDev1In-2    ;Function number for device zero
0297: CD 65 02      0517              CALL ReadJump       ;Read source entry
029A: 3E 08         0518              LD   A,kFnConIn     ;Destination device entry number
029C: CD 2C 02      0519              CALL ClaimJump      ;Write destination entry
029F: D1            0520              POP  DE
02A0: F1            0521              POP  AF
02A1: C9            0522              RET
                    0523  
                    0524  
                    0525  ; System: Input from specified console device
                    0526  ;   On entry: E = Console device number (1 to n)
                    0527  ;   On exit:  A = Character input 9if there is one ready)
                    0528  ;             NZ flagged if character has been input
                    0529  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
02A2: 7B            0530  DevInput:   LD   A,E            ;Get console device number
02A3: 87            0531              ADD  A,A            ;Double as two entries each
02A4: C6 0E         0532              ADD  kFnDev1In-2    ;Function number for device zero
02A6: CD 65 02      0533              CALL ReadJump       ;Read table entry
02A9: EB            0534              EX   DE,HL          ;Get routine address in HL
02AA: E9            0535              JP   (HL)           ;Jump to input routine
                    0536  
                    0537  
                    0538  ; System: Output to specified console device
                    0539  ;   On entry: A = Character to be output
                    0540  ;             E = Console device number (1 to n)
                    0541  ;   On exit:  IX IY I AF' BC' DE' HL' preserved
02AB: F5            0542  DevOutput:  PUSH AF             ;Store character to be output
02AC: 7B            0543              LD   A,E            ;Get console device number
02AD: 87            0544              ADD  A,A            ;Double as two entries each
02AE: C6 0F         0545              ADD  kFnDev1Out-2   ;Function number for device zero
02B0: CD 65 02      0546              CALL ReadJump       ;Read table entry
02B3: EB            0547              EX   DE,HL          ;Get routine address in HL
02B4: F1            0548              POP  AF             ;Restore character to be output
02B5: E9            0549              JP   (HL)           ;Jump to output routine
                    0550  
                    0551  
                    0552  ; System: Delay by specified number of millseconds
                    0553  ;   On entry: DE = Delay time in milliseconds
                    0554  ;   On exit:  BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0555  ; Clock =  1.0000 MHz,  1 ms =  1,000 TCy =  40 * 24 - 36 
                    0556  ; Clock =  4.0000 MHz,  1 ms =  4,000 TCy = 165 * 24 - 36
                    0557  ; Clock =  7.3728 MHz,  1 ms =  7,373 TCy = 306 * 24 - 36
                    0558  ; Clock = 12.0000 MHz,  1 ms = 12,000 TCy = 498 * 24 - 36
                    0559  ; Clock = 20.0000 MHz,  1 ms = 20,000 TCy = 831 * 24 - 36
02B6: C5            0560  Delay:      PUSH BC
02B7: D5            0561              PUSH DE
                    0562  ; 1 ms loop, DE times... (overhead = 36 TCy)
02B8: 01 32 01      0563  @LoopDE:    LD   BC,kDelayCnt   ;[10]  Loop counter
                    0564  ; 26 TCy loop, BC times...
02BB: 0B            0565  @LoopBC:    DEC  BC             ;[6]
02BC: 79            0566              LD   A,C            ;[4]
02BD: B0            0567              OR   B              ;[4]
02BE: C2 BB 02      0568              JP   NZ,@LoopBC     ;[10]
02C1: 1B            0569              DEC  DE             ;[6]
02C2: 7B            0570              LD   A,E            ;[4]
02C3: B2            0571              OR   D              ;[4]
02C4: 20 F2         0572              JR   NZ,@LoopDE     ;[12/7]
02C6: D1            0573              POP  DE
02C7: C1            0574              POP  BC
02C8: C9            0575              RET
                    0576  
                    0577  
                    0578  ; System: Get current console device numbers
                    0579  ;   On entry: No parameters required
                    0580  ;   On exit:  D = Current console output device number
                    0581  ;             E = Current console input device number
                    0582  ;   On exit:  AF BC HL IX IY I AF' BC' DE' HL' preserved
02C9: ED 5B FA FF   0583  GetConDev:  LD   DE,(kPassDevI) ;Get console device numbers
02CD: C9            0584              RET
                    0585  
                    0586  
                    0587  ; System: Get top of free memory
                    0588  ;   On entry: No parameters required
                    0589  ;   On exit:  DE = Top of free memory
                    0590  ;   On exit:  AF BC HL IX IY I AF' BC' DE' HL' preserved
02CE: ED 5B 60 A2   0591  GetMemTop:  LD   DE,(iMemTop)   ;Get top of free memory
02D2: C9            0592              RET
                    0593  
                    0594  
                    0595  ; System: Set top of free memory
                    0596  ;   On entry: DE = Top of free memory
                    0597  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
02D3: ED 53 60 A2   0598  SetMemTop:  LD   (iMemTop),DE   ;Set top of free memory
02D7: C9            0599              RET
                    0600  
                    0601  
                    0602  ; System: Get version details
                    0603  ;   On entry: No parameters required
                    0604  ;   On exit:  D,E and A = Monitor code version
                    0605  ;               D = kVersMajor
                    0606  ;               E = kVersMinor
                    0607  ;               A = kVersRevis(ion)
                    0608  ;             B,C = Configuration ID
                    0609  ;               B = kConfMajor ('R'=RC2014, 'L'=LiNC80, etc)
                    0610  ;               C = kConfMinor (sub-type '1', '2', etc)
                    0611  ;             H,L = Target hardware ID
                    0612  ;               H = kHardID (1=Simulator, 2=,SCDevKt, 3=RC2014, etc)
                    0613  ;               L = Hardware option flags (hardware specific)
                    0614  ;             IX IY I AF' BC' DE' HL' preserved
02D8:               0615  GetVersion:
02D8: 26 01         0616              LD  H,kHardID       ;H = Hardware ID
02DA: 3A A9 A2      0617              LD  A,(iHwFlags)    ;Get hardware option flags
02DD: 6F            0618              LD  L,A             ;L = Hardware option flags
02DE: 06 31         0619              LD  B,kConfMajor    ;B = Major configuration
02E0: 0E 30         0620              LD  C,kConfMinor    ;C = Minor configuration 
02E2: 16 01         0621              LD  D,kVersMajor    ;D = Major version number
02E4: 1E 00         0622              LD  E,kVersMinor    ;E = Minor version number
02E6: 3E 00         0623              LD  A,kVersRevis    ;A = Revision number
02E8: C9            0624              RET
                    0625  
                    0626  
                    0627  ; System: Output message
                    0628  ;  On entry:  A = Message number (0 to n)
                    0629  ;   On exit:  BC DE HL IX IY I AF' BC' DE' HL' preserved
02E9:               0630  OutputMessage:
02E9: B7            0631              OR   A              ;Null message?
02EA: C8            0632              RET  Z              ;Yes, so abort
02EB: D5            0633              PUSH DE             ;Preserve DE
02EC: E5            0634              PUSH HL             ;Preserve HL
                    0635  ; Monitor message?
                    0636  #IFDEF      IncludeMonitor
02ED: CD 0C 09      0637              CALL MonOutputMsg   ;Offer message number to monitor
02F0: B7            0638              OR   A              ;Message still needs handling?
02F1: 28 31         0639              JR   Z,@Exit        ;No, so exit
                    0640  #ENDIF
                    0641  ; Add any other message generating modules here
                    0642  ; ...........
                    0643  ; System message?
02F3: FE 05         0644              CP   kMsgLstSys+1   ;Valid system message number?
02F5: 30 2D         0645              JR   NC,@Exit       ;No, so abort
                    0646  ; About message?
02F7: FE 03         0647              CP   kMsgAbout      ;About message?
02F9: 20 11         0648              JR   NZ,@NotAbout   ;No, so skip
02FB: 11 39 03      0649              LD   DE,szProduct   ;="Small Computer Monitor"
02FE: CD EE 04      0650              CALL OutputZString  ;Output message at DE
0301: 11 64 03      0651              LD   DE,szAbout     ;="<about this configuration>"
0304: CD EE 04      0652              CALL OutputZString  ;Output message at DE
0307: CD 7E 1B      0653              CALL Hardware_Signon  ;Hardware signon message
030A: 18 18         0654              JR   @Exit
0000:               0655  @NotAbout:
                    0656  ; Device list message?
030C: FE 04         0657              CP   kMsgDevLst     ;Device list message?
030E: 20 05         0658              JR   NZ,@NotDevLst  ;No, so skip
                    0659  ;           LD   DE,szDevices   ;="Devices:"
                    0660  ;           CALL OutputZString  ;Output message at DE
0310: CD 90 1B      0661              CALL Hardware_Devices ;Output device list
0313: 18 0F         0662              JR   @Exit
0315:               0663  @NotDevLst:
                    0664  ; Other system message?
0315: 5F            0665              LD   E,A            ;Get message number
0316: 16 00         0666              LD   D,0
0318: 21 AE 03      0667              LD   HL,MsgTabSys   ;Get start of message table
031B: 19            0668              ADD  HL,DE          ;Calculate location in table
031C: 19            0669              ADD  HL,DE
031D: 7E            0670              LD   A,(HL)         ;Get address from table...
031E: 23            0671              INC  HL
031F: 56            0672              LD   D,(HL)
0320: 5F            0673              LD   E,A
0321: CD EE 04      0674              CALL OutputZString  ;Output message as DE
0324: E1            0675  @Exit:      POP  HL             ;Restore HL
0325: D1            0676              POP  DE             ;Restore DE
0326: C9            0677              RET
                    0678  
                    0679  
                    0680  ; System: Set baud rate
                    0681  ;  On entry:  A = Device identifier (0x01 to 0x06, or 0x0A to 0x0B)
                    0682  ;             E = Baud rate code 
                    0683  ;   On exit:  IF successful: (ie. valid device and baud code)
                    0684  ;               A != 0 and NZ flagged
                    0685  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
0327: FE 0A         0686  SetBaud:    CP   0x0A           ;Identifier is a hex letter?
0329: 38 02         0687              JR   C,@GotNum      ;No, so skip
032B: D6 09         0688              SUB  0x09           ;Convert 0x0A/B to 0x01/2
032D: 4F            0689  @GotNum:    LD   C,A            ;Get device identifier (0x01 to 0x06)
032E: 7B            0690              LD   A,E            ;Get baud rate code
                    0691  ; Set baud rate for device C (1 to 6) to baud code A
032F: C3 6D 1B      0692              JP   Hardware_BaudSet ;Failure: A=0 and Z flagged
                    0693  
                    0694  
                    0695  ; System: System reset
                    0696  ;  On entry:  A = Reset type: 
                    0697  ;               0 = Cold start monitor
                    0698  ;               1 = Warm start monitor
                    0699  ;   On exit:  System resets
0332: FE 01         0700  SysReset:   CP   0x01           ;Warm start monitor
0334: CA 03 01      0701              JP   Z,WarmStart    ;Yes, so warm start monitor
0337: C7            0702              RST  0              ;Cold start monitor
                    0703  
                    0704  
                    0705  ; **********************************************************************
                    0706  ; **  Constant data                                                   **
                    0707  ; **********************************************************************
                    0708  
                    0709  ; Message strings (zero terminated)
0338: 00            0710  szNull:     .DB  kNull
0339: 53 6D 61 6C   0711  szProduct:  .DB  "Small Computer Monitor ",kNull
033D: 6C 20 ...     0890  
0351: 44 65 76 69   0712  szDevices:  .DB  "Devices detected:",kNewLine,kNull
0355: 63 65 ...     0891  
0000:               0713  szAbout:
0364: 62 79 20 53   0714              .DB  "by Stephen C Cousins (www.scc.me.uk)",kNewLine
0368: 74 65 ...     0893  
0389: 56 65 72 73   0715              .DB  "Version "
038D: 69 6F 6E 20   0894  
0391: 31 2E         0716              .DB  '0'+kVersMajor,'.'
0393: 30 2E         0717              .DB  '0'+kVersMinor,'.'
0395: 30            0718              .DB  '0'+kVersRevis
0396: 20 63 6F 6E   0719              .DB  " configuration ",kConfMajor,kConfMinor
039A: 66 69 ...     0898  
                    0720  #IFDEF      SHOW_CONFIG_REVISION
                    0721              .DB  '.',kConfRevis
                    0722  #ENDIF
03A7: 20 66 6F 72   0723              .DB  " for ",kNull
03AB: 20 00         0902  
03AD: 00            0724              .DB  kNull
                    0725  
                    0726  ; Message table
03AE: 38 03         0727  MsgTabSys:  .DW  szNull
03B0: 39 03         0728              .DW  szProduct
03B2: 51 03         0729              .DW  szDevices
                    0730  ;           .DW  szAbout        ;Handled in code
                    0731  ;           .DW  szDevList      ;Handled in code 
                    0732  
                    0733  
                    0734  ; **********************************************************************
                    0735  ; **  Private workspace (in RAM)                                      **
                    0736  ; **********************************************************************
                    0737  
                    0738              .DATA
                    0739  
A260: 00 00         0740  iMemTop:    .DW  0              ;Top of free memory address
                    0741  
                    0742  ; **********************************************************************
                    0743  ; **  End of Alpha module                                             **
                    0744  ; **********************************************************************
                    0745  
                    0746  
                    0747  
                    0748  
                    0749  
                    0750  
                    0751  
                    0752  
                    0753  
                    0754  
                    0755  
                    0756  
                    0757  
                    0758  
                    0759  
                    0760  
                    0761  
                    0029  #INCLUDE    Monitor\Console.asm ;Console support
                    0001  ; **********************************************************************
                    0002  ; **  Console support (input and output)        by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module handles console input and output. The console is normally
                    0006  ; a serial terminal or terminal emulation program.
                    0007  ;
                    0008  ; Public functions provided
                    0009  ;   ConInitialise         Initialise console module
                    0010  ;   InputInsert           Insert character to character waiting buffer
                    0011  ;   InputMore             Ask if user wants to output more
                    0012  ;   InputPreview          Await one character but leave it to be input
                    0013  ;   InputChar             Input character from console input device
                    0014  ;   InputBufConvUpper     Convert contents of input buffer to upper case
                    0015  ;   InputLineEdit         Input line where existing line is replaced
                    0016  ;   InputLine             Input line to system line buffer
                    0017  ;   InputLineTo           Input line to specified line buffer
                    0018  ;   InputStatus           Check if input character is available
                    0019  ;   OutputChar            Output character to console output device
                    0020  ;   OutputNewLine         Output new line character(s)
                    0021  ;   OutputZString         Output a zero (null) terminated string
                    0022  
                    0023  
                    0024  ; **********************************************************************
                    0025  ; **  Public functions                                                **
                    0026  ; **********************************************************************
                    0027  
                    0028              .CODE
                    0029  
                    0030  ; Console: Initialise console module
                    0031  ;   On entry: No parameters required
                    0032  ;   On exit:  BC DE HL IX IY I AF' BC' DE' HL' preserved
03B4:               0033  ConInitialise:
03B4: AF            0034              XOR  A
03B5: 32 62 A2      0035              LD   (iConInChar),A
03B8: C9            0036              RET
                    0037  
                    0038  
                    0039  ; **********************************************************************
                    0040  ; **  Input form console / input device, typically a terminal         **
                    0041  ; **********************************************************************
                    0042  
                    0043  
                    0044  ; Console input: Insert character into character waiting buffer
                    0045  ;   On entry: A = ASCII character
                    0046  ;   On exit:  A BC DE HL IX IY I AF' BC' DE' HL' preserved
03B9:               0047  InputInsert:
03B9: 32 62 A2      0048              LD   (iConInChar),A ;Store as character waiting
03BC: C9            0049              RET
                    0050  
                    0051  
                    0052  ; Console input: Ask if user wants to output more
                    0053  ;   On entry: No parameters required
                    0054  ;   On exit:  A = ASCII character
                    0055  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0056  ; No prompt is given, it just waits until character is available. 
                    0057  ; If the character is the request for 'more' character (eg. Return) the 
                    0058  ; routine exits with the character in A and the Z flag set. 
                    0059  ; If the character is Escape then the routine exits with A = 0 and
                    0060  ; NZ flagged.
                    0061  ; Otherwise the character is stored in iConInChar and will be picked up 
                    0062  ; on next call to InputGetWaiting.
03BD: CD 24 A2      0063  InputMore:  CALL JpIdle         ;Process idle events
03C0: CD 18 A2      0064              CALL JpConIn        ;Wait for input character
03C3: 28 F8         0065              JR   Z,InputMore    ;Repeat until we get a character
03C5: FE 0A         0066              CP   kLinefeed      ;More (linefeed) ?
03C7: 28 F4         0067              JR   Z,InputMore    ;Ignore line feed
                    0068  ;           RET  Z              ;Yes, so return with Z flagged
03C9: FE 0D         0069              CP   kReturn        ;More (carriage return) ? 
03CB: C8            0070              RET  Z              ;Yes, so return with Z flagged
03CC: FE 1B         0071              CP   kEscape        ;Escape character ?
03CE: 28 04         0072              JR   Z,@Escape      ;Yes, so skip
03D0: 32 62 A2      0073              LD   (iConInChar),A ;Store as character waiting
03D3: C9            0074              RET                 ;  and return with NZ flagged
03D4: AF            0075  @Escape:    XOR  A              ;Clear A
03D5: FE 01         0076              CP   1              ;Flag NZ as not a request for more
03D7: C9            0077              RET
                    0078  
                    0079  
                    0080  ; Console input: Await one character but leave it waiting to be input
                    0081  ;   On entry: No parameters required
                    0082  ;   On exit:  A = ASCII character
                    0083  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
03D8:               0084  InputPreview:
03D8: 3A 62 A2      0085              LD   A,(iConInChar) ;Read from character waiting buffer
03DB: B7            0086              OR   A              ;Is there a character waiting?
03DC: C0            0087              RET  NZ             ;If character is waiting then return it
03DD: CD 18 A2      0088  @Wait:      CALL JpConIn        ;Wait for input character
03E0: 20 05         0089              JR   NZ,@GotOne     ;Skip if we get a character
03E2: CD 24 A2      0090              CALL JpIdle         ;Process idle events
03E5: 18 F6         0091              JR   @Wait          ;Repeat until we get a character
03E7: 32 62 A2      0092  @GotOne:    LD   (iConInChar),A ;Store as character waiting
03EA: C9            0093              RET
                    0094  
                    0095  
                    0096  ; Console input: Input character from console input device
                    0097  ;   On entry: No parameters required
                    0098  ;   On exit:  A = ASCII character
                    0099  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0100  ; Waits until character is available
0000:               0101  InputChar:
03EB: 3A 62 A2      0102              LD   A,(iConInChar) ;Read from character waiting buffer
03EE: B7            0103              OR   A              ;Is there a character waiting?
03EF: 28 07         0104              JR   Z,@Input       ;No, so go get new character..
                    0105  ; Return character which is waiting to be read
03F1: F5            0106              PUSH AF             ;Preserve character
03F2: AF            0107              XOR  A              ;Flush waiting buffer by
03F3: 32 62 A2      0108              LD   (iConInChar),A ;  storing zero in to
03F6: F1            0109              POP  AF             ;Restore character 
03F7: C9            0110              RET
                    0111  ; Get new character from console input device
03F8: CD 18 A2      0112  @Input:     CALL JpConIn        ;Look for input character
03FB: C0            0113              RET  NZ             ;Exit if we have a character
03FC: CD 24 A2      0114              CALL JpIdle         ;Process idle events
03FF: 18 F7         0115              JR   @Input         ;No character so keep looking
                    0116  
                    0117  
                    0118  ; Console input: Check if input character is available
                    0119  ;   On entry: No parameters required
                    0120  ;   On exit:  NZ flagged if character is available
                    0121  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0122  ; Does not wait for a character to become available
0401:               0123  InputStatus:
0401: 3A 62 A2      0124              LD   A,(iConInChar) ;Read from character waiting buffer
0404: B7            0125              OR   A              ;Is there a character waiting?
0405: C0            0126              RET  NZ             ;If character is waiting return
0406: CD 18 A2      0127              CALL JpConIn        ;Look for input character
0409: C8            0128              RET  Z              ;No character to exit
040A: 32 62 A2      0129              LD   (iConInChar),A ;Store character to read later
040D: C9            0130              RET
                    0131  
                    0132  
                    0133  ; Console input: Convert contents of input buffer to upper case
                    0134  ;   On entry: No parameters required
                    0135  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0136  ; One exception is the character following an apostrophe
040E:               0137  InputBufConvUpper:
040E: F5            0138              PUSH AF
040F: E5            0139              PUSH HL
0410: 2A 63 A2      0140              LD   HL,(iConInBuf) ;Get start of current input buffer
0413: 7E            0141  @Loop:      LD   A,(HL)         ;Get character from input buffer
0414: B7            0142              OR   A              ;Null string?
0415: 28 12         0143              JR   Z,@Done        ;Yes, so we're done here
                    0144  ; Do not convert character immediately following an apostrophe
0417: FE 27         0145              CP   kApostroph     ;Apostrophe?
0419: 20 07         0146              JR   NZ,@NotApos    ;No, so skip
041B: 23            0147              INC  HL             ;Skip apostrophe
041C: 7E            0148              LD   A,(HL)         ;Get character from input buffer
041D: B7            0149              OR   A              ;Null string?
041E: 28 09         0150              JR   Z,@Done        ;Yes, so we're done here
0420: 18 04         0151              JR   @Next          ;Go to next character
0000:               0152  @NotApos:
                    0153  ; Convert this character to upper case
0422: CD 81 07      0154              CALL ConvertCharToUCase
0425: 77            0155              LD   (HL),A         ;Write upper case char to string
0426: 23            0156  @Next:      INC  HL             ;Point ot next character in string
0427: 18 EA         0157              JR   @Loop          ;Loop until end of string
0429: E1            0158  @Done:      POP  HL
042A: F1            0159              POP  AF
042B: C9            0160              RET
                    0161  
                    0162  
                    0163  ; Console input: Input line to system line buffer
                    0164  ;   On entry: No parameters required
                    0165  ;   On exit:  DE = Start location of buffer
                    0166  ;             A = Number of characters in buffer
                    0167  ;             Z flagged if no characters in bufffer
                    0168  ;             BC HL IX IY I AF' BC' DE' HL' preserved
                    0169  ;             Interrupts enabled during this call ???
                    0170  ; The number of characters returned does not include the null terminator.
042C: 11 00 A1      0171  InputLine:  LD   DE,kInputBuff  ;Start of system line buffer
042F: AF            0172              XOR  A
0430: 12            0173              LD   (DE),A         ;Clear input buffer
0431: 3E 7F         0174              LD   A,kInputSize-1 ;Length of system line buffer
0433: C3 45 04      0175              JP   InputLineNow   ;Input line
                    0176  ;           CALL InputLineNow   ;Input line
                    0177  ;           RET
                    0178  
                    0179  
                    0180  ; Console input: Edit line in default string buffer
                    0181  ;   On entry: No parameters required
                    0182  ;   On exit:  DE = Start location of buffer
                    0183  ;             A = Number of characters in buffer
                    0184  ;             Z flagged if no characters in bufffer
                    0185  ;             BC HL IX IY I AF' BC' DE' HL' preserved
                    0186  ;             Interrupts enabled during this call ???
                    0187  ; The number of characters returned does not include the null terminator.
                    0188  ; DE points to a null terminated string to be edited
0436:               0189  InputLineEdit:
0436: 11 00 A1      0190              LD   DE,kInputBuff  ;Start of system line buffer
0439: CD 6B 06      0191              CALL StrCopyToZ     ;Copy current string to input buffer
043C: 3E 7F         0192              LD   A,kInputSize-1 ;Length of system line buffer
043E: C3 45 04      0193              JP   InputLineNow   ;Input line
                    0194  ;           CALL InputLineNow   ;Input line
                    0195  ;           RET
                    0196  
                    0197  
                    0198  ; Console input: Input line to user defined buffer
                    0199  ;   On entry: DE = Start of buffer
                    0200  ;             A = Size of input buffer in bytes
                    0201  ;   On exit:  A = Number of characters in input buffer
                    0202  ;             Z flagged if no characters in bufffer ???
                    0203  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0204  ;             Interrupts enabled during this call ???
                    0205  ; Maximum buffer length 255 bytes.
                    0206  ; The buffer length includes the string termination character (null).
                    0207  ; The number of characters returned does not include the null terminator.
0441:               0208  InputLineTo:
0441: F5            0209              PUSH AF
0442: AF            0210              XOR  A
0443: 12            0211              LD   (DE),A         ;Clear input buffer
0444: F1            0212              POP  AF
                    0213  ;           JP   InputLineNow   ;Input line
                    0214  
                    0215  
                    0216  ; Console input: Input or edit line at specified location 
                    0217  ;   On entry: DE = Start of buffer
                    0218  ;             A = Size of input buffer in bytes
                    0219  ;   On exit:  A = Number of characters in input buffer
                    0220  ;             Z flagged if no characters in bufffer ???
                    0221  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0222  ;             Interrupts enabled during this call ???
                    0223  ; Maximum buffer length 255 bytes.
                    0224  ; The buffer length includes the string termination character (null).
                    0225  ; The number of characters returned does not include the null terminator.
0445:               0226  InputLineNow:
0445: D5            0227              PUSH DE
0446: E5            0228              PUSH HL
0447: ED 53 63 A2   0229              LD (iConInBuf),DE   ;Store start of buffer
044B: 6F            0230              LD   L,A            ;Store end address of buffer lo byte
044C: 2D            0231              DEC  L              ;Allow space for return character
044D: 63            0232              LD   H,E            ;Store start address of buffer lo byte
                    0233              ;XOR  A
                    0234              ;LD   (DE),A        ;Clear input buffer
                    0235  ; Check if we are overtyping an existing string
044E: 1A            0236              LD   A,(DE)         ;Get first character in buffer
044F: B7            0237              OR   A              ;Null (zero)?
0450: 28 12         0238              JR   Z,@Input       ;Yes, so skip
                    0239  ; Output current string in buffer
0452: CD D1 04      0240  @Loop1:     CALL OutputChar     ;Output character
0455: 13            0241              INC  DE             ;Point to next character
0456: 1A            0242              LD   A,(DE)         ;Get character from buffer
0457: B7            0243              OR   A              ;Null (zero)?
0458: 20 F8         0244              JR   NZ,@Loop1      ;No, so go output it
                    0245  ; Backspace to start of string
045A: 3E 08         0246  @Loop2:     LD   A,kBackspace   ;ASCII backspace
045C: CD D1 04      0247              CALL OutputChar     ;Output backspace
045F: 1B            0248              DEC  DE             ;Back one character
0460: 7B            0249              LD   A,E            ;Get start address of buffer lo byte
0461: BC            0250              CP   H              ;Start of buffer?
0462: 20 F6         0251              JR   NZ,@Loop2      ;No, so go backspace again
                    0252  ; Input line to buffer
0464: CD EB 03      0253  @Input:     CALL InputChar      ;Wait for input character
0467: CB 7F         0254              BIT  7,A            ;Reject if bit 7 set
0469: 20 F9         0255              JR   NZ,@Input
046B: FE 1B         0256              CP   kEscape        ;Test if Escape character
046D: 28 38         0257              JR   Z,@Escape
046F: FE 08         0258              CP   kBackspace     ;Test if Delete character
0471: 28 3C         0259              JR   Z,@Backspace
0473: FE 0D         0260              CP   kReturn        ;Test if carriage return
0475: 28 50         0261              JR   Z,@Return
0477: FE 20         0262              CP   kSpace         ;Reject if control char
0479: 38 E9         0263              JR   C,@Input
                    0264  ; Normal character (ASCII 32 to 126), consider edit mode
                    0265  ; If start of line and in edit mode, erase the line
047B: F5            0266              PUSH AF
047C: 7B            0267              LD   A,E            ;Get start address of buffer lo byte
047D: BC            0268              CP   H              ;Start of buffer?
047E: 20 1A         0269              JR   NZ,@EndErase   ;No, so skip
0480: 1A            0270              LD   A,(DE)         ;Get first character in line
0481: B7            0271              OR   A              ;Anything to edit?
0482: 28 16         0272              JR   Z,@EndErase    ;No, so skip
                    0273  ; Erase string being edited
0484: 3E 20         0274  @Loop3:     LD   A,kSpace       ;ASCII space
0486: CD D1 04      0275              CALL OutputChar     ;Erase character from terminal
0489: AF            0276              XOR  A
048A: 12            0277              LD   (DE),A         ;Erase character from buffer
048B: 13            0278              INC  DE             ;Point to next character
048C: 1A            0279              LD   A,(DE)         ;Get character from buffer
048D: B7            0280              OR   A              ;Null (zero)?
048E: 20 F4         0281              JR   NZ,@Loop3      ;No, so go output it
0490: 3E 08         0282  @Loop4:     LD   A,kBackspace   ;ASCII backspace
0492: CD D1 04      0283              CALL OutputChar     ;Output backspace
0495: 1B            0284              DEC  DE             ;Back one character
0496: 7B            0285              LD   A,E            ;Get start address of buffer lo byte
0497: BC            0286              CP   H              ;Start of buffer?
0498: 20 F6         0287              JR   NZ,@Loop4      ;No, so go backspace again
049A: F1            0288  @EndErase:  POP  AF
                    0289  ; Normal character (ASCII 32 to 126), write to buffer
049B: 12            0290              LD   (DE),A         ;Store character in buffer
049C: 7B            0291              LD   A,E            ;Get current address lo byte
049D: BD            0292              CP   L              ;Buffer full?
049E: 28 C4         0293              JR   Z,@Input       ;Yes, so don't increment pointer
04A0: 1A            0294              LD   A,(DE)         ;No, so..
04A1: CD D1 04      0295              CALL OutputChar     ;  echo character just input
04A4: 13            0296              INC  DE             ;  and increment buffer pointer
04A5: 18 BD         0297              JR   @Input
                    0298  ; Escape character
04A7: CD E6 04      0299  @Escape:    CALL OutputNewLine  ;Output new line character(s)
04AA: 3E 1B         0300              LD   A,kEscape
04AC: BF            0301              CP   A              ;Set zero flag but with A = kEscape
04AD: 18 1F         0302              JR   @Exit
                    0303  ; Delete character
04AF:               0304  @Backspace:
04AF: 7B            0304  @Backspace: LD   A,E            ;Get start address of buffer lo byte
04B0: BC            0305              CP   H              ;Start of buffer?
04B1: 28 B1         0306              JR   Z,@Input       ;Yes, so nothing to delete
04B3: 3E 08         0307              LD   A,kBackspace   ;ASCII backspace
04B5: CD D1 04      0308              CALL OutputChar     ;Output backspace
04B8: 3E 20         0309              LD   A,kSpace       ;ASCII space
04BA: CD D1 04      0310              CALL OutputChar     ;Output space
04BD: 3E 08         0311              LD   A,kBackspace   ;ASCII backspace
04BF: CD D1 04      0312              CALL OutputChar     ;Output backspace
04C2: 1B            0313              DEC  DE             ;Decrement buffer pointer
04C3: AF            0314              XOR  A
04C4: 12            0315              LD   (DE),A         ;Mark end of string with null
04C5: 18 9D         0316              JR   @Input
                    0317  ; Carriage return
04C7: AF            0318  @Return:    XOR  A              ;Clear A to a null character (zero)
04C8: 12            0319              LD   (DE),A         ;Store null to terminate string in buffer
04C9: CD E6 04      0320              CALL OutputNewLine  ;Output new line character(s)
04CC: 7B            0321              LD   A,E            ;Calculate number of characters
04CD: 94            0322              SUB  A,H            ;  in input buffer
04CE: E1            0323  @Exit:      POP  HL
04CF: D1            0324              POP  DE
04D0: C9            0325              RET
                    0326  
                    0327  
                    0328  ; **********************************************************************
                    0329  ; **  Output to console / output device, typically a terminal         **
                    0330  ; **********************************************************************
                    0331  
                    0332  
                    0333  ; Console output: Output character to console output device
                    0334  ;   On entry: A = Character to output
                    0335  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0336  ; This is the only place the actual new line codes (eg. CR/LF) are used
04D1:               0337  OutputChar:
04D1: F5            0338              PUSH AF
04D2: FE 05         0339              CP   kNewLine       ;New line character?
04D4: 20 09         0340              JR   NZ,@NotNL      ;No, so skip
04D6: 3E 0D         0341              LD   A,kReturn      ;Yes, so output physical new line
04D8: CD 1B A2      0342  @Wait1:     CALL JpConOut       ;  to console..
04DB: 28 FB         0343              JR   Z,@Wait1
04DD: 3E 0A         0344              LD   A,kLinefeed
0000:               0345  @NotNL:
04DF: CD 1B A2      0346  @Wait2:     CALL JpConOut       ;Output character to console
04E2: 28 FB         0347              JR   Z,@Wait2
04E4: F1            0348  @Exit:      POP  AF
04E5: C9            0349              RET
                    0350  
                    0351  
                    0352  ; Console output: Output new line character(s)
                    0353  ;   On entry: No parameters
                    0354  ;   On exit:  A BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0355  ; This is the only place the actual new line codes (eg. CR/LF) are used
04E6:               0356  OutputNewLine:
04E6: F5            0357              PUSH AF
04E7: 3E 05         0358              LD   A,kNewLine     ;Get new line character
04E9: CD D1 04      0359              CALL OutputChar     ;Output carriage return character
04EC: F1            0360              POP  AF
04ED: C9            0361              RET
                    0362  
                    0363  
                    0364  ; Console output: Output a zero (null) terminated string
                    0365  ;   On entry: DE= Start address of string
                    0366  ;   On exit:  DE= Address after null
                    0367  ;             AF BC HL IX IY I AF' BC' DE' HL' preserved
                    0368  ;             Interrupts enabled during this call
                    0369  ; Supports \n for new line
04EE:               0370  OutputZString:
04EE: F5            0371              PUSH AF
04EF: 1A            0372  @Next:      LD   A,(DE)         ;Get character from string
04F0: 13            0373              INC  DE             ;Point to next character
04F1: B7            0374              OR   A              ;Null terminator?
04F2: 28 05         0375              JR   Z,@Finished    ;Yes, so we've finished
04F4: CD D1 04      0376              CALL OutputChar     ;Output character
04F7: 18 F6         0377              JR   @Next          ;Go process next character
04F9: F1            0378  @Finished:  POP  AF
04FA: C9            0379              RET
                    0380  
                    0381  
                    0382  ; **********************************************************************
                    0383  ; **  Private functions                                                **
                    0384  ; **********************************************************************
                    0385  
                    0386  
                    0387  #IFNDEF     IncludeUtilities
                    0388  ; This function is normal provided by the Utilities module, but if this 
                    0389  ; build does not include Utilities then assemble the function here.
                    0390  ; Utility: Convert character to upper case
                    0391  ;   On entry: A = Character in either case
                    0392  ;   On exit:  A = Character in upper case
                    0393  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0394  ConvertCharToUCase:
                    0395              CP   'a'            ;Character less than 'a'?
                    0396              RET  C              ;Yes, so finished
                    0397              CP   'z'+1          ;Character greater than 'z'?
                    0398              RET  NC             ;Yes, so finished
                    0399              SUB  'a'-'A'        ;Convert case
                    0400              RET
                    0401  #ENDIF
                    0402  
                    0403  
                    0404  ; **********************************************************************
                    0405  ; **  Private workspace (in RAM)                                      **
                    0406  ; **********************************************************************
                    0407  
                    0408              .DATA
                    0409  
A262:               0410  iConInChar:
A262: 00            0410  iConInChar: .DB  0x00           ;Console input character waiting
A263: 00 00         0411  iConInBuf:  .DW  0x0000         ;Console input buffer start
                    0412  
                    0413  
                    0414  ; **********************************************************************
                    0415  ; **  End of Console support module                                   **
                    0416  ; **********************************************************************
                    0417  
                    0418  
                    0419  
                    0420  
                    0421  
                    0030  #INCLUDE    Monitor\Idle.asm    ;Idle events
                    0001  ; **********************************************************************
                    0002  ; **  Idle events                               by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module handles the idle events.
                    0006  ;
                    0007  ; When the processor is not busy it repeatedly calls the idle handler.
                    0008  ; By default this is just a return instruction, but the system can be 
                    0009  ; configured to call IdlePoll instead. See API function 0x13.
                    0010  ;
                    0011  ; IdlePoll tries to emulate a timer interrupt and issues timer events
                    0012  ; at specified multiples 1 ms, 10 ms or 100 ms. Due to the lack of 
                    0013  ; hardware timer as standard in a typical small computer system (such 
                    0014  ; as RC2014) this function does not produce accurately timed events.
                    0015  ; Systems with a hardware timer, such as LiNC80, sync the idle events
                    0016  ; to the timer for better accuracy.
                    0017  ;
                    0018  ; Timer events are issued via the jump table to allow them to be
                    0019  ; directed anywhere required. Events are NOT issued from within an
                    0020  ; interrupt routine, but are simply subroutine calls made from within 
                    0021  ; system functions like Console Input. 
                    0022  ;
                    0023  ; Timer event handlers must preserve all registers except AF and HL,
                    0024  ; which are already preserved on the stack.
                    0025  ;
                    0026  ;
                    0027  ; Public functions provided
                    0028  ;   IdleConfig            Configure idle event handler
                    0029  ;   IdlePoll              Poll idle events
                    0030  ;   IdleTimer1            Set up Timer 1 event in multiples of 1 ms
                    0031  ;   IdleTimer2            Set up Timer 1 event in multiples of 10 ms
                    0032  ;   IdleTimer3            Set up Timer 1 event in multiples of 100 ms
                    0033  
                    0034  
                    0035  ; **********************************************************************
                    0036  ; **  Public functions                                                **
                    0037  ; **********************************************************************
                    0038  
                    0039              .CODE
                    0040  
                    0041  ; Idle: Configure idle events
                    0042  ;   On entry: A = Configuration:
                    0043  ;                 0 = Off (just execute RET instruction)
                    0044  ;                 1 = Software generated timer events
                    0045  ;                 2+ = Future expansion
                    0046  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
04FB:               0047  IdleConfig:
04FB: 11 09 05      0047  IdleConfig: LD   DE,@Return     ;Idle mode 0 routine
04FE: B7            0048              OR   A              ;A=0?
04FF: 28 03         0049              JR   Z,@IdleSet     ;Yes, so skip
0501: 11 0A 05      0050              LD   DE,IdlePoll    ;Idle mode 1 routine
                    0051  ; Set up event handler by writing to jump table
0504: 3E 0C         0052  @IdleSet:   LD   A,kFnIdle      ;Jump table 0x0C = idle handler
0506: C3 2C 02      0053              JP   ClaimJump      ;Write jump table entry A
0509: C9            0054  @Return:    RET                 ;Idle mode zero routine
                    0055  
                    0056  
                    0057  ; Idle: Poll idle events
                    0058  ;   On entry: No parameters required
                    0059  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0060  ; Registers must be preserved by this function
050A: F5            0061  IdlePoll:   PUSH AF
050B: CD 6F 1B      0062              CALL Hardware_PollTimer
050E: 20 02         0063              JR   NZ,@Event1ms   ;Skip if 1ms event to process
0510: F1            0064              POP  AF             ;  otherwise exit now
0511: C9            0065              RET
                    0066  ; 1 ms tick (we arrive here approximately 1000 times each second)
0512: C5            0067  @Event1ms:  PUSH BC             ;Preserve BC
0513: D5            0068              PUSH DE             ;Preserve DE
0514: E5            0069              PUSH HL             ;Preserve HL
0515: 21 67 A2      0070              LD   HL,iIdleT1     ;Point to timer 1
0518: 35            0071              DEC  (HL)           ;Decrement timer 1
0519: 20 07         0072              JR   NZ,@IdleT1end  ;Skip if not zero
051B: 3A 68 A2      0073              LD   A,(iIdleP1)    ;Get period for timer 1
051E: 77            0074              LD   (HL),A         ;Reset timer 1
051F: CD 27 A2      0075              CALL JpTimer1       ;Call n x 1 ms timer event handler
0522:               0076  @IdleT1end:
0522: 21 65 A2      0076  @IdleT1end: LD   HL,iIdleMS     ;Point to millisecond counter
0525: 35            0077              DEC  (HL)           ;Decrement millisecond counter
0526: 20 24         0078              JR   NZ,@IdleExit   ;Not zero so exit
                    0079  ; 10 ms tick (we arrive here approximately 100 times each second)
0528: 36 0A         0080              LD   (HL),10        ;Reset millisecond counter to 10
052A: 21 69 A2      0081              LD   HL,iIdleT2     ;Point to timer 2
052D: 35            0082              DEC  (HL)           ;Decrement timer 2
052E: 20 07         0083              JR   NZ,@IdleT2end  ;Skip if not zero
0530: 3A 6A A2      0084              LD   A,(iIdleP2)    ;Get period for timer 2
0533: 77            0085              LD   (HL),A         ;Reset timer 2
0534: CD 2A A2      0086              CALL JpTimer2       ;Call n x 10 ms timer event handler
0537:               0087  @IdleT2end:
0537: 21 66 A2      0087  @IdleT2end: LD   HL,iIdleCS     ;Point to centisecond counter
053A: 35            0088              DEC  (HL)           ;Decrement centisecond counter
053B: 20 0F         0089              JR   NZ,@IdleExit   ;Not zero so exit
                    0090  ; 100 ms tick (we arrive here approximately 10 times each second)
053D: 36 0A         0091              LD   (HL),10        ;Reset centisecond counter to 10
053F: 21 6B A2      0092              LD   HL,iIdleT3     ;Point to timer 3
0542: 35            0093              DEC  (HL)           ;Decrement timer 3
0543: 20 07         0094              JR   NZ,@IdleExit   ;Skip if not zero
0545: 3A 6C A2      0095              LD   A,(iIdleP3)    ;Get period for timer 3
0548: 77            0096              LD   (HL),A         ;Reset timer 3
0549: CD 2D A2      0097              CALL JpTimer3       ;Call n x 100 ms timer event handler
054C: E1            0098  @IdleExit:  POP  HL             ;Restore HL
054D: D1            0099              POP  DE             ;Restore DE
054E: C1            0100              POP  BC             ;Restore BC
054F: F1            0101              POP  AF
0550: C9            0102              RET
                    0103  
                    0104  
                    0105  ; Idle: Set up timer 1 / 2 / 3
                    0106  ;   On entry: A = Time period in units of 1 ms / 10 ms / 100 ms
                    0107  ;             DE = Address of timer event handler
                    0108  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
0551:               0109  IdleTimer1:
0551: 0E 01         0109  IdleTimer1: LD   C,1            ;Timer 1 (resolution 1 ms) 
0553: 18 06         0110              JR   IdleSetUp
0555:               0111  IdleTimer2:
0555: 0E 02         0111  IdleTimer2: LD   C,2            ;Timer 2 (resolution 10 ms) 
0557: 18 02         0112              JR   IdleSetUp
0559:               0113  IdleTimer3:
0559: 0E 03         0113  IdleTimer3: LD   C,3            ;Timer 3 (resolution 100 ms) 
                    0114  ; Set up timer number C (1 to 3)
055B: 06 00         0115  IdleSetUp:  LD   B,0
055D: 21 65 A2      0116              LD   HL,iIdleT1-2   ;Start of timer and period data
0560: 09            0117              ADD  HL,BC          ;Calculate address of timer data
0561: 09            0118              ADD  HL,BC          ;  which take two bytes each
0562: 77            0119              LD   (HL),A         ;Store timer value
0563: 23            0120              INC  HL             ;Point to period value
0564: 77            0121              LD   (HL),A         ;Store period value
0565: 79            0122              LD   A,C            ;Get timer number
0566: C6 0C         0123              ADD  A,kFnTimer1-1  ;Calculate jump table entry number
0568: C3 2C 02      0124              JP   ClaimJump      ;Write handler address to jump table
                    0125  
                    0126  
                    0127  ; **********************************************************************
                    0128  ; **  Private functions                                               **
                    0129  ; **********************************************************************
                    0130  
                    0131  
                    0132  ; **********************************************************************
                    0133  ; **  Private workspace (in RAM)                                      **
                    0134  ; **********************************************************************
                    0135  
                    0136              .DATA
                    0137  
                    0138  ; Cycle counting variables
A265: 00            0139  iIdleMS:    .DB  0              ;Millisecond counter
A266: 00            0140  iIdleCS:    .DB  0              ;Centisecond counter
                    0141  
                    0142  ; Periods and timers
                    0143  ; Each timer has a period value and a count down timer value
                    0144  ; WARNING: Do not change order as hard coded (above)
A267: 00            0145  iIdleT1:    .DB  0              ;Timer 1 (resolution = 1 ms)
A268: 00            0146  iIdleP1:    .DB  0              ;Period 1 (resolution = 1 ms)
A269: 00            0147  iIdleT2:    .DB  0              ;Timer 2 (resolution = 10 ms)
A26A: 00            0148  iIdleP2:    .DB  0              ;Period 2 (resolution = 10 ms)
A26B: 00            0149  iIdleT3:    .DB  0              ;Timer 3 (resolution = 100 ms)
A26C: 00            0150  iIdleP3:    .DB  0              ;Period 3 (resolution = 100 ms)
                    0151  
                    0152  
                    0153  ; **********************************************************************
                    0154  ; **  End of Idle events module                                       **
                    0155  ; **********************************************************************
                    0156  
                    0031  #INCLUDE    Monitor\Ports.asm   ;Port functions
                    0001  ; **********************************************************************
                    0002  ; **  Port functions                            by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides functions to manipulate I/O ports.
                    0006  ;
                    0007  ; Public functions provided
                    0008  ;   PrtOInit              Initialise output port
                    0009  ;   PrtOWr                Write to output port
                    0010  ;   PrtORd                Read from output port
                    0011  ;   PrtOTst               Test output port bit
                    0012  ;   PrtOSet               Set output port bit
                    0013  ;   PrtOClr               Clear output port bit
                    0014  ;   PrtOInv               Invert output port bit
                    0015  ;   PrtIInit              Initialise input port
                    0016  ;   PrtIRd                Read from input port
                    0017  ;   PrtITst               Test input port bit
                    0018  
                    0019  
                    0020  ; **********************************************************************
                    0021  ; **  Public functions                                                **
                    0022  ; **********************************************************************
                    0023  
                    0024              .CODE
                    0025  
                    0026  ; Ports: Initialise output port
                    0027  ;   On entry: A = Output port address
                    0028  ;   On exit:  A = Output port data byte (which will be zero)
                    0029  ;             DE HL IX IY I AF' BC' DE' HL' preserved
056B: 32 6E A2      0030  PrtOInit:   LD   (iPrtOutA),A   ;Store port address
056E: AF            0031              XOR  A              ;Clear A (data)
056F: 18 1C         0032              JR   PrtOWr         ;Write A to output port
                    0033  
                    0034  ; Ports: Read output port data
                    0035  ;   On entry: no parameters required
                    0036  ;   On exit:  A = Output port data
                    0037  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
0571: 3A 6F A2      0038  PrtORd:     LD   A,(iPrtOutD)   ;Read output port
0574: C9            0039              RET
                    0040  
                    0041  ; Ports: Test output port bit
                    0042  ;   On entry: A = Bit number 0 to 7
                    0043  ;   On exit:  A = 0 and Z flagged if bit low
                    0044  ;             A !=0 and NZ flagged if bit high
                    0045  ;             DE IX IY I AF' BC' DE' HL' preserved
0575: CD AF 05      0046  PrtOTst:    CALL PortMask       ;Get bit mask for bit A
0578: A0            0047              AND  B              ;Test against bit masked in B
0579: C9            0048              RET                 ;Flag NZ if bit set
                    0049  
                    0050  ; Ports: Set output port bit
                    0051  ;   On entry: A = Bit number 0 to 7
                    0052  ;   On exit:  A = Output port data
                    0053  ;             DE IX IY I AF' BC' DE' HL' preserved
057A: CD AF 05      0054  PrtOSet:    CALL PortMask       ;Get bit mask for bit A
057D: B0            0055              OR   B              ;Set bit masked in B
057E: 18 0D         0056              JR   PrtOWr         ;Write to port
                    0057  
                    0058  ; Ports: Clear output port bit
                    0059  ;   On entry: A = Bit number 0 to 7
                    0060  ;   On exit:  A = Output port data
                    0061  ;             DE IX IY I AF' BC' DE' HL' preserved
0580: CD AF 05      0062  PrtOClr:    CALL PortMask       ;Get bit mask for bit A
0583: 4F            0063              LD   C,A            ;Remember output port data
0584: 78            0064              LD   A,B            ;Get bit mask
0585: 2F            0065              CPL                 ;Complement mask (invert bits)
0586: A1            0066              AND  C              ;Invert bit masked in A
0587: 18 04         0067              JR   PrtOWr         ;Write to port
                    0068  
                    0069  ; Ports: Invert output port bit
                    0070  ;   On entry: A = Bit number 0 to 7
                    0071  ;   On exit:  A = Output port data
                    0072  ;             DE IX IY I AF' BC' DE' HL' preserved
0589: CD AF 05      0073  PrtOInv:    CALL PortMask       ;Get bit mask for bit A
058C: A8            0074              XOR  B              ;Invert bit masked in B
                    0075              ;JR   PrtOWr        ;Write to port
                    0076  
                    0077  ; Ports: Write to output port 
                    0078  ;   On entry: A = Output data byte
                    0079  ;   On exit:  A = Output port data
                    0080  ;             DE HL IX IY I AF' BC' DE' HL' preserved
058D: 47            0081  PrtOWr:     LD   B,A            ;Remember port data
058E: 3A 6E A2      0082              LD   A,(iPrtOutA)   ;Get port address 
0591: 4F            0083              LD   C,A            ;Remember port address
0592: 78            0084              LD   A,B            ;Get port data
0593: 32 6F A2      0085              LD   (iPrtOutD),A   ;Store port data
0596: ED 79         0086              OUT  (C),A          ;Write to port
0598: C9            0087              RET
                    0088  
                    0089  
                    0090  ; Ports: Initialise input port
                    0091  ;   On entry: A = Input port address
                    0092  ;   On exit:  A = Input port data
                    0093  ;             DE HL IX IY I AF' BC' DE' HL' preserved
0599: 32 6D A2      0094  PrtIInit:   LD   (iPrtInA),A    ;Store port address
059C: AF            0095              XOR  A              ;Clear A (data)
                    0096              ;JR   PrtIRd        ;Write A to output port
                    0097  
                    0098  ; Ports: Read input port data
                    0099  ;   On entry: no parameters required
                    0100  ;   On exit:  A = Input port data
                    0101  ;             B DE HL IX IY I AF' BC' DE' HL' preserved
059D: 3A 6D A2      0102  PrtIRd:     LD   A,(iPrtInA)    ;Get input port address 
05A0: 4F            0103              LD   C,A            ;Remember port address
05A1: ED 78         0104              IN   A,(C)          ;Read input port data
05A3: C9            0105              RET
                    0106  
                    0107  ; Ports: Test input port bit
                    0108  ;   On entry: A = Bit number 0 to 7
                    0109  ;   On exit:  A = 0 and Z flagged if bit low
                    0110  ;             A !=0 and NZ flagged if bit high
                    0111  ;             DE IX IY I AF' BC' DE' HL' preserved
05A4: CD AF 05      0112  PrtITst:    CALL PortMask       ;Get bit mask for bit A
05A7: 3A 6D A2      0113              LD   A,(iPrtInA)    ;Get input port address 
05AA: 4F            0114              LD   C,A            ;Remember port address
05AB: ED 78         0115              IN   A,(C)          ;Read input port data
05AD: A0            0116              AND  B              ;Test against bit masked in B
05AE: C9            0117              RET                 ;Flag NZ if bit set
                    0118  
                    0119  
                    0120  ; **********************************************************************
                    0121  ; **  Private functions                                               **
                    0122  ; **********************************************************************
                    0123  
                    0124  ; Get bit mask for bit A
                    0125  ;   On entry: A = Output port address
                    0126  ;   On exit:  B = Bit mask
                    0127  ;             A = Current output port value
                    0128  ;             DE IX IY I AF' BC' DE' HL' preserved
05AF: 21 BB 05      0129  PortMask:   LD   HL,@MaskTab    ;Start of bit mask table
05B2: 4F            0130              LD   C,A            ;Get bit number
05B3: 06 00         0131              LD   B,0            ;Clear B
05B5: 09            0132              ADD  HL,BC          ;Calculate location of bit mask in table
05B6: 46            0133              LD   B,(HL)         ;Get bit mask
05B7: 3A 6F A2      0134              LD   A,(iPrtOutD)   ;Get output data
05BA: C9            0135              RET
                    0136  ; Bit mask table: bit 0 mask, bit 1 mask, ...
05BB: 01 02 04 08   0137  @MaskTab:   .DB  1,2,4,8,16,32,64,128
05BF: 10 20 40 80   1657  
                    0138  
                    0139  
                    0140  ; **********************************************************************
                    0141  ; **  Private workspace (in RAM)                                      **
                    0142  ; **********************************************************************
                    0143  
                    0144              .DATA
                    0145  
A26D: 00            0146  iPrtInA:    .DB  0              ;Input port address
A26E: 00            0147  iPrtOutA:   .DB  0              ;Output port address
A26F: 00            0148  iPrtOutD:   .DB  0              ;Output port data
                    0149  
                    0150  
                    0151  ; **********************************************************************
                    0152  ; **  End of Port functions module                                    **
                    0153  ; **********************************************************************
                    0154  
                    0032  
                    0033  ; Optional modules (see #DEFINEs above)
                    0034  
                    0035  ; Exporting functions
                    0036  #IFDEF      IncludeAPI
                    0037  #INCLUDE    Monitor\API.asm     ;Application Programming Interface (API)
                    0001  ; **********************************************************************
                    0002  ; **  Application Programming Interface (API)   by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides a means of external software accessing some of
                    0006  ; the features of the Small Computer Monitor.
                    0007  ;
                    0008  ; API functions are accessed by:
                    0009  ; Loading C register with the function number
                    0010  ; Loading registers as required by the selected function
                    0011  ; Calling address 0x0030 (either with CALL or RST instruction)
                    0012  ;
                    0013  ; Public functions provided:
                    0014  ;   APIHandler            API main entry point
                    0015  
                    0016  
                    0017  ; **********************************************************************
                    0018  ; **  Public functions                                                **
                    0019  ; **********************************************************************
                    0020  
                    0021              .CODE
                    0022  
                    0023  ; API: Main entry point
                    0024  ;   On entry: C = Function number
                    0025  ;             A, DE = Parameters (as specified by function)
                    0026  ;   On exit:  AF,BC,DE,HL = Return values (as specified by function)
                    0027  ;             IX IY I AF' BC' DE' HL' preserved
                    0028  ; This handler modifies: F, B, HL but preserves A, C, DE
                    0029  ; Other registers depend on API function called
05C3:               0030  APIHandler:
05C3: 21 D5 05      0030  APIHandler: LD   HL,APITable    ;Start of function address table
05C6: 47            0031              LD   B,A            ;Preserve A
05C7: 79            0032              LD   A,C            ;Get function number
05C8: FE 2A         0033              CP   kAPILast+1     ;Supported function?
05CA: D0            0034              RET  NC             ;No, so abort
05CB: 78            0035              LD   A,B            ;Restore A
05CC: 06 00         0036              LD   B,0
05CE: 09            0037              ADD  HL,BC          ;Calculate table pointer..
05CF: 09            0038              ADD  HL,BC
05D0: 46            0039              LD   B,(HL)         ;Read function address from table..
05D1: 23            0040              INC  HL
05D2: 66            0041              LD   H,(HL)
05D3: 68            0042              LD   L,B
05D4: E9            0043              JP   (HL)           ;Jump to function address
                    0044  
                    0045  
                    0046  ; API: Function address table
                    0047  ; This table contains a list of addresses, one for each API function. 
                    0048  ; Each is the address of the subroutine for the relevant function.
05D5: 32 03         0049  APITable:   .DW  SysReset       ; 0x00 = System reset
05D7: EB 03         0050              .DW  InputChar      ; 0x01 = Input character
05D9: D1 04         0051              .DW  OutputChar     ; 0x02 = Output character
05DB: 01 04         0052              .DW  InputStatus    ; 0x03 = Input status
05DD: 41 04         0053              .DW  InputLineTo    ; 0x04 = Input line
05DF: 2C 04         0054              .DW  InputLine      ; 0x05 = Input line default
05E1: EE 04         0055              .DW  OutputZString  ; 0x06 = Output line
05E3: E6 04         0056              .DW  OutputNewLine  ; 0x07 = Output new line
05E5: D8 02         0057              .DW  GetVersion     ; 0x08 = Get version details
05E7: 2C 02         0058              .DW  ClaimJump      ; 0x09 = Claim jump table entry
05E9: B6 02         0059              .DW  Delay          ; 0x0A = Delay in milliseconds
05EB: E9 02         0060              .DW  OutputMessage  ; 0x0B = Output system message
05ED: 65 02         0061              .DW  ReadJump       ; 0x0C = Read jump table entry
05EF: 79 02         0062              .DW  SelConDev      ; 0x0D = Select console in/out device
05F1: 8F 02         0063              .DW  SelConDevI     ; 0x0E = Select console input device
05F3: 7C 02         0064              .DW  SelConDevO     ; 0x0F = Select console output device
05F5: A2 02         0065              .DW  DevInput       ; 0x10 = Input from specified device
05F7: AB 02         0066              .DW  DevOutput      ; 0x11 = Output to specifiec device
05F9: 24 A2         0067              .DW  JpIdle         ; 0x12 = Poll idle events
05FB: FB 04         0068              .DW  IdleConfig     ; 0x13 = Configure idle events
05FD: 51 05         0069              .DW  IdleTimer1     ; 0x14 = Timer 1 control
05FF: 55 05         0070              .DW  IdleTimer2     ; 0x15 = Timer 2 control
0601: 59 05         0071              .DW  IdleTimer3     ; 0x16 = Timer 3 control
0603: 6B 05         0072              .DW  PrtOInit       ; 0x17 = Output port initialise
0605: 8D 05         0073              .DW  PrtOWr         ; 0x18 = Write to output port
0607: 71 05         0074              .DW  PrtORd         ; 0x19 = Read from output port
0609: 75 05         0075              .DW  PrtOTst        ; 0x1A = Test output port bit
060B: 7A 05         0076              .DW  PrtOSet        ; 0x1B = Set output port bit
060D: 80 05         0077              .DW  PrtOClr        ; 0x1C = Clear output port bit
060F: 89 05         0078              .DW  PrtOInv        ; 0x1D = Invert output port bit
0611: 99 05         0079              .DW  PrtIInit       ; 0x1E = Input port initialise
0613: 9D 05         0080              .DW  PrtIRd         ; 0x1F = Read from input port
0615: A4 05         0081              .DW  PrtITst        ; 0x20 = Test input port bit
0617: 27 03         0082              .DW  SetBaud        ; 0x21 = Set baud rate
0619: 34 10         0083              .DW  CLIExecute     ; 0x22 = Execute command line
061B: 29 06         0084              .DW  RomGetPtr      ; 0x23 = Get pointer to command line
061D: 80 10         0085              .DW  CLISkipDelim   ; 0x24 = Skip delimiter
061F: 77 10         0086              .DW  CLISkipNonDeli ; 0x25 = Skip non-delimiter
0621: 89 10         0087              .DW  CLIGetHexParam ; 0x26 = Get hex parameter
0623: C9 02         0088              .DW  GetConDev      ; 0x27 = Get console in/out devices
0625: CE 02         0089              .DW  GetMemTop      ; 0x28 = Get top of free memory
0627: D3 02         0090              .DW  SetMemTop      ; 0x29 = Set top of free memory
                    0091  
                    0092  #IFDEF      RAM_BANK_SUPPORT
                    0093              .DW  RdBankedRAM    ; 0x2A = Read banked RAM
                    0094              .DW  WrBankedRAM    ; 0x2B = Write banked RAM
                    0095  kAPILast:   .EQU 0x2B           ;Last API function number
                    0096  #ELSE
0029:               0097  kAPILast:   .EQU 0x29           ;Last API function number
                    0098  #ENDIF
                    0099  
                    0100  
                    0101  ; Dummy entry points for unsupported features
                    0102  #IFNDEF     IncludeRomFS
0000:               0103  RomGetPtr:
                    0104  #ENDIF
0629: C9            0105              RET
                    0106  
                    0107  
                    0108  ; **********************************************************************
                    0109  ; **  End of Application Programming Interface (API) module           **
                    0110  ; **********************************************************************
                    0111  
                    0112  
                    0113  
                    0038  #ENDIF
                    0039  #IFDEF      IncludeFDOS
                    0040  #INCLUDE    Monitor\FDOS.asm    ;Very limited CP/M style FDOS support
                    0041  #ENDIF
                    0042  
                    0043  ; Support functions
                    0044  #IFDEF      IncludeStrings
                    0045  #INCLUDE    Monitor\Strings.asm ;String support
                    0001  ; **********************************************************************
                    0002  ; **  String support                            by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides a group of functions to handle strings. Strings
                    0006  ; are build in buffers using various functions, such as StrWrChar,
                    0007  ; which writes the specified character to the end of the currently 
                    0008  ; selected string. The string can then be 'printed' to the current 
                    0009  ; output device with the StrPrint function.
                    0010  ;
                    0011  ; Ensure StrInitialise or StrInitDefault is called before any other 
                    0012  ; string function as these finctions select and initialise a string 
                    0013  ; buffer.
                    0014  ;
                    0015  ; Strings are stored in buffers where the first byte of the buffer
                    0016  ; contains the string length. A value of zero therefore indicates
                    0017  ; an empty (or null) string. 
                    0018  ;
                    0019  ; Public functions provided
                    0020  ;   StrAppend             Append specified string to current buffer
                    0021  ;   StrAppendZ            Append specified zero terminated string
                    0022  ;   StrClear              Clear the current string buffer
                    0023  ;   StrConvUpper          Convert string to upper case
                    0024  ;   StrCopyToZ            Copy to zero (null) terminated string
                    0025  ;   StrGetLength          Get length of string in current string buffer
                    0026  ;   StrInitDefault        Initialise and select the default buffer
                    0027  ;   StrInitialise         Initialise default or supplied string buffer
                    0028  ;   StrPrint              Print string in current string buffer
                    0029  ;   StrPrintDE            Print string in string buffer at DE
                    0030  ;   StrWrAddress          Write address, colon, space to buffer
                    0031  ;   StrWrAsciiChar        Write ascii character to string buffer
                    0032  ;   StrWrBackspace        Write backspace to string buffer
                    0033  ;   StrWrBinaryByte       Write binary byte to string buffer
                    0034  ;   StrWrBinaryWord       TODO write binary byte
                    0035  ;   StrWrChar             Write character to string buffer
                    0036  ;   StrWrDecByte          TODO write decimal byte
                    0037  ;   StrWrDecWord          TODO write decimal word
                    0038  ;   StrWrHexByte          Write byte to buffer as 2 hex characters
                    0039  ;   StrWrHexNibble        Write nibble to buffer as 1 hex character
                    0040  ;   StrWrHexWord          Write word to buffer as 4 hex characters
                    0041  ;   StrWrNewLine          Write new line to string buffer
                    0042  ;   StrWrPadding          Write padding (spaces) to specified length
                    0043  ;   StrWrSpace            Write space character to string buffer
                    0044  ;   StrWrSpaces           Write specified spaces to string buffer
                    0045  ; Unless otherwise stated these functions have no return values and 
                    0046  ; preserved the registers: AF BC DE HL IX IY I AF' BC' DE' HL'
                    0047  
                    0048  
                    0049  ; **********************************************************************
                    0050  ; **  Public functions                                                **
                    0051  ; **********************************************************************
                    0052  
                    0053              .CODE
                    0054  
                    0055  ; String: Append specified string to current string buffer
                    0056  ;   On entry: DE = Start of string to be appended
                    0057  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
0000:               0058  StrAppend:
062A: F5            0059              PUSH AF
062B: C5            0060              PUSH BC
062C: D5            0061              PUSH DE
062D: 1A            0062              LD   A,(DE)         ;Get length of specified string
062E: B7            0063              OR   A              ;Null string?
062F: 28 08         0064              JR   Z,@Done        ;Yes, so we're done
0631: 47            0065              LD   B,A            ;Store length of string
0632: 13            0066  @Next:      INC  DE             ;Point to next character to append
0633: 1A            0067              LD   A,(DE)         ;Get character from specified string
0634: CD DB 06      0068              CALL StrWrChar      ;Write character to current string
0637: 10 F9         0069              DJNZ @Next          ;Loop back if more character
0639: D1            0070  @Done:      POP  DE
063A: C1            0071              POP  BC
063B: F1            0072              POP  AF
063C: C9            0073              RET
                    0074  
                    0075  
                    0076  ; String: Append specified zero (null) terminated string
                    0077  ;   On entry: DE = Start of string to be appended
                    0078  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0079  ; Appends specified zero (null) terminated string to current string 
                    0080  ; buffer. The string does not have the usual length prefix but 
                    0081  ; instead is terminated with a zero (null).
063D:               0082  StrAppendZ:
063D: F5            0083              PUSH AF
063E: D5            0084              PUSH DE
063F: 1A            0085  @Next:      LD   A,(DE)         ;Get length of specified string
0640: B7            0086              OR   A              ;Null string?
0641: 28 06         0087              JR   Z,@Done        ;Yes, so we're done
0643: CD DB 06      0088              CALL StrWrChar      ;Write character to current string
0646: 13            0089              INC  DE             ;Point to next character
0647: 18 F6         0090              JR   @Next          ;Loop back if more character
0649: D1            0091  @Done:      POP  DE
064A: F1            0092              POP  AF
064B: C9            0093              RET
                    0094  
                    0095  
                    0096  ; String: Clear string in current string buffer
                    0097  ;   On entry: No parameters required
                    0098  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
0000:               0099  StrClear:
064C: E5            0100              PUSH HL
064D: 2A 70 A2      0101              LD   HL,(iStrStart) ;Get start of current string buffer
0650: 36 00         0102              LD   (HL),0         ;Initialise string with length zero
0652: E1            0103              POP  HL
0653: C9            0104              RET
                    0105  
                    0106  
                    0107  ; String: Convert string to upper case
                    0108  ;   On entry: No parameters required
                    0109  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
0654:               0110  StrConvUpper:
0654: F5            0111              PUSH AF
0655: E5            0112              PUSH HL
0656: 2A 70 A2      0113              LD   HL,(iStrStart) ;Get start of current string buffer
0659: 7E            0114              LD   A,(HL)         ;Get length of string
065A: B7            0115              OR   A              ;Null string?
065B: 28 0B         0116              JR   Z,@Done        ;Yes, so we're done here
065D: C5            0117              PUSH BC
065E: 47            0118              LD   B,A            ;Store length of string
065F: 23            0119  @Loop:      INC  HL             ;Point to next character in string
0660: 7E            0120              LD   A,(HL)         ;Get character from string
0661: CD 81 07      0121              CALL ConvertCharToUCase
0664: 77            0122              LD   (HL),A         ;Write upper case char to string
0665: 10 F8         0123              DJNZ @Loop          ;Loop until end of string
0667: C1            0124              POP  BC
0668: E1            0125  @Done:      POP  HL
0669: F1            0126              POP  AF
066A: C9            0127              RET
                    0128  
                    0129  
                    0130  ; String: Copy to zero (null) terminated string
                    0131  ;   On entry: DE = Location to store Z string
                    0132  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
066B:               0133  StrCopyToZ:
066B: F5            0134              PUSH AF
066C: D5            0135              PUSH DE
066D: E5            0136              PUSH HL
066E: 2A 70 A2      0137              LD   HL,(iStrStart) ;Get start of current string buffer
0671: 7E            0138              LD   A,(HL)         ;Get length of string
0672: B7            0139              OR   A              ;Null string?
0673: 28 08         0140              JR   Z,@Done        ;Yes, so we're done here
0675: 23            0141              INC  HL             ;Point to first character in string
0676: C5            0142              PUSH BC
0677: 4F            0143              LD   C,A            ;Store length of string
0678: 06 00         0144              LD   B,0
067A: ED B0         0145              LDIR                ;Copy string from HL to DE
067C: C1            0146              POP  BC
067D: AF            0147  @Done:      XOR  A
067E: 12            0148              LD   (DE),A         ;Terminate string with null
067F: E1            0149              POP  HL
0680: D1            0150              POP  DE
0681: F1            0151              POP  AF
0682: C9            0152              RET
                    0153  
                    0154  
                    0155  ; String: Get length of string in current string buffer
                    0156  ;   On entry: No parameters required
                    0157  ;   On exit:  A = Length in characters
                    0158  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
0683:               0159  StrGetLength:
0683: E5            0160              PUSH HL
0684: 2A 70 A2      0161              LD   HL,(iStrStart) ;Get start of current string buffer
0687: 7E            0162              LD   A,(HL)         ;Get length of string in buffer
0688: E1            0163              POP  HL
0689: C9            0164              RET
                    0165  
                    0166  
                    0167  ; String: Initialise and select default string buffer
                    0168  ;   On entry: No parameters required
                    0169  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
068A:               0170  StrInitDefault:
068A: F5            0171              PUSH AF
068B: AF            0172              XOR  A              ;Select default string buffer (0)
068C: CD 91 06      0173              CALL StrInitialise  ;Select and initialise buffer
068F: F1            0174              POP  AF
0690: C9            0175              RET
                    0176  
                    0177  
                    0178  ; String: Initialise default or supplied string buffer
                    0179  ;   On entry: A = Size of buffer or zero to restore defaults
                    0180  ;             DE = Start address of string buffer
                    0181  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0182  ; Size includes the string's length byte so needs to be one byte
                    0183  ; longer than the largest string it can hold.
0691:               0184  StrInitialise:
0691: F5            0185              PUSH AF
0692: D5            0186              PUSH DE
0693: B7            0187              OR   A              ;Buffer length zero?
0694: 20 05         0188              JR   NZ,@Init       ;No, so go use supplied values
0696: 11 80 A1      0189              LD   DE,kStrBuffer  ;Get start of default buffer
0699: 3E 80         0190              LD   A,kStrSize     ;Get size of default buffer
069B: ED 53 70 A2   0191  @Init:      LD   (iStrStart),DE ;Store start of string buffer
069F: 32 72 A2      0192              LD   (iStrSize),A   ;Store size of string buffer
06A2: AF            0193              XOR  A              ;Prepare for length zero
06A3: 12            0194              LD   (DE),A         ;Initialise string with length zero
06A4: D1            0195              POP  DE
06A5: F1            0196              POP  AF
06A6: C9            0197              RET
                    0198  
                    0199  
                    0200  ; String: Print string in current string buffer
                    0201  ;   On entry: No parameters required
                    0202  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0203  ; The string is printed to the current output device
                    0204  ; Supports \n for new line
0000:               0205  StrPrint:
06A7: D5            0206              PUSH DE
06A8: ED 5B 70 A2   0207              LD   DE,(iStrStart) ;Get start of current string buffer
06AC: CD B1 06      0208              CALL StrPrintDE     ;Print string at DE
06AF: D1            0209  @Done:      POP  DE
06B0: C9            0210              RET
                    0211  
                    0212  
                    0213  ; String: Print string in current string buffer
                    0214  ;   On entry: DE = Address of string
                    0215  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0216  ; The string is printed to the current output device
06B1:               0217  StrPrintDE:
06B1: F5            0218              PUSH AF
06B2: C5            0219              PUSH BC
06B3: D5            0220              PUSH DE
06B4: 1A            0221              LD   A,(DE)         ;Get length of specified string
06B5: B7            0222              OR   A              ;Null string?
06B6: 28 08         0223              JR   Z,@Done        ;Yes, so we're done
06B8: 47            0224              LD   B,A            ;Store length of string
06B9: 13            0225  @Next:      INC  DE             ;Point to next character to append
06BA: 1A            0226              LD   A,(DE)         ;Get character from specified string
06BB: CD D1 04      0227              CALL OutputChar     ;Output character to output device
06BE: 10 F9         0228              DJNZ @Next          ;Loop back if more character
06C0: D1            0229  @Done:      POP  DE
06C1: C1            0230              POP  BC
06C2: F1            0231              POP  AF
06C3: C9            0232              RET
                    0233  
                    0234  
                    0235  ; String: Write address, colon, space to string buffer
                    0236  ;   On entry: DE = Address
                    0237  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0238  ; Example output: "1234: "
06C4:               0239  StrWrAddress:
06C4: F5            0240              PUSH AF
06C5: CD 0F 07      0241              CALL StrWrHexWord   ;Write start address of this line
06C8: 3E 3A         0242              LD   A,':'
06CA: CD DB 06      0243              CALL StrWrChar      ;Write colon
06CD: CD 35 07      0244              CALL StrWrSpace     ;Write space
06D0: F1            0245              POP  AF
06D1: C9            0246              RET
                    0247  
                    0248  
                    0249  ; String: Write ascii character to string buffer
                    0250  ;   On entry: A = ASCII character
                    0251  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0252  ; If the character is not printable then a dot is written instead
06D2:               0253  StrWrAsciiChar:
06D2: F5            0254              PUSH AF
06D3: CD 46 07      0255              CALL ConvertByteToAscii
06D6: CD DB 06      0256              CALL StrWrChar      ;Write character or a dot
06D9: F1            0257              POP  AF
06DA: C9            0258              RET
                    0259  
                    0260  
                    0261  #IFDEF      kIncludeUnusedCode
                    0262  ; String: Write backspace to string buffer
                    0263  ;   On entry: No parameters required
                    0264  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0265  ; Writeing backspace deletes the last character in the buffer
                    0266  StrWrBackspace:
                    0267              PUSH AF
                    0268              PUSH HL
                    0269              LD   HL,(iStrStart) ;Pointer to start of string buffer
                    0270              LD   A,(HL)         ;Get length of string in buffer
                    0271              OR   A              ;Null terminator?
                    0272              JR   Z,@Skip        ;Yes, so skip as null string
                    0273              DEC  HL             ;Decrement string length
                    0274  @Skip:      POP  HL
                    0275              POP  AF
                    0276              RET
                    0277  #ENDIF
                    0278  
                    0279  
                    0280  #IFDEF      kIncludeUnusedCode
                    0281  ; String: Write binary byte
                    0282  ;   On entry: A = Binary byte
                    0283  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0284  StrWrBinaryByte:
                    0285              PUSH AF
                    0286              PUSH BC
                    0287              LD   B,8            ;Set for 8-bits
                    0288              LD   C,A            ;Store binary byte
                    0289  @NextBit:   LD   A,'1'          ;Default to '1'
                    0290              RL   C              ;Rotate data byte
                    0291              JR   C,@One         ; result in Carry
                    0292              LD   A,'0'          ;Select '0'
                    0293  @One:       CALL StrWrChar      ;Output '1' or '0'
                    0294              DJNZ @NextBit       ;Loop until done
                    0295              POP  BC
                    0296              POP  AF
                    0297              RET
                    0298  #ENDIF
                    0299  
                    0300  
                    0301  ; String: Write character
                    0302  ;   On entry: A = Character to write to string buffer
                    0303  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0304  ; The specified character is writted to the string buffer and a null
                    0305  ; terminator added.
0000:               0306  StrWrChar:
06DB: F5            0307              PUSH AF
06DC: D5            0308              PUSH DE
06DD: E5            0309              PUSH HL
06DE: 5F            0310              LD   E,A            ;Store character to write
06DF: 2A 70 A2      0311              LD   HL,(iStrStart) ;Start of current string buffer
06E2: 7E            0312              LD   A,(HL)         ;Get length of string in buffer
                    0313  ; TODO >>>>> Trap strings too long for the buffer
06E3: 34            0314              INC  (HL)           ;Increment string length
06E4: 3C            0315              INC  A              ;Inc to skip length byte
06E5: 85            0316              ADD  A,L            ;Add A to start of buffer...
06E6: 6F            0317              LD   L,A            ;  to get address for next character
06E7: 30 01         0318              JR   NC,@Store
06E9: 24            0319              INC  H
06EA: 73            0320  @Store:     LD   (HL),E         ;Store character in buffer
06EB: E1            0321              POP  HL
06EC: D1            0322              POP  DE
06ED: F1            0323              POP  AF
06EE: C9            0324              RET
                    0325  
                    0326  
                    0327  ; TODO >>>>> WriteDecimalByte
                    0328  
                    0329  
                    0330  ; TODO >>>>> WriteDecimalByteWithZero
                    0331  
                    0332  
                    0333  ; String: Write hex byte to string buffer
                    0334  ;   On entry: A = Hex byte
                    0335  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
06EF:               0336  StrWrHexByte:
06EF: F5            0337              PUSH AF
06F0: D5            0338              PUSH DE
06F1: CD 51 07      0339              CALL ConvertByteToNibbles
06F4: 7A            0340              LD   A,D
06F5: CD FF 06      0341              CALL StrWrHexNibble
06F8: 7B            0342              LD   A,E
06F9: CD FF 06      0343              CALL StrWrHexNibble
06FC: D1            0344              POP  DE
06FD: F1            0345              POP  AF
06FE: C9            0346              RET
                    0347  
                    0348  
                    0349  ; String: Write hex nibble to string buffer
                    0350  ;   On entry: A = Hex nibble
                    0351  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
06FF:               0352  StrWrHexNibble:
06FF: F5            0353              PUSH AF
0700: E6 0F         0354              AND  0x0F           ;Mask off nibble
0702: FE 0A         0355              CP   0x0A           ;Nibble > 10 ?
0704: 38 02         0356              JR   C,@Skip        ;No, so skip
0706: C6 07         0357              ADD  A,7            ;Yes, so add 7
0708: C6 30         0358  @Skip:      ADD  A,0x30         ;Add ASCII '0'
070A: CD DB 06      0359              CALL StrWrChar      ;Write character
070D: F1            0360              POP  AF
070E: C9            0361              RET
                    0362  
                    0363  
                    0364  ; String: Write hex word to string buffer
                    0365  ;   On entry: DE = Hex word
                    0366  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
070F:               0367  StrWrHexWord:
070F: F5            0368              PUSH AF
0710: 7A            0369              LD   A,D            ;Get hi byte
0711: CD EF 06      0370              CALL StrWrHexByte   ;Write as two hex digits
0714: 7B            0371              LD   A,E            ;Get lo byte
0715: CD EF 06      0372              CALL StrWrHexByte   ;Write as two hex digits
0718: F1            0373              POP  AF
0719: C9            0374              RET
                    0375  
                    0376  
                    0377  ; String: Write new line to string buffer
                    0378  ;   On entry: No parameters
                    0379  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
071A:               0380  StrWrNewLine:
071A: F5            0381              PUSH AF
071B: 3E 05         0382              LD   A,kNewLine     ;Get new line character
071D: CD DB 06      0383              CALL StrWrChar      ;Write character to string
0720: F1            0384              POP  AF
0721: C9            0385              RET
                    0386  
                    0387  
                    0388  ; String:  Write padding (spaces) to specified length
                    0389  ;   On entry: A = Required length of string
                    0390  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
0722:               0391  StrWrPadding:
0722: F5            0392              PUSH AF
0723: C5            0393              PUSH BC
0724: E5            0394              PUSH HL
0725: 47            0395              LD   B,A
0726: 2A 70 A2      0396              LD   HL,(iStrStart) ;Get start of current string buffer
0729: 96            0397              SUB  (HL)           ;Compare required length to current
072A: 38 05         0398              JR   C,@End         ;End now if already too long
072C: 28 03         0399              JR   Z,@End         ;End now if already required length
072E: CD 3D 07      0400              CALL StrWrSpaces    ;Write required number of spaces
0731: E1            0401  @End:       POP  HL
0732: C1            0402              POP  BC
0733: F1            0403              POP  AF
0734: C9            0404              RET
                    0405  
                    0406  
                    0407  ; String: Write space character to string buffer
                    0408  ;   On entry: No parameters
                    0409  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
0735:               0410  StrWrSpace:
0735: F5            0411              PUSH AF
0736: 3E 20         0412              LD   A,kSpace       ;Space character
0738: CD DB 06      0413              CALL StrWrChar      ;Write space character
073B: F1            0414              POP  AF
073C: C9            0415              RET
                    0416  
                    0417  
                    0418  ; String: Write spaces to string buffer
                    0419  ;   On entry: A = Number of spaces to write
                    0420  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
073D:               0421  StrWrSpaces:
073D: F5            0422              PUSH AF
073E: CD 35 07      0423  @Loop:      CALL StrWrSpace     ;Print one space character
0741: 3D            0424              DEC  A              ;Written all required spaces?
0742: 20 FA         0425              JR   NZ,@Loop       ;No, so go write another
0744: F1            0426              POP  AF
0745: C9            0427              RET
                    0428  
                    0429  
                    0430  ; **********************************************************************
                    0431  ; **  Private workspace (in RAM)                                      **
                    0432  ; **********************************************************************
                    0433  
                    0434              .DATA
                    0435  
A270: 00 00         0436  iStrStart:  .DW  0x0000         ;Start of current string buffer
A272: 00            0437  iStrSize:   .DB  0x00           ;Size of current string buffer (0 to Len-1)
                    0438  
                    0439  
                    0440  ; **********************************************************************
                    0441  ; **  End of String support module                                    **
                    0442  ; **********************************************************************
                    0443  
                    0046  #ENDIF
                    0047  #IFDEF      IncludeUtilities
                    0048  #INCLUDE    Monitor\Utilities.asm ;Utility functions (needs strings)
                    0001  ; **********************************************************************
                    0002  ; **  Utility functions                         by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides a group of utility functions
                    0006  ;   ConvertBCDToBinary    Convert BCD to binary
                    0007  ;   ConvertBinaryToBCD    Convert binary to BCD
                    0008  ;   ConvertByteToAscii    Convert byte to ASCII character
                    0009  ;   ConvertByteToNibbles  Convert byte to nibbles
                    0010  ;   ConvertCharToLCase    Convert character to lower case
                    0011  ;   ConvertCharToNumber   Convert character to numeric value
                    0012  ;   ConvertCharToUCase    Convert character to upper case
                    0013  ;   ConvertStringToNumber Convert hex or decimal string to number
                    0014  ;   FindStringInList      Find start of string in bit 7 delimited list
                    0015  ;   IsCharHex             Is character hexadecimal (0 to 9, A to F)
                    0016  ;   IsCharNumeric         Is character numeric (0 to 9)
                    0017  ;   SearchStringList      Find number of string in bit 7 delimited list
                    0018  ;   SearchStringListNA    Find number of string in bit 7 delimited list
                    0019  ;   WrHexPrefix           Write hex prefix to current string buffer
                    0020  ;   WrInstruction         Write disassembled instruction to buffer
                    0021  ;   WrMemoryDump          Write memory dump line to string buffer
                    0022  ;   WrRegister1           Write registers line 1 to string buffer
                    0023  ;   WrRegister2           Write registers line 2 to string buffer
                    0024  
                    0025  
                    0026  ; **********************************************************************
                    0027  ; **  Public functions                                                **
                    0028  ; **********************************************************************
                    0029  
                    0030              .CODE
                    0031  
                    0032  #IFDEF      kIncludeUnusedCode
                    0033  ; Utility: Convert BCD to binary
                    0034  ;   On entry: A = BCD byte
                    0035  ;   On exit:  A = Binary byte
                    0036  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0037  ;             Interrupts not enabled
                    0038  ; Method: Determine the value in the top nibble of the supplied BCD
                    0039  ; number, then subtract 6 from the BCD number that many times. 
                    0040  ; So for a BCD number of 45 (hex value 0x45), subtract 4 x 6 from 
                    0041  ; 0x45 = 0x45 - (4 * 6) = 0x45 - 24 = 69 - 24 = 45 = 0x2D
                    0042  ConvertBCDToBinary:
                    0043              PUSH BC
                    0044              LD   C,A            ;Store BCD number
                    0045              SRL  A              ;Shift top nibble to
                    0046              SRL  A              ;  bottom nibble and
                    0047              SRL  A              ;  clear top nibble
                    0048              SRL  A              ;  so 45 BCD =>  4
                    0049              LD   B,A            ;Store shifted value as counter
                    0050              OR   A              ;Set zero flag if result is zero
                    0051              LD   A,C            ;Get original BCD number
                    0052              JR   Z,@ZJB         ;Skip if shifted value is zero
                    0053  @ZJA:       SUB  6              ;Subtract 6 from BCD number
                    0054              DJNZ @ZJA           ;Repeat until counter is zero
                    0055  @ZJB:       POP  BC
                    0056              RET
                    0057  #ENDIF
                    0058  
                    0059  
                    0060  #IFDEF      kIncludeUnusedCode
                    0061  ; Utility: Convert binary to BCD 
                    0062  ;   On entry: A = Binary byte
                    0063  ;   On exit:  A = BCD byte
                    0064  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0065  ;             Interrupts not enabled
                    0066  ; Values > 99 decimal roll over, so 129 is returned as 29
                    0067  ConvertBinaryToBCD:
                    0068              PUSH BC
                    0069              LD   C,0            ;Build result in C
                    0070  @ZAB:       CP   10             ;Remaining value > 9?
                    0071              JR   C,@ZAA         ;No, so finish loop
                    0072              SUB  10             ;Subtract 10 from remainder
                    0073              LD   B,A            ;Store remaining value
                    0074              LD   A,C            ;Get result so far
                    0075              ADD  0x10           ;Add 0x10 (10 in BCD)
                    0076              CP   0xA0           ;Result > 0x90? (90 in BCD)
                    0077              JR   C,@ZAC         ;No, so skip
                    0078              XOR  A              ;Yes, so clear result to 0
                    0079  @ZAC:       LD   C,A            ;Store result so far
                    0080              LD   A,B            ;Get remaining value
                    0081              JR   @ZAB           ;Loop round again
                    0082  @ZAA:       ADD  A,C            ;Add remainder to result
                    0083              POP  BC
                    0084              RET
                    0085  #ENDIF
                    0086  
                    0087  
                    0088  ; Utility: Convert byte to ascii character
                    0089  ;   On entry: A = Byte
                    0090  ;   On exit:  A = ASCII character
                    0091  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0092  ;             Interrupts enabled during this call
                    0093  ; If not printable then a dot is output instead.
0746:               0094  ConvertByteToAscii:
0746: FE 20         0095              CP   32             ;<SPACE?
0748: 38 04         0096              JR   C,@ZGW
074A: FE 7F         0097              CP   0x7F           ;>&7F?
074C: 38 02         0098              JR   C,@ZGX
074E: 3E 2E         0099  @ZGW:       LD   A,'.'
0750: C9            0100  @ZGX:       RET
                    0101  
                    0102  
                    0103  ; Utility: Convert byte to nibbles
                    0104  ;   On entry: A = Hex byte
                    0105  ;   On exit:  D = Most significant nibble
                    0106  ;             E = Least significant nibble
                    0107  ;             A BC HL IX IY I AF' BC' DE' HL' preserved
                    0108  ;             Interrupts not enabled
0751:               0109  ConvertByteToNibbles:
0751: F5            0110              PUSH AF
0752: 5F            0111              LD   E,A            ;Get byte to convert
0753: 1F            0112              RRA                 ;Shift top nibble to
0754: 1F            0113              RRA                 ;  botom four bits..
0755: 1F            0114              RRA
0756: 1F            0115              RRA
0757: E6 0F         0116              AND  0x0F           ;Mask off unwanted bits
0759: 57            0117              LD   D,A            ;Store top nibble
075A: 7B            0118              LD   A,E            ;Get byte to convert
075B: E6 0F         0119              AND  0x0F           ;Mask off unwanted bits
075D: 5F            0120              LD   E,A            ;Store bottom nibble
075E: F1            0121              POP  AF
075F: C9            0122              RET
                    0123  
                    0124  
                    0125  #IFDEF      kIncludeUnusedCode
                    0126  ; Utility: Convert character to lower case
                    0127  ;   On entry: A = Character in either case
                    0128  ;   On exit:  A = Character in lower case
                    0129  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0130  ConvertCharToLCase:
                    0131              CP   'A'            ;Character less than 'A'?
                    0132              RET  C              ;Yes, so finished
                    0133              CP   'Z'+1          ;Character greater than 'Z'?
                    0134              RET  NC             ;Yes, so finished
                    0135              ADD  'a'-'A'        ;Convert case
                    0136              RET
                    0137  #ENDIF
                    0138  
                    0139  
                    0140  ; Utility: Convert character to numberic value
                    0141  ;   On entry: A = ASCII character (0-9 or A-F)
                    0142  ;   On exit:  If character is a valid hex digit:
                    0143  ;               A = Numberic value (0 to 15) and Z flagged
                    0144  ;             If character is not a valid hex digit:
                    0145  ;               A = 0xFF and NZ flagged
                    0146  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0147  ;             Interrupts not enabled
0760:               0148  ConvertCharToNumber:
0760: CD 81 07      0149              CALL ConvertCharToUCase
0763: FE 30         0150              CP   '0'            ;Character < '0'?
0765: 38 0C         0151              JR   C,@Bad         ;Yes, so no hex character
0767: FE 3A         0152              CP   '9'+1          ;Character <= '9'?
0769: 38 0C         0153              JR   C,@OK          ;Yes, got hex character
076B: FE 41         0154              CP   'A'            ;Character < 'A'
076D: 38 04         0155              JR   C,@Bad         ;Yes, so not hex character
076F: FE 47         0156              CP   'F'+1          ;Character <= 'F'
0771: 38 04         0157              JR   C,@OK          ;No, not hex
                    0158  ; Character is not a hex digit so return 
0773: 3E FF         0159  @Bad:       LD   A,0xFF         ;Return status: not hex character
0775: B7            0160              OR   A              ;  A = 0xFF and NZ flagged
0776: C9            0161              RET
                    0162  ; Character is a hex digit so adjust from ASCII to number
0777: D6 30         0163  @OK:        SUB  '0'            ;Subtract '0'
0779: FE 0A         0164              CP   0x0A           ;Number < 10 ?
077B: 38 02         0165              JR   C,@Finished    ;Yes, so finished
077D: D6 07         0166              SUB  0x07           ;Adjust for 'A' to 'F'
077F: BF            0167  @Finished:  CP   A              ;Return A = number (0 to 15) and Z flagged to
0780: C9            0168              RET                 ;  indicate character is a valid hex digital
                    0169  
                    0170  
                    0171  ; Utility: Convert character to upper case
                    0172  ;   On entry: A = Character in either case
                    0173  ;   On exit:  A = Character in upper case
                    0174  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
0781:               0175  ConvertCharToUCase:
0781: FE 61         0176              CP   'a'            ;Character less than 'a'?
0783: D8            0177              RET  C              ;Yes, so finished
0784: FE 7B         0178              CP   'z'+1          ;Character greater than 'z'?
0786: D0            0179              RET  NC             ;Yes, so finished
0787: D6 20         0180              SUB  'a'-'A'        ;Convert case
0789: C9            0181              RET
                    0182  
                    0183  
                    0184  ; Utility: Convert hexadecimal or decimal text to number
                    0185  ;   On entry: DE = Pointer to start of ASCII string
                    0186  ;   On exit:  If valid number found:
                    0187  ;               A = 0 and Z flagged
                    0188  ;               HL = Number found
                    0189  ;             If valid number not found:
                    0190  ;               A != 0 and NZ flagged
                    0191  ;               HL = Not specified
                    0192  ;             DE = Not specified
                    0193  ;             HL = Number
                    0194  ;             BC DE IX IY I AF' BC' DE' HL' preserved
                    0195  ; Hexadecmal numbers can be prefixed with either "$" or "0x"
                    0196  ; Decimal numbers must be prefixed with "+"
                    0197  ; A number without a prefix is assumed to be hexadecimal
                    0198  ; Hexadecimal number without a prefix must start with "0" to "9"
                    0199  ; ... this is to stop the assembler getting confused between
                    0200  ; ... register names and constants which could be fixed by
                    0201  ; ... re-ordering the (dis)assebmer's instruction table
                    0202  ; Numbers can be terminated with ")", space, null or control code
                    0203  ; Negative numbers, preceded with "-", are not supported
                    0204  ; Text must be terminated with ')', space or control char.
078A:               0205  ConvertStringToNumber:
078A: C5            0206              PUSH BC
078B: 21 00 00      0207              LD   HL,0           ;Build result here
078E: 1A            0208              LD   A,(DE)         ;Get character from string
078F: FE 2B         0209              CP   '+'            ;Does string start with '+' ?
0791: 28 31         0210              JR   Z,@Decimal     ;Yes, so its decimal
0793: FE 24         0211              CP   '$'            ;Does string start with '$' ?
0795: 28 15         0212              JR   Z,@Hdecimal    ;Yes, so its hexadecimal
0797: FE 27         0213              CP   kApostroph     ;Does string start with apostrophe?
0799: 28 4E         0214              JR   Z,@Char        ;Yes, so its a character
079B: FE 22         0215              CP   '"'            ;Does string start with '"' ?
079D: 28 4A         0216              JR   Z,@Char        ;Yes, so its a character
                    0217  ;;          CALL IsCharNumeric  ;Is first character '0' to '9' ?
                    0218  ;;          JR   NC,@Failure    ;No, so invalid number
                    0219  ;           CALL IsCharHex      ;Is first character hexadecimal ?
                    0220  ;           JR   NC,@Failure    ;No, so invalid hex character
079F: FE 30         0221              CP   '0'            ;Is first character '0' ?
07A1: 20 0A         0222              JR   NZ,@HexNext    ;No, so default to hexadecimal
                    0223  ;           JR   NZ,@DecNext    ;No, so default to decimal
07A3: 13            0224              INC  DE             ;Point to next character in string
07A4: 1A            0225              LD   A,(DE)         ;Get character from string
07A5: CD 81 07      0226              CALL ConvertCharToUCase
07A8: FE 58         0227              CP   'X'            ;Is second character 'x' ?
07AA: 20 01         0228              JR   NZ,@HexNext    ;No, so must be default format
                    0229  ;           JR   NZ,@DecNext    ;No, so must be default format
                    0230  ; Hexadecimal number...
07AC: 13            0231  @Hdecimal:  INC  DE             ;Point to next character in string
07AD: 1A            0232  @HexNext:   LD   A,(DE)         ;Get character from string
07AE: FE 29         0233              CP   ')'            ;Terminated with a bracket?
07B0: 28 3C         0234              JR   Z,@Success     ;yes, so success
07B2: FE 21         0235              CP   A,kSpace+1     ;Space or control character?
07B4: 38 38         0236              JR   C,@Success     ;Yes, so successld hl
07B6: CD 60 07      0237              CALL ConvertCharToNumber  ;Convert character to number
07B9: 20 36         0238              JR   NZ,@Failure    ;Return if failure (NZ flagged)
07BB: 13            0239              INC  DE             ;Point to next character in string
07BC: 29            0240              ADD  HL,HL          ;Current result = 16 * current result..
07BD: 29            0241              ADD  HL,HL
07BE: 29            0242              ADD  HL,HL
07BF: 29            0243              ADD  HL,HL
07C0: B5            0244              OR   A,L            ;Add new number (0 to 15)..
07C1: 6F            0245              LD   L,A
07C2: 18 E9         0246              JR   @HexNext
                    0247  ; Decimal number...
07C4: 13            0248  @Decimal:   INC  DE             ;Point to next character in string
07C5: 1A            0249  @DecNext:   LD   A,(DE)         ;Get character from string
07C6: FE 29         0250              CP   ')'            ;Terminated with a bracket?
07C8: 28 24         0251              JR   Z,@Success     ;yes, so success
07CA: FE 21         0252              CP   A,kSpace+1     ;Space or control character?
07CC: 38 20         0253              JR   C,@Success     ;Yes, so success
07CE: CD 17 08      0254              CALL IsCharNumeric  ;Is first character '0' to '9' ?
07D1: 30 1E         0255              JR   NC,@Failure    ;No, so invalid number
07D3: CD 60 07      0256              CALL ConvertCharToNumber  ;Convert character to number
07D6: 20 19         0257              JR   NZ,@Failure    ;Return if failure (NZ flagged)
07D8: 13            0258              INC  DE             ;Point to next character in string
07D9: D5            0259              PUSH DE
07DA: 06 09         0260              LD   B,9            ;Current result = 10 * current result..
07DC: 54            0261              LD   D,H
07DD: 5D            0262              LD   E,L
07DE: 19            0263  @DecLoop:   ADD  HL,DE          ;Add result to itself 9 times
07DF: 10 FD         0264              DJNZ @DecLoop
07E1: D1            0265              POP  DE
07E2: 85            0266              ADD  A,L            ;Add new number (0 to 15)..
07E3: 6F            0267              LD   L,A
07E4: 30 DF         0268              JR   NC,@DecNext
07E6: 24            0269              INC  H
07E7: 18 DC         0270              JR   @DecNext
                    0271  ; Character...
07E9: 13            0272  @Char:      INC  DE             ;Point to next character in string
07EA: 1A            0273              LD   A,(DE)         ;Get ASCII character
07EB: 6F            0274              LD   L,A            ;Store ASCII value as result
07EC: 26 00         0275              LD   H,0
                    0276  ;           JR   @Success
                    0277  ; Return result...
07EE: C1            0278  @Success:   POP  BC
07EF: AF            0279              XOR  A              ;Return success with A = 0 and Z flagged
07F0: C9            0280              RET
07F1: C1            0281  @Failure:   POP  BC
07F2: 3E FF         0282              LD   A,0xFF         ;Return failure with A != 0
07F4: B7            0283              OR   A              ;  and NZ flagged
07F5: C9            0284              RET
                    0285  
                    0286  
                    0287  ; Utility: Find start of specified string in bit 7 delimited list
                    0288  ;   On entry: A = String number
                    0289  ;             HL = Start of string list
                    0290  ;   On exit:  HL = Start of string
                    0291  ;             AF BC DE IX IY I AF' BC' DE' HL' preserved
                    0292  ; Find string A in bit 7 delimited string list
07F6:               0293  FindStringInList:
07F6: F5            0294              PUSH AF
07F7: C5            0295              PUSH BC
07F8: 2B            0296              DEC  HL             ;Point to address before string list
07F9: 47            0297              LD   B,A            ;Get string number
07FA: 23            0298  @Next:      INC  HL             ;Point to next character
07FB: CB 7E         0299              BIT  7,(HL)         ;Start of new string?
07FD: 28 FB         0300              JR   Z,@Next        ;No, so go get next character
07FF: 10 F9         0301              DJNZ @Next          ;Loop back if not the right string
0801: C1            0302              POP  BC
0802: F1            0303              POP  AF
0803: C9            0304              RET
                    0305  
                    0306  
                    0307  ; Utility: Is character hexadecimal?
                    0308  ;   On entry: A = ASCII character
                    0309  ;   On exit:  Carry flag set if character is hexadecimal (0 to 9, A to F)
                    0310  ;             A BC DE HL IX IY I AF' BC' DE' HL' preserved
0804: FE 30         0311  IsCharHex:  CP   '0'            ;Less than '0'?
0806: 38 0D         0312              JR   C,@Not         ;Yes, so go return NOT hex
0808: FE 3A         0313              CP   '9'+1          ;Less than or equal to '9'?
080A: D8            0314              RET  C              ;Yes, so numeric (C flagged)
080B: CD 81 07      0315              CALL ConvertCharToUCase
080E: FE 41         0316              CP   'A'            ;Less than 'A'
0810: 38 03         0317              JR   C,@Not         ;Yes, so go return NOT hex
0812: FE 47         0318              CP   'F'+1          ;Less than or equal to 'F'?
0814: D8            0319              RET  C              ;Yes, so hexadecimal (C flagged)
0815: B7            0320  @Not:       OR   A              ;No, so NOT numeric (NC flagged)
0816: C9            0321              RET
                    0322  
                    0323  
                    0324  ; Utility: Is character numeric?
                    0325  ;   On entry: A = ASCII character
                    0326  ;   On exit:  Carry flag set if character is numeric (0 to 9)
                    0327  ;             A BC DE HL IX IY I AF' BC' DE' HL' preserved
0817:               0328  IsCharNumeric:
0817: FE 30         0329              CP   '0'            ;Less than '0'?
0819: 38 03         0330              JR   C,@Not         ;Yes, so go return NOT numeric
081B: FE 3A         0331              CP   '9'+1          ;Less than or equal to '9'?
081D: D8            0332              RET  C              ;Yes, so numeric (C flagged)
081E: B7            0333  @Not:       OR   A              ;No, so NOT numeric (NC flagged)
081F: C9            0334              RET
                    0335  
                    0336  
                    0337  ; Utility: Find number of matching string in bit 7 delimited string list
                    0338  ;   On entry: BC = Start of address list
                    0339  ;             DE = Start of target string
                    0340  ;             HL = Start of bit 7 delimited string list
                    0341  ;   On exit:  If string found in list:
                    0342  ;               A = String number in list (1 to 127) and NZ flagged
                    0343  ;               DE = Next address after target string
                    0344  ;               HL = Address from address list
                    0345  ;             If string not found in list:
                    0346  ;               A = 0 and Z flagged
                    0347  ;               DE = Start of target string (preserved)
                    0348  ;               HL = Not specified
                    0349  ;             BC IX IY I AF' BC' DE' HL' preserved
                    0350  ; Target string can be terminated with and control character or a space.
0820:               0351  SearchStringList:
0820: C5            0352              PUSH BC             ;Preserve start of address table
0821: 06 00         0353              LD   B,0            ;String counter
0823: D5            0354              PUSH DE             ;Preserve start of target string
                    0355  ; Find start of next string in list
0824: 04            0356  @NextStr:   INC  B              ;Increment string count
0825: D1            0357              POP  DE             ;Restore start of target string
0826: D5            0358              PUSH DE             ;Preserve start of target string
0827: CB 7E         0359  @NextChar:  BIT  7,(HL)         ;Start of new string?
0829: 20 03         0360              JR   NZ,@CompNext   ;Yes, so go compare characters
082B: 23            0361              INC  HL             ;No, so point to next character
082C: 18 F9         0362              JR   @NextChar      ;  and go consider it
                    0363  ; Compare target string (at DE) with string from list (at HL)
082E: 7E            0364  @CompNext:  LD   A,(HL)         ;Get character from list
082F: FE 80         0365              CP   0x80           ;End of list?
0831: 28 2D         0366              JR   Z,@Failed      ;Yes, so failed to find string
0833: 7E            0367  @CompChar:  LD   A,(HL)         ;Get character from list string
0834: E6 7F         0368              AND  0x7F           ;Mask off bit 7 start flag
0836: 4F            0369              LD   C,A            ;Store upper case char from list
0837: 1A            0370              LD   A,(DE)         ;Get character from target string
0838: 23            0371              INC  HL             ;Point to next character in list
0839: 13            0372              INC  DE             ;Point to next character in target
083A: CD 81 07      0373              CALL ConvertCharToUCase
083D: B9            0374              CP   C              ;Match with list character?
083E: 20 E4         0375              JR   NZ,@NextStr    ;No, so go try next list string
                    0376  ; Strings matching so far so check for end of both
0840: 1A            0377              LD   A,(DE)         ;Get character from target
                    0378  ;           CP   kSpace+1       ;End if target string?
                    0379  ;           JR   C,@Abbrev      ;Yes, so go (allow abbreviations)
0841: FE 21         0380              CP   kSpace+1       ;End of target string?
0843: 38 06         0381              JR   C,@EndT        ;Yes, so go check end of list str
0845: CB 7E         0382              BIT  7,(HL)         ;End of string in list?
0847: 28 EA         0383              JR   Z,@CompChar    ;No, so go compare next character
0849: 18 D9         0384              JR   @NextStr       ;Yes, so go try next string
                    0385  ; End of target string found
084B: CB 7E         0386  @EndT:      BIT  7,(HL)         ;End of string in list as well?
084D: 28 D5         0387              JR   Z,@NextStr     ;No, so go try next string
                    0388  ; Found target string in string list
                    0389  ; So get address from address list
                    0390  ;@Abbrev:
084F: E1            0391              POP  HL             ;Restore start of target string
0850: E1            0392              POP  HL             ;Restore start of address table
0851: E5            0393              PUSH HL             ;Preserve start of address table
0852: 2B            0394              DEC  HL             ;Point to start address -2
0853: 2B            0395              DEC  HL
0854: 48            0396              LD   C,B            ;Get string number (1 to N)
0855: 23            0397  @Loop:      INC  HL
0856: 23            0398              INC  HL
0857: 10 FC         0399              DJNZ @Loop
0859: 46            0400              LD   B,(HL)         ;Get address from table
085A: 23            0401              INC  HL
085B: 66            0402              LD   H,(HL)
085C: 68            0403              LD   L,B
085D: 79            0404              LD   A,C            ;Return number of this string in list
085E: 18 02         0405              JR   @Exit
                    0406  ; Failed to find target string in string list
0860: C1            0407  @Failed:    POP  BC             ;Restore start of target string
0861: AF            0408              XOR  A              ;Return zero if failed to find string
0862: B7            0409  @Exit:      OR   A              ;Return Z flag if not found
0863: C1            0410              POP  BC             ;Restore start of address table
0864: C9            0411              RET
                    0412  
                    0413  
                    0414  ; Utility: Find number of matching string in bit 7 delimited string list
                    0415  ;   On entry: DE = Start of target string
                    0416  ;             HL = Start of bit 7 delimited string list
                    0417  ;   On exit:  If string found in list:
                    0418  ;               A = String number in list (1 to 127) and NZ flagged
                    0419  ;               DE = Next address after target string
                    0420  ;               HL = Address from address list
                    0421  ;             If string not found in list:
                    0422  ;               A = 0 and Z flagged
                    0423  ;               DE = Not specified
                    0424  ;               HL = Not specified
                    0425  ;             BC IX IY I AF' BC' DE' HL' preserved
                    0426  ; Target string can be terminated with and control character or a space.
                    0427  ; This version of the search function is for use where there is no 
                    0428  ; associated address table. A dummy address table is set up here such
                    0429  ; that the main search function has somewhere harmless to pick up an
                    0430  ; address word (which is just whatever is in memory at the time).
0865:               0431  SearchStringListNA:
0865: C5            0432              PUSH BC             ;Preserve start of address table
0866: 01 65 08      0433              LD   BC,SearchStringListNA  ;Dummy address
0869: CD 20 08      0434              CALL SearchStringList
086C: C1            0435              POP  BC
086D: C9            0436              RET
                    0437  
                    0438  
                    0439  ; Utility: Write hex prefix (eg. "0x") to current string buffer
                    0440  ;   On entry: No parameters required
                    0441  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
086E:               0442  WrHexPrefix:
086E: F5            0443              PUSH AF
086F: 3E 24         0444              LD   A,'$'
0871: CD DB 06      0445              CALL StrWrChar      ;Write '$'
                    0446  ;           LD   A,'0'
                    0447  ;           CALL StrWrChar      ;Write '0'
                    0448  ;           LD   A,'x'
                    0449  ;           CALL StrWrChar      ;Write 'x'
0874: F1            0450              POP  AF
0875: C9            0451              RET
                    0452  
                    0453  
                    0454  ; Utility: Disassemble instruction and write to default string
                    0455  ;   On entry: HL = Start of instruction to be disassembled
                    0456  ;   On exit:  HL = Address after this instruction
                    0457  ;                  or start address + 1 if no disassembler
                    0458  ;             BC IX IY I AF' BC' DE' HL' preserved
                    0459  ; If the disassembler is not included the address and hex opcode bytes
                    0460  ; are output instead.
0876:               0461  WrInstruction:
                    0462  #IFDEF      IncludeDisassemble
                    0463  ; Disassembler available so display address, opcode bytes and mnemonic
0876: CD 4E 14      0464              CALL DisWrInstruction
0879: 3E 2F         0465              LD   A,47           ;Column number
087B: CD 22 07      0466              CALL StrWrPadding   ;Pad with spaces to specified column
                    0467  #ELSE
                    0468  ; No disassembler so just display address and hex opcode bytes
                    0469              CALL StrInitDefault ;Initialise default string buffer
                    0470              LD   D,H            ;Get current address
                    0471              LD   E,L
                    0472              INC  HL             ;Prepare return address
                    0473              CALL StrWrHexWord   ;Display breakpoint address
                    0474              LD   A,':'
                    0475              CALL StrWrChar      ;Print ':'
                    0476  ;           LD   A,(DE)         ;Get op-code at PC
                    0477              LD   A,4            ;Get length of instruction TODO
                    0478              LD   B,A
                    0479  @ZAO:       CALL StrWrSpace
                    0480              LD   A,(DE)         ;Read byte at PC
                    0481              CALL StrWrHexByte
                    0482              INC  DE
                    0483              DJNZ @ZAO
                    0484  ;           LD   A,'?'
                    0485  ;           CALL StrWrChar      ;Print '?' (no disassembly)
                    0486              LD   A,25           ;Column number
                    0487              CALL StrWrPadding   ;Pad with spaces to specified column
                    0488  #ENDIF
                    0489  ; With or without disassembler, terminate instruction line
087E: 3E 3E         0490              LD   A,'>'
0880: CD DB 06      0491              CALL StrWrChar      ;Write '>' to string
0883: C3 35 07      0492              JP   StrWrSpace     ;Write space to string
                    0493  
                    0494  
                    0495  ; Utility: Write memory dump line to default string buffer
                    0496  ;   On entry: DE = Start location
                    0497  ;   On exit:  DE = Next address after dump
                    0498  ;             AF BC HL IX IY I AF' BC' DE' HL' preserved
0886:               0499  WrMemoryDump:
0886: F5            0500              PUSH AF
0887: C5            0501              PUSH BC
                    0502  ; Write once line of memory dump
                    0503  ; Write memory contents in hex 
0888: D5            0504  @Line:      PUSH DE             ;Store start address of this line
0889: CD 8A 06      0505              CALL StrInitDefault ;Initialise default string buffer
088C: CD C4 06      0506              CALL StrWrAddress   ;Write address, colon, space
088F: 06 10         0507              LD   B,16           ;Write 16 hex bytes...
0891: CD 35 07      0508  @Hex:       CALL StrWrSpace     ;Write space to string buffer
0894: 1A            0509              LD   A,(DE)         ;Get byte from memory
0895: CD EF 06      0510              CALL StrWrHexByte   ;Write hex byte to string buffer
0898: 13            0511              INC  DE             ;Point to next memory location
0899: 7B            0512              LD   A,E            ;Add extra space after 8 bytes...
089A: E6 07         0513              AND   7             ;Test for byte 8
089C: CC 35 07      0514              CALL Z,StrWrSpace   ;Tes, so write space to string
089F: 10 F0         0515              DJNZ @Hex           ;Repeat until all done
08A1: D1            0516              POP  DE             ;Get start address of this line
08A2: CD 35 07      0517              CALL StrWrSpace     ;Write spaces
08A5: 06 10         0518              LD   B,16           ;Write 16 ascii characters...
                    0519  ; Write memory contents in ASCII
08A7: 1A            0520  @Ascii:     LD   A,(DE)         ;Get byte from memory
08A8: CD D2 06      0521              CALL StrWrAsciiChar ;Convert to ASCII character or dot
08AB: 13            0522              INC  DE             ;Point to next memory location
08AC: 10 F9         0523              DJNZ @Ascii         ;Repeat until all done
08AE: CD 1A 07      0524              CALL StrWrNewLine   ;Write new line to string buffer
08B1: C1            0525              POP  BC
08B2: F1            0526              POP  AF
08B3: C9            0527              RET
                    0528  
                    0529  
                    0530  ; Utility: Write register values and flags to default string bufffer
                    0531  ;   On entry: No parameters
                    0532  ;   On exit:  IX IY I AF' BC' DE' HL' I AF' BC' DE' HL' preserved
08B4:               0533  WrRegister1:
08B4: 11 25 09      0534              LD   DE,sRegisters  ;Register strings (line 1)
08B7: 21 73 A2      0535              LD   HL,iRegisters  ;Register values
08BA: 01 75 A2      0536              LD   BC,iAF         ;Flags value
08BD: 18 09         0537              JR   WrRegister     ;Go write registers
08BF:               0538  WrRegister2:
08BF: 11 48 09      0539              LD   DE,sRegister2  ;Register strings (line 2)
08C2: 21 81 A2      0540              LD   HL,iRegister2  ;Register values
08C5: 01 83 A2      0541              LD   BC,iAF2        ;Flags value
                    0542  ; Write register details in BC, DE and HL, to string buffer
08C8:               0543  WrRegister:
08C8: CD 8A 06      0543  WrRegister: CALL StrInitDefault ;Initialise default string buffer
08CB: 1A            0544  @Name:      LD   A,(DE)         ;Get character of register name
08CC: 13            0545              INC  DE             ;Point to next character of name
08CD: FE 2C         0546              CP   ','            ;Character is comma?
08CF: 28 0C         0547              JR   Z,@Value       ;Yes, so go write value
08D1: FE 2D         0548              CP   '-'            ;Character is '-'?
08D3: 28 16         0549              JR   Z,@WriteFlag   ;Yes, so go write flags
08D5: B7            0550              OR   A              ;Null terminator?
08D6: 28 30         0551              JR   Z,@WriteEOL    ;Yes, so we've finished
08D8: CD DB 06      0552              CALL StrWrChar      ;Write character of register name
08DB: 18 EE         0553              JR   @Name          ;Loop back for next character
                    0554  ; Write register values in hex
08DD: D5            0555  @Value:     PUSH DE
08DE: 5E            0556              LD   E,(HL)         ;Get lo byte of register value
08DF: 23            0557              INC  HL
08E0: 56            0558              LD   D,(HL)         ;Get hi byte of register value
08E1: 23            0559              INC  HL
08E2: CD 0F 07      0560              CALL StrWrHexWord   ;Write register value
08E5: D1            0561              POP  DE
08E6: CD 35 07      0562              CALL StrWrSpace
08E9: 18 E0         0563              JR   @Name          ;Loop back for next register
                    0564  ; Write flags
08EB:               0565  @WriteFlag:
08EB: 50            0565  @WriteFlag: LD   D,B            ;Get address of flags register
08EC: 59            0566              LD   E,C
08ED: 0E 80         0567              LD   C,0x80         ;Initialise flag bit mask
08EF: 21 6B 09      0568              LD   HL,sFlags      ;Point to flags string
08F2: 7E            0569  @NextFlag:  LD   A,(HL)         ;Get flag character
08F3: FE 2D         0570              CP   '-'            ;Flag bit used?
08F5: 28 09         0571              JR   Z,@ZBU         ;No, so skip
08F7: 1A            0572              LD   A,(DE)         ;Get flags register
08F8: A1            0573              AND  C              ;Test with bit mask C
08F9: 28 03         0574              JR   Z,@ZBT         ;Flag not set, so skip
08FB: 7E            0575              LD   A,(HL)         ;Flag set, so get flag char
08FC: 18 02         0576              JR   @ZBU
08FE: 3E 2D         0577  @ZBT:       LD   A,'-'          ;Flag not set, so use '-' char
0900: CD DB 06      0578  @ZBU:       CALL StrWrChar      ;Write flag character or '-'
0903: 23            0579              INC  HL             ;Prepare for next flag
0904: CB 39         0580              SRL  C              ;Shift flag bit mask
0906: 30 EA         0581              JR   NC,@NextFlag   ;No carry, so loop to next bit
                    0582  ; Write end of line
0908: CD 1A 07      0583  @WriteEOL:  CALL StrWrNewLine   ;New line
090B: C9            0584              RET
                    0585  
                    0586  
                    0587  ; **********************************************************************
                    0588  ; **  End of Utility functions module                                 **
                    0589  ; **********************************************************************
                    0590  
                    0049  #ENDIF
                    0050  
                    0051  ; Monitor functions
                    0052  #IFDEF      IncludeMonitor
                    0053  #INCLUDE    Monitor\Monitor.asm ;Minitor essentials
                    0001  ; **********************************************************************
                    0002  ; **  Monitor essentials                        by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides the following:
                    0006  ;   Defines monitor's global workspace / variables
                    0007  ;   Defines monitor's constant message data
                    0008  ;   Function to output monitor messages
                    0009  ;
                    0010  ; Public functions provided:
                    0011  ;   MonOutputMsg          Output monitor messages
                    0012  
                    0013  
                    0014  ; **********************************************************************
                    0015  ; **  Constants                                                       **
                    0016  ; **********************************************************************
                    0017  
                    0018  ; Message numbers
090C:               0019  kMsgMonFst:
                    0019  kMsgMonFst  .EQU 0x20           ;First monitor message
090C:               0020  kMsgBadCmd:
                    0020  kMsgBadCmd: .EQU kMsgMonFst+0   ;Bad commandr
090C:               0021  kMsgBadPar:
                    0021  kMsgBadPar: .EQU kMsgMonFst+1   ;Bad parameter
090C:               0022  kMsgSyntax:
                    0022  kMsgSyntax: .EQU kMsgMonFst+2   ;Syntax error
0023:               0023  kMsgBPSet:  .EQU kMsgMonFst+3   ;Breakpoint set
0024:               0024  kMsgBPClr:  .EQU kMsgMonFst+4   ;Breakpoint cleared
090C:               0025  kMsgBPFail:
                    0025  kMsgBPFail: .EQU kMsgMonFst+5   ;Unable to set breakpoint here
0026:               0026  kMsgHelp:   .EQU kMsgMonFst+6   ;Help text
0027:               0027  kMsgNotAv:  .EQU kMsgMonFst+7   ;Feature not included
0028:               0028  kMsgReady:  .EQU kMsgMonFst+8   ;Ready
090C:               0029  kMsgFileEr:
                    0029  kMsgFileEr: .EQU kMsgMonFst+9   ;File error
090C:               0030  kMsgMonLst:
                    0030  kMsgMonLst: .EQU kMsgFileEr     ;Last monitor message
                    0031  
                    0032  
                    0033  ; **********************************************************************
                    0034  ; **  Public functions                                                **
                    0035  ; **********************************************************************
                    0036  
                    0037  ; Monitor: Output message
                    0038  ;  On entry:  A = Message number (1 to n)
                    0039  ;   On exit:  If message output by monitor A = 0
                    0040  ;             otherwise A = Message number
                    0041  ;             BC IX IY I AF' BC' DE' HL' preserved
090C:               0042  MonOutputMsg:
                    0043  ; Monitor message?
090C: FE 20         0044              CP   kMsgMonFst     ;Valid system message number?
090E: D8            0045              RET  C              ;No, so abort
090F: FE 2A         0046              CP   kMsgMonLst+1   ;Valid system message number?
0911: D0            0047              RET  NC             ;No, so abort
0912: D6 20         0048              SUB  kMsgMonFst     ;Adjust message number to 0 to n
0914: 5F            0049              LD   E,A            ;Get message number
0915: 16 00         0050              LD   D,0
0917: 21 16 0C      0051              LD   HL,MsgTabMon   ;Get start of message table
091A: 19            0052              ADD  HL,DE          ;Calculate location in table
091B: 19            0053              ADD  HL,DE
091C: 7E            0054              LD   A,(HL)         ;Get address from table...
091D: 23            0055              INC  HL
091E: 56            0056              LD   D,(HL)
091F: 5F            0057              LD   E,A
0920: CD EE 04      0058              CALL OutputZString  ;Output message as DE
0923: AF            0059              XOR  A              ;Flag message output by monitor
0924: C9            0060              RET
                    0061  
                    0062  ; **********************************************************************
                    0063  ; **  Constant data                                                   **
                    0064  ; **********************************************************************
                    0065  
                    0066  ; Register and flag strings
                    0067  ; Terminate register name strings with '-' (for flags) or a null
                    0068  ; These strings must match the order the registers are stored in RAM
0925:               0069  sRegisters:
0925: 50 43 3A 2C   0069  sRegisters: .DB  "PC:,AF:,BC:,DE:,HL:,IX:,IY:,Flags:-"
0929: 41 46 ...     2911  
0948:               0070  sRegister2:
0948: 53 50 3A 2C   0070  sRegister2: .DB  "SP:,AF',BC',DE',HL',(S),IR:,Flags'-"
094C: 41 46 ...     2912  
096B: 53 5A 2D 48   0071  sFlags:     .DB  "SZ-H-PNC"
096F: 2D 50 4E 43   2913  
                    0072  
                    0073  
                    0074  ; Message strings (zero terminated)
0973: 42 61 64 20   0075  szBadCmd:   .DB  "Bad command",kNewLine,kNull
0977: 63 6F ...     2917  
0980:               0076  szBadParam:
0980: 42 61 64 20   0076  szBadParam: .DB  "Bad parameter",kNewLine,kNull
0984: 70 61 ...     2918  
098F:               0077  szAsmError:
098F: 53 79 6E 74   0077  szAsmError: .DB  "Syntax error",kNewLine,kNull
0993: 61 78 ...     2919  
099D: 42 72 65 61   0078  szBPSet:    .DB  "Breakpoint set",kNewLine,kNull
09A1: 6B 70 ...     2920  
09AD: 42 72 65 61   0079  szBPClear:  .DB  "Breakpoint cleared",kNewLine,kNull
09B1: 6B 70 ...     2921  
09C1: 55 6E 61 62   0080  szBPFail:   .DB  "Unable to set breakpoint here",kNewLine,kNull
09C5: 6C 65 ...     2922  
09E0:               0081  szNotAvail:
09E0: 46 65 61 74   0081  szNotAvail: .DB  "Feature not included",kNewLine,kNull
09E4: 75 72 ...     2923  
09F6: 52 65 61 64   0082  szReady:    .DB  "Ready",kNewLine,kNull
09FA: 79 05 00      2924  
09FD: 46 69 6C 65   0083  szFileErr:  .DB  "File error",kNewLine,kNull
0A01: 20 65 ...     2925  
                    0084  
0000:               0085  szCmdHelp:
                    0086  #IFDEF      IncludeHelp
0A09: 4D 6F 6E 69   0087              .DB  "Monitor commands:",kNewLine
0A0D: 74 6F ...     2929  
                    0088  ; Single character commands         20        30        40        50        60        70        80
                    0089  ;                 12345678901234567890123456789012345678901234567890123456789012345678901234567890
0A1B: 41 20 5B 3C   0090              .DB  "A [<address>]  = Assemble        |  D [<address>]   = Disassemble",kNewLine
0A1F: 61 64 ...     2932  
0A5D: 4D 20 5B 3C   0091              .DB  "M [<address>]  = Memory display  |  E [<address>]   = Edit memory",kNewLine
0A61: 61 64 ...     2933  
0A9F: 52 20 5B 3C   0092              .DB  "R [<name>]     = Registers/edit  |  F [<name>]      = Flags/edit",kNewLine 
0AA3: 6E 61 ...     2934  
0AE0: 42 20 5B 3C   0093              .DB  "B [<address>]  = Breakpoint      |  S [<address>]   = Single step",kNewLine
0AE4: 61 64 ...     2935  
0B22: 49 20 3C 70   0094              .DB  "I <port>       = Input from port |  O <port> <data> = Output to port",kNewLine
0B26: 6F 72 ...     2936  
0B67: 47 20 5B 3C   0095              .DB  "G [<address>]  = Go to program",kNewLine
0B6B: 61 64 ...     2937  
                    0096  ; Full word commands
0B86: 42 41 55 44   0097              .DB  "BAUD <device> <rate>             |  CONSOLE <device>",kNewLine
0B8A: 20 3C ...     2939  
0BBB: 46 49 4C 4C   0098              .DB  "FILL <start> <end> <byte>        |  API <function> [<A>] [<DE>]",kNewLine
0BBF: 20 3C ...     2940  
0BFB: 44 45 56 49   0099              .DB  "DEVICES, DIR, HELP, RESET",kNewLine
0BFF: 43 45 ...     2941  
                    0100  ; Optional commands
                    0101  #IFDEF      IncludeScripting
                    0102              .DB  "Scripting commands:",kNewLine
                    0103              .DB  "RUN, SCRIPT (list), OLD, NEW",kNewLine
                    0104  #ENDIF
                    0105  ;           .DB  kNewLine
                    0106  #ENDIF
0C15: 00            0107              .DB  kNull
                    0108  
                    0109  
                    0110  ; Message table
0C16: 73 09         0111  MsgTabMon:  .DW  szBadCmd
0C18: 80 09         0112              .DW  szBadParam
0C1A: 8F 09         0113              .DW  szAsmError
0C1C: 9D 09         0114              .DW  szBPSet
0C1E: AD 09         0115              .DW  szBPClear
0C20: C1 09         0116              .DW  szBPFail
0C22: 09 0A         0117              .DW  szCmdHelp
0C24: E0 09         0118              .DW  szNotAvail
0C26: F6 09         0119              .DW  szReady
0C28: FD 09         0120              .DW  szFileErr
                    0121  
                    0122  ; **********************************************************************
                    0123  ; **  Global workspace                                                **
                    0124  ; **********************************************************************
                    0125  
                    0126              .DATA
                    0127  
A273:               0128  iRegisters:
                    0129  ; Order is hard coded so do not change (see strings above)
A273: 01 00         0130  iPC:        .DW  0x0001         ;Register pair PC (Program Counter)
A275: 02 00         0131  iAF:        .DW  0x0002         ;Register pair AF
A277: 03 00         0132  iBC:        .DW  0x0003         ;Register pair BC
A279: 04 00         0133  iDE:        .DW  0x0004         ;Register pair DE
A27B: 05 00         0134  iHL:        .DW  0x0005         ;Register pair HL
A27D: 06 00         0135  iIX:        .DW  0x0006         ;Register pair IX
A27F: 07 00         0136  iIY:        .DW  0x0007         ;Register pair IY
                    0137  
A281:               0138  iRegister2:
                    0139  ; Order is hard coded so do not change (see strings above)
A281: 11 00         0140  iSP:        .DW  0x0011         ;Register pair SP (Stack Pointer)
A283: 12 00         0141  iAF2:       .DW  0x0012         ;Register pair AF'
A285: 13 00         0142  iBC2:       .DW  0x0013         ;Register pair BC'
A287: 14 00         0143  iDE2:       .DW  0x0014         ;Register pair DE'
A289: 15 00         0144  iHL2:       .DW  0x0015         ;Register pair HL'
A28B: 16 00         0145  iCSP:       .DW  0x0016         ;Register pair (SP)
A28D: 17 00         0146  iIR:        .DW  0x0017         ;Register pair IR
                    0147  
                    0148  
                    0149  ; **********************************************************************
                    0150  ; **  End of Monitor essentials                                       **
                    0151  ; **********************************************************************
                    0152  
                    0054  #ENDIF
                    0055  #IFDEF      IncludeAssembler
                    0056  #INCLUDE    Monitor\Assembler.asm ;In-line assembler (needs disassembler)
                    0001  ; **********************************************************************
                    0002  ; **  Assembler support                         by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides in-line assembly for a single instruction. It
                    0006  ; provides one public function which assembles the supplied string:
                    0007  ;
                    0008  ; Function: Assemble
                    0009  ; This takes the string pointed to by DE (eg. "LD A,2") and writes
                    0010  ; the instruction's opcodes to the address pointed to by HL.
                    0011  ;
                    0012  ; This module requires the Disassembler support module to be included
                    0013  ; as it makes heavy use of its functions and data.
                    0014  ;
                    0015  ; Assembly method:
                    0016  ; Try each possible instruction in the DistInst list.
                    0017  ; To save time the following are cached first:
                    0018  ;   Operation string number
                    0019  ;   Location of start of each operand string
                    0020  ;   Each operand string is null terminated
                    0021  
                    0022  
                    0023  ; **********************************************************************
                    0024  ; **  Public functions                                                **
                    0025  ; **********************************************************************
                    0026  
                    0027              .CODE
                    0028  
                    0029  ; Assemble instruction in input buffer
                    0030  ;   On entry: DE = Start location of buffer
                    0031  ;             HL = Address to store opcodes
                    0032  ;   On exit:  If instruction is valid:
                    0033  ;               Opcodes written to memory
                    0034  ;               A = Length of instruction in bytes and NZ flagged
                    0035  ;               HL = Address of next instruction
                    0036  ;             If invalid instruction:
                    0037  ;               Opcodes not written to memory
                    0038  ;               A = Error messgae number and Z flagged
                    0039  ;                   0 = Unspecified error, so report 'Syntax error'
                    0040  ;             IY I AF' BC' DE' HL' preserved
0C2A: CD 0E 04      0041  Assemble:   CALL InputBufConvUpper  ;Convert input string to upper case
0C2D: E5            0042              PUSH HL             ;Preserve address of opcodes
0C2E: 06 01         0043              LD   B,1            ;Length of instruction
                    0044  ; Get operation string number
0C30: 21 27 17      0045              LD   HL,DisString+1 ;Skip string 1 (blank string)
                    0046  ;           CALL SearchStringListNA
0C33: CD 20 08      0047              CALL SearchStringList
0C36: 28 4D         0048              JR   Z,@Error       ;Not found so error
0C38: 3C            0049              INC  A              ;Adjust as first string skipped
0C39: 32 8F A2      0050              LD   (iAsmOper),A   ;Store operation string number
                    0051  ; Get operand 1 string start address
0C3C: CD 87 0D      0052              CALL AsmSkipOverDelimiter
0C3F: ED 53 90 A2   0053              LD   (iAsmOp1),DE   ;Store operand 1 start address
0C43: CD 97 0D      0054              CALL AsmSkipToDelimiter
0C46: 62            0055              LD   H,D            ;Remember start of delimiter
0C47: 6B            0056              LD   L,E
                    0057  ; Get operand 2 string start address
0C48: CD 87 0D      0058              CALL AsmSkipOverDelimiter
0C4B: ED 53 92 A2   0059              LD   (iAsmOp2),DE   ;Store operand 2 start address
0C4F: CD 97 0D      0060              CALL AsmSkipToDelimiter
                    0061  ; Terminate operands and set default index instruction
0C52: AF            0062              XOR  A
0C53: 77            0063              LD   (HL),A         ;Terminate operand 1 with null
0C54: 12            0064              LD   (DE),A         ;Terminate operand 2 with null
0C55: 32 94 A2      0065              LD   (iAsmIndex),A  ;Default to no index instruction
0C58: 32 9A A2      0066              LD   (iAsmDisFl),A  ;Clear displacement flag
                    0067  ; Substitute HL for IX and IY
0C5B: 2A 90 A2      0068              LD   HL,(iAsmOp1)   ;Start of operand 1 string
0C5E: CD 25 0D      0069              CALL AsmSubsIndex   ;Substitute HL for IX/IY in operand 1
0C61: 2A 92 A2      0070              LD   HL,(iAsmOp2)   ;Start of operand 2 string
0C64: CD 25 0D      0071              CALL AsmSubsIndex   ;Substitute HL for IX/IY in operand 1
                    0072  ; Try each instruction in the instruction list
0C67: DD 21 8C 18   0073              LD   IX,DisInst     ;Start of instruction list
0C6B: AF            0074  @Next:      XOR  A              ;Clear A
0C6C: 32 95 A2      0075              LD   (iAsmPri),A    ;Clear primary opcode special bits
0C6F: 32 98 A2      0076              LD   (iAsmLenIm),A  ;Clear length of immediate value
0C72: CD A3 0D      0077              CALL AsmTestInstruction
0C75: 28 11         0078              JR   Z,@Found       ;Instruction found in table so skip
0C77: C5            0079              PUSH BC             ;Preserve BC
0C78: 06 05         0080              LD   B,5            ;Move IX to start of next
0C7A: DD 23         0081  @Inc:       INC  IX             ;  table entry by adding 5
0C7C: 10 FC         0082              DJNZ @Inc
0C7E: C1            0083              POP  BC             ;Restore BC
0C7F: DD 7E 01      0084              LD   A,(IX+1)       ;Get instruction bit mask
0C82: B7            0085              OR   A              ;Bit mask zero? (marks end of table)
0C83: 20 E6         0086              JR   NZ,@Next       ;No, so go try this instrucion
                    0087  ; Operation string not found in table
0C85: E1            0088  @Error:     POP  HL             ;Restore address of opcodes
0C86: AF            0089              XOR  A              ;Return error A=0 and Z flagged
0C87: C9            0090              RET
                    0091  ; Found instruction, so write opcodes to memory
                    0092  ; If there is an index instruction with displacement the displacement
                    0093  ; value is always the third opcode of the instruction
0C88: E1            0094  @Found:     POP  HL             ;Restore address of opcodes
0C89: 0E 00         0095              LD   C,0            ;Clear opcode counter
                    0096  ; Index instruction prefix
0C8B: 3A 94 A2      0097              LD   A,(iAsmIndex)  ;Get index instuction opcode
0C8E: B7            0098              OR   A              ;Zero? (not an index instruction)
0C8F: 28 03         0099              JR   Z,@NoIndex     ;Yes, so skip
0C91: 77            0100              LD   (HL),A         ;Store index instruction opcode
0C92: 23            0101              INC  HL             ;Increment opcode pointer
0C93: 0C            0102              INC  C              ;Increment opcode counter
0000:               0103  @NoIndex:
                    0104  ; Extended instruction prefix
0C94: DD CB 03 7E   0105              BIT  7,(IX+3)       ;Extended instruction?
0C98: 28 0D         0106              JR   Z,@NoExtn      ;No, so skip
0C9A: 3E CB         0107              LD   A,0xCB         ;Default prefix = 0xCB
0C9C: DD CB 03 76   0108              BIT  6,(IX+3)       ;Is Prefix = 0xED?
0CA0: 28 02         0109              JR   Z,@GotPrefix   ;No, so skip
0CA2: 3E ED         0110              LD   A,0xED         ;Prefix = 0xED
0CA4:               0111  @GotPrefix:
0CA4: 77            0111  @GotPrefix: LD   (HL),A         ;Store extended instruction opcode
0CA5: 23            0112              INC  HL             ;Increment opcode pointer
0CA6: 0C            0113              INC  C              ;Increment opcode counter
0000:               0114  @NoExtn:
                    0115  ; Index instruction displacement
0CA7: CD 11 0D      0116              CALL @Displace      ;Optionally put displacement here
                    0117  ; Primary opcode
0CAA: 3A 95 A2      0118              LD   A,(iAsmPri)    ;Get extra bits for primary opcode
0CAD: DD B6 00      0119              OR   (IX+0)         ;Include primary opcode from table
0CB0: 77            0120              LD   (HL),A         ;Store primary opcode in memory
0CB1: 23            0121              INC  HL             ;Increment opcode pointer
0CB2: 0C            0122              INC  C              ;Increment opcode counter
                    0123  ; Index instruction displacement
0CB3: CD 11 0D      0124              CALL @Displace      ;Optionally put displacement here
                    0125  ; Immediate value
0CB6: 3A 98 A2      0126              LD   A,(iAsmLenIm)  ;Get length of immediate value
0CB9: B7            0127              OR   A              ;Zero? (no immediate value)
0CBA: 28 4D         0128              JR   Z,@NoImmed     ;Yes, so skip
0CBC: 47            0129              LD   B,A            ;Remember length of immediate value
                    0130  ; Is immediate value a relative jump?
0CBD: 3A 8F A2      0131              LD   A,(iAsmOper)   ;Get operation number
0CC0: FE 1B         0132              CP   kDisJR         ;JR instruction ?
0CC2: 28 04         0133              JR   Z,@RelJp       ;Yes, so skip
0CC4: FE 1C         0134              CP   kDisDJNZ       ;DJNZ instruction ?
0CC6: 20 2C         0135              JR   NZ,@GetImmed   ;No, so skip
                    0136  ; Immediate value is a relative jump
0CC8: E5            0137  @RelJp:     PUSH HL             ;Preserve current opcode pointer
0CC9: 54            0138              LD   D,H            ;Get current address..
0CCA: 5D            0139              LD   E,L
0CCB: 13            0140              INC  DE             ;Increment to end of instruction
0CCC: 2A 96 A2      0141              LD   HL,(iAsmImmed) ;Get destination address..
0CCF: 7C            0142              LD   A,H            ;If the value entered is a single 
0CD0: B7            0143              OR   A              ;  byte we skip the calculation
0CD1: 7D            0144              LD   A,L            ;  and just use value supplied
0CD2: 28 1B         0145              JR   Z,@RelStore
0CD4: B7            0146              OR   A              ;Clear carry flag
0CD5: ED 52         0147              SBC  HL,DE          ;Calculate relative jump
                    0148  ; Trap jump which is too bog
0CD7: 38 0A         0149              JR   C,@RelJpNeg    ;Skip if negative displacement
0CD9: 7C            0150              LD   A,H            ;Get hi byte of displacement
0CDA: B7            0151              OR   A              ;0x00 ?
0CDB: 20 0E         0152              JR   NZ,@RelTooBig  ;No, so too big
0CDD: CB 7D         0153              BIT  7,L            ;Test if < 128
0CDF: 28 0D         0154              JR   Z,@RelJpOK     ;Skip if within range
0CE1: 18 08         0155              JR   @RelTooBig     ;Displacement too big
0CE3: 7C            0156  @RelJpNeg:  LD   A,H            ;Get hi byte of displacement
0CE4: 3C            0157              INC  A              ;0xFF ?
0CE5: 20 04         0158              JR   NZ,@RelTooBig  ;No, so too big
0CE7: CB 7D         0159              BIT  7,L            ;Test if > -128
0CE9: 20 03         0160              JR   NZ,@RelJpOK    ;Skip if within range
0CEB:               0161  @RelTooBig:
0CEB: E1            0161  @RelTooBig: POP  HL             ;Restore opcode pointer
0CEC: 18 1E         0162              JR   @TooBig        ;Return with error
0CEE: 7D            0163  @RelJpOK:   LD   A,L            ;Get relative jump
0CEF: E1            0164  @RelStore:  POP  HL             ;Restore opcode pointer
0CF0: 77            0165              LD   (HL),A         ;Store relative jump in memory
0CF1: 23            0166              INC  HL             ;Point to next opcode address
0CF2: 18 15         0167              JR   @NoImmed
                    0168  ; Immediate value is not a relative jump
                    0169  ; B = Length of immediate value in bytes (ie. 1 or 2)
0CF4: 78            0170  @GetImmed:  LD   A,B            ;Get length of immediate value
0CF5: FE 02         0171              CP   2              ;Two byte value?
0CF7: 28 06         0172              JR   Z,@WrImmed     ;Yes, so skip test for too big
0CF9: 3A 97 A2      0173              LD   A,(iAsmImmed+1)  ;Get hi byte of immediate value
0CFC: B7            0174              OR   A              ;Zero?
0CFD: 20 0D         0175              JR   NZ,@TooBig     ;No, so value is too big
0CFF: 11 96 A2      0176  @WrImmed:   LD   DE,iAsmImmed   ;Get address of immediate value
0D02: 1A            0177  @WrImLoop:  LD   A,(DE)         ;Get byte of immediate value
0D03: 77            0178              LD   (HL),A         ;Write to memory
0D04: 13            0179              INC  DE             ;Point to next byte of immediate value
0D05: 23            0180              INC  HL             ;Increment opcode pointer
0D06: 0C            0181              INC  C              ;Increment opcode counter
0D07: 10 F9         0182              DJNZ @WrImLoop      ;Loop until immediate is finished
0000:               0183  @NoImmed:
                    0184  ; Return with length of instruction or failure flag
0D09: 79            0185              LD   A,C            ;Return success A>0 and NZ flagged
0D0A: B7            0186              OR   A              ;  or error A=0 and Z flagged
0D0B: C9            0187              RET
                    0188  ; Return with failure flagged (immediate value to big)
0D0C: AF            0189  @TooBig:    XOR  A              ;Return error A=0 and Z flagged
0D0D: 3E 21         0190              LD   A,kMsgBadPar
0D0F: BF            0191              CP   A
0D10: C9            0192              RET
                    0193  ; Consider if displacement opcode should be stored here
0D11: 79            0194  @Displace:  LD   A,C            ;Get opcode counter
0D12: FE 02         0195              CP   2              ;Opcode byte 2?
0D14: C0            0196              RET  NZ             ;No, so return
0D15: 3A 9A A2      0197              LD   A,(iAsmDisFl)  ;Get opcode displacement flag
0D18: B7            0198              OR   A              ;Zero? (no displacement)
0D19: C8            0199              RET  Z              ;Yes, so return
0D1A: 3A 99 A2      0200              LD   A,(iAsmDisp)   ;Get displacement value
0D1D: 77            0201              LD   (HL),A         ;Store as opcode
0D1E: 23            0202              INC  HL             ;Increment opcode pointer
0D1F: 0C            0203              INC  C              ;Increment opcode counter
0D20: AF            0204              XOR  A              ;Clear A
0D21: 32 9A A2      0205              LD   (iAsmDisFl),A  ;Clear displacement flag
0D24: C9            0206              RET                 ;  as we've handled it
                    0207  
                    0208  
                    0209  ; **********************************************************************
                    0210  ; **  Private functions                                               **
                    0211  ; **********************************************************************
                    0212  
                    0213  
                    0214  ; Substitue index instruction (where appropriate)
                    0215  ;   On entry: HL = Start of operand string
                    0216  ;   On exit:  Operand string modified (where appropriate)
                    0217  ;             iAsmPri, iAsmImmed, iAsmLenIm updated
                    0218  ;             B IX IY I AF' BC' DE' HL' preserved
                    0219  ; Substitute "HL" for "IX" or "IY"
                    0220  ; Substitute "(HL)" for "(IX+d)" or "(IY+d)", and store displacement
                    0221  ;   except for JP instruction which does not have a displacement
                    0222  ; Substitute "-" for "(HL)" and thus also "(IX+d)" and "(IY+d)"
0D25:               0223  AsmSubsIndex:
0D25: 54            0224              LD   D,H            ;Remember start of operand..
0D26: 5D            0225              LD   E,L
                    0226  ; Is the operand string "(HL)" ?
0D27: 7E            0227              LD   A,(HL)         ;Get first character
0D28: FE 28         0228              CP   '('            ;Is it '(' ?
0D2A: 20 12         0229              JR   NZ,@NoBrac     ;No, so skip
0D2C: 23            0230              INC  HL             ;Point to second character
0D2D: 7E            0231              LD   A,(HL)         ;Get second character
0D2E: FE 48         0232              CP   'H'            ;Is it 'H' ?
0D30: 20 0C         0233              JR   NZ,@NoBrac     ;No, so skip
0D32: 23            0234              INC  HL             ;Point to third character
0D33: 7E            0235              LD   A,(HL)         ;Get third character
0D34: FE 4C         0236              CP   'L'            ;Is it 'L' ?
0D36: 20 06         0237              JR   NZ,@NoBrac     ;No, so skip
0D38: 23            0238              INC  HL             ;Point to fourth character
0D39: 7E            0239              LD   A,(HL)         ;Get fourth character
0D3A: FE 29         0240              CP   ')'            ;Is it ')' ?
0D3C: 28 3B         0241              JR   Z,@SubMinus    ;Yes, so we found "(HL)"
                    0242  ; Not "(HL)" so check for "IX", "IY" (can have leading bracket)
0D3E: FE 49         0243  @NoBrac:    CP   'I'            ;Operand character = 'I' ?
0D40: C0            0244              RET   NZ            ;No, so exit
0D41: 23            0245              INC  HL             ;Point to next character
                    0246  ;           PUSH BC
0D42: 0E 00         0247              LD   C,0            ;Default to no index
0D44: 7E            0248              LD   A,(HL)         ;Get next character
0D45: FE 58         0249              CP   'X'            ;Operand character = 'X' ?
0D47: 20 02         0250              JR   NZ,@NotIndX    ;No, so not index register X
0D49: 0E DD         0251              LD   C,0xDD         ;Store IX opcode
0D4B: FE 59         0252  @NotIndX:   CP   'Y'            ;Operand character = 'Y' ?
0D4D: 20 02         0253              JR   NZ,@NotIndY    ;No, so not index register Y
0D4F: 0E FD         0254              LD   C,0xFD         ;Store IX opcode
0D51: 79            0255  @NotIndY:   LD   A,C            ;Get index opcode (if there is one)
                    0256  ;           POP  BC
0D52: B7            0257              OR   A              ;Is this an index instruction?
0D53: C8            0258              RET  Z              ;No, so exit
                    0259  ; We found IX or IY, so replace with "HL"
0D54: 32 94 A2      0260              LD   (iAsmIndex),A  ;Store index opcode
0D57: 2B            0261              DEC  HL             ;Point to previous character ('I')
0D58: 36 48         0262              LD   (HL),'H'       ;Replace with 'H'
0D5A: 23            0263              INC  HL             ;Point to next character
0D5B: 36 4C         0264              LD   (HL),'L'       ;Replace with 'L'
                    0265  ; Now look for <+displacement> eg. "(IX+12)"
                    0266  ; Replacing with "-" and storing displacement value
0D5D: 3A 8F A2      0267              LD   A,(iAsmOper)   ;Get instruction number
0D60: FE 1E         0268              CP   kDisJP         ;JP instruction?
0D62: C8            0269              RET  Z              ;Yes, so abort as no displacement
0D63: 23            0270              INC  HL             ;Point to next character
0D64: 7E            0271              LD   A,(HL)         ;Get next character
0D65: FE 2B         0272              CP   '+'            ;Displacement to follow?
0D67: C0            0273              RET  NZ             ;No, so exit
                    0274  ; We are not bothering to raise an error for bad syntax here
                    0275  ; as it gets trapped later.
0D68: D5            0276              PUSH DE             ;Preserve start of operand string
0D69: 23            0277              INC  HL             ;Point to displacement string
0D6A: 54            0278              LD   D,H            ;Get address hi byte of string
0D6B: 5D            0279              LD   E,L            ;Get address lo byte of string
0D6C: CD 8A 07      0280              CALL ConvertStringToNumber
0D6F: 7D            0281              LD   A,L            ;Get lo byte of number
0D70: 32 99 A2      0282              LD   (iAsmDisp),A   ;Store as displacement
0D73: 3E FF         0283              LD   A,0xFF         ;Get value to use as flag
0D75: 32 9A A2      0284              LD   (iAsmDisFl),A  ;Flag displacement present
0D78: D1            0285              POP  DE             ;Restore start of operand string
                    0286  ; Store "-" in string instead of "(HL)" or "(IX+d)" or "(IY+d)"
                    0287  ; Except for JP (HL) or (IX) or (IY)
0D79: 3A 8F A2      0288  @SubMinus:  LD   A,(iAsmOper)   ;Get instruction number
0D7C: FE 1E         0289              CP   kDisJP         ;JP instruction?
0D7E: C8            0290              RET  Z              ;Yes, so abort
0D7F: 62            0291              LD   H,D            ;Restore to start of operand..
0D80: 6B            0292              LD   L,E
0D81: 36 2D         0293              LD   (HL),'-'       ;Replace operand string with "-"
0D83: 23            0294              INC  HL
0D84: 36 00         0295              LD   (HL),0         ;Terminate operand string
0D86: C9            0296  @NotInd:    RET
                    0297  
                    0298  
                    0299  ; Skip over delimiter
                    0300  ;   On entry: DE = Start of target string
                    0301  ;   On exit:  DE = Address of first non-delimiter or null
                    0302  ;             If null found then A=0 and Z flagged
                    0303  ;             If other non-delimiter found then A>0 and NZ flagged
                    0304  ;             BC HL IX IY I AF' BC' DE' HL' preserved
                    0305  ; A delimiter is a space, a comma or any control character other than null.
                    0306  ; The address returned can be that of the string's null terminator.
0D87:               0307  AsmSkipOverDelimiter:
0D87: 1A            0308  @Loop:      LD   A,(DE)         ;Get character from input line
0D88: B7            0309              OR   A              ;End of line (null)?
0D89: C8            0310              RET  Z              ;Yes, so return with Z flagged
0D8A: FE 2C         0311              CP   ','            ;Comma?
0D8C: 28 04         0312              JR   Z,@Next        ;Yes, so skip
0D8E: FE 21         0313              CP   kSpace+1       ;Character > space?
0D90: 30 03         0314              JR   NC,@Other      ;Yes, so skip
0D92: 13            0315  @Next:      INC  DE             ;No, so skip delimiter
0D93: 18 F2         0316              JR   @Loop          ;  and go try next character
0D95: B7            0317  @Other:     OR   A              ;Return NZ as non-delimiter other
0D96: C9            0318              RET                 ;  than null
                    0319  
                    0320  
                    0321  ; Skip to delimiter
                    0322  ;   On entry: DE = Start of target string
                    0323  ;   On exit:  DE = Address of first delimiter or null
                    0324  ;             If null found then A=0 and Z flagged
                    0325  ;             If delimiter found then A>0 but Z flag unknown
                    0326  ;             A=0 and Z flagged if non-delimter is not found
                    0327  ;             BC HL IX IY I AF' BC' DE' HL' preserved
                    0328  ; A delimiter is a space, a comma or any control character other than null.
                    0329  ; The address returned can be that of the string's null terminator.
0D97:               0330  AsmSkipToDelimiter:
0D97: 1A            0331  @Loop:      LD   A,(DE)         ;Get character from input line
0D98: B7            0332              OR   A              ;End of line (null)?
0D99: C8            0333              RET  Z              ;Yes, so return with Z flagged
0D9A: FE 2C         0334              CP   ','            ;Comma?
0D9C: C8            0335              RET  Z              ;Yes, so return with Z flagged
0D9D: FE 21         0336              CP   kSpace+1       ;Character > space?
0D9F: D8            0337              RET  C              ;No, so return with NZ flagged
0DA0: 13            0338  @Next:      INC  DE             ;Yes, so skip non-delimiter
0DA1: 18 F4         0339              JR   @Loop          ;  and go try next character
                    0340  
                    0341  
                    0342  ; Test if instruction matches table entry
                    0343  ;   On entry: IX = Instruction table entry address
                    0344  ;             iAsmOper = Operation string number
                    0345  ;             iAsmOp1 = Pointer to start of operand 1 string
                    0346  ;             iAsmOp2 = Pointer to start of operand 2 string
                    0347  ;   On exit:  If match found A = 0 and Z flagged
                    0348  ;             BC HL IX IY I AF' BC' DE' HL' preserved
                    0349  ;   Calls AsmTestOperand:
                    0350  ;             iAsmPri, iAsmImmed, iAsmLenIm updated
0DA3:               0351  AsmTestInstruction:
0DA3: 3A 8F A2      0352              LD   A,(iAsmOper)   ;Get operation string number
0DA6: DD BE 02      0353              CP   (IX+2)         ;Compare with table
0DA9: C0            0354              RET  NZ             ;Failed so return NZ
0DAA: ED 5B 90 A2   0355              LD   DE,(iAsmOp1)   ;Get address of operand 1 string
0DAE: DD 7E 03      0356              LD   A,(IX+3)       ;Get operand 1 string number
0DB1: E6 3F         0357              AND  0x3F           ;Mask away unwanted bits
0DB3: CD C6 0D      0358              CALL AsmTestOperand ;Test this operand
0DB6: C0            0359              RET  NZ             ;Failed so return NZ
0DB7: ED 5B 92 A2   0360              LD   DE,(iAsmOp2)   ;Get address of operand 2 string
0DBB: DD 7E 04      0361              LD   A,(IX+4)       ;Get operand 2 string number
0DBE: E6 3F         0362              AND  0x3F           ;Mask away unwabted bits
0DC0: CD C6 0D      0363              CALL AsmTestOperand ;Test this operand
0DC3: C0            0364              RET  NZ             ;Failed so return NZ
                    0365  ;           LD   (iAsmOp2),HL   ;Store result of operand 2
                    0366  ; Succeeded in finding instruction in table
0DC4: AF            0367  @Success:   XOR  A              ;Success so return Z
0DC5: C9            0368              RET
                    0369  
                    0370  
                    0371  ; Test if operand matches table entry
                    0372  ;   On entry: A = Operand string number from table
                    0373  ;             DE = Start of target operand string
                    0374  ;             IX = Instruction table entry address
                    0375  ;             iAsmOper = Operation string number
                    0376  ;             iAsmOp1 = Pointer to start of operand 1 string
                    0377  ;             iAsmOp2 = Pointer to start of operand 2 string
                    0378  ;   On exit:  If match found A = 0 and Z flagged
                    0379  ;             BC HL IX IY I AF' BC' DE' HL' preserved
                    0380  ;             iAsmPri, iAsmImmed, iAsmLenIm updated
0DC6:               0381  AsmTestOperand:
0DC6: 4F            0382              LD   C,A            ;Store string number from table
0DC7: FE 0E         0383              CP   kDisSubsL+1    ;Is operand a substitution string?
0DC9: 38 0E         0384              JR   C,@Subs        ;Yes, so skip
                    0385  ; Operand is a constant string which should be in string list
0DCB: 21 27 17      0386              LD   HL,DisString+1 ;Skip string 1 (blank string)
                    0387  ;           CALL SearchStringListNA
0DCE: CD 20 08      0388              CALL SearchStringList
0DD1: 28 6D         0389              JR   Z,@Failure     ;Not found so failure
0DD3: 3C            0390              INC  A              ;Adjust for first string number
0DD4: B9            0391              CP   C              ;Do strings match?
0DD5: 28 6D         0392              JR   Z,@Success     ;Yes, so we've found it
0DD7: 18 67         0393              JR   @Failure       ;No, so go return failure
                    0394  ; Operand in table is a substitution string
0DD9: FE 01         0395  @Subs:      CP   1              ;String 1 = ""
0DDB: 20 03         0396              JR   NZ,@NotNull
0DDD: 1A            0397              LD   A,(DE)         ;Get operand's first character
0DDE: B7            0398              OR   A              ;Null
0DDF: C8            0399              RET  Z              ;Yes, so return success
0000:               0400  @NotNull:
                    0401  ; Calculate operand table location for this operand and get details
0DE0: 21 02 17      0402              LD   HL,DisOperandTable-2
0DE3: 87            0403              ADD  A,A            ;Two bytes per entry
0DE4: 85            0404              ADD  A,L            ;Add to start of table
0DE5: 6F            0405              LD   L,A            ;Store updated lo byte
0DE6: 30 01         0406              JR   NC,@NoOverFlo  ;Skip if no overflow
0DE8: 24            0407              INC  H              ;Overflow so increment hi byte
0DE9:               0408  @NoOverFlo:
0DE9: 4E            0408  @NoOverFlo: LD   C,(HL)         ;Get substitution string number
0DEA: 23            0409              INC  HL             ;Point to BIILMM bits
0DEB: 46            0410              LD   B,(HL)         ;Get BIILMM function bits
                    0411  ;           PUSH DE             ;So we can use E for scratch reg
                    0412  ; Process this operand as detailed in DE, left bracket?
0DEC: CB 68         0413              BIT  kDisBrack,B    ;Bracket flagged?
0DEE: 28 06         0414              JR   Z,@NoBracL     ;No, so skip
0DF0: 1A            0415              LD   A,(DE)         ;Get char from target string
0DF1: 13            0416              INC  DE             ;Point to next char in target
0DF2: FE 28         0417              CP   A,'('          ;Is it a left bracket character?
0DF4: 20 4A         0418              JR   NZ,@Failure
0000:               0419  @NoBracL:   
                    0420  ; Process this operand as detailed in BC, immediate value?
0DF6: CB 60         0421              BIT  kDisImmed,B    ;Immediate value flagged?
0DF8: 28 12         0422              JR   Z,@NoImmedia   ;No, so skip
0DFA: CD 8A 07      0423              CALL ConvertStringToNumber
0DFD: 20 41         0424              JR   NZ,@Failure
0DFF: 22 96 A2      0425              LD   (iAsmImmed),HL ;Store immediate value
0E02: 3E 01         0426              LD   A,1
0E04: CB 58         0427              BIT  kDisWord,B     ;Immediate value is a word?
0E06: 28 01         0428              JR   Z,@ImmedLo     ;No, so skip
0E08: 3C            0429              INC  A              ;Increment offset to hi byte
0E09: 32 98 A2      0430  @ImmedLo:   LD   (iAsmLenIm),A  ;Store length of immediate value
0E0C:               0431  @NoImmedia:
                    0432  ; Process this operand as detailed in DE, right bracket?
0E0C: CB 68         0433              BIT  kDisBrack,B    ;Bracket flagged?
0E0E: 28 06         0434              JR   Z,@NoBracR     ;No, so skip
0E10: 1A            0435              LD   A,(DE)         ;Get char from target string
0E11: 13            0436              INC  DE             ;Point to next char in target
0E12: FE 29         0437              CP   A,')'          ;Is it a left bracket character?
0E14: 20 2A         0438              JR   NZ,@Failure
0000:               0439  @NoBracR:   
                    0440  ; Process this operand as detailed in DE, substitution string?
0E16: 79            0441              LD   A,C            ;Get substitution string number?
0E17: B7            0442              OR   A              ;Substitution string?
0E18: 28 2A         0443              JR   Z,@Success     ;No, so we've finished
                    0444  ; A = Substitution string number eg. "CDEHL-A"
                    0445  ; Find the substitution string and search it for target string
0E1A: 21 26 17      0446              LD   HL,DisString   ;Start of disassembler's string list
0E1D: CD F6 07      0447              CALL FindStringInList ;Set HL=Start of substitution string
0E20: CD 46 0E      0448              CALL @Instring      ;Look for target in subs string
0E23: 20 1B         0449              JR   NZ,@Failure
                    0450  ; C = Target string's position in substitution string (0 to 3)
                    0451  ; B = Function bits BIILMM from DisOperandTable
                    0452  ; Convert position to bit pattern for instruction opcode
                    0453  ; Do this by shifting bits right as many times as it takes to shift
                    0454  ; right the mask, from masktable, to get a one in the carry flag.
0E25: 78            0455              LD   A,B            ;Get BIILMM function bits
0E26: E6 03         0456              AND  A,kDisMask     ;Separate mask type bits
0E28: 21 1E 17      0457              LD   HL,DisMaskTable  ;Point to table of mask bits
0E2B: 85            0458              ADD  A,L            ;Add to start of table
0E2C: 6F            0459              LD   L,A            ;Store updated lo byte
0E2D: 30 01         0460              JR   NC,@NoOFlow    ;Skip if no overflow
0E2F: 24            0461              INC  H              ;Overflow so increment hi byte
0E30: 46            0462  @NoOFlow:   LD   B,(HL)         ;Get bit mask from mask table
0E31: 79            0463              LD   A,C            ;Get position in string
0E32:               0464  @SubsShift:
0E32: CB 38         0464  @SubsShift: SRL  B              ;Shift mask right
0E34: 38 03         0465              JR   C,@DoneShift   ;If bit 1 was set then we're done
0E36: 07            0466              RLCA                ;Shift position/opcode bits left
0E37: 18 F9         0467              JR   @SubsShift     ;Go repeat..
0E39:               0468  @DoneShift:
0E39: 21 95 A2      0468  @DoneShift: LD   HL,iAsmPri     ;Point to primary opcode bits
0E3C: B6            0469              OR   (HL)           ;Include new bits
0E3D: 77            0470              LD   (HL),A         ;Store primary opcode bits
0E3E: 18 04         0471              JR   @Success
                    0472  ; Failed to find operand in table etc
0E40: 3E FF         0473  @Failure:   LD   A,0xFF
0E42: B7            0474              OR   A              ;Failure so return NZ
0E43: C9            0475              RET
                    0476  ; Succeeded in finding operand in table
0E44: AF            0477  @Success:   XOR  A              ;Success so return Z
0E45: C9            0478              RET
                    0479  
                    0480  
                    0481  ; Instring function
                    0482  ;   On entry: A = Substitution string number
                    0483  ;             DE = Start of target string (1 or 2 characters)
                    0484  ;             HL = Start of substitution string
                    0485  ;   On exit:  If match found Z flagged, and
                    0486  ;               C = Position in substitution string (0 to 3)
                    0487  ;             B IX IY I AF' BC' DE' HL' preserved
                    0488  ; Subroutine to look for target string (DE) is substitution string (HL)
                    0489  ; Substitution string may be something like this: "BCDEHL-A"
                    0490  ; Target string may be something like "BC"<null>
                    0491  ; Substitution strings are delimited by first character having bit 7 set
                    0492  ; Target strings can be one or two characters long and null terminated
0000:               0493  @Instring:  
                    0494  ; Special handling for RST instruction
0E46: FE 13         0495              CP   0x13           ;Substution of RST address?
0E48: 20 1C         0496              JR   NZ,@InStNotRST ;Skip if not RST instruction
0E4A: E5            0497              PUSH HL
0E4B: CD 8A 07      0498              CALL ConvertStringToNumber  ;Convert string at DE
0E4E: 7D            0499              LD   A,L            ;Get operand
0E4F: CD 51 07      0500              CALL ConvertByteToNibbles
0E52: 7A            0501              LD   A,D            ;Get MSByte of operand
0E53: F6 30         0502              OR   '0'            ;Convert to ASCII
0E55: 32 F0 A1      0503              LD   (kStrBuffer+$70),A ;Store in temporary space
0E58: 7B            0504              LD   A,E            ;Get MSByte of operand
0E59: F6 30         0505              OR   '0'            ;Convert to ASCII
0E5B: 32 F1 A1      0506              LD   (kStrBuffer+$71),A ;Store in temporary space
0E5E: AF            0507              XOR  A              ;Clear A as string terminator
0E5F: 32 F2 A1      0508              LD   (kStrBuffer+$72),A ;StoreRST 00 in temporary space
0E62: 11 F0 A1      0509              LD   DE,kStrBuffer+$70
0E65: E1            0510              POP  HL
0E66:               0511  @InStNotRST:
                    0512  ; Handle standard formats
0E66: 0E FF         0513              LD   C,0xFF         ;Count poisition in subs string
0E68: CB 50         0514              BIT  kDisLength,B   ;Two character substitution
0E6A: 20 0D         0515              JR   NZ,@Instr2     ;Yes, so go..
                    0516  ; Single byte target string
0E6C: 0C            0517  @NextS1:    INC  C              ;Count position in subs string
0E6D: 1A            0518              LD   A,(DE)         ;Get character from target string
0E6E: AE            0519              XOR  (HL)           ;Compare with char from subs string
0E6F: E6 7F         0520              AND  0x7F           ;Mask off start of string bit
0E71: 28 2B         0521              JR   Z,@InstrOK     ;Skip if characters match
0E73: 23            0522              INC  HL             ;Try next character in subs string
0E74: CB 7E         0523              BIT  7,(HL)         ;End of substitution string?
0E76: 28 F4         0524              JR   Z,@NextS1      ;No, so try next character
0E78: C9            0525              RET                 ;Return failure (NZ flagged)
                    0526  ; Two byte target string
0E79: 0C            0527  @Instr2:    INC  C              ;Count position in subs string
0E7A: 1A            0528              LD   A,(DE)         ;Get character from target string
0E7B: FE 48         0529              CP   'H'            ;Substitute '*' for 'H'...
0E7D: 20 02         0530              JR   NZ,@NotH
0E7F: 3E 2A         0531              LD   A,'*'
0E81: AE            0532  @NotH:      XOR  (HL)           ;Compare with char from subs string
0E82: E6 7F         0533              AND  0x7F           ;Mask off start of string bit
0E84: 23            0534              INC  HL             ;Prepare to try next char in subs
0E85: 20 11         0535              JR   NZ,@InstrN1    ;Skip if chars don't match
0E87: 13            0536              INC  DE             ;Compare with second char in target
0E88: 1A            0537              LD   A,(DE)         ;Get character from target string
0E89: FE 4C         0538              CP   'L'            ;Substitute '*' for 'L'...
0E8B: 20 02         0539              JR   NZ,@NotL
0E8D: 3E 2A         0540              LD   A,'*'
0E8F: AE            0541  @NotL:      XOR  (HL)           ;Compare with char from subs string
0E90: 28 0C         0542              JR   Z,@InstrOK     ;Characters match so go..
0E92: 1B            0543              DEC  DE             ;Compare with first char in target
0E93: 7E            0544              LD   A,(HL)         ;Check if subs is a null character
0E94: FE 2E         0545              CP   '.'            ;  represented by a '.'
0E96: 28 06         0546              JR   Z,@InstrOK     ;Yes, so go..
0E98: 23            0547  @InstrN1:   INC  HL             ;Point to next pair in subs string
0E99:               0548  @InstrNext:
0E99: CB 7E         0548  @InstrNext: BIT  7,(HL)         ;End of substitution string?
0E9B: 28 DC         0549              JR   Z,@Instr2      ;No, so try next character
0E9D: C9            0550              RET                 ;Return failure (NZ flagged)
                    0551  ; Strings match so check there are no more chars in target string
0E9E: 13            0552  @InstrOK:   INC  DE             ;Check next char in target is null
0E9F: 1A            0553              LD   A,(DE)         ;Get character from target string
0EA0: B7            0554              OR   A              ;Null?
0EA1: C9            0555              RET                 ;Yes, so return success(Z)/failure(NZ)
                    0556  
                    0557  
                    0558  ; **********************************************************************
                    0559  ; **  Private workspace (in RAM)                                      **
                    0560  ; **********************************************************************
                    0561  
                    0562              .DATA
                    0563  
A28F: 00            0564  iAsmOper:   .DB  0              ;Instruction operation number
A290: 00 00         0565  iAsmOp1:    .DW  0              ;Instruction operand 1 number
A292: 00 00         0566  iAsmOp2:    .DW  0              ;Instruction operand 2 number
A294: 00            0567  iAsmIndex:  .DB  0              ;Index instruction opcode
A295: 00            0568  iAsmPri:    .DB  0              ;Primary opcode
A296: 00 00         0569  iAsmImmed:  .DW  0              ;Immediate value
A298: 00            0570  iAsmLenIm:  .DB  0              ;Length of immedaite value
A299: 00            0571  iAsmDisp:   .DB  0              ;Displacement value
A29A: 00            0572  iAsmDisFl:  .DB  0              ;Displacement flag
                    0573  
                    0574  
                    0575  ; **********************************************************************
                    0576  ; **  End of Assembler support module                                 **
                    0577  ; **********************************************************************
                    0578  
                    0057  #ENDIF
                    0058  #IFDEF      IncludeBreakpoint
                    0059  #INCLUDE    Monitor\Breakpoint.asm  ;Breakpoint handler
                    0001  ; **********************************************************************
                    0002  ; **  Breakpoint Support                        by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides breakpoint and single stepping support.
                    0006  ;
                    0007  ; Limitations of breakpoints and single step:
                    0008  ;
                    0009  ; You can't set breakpoints in read only memory. As a result you can't
                    0010  ; single step through code in read only memory.
                    0011  ;
                    0012  ; Single stepping code in the monitor itself is problematic so it is
                    0013  ; prevented. To achieve this any instruction trying to call or jump
                    0014  ; into the monitor is not stepped, but instead the instruction after
                    0015  ; is trapped. As a result calls into the monitor are stepped over.
                    0016  ; To achieve this for the monitor's API etc we also step over calls 
                    0017  ; and jumps to the address range 0x0000 to 0x00FF.
                    0018  ;
                    0019  ; An instruction that jumps to itself will never run if you attempt to
                    0020  ; single step it. For examples:
                    0021  ;   Loop:  JP Loop
                    0022  ;   Loop:  DJNZ Loop
                    0023  ; Single step does not run the instruction as a breakproint is set there
                    0024  ; each time you try to step. The only case this is likely to be an issue
                    0025  ; is where DJNZ loops back to itself to create a short delay.
                    0026  ;
                    0027  ; Public functions provided:
                    0028  ;   BPInitialise          Initialise the breakpoint module
                    0029  ;   BPHandler             Code executed when breakpoint encountered
                    0030  ;   BPReqSet              Clear set the requested breakpoint address
                    0031  ;   BPReqClr              Clear the requested breakpoint address
                    0032  ;   BPGo                  Breakpoint: Jump here for Go command
                    0033  ;   BPStep                Breakpoint: Jump here for Step command
                    0034  ;   BPIsInMonitor         Is address in monitor code?
                    0035  
                    0036  
                    0037  ; **********************************************************************
                    0038  ; **  Constants                                                       **
                    0039  ; **********************************************************************
                    0040  
00EF:               0041  kBPOpcode:  .EQU 0xEF           ;Breakpoint restart = RST 0x28
A29B:               0042  kBPAddress:
                    0042  kBPAddress: .EQU 0x28           ;Breakpoint reset address = 0x28
                    0043  
                    0044  
                    0045  ; **********************************************************************
                    0046  ; **  Public functions                                                **
                    0047  ; **********************************************************************
                    0048  
                    0049              .CODE
                    0050  
                    0051  ; Breakpoint: Initialise this module
                    0052  ;   On entry: No parameters required
                    0053  ;   On exit:  BC IX IY I AF' BC' DE' HL' preserved
0EA2:               0054  BPInitialise:
0EA2: CD AA 0F      0055              CALL BPClear        ;Clear breakpoint from memory
0EA5: CD 68 0F      0056              CALL BPReqClr       ;Clear requested breakpoint address
0EA8: 21 28 00      0057              LD   HL,kBPAddress  ;Address of breakpoint restart
0EAB: 36 C3         0058              LD   (HL),0xC3      ;Write JP instruction at restart
0EAD: 23            0059              INC  HL             ;Increment address pointer
0EAE: 11 B5 0E      0060              LD   DE,BPHandler   ;Write address of breakpoint handler
0EB1: 73            0061              LD   (HL),E         ;  at restart...
0EB2: 23            0062              INC  HL             ;  Should use LD (HL),BPHandler/256 etc
0EB3: 72            0063              LD   (HL),D         ;  but homebrew assembler fails at that
0EB4: C9            0064              RET                 ;  TODO fix the assembler!
                    0065  
                    0066  
                    0067  ; Breakpoint: Breakpoint handler
                    0068  ; Directed here when suitable breakpoint is encountered
0000:               0069  BPHandler:
                    0070  ; Store state of processor
0EB5: ED 43 77 A2   0071              LD   (iBC),BC       ;Store BC
0EB9: ED 53 79 A2   0072              LD   (iDE),DE       ;Store DE
0EBD: 22 7B A2      0073              LD   (iHL),HL       ;Store HL
0EC0: DD 22 7D A2   0074              LD   (iIX),IX       ;Store IX
0EC4: FD 22 7F A2   0075              LD   (iIY),IY       ;Store IY
0EC8: E1            0076              POP  HL             ;Get address of breakpoint + 1
0EC9: 2B            0077              DEC  HL             ;Adjust to address of breakpoint
0ECA: 22 73 A2      0078              LD   (iPC),HL       ;Store address of breakpoint
0ECD: ED 73 81 A2   0079              LD   (iSP),SP       ;Store stack pointer at breakpoint
0ED1: E3            0080              EX   (SP),HL
0ED2: 22 8B A2      0081              LD   (iCSP),HL      ;Store contents of SP
0ED5: E3            0082              EX   (SP),HL
0ED6: F5            0083              PUSH AF             ;Copy AF to HL...
0ED7: E1            0084              POP  HL             ;  and store AF value
0ED8: 22 75 A2      0085              LD   (iAF),HL       ;Store AF
0EDB: ED 57         0086              LD   A,I
0EDD: 32 8E A2      0087              LD   (iIR+1),A      ;Store I register
0EE0: ED 5F         0088              LD   A,R
0EE2: 32 8D A2      0089              LD   (iIR),A        ;Store R register
                    0090  ; Stack pointer now same value as it was before the breakpoint's restart
                    0091  ; What caused this breakpoint?
0EE5: 2A 73 A2      0092              LD   HL,(iPC)       ;Did breakpoint restart occur at
0EE8: 7D            0093              LD   A,L            ;  the current breakpoint?
0EE9: 54            0094              LD   D,H            ;  ie. PC=BP 
0EEA: 2A 9B A2      0095              LD   HL,(iBPAddr)
0EED: BD            0096              CP   L              ;LSBytes equal
0EEE: 20 12         0097              JR   NZ,@Trap       ;No, so TRAP
0EF0: 7A            0098              LD   A,D
0EF1: BC            0099              CP   H              ;MSBytes equal
0EF2: 20 0E         0100              JR   NZ,@Trap       ;No, so TRAP
                    0101  ; A Restart 28 instruction was encountered at the breakpoint addr
0EF4: CD AA 0F      0102              CALL BPClear
0EF7: 3A 9E A2      0103              LD   A,(iBPType)    ;Get breakpoint type
0EFA: B7            0104              OR   A              ;Type 0 = Once?
0EFB: 20 0B         0105              JR   NZ,@Reg        ;No, so may be single stepping
0EFD: 11 DA 0F      0106              LD   DE,szBreak     ;Point to message "Breakpoint"
0F00: 18 03         0107              JR   @Msg
                    0108  ; A Restart 28 instruction was encountered but not the breakpoint
0F02: 11 E6 0F      0109  @Trap:      LD   DE,szTrap      ;Point to message "Trap"
0F05: CD EE 04      0110  @Msg:       CALL OutputZString  ;Output message
                    0111  ; Output register values as they were at the breakpoint
0F08: CD B4 08      0112  @Reg:       CALL WrRegister1    ;Build primary register line
0F0B: CD A7 06      0113              CALL StrPrint       ;Output primary register line
                    0114              ;CALL WrRegister2   ;Build secondary register line
                    0115              ;CALL StrPrint      ;Output secondary register line
                    0116  #IFDEF      IncludeDisassemble
                    0117  ; Disassemble this instruction and output it
                    0118  ; Stack pointer now same value as it was before the breakpoint's restart
0F0E: 3A 9E A2      0119              LD   A,(iBPType)    ;Get breakpoint type
0F11: B7            0120              OR   A              ;Type 0 = Once?
0F12: CA 03 01      0121              JP   Z,WarmStart    ;Yes, so do not set another breakpoint
                    0122  ; Single step mode, so wait for user key press
0F15: CD BD 03      0123              CALL InputMore      ;Print more?
0F18: C2 03 01      0124              JP   NZ,WarmStart   ;No, so exit
                    0125  ; Prepare to step next instruction
0F1B: 2A 73 A2      0126              LD   HL,(iPC)       ;Get current address
0F1E: CD 4E 14      0127              CALL DisWrInstruction ;Disassemble instruction
0F21: 54            0128              LD   D,H            ;Store address of next instruction
0F22: 5D            0129              LD   E,L            ;  (the one immediately after this)
0F23: CD 1A 07      0130              CALL StrWrNewLine   ;Write new line to string buffer
0F26: CD A7 06      0131              CALL StrPrint       ;Print to output device
0F29: CD 55 15      0132              CALL DisGetNextAddress  ;Get PC after executing this inst
                    0133  ; Catch jumps and calls into the monitor code and bottom 256 bytes
                    0134  ; as we can't step reliably through code in the monitor itself
                    0135  ; Also we trap the end of user program when it returns to monitor
                    0136  ;           LD   A,H            ;Get hi byte of address of next inst
                    0137  ;           OR   A              ;Is next inst in bottom 256 bytes?
                    0138  ;           JR   Z,@StepOver    ;Yes, so step over this instruction
0F2C: CD CC 0F      0139              CALL BPIsInMonitor  ;Next instruction within monitor code?
0F2F: 28 05         0140              JR   Z,@StepOver    ;Yes, so step over this instruction
                    0141  ; Attempt to follow this instruction (ie. follow jumps etc)
0F31: CD 90 0F      0142              CALL BPSet          ;Attempt to set breakpoint here
0F34: 28 0C         0143              JR   Z,@SetOK       ;Set ok (ie in RAM) so skip
                    0144  ; Attempt to step over this instruction (ie. don't follow jumps etc)
                    0145  ; as we can't step through ROM code or reliably through monitor code
0F36: 62            0146  @StepOver:  LD   H,D            ;Get address after this instruction
0F37: 6B            0147              LD   L,E            ;  as we can't step into ROM
0F38: 11 EC 0F      0148              LD   DE,szOver
0F3B: CD EE 04      0149              CALL OutputZString  ;Output "Stepping over..."
0F3E: CD 90 0F      0150              CALL BPSet          ;Attempt to set breakpoint here
0F41: C0            0151              RET  NZ             ;Abort as failed so set (not in RAM)
                    0152  ; Brakpoint set for next step ok
0000:               0153  @SetOK:
                    0154  #ELSE
                    0155  ; No disassembler so just display address and hex bytes
                    0156  ; Stack pointer now same value as it was before the breakpoint's restart
                    0157              CALL StrInitDefault ;Initialise default string buffer
                    0158              LD   DE,(iPC)       ;Get current address
                    0159              CALL StrWrHexWord   ;Display breakpoint address
                    0160              LD   A,':'
                    0161              CALL StrWrChar      ;Print ':'
                    0162              LD   A,4            ;Get length of instruction 
                    0163              LD   B,A
                    0164              LD   L,A
                    0165  @Loop:      CALL StrWrSpace
                    0166              LD   A,(DE)         ;Read byte at PC
                    0167              CALL StrWrHexByte
                    0168              INC  DE
                    0169              DJNZ @Loop
                    0170              LD   A,5            ;TAB cursor..
                    0171              SUB  L
                    0172              LD   L,A
                    0173              ADD  L
                    0174              ADD  L
                    0175              CALL StrWrSpaces    ;Display A spaces
                    0176              LD   A,'?'
                    0177              CALL StrWrChar      ;Print '?' (no disassembly)
                    0178              CALL StrWrNewLine
                    0179              CALL StrPrint       ;Print to output device
                    0180              RET
                    0181  #ENDIF
                    0182  ; Restore state of processor
                    0183  ; Stack pointer now same value as it was before the breakpoint's restart
0F42: 3A 8E A2      0184  BPRestore:  LD   A,(iIR+1)      ;Get value or I register
0F45: ED 47         0185              LD   I,A            ;Retore I register
                    0186  ;           LD   A,(iIR)        ;Don't restore R as it is free 
                    0187  ;           LD   R,A            ;  running refresh counter
0F47: 2A 75 A2      0188              LD   HL,(iAF)       ;Get value of AF registers
0F4A: E5            0189              PUSH HL
0F4B: F1            0190              POP  AF             ;Restore AF
0F4C: ED 7B 81 A2   0191              LD   SP,(iSP)       ;Restore SP
0F50: 2A 73 A2      0192              LD   HL,(iPC)       ;Get value of PC register
0F53: E5            0193              PUSH HL             ;Put continuation address on stack
0F54: FD 2A 7F A2   0194              LD   IY,(iIY)       ;Restore IY
0F58: DD 2A 7D A2   0195              LD   IX,(iIX)       ;Restore IX
0F5C: 2A 7B A2      0196              LD   HL,(iHL)       ;Restore HL
0F5F: ED 5B 79 A2   0197              LD   DE,(iDE)       ;Restore DE
0F63: ED 4B 77 A2   0198              LD   BC,(iBC)       ;Restore BC
0F67: C9            0199              RET                 ;Return to continuation address
                    0200  
                    0201  
                    0202  ; Clear or set the requested breakpoint address
                    0203  ; This does not actually set or clear the breakpoint in memory
                    0204  ; The actually breakpoint is manipulated at reset, Go or Step
                    0205  ;   On entry: HL = Breakpoint address required
                    0206  ;   On exit:  BC DE IX IY I AF' BC' DE' HL' preserved
0F68: 21 00 00      0207  BPReqClr:   LD   HL,0           ;Address zero indicates no BP request
0F6B: 18 04         0208              JR   BPWrAddr       ;Go clear the breakpoint request
                    0209  ;   On entry: HL = Breakpoint address required
                    0210  ;   On exit:  If successful NZ flagged
                    0211  ;             It can fail (Z flagged) if address is in monitor code
                    0212  ;             BC DE IX IY I AF' BC' DE' HL' preserved
0F6D: CD CC 0F      0213  BPReqSet:   CALL BPIsInMonitor  ;Is address HL in monitor code are
0F70: C8            0214              RET  Z              ;Yes, so return with Z flagged
0F71: 22 9F A2      0215  BPWrAddr:   LD   (iBPReq),HL    ;Store as requested BP address
0F74: C9            0216              RET                 ;Return NZ for successfully Set 
                    0217  
                    0218  
                    0219  ; Breakpoint: Jump here for Go command
0F75: AF            0220  BPGo:       XOR  A              ;Set for breakpoint mode
0F76: 32 9E A2      0221              LD   (iBPType),A    ;  not single step mode
0F79: 2A 9F A2      0222              LD   HL,(iBPReq)    ;Get requested breakpoint address
0F7C: CD 90 0F      0223              CALL BPSet          ;Set the requested breakpoint 
0F7F: C3 42 0F      0224              JP   BPRestore      ;Restore registers from variables
                    0225  
                    0226  
                    0227  ; Breakpoint: Jump here for Step command
0F82: 3E 01         0228  BPStep:     LD   A,1            ;Set for single step mode
0F84: 32 9E A2      0229              LD   (iBPType),A    ;  not breakpoint mode
0F87: 2A 73 A2      0230              LD   HL,(iPC)       ;Get next instruction address
0F8A: CD 90 0F      0231              CALL BPSet          ;Set the requested breakpoint 
0F8D: C3 42 0F      0232              JP   BPRestore      ;Restore registers from variables
                    0233  
                    0234  
                    0235  ; **********************************************************************
                    0236  ; **  Private functions                                               **
                    0237  ; **********************************************************************
                    0238  
                    0239  
                    0240  ; Breakpoint: Set breakpoint
                    0241  ;   On entry: HL = Address of breakpoint
                    0242  ;   On exit:  If successful A = 0 and Z flagged
                    0243  ;               otherwise A != 0 and NZ flagged
                    0244  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0245  ; Failure can occur when trying to set breakpoint to address which is 
                    0246  ; not RAM.
0F90: CD AA 0F      0247  BPSet:      CALL BPClear        ;Ensure previous breakpoint removed
0F93: 7C            0248              LD   A,H            ;Check if requested address is 0x0000
0F94: B5            0249              OR   L              ;  and if so abort as nothing to do
0F95: C8            0250              RET  Z
0F96: 7E            0251              LD   A,(HL)         ;Get contents of breakpoint address
0F97: 32 9D A2      0252              LD   (iBPData),A    ;Store as breakpoint data
0F9A: 36 EF         0253              LD   (HL),kBPOpcode ;Write breakpoint opcode to address
0F9C: 7E            0254              LD   A,(HL)         ;Read back to see if in RAM
0F9D: FE EF         0255              CP   kBPOpcode      ;Is it the breakpoint opcode?
0F9F: 20 05         0256              JR   NZ,@Failure    ;No, so failed to set
0FA1: 22 9B A2      0257              LD   (iBPAddr),HL   ;Store requested breakpoint address
0FA4: AF            0258              XOR  A              ;Return success A = 0 and Z flagged
0FA5: C9            0259              RET
0FA6: 3E FF         0260  @Failure:   LD   A,0xFF         ;Return failure A != 0 and NZ flagged
0FA8: B7            0261              OR   A
0FA9: C9            0262              RET
                    0263  
                    0264  
                    0265  ; Breakpoint: Clear breakpoint
                    0266  ;   On entry: No parameters required
                    0267  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
0FAA: F5            0268  BPClear:    PUSH AF
0FAB: E5            0269              PUSH HL
0FAC: 2A 9B A2      0270              LD   HL,(iBPAddr)   ;Get current breakpoint address
0FAF: 7D            0271              LD   A,L            ;Test if breakpoint address is 0xFFFF
0FB0: A4            0272              AND  H              ;If it is 0xFFFF then breakpoint is not set
0FB1: FE FF         0273              CP   0xFF           ;Breakpoint set?
0FB3: 28 0F         0274              JR   Z,@ClrData     ;No, so skip breakpoint clear
0FB5: 7E            0275              LD   A,(HL)         ;Test if breakpoint contains breakpoint opcode
0FB6: FE EF         0276              CP   kBPOpcode      ;If it is then breakpoint is not set
0FB8: 20 04         0277              JR   NZ,@ClrAddr    ;No, so skip breakpoint clear
                    0278  ; Breakpoint is currently set, so restore memory contents and clear BP
0FBA: 3A 9D A2      0279              LD   A,(iBPData)    ;Restore original contents of memory at current
0FBD: 77            0280              LD   (HL),A         ;  breakpoint address to remove breakpoint opcode
0FBE: 21 FF FF      0281  @ClrAddr:   LD   HL,0xFFFF      ;Get value indicating break address is not set
0FC1: 22 9B A2      0282              LD   (iBPAddr),HL   ;Store as breakpoint address to incicate not set
0FC4: 3E EF         0283  @ClrData:   LD   A,kBPOpcode    ;Get value indicating break data is not set
0FC6: 32 9D A2      0284              LD   (iBPData),A    ;Store as breakpoint data to incicate not set
0FC9: E1            0285              POP HL
0FCA: F1            0286              POP AF
0FCB: C9            0287              RET
                    0288  
                    0289  
                    0290  ; Breakpoint: Is address in monitor code space?
                    0291  ;   On entry: HL = Memory address to be tested
                    0292  ;   On exit:  If address is in monitor code Z flagged
                    0293  ;               otherwise NZ flagged
                    0294  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0295  ; Only test the most significant byte of the address. This is fine
                    0296  ; for the start of the monitor code which is assumed to be on a 256
                    0297  ; byte boundary. But the end of the monitor code will be treated as
                    0298  ; entending to the end of the 256 byte boundry it is in.
0FCC:               0299  BPIsInMonitor:
0FCC: 7C            0300              LD   A,H            ;Get hi byte of address to be tested
0FCD: B7            0301              OR   A              ;Is it 0x00? (address 0x0000 to 0x00FF
0FCE: C8            0302              RET  Z              ;Yes, so return Z
                    0303  ; H is not 0x00
0FCF: 3E 1B         0304              LD   A,EndOfMonitor\256
0FD1: BC            0305              CP   H              ;Compare with hi byte of address
                    0306  ;           RET  Z              ;Return Z if H = monitor end
0FD2: D8            0307              RET  C              ;Return NZ if > monitor end
                    0308  ; H is now known to be less than or equal to monitor end address
0FD3: 3E 00         0309              LD   A,StartOfMonitor\256
0FD5: BC            0310              CP   H              ;Compare with hi byte of address
0FD6: C8            0311              RET  Z              ;Return Z if H = monitor start
0FD7: D0            0312              RET  NC             ;Return NZ if H < monitor start
                    0313  ; H is now known to be greater than monitor start (also H <= end)
0FD8: AF            0314              XOR  A              ;Return Z as address in monitor code
0FD9: C9            0315              RET
                    0316  
                    0317  
                    0318  ; **********************************************************************
                    0319  ; **  Constant data                                                   **
                    0320  ; **********************************************************************
                    0321  
0FDA: 42 72 65 61   0322  szBreak:    .DB  "Breakpoint",kNewLine,kNull
0FDE: 6B 70 ...     3900  
0FE6: 54 72 61 70   0323  szTrap:     .DB  "Trap",kNewLine,kNull
0FEA: 05 00         3901  
0FEC: 53 74 65 70   0324  szOver:     .DB  "Stepping over code in ROM or in monitor",kNewLine,kNull
0FF0: 70 69 ...     3902  
                    0325  
                    0326  
                    0327  ; **********************************************************************
                    0328  ; **  Private workspace (in RAM)                                      **
                    0329  ; **********************************************************************
                    0330  
                    0331              .DATA
                    0332  
A29B: 00 00         0333  iBPAddr:    .DW  0x0000         ;Breakpoint address
A29D: 00            0334  iBPData:    .DB  0x00           ;Breakpoint data (contents of BP address)
A29E: 00            0335  iBPType:    .DB  0x00           ;Breakpoint type: 0=Once, 1=Step
A29F: 00 00         0336  iBPReq:     .DW  0x0000         ;Breakpoint address request
                    0337  
                    0338  
                    0339  ; To set a breakpoint or single step break, call xxx 
                    0340  ; This address is held in iBPReq.
                    0341  ; When a program run or continue is required...
                    0342  
                    0343  
                    0344  ; Instructions which can change flow of code (ie. alter PC)
                    0345  ;   DJNZ d          10 nn      0001 0000
                    0346  ;   JR   d          18 nn      0001 1000
                    0347  ;   JR   c,  d      xx nn      001c c000
                    0348  ;   JP   nn         C3 nn nn   1100 0011
                    0349  ;   JP   cc, nn     xx nn nn   11cc c010
                    0350  ;   JP   HL         E9         1110 1001
                    0351  ;   JP   IX         DD E9      1110 1001
                    0352  ;   JP   IY         FD E9      1110 1001
                    0353  ;   CALL nn         CD nn nn   1100 1101
                    0354  ;   CALL cc, nn     xx nn nn   11cc c100
                    0355  ;   RET             C9         1100 1001
                    0356  ;   RET  cc         xx         11cc c000
                    0357  ;   RETI            ED 4D      0100 1101
                    0358  ;   RETN            ED 45      0100 0101
                    0359  ;   RST  aa         xx         11tt t111
                    0360  ; Also an interrupt or reset signal changes PC
                    0361  
                    0362  
                    0363  ; **********************************************************************
                    0364  ; **  End of Breakpoint module                                        **
                    0365  ; **********************************************************************
                    0366  
                    0367  
                    0368  
                    0060  #ENDIF
                    0061  #IFDEF      IncludeCommands
                    0062  #INCLUDE    Monitor\Commands.asm  ;Command Line Interprester (CLI)
                    0001  ; **********************************************************************
                    0002  ; **  Command Line Interpreter                  by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides the monitor's Command Line Interpreter (CLI)
                    0006  ; including the commands themselves.
                    0007  ;
                    0008  ; Public functions provided:
                    0009  ;   CLILoop               Command Line Interpreter main loop
                    0010  ;   CLIExecute            Offer string to command line interpreter
                    0011  ;   CLISkipNonDeli        Skip non-deliminaters in input line
                    0012  ;   CLISkipDelim          Skip deliminaters in input line
                    0013  ;   CLIGetHexParam        Get hex word/byte from input line
                    0014  
                    0015  
                    0016  ; **********************************************************************
                    0017  ; **  Constants                                                       **
                    0018  ; **********************************************************************
                    0019  
                    0020  ; Prompt character
002A:               0021  kPrompt:    .EQU '*'            ;Prompt character
                    0022  
                    0023  ; Error reporting flags
A2A1:               0024  kReportBad:
                    0024  kReportBad: .EQU 1              ;Report bad hex parameter
A2A1:               0025  kReportMis:
                    0025  kReportMis: .EQU 2              ;Report missing parameter
A2A1:               0026  kReportAny:
                    0026  kReportAny: .EQU 3              ;Report any error
                    0027  
                    0028  
                    0029  ; **********************************************************************
                    0030  ; **  Public functions                                                **
                    0031  ; **********************************************************************
                    0032  
                    0033              .CODE
                    0034  
                    0035  ; Command Line Interpreter: Main loop
1015: CD 8A 06      0036  CLILoop:    CALL StrInitDefault ;Initialise default string buffer
1018: 3E 2A         0037              LD   A,kPrompt      ;Get prompt character
101A: CD D1 04      0038              CALL OutputChar     ;Output a prompt character
                    0039  #IFDEF      IncludeMiniTerm
                    0040              XOR  A              ;Flag command as
                    0041              LD   (iMiniTerm),A  ;  not from mini terminal
                    0042  #ENDIF
                    0043  #IFDEF      IncludeHexLoader
                    0044  ; Trap colon character and input intel hex record(s)
101D: CD D8 03      0045  @Preview:   CALL InputPreview   ;Preview first character in line
1020: FE 3A         0046              CP   kColon         ;Start of Intel Hex record/line?
1022: 20 08         0047              JR   NZ,@NotHex     ;No, so skip..
1024: CD B7 1A      0048              CALL HexLoad        ;Load Intel Hex record
1027: CD B9 03      0049              CALL InputInsert    ;Insert returned character as waiting
102A: 18 F1         0050              JR   @Preview       ;Go preview start of next line..
0000:               0051  @NotHex:
                    0052  #IFDEF      IncludeMiniTerm
                    0053  ; WARNING this should be outside IncludeHexLoader
                    0054              CP   '-'
                    0055              JR   NZ,@NotMini
                    0056              LD   (iMiniTerm),A
                    0057              XOR   A
                    0058              CALL InputInsert    ;Insert returned character as waiting
                    0059              JR   @Preview       ;Go preview start of next line..
                    0060  @NotMini:
                    0061  #ENDIF
                    0062  #ENDIF
                    0063  ; Input line and execute it
102C: CD 2C 04      0064              CALL InputLine      ;Input a text line
102F: CD 34 10      0065              CALL CLIExecute     ;Execute command line
1032: 18 E1         0066              JR   CLILoop        ;Go get next line
                    0067  
                    0068  
                    0069  ; Offer string to command line interpreter
                    0070  ;  On entry:  DE = Start of command string terminated in Null
                    0071  ;  On exit:   If command handled (blank line or executed command):
                    0072  ;               A = 0x00 and Z flagged
                    0073  ;             If command not handled:
                    0074  ;               A = 0xFF and NZ flagged
                    0075  ;             No register contents preserved
                    0076  ; If found the command is executed before return. HL points to
                    0077  ; start of parameter string when command code entered.
1034:               0078  CLIExecute:
                    0079              ;EI
1034: 1A            0080  @Leading:   LD   A,(DE)         ;Skip leading spaces...
1035: FE 20         0081              CP   kSpace         ;Space character?
1037: 20 03         0082              JR   NZ,@NotSpace   ;No, so continue to next char
1039: 13            0083              INC  DE             ;Increment string pointer
103A: 18 F8         0084              JR   @Leading       ;Go consider next character
103C: FE 00         0085  @NotSpace:  CP   kNull          ;Blank line?
103E: C8            0086              RET  Z              ;Yes, so exit with A=0x00 and Z flagged
                    0087  ; Optionally include scripting
                    0088  #IFDEF      IncludeScripting
                    0089  ; Scripting lines start with a numeric character
                    0090              CALL IsCharNumeric  ;Numeric character
                    0091              JR   NC,@NotNum     ;No, so skip..
                    0092              CALL CLIGetHexParam
                    0093              CALL ScrEdit        ;Send line to scripting editor
                    0094              JR   @Return
                    0095  @NotNum:
                    0096  #ENDIF
                    0097  ; Offer command string to system command line interpreter
                    0098  ; DE = Start of command string
103F: 21 5B 13      0099              LD   HL,CmdNameList
1042: 01 90 13      0100              LD   BC,CmdAddressList
1045: CD 20 08      0101              CALL SearchStringList
                    0102  ;           JR   Z,@Error       ;Not found so return error
1048: 28 05         0103              JR   Z,@NotFound    ;Not found so try single letter
                    0104  ; Execute command
104A: 01 6C 10      0105              LD   BC,@Return     ;Get return address
104D: C5            0106              PUSH BC             ;Push return address onto stack
104E: E9            0107              JP   (HL)           ;Execute address from table
0000:               0108  @NotFound
                    0109  ; Try looking for command in ROM filing system
                    0110  #IFDEF      IncludeRomFS
                    0111              PUSH DE
                    0112              CALL RomExFile      ;Execute ROM file named at DE
                    0113              POP  DE
                    0114              RET  Z              ;Exit if command executed
                    0115  #ENDIF
                    0116  ; Try inserting space after first character in command string
                    0117  ; to allow single letter commands to be entered without space
                    0118  ; DE = Start of command string
104F: 62            0119              LD   H,D            ;Get start of command string..
1050: 6B            0120              LD   L,E
1051: 23            0121              INC  HL             ;Skip first character in string
1052: 0E 20         0122              LD   C,kSpace       ;Insert space
1054: 7E            0123  @Shift:     LD   A,(HL)         ;Get current character
1055: 71            0124              LD   (HL),C         ;Write new character
1056: 4F            0125              LD   C,A            ;Store previous character
1057: 7E            0126              LD   A,(HL)         ;Get character just written
1058: 23            0127              INC  HL             ;Point to next character
1059: B7            0128              OR   A              ;Null terminator?
105A: 20 F8         0129              JR   NZ,@Shift      ;No, so repeat
105C: 21 5B 13      0130              LD   HL,CmdNameList
105F: 01 90 13      0131              LD   BC,CmdAddressList
1062: CD 20 08      0132              CALL SearchStringList
1065: 28 07         0133              JR   Z,@Error       ;Not found so return error
                    0134  ; Execute single letter command
1067: 01 6C 10      0135              LD   BC,@Return     ;Get return address
106A: C5            0136              PUSH BC             ;Push return address onto stack
106B: E9            0137              JP   (HL)           ;Execute address from table
                    0138  ; Return here after executing the command
106C: AF            0139  @Return:    XOR  A              ;Return A = 0x00 and Z flagged
106D: C9            0140              RET
                    0141  ; Bad command
106E: 3E 20         0142  @Error:     LD   A,kMsgBadCmd   ;Message = Bad command
1070: CD E9 02      0143              CALL OutputMessage  ;Output message
1073: 3E FF         0144              LD   A,0xFF         ;No match found, so return:
1075: B7            0145              OR   A              ;  A = 0xFF and NZ flagged
1076: C9            0146              RET
                    0147  
                    0148  
                    0149  ; Skip non-deliminaters in input line
                    0150  ;   On entry: DE = Start address in input line
                    0151  ;   On exit:  A = Character at returned address
                    0152  ;             DE = Address of first non-delimiter character
                    0153  ;             BC HL IX IY preserved
                    0154  ; Delimiters are spaces or tabs (actually any control character other than null)
                    0155  ; Input line must be null terminated
                    0156  ; The return address can be that of the null terminator
1077:               0157  CLISkipNonDeli:
1077: 1A            0158  @Loop:      LD   A,(DE)         ;Get character from input line
1078: B7            0159              OR   A              ;End of line (null)?
1079: C8            0160              RET  Z              ;Yes, so exit
107A: FE 21         0161              CP   kSpace+1       ;Character > space?
107C: D8            0162              RET   C             ;No, so exit
107D: 13            0163              INC  DE             ;No, so non-delimiter
107E: 18 F7         0164              JR   @Loop          ;  and go try next character
                    0165  
                    0166  
                    0167  ; Skip deliminaters in input line
                    0168  ;   On entry: DE = Start address in input line
                    0169  ;   On exit:  If end of line (null) found:
                    0170  ;               A = Zero and Z flagged
                    0171  ;               DE = Address of null character
                    0172  ;             If non-delimiter character found:
                    0173  ;               A = Character found and NZ flagged
                    0174  ;               DE = Address of first non-delimiter character
                    0175  ;             BC HL IX IY preserved
                    0176  ; Delimiters are spaces or tabs (actually any control character other than null)
                    0177  ; Input line must be null terminated
                    0178  ; The return address can be that of the null terminator
1080:               0179  CLISkipDelim:
1080: 1A            0180  @Loop:      LD   A,(DE)         ;Get character from input line
1081: B7            0181              OR   A              ;End of line (null)?
1082: C8            0182              RET  Z              ;Yes, so exit
1083: FE 21         0183              CP   kSpace+1       ;Character > space?
1085: D0            0184              RET  NC             ;Yes, so exit
1086: 13            0185              INC  DE             ;No, so skip delimiter
1087: 18 F7         0186              JR   @Loop          ;  and go try next character
                    0187  
                    0188  
                    0189  ; Get hex word/byte from input line
                    0190  ;   On entry: A = Error reporting flags kReportXXX
                    0191  ;             DE = Location of parameter in input line
                    0192  ;             HL = Default value returned if no parameter found
                    0193  ;   On exit:  If a valid hex parameter:
                    0194  ;               A = 0x00 and Z flagged and C flagged
                    0195  ;               DE = Location after parameter in input line
                    0196  ;               HL = Hex byte/word from input line
                    0197  ;               Carry flagged if no parameter found
                    0198  ;             If no parameter if found:
                    0199  ;               A = 0x00 and Z flagged and NC flagged
                    0200  ;               DE = Location after parameter in input line
                    0201  ;               HL = Hex byte/word from input line
                    0202  ;               Carry flagged if no parameter found
                    0203  ;               An error message is may be shown
                    0204  ;             If an invalid hex parameter is found
                    0205  ;               A = 0xFF and NZ flagged and NC flagged
                    0206  ;               DE = Location after any valid characters
                    0207  ;               HL = Unspecified
                    0208  ;               An error message is may be shown
                    0209  ;             BC IX IY preserved
                    0210  ; If a non-hex character is encountered before a delimiter or null an error
                    0211  ; is reported.
                    0212  ; The hex conversion duplicates that in ConvertStringToNumber but we
                    0213  ; can't use that function here for hex as it requires leading numeric
                    0214  ; character ('0' to '9') for hex numbers:
                    0215  ; ... this is to stop the assembler getting confused between
                    0216  ; ... register names and constants which could be fixed by
                    0217  ; ... re-ordering the (dis)assebmer's instruction table
1089:               0218  CLIGetHexParam:
1089: C5            0219              PUSH BC             ;Preserve BC
108A: 4F            0220              LD   C,A            ;Store error report flags
108B: CD 80 10      0221              CALL CLISkipDelim   ;Skip deliminater
108E: B7            0222              OR   A              ;End of line (null)? This clears carry flag
108F: 28 35         0223              JR   Z,@None        ;Yes, so exit as no parameter found
1091: CD 04 08      0224              CALL IsCharHex      ;Is first character hexadecimal ?
1094: 30 25         0225              JR   NC,@Other      ;No, so invalid hex character
1096: 21 00 00      0226              LD   HL,0           ;Clear result (from supplied default)
1099: 1A            0227  @Loop:      LD   A,(DE)         ;Get character from input line
                    0228  ;           OR   A              ;End of line (null)? This clears carry flag
                    0229  ;           JR   Z,@None        ;Yes, so exit as ????with A = 0x00 and Z flagged
109A: FE 21         0230              CP   kSpace+1       ;Character > space?
109C: 38 24         0231              JR   C,@Found       ;No, so go end with delimiter
109E: CD 81 07      0232              CALL ConvertCharToUCase
10A1: CD 60 07      0233              CALL ConvertCharToNumber
10A4: 20 29         0234              JR   NZ,@Bad        ;Bad hex parameter
10A6: CB 25         0235              SLA  L              ;Rotate new nibble
10A8: CB 14         0236              RL   H              ;  into 16 bit result...
10AA: CB 25         0237              SLA  L
10AC: CB 14         0238              RL   H
10AE: CB 25         0239              SLA  L
10B0: CB 14         0240              RL   H
10B2: CB 25         0241              SLA  L
10B4: CB 14         0242              RL   H
10B6: B5            0243              OR   L
10B7: 6F            0244              LD   L,A
10B8: 13            0245              INC  DE
10B9: 18 DE         0246              JR   @Loop
                    0247  ; Try all other format not starting with hex character
10BB: CD 8A 07      0248  @Other:     CALL ConvertStringToNumber
10BE: 28 02         0249              JR   Z,@Found
10C0: 18 0D         0250              JR   @Bad
                    0251  ; Valid hex parameter found
10C2: C1            0252  @Found:     POP  BC             ;Retore BC
10C3: AF            0253              XOR  A              ;Return with A = 0x00
10C4: 37            0254              SCF                 ;  and Z flagged (= no bad hex)
10C5: C9            0255              RET                 ;  and C flagged (= no error)
                    0256  ; Parameter error: no parameter found
10C6: 79            0257  @None:      LD   A,C            ;Get error report flags
10C7: E6 02         0258              AND  kReportMis     ;Missing parameter report flag?
10C9: C4 DA 10      0259              CALL NZ,@Error      ;Yes, so report error
10CC: C1            0260              POP  BC             ;Retore BC
10CD: AF            0261              XOR  A              ;Return with A = 0x00
                    0262              ;  and Z flagged (= no bad hex)
10CE: C9            0263              RET                 ;  and NC flagged (= error)
                    0264  ; Parameter error: non-hex digit found
10CF: 79            0265  @Bad:       LD   A,C            ;Get error report flags
10D0: E6 01         0266              AND  kReportBad     ;Bad parameter report flag?
10D2: C4 DA 10      0267              CALL NZ,@Error      ;Yes, so report error
10D5: C1            0268              POP  BC             ;Retore BC
10D6: 3E FF         0269              LD   A,0xFF         ;;Return with A = 0xFF 
10D8: B7            0270              OR   A              ;  and NZ flagged (= bad hex)
10D9: C9            0271              RET                 ;  and NC flagged (= error)
                    0272  ; Report error
0000:               0273  @Error:     ;PUSH DE
10DA: CD DF 10      0274              CALL CLIBadParam
                    0275              ;POP  DE
10DD: 13            0276              INC  DE
10DE: C9            0277              RET
                    0278  
                    0279  
                    0280  ; **********************************************************************
                    0281  ; **  Private functions                                               **
                    0282  ; **********************************************************************
                    0283  
                    0284  
                    0285  ; Output bad parameter error message
10DF:               0286  CLIBadParam:
10DF: F5            0287              PUSH AF
10E0: 3E 21         0288              LD   A,kMsgBadPar   ;Message = Bad parameter
10E2: CD E9 02      0289              CALL OutputMessage  ;Output message
10E5: F1            0290              POP  AF
10E6: C9            0291              RET
                    0292  
                    0293  
                    0294  ; Returns NZ if mini-terminal mode
                    0295  #IFDEF      IncludeMiniTerm
                    0296  IsMiniTerm: LD   A,(iMiniTerm)  ;Get mini-terminal mode flag
                    0297              OR   A              ;Return NZ in mini-terminal mode
                    0298              RET
                    0299  #ELSE
10E7:               0300  IsMiniTerm:
10E7: AF            0300  IsMiniTerm: XOR  A              ;Return Z as no mini-terminal mode
10E8: C9            0301              RET
                    0302  #ENDIF
                    0303  
                    0304  
                    0305  ; **********************************************************************
                    0306  ; **  Commands                                                        **
                    0307  ; **********************************************************************
                    0308  
                    0309  
                    0310  ; Command: API <fn> [<A>] [<DE>]
10E9: 3E 03         0311  CmdAPI:     LD   A,kReportAny   ;Report any error
10EB: CD 89 10      0312              CALL CLIGetHexParam ;Get function number
10EE: D0            0313              RET  NC             ;Abort if any error
10EF: 4D            0314              LD   C,L            ;Store function number
10F0: 3E 01         0315              LD   A,kReportBad   ;Only report bad hex parameter
10F2: CD 89 10      0316              CALL CLIGetHexParam ;Get value for A register
                    0317  ;           JR   NC             ;Abort if any error
10F5: 45            0318              LD   B,L            ;Store value for A register
10F6: 3E 01         0319              LD   A,kReportBad   ;Only report bad hex parameter
10F8: CD 89 10      0320              CALL CLIGetHexParam ;Get value for DE registers
                    0321  ;           RET  NC             ;Abort if any error
10FB: EB            0322              EX   DE,HL          ;Prepare DE register value
10FC: 78            0323              LD   A,B            ;Prepare A register
10FD: F7            0324  @Call:      RST  $30            ;Call API function C
10FE: CD EF 06      0325              CALL StrWrHexByte   ;Write hex byte to string
1101: CD 35 07      0326              CALL StrWrSpace     ;Write space to string
1104: CD 0F 07      0327              CALL StrWrHexWord   ;Write hex word to string
1107: CD 1A 07      0328              CALL StrWrNewLine   ;Write new line to string
110A: C3 A7 06      0329              JP   StrPrint       ;Output string
                    0330  
                    0331  
                    0332  ; Command: Assembler: A [<start address>]
                    0333  #IFDEF      IncludeAssembler
110D:               0334  CmdAssemble:
110D: 2A A1 A2      0335              LD   HL,(iParam1)   ;Default parameter
1110: 3E 01         0336              LD   A,kReportBad   ;Only report bad hex parameter
1112: CD 89 10      0337              CALL CLIGetHexParam
1115: C0            0338              RET  NZ             ;Abort if bad hex in parameter
                    0339  ; Start new line. HL = Current memory location, DE = Not specified
1116: 22 A1 A2      0340  @NextLine:  LD   (iParam1),HL   ;Update default parameter
1119: CD 76 08      0341              CALL WrInstruction
111C: CD A7 06      0342              CALL StrPrint
                    0343  ; Input line. HL = Next memory location, DE = Not specified
111F: CD 2C 04      0344              CALL InputLine      ;Input text line
1122: 20 05         0345              JR   NZ,@GotLine    ;Skip if line is not a null string
1124: FE 1B         0346              CP   kEscape        ;Escaped from input line?
1126: C8            0347              RET  Z              ;Yes, so abort
1127: 18 ED         0348              JR   @NextLine      ;No, so go to next line
                    0349  ; Got line to process. HL = Not specified, DE = Start of line
1129: 2A A1 A2      0350  @GotLine:   LD   HL,(iParam1)   ;Get address for this instruction
112C: 1A            0351              LD   A,(DE)         ;Get character from input line
                    0352  ;           OR   A              ;End of line?
                    0353  ;           JR   Z,@NextLine    ;Yes, so go to next location
112D: FE 2E         0354              CP   '.'            ;End modify?
112F: C8            0355              RET  Z              ;Yes, so exit
                    0356  ;           CP   '"'            ;String? (quote character)
                    0357  ;           JR   Z,@String      ;Yes...
                    0358  ;           CP   '^'            ;Back one address?
                    0359  ;           JR   Z,@Back        ;Yes...
                    0360  ; New assembler instruction
1130: CD 2A 0C      0361              CALL Assemble       ;Assemble string in input buffer
1133: 28 11         0362              JR   Z,@Error
1135: 2A A1 A2      0363              LD   HL,(iParam1)
1138: CD 8A 06      0364              CALL StrInitDefault ;Initiase default string buffer
113B: CD 4E 14      0365              CALL DisWrInstruction ;Full disassembly to string buffer
113E: CD 1A 07      0366              CALL StrWrNewLine
1141: CD A7 06      0367              CALL StrPrint       ;Print to output device
1144: 18 D0         0368              JR   @NextLine
                    0369  ; Report error
1146: B7            0370  @Error:     OR   A              ;Error 0 = unspecifed
1147: 20 02         0371              JR   NZ,@ErrOut     ;No, so skip
1149: 3E 22         0372              LD   A,kMsgSyntax   ;Message = Syntax error
114B: CD E9 02      0373  @ErrOut:    CALL OutputMessage  ;Output message
114E: 2A A1 A2      0374              LD   HL,(iParam1)
1151: 18 C3         0375              JR   @NextLine
                    0376  #ENDIF
                    0377  
                    0378  
                    0379  ; Command: Baud rate: Baud <device> <rate-code>
                    0380  #IFDEF      IncludeBaud
                    0381  CmdBaud:    LD   A,kReportAny   ;Report bad or missing hex parameter
                    0382              CALL CLIGetHexParam
                    0383              RET  NC             ;Abort if bad hex in parameter
                    0384              LD   C,L            ;Store device number (1 to 6, or A to B)
                    0385              LD   A,kReportAny   ;Report bad or missing hex parameter
                    0386              CALL CLIGetHexParam
                    0387              RET  NC             ;Abort if bad hex in parameter
                    0388              LD   A,C            ;Get requested device identifier
                    0389              LD   E,L            ;Get requested baud rate code
                    0390              CALL SetBaud        ;Set device (A) to baud rate (E) 
                    0391              JP   Z,CLIBadParam  ;Failed, so raise error
                    0392              RET
                    0393  #ENDIF
                    0394  
                    0395  
                    0396  ; Command: Breakpoint: B [<address>]
                    0397  #IFDEF      IncludeBreakpoint
1153: 2A A1 A2      0398  CmdBP:      LD   HL,(iParam1)   ;Default parameter
1156: 3E 01         0399              LD   A,kReportBad   ;Only report bad hex parameter
1158: CD 89 10      0400              CALL CLIGetHexParam
115B: C0            0401              RET  NZ             ;Abort if bad hex in parameter
115C: 38 07         0402              JR   C,@Set         ;If address given then set breakpoint
115E: CD 68 0F      0403              CALL BPReqClr       ;No address, so clear requested address
1161: 3E 24         0404              LD   A,kMsgBPClr    ;String = Breakpoint cleared
1163: 18 09         0405              JR   @Result        ;Go output message
1165: CD 6D 0F      0406  @Set:       CALL BPReqSet       ;Attempt to set breakpoint
1168: 3E 23         0407              LD   A,kMsgBPSet    ;String = Breakpoint set
116A: 20 02         0408              JR   NZ,@Result     ;Skip if breakpiont set ok
116C: 3E 25         0409              LD   A,kMsgBPFail   ;String = Breakpoint setting failed
116E: C3 E9 02      0410  @Result:    JP   OutputMessage  ;Output message A
                    0411  #ENDIF
                    0412  
                    0413  
                    0414  ; Command: Console <device>
1171:               0415  CmdConsole:
1171: 3E 03         0415  CmdConsole: LD   A,kReportAny   ;Report bad or missing hex parameter
1173: CD 89 10      0416              CALL CLIGetHexParam
1176: D0            0417              RET  NC             ;Abort if bad hex in parameter
1177: 7D            0418              LD   A,L            ;Get requested device number
1178: B7            0419              OR   A              ;Device = 0?
1179: CA DF 10      0420              JP   Z,CLIBadParam  ;Yes, then error
117C: FE 0A         0421              CP   0x0A           ;Identifier is a hex letter?
117E: 38 02         0422              JR   C,@GotNum      ;No, so skip
1180: D6 09         0423              SUB  0x09           ;Convert 0x0A/B to 0x01/2
1182: FE 07         0424  @GotNum:    CP   7              ;Device >= 7?
1184: D2 DF 10      0425              JP   NC,CLIBadParam ;Yes, then error
1187: CD 79 02      0426              CALL SelConDev      ;Select console device
118A: C9            0427              RET
                    0428  
                    0429  
                    0430  ; Command: Devices
118B:               0431  CmdDevices:
                    0431  CmdDevices: ;LD   A,kMsgDevice  ;="Devices:"
                    0432              ;CALL OutputMessage ;Output message
118B: C3 90 1B      0433              JP   Hardware_Devices ;Output device list
                    0434  
                    0435  
                    0436  ; Command: Directory: DIR
                    0437  #IFDEF      IncludeRomFS
                    0438  CmdDir:     CALL RomSearchInit  ;Initialise ROM file search
                    0439  @Loop:      CALL RomSearchNext  ;Search for next file reference
                    0440              RET  NZ             ;None found so abort
                    0441              CALL RomGetName     ;Get pointer to file name
                    0442              CALL StrPrintDE     ;Print file name
                    0443              LD   A,kPeriod      ;Get period character ('.')
                    0444              CALL OutputChar     ;Output character
                    0445              CALL RomGetType     ;Get file type
                    0446              AND  0x0F           ;Remove file flags from type
                    0447              ADD  A              ;A = 2 x File type
                    0448              ADD  A              ;A = 4 x File type
                    0449              LD   L,A            ;Store as HL
                    0450              LD   H,0
                    0451              LD   DE,@Extns      ;Get start of extension strings
                    0452              ADD  HL,DE          ;Add offset for this file type
                    0453              EX   DE,HL
                    0454              CALL OutputZString  ;Output file extension
                    0455              CALL OutputNewLine  ;Output new line
                    0456              JR   @Loop
                    0457  @Extns:     .DB  "DAT",0        ;Type 0 = Unspecified
                    0458              .DB  "COM",0        ;Type 1 = Monitor command
                    0459              .DB  "EXE",0        ;Type 2 = Executable
                    0460              .DB  "HLP",0        ;Type 3 = Help
                    0461              .DB  "TXT",0        ;Type 4 = Text
                    0462              .DB  "???",0        ;Type 5 = Unknown
                    0463  #ENDIF
                    0464  
                    0465  
                    0466  ; Command: Disassemble: D [<start address>]
                    0467  #IFDEF      IncludeDisassemble
118E:               0468  CmdDisassemble:
0000:               0469  CmdList:
118E: 2A A1 A2      0470              LD   HL,(iParam1)   ;Default parameter
1191: 3E 01         0471              LD   A,kReportBad   ;Only report bad hex parameter
1193: CD 89 10      0472              CALL CLIGetHexParam
1196: C0            0473              RET  NZ             ;Abort if bad hex in parameter
1197: 16 14         0474  @More:      LD   D,20           ;Number of instructions to list
1199: CD 4E 14      0475  @Instruct:  CALL DisWrInstruction ;Full disassembly to string buffer
119C: CD 1A 07      0476              CALL StrWrNewLine   ;Write new line to string buffer
119F: CD A7 06      0477              CALL StrPrint       ;Print to output device
11A2: 15            0478              DEC  D              ;Any more instruction to write?
11A3: 20 F4         0479              JR   NZ,@Instruct   ;Yes, so go write next one
11A5: 22 A1 A2      0480              LD   (iParam1),HL   ;Update default parameter
11A8: CD BD 03      0481              CALL InputMore      ;Print more?
11AB: 28 EA         0482              JR   Z,@More        ;Yes, so repeat
11AD: C9            0483              RET
                    0484  #ENDIF
                    0485  
                    0486  
                    0487  ; Command: Edit memory: E [<start address>]
11AE: 2A A1 A2      0488  CmdEdit:    LD   HL,(iParam1)   ;Default start address
11B1: 3E 01         0489              LD   A,kReportBad   ;Only report bad hex parameter
11B3: CD 89 10      0490              CALL CLIGetHexParam
11B6: C0            0491              RET  NZ             ;Abort if bad hex in parameter
                    0492  ; Start new line. HL = Current memory location, DE = Not specified
11B7: 22 A1 A2      0493  @NextLine:  LD   (iParam1),HL   ;Store current address
11BA: CD E7 10      0494              CALL IsMiniTerm     ;Is this command in mini-terminal mode?
11BD: 20 0B         0495              JR   NZ,@Mini       ;Yes, so skip
                    0496  ; Normal terminal mode
11BF: CD 76 08      0497              CALL WrInstruction  ;Write disassembled instruction string
11C2: CD A7 06      0498              CALL StrPrint       ;Output disassembled instruction
11C5: CD 2C 04      0499              CALL InputLine      ;Input text line
11C8: 18 19         0500              JR   @Inputed
                    0501  ; Mini-terminal mode
11CA: CD 8A 06      0502  @Mini:      CALL StrInitDefault ;Initialise default string buffer
11CD: 54            0503              LD   D,H            ;Get current address
11CE: 5D            0504              LD   E,L
11CF: 23            0505              INC  HL             ;Prepare return address
11D0: CD 0F 07      0506              CALL StrWrHexWord   ;Write memory address string
11D3: CD 35 07      0507              CALL StrWrSpace     ;Write space to string
11D6: CD A7 06      0508              CALL StrPrint       ;Print string
11D9: CD 8A 06      0509              CALL StrInitDefault ;Initialise default string buffer
11DC: 1A            0510              LD   A,(DE)         ;Read byte from memory
11DD: CD EF 06      0511              CALL StrWrHexByte   ;Write hex byte to string buffer
11E0: CD 36 04      0512              CALL InputLineEdit  ;Edit input line
                    0513  ; Input line. HL = Next memory location, DE = Not specified
                    0514              ;CALL InputLine     ;Input text line
11E3: 20 05         0515  @Inputed:   JR   NZ,@GotLine    ;Skip if line is not a null string
11E5: FE 1B         0516              CP   kEscape        ;Escaped from input line?
11E7: C8            0517              RET  Z              ;Yes, so abort
11E8: 18 CD         0518              JR   @NextLine      ;No, so go to next line
                    0519  ; Got line to process. HL = Not specified, DE = Start of line
11EA: 2A A1 A2      0520  @GotLine:   LD   HL,(iParam1)   ;Get address for this instruction
11ED:               0521  @NextParam:
11ED: 1A            0521  @NextParam: LD   A,(DE)         ;Get character from input line
11EE: B7            0522              OR   A              ;End of line?
11EF: 28 C6         0523              JR   Z,@NextLine    ;Yes, so go to next location
11F1: FE 2E         0524              CP   '.'            ;End modify?
11F3: C8            0525              RET  Z              ;Yes, so exit
11F4: FE 22         0526              CP   '"'            ;String? (quote character)
11F6: 28 15         0527              JR   Z,@String      ;Yes...
11F8: FE 5E         0528              CP   '^'            ;Back one address?
11FA: 28 1A         0529              JR   Z,@Back        ;Yes...
                    0530  ; New memory data is a hex value
11FC: E5            0531              PUSH HL             ;Remember current memory location
11FD: 6F            0532              LD   L,A            ;Set default value to current contents
11FE: 3E 01         0533              LD   A,kReportBad   ;Only report bad hex parameter
1200: CD 89 10      0534              CALL CLIGetHexParam
1203: 7D            0535              LD   A,L            ;Get parameter value (lo byte only)
1204: E1            0536              POP  HL             ;Restore current location
1205: 20 B0         0537              JR   NZ,@NextLine   ;If bad hex parameter start next line
1207: 30 AE         0538              JR   NC,@NextLine   ;If no parameter then start next line
1209: 77            0539              LD   (HL),A         ;Store new byte at current location
120A: 23            0540              INC  HL             ;Increment memory location
                    0541  ;           LD   (iParam1),HL   ;Update memory location
120B: 18 E0         0542              JR   @NextParam
                    0543  ; New memory data is a string
120D: 13            0544  @String:    INC  DE             ;Increment pointer to input line
120E: 1A            0545              LD   A,(DE)         ;Get character from input line
120F: B7            0546              OR   A              ;End of string?
1210: 28 A5         0547              JR   Z,@NextLine    ;Yes, next line
1212: 77            0548              LD   (HL),A         ;Store new byte at current location
1213: 23            0549              INC  HL             ;Increment memory location
1214: 18 F7         0550              JR   @String
                    0551  ; Back one location
1216: 2B            0552  @Back:      DEC  HL             ;Back one memory location
1217: 18 9E         0553              JR   @NextLine
                    0554  
                    0555  
                    0556  ; Command: Flag: F [<name>]
1219: CD 80 10      0557  CmdFlag:    CALL CLISkipDelim   ;Skip deliminater
121C: 28 14         0558              JR   Z,@Results     ;No flag specified so display flags
                    0559  ; Flag name specified so set or clear flag
121E: 21 14 14      0560              LD   HL,FlagNames
1221: 01 2E 14      0561              LD   BC,FlagLogic
1224: CD 20 08      0562              CALL SearchStringList
1227: CA DF 10      0563              JP   Z,CLIBadParam  ;Report error if flag name not found
122A: 3A 75 A2      0564              LD   A,(iAF)        ;Get flags register
122D: A5            0565              AND  L              ;AND with value from list
122E: B4            0566              OR   H              ;OR with value form list
122F: 32 75 A2      0567              LD   (iAF),A        ;Get flags register
1232: CD B4 08      0568  @Results:   CALL WrRegister1    ;Write registers line 1 to buffer
1235: C3 A7 06      0569              JP   StrPrint       ;Output registers (inc flags)
                    0570  
                    0571  
                    0572  ; Command: Fill <start> <end> <data>
1238: 3E 03         0573  CmdFill:    LD   A,kReportAny   ;Report any error
123A: CD 89 10      0574              CALL CLIGetHexParam ;Start address
123D: D0            0575              RET  NC             ;Abort if any error
123E: 22 A1 A2      0576              LD   (iParam1),HL   ;Store start address
1241: 3E 03         0577              LD   A,kReportAny   ;Report any error
1243: CD 89 10      0578              CALL CLIGetHexParam ;End address
1246: D0            0579              RET  NC             ;Abort if any error
1247: 44            0580              LD   B,H            ;Store last address
1248: 4D            0581              LD   C,L
1249: 3E 03         0582              LD   A,kReportAny   ;Report any error
124B: CD 89 10      0583              CALL CLIGetHexParam ;Data byte
124E: D0            0584              RET  NC             ;Abort if any error
124F: 5D            0585              LD   E,L            ;Store data byte
1250: 2A A1 A2      0586              LD   HL,(iParam1)   ;Get start address
1253: 2B            0587              DEC  HL
1254: 23            0588  @Loop:      INC  HL             ;Point to next address to fill
1255: 73            0589              LD   (HL),E         ;Write date byte to memory
1256: 7D            0590              LD   A,L            ;Lo byte of current address
1257: B9            0591              CP   C              ;Same as last address to fill?
1258: 20 FA         0592              JR   NZ,@Loop       ;No, so continue
125A: 7C            0593              LD   A,H            ;Hi byte of current address
125B: B8            0594              CP   B              ;Same as last address to fill?
125C: 20 F6         0595              JR   NZ,@Loop       ;No, so continue
125E: C9            0596              RET
                    0597  
                    0598  
                    0599  ; Command: Go: G [<start address>]
125F: 3E 01         0600  CmdGo:      LD   A,kReportBad   ;Only report bad hex parameter
1261: CD 89 10      0601              CALL CLIGetHexParam
1264: C0            0602              RET  NZ             ;Abort if bad hex in parameter
1265: 30 10         0603              JR   NC,@Restore    ;Skip if no address parameter
1267: 22 73 A2      0604              LD   (iPC),HL       ;Store supplied address as PC
126A: 21 C0 A0      0605              LD   HL,kSPUsr      ;Get top of user stack
126D: 11 03 01      0606              LD   DE,WarmStart   ;Get return address
1270: 2B            0607              DEC  HL             ;  and 'push' it onto
1271: 72            0608              LD   (HL),D         ;  user stack
1272: 2B            0609              DEC  HL
1273: 73            0610              LD   (HL),E
1274: 22 81 A2      0611              LD   (iSP),HL       ;Store as user stack pointer
                    0612  #IFDEF      IncludeBreakpoint
1277: C3 75 0F      0613  @Restore:   JP   BPGo           ;Execute using stored register values
                    0614  #ELSE
                    0615  @Restore:   LD   HL,(iPC)       ;Get execution address
                    0616              JP   (HL)           ;Run from this address
                    0617  #ENDIF
                    0618  
                    0619  
                    0620  ; Command: Help: HELP or ?
                    0621  ;#IFDEF     IncludeHelp
127A: 3E 03         0622  CmdHelp:    LD   A,kMsgAbout    ;Message = about text
127C: CD E9 02      0623              CALL OutputMessage  ;Output message
127F: CD E6 04      0624              CALL OutputNewLine  ;Output new line
1282: 3E 26         0625              LD   A,kMsgHelp     ;Message = help text
                    0626              ;JP   OutputMessage ;Output message
1284: CD E9 02      0627              CALL OutputMessage  ;Output message
                    0628  ; Look for ROM filing system help extensions
                    0629  #IFDEF      IncludeRomFS
                    0630              CALL RomSearchInit
                    0631  @Loop:      CALL RomSearchNext
                    0632              RET  NZ
                    0633              CALL RomGetType
                    0634              CP   3
                    0635              JR   NZ,@Loop
                    0636              CALL RomGetHlp
                    0637              CALL OutputZString
                    0638              JR   @Loop
                    0639  #ELSE
1287: C9            0640              RET
                    0641  #ENDIF
                    0642  ;#ENDIF
                    0643  
                    0644  
                    0645  ; Command: Input: I <port address>
1288: 3E 03         0646  CmdIn:      LD   A,kReportAny   ;Report any error
128A: CD 89 10      0647              CALL CLIGetHexParam
128D: D0            0648              RET  NC             ;Abort if any error
128E: 4D            0649              LD   C,L
128F: ED 78         0650              IN   A,(C)          ;Input from specified port
1291: CD EF 06      0651              CALL StrWrHexByte   ;Write hex byte to string
1294: CD 1A 07      0652              CALL StrWrNewLine   ;Write new line to string
1297: C3 A7 06      0653              JP   StrPrint       ;Output string
                    0654  
                    0655  
                    0656  ; Command: Memory display: M [<start address>]
129A: 2A A1 A2      0657  CmdMemory:  LD   HL,(iParam1)   ;Default parameter
129D: 3E 01         0658              LD   A,kReportBad   ;Only report bad hex parameter
129F: CD 89 10      0659              CALL CLIGetHexParam
12A2: C0            0660              RET  NZ             ;Abort if bad hex in parameter
12A3: 54            0661  @More:      LD   D,H
12A4: 5D            0662              LD   E,L
12A5: 0E 08         0663              LD   C,8            ;Number of lines of hex dump
12A7: CD 86 08      0664  @Line:      CALL WrMemoryDump   ;Build string of one line of dump
12AA: CD A7 06      0665              CALL StrPrint       ;Print to output device
12AD: 0D            0666              DEC  C              ;End of dump?
12AE: 20 F7         0667              JR   NZ,@Line       ;No, so loop back for another line
12B0: 62            0668              LD   H,D
12B1: 6B            0669              LD   L,E
12B2: 22 A1 A2      0670              LD   (iParam1),HL   ;Update default parameter
12B5: CD BD 03      0671              CALL InputMore      ;Print more?
12B8: 28 E9         0672              JR   Z,@More        ;Yes, so repeat
12BA: C9            0673              RET
                    0674  
                    0675  
                    0676  ; Command: New script: NEW
                    0677  #IFDEF      IncludeScripting
                    0678  CmdNew:     JP   ScrNew         ;Script, new command
                    0679  #ENDIF
                    0680  
                    0681  
                    0682  ; Command: Old script: OLD
                    0683  #IFDEF      IncludeScripting
                    0684  CmdOld:     JP   ScrOld         ;Script, old command
                    0685  #ENDIF
                    0686  
                    0687  
                    0688  ; Command: Output: O <port address> <port data>
12BB: 3E 03         0689  CmdOut:     LD   A,kReportAny   ;Report any error
12BD: CD 89 10      0690              CALL CLIGetHexParam
12C0: D0            0691              RET  NC             ;Abort if any error
12C1: 4D            0692              LD   C,L
12C2: 3E 03         0693              LD   A,kReportAny   ;Report any error
12C4: CD 89 10      0694              CALL CLIGetHexParam
12C7: D0            0695              RET  NC             ;Abort if any error
12C8: 7D            0696              LD   A,L
12C9: ED 79         0697              OUT  (C),A
12CB: C9            0698              RET
                    0699  
                    0700  
                    0701  ; Command: Registers: R [<name>]
12CC:               0702  CmdRegisters:
12CC: CD 80 10      0703              CALL CLISkipDelim   ;Skip deliminater
12CF: 20 0C         0704              JR   NZ,@Param      ;Go handle parameter
                    0705  ; No parameters, so just output register values
12D1: CD B4 08      0706  @Show:      CALL WrRegister1
12D4: CD A7 06      0707              CALL StrPrint
12D7: CD BF 08      0708              CALL WrRegister2
12DA: C3 A7 06      0709              JP   StrPrint
                    0710  ; Handle parameter
12DD: D5            0711  @Param:     PUSH DE             ;Preserve start address of parameter
12DE: 21 BA 13      0712              LD   HL,RegisterNames
12E1: 01 E6 13      0713              LD   BC,RegisterAddresses
12E4: CD 20 08      0714              CALL SearchStringList
12E7: D1            0715              POP  DE             ;Restore start address of parameter
12E8: CA DF 10      0716              JP   Z,CLIBadParam  ;Report error if reg name not found
                    0717  ; Edit specified register's value
12EB: CD 8A 06      0718              CALL StrInitDefault ;Initialise default string buffer
12EE: 0E 00         0719              LD   C,0            ;Length of register name
12F0: 1A            0720  @NextChar:  LD   A,(DE)         ;Get character of register name
12F1: FE 1F         0721              CP   kSpace-1       ;End of register name?
12F3: 38 0A         0722              JR   C,@Colon       ;Yes, so write colon
12F5: CD 81 07      0723              CALL ConvertCharToUCase
12F8: CD DB 06      0724              CALL StrWrChar      ;Write character to string buffer
12FB: 0C            0725              INC  C              ;Count characters in name
12FC: 13            0726              INC  DE             ;Increment to next char of name
12FD: 18 F1         0727              JR   @NextChar      ;  and go get next character
12FF: 3E 3A         0728  @Colon:     LD   A,':'          ;Get colon character
1301: CD DB 06      0729              CALL StrWrChar      ;Write colon to string buffer
1304: CD 35 07      0730              CALL StrWrSpace     ;Write space to string buffer
1307: 5E            0731              LD   E,(HL)         ;Get register contents
1308: 23            0732              INC  HL
1309: 56            0733              LD   D,(HL)
130A: 2B            0734              DEC  HL
130B: 79            0735              LD   A,C            ;Length of register name
130C: FE 01         0736              CP   1              ;One character long?
130E: 20 06         0737              JR   NZ,@Word
1310: 7B            0738              LD   A,E            ;Get lo byte 
1311: CD EF 06      0739              CALL StrWrHexByte   ;Write hex byte value of register
1314: 18 03         0740              JR   @Space
1316: CD 0F 07      0741  @Word:      CALL StrWrHexWord   ;Write hex word value of register
1319: 3E 02         0742  @Space:     LD   A,2
131B: CD 3D 07      0743              CALL StrWrSpaces    ;Write 2 spaces to string buffer
131E: CD A7 06      0744              CALL StrPrint       ;Print current string ot output device
                    0745  ; Input line. HL = Memory location of register
1321: CD 2C 04      0746              CALL InputLine      ;Input text line
1324: C8            0747              RET  Z              ;No input, so we're done
                    0748  ; Extract new register value from input buffer
1325: E5            0749              PUSH HL             ;Preserve memory location
1326: 3E 03         0750              LD   A,kReportAny   ;Report any error
1328: CD 89 10      0751              CALL CLIGetHexParam
132B: 5D            0752              LD   E,L            ;Get hex value input
132C: 54            0753              LD   D,H
132D: E1            0754              POP  HL             ;Restore memory location
132E: D0            0755              RET  NC             ;If any error then we're done
132F: 73            0756              LD   (HL),E         ;Store lo byte at register location
1330: 79            0757              LD   A,C            ;Length of register name
1331: FE 01         0758              CP   1              ;One character long?
1333: C8            0759              RET  Z              ;Yes, so we're done
1334: 23            0760              INC  HL             ;Increment memory location
1335: 72            0761              LD   (HL),D         ;Store hi byte at register location
1336: C9            0762              RET
                    0763  
                    0764  
                    0765  ; Command: Reset: RESET
0100:               0766  CmdReset:   .EQU ColdStart      ;Command reset = Cold start system
1337: F3            0767              DI                  ;Disable interrupts
1338: C3 00 01      0768              JP   ColdStart      ;Run as if hardware reset
                    0769  
                    0770  
                    0771  ; Command: Script list: SCRIPT
                    0772  #IFDEF      IncludeScripting
                    0773  CmdScript:  JP   ScrList
                    0774  #ENDIF
                    0775  
                    0776  
                    0777  ; Command: Step: S [<start address>]
                    0778  #IFDEF      IncludeDisassemble
133B: 3E 01         0779  CmdStep:    LD   A,kReportBad   ;Only report bad hex parameter
133D: CD 89 10      0780              CALL CLIGetHexParam
1340: C0            0781              RET  NZ             ;Abort if bad hex in parameter
1341: 30 10         0782              JR   NC,@Restore    ;Skip if no address parameter
1343: 22 73 A2      0783              LD   (iPC),HL       ;Store supplied address as PC
1346: 21 C0 A0      0784              LD   HL,kSPUsr      ;Get top of user stack
1349: 11 03 01      0785              LD   DE,WarmStart   ;Get return address
134C: 2B            0786              DEC  HL             ;  and 'push' it onto
134D: 72            0787              LD   (HL),D         ;  user stack
134E: 2B            0788              DEC  HL
134F: 73            0789              LD   (HL),E
1350: 22 81 A2      0790              LD   (iSP),HL       ;Store as user stack pointer
1353: C3 82 0F      0791  @Restore:   JP   BPStep         ;Execute using stored register values
                    0792  #ENDIF
                    0793  
                    0794  
                    0795  ; Trap optional features that have not been included in this build
                    0796  #IFNDEF     IncludeAssembler
                    0797  CmdAssemble:
                    0798  #ENDIF
                    0799  #IFNDEF     IncludeBaud
0000:               0800  CmdBaud:
                    0801  #ENDIF
                    0802  #IFNDEF     IncludeBreakpoint
                    0803  CmdBP:
                    0804  #ENDIF
                    0805  #IFNDEF     IncludeDisassemble
                    0806  CmdDisassemble:
                    0807  CmdStep
                    0808  CmdList:
                    0809  #ENDIF
                    0810  #IFNDEF     IncludeRomFS
0000:               0811  CmdDir:
                    0812  #ENDIF
                    0813  #IFNDEF     IncludeScripting
0000:               0814  CmdNew:
0000:               0815  CmdOld:
0000:               0816  CmdScript:
                    0817  #ENDIF
                    0818  #IFNDEF     IncludeHelp
                    0819  CmdHelp:
                    0820  #ENDIF
1356: 3E 27         0821              LD   A,kMsgNotAv    ;Message = Feature no included
1358: C3 E9 02      0822              JP   OutputMessage  ;Output message
                    0823  
                    0824  
                    0825  ; **********************************************************************
                    0826  ; **  Constant data                                                   **
                    0827  ; **********************************************************************
                    0828  
                    0829  
                    0830  ; Command summary
                    0831  ; Char/Cmd,  Description     ? Other possible commands
                    0832  ;  :         Download intel hex record
                    0833  ;  ?         Help
                    0834  ;  A         Assemble        ?
                    0835  ;  B         Breakpoint      ?
                    0836  ;  C                         ? Compare, Copy, CPM
                    0837  ;  CONSOLE   Console select  ?
                    0838  ;  D         Disassemble     ? Dump, Display
                    0839  ;  DEVICES   Device list     ?
                    0840  ;  DIR       Directory list  ?
                    0841  ;  E         Edit memory     ? Execute
                    0842  ;  F         Flags           ? 
                    0843  ;  FILL      Fill memory     ?
                    0844  ;  G         Go              ?
                    0845  ;  H                         ?
                    0846  ;  HELP      Help            ?
                    0847  ;  I         Input from port ?
                    0848  ;  J                         ? Jump
                    0849  ;  K                         ? 
                    0850  ;  L                         ? Load, List 
                    0851  ;  M         Memory          ? Modify, Move
                    0852  ;  N                         ? Next, New
                    0853  ;  NEW       New script      ?
                    0854  ;  O         Output to port  ? Old
                    0855  ;  OLD       Old srcipt      ?
                    0856  ;  P                         ?
                    0857  ;  Q                         ?
                    0858  ;  R         Registers       ? 
                    0859  ;  RESET     Reset           ?
                    0860  ;  ROM       Directory list  ?
                    0861  ;  S         Step            ? Save, Script
                    0862  ;  SCRIPT    Script          ?
                    0863  ;  T                         ? Transfer
                    0864  ;  U                         ?
                    0865  ;  V                         ? Verify
                    0866  ;  W                         ?
                    0867  ;  X                         ?
                    0868  ;  Y                         ?
                    0869  ;  Z                         ?
                    0870  
                    0871  ; Command summary for mini-terminal
                    0872  ;  B         Breakpoint
                    0873  ;  E         Edit memory     (mini version -E)
                    0874  ;  F         Flags           (mini version needed)
                    0875  ;  G         Go
                    0876  ;  I         Input from port (mini version needed)
                    0877  ;  O         Output to port 
                    0878  ;  R         Registers       (mini version needed)
                    0879  ; Problems to sort: Console, Fill (if it is worth it)
                    0880  
                    0881  ; Command name list
                    0882  ; If list search allows abbreviations then the first match will be accepted
135B:               0883  CmdNameList:
                    0884  ; Single character commands
135B: BF            0885              .DB  128+'?'        ;?        Help
135C: C1            0886              .DB  128+'A'        ;A        Assemble
135D: C2            0887              .DB  128+'B'        ;B        Breakpoint
135E: C4            0888              .DB  128+'D'        ;D        Disassemble
135F: C5            0889              .DB  128+'E'        ;E        Edit memory
1360: C6            0890              .DB  128+'F'        ;F        Flag
1361: C7            0891              .DB  128+'G'        ;G        Go
1362: C9            0892              .DB  128+'I'        ;I        Input from port
1363: CD            0893              .DB  128+'M'        ;M        Memory display
1364: CF            0894              .DB  128+'O'        ;O        Output to port
1365: D2            0895              .DB  128+'R'        ;R        Registers
1366: D3            0896              .DB  128+'S'        ;S        Step
                    0897  ; Full word commands
1367: C1 50 49      0898              .DB  128+'A',"PI"   ;API      API call
136A: C2 41 55 44   0899              .DB  128+'B',"AUD"  ;BAUD     Set baud rate
136E: C3 4F 4E 53   0900              .DB  128+'C',"ONSOLE" ;CONSOLE  Set console device
1372: 4F 4C 45      4849  
1375: C4 45 56 49   0901              .DB  128+'D',"EVICES" ;DEVICES  Devices list
1379: 43 45 53      4850  
137C: C4 49 52      0902              .DB  128+'D',"IR"   ;DIR      Directory
137F: C6 49 4C 4C   0903              .DB  128+'F',"ILL"  ;FILL     Fill memory
1383: C8 45 4C 50   0904              .DB  128+'H',"ELP"  ;HELP     Help
1387: D2 45 53 45   0905              .DB  128+'R',"ESET" ;RESET    Reset
138B: 54            4854  
138C: D2 4F 4D      0906              .DB  128+'R',"OM"   ;ROM      Directory
                    0907  ; Optional commands
                    0908  #IFDEF      IncludeScripting
                    0909              .DB  128+'N',"EW"   ;NEW      New (for script)
                    0910              .DB  128+'O',"LD"   ;OLD      Old (for script)
                    0911              .DB  128+'S',"CRIPT"  ;SCRIPT  Script (list program)
                    0912  #ENDIF
138F: 80            0913              .DB  128            ;List terminator
                    0914  
                    0915  ; Command address list
1390:               0916  CmdAddressList:
                    0917  ; Single character commands
1390: 7A 12         0918              .DW  CmdHelp        ;?        Help
1392: 0D 11         0919              .DW  CmdAssemble    ;A        Assemble
1394: 53 11         0920              .DW  CmdBP          ;B        Breakpoint
1396: 8E 11         0921              .DW  CmdDisassemble ;D        Disassemble
1398: AE 11         0922              .DW  CmdEdit        ;E        Edit memory
139A: 19 12         0923              .DW  CmdFlag        ;F        Flag
139C: 5F 12         0924              .DW  CmdGo          ;G        Go
139E: 88 12         0925              .DW  CmdIn          ;I        In
13A0: 9A 12         0926              .DW  CmdMemory      ;M        Memory display
13A2: BB 12         0927              .DW  CmdOut         ;O        Out
13A4: CC 12         0928              .DW  CmdRegisters   ;R        Registers
13A6: 3B 13         0929              .DW  CmdStep        ;S        Step
                    0930  ; Full word commands
13A8: E9 10         0931              .DW  CmdAPI         ;API      API call
13AA: 56 13         0932              .DW  CmdBaud        ;BAUD     Set baud rate
13AC: 71 11         0933              .DW  CmdConsole     ;CONSOLE  Set console device
13AE: 8B 11         0934              .DW  CmdDevices     ;DEVICES  Devices list
13B0: 56 13         0935              .DW  CmdDir         ;DIR      Directory
13B2: 38 12         0936              .DW  CmdFill        ;FILL     Fill memory
13B4: 7A 12         0937              .DW  CmdHelp        ;HELP     Help
13B6: 00 01         0938              .DW  CmdReset       ;RESET    Reset
13B8: 56 13         0939              .DW  CmdDir         ;ROM      Directory
                    0940  ; Optional commands
                    0941  #IFDEF      IncludeScripting
                    0942              .DW  CmdNew         ;NEW      New
                    0943              .DW  CmdOld         ;OLD      Old
                    0944              .DW  CmdScript      ;SCRIPT   Script 
                    0945  #ENDIF
                    0946  
                    0947  
                    0948  ; Register name list (bit 7 delimited)
13BA:               0949  RegisterNames:
13BA: D0 43         0950              .DB  128+'P','C'    ;PC
13BC: D3 50         0951              .DB  128+'S','P'    ;SP
13BE: A8 29         0952              .DB  128+'(',")"    ;()
13C0: A8 53 50 29   0953              .DB  128+'(',"SP)"  ;(SP)
13C4: C1 46         0954              .DB  128+'A','F'    ;AF
13C6: C2 43         0955              .DB  128+'B','C'    ;BC
13C8: C4 45         0956              .DB  128+'D','E'    ;DE
13CA: C8 4C         0957              .DB  128+'H','L'    ;HL
13CC: C9 58         0958              .DB  128+'I','X'    ;IX
13CE: C9 59         0959              .DB  128+'I','Y'    ;IY
13D0: C1 46 27      0960              .DB  128+'A',"F'"   ;AF'
13D3: C2 43 27      0961              .DB  128+'B',"C'"   ;BC'
13D6: C4 45 27      0962              .DB  128+'D',"E'"   ;DE'
13D9: C8 4C 27      0963              .DB  128+'H',"L'"   ;HL'
13DC: C1            0964              .DB  128+'A'        ;A
13DD: C6            0965              .DB  128+'F'        ;F
13DE: C2            0966              .DB  128+'B'        ;B
13DF: C3            0967              .DB  128+'C'        ;C
13E0: C4            0968              .DB  128+'D'        ;D
13E1: C5            0969              .DB  128+'E'        ;E
13E2: C8            0970              .DB  128+'H'        ;H
13E3: CC            0971              .DB  128+'L'        ;L
13E4: C9            0972              .DB  128+'I'        ;I
13E5: 80            0973              .DB  128            ;List terminator
                    0974  ; Register address list
13E6:               0975  RegisterAddresses:
13E6: 73 A2         0976              .DW  iPC            ;PC
13E8: 81 A2         0977              .DW  iSP            ;SP
13EA: 8B A2         0978              .DW  iCSP           ;()
13EC: 8B A2         0979              .DW  iCSP           ;(SP)
13EE: 75 A2         0980              .DW  iAF            ;AF
13F0: 77 A2         0981              .DW  iBC            ;BC
13F2: 79 A2         0982              .DW  iDE            ;DE
13F4: 7B A2         0983              .DW  iHL            ;HL
13F6: 7D A2         0984              .DW  iIX            ;IX
13F8: 7F A2         0985              .DW  iIY            ;IY
13FA: 83 A2         0986              .DW  iAF2           ;AF'
13FC: 85 A2         0987              .DW  iBC2           ;BC'
13FE: 87 A2         0988              .DW  iDE2           ;DE'
1400: 89 A2         0989              .DW  iHL2           ;HL'
1402: 76 A2         0990              .DW  iAF+1          ;A
1404: 75 A2         0991              .DW  iAF            ;F
1406: 78 A2         0992              .DW  iBC+1          ;B
1408: 77 A2         0993              .DW  iBC            ;C
140A: 7A A2         0994              .DW  iDE+1          ;D
140C: 79 A2         0995              .DW  iDE            ;E
140E: 7C A2         0996              .DW  iHL+1          ;H
1410: 7B A2         0997              .DW  iHL            ;L
1412: 8E A2         0998              .DW  iIR+1          ;H
                    0999  
                    1000  
                    1001  ; Flag names list (bit 7 delimited)
1414: D3            1002  FlagNames:  .DB  128+'S'        ;S    Bit 7, Flag S set to 1 (negative/minus)
1415: CE 53         1003              .DB  128+'N','S'    ;NS   Bit 7, Flag S cleared to 0 (positive)
1417: CD            1004              .DB  128+'M'        ;M    Bit 7, Flag S set to 1 (negative/minus)
1418: D0            1005              .DB  128+'P'        ;P    Bit 7, Flag S cleared to 0 (positive)
1419: DA            1006              .DB  128+'Z'        ;Z    Bit 6, Flag Z set to 1 (zero)
141A: CE 5A         1007              .DB  128+'N','Z'    ;NZ   Bit 6, Flag Z cleared to 0 (not zero)
141C: C8            1008              .DB  128+'H'        ;H    Bit 4, Flag H set to 1 (half carry)
141D: CE 48         1009              .DB  128+'N','H'    ;NH   4it 4, Flag H cleared to 0 (not half carry)
141F: D0 41         1010              .DB  128+'P','A'    ;Pa   Bit 2, Flag P/V set to 1 (even parity or overflow)
1421: CE 50         1011              .DB  128+'N','P'    ;NP   Bit 2, Flag P/V set to 0 (odd parity or no overflow)
1423: D0 45         1012              .DB  128+'P','E'    ;PE   Bit 2, Flag P/V set to 1 (even parity or overflow)
1425: D0 4F         1013              .DB  128+'P','O'    ;Po   Bit 2, Flag P/V set to 0 (odd parity or no overflow)
1427: CE            1014              .DB  128+'N'        ;N    Bit 1, Flag N set to 1 (subtract)
1428: CE 4E         1015              .DB  128+'N','N'    ;NN   Bit 1, Flag N cleared to 0 (add)
142A: C3            1016              .DB  128+'C'        ;C    Bit 0, Flag C set to 1 (carry)
142B: CE 43         1017              .DB  128+'N','C'    ;NC   Bit 0, Flag C cleared to 0 (not carry)
142D: 80            1018              .DB  128            ;List terminator
                    1019  ; Flag manipulation list 
                    1020  ; Lo byte is ANDed with flags register, then Hi byte is ORed with flags register
                    1021  ; Yes, we could drive this from one byte but we are using the existing list handlers
                    1022  ; which need words, so might as well specify both AND and OR values!
142E: 7F 80         1023  FlagLogic:  .DB  0x7F,0x80      ;S    Bit 7, Flag S set to 1 (negative/minus)
1430: 7F 00         1024              .DB  0x7F,0x00      ;NS   Bit 7, Flag S cleared to 0 (positive)
1432: 7F 80         1025              .DB  0x7F,0x80      ;M    Bit 7, Flag S set to 1 (negative/minus)
1434: 7F 00         1026              .DB  0x7F,0x00      ;P    Bit 7, Flag S cleared to 0 (positive)
1436: BF 40         1027              .DB  0xBF,0x40      ;Z    Bit 6, Flag Z set to 1 (zero)
1438: BF 00         1028              .DB  0xBF,0x00      ;NZ   Bit 6, Flag Z cleared to 0 (not zero)
143A: EF 10         1029              .DB  0xEF,0x10      ;H    Bit 4, Flag H set to 1 (half carry)
143C: EF 00         1030              .DB  0xEF,0x00      ;NH   4it 4, Flag H cleared to 0 (not half carry)
143E: FB 04         1031              .DB  0xFB,0x04      ;Pa   Bit 2, Flag P/V set to 1 (even parity or overflow)
1440: FB 00         1032              .DB  0xFB,0x00      ;NP   Bit 2, Flag P/V set to 0 (odd parity or no overflow)
1442: FB 04         1033              .DB  0xFB,0x04      ;PE   Bit 2, Flag P/V set to 1 (even parity or overflow)
1444: FB 00         1034              .DB  0xFB,0x00      ;Po   Bit 2, Flag P/V set to 0 (odd parity or no overflow)
1446: FD 02         1035              .DB  0xFD,0x02      ;N    Bit 1, Flag N set to 1 (subtract)
1448: FD 00         1036              .DB  0xFD,0x00      ;NN   Bit 1, Flag N cleared to 0 (add)
144A: FE 01         1037              .DB  0xFE,0x01      ;C    Bit 0, Flag C set to 1 (carry)
144C: FE 00         1038              .DB  0xFE,0x00      ;NC   Bit 0, Flag C cleared to 0 (not carry)
                    1039  
                    1040  
                    1041  ; **********************************************************************
                    1042  ; **  Private workspace (in RAM)                                      **
                    1043  ; **********************************************************************
                    1044  
                    1045              .DATA
                    1046  
A2A1: 00 00         1047  iParam1:    .DW  0x0000         ;CLI parameter 1
                    1048  
                    1049  #IFDEF      IncludeMiniTerm
                    1050  iMiniTerm:  .DB  0x00           ;Mini terminal flag
                    1051  #ENDIF
                    1052  
                    1053              .CODE
                    1054  
                    1055  ; **********************************************************************
                    1056  ; **  End of Command Line Interpreter                                 **
                    1057  ; **********************************************************************
                    1058  
                    0063  #ENDIF
                    0064  #IFDEF      IncludeDisassemble
                    0065  #INCLUDE    Monitor\Disassembler.asm  ;In-line disassembler
                    0001  ; **********************************************************************
                    0002  ; **  Disassembler support                      by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module provides instruction disassembly support. There are two
                    0006  ; main public functions which disassemble an instruction and provide the
                    0007  ; result as a string in the current string buffer. These are:
                    0008  ;
                    0009  ; Function: DisWrInstruction
                    0010  ; This returns a string in the format: Address: Opcodes  Mnemonic
                    0011  ; eg.   0300: CD FB 01       CALL 0x1FB
                    0012  ; It also returns the length of the instruction in bytes and the 
                    0013  ; address of the next instruction.
                    0014  ;
                    0015  ; Function: DisWrMnemonic
                    0016  ; This returns a string in the format: Mnemonic only
                    0017  ; eg.   CALL 0x1FB
                    0018  ; It also returns the length of the instruction in bytes.
                    0019  ;
                    0020  ; This module also provides the public helper function:
                    0021  ;
                    0022  ; Function: DisGetNextAddress
                    0023  ; Returns address of next instruction to be executed. This is used by 
                    0024  ; the single stepping feature. It takes into account flags to determine
                    0025  ; outcome of conditional instructions.
                    0026  ;
                    0027  ; Further documentation and notes are at the end of this file.
                    0028  ;
                    0029  ; Public functions provided
                    0030  ;   DisWrInstruction      Returns string if full details
                    0031  ;   DisWrMnemonic         Returns string of mnemonic only
                    0032  ;   DisGetNextAddress     Returns address of next instruction
                    0033  ; Private support function (not intended to be called from outside)
                    0034  ;   DisWrOperand          Process suppied operand
                    0035  ;   DisGetOpcode          Get instruction opcode
                    0036  ;   DisWrChar             Write a character to the buffer with filters
                    0037  ;   DisWrString           Write a string to the buffer with filters
                    0038  
                    0039  
                    0040  ; **********************************************************************
                    0041  ; **  Constants                                                       **
                    0042  ; **********************************************************************
                    0043  
0005:               0044  kDisBrack:  .EQU 5              ;Bracket flag
0004:               0045  kDisImmed:  .EQU 4              ;Immediate value flag
0003:               0046  kDisWord:   .EQU 3              ;Immediate value is word (not byte) flag
144E:               0047  kDisLength:
                    0047  kDisLength: .EQU 2              ;Substite two characters (not one) flag
0003:               0048  kDisMask:   .EQU 0x03           ;Mask type 0=0x07,1=0x18,2=0x30,3=0x38
                    0049  ; Should create EQUates for all numeric values used below. It's the law!
                    0050  
                    0051  
                    0052  ; **********************************************************************
                    0053  ; **  Public functions                                                **
                    0054  ; **********************************************************************
                    0055  
                    0056              .CODE
                    0057  
                    0058  ; Disassembler: Write full disassembly to string buffer
                    0059  ;   On entry: HL = Start of instruction to be disassembled
                    0060  ;   On exit:  Address, opcodes and mnemonic in current string buffer
                    0061  ;             iDisIndex variable used
                    0062  ;             A = Length of instruction in bytes
                    0063  ;             HL = Start address of next instruction
                    0064  ;             BC DE IX IY I AF' BC' DE' HL' preserved
144E:               0065  DisWrInstruction:
144E: C5            0066              PUSH BC
144F: D5            0067              PUSH DE
1450: 3E 14         0068              LD   A,20           ;Select string for mnemonic...
1452: 11 D0 A1      0069              LD   DE,kStrBuffer+80 ;Length 20 at end of default string
1455: CD 91 06      0070              CALL StrInitialise  ;Initialise string for mnemonic
1458: CD 8B 14      0071              CALL DisWrMnemonic  ;Disassemble to mnemonic string
145B: 4F            0072              LD   C,A            ;Store length of instruction in bytes
                    0073  ;           XOR  A              ;CLear A to zero
145C: CD 8A 06      0074              CALL StrInitDefault ;Select default string for opcodes
145F: 54            0075              LD   D,H            ;Get start of instruction..
1460: 5D            0076              LD   E,L
1461: CD C4 06      0077              CALL StrWrAddress   ;Write address, colon and space
1464: 41            0078              LD   B,C            ;Get length of instruction
1465: 7E            0079  @Opcode:    LD   A,(HL)         ;Get instruction opcode
1466: CD EF 06      0080              CALL StrWrHexByte   ;Write as hex byte
1469: CD 35 07      0081              CALL StrWrSpace     ;Write space
146C: 23            0082              INC  HL             ;Point to next byte 
146D: 10 F6         0083              DJNZ @Opcode        ;Loop until all hex bytes written
146F: 3E 13         0084              LD   A,19           ;Column number
1471: CD 22 07      0085              CALL StrWrPadding   ;Pad with spaces to specified column
1474: 41            0086              LD   B,C            ;Get length of instruction
1475: 1A            0087  @Ascii:     LD   A,(DE)         ;Get instruction opcode
1476: CD D2 06      0088              CALL StrWrAsciiChar ;Write as ASCII character
1479: 13            0089              INC  DE             ;Point to next byte 
147A: 10 F9         0090              DJNZ @Ascii         ;Loop until all characters written
147C: 3E 19         0091              LD   A,25           ;Column number
147E: CD 22 07      0092              CALL StrWrPadding   ;Pad with spaces to specified column
1481: 11 D0 A1      0093  @Mnemonic:  LD   DE,kStrBuffer+80
1484: CD 2A 06      0094              CALL StrAppend      ;Append disassembly string
                    0095  ;           CALL StrWrNewLine   ;Write new line to string buffer
1487: 79            0096              LD   A,C            ;Get length of instruction in bytes
1488: D1            0097              POP  DE
1489: C1            0098              POP  BC
148A: C9            0099              RET
                    0100  
                    0101  
                    0102  ; Disassembler: Write mnemonic only to string buffer
                    0103  ;   On entry: HL = Start of instruction to be disassembled
                    0104  ;   On exit:  Mnemonic is written to current string buffer
                    0105  ;             iDisIndex variable used
                    0106  ;             A = Length of instruction in bytes
                    0107  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
148B:               0108  DisWrMnemonic:
148B: C5            0109              PUSH BC
148C: D5            0110              PUSH DE
148D: E5            0111              PUSH HL
148E: DD E5         0112              PUSH IX
1490: FD E5         0113              PUSH IY
                    0114  ; Prepare to disassemble 
                    0115  ; HL = Address of current instruction
1492: E5            0116              PUSH HL             ;Copy start address of instruction
1493: FD E1         0117              POP  IY             ;  to IY 
1495: DD 21 8C 18   0118              LD   IX,DisInst     ;Start of instruction table
1499: AF            0119              XOR  A
149A: 32 A3 A2      0120              LD   (iDisIndex),A  ;Clear index instruction opcode
149D: 5F            0121              LD   E,A            ;Clear prefix for extended instructions
149E: 56            0122              LD   D,(HL)         ;Instruction's primary opcode 
149F: 47            0123              LD   B,A            ;Offset to instruction's primary opcode
                    0124  ; Check for index register instruction (IX or IY)
14A0: 7A            0125              LD   A,D            ;Could have been written LD A,(IY+0)
14A1: FE DD         0126              CP   0xDD           ;IX instruction?
14A3: 28 04         0127              JR   Z,@Index       ;Yes, so skip
14A5: FE FD         0128              CP   0xFD           ;IY instruction?
14A7: 20 07         0129              JR   NZ,@NotIndex   ;No, so skip
14A9: 32 A3 A2      0130  @Index:     LD   (iDisIndex),A  ;Store index instruction opcode
14AC: 04            0131              INC  B              ;Increment offset to primary opcode
14AD: FD 7E 01      0132              LD   A,(IY+1)       ;Get next opcode byte
0000:               0133  @NotIndex:
                    0134  ; Check for extended instruction
14B0: FE CB         0135              CP   0xCB           ;Extended instruction?
14B2: 28 04         0136              JR   Z,@Extend      ;Yes, so skip
14B4: FE ED         0137              CP   0xED           ;Extended instruction?
14B6: 20 0D         0138              JR   NZ,@NotExtend  ;No, so skip
14B8: 5F            0139  @Extend:    LD   E,A            ;Store prefix for extended instructions
14B9: 04            0140              INC  B              ;Increment offset to primary opcode
14BA: 3A A3 A2      0141              LD   A,(iDisIndex)  ;Get index instruction opcode
14BD: B7            0142              OR   A              ;Is this an index instruction?
14BE: 78            0143              LD   A,B            ;Prepare to read primary opcode
14BF: 28 01         0144              JR   Z,@ExNoIndx    ;No, so skip
14C1: 3C            0145              INC  A              ;Yes, skip index displacement byte
14C2: CD 87 16      0146  @ExNoIndx:  CALL DisGetOpcode   ;Get primary opcode
14C5:               0147  @NotExtend:
14C5: 57            0147  @NotExtend: LD   D,A            ;Remember instruction's primary opcode
14C6: 32 A6 A2      0148              LD   (iDisOpcode),A ;Store primary opcode
                    0149  ; Locate instruction table entry for current instruction (pointer to by HL)
                    0150  ; BASIC: (i And iMask(n)) = (iValue(n) And iMask(n)) ?
14C9: DD 7E 00      0151  @Table:     LD   A,(IX+0)       ;Get opcode value from table
14CC: DD A6 01      0152              AND  (IX+1)         ;AND with opcode mask from table
14CF: 4F            0153              LD   C,A            ;Store Value AND Mask
14D0: DD 7E 01      0154              LD   A,(IX+1)       ;Get opcode mask from table
14D3: A2            0155              AND  D              ;AND with instruction being disassembled
14D4: B9            0156              CP   C              ;Is this the correct table entry?
14D5: 20 14         0157              JR   NZ,@NotFound   ;No, so this is not the correct table
                    0158  ; BASIC: ... AND (p = iPrecode(n)) ?
14D7: AF            0159              XOR  A              ;Default precode for comparison = 0x00
14D8: DD CB 03 7E   0160              BIT  7,(IX+3)       ;Precode (index or extended)?
14DC: 28 0A         0161              JR   Z,@GotPrCode   ;No, so skip
14DE: 3E CB         0162              LD   A,0xCB         ;Default precode for comparison = 0xCB
14E0: DD CB 03 76   0163              BIT  6,(IX+3)       ;Precode = 0xED?
14E4: 28 02         0164              JR   Z,@GotPrCode   ;No, so skip
14E6: 3E ED         0165              LD   A,0xED         ;Yes, so precode for comparison = 0xED
14E8:               0166  @GotPrCode:
14E8: BB            0166  @GotPrCode: CP   E              ;Compare table precode with instruction
14E9: 28 09         0167              JR   Z,@Found       ;Yes, so this is the correct table
14EB: C5            0168  @NotFound:  PUSH BC             ;Preserve BC
14EC: 01 05 00      0169              LD   BC,5           ;No, so try next table entry
14EF: DD 09         0170              ADD  IX,BC          ;Point to next table entry
14F1: C1            0171              POP  BC             ;Restore BC
14F2: 18 D5         0172              JR   @Table
                    0173  ; We now have the correct instruction table entry (pointer to by IX)
                    0174  ; BASIC: (p = iPrecode(n)) And (i And iMask(n)) = (iValue(n) And iMask(n))
14F4: DD 7E 02      0175  @Found:     LD   A,(IX+2)       ;Get operation string number
14F7: 32 A4 A2      0176              LD   (iDisOpStr),A  ;Store operation string number
14FA: CD A9 16      0177              CALL DisWrString    ;Write operation string
14FD: CD 35 07      0178              CALL StrWrSpace
                    0179  ; BASIC: Operand sString(iOperand1(n)), t
1500: DD 7E 03      0180              LD   A,(IX+3)       ;Get operand #1 string number
1503: 32 A5 A2      0181              LD   (iDisOp1Str),A ;Store opcode #1 string number
1506: 4A            0182              LD   C,D            ;Get primary opcode value
1507: CD F0 15      0183              CALL DisWrOperand
                    0184  ; BASIC: Operand sString(iOperand2(n)), t
150A: DD 7E 04      0185              LD   A,(IX+4)       ;Get operand #2 string number
150D: 3D            0186              DEC  A              ;Is is 1? (null string)
150E: 28 0C         0187              JR   Z,@NoOp2       ;Yes, so skip this operand
1510: 3E 2C         0188              LD   A,','          ;Get comma character
1512: CD DB 06      0189              CALL StrWrChar      ;Write comma to string
1515: DD 7E 04      0190              LD   A,(IX+4)       ;Get operand #2 string number
1518: 4A            0191              LD   C,D            ;Get primary opcode value
1519: CD F0 15      0192              CALL DisWrOperand
0000:               0193  @NoOp2:
                    0194  ; If relative jump show absolute address in brackets
151C: 3A A4 A2      0195              LD   A,(iDisOpStr)  ;Get operation string number
151F: FE 1B         0196              CP   kDisJR         ;JR instruction?
1521: 28 04         0197              JR   Z,@Rel         ;Yes, so skip
1523: FE 1C         0198              CP   kDisDJNZ       ;DJNZ instruction?
1525: 20 24         0199              JR   NZ,@NotRel     ;No so skip
1527: 11 FD 16      0200  @Rel:       LD   DE,szDisTo     ;String = "  (to "
152A: CD 3D 06      0201              CALL StrAppendZ     ;Append zero terminated string
152D: FD E5         0202              PUSH IY             ;Push address of instruction
152F: E1            0203              POP  HL             ;POP address of instruction
1530: 23            0204              INC  HL             ;Increment to
1531: 23            0205              INC  HL             ;  end of the JR/DJNZ instruction
1532: 3A A7 A2      0206              LD   A,(iDisImmed)  ;Get immediate value from instruction
1535: 5F            0207              LD   E,A            ;Get displacement lo (signed byte)
1536: 16 00         0208              LD   D,0            ;Default to hi byte = zero
1538: CB 7F         0209              BIT  7,A            ;Displacement negative?
153A: 28 01         0210              JR   Z,@JRadd       ;No, so skip
153C: 15            0211              DEC  D              ;Yes, so set hi byte to 0xFF
153D: 19            0212  @JRadd:     ADD  HL,DE          ;Add signed 16-bit displacement
153E: 54            0213              LD   D,H            ;Get destination address hi byte
153F: 5D            0214              LD   E,L            ;Get destination address lo byte
1540: CD 6E 08      0215              CALL WrHexPrefix    ;Write hex prefix to string
1543: CD 0F 07      0216              CALL StrWrHexWord   ;Write hex word to string
1546: 3E 29         0217              LD   A,')'          ;Get close bracket character
1548: CD DB 06      0218              CALL StrWrChar      ;Write close bracket to string
0000:               0219  @NotRel:
                    0220  ; Finish building mnemonic string
154B: 78            0221              LD   A,B            ;Get offset into instruction
154C: 3C            0222              INC  A              ;Increment to give instruction length
154D: FD E1         0223              POP  IY
154F: DD E1         0224              POP  IX
1551: E1            0225              POP  HL
1552: D1            0226              POP  DE
1553: C1            0227              POP  BC
1554: C9            0228              RET
                    0229  
                    0230  
                    0231  ; Disassembler: Get address of next instruction
                    0232  ;   On entry: HL = Next address ignoring flow control instructions
                    0233  ;             Next instruction
                    0234  ;   On exit:  HL = Next address after consider flow instructions
                    0235  ;             AF BC DE IX IY I AF' BC' DE' HL' preserved
                    0236  ; Just prior to this function the next instruction must have been
                    0237  ; disassembled so instruction details are available in iDisXXXX
                    0238  ; workspace. Also breakpoint register values must be in workspace.
1555:               0239  DisGetNextAddress:
1555: F5            0240              PUSH AF
1556: C5            0241              PUSH BC
1557: D5            0242              PUSH DE
                    0243  ; Determine if last instruction may have changed program flow
1558: 3A A4 A2      0244              LD   A,(iDisOpStr)  ;Get operation string number
155B: FE 1B         0245              CP   kDisFlowF      ;Compare with first flow control instr
155D: 38 5C         0246              JR   C,@Done2       ;Not a flow instruction so we're done
155F: FE 23         0247              CP   kDisFlowL+1    ;Compare with first flow control instr
1561: 30 58         0248              JR   NC,@Done2      ;Not a flow instruction so we're done
                    0249  ; The current instruction is a flow controlling instruction eg. CALL
                    0250  ; Consider if the instruction is conditional or not by looking at
                    0251  ; operand 1 string number to see if it is the operand substitution
                    0252  ; string "c" or "cc" (for conditions NZ,Z,NC,C,PO,PE,P,M)
1563: 3A A5 A2      0253              LD   A,(iDisOp1Str) ;Get operand 1 string number
1566: 06 18         0254              LD   B,kDisMskC     ;Prepare condition 'c' mask
1568: FE 0A         0255              CP   kDisSubC       ;Is operand 'c'? eg. 'Z' in 'JR Z,addr'
156A: 28 06         0256              JR   Z,@Condition   ;Yes, so go handle condition
156C: 06 38         0257              LD   B,kDisMskCC    ;Prepare condition 'cc' mask
156E: FE 0B         0258              CP   kDisSubCC      ;Is operand 'cc'? eg. 'PE' in 'JP PE,addr'
1570: 20 1B         0259              JR   NZ,@NoCond     ;No, so skip condition evaluation
                    0260  ; Evaluate condition. B is the conditions bit mask
1572:               0261  @Condition:
1572: 3A A6 A2      0261  @Condition: LD   A,(iDisOpcode) ;Get instruction's primary opcode
1575: A0            0262              AND  B              ;Mask to give condition bits, Cy=0
1576: 1F            0263              RRA                 ;Shift condition bits to bits 0 to 1
1577: 1F            0264              RRA                 ;  to give offset in table
1578: 1F            0265              RRA                 ;  for each coded condition
1579: 1F            0266              RRA                 ;  plus flag state in Carry
157A: 47            0267              LD   B,A            ;Set up table loop counter
                    0268  ; Condition table contains one byte for each flag condition:
                    0269  ; 0=NZ/Z, 1=NC/C,2=PO/PE, 3=P/M and C set for Z, C, PE and M
                    0270  ; The values in the table are bit masks for the flags register
                    0271  ; which is ORed with Flags register to test if flag is set, and 
                    0272  ; then exclusively ORed with flags register to test if not set.
157B: E5            0273              PUSH HL
157C: 21 21 17      0274              LD   HL,DisConTab-1 ;Point to start of condition table -1
157F: 04            0275              INC  B              ;Increment loop counter
1580: 23            0276  @IncPtr:    INC  HL             ;Inc pointer into condition table
1581: 10 FD         0277              DJNZ @IncPtr        ;Go inc again until we are there
1583: 3A 75 A2      0278              LD   A,(iAF)        ;Get flags register value
1586: 38 01         0279              JR   C,@ConTest     ;Looking for flag low?
1588: AE            0280              XOR  (HL)           ;Yes, so invert required flag bit
1589: A6            0281  @ConTest:   AND   (HL)          ;Mask required flag bit (clears Cy)
158A: E1            0282              POP  HL
158B: 28 5F         0283              JR   Z,@Done        ;We're done if condition not met
                    0284  ; Determine address after executing the flow controlling instruction
                    0285  ; when the condition is met (if there is a condition)
158D: 3A A4 A2      0286  @NoCond:    LD   A,(iDisOpStr)  ;Get operation string number
1590: FE 1F         0287              CP   kDisCALL       ;Instruction = "CALL"
1592: 28 55         0288              JR   Z,@CALL
1594: FE 1C         0289              CP   kDisDJNZ       ;Instruction = "DJNZ"
1596: 28 11         0290              JR   Z,@DJNZ
1598: FE 1E         0291              CP   kDisJP         ;Instruction = "JP"
159A: 28 21         0292              JR   Z,@JP
159C: FE 1B         0293              CP   kDisJR         ;Instruction = "JR"
159E: 28 0F         0294              JR   Z,@JR
15A0: FE 1D         0295              CP   kDisRST        ;Instruction = "RST"
15A2: 28 3B         0296              JR   Z,@RST
                    0297  ; Instruction: RET or RET cc or RETI or RETN
15A4: 2A 81 A2      0298  @RET:       LD   HL,(iSP)       ;Get stack pointer at breakpoint
15A7: 18 30         0299              JR   @JP2           ;Go to addess pointed to by HL
                    0300  ; Instruction: DJNZ n
15A9: 3A 78 A2      0301  @DJNZ:      LD   A,(iBC+1)      ;Get register B value
15AC: 3D            0302              DEC   A             ;Will B reach zero?
15AD: 28 3D         0303              JR   Z,@Done        ;Yes, so we're done
                    0304  ;           JR   @JR            ;No, so go treat as JR instruction
                    0305  ; Instruction: JR n or JR c,n
15AF: 3A A7 A2      0306  @JR:        LD   A,(iDisImmed)  ;Get immediate value from instruction
15B2: 5F            0307              LD   E,A            ;Get displacement lo (signed byte)
15B3: 16 00         0308              LD   D,0            ;Default to hi byte = zero
15B5: CB 7F         0309              BIT  7,A            ;Displacement negative?
15B7: 28 01         0310              JR   Z,@JRadd       ;No, so skip
15B9: 15            0311              DEC  D              ;Yes, so set hi byte to 0xFF
15BA: 19            0312  @JRadd:     ADD  HL,DE          ;Add signed 16-bit displacement
15BB: 18 2F         0313  @Done2:     JR   @Done
                    0314  ; Instruction: JP nn or JP cc,nn or JP HL or JP IX or JP IY
15BD: 3A A5 A2      0315  @JP:        LD   A,(iDisOp1Str) ;Get operand 1 string number
15C0: FE 0B         0316              CP   kDisSubCC      ;Is operand 'cc'? eg. 'PE' in 'JP PE,addr'
15C2: 28 25         0317              JR   Z,@GOTOnn      ;Yes, so goto address nn
15C4: FE 04         0318              CP   kDisSubNN      ;Instruction = JP nn ?
15C6: 28 21         0319              JR   Z,@GOTOnn      ;Yes, so goto address nn
                    0320  ; Instruction: JP HL or JP IX or JP IY
15C8: 21 7B A2      0321              LD   HL,iHL         ;Point to register storage for HL
15CB: 3A A3 A2      0322              LD   A,(iDisIndex)  ;Index register instruction?
15CE: B7            0323              OR   A              ;No, so go JP 
15CF: 28 08         0324              JR   Z,@JP2
15D1: 23            0325              INC  HL             ;Point to register storage for IX
15D2: 23            0326              INC  HL
15D3: FE DD         0327              CP   0xDD           ;Instruction = JP IX
15D5: 28 02         0328              JR   Z,@JP2
15D7: 23            0329              INC  HL             ;Point to register storage for IX
15D8: 23            0330              INC  HL
                    0331  ; Go to the address pointed to by HL
15D9: 7E            0332  @JP2:       LD   A,(HL)         ;Get lo byte of new address
15DA: 23            0333              INC  HL             ;Point to hi byte
15DB: 66            0334              LD   H,(HL)         ;Get hi byte of new address
15DC: 6F            0335              LD   L,A            ;Get lo byte of newreturn address
15DD: 18 0D         0336              JR   @Done
                    0337  ; Instruction: RST n
15DF: 3A A6 A2      0338  @RST:       LD   A,(iDisOpcode) ;Get primary opcode
15E2: E6 38         0339              AND  A,kDisMskRST   ;Mask off unwanted bits
15E4: 6F            0340              LD   L,A            ;Store as lo byte of new address
15E5: 26 00         0341              LD   H,0            ;Clear hi byte of new address
15E7: 18 03         0342              JR   @Done
                    0343  ; Instruction: CALL nn or CALL cc,nn
0000:               0344  @CALL:      ;JR  @JP            ;Treat as JP instruction
                    0345  ; Instruction: CALL nn or CALL cc,nn or JP nn pr JP cc,nn
15E9: 2A A7 A2      0346  @GOTOnn:    LD   HL,(iDisImmed) ;Get immediate value from instruction
                    0347  ;           JR   @Done
15EC: D1            0348  @Done:      POP  DE
15ED: C1            0349              POP  BC
15EE: F1            0350              POP  AF
15EF: C9            0351              RET
                    0352  
                    0353  
                    0354  ; **********************************************************************
                    0355  ; **  Private functions                                               **
                    0356  ; **********************************************************************
                    0357  
                    0358  
                    0359  ; Disassembler: Write operand to buffer
                    0360  ;   On entry: A = Operand string number
                    0361  ;             B = Offset to opcode from start of instruction
                    0362  ;             C = Primary op-code
                    0363  ;             IY = Start address of instruction
                    0364  ;   On exit:  A = Unspecified
                    0365  ;             B = Updated offset to opcode from start of instruction
                    0366  ;             C = Not specified
                    0367  ;             DE HL IX IY I AF' BC' DE' HL' preserved
15F0:               0368  DisWrOperand:
15F0: E6 3F         0369              AND  kDisOpMask     ;Mask off flag bits
15F2: FE 0E         0370              CP   kDisSubsL+1    ;Substitution operand string?
15F4: D2 A9 16      0371              JP   NC,DisWrString ;No, so just write string
15F7:               0372  @DisSubStr:
15F7: D5            0372  @DisSubStr: PUSH DE
15F8: E5            0373              PUSH HL
                    0374  ; Calculate operand table location for this operand and get details
15F9: 21 02 17      0375              LD   HL,DisOperandTable-2
15FC: 87            0376              ADD  A,A            ;Two bytes per entry
15FD: 85            0377              ADD  A,L            ;Add to start of table
15FE: 6F            0378              LD   L,A            ;Store updated lo byte
15FF: 30 01         0379              JR   NC,@NoOverFlo  ;Skip if no overflow
1601: 24            0380              INC  H              ;Overflow so increment hi byte
1602:               0381  @NoOverFlo:
1602: 5E            0381  @NoOverFlo: LD   E,(HL)         ;Get substitution string number
1603: 23            0382              INC  HL             ;Point to BIILMM bits
1604: 56            0383              LD   D,(HL)         ;Get BIILMM function bits
1605: D5            0384              PUSH DE             ;So we can use E for scratch reg
                    0385  ; Process this operand as detailed in DE, left bracket?
1606: CB 6A         0386              BIT  kDisBrack,D    ;Bracket flagged?
1608: 28 05         0387              JR   Z,@NoBracL     ;No, so skip
160A: 3E 28         0388              LD   A,'('          ;Get left bracket character
160C: CD DB 06      0389              CALL StrWrChar      ;Print left bracket
0000:               0390  @NoBracL:   
                    0391  ; Process this operand as detailed in DE, immediate value?
160F: CB 62         0392              BIT  kDisImmed,D    ;Immediate value flagged?
1611: 28 1F         0393              JR   Z,@NoImmedia   ;No, so skip
1613: CD 6E 08      0394              CALL WrHexPrefix    ;Print "0x" (or whatever we use)
1616: 04            0395              INC  B              ;Increment offset to lo byte
1617: 78            0396              LD   A,B            ;Offset to instruction byte
1618: CD 87 16      0397              CALL DisGetOpcode   ;Get lo byte of immediate value
161B: 32 A7 A2      0398              LD   (iDisImmed),A  ;Store lo byte of immediate value
161E: 5F            0399              LD   E,A            ;Store lo byte of immediate value
161F: CB 5A         0400              BIT  kDisWord,D     ;Immediate value is a word?
1621: 28 0B         0401              JR   Z,@ImmedLo     ;No, so skip
1623: 04            0402              INC  B              ;Increment offset to hi byte
1624: 78            0403              LD   A,B            ;Offset to instruction byte
1625: CD 87 16      0404              CALL DisGetOpcode   ;Get hi byte of immediate value
1628: 32 A8 A2      0405              LD   (iDisImmed+1),A  ;Store hi byte of immediate value
162B: CD EF 06      0406              CALL StrWrHexByte   ;Print hi byte of immediate value
162E: 7B            0407  @ImmedLo:   LD   A,E            ;Restore lo byte of immediate value
162F: CD EF 06      0408              CALL StrWrHexByte   ;Print lo byte of immediate value
1632:               0409  @NoImmedia:
                    0410  ; Process this operand as detailed in DE, right bracket?
1632: CB 6A         0411              BIT  kDisBrack,D    ;Bracket flagged?
1634: 28 05         0412              JR   Z,@NoBracR     ;No, so skip
1636: 3E 29         0413              LD   A,')'          ;Get right bracket character
1638: CD DB 06      0414              CALL StrWrChar      ;Print right bracket
0000:               0415  @NoBracR:   
                    0416  ; Process this operand as detailed in DE, substitution string?
163B: D1            0417              POP  DE             ;Restore details
163C: 7B            0418              LD   A,E            ;Get substitution string number
163D: B7            0419              OR   A              ;String specified?
163E: 28 44         0420              JR   Z,@SubEnd      ;No, so skip
1640: 7A            0421              LD   A,D            ;Get BIILMM function bits
1641: E6 03         0422              AND  A,kDisMask     ;Separate mask type bits
1643: 21 1E 17      0423              LD   HL,DisMaskTable  ;Point to table of mask bits
1646: 85            0424              ADD  A,L            ;Add to start of table
1647: 6F            0425              LD   L,A            ;Store updated lo byte
1648: 30 01         0426              JR   NC,@NoOFlow    ;Skip if no overflow
164A: 24            0427              INC  H              ;Overflow so increment hi byte
164B: 7E            0428  @NoOFlow:   LD   A,(HL)         ;Get bit mask
164C: A1            0429              AND  A,C            ;Mask primary opcode
164D: 4F            0430              LD   C,A            ;Store masked primary opcode
164E: 7E            0431              LD   A,(HL)         ;Get bit mask
                    0432  ; Now shift primary opcode (masked) to right the number of
                    0433  ; times it takes to shift mask byte right before bit 1 is set
164F:               0434  @SubsShift:
164F: CB 3F         0434  @SubsShift: SRL  A              ;Shift mask right
1651: 38 04         0435              JR   C,@DoneShift   ;Bit 1 was set so we're done
1653: CB 39         0436              SRL  C              ;Shift primary opcode (masked) right
1655: 18 F8         0437              JR   @SubsShift     ;Go repeat..
1657:               0438  @DoneShift:
1657: CB 52         0438  @DoneShift: BIT  kDisLength,D   ;Length bit flagged?
1659: 28 02         0439              JR   Z,@Single      ;No, so skip
165B: CB 21         0440              SLA  C              ;Double value for two bytes
                    0441  ; C is now the offset into the substitute string
165D: 7B            0442  @Single:    LD   A,E            ;Substitute string number
165E: 21 26 17      0443              LD   HL,DisString   ;Start of string list
1661: CD F6 07      0444              CALL FindStringInList ;Get start of string (=HL)
1664: 79            0445              LD   A,C            ;Offset into string
1665: 85            0446              ADD  A,L            ;Add to start of string
1666: 6F            0447              LD   L,A            ;Store updated lo byte
1667: 30 01         0448              JR   NC,@NoOver     ;Skip if no overflow
1669: 24            0449              INC  H              ;Overflow so increment hi byte
166A: 7E            0450  @NoOver:    LD   A,(HL)         ;Get substitute character
166B: FE 2A         0451              CP   '*'            ;Code for 2 byte HL/IX/IY string
166D: 20 07         0452              JR   NZ,@NotStar    ;No, so skip
166F: 3E 18         0453              LD   A,24           ;String = "HL"
1671: CD A9 16      0454              CALL DisWrString    ;Print string with substitutions
1674: 18 0E         0455              JR   @SubEnd
1676: CD 96 16      0456  @NotStar:   CALL DisWrChar      ;Print character with filters
1679: CB 52         0457              BIT  kDisLength,D   ;Length bit flagged?
167B: 28 07         0458              JR   Z,@SubEnd      ;No, so skip
167D: 23            0459              INC  HL             ;Point to second substitute character
167E: 7E            0460              LD   A,(HL)         ;Get substitute character
167F: FE 2E         0461              CP   '.'            ;Do not print '.' character
1681: C4 96 16      0462              CALL NZ,DisWrChar   ;Print character with filters
1684: E1            0463  @SubEnd:    POP  HL
1685: D1            0464              POP  DE
1686: C9            0465              RET
                    0466  
                    0467  
                    0468  ; Disassembler: Get instruction opcode
                    0469  ;   On entry: A = Offset from start of instruction
                    0470  ;             IY = Start of instruction
                    0471  ;   On exit:  A = Opcode
                    0472  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
1687:               0473  DisGetOpcode:
1687: C5            0474              PUSH BC
1688: FD E5         0475              PUSH IY
168A: 4F            0476              LD   C,A            ;Offset from start of instruction
168B: 06 00         0477              LD   B,0            ;Clear hi byte ready for addition
168D: FD 09         0478              ADD  IY,BC          ;Calculate location of opcode
168F: FD 7E 00      0479              LD   A,(IY+0)       ;Get opcode from memory
1692: FD E1         0480              POP  IY
1694: C1            0481              POP  BC
1695: C9            0482              RET
                    0483  
                    0484  
                    0485  ; Disassembler: Write character to string buffer
                    0486  ;   On entry: A = Character to write
                    0487  ;   On exit:  AF BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0488  ; This version of write character removes bit 7 (the new string flag)
                    0489  ; and replaces "-" with "(HL)"
0000:               0490  DisWrChar:
1696: F5            0491              PUSH AF
1697: E6 7F         0492              AND  A,0x7F         ;Mask off bit 7 (string start bit)
1699: FE 2D         0493              CP   '-'            ;Code for "(HL)" ?
169B: 28 05         0494              JR   Z,@SubHL       ;Yes, so go write "(HL)" instead
169D: CD DB 06      0495              CALL StrWrChar      ;Print character
16A0: 18 05         0496              JR   @Done
16A2: 3E 15         0497  @SubHL:     LD   A,21           ;String number for "(HL)"
16A4: CD A9 16      0498              CALL DisWrString    ;Write "(HL)" instead of "-"
16A7: F1            0499  @Done:      POP  AF
16A8: C9            0500              RET                 ;JP instead to save byte
                    0501  
                    0502  
                    0503  ; Write disassembler string
                    0504  ;   On entry: A = Disassembler data string number
                    0505  ;             B = Offset to current opcode from start of instruction
                    0506  ;             IY = Start address for current instruction
                    0507  ;             (iDisIndex) = Index instruction opcode or zero
                    0508  ;   On exit:  AF C DE HL IX IY I AF' BC' DE' HL' preserved
                    0509  ;             B is incremented if (IX/IY+d) is substituted
                    0510  ; This version of write string removes bit 7 (the new string flag)
                    0511  ; If iDisTmp1 (the current index instruction opcode) is 0xDD or 0xFD, 
                    0512  ; is not zero then strings are replaced: 
                    0513  ;   HL is replaced with IX or IY
                    0514  ;   (HL) is replaced with (IX + d) or (IY + d) except for JP instruction
                    0515  ;   where is is just replaced by (IX) or (IY)
16A9:               0516  DisWrString:
16A9: F5            0517              PUSH AF
16AA: E5            0518              PUSH HL
16AB: 6F            0519              LD   L,A            ;Store string number
16AC: FE 15         0520              CP   kDisBracHL     ;String = (HL) ?
16AE: 28 04         0521              JR   Z,@Subs        ;Yes, so go do substitution
16B0: FE 18         0522              CP   kDisHL         ;String = HL ?
16B2: 20 0C         0523              JR   NZ,@GotString  ;No, so just write the string
                    0524  ; Substitute IX/IY in HL string or (IX/IY+d) in (HL) string
16B4: 3A A3 A2      0525  @Subs:      LD   A,(iDisIndex)  ;Get index instruction opcode
16B7: B7            0526              OR   A              ;Index instruction?
16B8: 28 06         0527              JR   Z,@GotString   ;No, so skip substitutions
16BA: 2C            0528              INC  L              ;Increment to IX string number
16BB: FE DD         0529              CP   0xDD           ;IX instruction?
16BD: 28 01         0530              JR   Z,@GotString   ;Yes, so go write it
16BF: 2C            0531              INC  L              ;Increment to IY string
16C0:               0532  @GotString:
16C0: 7D            0532  @GotString: LD   A,L            ;Get string number
16C1: 21 26 17      0533              LD   HL,DisString   ;Start of string list
16C4: CD F6 07      0534              CALL FindStringInList ;Find start of string A
                    0535  ; HL now points to disassembler string
16C7: 7E            0536  @Char:      LD   A,(HL)         ;Get character from string
16C8: E6 7F         0537              AND  0x7F           ;Mask off string start bit
16CA: FE 2B         0538              CP   '+'            ;Is it a '+' sign (displacement) ?
16CC: 28 05         0539              JR   Z,@Plus        ;No, so skip to next character
16CE: CD DB 06      0540              CALL StrWrChar      ;Write character
16D1: 18 22         0541              JR   @Next          ;No, so skip to next character
                    0542  ; Encountered a plus sign so expecting to show a displacement
16D3: 3A A4 A2      0543  @Plus:      LD   A,(iDisOpStr)  ;Get instruction string
16D6: FE 1E         0544              CP   kDisJP         ;JP instruction?
16D8: 20 07         0545              JR   NZ,@Displace   ;No, so go show displacement
16DA: 3E 29         0546              LD   A,')'          ;Yes, so just terminate with ')'
16DC: CD DB 06      0547              CALL StrWrChar      ;Write close bracket character
16DF: 18 19         0548              JR   @End
                    0549  ; Show displacement in (IX+...) and (IY+...) instructions
16E1: 3E 2B         0550  @Displace:  LD   A,'+'
16E3: CD DB 06      0551              CALL StrWrChar      ;Write plus character
16E6: CD 6E 08      0552              CALL WrHexPrefix
16E9: FD 7E 02      0553              LD   A,(IY+2)       ;Get index instruction displacement
16EC: CD EF 06      0554              CALL StrWrHexByte   ;Write displacement in hex
16EF: 3E 29         0555              LD   A,')'
16F1: CD DB 06      0556              CALL StrWrChar      ;Write close bracket character
16F4: 04            0557              INC  B              ;Increment opcode offset
                    0558  ; Consider next character in disassembler string
16F5: 23            0559  @Next:      INC  HL             ;Point to next character
16F6: CB 7E         0560              BIT  7,(HL)         ;Start of new string?
16F8: 28 CD         0561              JR   Z,@Char        ;No, so go get next character
16FA: E1            0562  @End:       POP  HL
16FB: F1            0563              POP  AF
16FC: C9            0564              RET
                    0565  
                    0566  
                    0567  ; **********************************************************************
                    0568  ; **  Constant data                                                   **
                    0569  ; **********************************************************************
                    0570  
                    0571  
                    0572  ; Strings
16FD: 20 20 28 74   0573  szDisTo:    .DB  "  (to ",kNull
1701: 6F 20 00      5583  
                    0574  
                    0575  
                    0576  ; Operand table:
                    0577  ;   Index into table is the operand string number 1 to 13)
                    0578  ;   Contents: Substitution string number, function bits BIILMM
                    0579  ;
                    0580  ; Op  String  Offset  Bracket  Immediate  Substitue     subsLen  subsMask  ->  BIILMM
                    0581  ;  1  =""     +0      No       No   (00)  No                n/a  n/a           000000
                    0582  ;  2  ="n"    +1      No       Byte (10)  No                n/a  n/a           010000
                    0583  ;  3  ="(n)"  +1      Yes      Byte (10)  No                n/a  n/a           110000
                    0584  ;  4  ="nn"   +2      No       Word (11)  No                n/a  n/a           011000
                    0585  ;  5  ="(nn)" +2      Yes      Word (11)  No                n/a  n/a           111000
                    0586  ;  6  ="r"    +0      No       No   (00)  "BCDEHL-A"          1  0x38 (11)     000011
                    0587  ;  7  ="r2"   +0      No       No   (00)  "BCDEHL-A"          1  0x07 (00)     000000
                    0588  ;  8  ="dd"   +0      No       No   (00)  "BCDEHLSP"          2  0x30 (10)     000110
                    0589  ;  9  ="qq"   +0      No       No   (00)  "BCDEHLAF"          2  0x30 (10)     000110
                    0590  ; 10  ="c"    +0      No       No   (00)  "NZZ NCC "          2  0x18 (01)     000101
                    0591  ; 11  ="cc"   +0      No       No   (00)  "NZZ NCC POPEP M "  2  0x38 (11)     000111
                    0592  ; 12  ="t"    +0      No       No   (00)  "0008101820283038"  2  0x38 (11)     000111
                    0593  ; 13  ="b"    +0      No       No   (00)  "01234567"          1  0x38 (11)     000011
                    0594  ; Each table entry is coded with the string number plus a byte containing BIILMM bits
                    0595  ; Length bit is hi for strings with two character substitutions
1704:               0596  DisOperandTable:
1704: 00 00         0597              .DB  0x00,0x00      ;0b000000 ;Operand  1 = ""
1706: 00 10         0598              .DB  0x00,0x10      ;0b010000 ;Operand  2 = "n"
1708: 00 30         0599              .DB  0x00,0x30      ;0b110000 ;Operand  3 = "(n)"
170A: 00 18         0600              .DB  0x00,0x18      ;0b011000 ;Operand  4 = "nn"
170C: 00 38         0601              .DB  0x00,0x38      ;0b111000 ;Operand  5 = "(nn)"
170E: 0E 03         0602              .DB  0x0E,0x03      ;0b000011 ;Operand  6 = "r"
1710: 0E 00         0603              .DB  0x0E,0x00      ;0b000000 ;Operand  7 = "r2"
1712: 0F 06         0604              .DB  0x0F,0x06      ;0b000110 ;Operand  8 = "dd"
1714: 10 06         0605              .DB  0x10,0x06      ;0b000110 ;Operand  9 = "qq"
1716: 11 05         0606              .DB  0x11,0x05      ;0b000101 ;Operand 10 = "c"
1718: 12 07         0607              .DB  0x12,0x07      ;0b000111 ;Operand 11 = "cc"
171A: 13 07         0608              .DB  0x13,0x07      ;0b000111 ;Operand 12 = "t"
171C: 14 03         0609              .DB  0x14,0x03      ;0b000011 ;Operand 13 = "b"
                    0610  
                    0611  ; Mask table
                    0612  ; These are the masks used to separate token values such as register "BCDEHL-A"
                    0613  ; The index into the table is coded in the two mask bits from the above table.
171E:               0614  DisMaskTable:
171E: 07            0615              .DB  0x07           ;Mask type 0
171F: 18            0616              .DB  0x18           ;Mask type 1
1720: 30            0617              .DB  0x30           ;Mask type 2
1721: 38            0618              .DB  0x38           ;Mask type 3
                    0619  
                    0620  
                    0621  ; Condition mask table
                    0622  ; The condition mask table contains one byte for each condition flag:
                    0623  ; NZ,Z,NC,C,PO,PE,P,M where offset into table is 0 for Z/NZ, 1 for C/NC, etc
                    0624  ; The value of each table entry is a bit mask, which when exclusively for the flags register
                    0625              ;SZ-H-PNC   Condition, Flag, Description
1722: 40            0626  DisConTab:  .DB  0x40           ;xZxxxxxx   NZ,        Z=0,  Not Zero
1723: 01            0627              .DB  0x01           ;xxxxxxxC   NC,        C=0,  No Carry
1724: 04            0628              .DB  0x04           ;xxxxxxxC   PO,        P=0,  Parity Odd
1725: 80            0629              .DB  0x80           ;xxxxxxxC   PO,        S=0,  Positive
                    0630  
                    0631  
                    0632  ; Include the data tables  DisString: and DisInst:
                    0633  ;
                    0634  ; Disassembler string table: (DisString)
                    0635  ; This contains many string which are not null terminated and have no length 
                    0636  ; value. Instead they are tightly packed with the start of each string 
                    0637  ; indicated by the first character having bit 7 set.
                    0638  ;
                    0639  ; Instruction table: (DisInst)
                    0640  ; The instruction table definition of the processor's instruction set.
                    0641  ; Each instruction is described by 5 bytes:
                    0642  ;    Byte 0:  Opcode value
                    0643  ;    Byte 1:  Opcode mask
                    0644  ;    Byte 2:  Operation string number
                    0645  ;    Byte 3:  Operand #1 string number, plus bits 6-7 define precode
                    0646  ;    Byte 4:  Operand #2 string number
                    0647  ; The precode values code in bits 6-7 are:
                    0648  ;    00xx xxxx = No precode
                    0649  ;    10xx xxxx = Precode 0xCB
                    0650  ;    11xx xxxx = Precode 0xED
                    0651  ; Precodes are used by the processor's extended instructions
                    0652  #INCLUDE    Monitor\DisData.asm
000D:               0001  kDisSubsL:	.EQU 13	;Last operand substitution string
0004:               0002  kDisSubNN:	.EQU 4	;Operand substitution string 'nn'
000A:               0003  kDisSubC:	.EQU 10	;Operand substitution string 'c'
000B:               0004  kDisSubCC:	.EQU 11	;Operand substitution string 'cc'
1726:               0005  kDisBracHL:
                    0005  kDisBracHL:	.EQU 21	;Bracketed HL
0018:               0006  kDisHL:	.EQU 24	;HL
001B:               0007  kDisFlowF:	.EQU 27	;First flow control instructions
0022:               0008  kDisFlowL:	.EQU 34	;Last flow control instructions
001B:               0009  kDisJR:	.EQU 27	;Operation string 'JR'
001C:               0010  kDisDJNZ:	.EQU 28	;Operation string 'DJNZ'
001D:               0011  kDisRST:	.EQU 29	;Operation string 'RST'
001E:               0012  kDisJP:	.EQU 30	;Operation string 'JP'
001F:               0013  kDisCALL:	.EQU 31	;Operation string 'CALL'
0020:               0014  kDisRET:	.EQU 32	;Operation string 'RET'
1726:               0015  kDisOpMask:
                    0015  kDisOpMask:	.EQU 0x3F	;Operand 1 mask to exclude pre-code bits
0018:               0016  kDisMskC:	.EQU 0x18	;Condition bit mask for Operand 1 = C
0038:               0017  kDisMskCC:	.EQU 0x38	;Condition bit mask for Operand 1 = CC
1726:               0018  kDisMskRST:
                    0018  kDisMskRST:	.EQU 0x38	;Restart address bits
                    0019  
0000:               0020  DisString:
1726: 80            0021  	.DB  0x80                              	;String 0x01 = 
1727: EE            0022  	.DB  0x80+'n'                          	;String 0x02 = n
1728: A8 6E 29      0023  	.DB  0x80+'(',"n)"                     	;String 0x03 = (n)
172B: EE 6E         0024  	.DB  0x80+'n',"n"                      	;String 0x04 = nn
172D: A8 6E 6E 29   0025  	.DB  0x80+'(',"nn)"                    	;String 0x05 = (nn)
1731: F2            0026  	.DB  0x80+'r'                          	;String 0x06 = r
1732: F2 32         0027  	.DB  0x80+'r',"2"                      	;String 0x07 = r2
1734: E4 64         0028  	.DB  0x80+'d',"d"                      	;String 0x08 = dd
1736: F1 71         0029  	.DB  0x80+'q',"q"                      	;String 0x09 = qq
1738: E3            0030  	.DB  0x80+'c'                          	;String 0x0A = c
1739: E3 63         0031  	.DB  0x80+'c',"c"                      	;String 0x0B = cc
173B: F4            0032  	.DB  0x80+'t'                          	;String 0x0C = t
173C: E2            0033  	.DB  0x80+'b'                          	;String 0x0D = b
173D: C2 43 44 45   0034  	.DB  0x80+'B',"CDEHL-A"                	;String 0x0E = BCDEHL-A
1741: 48 4C 2D 41   5696  
1745: C2 43 44 45   0035  	.DB  0x80+'B',"CDE**SP"                	;String 0x0F = BCDE**SP
1749: 2A 2A 53 50   5697  
174D: C2 43 44 45   0036  	.DB  0x80+'B',"CDE**AF"                	;String 0x10 = BCDE**AF
1751: 2A 2A 41 46   5698  
1755: CE 5A 5A 2E   0037  	.DB  0x80+'N',"ZZ.NCC."                	;String 0x11 = NZZ.NCC.
1759: 4E 43 43 2E   5699  
175D: CE 5A 5A 2E   0038  	.DB  0x80+'N',"ZZ.NCC.POPEP.M."        	;String 0x12 = NZZ.NCC.POPEP.M.
1761: 4E 43 ...     5700  
176D: B0 30 30 38   0039  	.DB  0x80+'0',"008101820283038"        	;String 0x13 = 0008101820283038
1771: 31 30 ...     5701  
177D: B0 31 32 33   0040  	.DB  0x80+'0',"1234567"                	;String 0x14 = 01234567
1781: 34 35 36 37   5702  
1785: A8 48 4C 29   0041  	.DB  0x80+'(',"HL)"                    	;String 0x15 = (HL)
1789: A8 49 58 2B   0042  	.DB  0x80+'(',"IX+"                    	;String 0x16 = (IX+
178D: A8 49 59 2B   0043  	.DB  0x80+'(',"IY+"                    	;String 0x17 = (IY+
1791: C8 4C         0044  	.DB  0x80+'H',"L"                      	;String 0x18 = HL
1793: C9 58         0045  	.DB  0x80+'I',"X"                      	;String 0x19 = IX
1795: C9 59         0046  	.DB  0x80+'I',"Y"                      	;String 0x1A = IY
1797: CA 52         0047  	.DB  0x80+'J',"R"                      	;String 0x1B = JR
1799: C4 4A 4E 5A   0048  	.DB  0x80+'D',"JNZ"                    	;String 0x1C = DJNZ
179D: D2 53 54      0049  	.DB  0x80+'R',"ST"                     	;String 0x1D = RST
17A0: CA 50         0050  	.DB  0x80+'J',"P"                      	;String 0x1E = JP
17A2: C3 41 4C 4C   0051  	.DB  0x80+'C',"ALL"                    	;String 0x1F = CALL
17A6: D2 45 54      0052  	.DB  0x80+'R',"ET"                     	;String 0x20 = RET
17A9: D2 45 54 49   0053  	.DB  0x80+'R',"ETI"                    	;String 0x21 = RETI
17AD: D2 45 54 4E   0054  	.DB  0x80+'R',"ETN"                    	;String 0x22 = RETN
17B1: C1            0055  	.DB  0x80+'A'                          	;String 0x23 = A
17B2: A8 53 50 29   0056  	.DB  0x80+'(',"SP)"                    	;String 0x24 = (SP)
17B6: C1 46         0057  	.DB  0x80+'A',"F"                      	;String 0x25 = AF
17B8: C4 45         0058  	.DB  0x80+'D',"E"                      	;String 0x26 = DE
17BA: B0            0059  	.DB  0x80+'0'                          	;String 0x27 = 0
17BB: B1            0060  	.DB  0x80+'1'                          	;String 0x28 = 1
17BC: B2            0061  	.DB  0x80+'2'                          	;String 0x29 = 2
17BD: A8 42 43 29   0062  	.DB  0x80+'(',"BC)"                    	;String 0x2A = (BC)
17C1: A8 44 45 29   0063  	.DB  0x80+'(',"DE)"                    	;String 0x2B = (DE)
17C5: D3 50         0064  	.DB  0x80+'S',"P"                      	;String 0x2C = SP
17C7: C9            0065  	.DB  0x80+'I'                          	;String 0x2D = I
17C8: D2            0066  	.DB  0x80+'R'                          	;String 0x2E = R
17C9: A8 43 29      0067  	.DB  0x80+'(',"C)"                     	;String 0x2F = (C)
17CC: C1 46 27      0068  	.DB  0x80+'A',"F'"                     	;String 0x30 = AF'
17CF: C1 44 43      0069  	.DB  0x80+'A',"DC"                     	;String 0x31 = ADC
17D2: C1 44 44      0070  	.DB  0x80+'A',"DD"                     	;String 0x32 = ADD
17D5: C1 4E 44      0071  	.DB  0x80+'A',"ND"                     	;String 0x33 = AND
17D8: C2 49 54      0072  	.DB  0x80+'B',"IT"                     	;String 0x34 = BIT
17DB: C3 43 46      0073  	.DB  0x80+'C',"CF"                     	;String 0x35 = CCF
17DE: C3 50         0074  	.DB  0x80+'C',"P"                      	;String 0x36 = CP
17E0: C3 50 44      0075  	.DB  0x80+'C',"PD"                     	;String 0x37 = CPD
17E3: C3 50 44 52   0076  	.DB  0x80+'C',"PDR"                    	;String 0x38 = CPDR
17E7: C3 50 49      0077  	.DB  0x80+'C',"PI"                     	;String 0x39 = CPI
17EA: C3 50 49 52   0078  	.DB  0x80+'C',"PIR"                    	;String 0x3A = CPIR
17EE: C3 50 4C      0079  	.DB  0x80+'C',"PL"                     	;String 0x3B = CPL
17F1: C4 41 41      0080  	.DB  0x80+'D',"AA"                     	;String 0x3C = DAA
17F4: C4 45 43      0081  	.DB  0x80+'D',"EC"                     	;String 0x3D = DEC
17F7: C4 49         0082  	.DB  0x80+'D',"I"                      	;String 0x3E = DI
17F9: C5 49         0083  	.DB  0x80+'E',"I"                      	;String 0x3F = EI
17FB: C5 58         0084  	.DB  0x80+'E',"X"                      	;String 0x40 = EX
17FD: C5 58 58      0085  	.DB  0x80+'E',"XX"                     	;String 0x41 = EXX
1800: C8 41 4C 54   0086  	.DB  0x80+'H',"ALT"                    	;String 0x42 = HALT
1804: C9 4D         0087  	.DB  0x80+'I',"M"                      	;String 0x43 = IM
1806: C9 4E         0088  	.DB  0x80+'I',"N"                      	;String 0x44 = IN
1808: C9 4E 43      0089  	.DB  0x80+'I',"NC"                     	;String 0x45 = INC
180B: C9 4E 44      0090  	.DB  0x80+'I',"ND"                     	;String 0x46 = IND
180E: C9 4E 44 52   0091  	.DB  0x80+'I',"NDR"                    	;String 0x47 = INDR
1812: C9 4E 49      0092  	.DB  0x80+'I',"NI"                     	;String 0x48 = INI
1815: C9 4E 49 52   0093  	.DB  0x80+'I',"NIR"                    	;String 0x49 = INIR
1819: CC 44         0094  	.DB  0x80+'L',"D"                      	;String 0x4A = LD
181B: CC 44 44      0095  	.DB  0x80+'L',"DD"                     	;String 0x4B = LDD
181E: CC 44 44 52   0096  	.DB  0x80+'L',"DDR"                    	;String 0x4C = LDDR
1822: CC 44 49      0097  	.DB  0x80+'L',"DI"                     	;String 0x4D = LDI
1825: CC 44 49 52   0098  	.DB  0x80+'L',"DIR"                    	;String 0x4E = LDIR
1829: CE 45 47      0099  	.DB  0x80+'N',"EG"                     	;String 0x4F = NEG
182C: CE 4F 50      0100  	.DB  0x80+'N',"OP"                     	;String 0x50 = NOP
182F: CF 52         0101  	.DB  0x80+'O',"R"                      	;String 0x51 = OR
1831: CF 54 44 52   0102  	.DB  0x80+'O',"TDR"                    	;String 0x52 = OTDR
1835: CF 54 49 52   0103  	.DB  0x80+'O',"TIR"                    	;String 0x53 = OTIR
1839: CF 55 54      0104  	.DB  0x80+'O',"UT"                     	;String 0x54 = OUT
183C: CF 55 54 44   0105  	.DB  0x80+'O',"UTD"                    	;String 0x55 = OUTD
1840: CF 55 54 49   0106  	.DB  0x80+'O',"UTI"                    	;String 0x56 = OUTI
1844: D0 4F 50      0107  	.DB  0x80+'P',"OP"                     	;String 0x57 = POP
1847: D0 55 53 48   0108  	.DB  0x80+'P',"USH"                    	;String 0x58 = PUSH
184B: D2 45 53      0109  	.DB  0x80+'R',"ES"                     	;String 0x59 = RES
184E: D2 4C         0110  	.DB  0x80+'R',"L"                      	;String 0x5A = RL
1850: D2 4C 41      0111  	.DB  0x80+'R',"LA"                     	;String 0x5B = RLA
1853: D2 4C 43      0112  	.DB  0x80+'R',"LC"                     	;String 0x5C = RLC
1856: D2 4C 43 41   0113  	.DB  0x80+'R',"LCA"                    	;String 0x5D = RLCA
185A: D2 4C 44      0114  	.DB  0x80+'R',"LD"                     	;String 0x5E = RLD
185D: D2 52         0115  	.DB  0x80+'R',"R"                      	;String 0x5F = RR
185F: D2 52 41      0116  	.DB  0x80+'R',"RA"                     	;String 0x60 = RRA
1862: D2 52 43      0117  	.DB  0x80+'R',"RC"                     	;String 0x61 = RRC
1865: D2 52 43 41   0118  	.DB  0x80+'R',"RCA"                    	;String 0x62 = RRCA
1869: D2 52 44      0119  	.DB  0x80+'R',"RD"                     	;String 0x63 = RRD
186C: D3 42 43      0120  	.DB  0x80+'S',"BC"                     	;String 0x64 = SBC
186F: D3 43 46      0121  	.DB  0x80+'S',"CF"                     	;String 0x65 = SCF
1872: D3 45 54      0122  	.DB  0x80+'S',"ET"                     	;String 0x66 = SET
1875: D3 4C 41      0123  	.DB  0x80+'S',"LA"                     	;String 0x67 = SLA
1878: D3 4C 4C      0124  	.DB  0x80+'S',"LL"                     	;String 0x68 = SLL
187B: D3 52 41      0125  	.DB  0x80+'S',"RA"                     	;String 0x69 = SRA
187E: D3 52 4C      0126  	.DB  0x80+'S',"RL"                     	;String 0x6A = SRL
1881: D3 55 42      0127  	.DB  0x80+'S',"UB"                     	;String 0x6B = SUB
1884: D8 4F 52      0128  	.DB  0x80+'X',"OR"                     	;String 0x6C = XOR
1887: BF 3F 3F 3F   0129  	.DB  0x80+'?',"???"                    	;String 0x6D = ????
188B: 80            0130  	.DB  0x80
                    0131  
0000:               0132  DisInst:
188C: 88 F8 31 23   0133  	.DB  0x88,0xF8,0x31,0x23,0x07 ;Opcode: 0x88 - ADC  A   ,r2  
1890: 07            5795  
1891: CE FF 31 23   0134  	.DB  0xCE,0xFF,0x31,0x23,0x02 ;Opcode: 0xCE - ADC  A   ,n   
1895: 02            5796  
1896: 4A CF 31 D8   0135  	.DB  0x4A,0xCF,0x31,0xD8,0x08 ;Opcode: 0x4A - ADC  HL  ,dd  
189A: 08            5797  
189B: 80 F8 32 23   0136  	.DB  0x80,0xF8,0x32,0x23,0x07 ;Opcode: 0x80 - ADD  A   ,r2  
189F: 07            5798  
18A0: C6 FF 32 23   0137  	.DB  0xC6,0xFF,0x32,0x23,0x02 ;Opcode: 0xC6 - ADD  A   ,n   
18A4: 02            5799  
18A5: 09 CF 32 18   0138  	.DB  0x09,0xCF,0x32,0x18,0x08 ;Opcode: 0x09 - ADD  HL  ,dd  
18A9: 08            5800  
18AA: A0 F8 33 07   0139  	.DB  0xA0,0xF8,0x33,0x07,0x01 ;Opcode: 0xA0 - AND  r2  ,    
18AE: 01            5801  
18AF: E6 FF 33 02   0140  	.DB  0xE6,0xFF,0x33,0x02,0x01 ;Opcode: 0xE6 - AND  n   ,    
18B3: 01            5802  
18B4: 40 C0 34 8D   0141  	.DB  0x40,0xC0,0x34,0x8D,0x07 ;Opcode: 0x40 - BIT  b   ,r2  
18B8: 07            5803  
18B9: C4 C7 1F 0B   0142  	.DB  0xC4,0xC7,0x1F,0x0B,0x04 ;Opcode: 0xC4 - CALL cc  ,nn  
18BD: 04            5804  
18BE: CD FF 1F 04   0143  	.DB  0xCD,0xFF,0x1F,0x04,0x01 ;Opcode: 0xCD - CALL nn  ,    
18C2: 01            5805  
18C3: 3F FF 35 01   0144  	.DB  0x3F,0xFF,0x35,0x01,0x01 ;Opcode: 0x3F - CCF      ,    
18C7: 01            5806  
18C8: B8 F8 36 07   0145  	.DB  0xB8,0xF8,0x36,0x07,0x01 ;Opcode: 0xB8 - CP   r2  ,    
18CC: 01            5807  
18CD: FE FF 36 02   0146  	.DB  0xFE,0xFF,0x36,0x02,0x01 ;Opcode: 0xFE - CP   n   ,    
18D1: 01            5808  
18D2: A9 FF 37 C1   0147  	.DB  0xA9,0xFF,0x37,0xC1,0x01 ;Opcode: 0xA9 - CPD      ,    
18D6: 01            5809  
18D7: B9 FF 38 C1   0148  	.DB  0xB9,0xFF,0x38,0xC1,0x01 ;Opcode: 0xB9 - CPDR     ,    
18DB: 01            5810  
18DC: A1 FF 39 C1   0149  	.DB  0xA1,0xFF,0x39,0xC1,0x01 ;Opcode: 0xA1 - CPI      ,    
18E0: 01            5811  
18E1: B1 FF 3A C1   0150  	.DB  0xB1,0xFF,0x3A,0xC1,0x01 ;Opcode: 0xB1 - CPIR     ,    
18E5: 01            5812  
18E6: 2F FF 3B 01   0151  	.DB  0x2F,0xFF,0x3B,0x01,0x01 ;Opcode: 0x2F - CPL      ,    
18EA: 01            5813  
18EB: 27 FF 3C 01   0152  	.DB  0x27,0xFF,0x3C,0x01,0x01 ;Opcode: 0x27 - DAA      ,    
18EF: 01            5814  
18F0: 0B CF 3D 08   0153  	.DB  0x0B,0xCF,0x3D,0x08,0x01 ;Opcode: 0x0B - DEC  dd  ,    
18F4: 01            5815  
18F5: 05 C7 3D 06   0154  	.DB  0x05,0xC7,0x3D,0x06,0x01 ;Opcode: 0x05 - DEC  r   ,    
18F9: 01            5816  
18FA: F3 FF 3E 01   0155  	.DB  0xF3,0xFF,0x3E,0x01,0x01 ;Opcode: 0xF3 - DI       ,    
18FE: 01            5817  
18FF: 10 FF 1C 02   0156  	.DB  0x10,0xFF,0x1C,0x02,0x01 ;Opcode: 0x10 - DJNZ n   ,    
1903: 01            5818  
1904: FB FF 3F 01   0157  	.DB  0xFB,0xFF,0x3F,0x01,0x01 ;Opcode: 0xFB - EI       ,    
1908: 01            5819  
1909: E3 FF 40 24   0158  	.DB  0xE3,0xFF,0x40,0x24,0x18 ;Opcode: 0xE3 - EX   (SP),HL  
190D: 18            5820  
190E: 08 FF 40 25   0159  	.DB  0x08,0xFF,0x40,0x25,0x30 ;Opcode: 0x08 - EX   AF  ,AF' 
1912: 30            5821  
1913: EB FF 40 26   0160  	.DB  0xEB,0xFF,0x40,0x26,0x18 ;Opcode: 0xEB - EX   DE  ,HL  
1917: 18            5822  
1918: D9 FF 41 01   0161  	.DB  0xD9,0xFF,0x41,0x01,0x01 ;Opcode: 0xD9 - EXX      ,    
191C: 01            5823  
191D: 76 FF 42 01   0162  	.DB  0x76,0xFF,0x42,0x01,0x01 ;Opcode: 0x76 - HALT     ,    
1921: 01            5824  
1922: 46 FF 43 E7   0163  	.DB  0x46,0xFF,0x43,0xE7,0x01 ;Opcode: 0x46 - IM   0   ,    
1926: 01            5825  
1927: 56 FF 43 E8   0164  	.DB  0x56,0xFF,0x43,0xE8,0x01 ;Opcode: 0x56 - IM   1   ,    
192B: 01            5826  
192C: 5E FF 43 E9   0165  	.DB  0x5E,0xFF,0x43,0xE9,0x01 ;Opcode: 0x5E - IM   2   ,    
1930: 01            5827  
1931: 40 C7 44 C6   0166  	.DB  0x40,0xC7,0x44,0xC6,0x2F ;Opcode: 0x40 - IN   r   ,(C) 
1935: 2F            5828  
1936: DB FF 44 23   0167  	.DB  0xDB,0xFF,0x44,0x23,0x03 ;Opcode: 0xDB - IN   A   ,(n) 
193A: 03            5829  
193B: 03 CF 45 08   0168  	.DB  0x03,0xCF,0x45,0x08,0x01 ;Opcode: 0x03 - INC  dd  ,    
193F: 01            5830  
1940: 04 C7 45 06   0169  	.DB  0x04,0xC7,0x45,0x06,0x01 ;Opcode: 0x04 - INC  r   ,    
1944: 01            5831  
1945: AA FF 46 C1   0170  	.DB  0xAA,0xFF,0x46,0xC1,0x01 ;Opcode: 0xAA - IND      ,    
1949: 01            5832  
194A: BA FF 47 C1   0171  	.DB  0xBA,0xFF,0x47,0xC1,0x01 ;Opcode: 0xBA - INDR     ,    
194E: 01            5833  
194F: A2 FF 48 C1   0172  	.DB  0xA2,0xFF,0x48,0xC1,0x01 ;Opcode: 0xA2 - INI      ,    
1953: 01            5834  
1954: B2 FF 49 C1   0173  	.DB  0xB2,0xFF,0x49,0xC1,0x01 ;Opcode: 0xB2 - INIR     ,    
1958: 01            5835  
1959: E9 FF 1E 15   0174  	.DB  0xE9,0xFF,0x1E,0x15,0x01 ;Opcode: 0xE9 - JP   (HL),    
195D: 01            5836  
195E: C2 C7 1E 0B   0175  	.DB  0xC2,0xC7,0x1E,0x0B,0x04 ;Opcode: 0xC2 - JP   cc  ,nn  
1962: 04            5837  
1963: C3 FF 1E 04   0176  	.DB  0xC3,0xFF,0x1E,0x04,0x01 ;Opcode: 0xC3 - JP   nn  ,    
1967: 01            5838  
1968: 20 E7 1B 0A   0177  	.DB  0x20,0xE7,0x1B,0x0A,0x02 ;Opcode: 0x20 - JR   c   ,n   
196C: 02            5839  
196D: 18 FF 1B 02   0178  	.DB  0x18,0xFF,0x1B,0x02,0x01 ;Opcode: 0x18 - JR   n   ,    
1971: 01            5840  
1972: 40 C0 4A 06   0179  	.DB  0x40,0xC0,0x4A,0x06,0x07 ;Opcode: 0x40 - LD   r   ,r2  
1976: 07            5841  
1977: 02 FF 4A 2A   0180  	.DB  0x02,0xFF,0x4A,0x2A,0x23 ;Opcode: 0x02 - LD   (BC),A   
197B: 23            5842  
197C: 12 FF 4A 2B   0181  	.DB  0x12,0xFF,0x4A,0x2B,0x23 ;Opcode: 0x12 - LD   (DE),A   
1980: 23            5843  
1981: 32 FF 4A 05   0182  	.DB  0x32,0xFF,0x4A,0x05,0x23 ;Opcode: 0x32 - LD   (nn),A   
1985: 23            5844  
1986: 22 FF 4A 05   0183  	.DB  0x22,0xFF,0x4A,0x05,0x18 ;Opcode: 0x22 - LD   (nn),HL  
198A: 18            5845  
198B: 43 CF 4A C5   0184  	.DB  0x43,0xCF,0x4A,0xC5,0x08 ;Opcode: 0x43 - LD   (nn),dd  
198F: 08            5846  
1990: 0A FF 4A 23   0185  	.DB  0x0A,0xFF,0x4A,0x23,0x2A ;Opcode: 0x0A - LD   A   ,(BC)
1994: 2A            5847  
1995: 1A FF 4A 23   0186  	.DB  0x1A,0xFF,0x4A,0x23,0x2B ;Opcode: 0x1A - LD   A   ,(DE)
1999: 2B            5848  
199A: 3A FF 4A 23   0187  	.DB  0x3A,0xFF,0x4A,0x23,0x05 ;Opcode: 0x3A - LD   A   ,(nn)
199E: 05            5849  
199F: 2A FF 4A 18   0188  	.DB  0x2A,0xFF,0x4A,0x18,0x05 ;Opcode: 0x2A - LD   HL  ,(nn)
19A3: 05            5850  
19A4: F9 FF 4A 2C   0189  	.DB  0xF9,0xFF,0x4A,0x2C,0x18 ;Opcode: 0xF9 - LD   SP  ,HL  
19A8: 18            5851  
19A9: 01 CF 4A 08   0190  	.DB  0x01,0xCF,0x4A,0x08,0x04 ;Opcode: 0x01 - LD   dd  ,nn  
19AD: 04            5852  
19AE: 4B CF 4A C8   0191  	.DB  0x4B,0xCF,0x4A,0xC8,0x05 ;Opcode: 0x4B - LD   dd  ,(nn)
19B2: 05            5853  
19B3: 57 FF 4A E3   0192  	.DB  0x57,0xFF,0x4A,0xE3,0x2D ;Opcode: 0x57 - LD   A   ,I   
19B7: 2D            5854  
19B8: 5F FF 4A E3   0193  	.DB  0x5F,0xFF,0x4A,0xE3,0x2E ;Opcode: 0x5F - LD   A   ,R   
19BC: 2E            5855  
19BD: 47 FF 4A ED   0194  	.DB  0x47,0xFF,0x4A,0xED,0x23 ;Opcode: 0x47 - LD   I   ,A   
19C1: 23            5856  
19C2: 4F FF 4A EE   0195  	.DB  0x4F,0xFF,0x4A,0xEE,0x23 ;Opcode: 0x4F - LD   R   ,A   
19C6: 23            5857  
19C7: 06 C7 4A 06   0196  	.DB  0x06,0xC7,0x4A,0x06,0x02 ;Opcode: 0x06 - LD   r   ,n   
19CB: 02            5858  
19CC: A8 FF 4B C1   0197  	.DB  0xA8,0xFF,0x4B,0xC1,0x01 ;Opcode: 0xA8 - LDD      ,    
19D0: 01            5859  
19D1: B8 FF 4C C1   0198  	.DB  0xB8,0xFF,0x4C,0xC1,0x01 ;Opcode: 0xB8 - LDDR     ,    
19D5: 01            5860  
19D6: A0 FF 4D C1   0199  	.DB  0xA0,0xFF,0x4D,0xC1,0x01 ;Opcode: 0xA0 - LDI      ,    
19DA: 01            5861  
19DB: B0 FF 4E C1   0200  	.DB  0xB0,0xFF,0x4E,0xC1,0x01 ;Opcode: 0xB0 - LDIR     ,    
19DF: 01            5862  
19E0: 44 FF 4F C1   0201  	.DB  0x44,0xFF,0x4F,0xC1,0x01 ;Opcode: 0x44 - NEG      ,    
19E4: 01            5863  
19E5: 00 FF 50 01   0202  	.DB  0x00,0xFF,0x50,0x01,0x01 ;Opcode: 0x00 - NOP      ,    
19E9: 01            5864  
19EA: B0 F8 51 07   0203  	.DB  0xB0,0xF8,0x51,0x07,0x01 ;Opcode: 0xB0 - OR   r2  ,    
19EE: 01            5865  
19EF: F6 FF 51 02   0204  	.DB  0xF6,0xFF,0x51,0x02,0x01 ;Opcode: 0xF6 - OR   n   ,    
19F3: 01            5866  
19F4: BB FF 52 C1   0205  	.DB  0xBB,0xFF,0x52,0xC1,0x01 ;Opcode: 0xBB - OTDR     ,    
19F8: 01            5867  
19F9: B3 FF 53 C1   0206  	.DB  0xB3,0xFF,0x53,0xC1,0x01 ;Opcode: 0xB3 - OTIR     ,    
19FD: 01            5868  
19FE: 41 C7 54 EF   0207  	.DB  0x41,0xC7,0x54,0xEF,0x06 ;Opcode: 0x41 - OUT  (C) ,r   
1A02: 06            5869  
1A03: D3 FF 54 03   0208  	.DB  0xD3,0xFF,0x54,0x03,0x23 ;Opcode: 0xD3 - OUT  (n) ,A   
1A07: 23            5870  
1A08: AB FF 55 C1   0209  	.DB  0xAB,0xFF,0x55,0xC1,0x01 ;Opcode: 0xAB - OUTD     ,    
1A0C: 01            5871  
1A0D: A3 FF 56 C1   0210  	.DB  0xA3,0xFF,0x56,0xC1,0x01 ;Opcode: 0xA3 - OUTI     ,    
1A11: 01            5872  
1A12: C1 CF 57 09   0211  	.DB  0xC1,0xCF,0x57,0x09,0x01 ;Opcode: 0xC1 - POP  qq  ,    
1A16: 01            5873  
1A17: C5 CF 58 09   0212  	.DB  0xC5,0xCF,0x58,0x09,0x01 ;Opcode: 0xC5 - PUSH qq  ,    
1A1B: 01            5874  
1A1C: 80 C0 59 8D   0213  	.DB  0x80,0xC0,0x59,0x8D,0x07 ;Opcode: 0x80 - RES  b   ,r2  
1A20: 07            5875  
1A21: C9 FF 20 01   0214  	.DB  0xC9,0xFF,0x20,0x01,0x01 ;Opcode: 0xC9 - RET      ,    
1A25: 01            5876  
1A26: C0 C7 20 0B   0215  	.DB  0xC0,0xC7,0x20,0x0B,0x01 ;Opcode: 0xC0 - RET  cc  ,    
1A2A: 01            5877  
1A2B: 4D FF 21 C1   0216  	.DB  0x4D,0xFF,0x21,0xC1,0x01 ;Opcode: 0x4D - RETI     ,    
1A2F: 01            5878  
1A30: 45 FF 22 C1   0217  	.DB  0x45,0xFF,0x22,0xC1,0x01 ;Opcode: 0x45 - RETN     ,    
1A34: 01            5879  
1A35: 10 F8 5A 87   0218  	.DB  0x10,0xF8,0x5A,0x87,0x01 ;Opcode: 0x10 - RL   r2  ,    
1A39: 01            5880  
1A3A: 17 FF 5B 01   0219  	.DB  0x17,0xFF,0x5B,0x01,0x01 ;Opcode: 0x17 - RLA      ,    
1A3E: 01            5881  
1A3F: 00 F8 5C 87   0220  	.DB  0x00,0xF8,0x5C,0x87,0x01 ;Opcode: 0x00 - RLC  r2  ,    
1A43: 01            5882  
1A44: 07 FF 5D 01   0221  	.DB  0x07,0xFF,0x5D,0x01,0x01 ;Opcode: 0x07 - RLCA     ,    
1A48: 01            5883  
1A49: 6F FF 5E C1   0222  	.DB  0x6F,0xFF,0x5E,0xC1,0x01 ;Opcode: 0x6F - RLD      ,    
1A4D: 01            5884  
1A4E: 18 F8 5F 87   0223  	.DB  0x18,0xF8,0x5F,0x87,0x01 ;Opcode: 0x18 - RR   r2  ,    
1A52: 01            5885  
1A53: 1F FF 60 01   0224  	.DB  0x1F,0xFF,0x60,0x01,0x01 ;Opcode: 0x1F - RRA      ,    
1A57: 01            5886  
1A58: 08 F8 61 87   0225  	.DB  0x08,0xF8,0x61,0x87,0x01 ;Opcode: 0x08 - RRC  r2  ,    
1A5C: 01            5887  
1A5D: 0F FF 62 01   0226  	.DB  0x0F,0xFF,0x62,0x01,0x01 ;Opcode: 0x0F - RRCA     ,    
1A61: 01            5888  
1A62: 67 FF 63 C1   0227  	.DB  0x67,0xFF,0x63,0xC1,0x01 ;Opcode: 0x67 - RRD      ,    
1A66: 01            5889  
1A67: C7 C7 1D 0C   0228  	.DB  0xC7,0xC7,0x1D,0x0C,0x01 ;Opcode: 0xC7 - RST  t   ,    
1A6B: 01            5890  
1A6C: 98 F8 64 23   0229  	.DB  0x98,0xF8,0x64,0x23,0x07 ;Opcode: 0x98 - SBC  A   ,r2  
1A70: 07            5891  
1A71: DE FF 64 23   0230  	.DB  0xDE,0xFF,0x64,0x23,0x02 ;Opcode: 0xDE - SBC  A   ,n   
1A75: 02            5892  
1A76: 42 CF 64 D8   0231  	.DB  0x42,0xCF,0x64,0xD8,0x08 ;Opcode: 0x42 - SBC  HL  ,dd  
1A7A: 08            5893  
1A7B: 37 FF 65 01   0232  	.DB  0x37,0xFF,0x65,0x01,0x01 ;Opcode: 0x37 - SCF      ,    
1A7F: 01            5894  
1A80: C0 C0 66 8D   0233  	.DB  0xC0,0xC0,0x66,0x8D,0x07 ;Opcode: 0xC0 - SET  b   ,r2  
1A84: 07            5895  
1A85: 20 F8 67 87   0234  	.DB  0x20,0xF8,0x67,0x87,0x01 ;Opcode: 0x20 - SLA  r2  ,    
1A89: 01            5896  
1A8A: 30 F8 68 87   0235  	.DB  0x30,0xF8,0x68,0x87,0x01 ;Opcode: 0x30 - SLL  r2  ,    
1A8E: 01            5897  
1A8F: 28 F8 69 87   0236  	.DB  0x28,0xF8,0x69,0x87,0x01 ;Opcode: 0x28 - SRA  r2  ,    
1A93: 01            5898  
1A94: 38 F8 6A 87   0237  	.DB  0x38,0xF8,0x6A,0x87,0x01 ;Opcode: 0x38 - SRL  r2  ,    
1A98: 01            5899  
1A99: 90 F8 6B 07   0238  	.DB  0x90,0xF8,0x6B,0x07,0x01 ;Opcode: 0x90 - SUB  r2  ,    
1A9D: 01            5900  
1A9E: D6 FF 6B 02   0239  	.DB  0xD6,0xFF,0x6B,0x02,0x01 ;Opcode: 0xD6 - SUB  n   ,    
1AA2: 01            5901  
1AA3: A8 F8 6C 07   0240  	.DB  0xA8,0xF8,0x6C,0x07,0x01 ;Opcode: 0xA8 - XOR  r2  ,    
1AA7: 01            5902  
1AA8: EE FF 6C 02   0241  	.DB  0xEE,0xFF,0x6C,0x02,0x01 ;Opcode: 0xEE - XOR  n   ,    
1AAC: 01            5903  
1AAD: 00 00 6D 01   0242  	.DB  0x00,0x00,0x6D,0x01,0x01 ;Opcode: 0x00 - ????     ,    
1AB1: 01            5904  
1AB2: 00 00 6D C1   0243  	.DB  0x00,0x00,0x6D,0xC1,0x01 ;Opcode: 0x00 - ????     ,    
1AB6: 01            5905  
                    0653  
                    0654  
                    0655  ; **********************************************************************
                    0656  ; **  Private workspace (in RAM)                                      **
                    0657  ; **********************************************************************
                    0658  
                    0659              .DATA
                    0660  
A2A3: 00            0661  iDisIndex:  .DB  0x00           ;Index instruction opcode
A2A4: 00            0662  iDisOpStr:  .DB  0x00           ;Operation string number
A2A5:               0663  iDisOp1Str:
A2A5: 00            0663  iDisOp1Str: .DB  0x00           ;Operand 1 string number
A2A6:               0664  iDisOpcode:
A2A6: 00            0664  iDisOpcode: .DB  0x00           ;Primary instruction opcode
A2A7: 00 00         0665  iDisImmed:  .DW  0x0000         ;Immediate value
                    0666  
                    0667  
                    0668  ; Disassembler: How it works...
                    0669  ; Solution is to use data table to define functions for each operand (see below)
                    0670  ; Decoding table: where the table entry is determined by the operand string number
                    0671  ; String numbers 0 to 12:
                    0672  ;   If bracket flagged print "("
                    0673  ;   If immediate byte flagged print hex byte at PC+Offset+1, Offset += 1
                    0674  ;   If immediate word flagged print word byte at PC+Offset+1 and PC+Offset+2, Offset += 2
                    0675  ;   If bracket flagged print ")"
                    0676  ;   If substitution string specified: (non-zero value)
                    0677  ;     n = opcode and SubsMask
                    0678  ;     n = n >> x, where x is the number of right shifts of the mask til bit 0 is a 1
                    0679  ;     If subsLen is 2 then n = n << 1
                    0680  ;     c =  character at (start of Substitution String + n + 0)
                    0681  ;     if = "-" then print "(HL)" else print character c
                    0682  ;     If SubsLen = 2 then
                    0683  ;       print character at (start of Substitution String + n + 1)
                    0684  ;     Endif
                    0685  ;   End if
                    0686  
                    0687  
                    0688  ; Single stepping
                    0689  ; Instructions which can change flow of code (ie. alter PC)
                    0690  ;   DJNZ d          10 nn      0001 0000
                    0691  ;   JR   d          18 nn      0001 1000
                    0692  ;   JR   c,  d      xx nn      001c c000
                    0693  ;   JP   nn         C3 nn nn   1100 0011
                    0694  ;   JP   cc, nn     xx nn nn   11cc c010
                    0695  ;   JP   HL         E9         1110 1001
                    0696  ;   JP   IX         DD E9      1110 1001
                    0697  ;   JP   IY         FD E9      1110 1001
                    0698  ;   CALL nn         CD nn nn   1100 1101
                    0699  ;   CALL cc, nn     xx nn nn   11cc c100
                    0700  ;   RET             C9         1100 1001
                    0701  ;   RET  cc         xx         11cc c000
                    0702  ;   RETI            ED 4D      0100 1101
                    0703  ;   RETN            ED 45      0100 0101
                    0704  ;   RST  aa         xx         11tt t111
                    0705  ; Also an interrupt or reset signal changes PC
                    0706  ; The above instructions are trapped after disassembly and the next instruction
                    0707  ; determined. The breakpoint is then placed here to allow single stepping.
                    0708  
                    0709  
                    0710  ; **********************************************************************
                    0711  ; **  End of Disassembler support module                              **
                    0712  ; **********************************************************************
                    0713  
                    0714  
                    0715  
                    0716  
                    0717  
                    0066  #ENDIF
                    0067  #IFDEF      IncludeHexLoader
                    0068  #INCLUDE    Monitor\HexLoader.asm ;Intel hex loader
                    0001  ; **********************************************************************
                    0002  ; **  Hex file loader                           by Stephen C Cousins  **
                    0003  ; **********************************************************************
                    0004  
                    0005  ; This module loads an Intel Hex file from the current input device.
                    0006  ;
                    0007  ; An Intel Hex file is a text file where each line is a record.
                    0008  ;
                    0009  ; A record starts with a colon (':') and ends with CR and/or LF.
                    0010  ;
                    0011  ; The next two characters form a hex byte which is the number of data
                    0012  ; bytes in the record.
                    0013  ;
                    0014  ; The next four characters form a hex word which is the start address 
                    0015  ; for the record's data bytes. High byte first.
                    0016  ;
                    0017  ; The next two characters form a hex byte which describes the type of
                    0018  ; record. 0x00 is a normal data record. 0x01 is an end of file marker.
                    0019  ;
                    0020  ; Then follows the specified number of data bytes, each written as two 
                    0021  ; character hex number.
                    0022  ;
                    0023  ; Finally there is a checksum byte in the form of a two character hex
                    0024  ; number. 
                    0025  ;
                    0026  ; To test the checksum simply add up all bytes in the record, including
                    0027  ; the checksum (but not the colon), and test to see if it is zero.
                    0028  ;
                    0029  ; The checksum is calculated by adding together all bytes in the record
                    0030  ; except the checksum byte and the colon character, ANDing with 0xFF 
                    0031  ; and then subtracting from 0x100. 
                    0032  ;
                    0033  ; Example record:
                    0034  ;   :0300300002337A1E 
                    0035  ; Record Length: 03 (3 bytes of data)
                    0036  ; Address: 0030 (the 3 bytes will be stored at 0030, 0031, and 0032)
                    0037  ; Record Type: 00 (normal data)
                    0038  ; Data: 02, 33, 7A
                    0039  ; Checksum: 1E (03 + 00 + 30 + 00 + 02 + 33 + 7A = E2, 100 - E2 = 1E)
                    0040  ;
                    0041  ; The last line of the file is an end marker with 00 data bytes and 
                    0042  ; record type 01, and so is:
                    0043  ;   :00000001FF
                    0044  ;
                    0045  ; Test file: (loads data 0x03 0x02 0x01 to address 0x4000)
                    0046  ;   :03400000030201B7
                    0047  ;   :00000001FF
                    0048  ;
                    0049  ; Public functions provided
                    0050  ;   HexLoad               Load hex file from the current console input
                    0051  
                    0052  
                    0053  ; **********************************************************************
                    0054  ; **  Public functions                                                **
                    0055  ; **********************************************************************
                    0056  
                    0057              .CODE
                    0058  
                    0059  ; HexLoader: Load an intel hex file from the current console input
                    0060  ;   On entry: No parameters required
                    0061  ;   On exit:  IX IY I AF' BC' DE' HL' preserved
1AB7: 0E 00         0062  HexLoad:    LD   C,0            ;Clear checksum of this whole file
1AB9: CD EB 03      0063  @Line:      CALL InputChar      ;Get first character in record/line
1ABC: FE 20         0064              CP   kSpace         ;Control character?
1ABE: 38 F9         0065              JR   C,@Line        ;Yes, so discard it
1AC0: FE 3A         0066              CP   kColon         ;Colon?
1AC2: C0            0067              RET  NZ             ;No, so return with this character
                    0068  ;           LD   C,0            ;Clear checksum for this line only
                    0069  ; Get number of data bytes in this record
1AC3: CD 03 1B      0070              CALL HexGetByte     ;Get number of data bytes
1AC6: 47            0071              LD   B,A            ;Store number of data bytes in record
1AC7: 81            0072              ADD  A,C            ;Add to checksum
1AC8: 4F            0073              LD   C,A
                    0074  ; Get start address for this record
1AC9: CD 03 1B      0075              CALL HexGetByte     ;Get address hi byte
1ACC: 57            0076              LD   D,A            ;Store address hi byte
1ACD: 81            0077              ADD  A,C            ;Add to checksum
1ACE: 4F            0078              LD   C,A
1ACF: CD 03 1B      0079              CALL HexGetByte     ;Get address lo byte
1AD2: 5F            0080              LD   E,A            ;Store address lo byte
1AD3: 81            0081              ADD  A,C            ;Add to checksum
1AD4: 4F            0082              LD   C,A
                    0083  ; Get record type
1AD5: CD 03 1B      0084              CALL HexGetByte     ;Get record type
1AD8: 67            0085              LD   H,A            ;Store record type
1AD9: 81            0086              ADD  A,C            ;Add to checksum
1ADA: 4F            0087              LD   C,A
                    0088  ; Input any data bytes in this record
1ADB: 78            0089              LD   A,B            ;Get number of bytes in record
1ADC: B7            0090              OR   A              ;Zero?
1ADD: 28 09         0091              JR   Z,@Check       ;Yes, so skip..
1ADF: CD 03 1B      0092  @Data:      CALL HexGetByte     ;Get data byte
1AE2: 12            0093              LD   (DE),A         ;Store data byte in memory
1AE3: 13            0094              INC  DE             ;Point to next memory location
1AE4: 81            0095              ADD  A,C            ;Add to checksum
1AE5: 4F            0096              LD   C,A
1AE6: 10 F7         0097              DJNZ @Data
                    0098  ; Get checksum byte for this record
1AE8: CD 03 1B      0099  @Check:     CALL HexGetByte     ;Get checksum byte
1AEB: 81            0100              ADD  A,C            ;Add to checksum
1AEC: 4F            0101              LD   C,A
                    0102  ; Should now test checksum for this line, but instead keep a checksum 
                    0103  ; for the whole file and test only at the end. This avoids having to 
                    0104  ; store a failure flag (no registers left) whilst still allowing this
                    0105  ; function to flush all lines of the file.
                    0106  ;Test for end of file
1AED: 7C            0107              LD   A,H            ;Get record type
1AEE: FE 01         0108              CP   1              ;End of file?
1AF0: 20 C7         0109              JR   NZ,@Line       ;No, so repeat for next record
                    0110  ; End of file so test checksum
1AF2: 79            0111              LD   A,C            ;Get checksum
1AF3: B7            0112              OR   A              ;It should be zero?
1AF4: 3E 28         0113              LD   A,kMsgReady    ;Prepare for checksum ok message
1AF6: 28 02         0114              JR   Z,@Result      ;Skip if checksum ok
1AF8: 3E 29         0115              LD   A,kMsgFileEr   ;File error message number
1AFA: CD 0C 09      0116  @Result:    CALL MonOutputMsg   ;Output message #A
1AFD: AF            0117              XOR  A              ;Return null character
1AFE: 3E 05         0118              LD   A,kNewLine
1B00: 3E 0D         0119              LD   A,kReturn
1B02: C9            0120              RET
                    0121  
                    0122  
                    0123  ; **********************************************************************
                    0124  ; **  Private functions                                               **
                    0125  ; **********************************************************************
                    0126  
                    0127  ; HexLoader: Get byte from two hex characters from current console input
                    0128  ;   On entry: No parameters required
                    0129  ;   On exit:  A = Bytes received
                    0130  ;             BC DE H IX IY I AF' BC' DE' HL' preserved
1B03:               0131  HexGetByte:
1B03: CD EB 03      0131  HexGetByte: CALL InputChar      ;Get character from input device
1B06: CD 60 07      0132              CALL ConvertCharToNumber
1B09: 07            0133              RLCA
1B0A: 07            0134              RLCA
1B0B: 07            0135              RLCA
1B0C: 07            0136              RLCA
1B0D: 6F            0137              LD   L,A            ;Store result hi nibble
1B0E: CD EB 03      0138              CALL InputChar      ;Get character from input device
1B11: CD 60 07      0139              CALL ConvertCharToNumber
1B14: B5            0140              OR   A,L            ;Get result byte
1B15: C9            0141              RET
                    0142  
                    0143  
                    0144  ; **********************************************************************
                    0145  ; **  End of Hex file loader module                                   **
                    0146  ; **********************************************************************
                    0147  
                    0148  
                    0149  
                    0069  #ENDIF
                    0070  #IFDEF      IncludeScripting
                    0071  #INCLUDE    Monitor\Script.asm  ;Simple scripting language
                    0072  #ENDIF
                    0073  
                    0074  ; Extensions
                    0075  #IFDEF      IncludeTrace
                    0076  #INCLUDE    Monitor\Trace.asm   ;Trace execution (needs disassembler)
                    0077  #ENDIF
                    0078  #IFDEF      IncludeRomFS
                    0079  #INCLUDE    Monitor\RomFS.asm   ;ROM filing system
                    0080  #ENDIF
                    0081  
                    0082  ; **********************************************************************
                    0083  ; **  End of Include SCM core modules                                 **
                    0084  ; **********************************************************************
                    0085  
                    0086  
                    0087  
                    0014  
                    0015  #INCLUDE    Hardware\Custom_CPM\!Manager.asm
                    0001  ; **********************************************************************
                    0002  ; **  Hardware Manager                          by Stephen C Cousins  **
                    0003  ; **  Hardware: SC_S4 (SC111 and compatibles)                         **
                    0004  ; **********************************************************************
                    0005  
                    0006  ; This module is responsible for:
                    0007  ;   Any optional hardware detection
                    0008  ;   Setting up drivers for all hardware
                    0009  ;   Initialising hardware
                    0010  
                    0011  ; Global constants
0080:               0012  kSIO2:      .EQU 0x80           ;Base address of SIO/2 chip
0080:               0013  kACIA1:     .EQU 0x80           ;Base address of serial ACIA #1
0040:               0014  kACIA2:     .EQU 0x40           ;Base address of serial ACIA #2
0000:               0015  kPrtIn:     .EQU 0x00           ;General input port
0000:               0016  kPrtOut:    .EQU 0x00           ;General output port
                    0017  
                    0018  ; Include device modules
                    0019  #INCLUDE    Hardware\Custom_cpm\SerialCPM.asm
                    0001  ; **********************************************************************
                    0002  ; **  Device Driver                                   by Armin Diehl  **
                    0003  ; **  Hardware:  CPM Console
                    0004  ; **  Interface: Serial SIO/2                                         **
                    0005  ; **********************************************************************
                    0006  
                    0007  
                    0008  
                    0009              .CODE
                    0010  
1B16:               0011  CPM_CONInitialize:
1B16: C9            0012  	RET
                    0013  
                    0014  
0002:               0015  BCONST  EQU     2
0003:               0016  BCONIN  EQU     3
0004:               0017  BCONOUT EQU     4
                    0018  
                    0019  ; call cpm  bios function, function no in A (beginning with 0 for cold boot)
0000:               0020  BIOSCALL:
1B17: C5            0021  	PUSH    BC
1B18: 06 00         0022  	LD      B,0
1B1A: 4F            0023          LD      C,A
1B1B: 2A 01 00      0024          LD      HL,(1)  ; 0000: JMP wboot (1)
1B1E: 2B            0025          DEC     HL
1B1F: 2B            0026          DEC     HL
1B20: 2B            0027          DEC     HL      ; cold boot=function 0
1B21: 09            0028          ADD     HL,BC
1B22: 09            0029          ADD     HL,BC
1B23: 09            0030          ADD     HL,BC
1B24: C1            0031          POP     BC
1B25: E9            0032          JP      (HL)
                    0033  
0000:               0034  CONST:
1B26: C5            0035  	PUSH	BC
1B27: E5            0036  	PUSH	HL
1B28: 3E 02         0037  	LD	A,BCONST
1B2A: CD 17 1B      0038  	CALL	BIOSCALL
                    0039  
                    0040  
                    0041  ; CPM bios input character
                    0042  ;   On entry: No parameters required
                    0043  ;   On exit:  A = Character input from the device
                    0044  ;             NZ flagged if character input
                    0045  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
1B2D:               0046  CPM_CONInputChar:
1B2D: C5            0047  	PUSH	BC
1B2E: E5            0048  	PUSH	HL
1B2F: 3E 02         0049  	LD	A,BCONST	; Status A=0:no char available, 0xFF=char is available
1B31: CD 17 1B      0050  	CALL	BIOSCALL
1B34: B7            0051  	OR	A
1B35: CA 3F 1B      0052  	JP	Z, NoCharAvail
1B38: 3E 03         0053  	LD	A,BCONIN
1B3A: CD 17 1B      0054  	CALL	BIOSCALL	; char in A
1B3D: F6 FF         0055  	OR	0xFF
                    0056  
1B3F:               0057  NoCharAvail:
1B3F:               0058  CPM_CONInputChar_End:
1B3F: E1            0059  	POP	HL
1B40: C1            0060  	POP	BC
1B41: C9            0061  	RET            
                    0062  
                    0063  
                    0064  ; CPM bios output character
                    0065  ;   On entry: A = Character to be output to the device
                    0066  ;   On exit:  If character output successful (eg. device was ready)
                    0067  ;               NZ flagged and A != 0
                    0068  ;             If character output failed (eg. device busy)
                    0069  ;               Z flagged and A = Character to output
                    0070  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
1B42:               0071  CPM_CONOutputChar:
1B42: C5            0072          PUSH    BC
1B43: D5            0073          PUSH    DE
1B44: E5            0074          PUSH    HL
1B45: 3E 04         0075          LD      A,BCONOUT
1B47: CD 17 1B      0076          CALL    BIOSCALL
1B4A: E1            0077          POP     HL
1B4B: D1            0078          POP     DE
1B4C: C1            0079          POP     BC
1B4D: F6 FF         0080  	OR	0xFF
1B4F: C9            0081          RET
                    0082  
                    0083  
                    0084  ; **********************************************************************
                    0085  ; **  End of driver: CPM console                                      **
                    0086  ; **********************************************************************
                    0087  
                    0088  
                    0089  
                    0090  
                    0091  
                    0092  
                    0093  
                    0094  
                    0095  
                    0020  
                    0021  
                    0022  ; **********************************************************************
                    0023  ; **  Public functions                                                **
                    0024  ; **********************************************************************
                    0025  
                    0026              .CODE
                    0027  
                    0028  ; Startup message
1B50: 43 50 4D 00   0029  szStartup:  .DB "CPM",kNull
                    0030  
                    0031  
                    0032  ; Hardware initialise
                    0033  ;   On entry: No parameters required
                    0034  ;   On exit:  AF BC DE HL not specified
                    0035  ;             IX IY I AF' BC' DE' HL' preserved
                    0036  ; Identify and initialise console devices:
                    0037  ;   Console device 1 = Serial device at $80 (SIO port A or ACIA #1)
                    0038  ;   Console device 2 = Serial device at $80 (SIO port B)
                    0039  ;   Console device 3 = Serial device at $40 (ACIA #2)
                    0040  ; Sets up hardware device flags:
                    0041  ;   Bit 0 = Serial 6850 ACIA #1 detected
                    0042  ;   Bit 1 = Serial Z80 SIO   #1 detected
                    0043  ;   Bit 2 = Serial 6850 ACIA #2 detected
1B54:               0044  Hardware_Initialise:
1B54: AF            0045              XOR  A
1B55: 32 A9 A2      0046              LD   (iHwFlags),A   ;Clear hardware flags
1B58: CD 16 1B      0047              CALL CPM_CONInitialize
1B5B: CB CE         0048              SET  1,(HL)         ;Set SIO2 present flag
1B5D: 21 69 1B      0049              LD   HL,@PtrCONT    ;Pointer to vector list
1B60: 3E 10         0050  @Serial:    LD   A,kFnDev1In    ;First device jump entry
1B62: CD 21 02      0051              CALL InitJumps      ;Set up serial vectors
1B65: CD 21 02      0052              CALL InitJumps      ;Set up serial vectors
1B68: C9            0053  	    RET
                    0054  ; Jump table enties
0000:               0055  @PtrCONT: ; Device #1
1B69: 2D 1B         0056              .DW  CPM_CONInputChar
1B6B: 42 1B         0057              .DW  CPM_CONOutputChar
                    0058  
                    0059  
                    0060  ; Hardware: Set baud rate
                    0061  ;   On entry: No parameters required
                    0062  ;   On entry: A = Baud rate code
                    0063  ;             C = Console device number (1 to 6)
                    0064  ;   On exit:  IF successful: (ie. valid device and baud code)
                    0065  ;               A != 0 and NZ flagged
                    0066  ;             BC HL not specified
                    0067  ;             DE? IX IY I AF' BC' DE' HL' preserved
1B6D:               0068  Hardware_BaudSet:
1B6D: AF            0069              XOR  A              ;Return failure (A=0 and Z flagged)
1B6E: C9            0070              RET                 ;Abort as invalid baud rate
                    0071  
                    0072  
                    0073  ; Hardware: Poll timer
                    0074  ;   On entry: No parameters required
                    0075  ;   On exit:  If 1ms event to be processed NZ flagged and A != 0
                    0076  ;             BC DE HL IX IY I AF' BC' DE' HL' preserved
                    0077  ; Poll software generated timer to see if a 1ms event has occurred.
                    0078  ; We have to estimate the number of clock cycles used since the last
                    0079  ; call to this routine. When the system is waiting for a console input
                    0080  ; character this will be the time it takes to call here plus the time 
                    0081  ; to poll the serial input device. Lets call this the loop time.
                    0082  ; The rest of the time we don't know so the timer events will probably 
                    0083  ; run slow.
                    0084  ; We generate a 1000 Hz event (every 1,000 micro seconds) by 
                    0085  ; counting processor clock cycles.
                    0086  ; With a 7.3728 Hz CPU clock, 1,000 micro seconds is 7,373 cycles
1B6F:               0087  Hardware_PollTimer:
1B6F: 3A AA A2      0088              LD   A,(iHwIdle)    ;Get loop counter
1B72: C6 07         0089              ADD  A,7            ;Add to loop counter
1B74: 32 AA A2      0090              LD   (iHwIdle),A    ;Store updated counter
1B77: 38 02         0091              JR   C,@RollOver    ;Skip if roll over (1ms event)
1B79: AF            0092              XOR   A             ;No event so Z flagged and A = 0
1B7A: C9            0093              RET
1B7B: F6 FF         0094  @RollOver:  OR    0xFF          ;1ms event so NZ flagged and A != 0
1B7D: C9            0095              RET
                    0096  
                    0097  
                    0098  ; Hardware: Output signon info
                    0099  ;   On entry: No parameters required
                    0100  ;   On exit:  AF BC DE HL not specified
                    0101  ;             IX IY I AF' BC' DE' HL' preserved
1B7E:               0102  Hardware_Signon:
1B7E: 11 84 1B      0103              LD   DE,@szHardware ;Pointer to start up message
1B81: C3 EE 04      0104              JP   OutputZString  ;Output start up message
1B84:               0105  @szHardware:
1B84: 43 50 4D 20   0106              .DB  "CPM system",kNewLine,kNull
1B88: 73 79 ...     6344  
                    0107  
                    0108  
                    0109  ; Hardware: Output devices info
                    0110  ;   On entry: No parameters required
                    0111  ;   On exit:  AF BC DE HL not specified
                    0112  ;             IX IY I AF' BC' DE' HL' preserved
1B90:               0113  Hardware_Devices:
                    0114  ;            LD   HL,iHwFlags    ;Get hardware present flags
1B90: 11 97 1B      0115              LD   DE,@szCPMCON
1B93: C4 EE 04      0116              CALL NZ,OutputZString ;Yes, so list it
1B96: C9            0117              RET
1B97: 31 20 3D 20   0118  @szCPMCON:  .DB  "1 = CPM Console",kNewLine,kNull
1B9B: 43 50 ...     6356  
                    0119  
                    0120  
                    0121  
                    0122  ; Initialise ROM paging
                    0123  ;   On entry: No parameters required
                    0124  ;   On exit:  BC DE HL IX IY I AF' BC' DE' HL' preserved
1BA8:               0125  RomPageInit:
1BA8: C9            0126              RET
                    0127  
                    0128  ; Fixed address to allow external code to use it
1BA9:               0129  kTransCode:
                    0129  kTransCode: .EQU 0xFF80         ;Transient code area
                    0130  
                    0131  ; Execute code in ROM bank
                    0132  ;   On entry: A = ROM bank number (0 to 3)
                    0133  ;             DE = Absolute address to execute
                    0134  ;   On exit:  IX IY I AF' BC' DE' HL' preserved
                    0135  ; WARNING: Not safe against interrupt changing config register
                    0136  ; First copy required utility function to RAM and then run it
                    0137  ; The ROM bank is selected and the code executed
1BA9: D5            0138  RomExec:    PUSH DE
1BAA: 21 B9 1B      0139              LD   HL,@TransExec  ;Source: start of code to copy
1BAD: 11 80 FF      0140              LD   DE,kTransCode  ;Destination: transient code area
1BB0: 01 07 00      0141              LD   BC,@TransExecEnd-@TransExec  ;Length of copy
1BB3: ED B0         0142              LDIR                ;Copy (HL) to (DE) and repeat x BC
1BB5: D1            0143              POP DE
1BB6: C3 80 FF      0144              JP  kTransCode
                    0145  ; Transient code copied to RAM before being executed
1BB9:               0146  @TransExec:
                    0146  @TransExec: ;RLCA               ;Shift requested ROM bank number
                    0147              ;RLCA               ;  from  0b000000NN
                    0148              ;RLCA               ;  to    0b00NN0000
                    0149              ;RLCA
                    0150              ;LD   B,A           ;Store new ROM bank bits
                    0151              ;LD   A,(iConfigCpy)  ;Get current config byte
                    0152              ;LD   (iConfigPre),A  ;Store as 'previous' config byte
                    0153              ;AND  0b11001111    ;Clear ROM bank bits
                    0154              ;OR   B             ;Include new ROM bank bits
                    0155              ;LD   (iConfigCpy),A  ;Write config byte to shadow copy
                    0156              ;OUT  (kConfigReg),A  ;Write config byte to register
1BB9: 01 86 FF      0157              LD   BC,kTransCode+@TransRet-@TransExec
1BBC: C5            0158              PUSH BC             ;Push return address onto stack
1BBD: D5            0159              PUSH DE             ;Jump to DE by pushing on
1BBE: C9            0160              RET                 ;  to stack and 'returning'
0000:               0161  @TransRet:  ;LD   A,(iConfigPre)  ;Get previous ROM page
                    0162              ;LD   (iConfigCpy),A  ;Write config byte to shadow copy
                    0163              ;OUT  (kConfigReg),A  ;Write config byte to register
1BBF: C9            0164              RET
1BC0:               0165  @TransExecEnd:
                    0166  
                    0167  
                    0168  ; Copy from ROM bank to RAM
                    0169  ;   On entry: A = ROM bank number (0 to 3)
                    0170  ;             HL = Source start address (in ROM)
                    0171  ;             DE = Destination start address (in RAM)
                    0172  ;             BC = Number of bytes to copy
                    0173  ;   On exit:  IX IY I AF' BC' DE' HL' preserved
                    0174  ; WARNING: Not safe against interrupt changing config register
                    0175  ; First copy required utility function to RAM and then run it
1BC0: C5            0176  RomCopy:    PUSH BC
1BC1: D5            0177              PUSH DE
1BC2: E5            0178              PUSH HL
1BC3: 21 D4 1B      0179              LD   HL,TransCopy   ;Source: start of code to copy
1BC6: 11 80 FF      0180              LD   DE,kTransCode  ;Destination: transient code area
1BC9: 01 03 00      0181              LD   BC,TransCopyEnd-TransCopy  ;Length of copy
1BCC: ED B0         0182              LDIR                ;Copy (HL) to (DE) and repeat x BC
1BCE: E1            0183              POP  HL
1BCF: D1            0184              POP  DE
1BD0: C1            0185              POP  BC
1BD1: C3 80 FF      0186              JP   kTransCode
                    0187  ; Transient code copied to RAM before being executed
0000:               0188  TransCopy:  ;PUSH BC            ;Preserve number of bytes to copy
                    0189              ;RLCA               ;Shift requested ROM bank number
                    0190              ;RLCA               ;  from  0b000000NN
                    0191              ;RLCA               ;  to    0b00NN0000
                    0192              ;RLCA
                    0193              ;LD   B,A           ;Store new ROM bank bits
                    0194              ;LD   A,(iConfigCpy)  ;Get current config byte
                    0195              ;LD   C,A           ;Store as 'previous' config byte
                    0196              ;AND  0b11001111    ;Clear ROM bank bits
                    0197              ;OR   B             ;Include new ROM bank bits
                    0198              ;OUT  (kConfigReg),A  ;Write new config byte to register
                    0199              ;LD   A,C           ;Get 'previous' config byte
                    0200              ;POP  BC            ;Restore number of bytes to copy
1BD4: ED B0         0201              LDIR                ;Copy (HL) to (DE) and repeat x BC
                    0202              ;OUT  (kConfigReg),A  ;Restore 'previous' config byte
1BD6: C9            0203              RET
1BD7:               0204  TransCopyEnd:
                    0205  
                    0206  
                    0207  ; **********************************************************************
                    0208  ; **  Public workspace (in RAM)                                       **
                    0209  ; **********************************************************************
                    0210  
                    0211              .DATA
                    0212  
                    0213  ; Hardware flags
                    0214  ; Bit 0 = Serial 6850 ACIA #1 detected
                    0215  ; Bit 1 = Serial Z80 SIO   #1 detected
                    0216  ; Bit 2 = Serial 6850 ACIA #2 detected
                    0217  ; Bit 3 to 7 = Not defined, all cleared to zero
A2A9: 00            0218  iHwFlags:   .DB  0x00           ;Hardware flags
                    0219  
A2AA: 00            0220  iHwIdle:    .DB  0              ;Poll timer count
                    0221  
                    0222  ; **********************************************************************
                    0223  ; **  End of Hardware manager                                         **
                    0224  ; **********************************************************************
                    0225  
                    0226  
                    0227  
                    0016  
                    0017  #INCLUDE    Monitor\End.asm
                    0001  ; **********************************************************************
                    0002  ; **  Small Computer Monitor code ending                              **
                    0003  ; **********************************************************************
                    0004  
                    0005              .CODE
1BD7:               0006  EndOfMonitor:
                    0006  EndOfMonitor:                   ; End of monitor code
                    0007  
                    0018  
                    0019  ;#INCLUDE    Hardware\SC_S4\ROM_Info.asm
                    0020  
                    0021  
                    0043  #ENDIF
                    0044  
                    0045  #IF         BUILD = "L*"
                    0046  #INCLUDE    Hardware\LiNC80\Build.asm
                    0047  #ENDIF
                    0048  
                    0049  #IF         BUILD = "R*"
                    0050  #INCLUDE    Hardware\RC2014\Build.asm
                    0051  #ENDIF
                    0052  
                    0053  #IF         BUILD = "S2"
                    0054  #INCLUDE    Hardware\SC_S2\Build.asm
                    0055  #ENDIF
                    0056  
                    0057  #IF         BUILD = "S3"
                    0058  #INCLUDE    Hardware\SC_S3\Build.asm
                    0059  #ENDIF
                    0060  
                    0061  #IF         BUILD = "S4"
                    0062  #INCLUDE    Hardware\SC_S4\Build.asm
                    0063  #ENDIF
                    0064  
                    0065  #IF         BUILD = "T1"
                    0066  #INCLUDE    Hardware\TomsSBC\Build.asm
                    0067  #ENDIF
                    0068  
                    0069  #IF         BUILD = "W1"
                    0070  #INCLUDE    Hardware\Workshop\Build.asm
                    0071  #ENDIF
                    0072  
                    0073  #IF         BUILD = "Z1"
                    0074  #INCLUDE    Hardware\Z280RC\Build.asm
                    0075  #ENDIF
                    0076  
                    0077  #IF         BUILD = "Z2"
                    0078  #INCLUDE    Hardware\Z80SBCRC\Build.asm
                    0079  #ENDIF
                    0080  
                    0081  
                    0082  
                    0083  
                    0084  
                    0085  
                    0086  
                    0087  
                    0088  
                    0089  
                    0090  
                    0091  
                    0092  
 
