;  SOLOS/AUSTIN EXTENSION
;   
SOLEXT  EQU  $
;   
  JMP  BOPEN
  JMP  PCLOS
  JMP  RTBYT
  JMP  WTBYT
;   
;  EXTENDED COMMAND TABLE
;   
EXTCT  EQU  $
  DW  -1  ;EXTRA SLOTS
  DW  -1
  DW  -1
  DW  -1
  DW  -1
  DW  -1
  ASC 'ED'
  DW  EXDEP
  ASC  'PR'
  DW  PRROM
  ASC  'TE'
  DW  TERM
  ASC  'EC'
  DW  ECHO
  ASC  'MO'
  DW  MOVE
  ASC  'ZI'
  DW  ZIP
  ASC  'DA'
  DW  DA
  ASC  'EO'
  DW  EOCT
  ASC  'DO'
  DW  DOCT
  ASC  'FI'
  DW  FIND
  DB  0
;  END OF TABLE
;   
; PROM programmer (64 passes)
; FROM and TO addresses must be
;    on 1K boundaries.
; (C) 1977 Ronald G. Parsons
;   
PRROM: CALL PARM
     PUSH H
     CALL PARM
     POP D
     LXI B,0
PWLOOP: LDAX D
     MOV M,A
     INX H
     INX D
     DCX B
     MOV A,C
     ORA A
     JNZ PWLOOP
     MOV A,B
     ORA A
     JZ VER
     ANI 3
     JNZ PWLOOP
     CALL ADJP
     JMP PWLOOP
VER:  CALL ADJP
     LXI B,400H
VLOOP: LDAX D
     CMP M
     CNZ VERR
     INX H
     INX D
     DCX B
     MOV A,C
     ORA B
     JNZ VLOOP
     RET done
PARM: CALL SCONV
     MOV A,H
     ANI 3
     JNZ ERR1
     MOV A,L
     ORA A
     JNZ ERR1
     RET
ADJP:  MOV A,H
     SUI 4
     MOV H,A
     MOV A,D
     SUI H
     MOV D,A
     RET
VERR: PUSH B
     CALL CRLF
     CALL ADOUT
     LDAX D
     CALL HBOUT
     MOV A,M
     CALL HBOUT
     POP B
     RET
; End of PRROM
;   
ECHO:  CALL SINP  ;TEST ROUTINE
  JZ  ECHO
  CPI  ESC
  JZ  COMND
  MOV  B,A
  CALL SOUT
  JMP  ECHO  ;AGAIN
;   
;   
;  MOVE COMMAND
;   
;  SYNTAX:
;  MOVE <p1> BYTES <p2> <p3>   ; <p1> bytes are moved starting
;                                from <p2> to <p3>
;  MOVE <p1> TO    <p2> <p3>   ; The segment from <p1> to <p2>
;                                is moved to <p3>
;  Moves may overlap
;   
MOVE  EQU  $
  CALL SCONV  ;GET P1
  PUSH H  ;SAVE P1
  CALL SBLK  ;LOOK FOR NEXT PARAMETER
  JZ  ERR1  ;NO PARAMETER
  LDAX  D  ;GET TYPE PARAMETER
  ANI  5FH  ;MAKE IT UPPER CASE
  CPI  'T'
  JZ  MOVETO
  CPI  'B'
  JNZ  ERR1
;  MOVE  ...  BYTE  ...  CODE
  CALL SCONV  ;GET P2
  PUSH  H
  CALL  SCONV  ;GET P3
MOVE1: POP  D
  CALL  COMPR  ;DE - HL
  POP  B
; B HAS # BYTES, D HAS FROM ADR, H HAS TO ADR
  JC  UPLP  ;MOVE UP
DNLP: LDAX  D
  MOV  M,A
  DCX  B
  INX  H
  INX  D
  MOV  A,C  ;DONE?
  ORA  B
  JNZ  DNLP
  RET
;   
MOVETO:  CALL SCONV  ;GET P2
  POP  B  ;GET P1
  PUSH  B  ;SAVE P1
  PUSH  D  ;SAVE COMMAND POINTER
  MOV  A,B  ;COMPLEMENT B (P1)
  CMA
  MOV  B,A
  MOV  A,C
  CMA
  MOV  C,A
  INX  B
  INX  B  ; + 1
  DAD  B  ;P2 - P1 + 1
  POP  D  ;RESTORE COMMAND POINTER
  POP  B  ;GET P2
  PUSH  H  ;SAVE P2 - P1 + 1
  PUSH  B  ;SAVE P2
  CALL  SCONV  ;GET P3
  JMP  MOVE1
;   
UPLP:  DCX  B  ;ADD BC - 1 TO DE AND HL
  DAD  B
  PUSH  H
  PUSH  D  ;MOVE DE TO HL
  POP  H
  DAD  B
  PUSH  H
  POP  D
  POP  H
  INX  B  ;RESTORE B
UPLP1:  LDAX  D
  MOV  M,A
  DCX  B
  DCX  H
  DCX  D
  MOV  A,C  ;DONE?
  ORA  B
  JNZ  UPLP1
  RET
;   
;   
;  ZIP  COMMAND
;   
;  SYNTAX:
;  ZIP                         ;    0    - SOLOS   <--   0
;  ZIP <byte>                  ;    0    - SOLOS   <--  <BYTE>
;  ZIP <byte>  <add1>          ;    0    - <add1>  <--  <byte>
;  ZIP <byte>  <add1>  <add2>  ;  <add1> - <add2>  <--  <byte>
;   
ZIP  EQU  $
  DCX  H
  PUSH  H  ;SAVE SOLOS ADDRESS - 1
  CALL SBLK  ;LOOK FOR PARM
  JZ  ZIP0  ;NONE
  CALL SHEX
  MOV  A,L
  JMP  ZIP1
ZIP0:  XRA  A  ;DEFAULT BYTE
ZIP1:  POP  H  ;GET ADD1 DEFAULT
  PUSH PSW  ;SAVE BYTE
  CALL PSCAN  ;ADD1 IN HL
  PUSH  H
  CALL SBLK  ;LOOK FOR LAST PARM
  JZ  ZIP2  ;NO ADD2
  CALL  SHEX  ;ADD2 IN HL
  POP  D  ;LOW LIM IN DE, UP LIM IN HL
  JMP  ZIP3
ZIP2:  LXI D,0  ;DEFAULT LOWER LIMIT
  POP H  ;0 IN DE, UP LIM IN HL
ZIP3:  POP B  ;BYTE TO B
  XCHG .  ;LOW LIM IN HL, UP LIM IN DE
;   
  CALL  COMPR
  INX  D
  JNC  ZIP4
  MVI  D,6  ;LIMITS OUT OF ORDER
  LXI  H,ERRM
  CALL  NLOOP
  JMP  COMND
;   
ZIP4  EQU  $
  MOV  M,B  ;STORE BYTE
  INX  H
  CALL  COMPR
  JZ  COMND  ;DONE
  JMP  ZIP4
;   
COMPR:  MOV  A,E  ; DE - HL
  SUB  L
  MOV  C,A
  MOV  A,D
  SBB  H
  RC .  ; CY SET IF NEGATIVE
  ORA  C  ;ZERO SET IF ZERO
  RET
;   
;   
;   
;  ;;;;; TERMINAL COMMAND ;;;;;
;   
;  THIS ROUTINE GETS CHARACTERS FROM THE SYSTEM KEYBOARD
; AND OUTPUTS THEM TO THE SELECTED OUTPUT PORT.  IT IS
; INTENDED TO CONFIGURE THE SOL AS A STANDARD VIDEO
; TERMINAL.  COMMAND KEYS ARE NOT OUTPUT TO THE OUTPUT
; PORT BUT ARE INTERPRETED AS DIRECT SOL COMMANDS.
; THE MODE COMMAND, RECEIVED BY THE KEYBOARD, PUTS THE SOL
; IN THE COMMAND MODE.
;   
;
;
TERM:  CALL  PSCAN  ;FIND IF INPUT PARAMETER IS PRESENT
  STA  IPORT  ;SINP WILL USE THIS DRIVER (DEFAULT IS 1)
  CALL  PSCAN  ;NOW FOR THE OUTPUT DRIVER
  STA  OPORT
;
TERM1:  CALL  KSTAT  ;IS THERE ONE WAITING?
  JZ  TIN  ;IF NOT
  MOV  B,A  ;SAVE IT IN B
  CPI  MODE  ;IS IT MODE?
  JZ  COMN1  ;YES...RESET AND QUIT TERM
  JC  TOUT  ;NON-CURSOR KEY...SEND TO TERM PORT
  CALL  VDMOT  ;PROCESS IT
  JMP  TIN
;   
TOUT:  CALL  SOUT  ;OUTPUT IT TO THE SERIAL PORT
TIN:  CALL  SINP  ;GET INPUT STATUS
  JZ  TERM1  ;LOOP IF NOT
  ANI  7FH  ;NO HIGH BITS FROM HERE
  JZ  TERM1  ;A NULL IS IGNORED
  MOV  B,A  ;IT'S OUTPUT FROM 'B'
  CPI  1BH  ;IS IT A CONTROL CHAR TO BE IGNORED
  JNC  TERM2  ;NO...TO VDM AS IS THEN
  CPI  CR  ;CR OR LF ARE SPECIAL CASES THOUGH
  JZ  TERM2  ;AND MUST BE PASSED STD MODE TO VDM
  CPI  LF
  JZ  TERM2
  LDA  ESCFL  ;A CTRL CHAR...ARE WE W/IN ESC SEQUENCE?
  ORA  A  ;IF YES, THEN OUTPUT CTRL CHAR DIRECTLY TO VDM
  JNZ  TERM2  ;WE SURE ARE, LET VDM DRIVER HANDLE IT
  PUSH  B  ;SAVE THE CHARACTER
  MVI  B,ESC  ;CTRL CHAR TO VDM VIA ESC SEQUENCE
  CALL  VDMOT
  MVI  B,7  ;SAY TO PUT OUT NEXT CHAR AS IS
  CALL   VDMOT  ;ALMOST READY
  POP  B  ;RESTORE CHAR
TERM2:  EQU  $  ;ALL READY TO OUTPUT THE CHAR
  CALL  VDMOT  ;PUT IT ON THE SCREEN
  JMP  TERM1  ;LOOP OVER AND OVER
;   
;   
; THE FOLLOWING ROUTINES PROVIDE "BYTE BY BYTE" ACCESS
; TO THE CASSETTE TAPES ON EITHER A READ ORWRITE BASIS.
;   
; THE TAPE IS READ ONE BLOCK AT A TIME AND INDIVIDUAL
; TRANSFERS OF DATA HANDLED BY MANAGING A BUFFER AREA.
;   
; THE BUFFER AREA IS CONTROLLED BY A FILE CONTROL BLOCK
; (FCB) WHOSE STRUCTURE IS:
;
;    7 BYTES FOR EACH OF THE TWO FILES STRUCTURED AS
;    FOLLOWS:
;
;  1 BYTE - ACCESS CONTROL    00 IF CLOSED
;          FF IF READING
;          FEIF WRITING
;  1 BYTE - READ COUNTER
;  1 BYTE - BUFFER POSITION POINTER
;  2 BYTE - CONTROL HEADER ADDRESS
;  2 BYTE - BUFFER LOCATION ADDRESS
;   
;   
;   
; THIS ROUTINE "OPENS" THE CASSETTE UNIT FOR ACCESS
;
; ON ENTRY:   A - HAS THE TAPE UNIT NUMBER (1 OR 2)
;    HL - HAS USER SUPPLIED HEADER FOR TAPE FILE
;
;
; NORMAL RETURN:  ALL REGISTERS ARE ALTERED
;      BLOCK IS READY FOR ACCESS
;   
; ERROR RETURN:   CARRY BIT IS SET
;   
; ERRORS:   BLOCK ALREADY OPEN
;
;   
BOPEN:  PUSH  H  ;SAVE HEADER ADDRESS
  CALL  LFCB  ;GET ADDRESS OF FILE CONTROL
  JNZ  TERE2  ;FILE WAS ALREADY OPEN
  MVI  M,1  ;NOW IT IS
  INX  H  ;POINT TO READ COUNT
  MOV  M,A  ;ZERO
  INX  H  ;POINT TO BUFFER CURSOR
  MOV  M,A  ;PUT IN THE ZERO COUNT
;
; ALLOCATE THE BUFFER
;   
  LXI  D,FBUF1  ;POINT TO BUFFER AREA
  LDA  FNUMF  ;GET WHICH ONE WE ARE GOING TO USE
  ADD  D
  MOV  D,A  ;256 BIT ADD
;   
UBUF:  POP  B  ;HEADER ADDRESS
  ORA  A  ;CLEAR CARRY AND RET AFTER STORING PARAMS
  JMP  PSTOR  ;STORE THE VALUES
;
; GENERAL ERROR RETURN POINTS FOR STACK CONTROL
;
TERE2:  POP  H
TERE1:  POP  D
TERE0:  XRA  A  ;CLEAR ALL FLAGS
  STC    ;SET ERROR
  RET
;
;   
EOFER:  DCR  A  ;SET MINUS FLAGS
  STC    ;AND CARRY
  POP  D  ;CLEAR THE STACK
  RET    ;THE FLAGS TELL ALL
;
;
;
;
; THIS ROUTINE CLOSES THE FILE BUFFER TO ALLOW ACCESS
; FOR A DIFFERENT CASSETTE OF PROGRAM.  IF THE TILE
; OPERATIONS WERE "WRITE" THEN THE LAST BLOCK IS WRITTEN
; OUT AND AN "END OF FILE" WRITTEN TO THE TAPE.  IF
; THE OPERATIONS WERE "READS" THEN THE FILE IS JUST
; MADE READY FOR NEW USE.
;
; ON ENTRY:   A - HAS WHICH UNIT (1 OR 2)
;
; ERROR RETURNS:   FILE WASN'T OPEN
;   
;   
PCLOS:  CALL  LFCB  ;GET CONTROL BLOCK ADDRESS
  RZ    ;WASN'T OPEN, CARRY IS SET FROM LFCR
  ORA  A  ;CLEAR CARRY
  INR  A  ;SET CONDITION FLAGS
  MVI  M,0  ;CLOSE THE CONTROL BYTE
  RZ    ;WE WERE READING...NOTHING MORE TO DO
;
; THE FILE OPERATIONS WERE "WRITES"
;
; PUT THE CURRENT BLOCK ON THE TAPE
; (EVEN IF ONLY ONE BYTE)
; THEN WRITE AN END OF FILE TO THE TAPE
;
;
  INX  H
  INX  H
  MOV  A,M  ;GET CURSOR POSITION
  CALL  PLOAD  ;BC GET HEADER ADDRESS, DE BUFFER ADDRESS
  PUSH  B  ;HEADER TO STACK
  LXI  H,BLKOF  ;OFFSET TO BLOCK SIZE
  DAD  B
  ORA  A  ;TEST COUNT
  JZ  EOFW  ;NO BYTES...JUST WRITE EOF
;
; WRITE LAST BLOCK
;   
  PUSH  H  ;SAVE BLOCK SIZE POINTER FOR EOF
  MOV  M,A  ;PUT IN COUNT
  INX  H
  MVI  M,0  ;ZERO THE HIGHER BYTE
  INX  H
  MOV  M,E  ;BUFFER ADDRESS
  INX  H
  MOV  M,D
  MOV  H,B
  MOV  L,C  ;PUT HEADER ADDRESS IN HL
  CALL  WFBLK  ;GO WRITE IT OUT
  POP  H  ;BLOCK SIZE POINTER
;
; NOW WRITE END OF FILE TO CASSETTE
;
EOFW:  XRA  A  ;PUT IN ZEROS FOR SIZE
;      EOF MARK IS ZERO BYTES!
  MOV  M,A
  INX  H
  MOV  M,A
  POP  H  ;HEADER ADDRESS
  JMP  WFBLK  ;WRITE IT OUT AND RETURN
;
;
;
;
; THIS ROUTINE LOCATES THE FILE CONTROL BLOCK POINTED TO
; BY REGISTER "A".  ON RETURN HL POINTS TO THE CONTROL BYTE
; AND REGISTER "A" HAS THE CONTROL WORD WITH THE FLAGS
; SET FOR IMMEDIATE CONDITION DECISIONS.
;
;
LFCB:  LXI  H,FCBAS  ;POINT PO THE BASE OF IT
  RAR    ;MOVE THE 1 & 2 TO 0 & 1
  ANI  1  ;SMALL NUMBERS ARE THE RULE
  STA  FNUMF  ;CURRENT ACCESS FILE NUMBER
  JZ  LFCB1  ;UNIT ONE (VALUE OF ZERO)
  LXI  H,FCBA2  ;UNIT TWO--POINT TO ITS FCB
LFCB1:  EQU  $  ;HL POINT TO PROPER FCB
  MOV  A,M  ;PICK UP FLAGS FROM FCB
  ORA  A  ;SET FLAGS BASED ON CONTROL WORD
  STC    ;SET CARRY IN CASE OF IMMEDIATE ERROR RET
  RET
;
;
;
;
;  READ TAPE BYTE ROUTINE
;
; ENTRY:  - A - HAS FILE NUMBER
; EXIT:  NORMAL - A - HAS BYTE
;   ERROR
;      CARRY SET     - IF FILE NOT OPEN OR
;           PREVIOUS OPERATIONS WERE WRITE
;      CARRY & MINUS  - END OF FILE ENCOUNTERED
;
;
;
;
RTBYT:  CALL  LFCB  ;LOCATE THE FILE CONTROL BLOCK
  RZ    ;FILE NOT OPEN
  INR  A  ;TEST IF FF
  JM  TERE0  ;ERROR WAS WRITING
  MVI  M,-1  ;SET IT AS READ (IN CASE IT WAS JUST OPENED)
  INX  H
  MOV  A,M  ;GET READ COUNT
  PUSH  H  ;SAVE COUNT ADDRESS
  INX  H
  CALL  PLOAD  ;GET THE OTHER PARAMETERS
  POP  H
  ORA  A
  JNZ  GTBYT  ;IF NOT EMPTY GO GET BYTE
;
; CURSOR POSITION WAS ZERO...READ A NEW BLOCK
; INTO THE BUFFER.
;
RDNBLK:  PUSH  D  ;BUFFER POINTER
  PUSH  H  ;TABLE ADDRESS
  INX  H
  CALL  PHEAD  ;PREPARE THE HEADER FOR READ
  CALL  RFBLK  ;READ IN THE BLOCK
  JC  TERE2  ;ERROR POP OFF STACK BEFORE RETURN
  POP  H
  MOV  A,E  ;LOW BYTE OF COUNT (WILL BE ZERO IF 256)
  ORA  D  ;SEE IF BOTH ARE ZERO
  JZ  EOFER  ;BYTE COUNT WAS ZERO...END OF FILE
  MOV  M,E  ;NEW COUNT (ZERO IS 256 AT THIS POINT)
  INX  H  ;BUFFER LOCATION POINTER
  MVI  M,0
  DCX  H
  MOV  A,E  ;GET BACK BUFFER ADDRESS
  POP  D
;
;
;
; THIS ROUTINE GETS ONE BYTE FROM THE BUFFER
; AND RETURNS IT IN REGISTER "A".  IF THE END
; OF THE BUFFER IS REACHED IT MOVES THE POINTER
; TO THE BEGINNING OF THE BUFFER FOR THE NEXT
; LOAD.
;   
GTBYT:  DCR  A  ;BUMP THE COUNT
  MOV  M,A  ;RESTORE IT
  INX  H
  MOV  A,M  ;GET BUFFER POSITION
  INR  M  ;BUMP IT
;
  ADD  E
  MOV  E,A  ;DE NOW POINT TO CORRECT BUFFER POSITION
  JNC  RT1
  INR  D
RT1:  LDAX  D  ;GET CHARACTER FROM BUFFER
  ORA  A  ;CLEAR CARRY
  RET    ;ALL DONE
;
;
;   
; THIS ROUTINE IS USED TO WRITE A BYTE TO THE FILE
;
; ON ENTRY:  A - HAS FILE NUMBER
;    B - HAS DATA BYTE
;
;
WTBYT:  CALL  LFCB  ;GET CONTROL BLOCK
  RZ    ;FILE WASN'T OPEN
  INR  A
  RZ    ;FILE WAS READ
  MVI  M,0FEH  ;SET IT TO WRITE
  INX  H
  INX  H
  MOV  A,B  ;GET CHARACTER
  PUSH  PSW
  PUSH  H  ;SAVE CONTROL ADDRESS+2
;   
; NOW DO THE WRITE
;   
  CALL  PLOAD  ;BC GETS HEADER ADDR
;      DE BUFFER ADDRESS
  POP  H
  MOV  A,M  ;COUNT BYTE
  ADD  E
  MOV  E,A
  JNC  WT1
  INR  D
WT1:  POP  PSW  ;CHARACTER
  STAX  D  ;PUT CHR IN BUFFER
  ORA  A  ;CLEAR FLAGS
  INR  M  ;INCREMENT THE COUNT
  RNZ    ;RETURN IF COUNT DIDN'T ROLL OVER
;
; THE BUFFER IS FULL.  WRITE IT TO TAPE
; AND RESET CONTROL BLOCK.
;   
  CALL  PHEAD  ;PREPARE THE HEADER
  JMP  WFBLK  ;WRITE IT OUT AND RETURN
;
;
;
;
; THIS ROUTINE PUTS THE BLOCK SIZE (256) AND BUFFER
; ADDRESS IN THE FILE HEADER.
;   
PHEAD:  CALL  PLOAD  ;GET HEADER AND BUFFER ADDRESSES
  PUSH  B  ;HEADER ADDRESS
  LXI  H,BLKOF-1  ;PSTOR DOES AN INCREMENT
  DAD  B  ;HL POINTS TO  BLOCKSIZE ENTRY
  LXI  B,256
  CALL  PSTOR
  POP  H  ;HL RETURN WITH HEADER ADDRESS
  RET
;
;
PSTOR:  INX  H
  MOV  M,C
  INX  H
  MOV  M,B
  INX  H
  MOV  M,E
  INX  H
  MOV  M,D
  RET
;   
;
PLOAD:  INX  H
  MOV  C,M
  INX  H
  MOV  B,M
  INX  H
  MOV  E,M
  INX  H
  MOV  D,M
  RET
;   
;   
; Dump routine for both hex and ASCII
; Syntax same as DUMP
; (C) 1977 Ronald G. Parsons
;
; Entry point
DA   EQU $
     CALL SCONV
     PUSH H
     CALL PSCAN
     POP D
     XCHG
;
DALP EQU $
     CALL CRLF
     CALL ADOUT
     CALL BOUT
     MVI C,8   values per line
     PUSH H    save start H
;   
DALP1 EQU $
     MOV A,M
     PUSH B
     CALL HBOUT
     MOV A,L
     SUB E
     MOV A,H
     SBB D
     POP B
     JNC DALP3
     INX H
     DCR C
     JNZ DALP1
DALP3 EQU $
     MVI B,ESC
     CALL SOUT begin escape sequence
     MVI B,1
     CALL SOUT
     MVI B,31
     CALL SOUT
     MVI C,8   values per line
     POP H     restore H
;
DALP2 EQU $
     MVI B,ESC begin escape sequence
     CALL SOUT
     MVI B,7   2nd escape
     CALL SOUT
     MOV B,M
     CALL SOUT output character
     CALL BOUT
     MOV A,L
     SUB E
     MOV A,H
     SBB D
     JNC COMND
     INX H
     DCR C
     JNZ DALP2
     JMP DALP
;
; Enter Octal (EO)
;    and Dump Octal (DO)
; (C) 1977 Ronald G. Parsons
; Syntax same as SOLOS EN command
;    and DU command
; Uses split octal for addresses
; Can only be used in lower 32K
; Entry point
EOCT CALL SCON
     PUSH H
     XRA A
     STA OPORT
EOLOP CALL CRLF
     MVI B,':'
     CALL CONT
     CALL CREM
     MVI C,1
     CALL VDAD2
     XCHG
EOLO1 MVI C,3
     CALL SCHR1
     JZ EOLOP
     CPI '/'
     JZ COMN1
     CALL SOCT
     CPI ':'
     JZ EOLO3
     MOV A,L
     POP H
     MOV M,A
     INX H
     PUSH H
     JMP EOLO1
EOLO3 XTHL
     INX D
     JMP EOLO1
;   
SCON  CALL SBLK
     JZ ERR1
     XRA  A
     STA  DHEAD  ;TEMP STORE
SOCT LXI H,0
SOC1 LDAX D
     CPI ' '
     JZ ADJ
     CPI '/'
     JZ ADJ
     CPI ':'
     JZ ADJ
     CPI '.'
     JZ ADJ-1
OCONV DAD H
     DAD H
     DAD H
     CC  SETCY  ;SET DAD CY FLAG
     SUI 48
     CPI 8
     JNC ERR1
     ADD L
     MOV L,A
     INX D
     JMP SOC1
     INX D
ADJ  PUSH PSW
     MOV  A,H  ;CHECK FOR BIT 8 HIGH
     ANI  1
     JNZ  ERR1
     MOV A,H  ;Shift H 1 bit right
     RRC
     MOV H,A
     CALL  GETCY  ;BRING IN BIT 15
     POP PSW
     RET
;   
SETCY:  PUSH  PSW
     MVI  A,80H
     STA  DHEAD  ;STORE CARRY
     POP  PSW
     RET
;   
GETCY:  LDA  DHEAD
     ORA  A
     RZ  .  ;NO CARRY
     ORA  H  ;ADD TO H
     MOV  H,A  ;SAVE IT
     RET
;   
; End of EOCT
;   
; Entry point
DOCT CALL SCON
     PUSH H
     CALL OSCAN
     POP D
     XCHG
OLOOP CALL CRLF
     CALL AOOUT
     CALL OOUT
     MVI C,8
DLP2 MOV A,M
     PUSH B
     CALL OBOUT
     MOV A,L
     SUB E
     MOV A,H
     SBB D
     JNC COMND
     POP B
     INX H
     DCR C
     JNZ DLP2
     JMP OLOOP
OSCAN CALL SBLK
     MVI A,1
     RZ
     CALL SOCT
     MOV A,L
     RET
AOOUT MOV A,H
     CALL OCOUT
     MOV A,L
OBOUT CALL OCOUT
OOUT MVI B,' '
     JMP SOUT
OCOUT MOV C,A
     RLC
     RLC
     ANI 3
     CALL OCOU1 upper 2
     MOV A,C
     RRC
     RRC
     RRC
     CALL OCOU1 middle 3
     MOV A,C
OCOU1 ANI 7
     ADI 48
     MOV B,A
     JMP SOUT
; End of DOCT
;   
;  FIND ROUTINE
;   
;  SYNTAX
;  FIND  <low-adr>  <high-adr>  {A or H}
;       A  for ASCII search; H for hex search
;       A line will be prompted by :
;       Up to 16 ASCII characters (terminated by \) or
;       up to 16 hex numbers (terminated by /) may be input.
;   
FIND  EQU  $
  CALL  SCONV  ;GET P1
  PUSH  H
  CALL  SCONV  ;GET P2
  PUSH  H
  CALL  SBLK
  JZ  ERR1
  LDAX  D  ;GET P3
  ANI  5FH  ;MAKE IT UPPER CASE
  CPI  'A'
  JZ  SEA1
  CPI  'H'
  JNZ  ERR1  ;PARM NOT VALID
;   
SEA1:  PUSH  PSW
  CALL CRLF
  CALL CLINE  ;CLEAR LINE
  MVI  B,':'  ;PROMPT
  CALL  CONT  ;GET INPUT LINE
  CALL  CREM
  MVI  C,1  ;START SCAN
  CALL  VDAD2  ;GET ADDRESS
  XCHG
  LXI  H,DHEAD  ;SEARCH BUFFER
  MVI  B,17  ;16 MAX VALUES
  POP  PSW
  CPI  'A'
  JZ  SEAAS  ;ASCII SEARCH
;   
SEAHX  EQU  $  ;HEX SEARCH
  MVI  C,3  ;3 SPACES MAX
  CALL  SCHR1  ;GET VALUE
  JZ  ERR1  ;NO TERMINATOR
  CPI  '/'  ;TERMINATOR?
  JZ  GOSH  ;GO SEARCH
  PUSH  H  ;CONVERT
  CALL  SHEX
  MOV  A,L
  POP  H
  DCR  B
  JZ  ERR1  ;TOO MANY
  MOV  M,A
  INX  H
  JMP  SEAHX
;   
SEAAS  EQU  $
  LDAX  D
  CPI  '\'  ;TERMINATOR?
  JZ  GOSH  ;GO SEARCH
  DCR  B
  JZ  ERR1  ;TOO MANY
  MOV  M,A
  INX  D
  INX  H
  JMP  SEAAS
;   
GOSH  EQU  $
  POP  D  ;END ADDRESS
  POP  H  ;START ADDRESS
  MOV  A,B  ;CALCULATE STRING LENGTH
  CMA
  ADI  18  ;#  CHARACTERS
  MOV  B,A
  ORA  A
  JZ  COMND  ;ZERO LEN STRING
  PUSH  B
  CALL CRLF
  POP  B
;   
GOSH1  EQU  $
  PUSH  B
  PUSH  D
  PUSH  H
  LXI  D,DHEAD
  CALL DHLOP  ;COMPARE
  POP  H
  PUSH  PSW
  CZ  ADOUT  ;GOT ONE
  POP  PSW
  CZ  CRLF
  POP  D
  CALL COMPR  ;DE - HL
  POP  B
  JZ  COMND  ;DONE
  INX  H
  JMP  GOSH1  ;AGAIN
;   
;   
;  EXAMINE/DEPOSIT
;   
; SYNTAX  ED <addr>
; <addr> IS DISPLAYED WITH ITS CONTENTS
; THE KEYBOARD IS READ AND IF A 1 OR 2 DIGIT HEX NUMBER
;    IS INPUT, THAT VALUE WILL REPLACE THE CURRENT CONTENTS.
; IF A CR, SPACE, SLASH, COLON OR A HEX NUMBER LARGER THAN FF
;    IS INPUT, THE CURRENT CONTENTS ARE UNCHANGED
; THE NEXT MEMORY LOCATION IS THEN EXAMINED
;   
; MODE OR CONVERSION ERROR TERMINATES THE COMMAND
;   
EXDEP  EQU  $
  CALL  SCONV  ;GET START ADDRESS
EXDP1:  CALL CRLF
  CALL  ADOUT  ;DISPLAY HL
  MOV  A,M
  CALL  HBOUT  ;DISPLAY (HL)
  PUSH  H
  CALL  GCLIN  ;GET INPUT LINE
  CALL CREM  ;REMOVE CURSOR
  MVI  C,8
  CALL  VDAD2  ;GET SCREEN ADDRESS
  XCHG    ;  TO DE
  LXI  H,8000H
  CALL  SHE1  ;CONVERT VALUE
  MOV  A,H
  ORA  A
  JNZ  NOCHG  ;INVALID OR NO INPUT
  MOV  A,L  ;GET VALUE
  POP  H
  MOV  M,A  ;DEPOSIT IT
  CMP  M  ;TEST MEMORY
  JNZ  ERR1  ;BAD MEMORY OR ROM
EXDP2:  INX  H  ;NEXT
  JMP  EXDP1
NOCHG:  POP  H
  JMP  EXDP2
;   
;   

