home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol099 / du2.asm < prev    next >
Assembly Source File  |  1984-04-29  |  69KB  |  3,903 lines

  1. ;
  2. ; PROGRAM:  DU2
  3. ; AUTHOR:  RICHARD CONN
  4. ; DERIVATION:  DUTIL is derived from DU Version 7.5
  5. ;        DU2 is derived from DUTIL Version 1.1
  6. ; VERSION:  1.0
  7. ; DATE:  10 JAN 83
  8. ; PREVIOUS VERSIONS:  None
  9. ; NOTE:  DU2 must be assembled using MAC (or equiv) and will only run on
  10. ;        a Z80
  11. ;
  12. VERS    EQU    10
  13.  
  14. ;
  15. ;  DU2 is derived from --
  16. ;      DU.ASM  V7.5    Revised 1/23/81
  17. ;    DISK UTILITY - By Ward Christensen
  18. ;
  19. ;  Principal Authors of DU V7.5 are --
  20. ;    WLC   KBP   RGF   BRR
  21. ;
  22. ;  Key comments from DU V7.5 and DU2 follow --
  23. ;
  24. ;This version of DU is compatible with CP/M 1.4 and 2.x
  25. ;and does not require alteration for various hardware
  26. ;configurations.  It adjusts itself automatically to
  27. ;the correct number of sectors, tracks, directory size,
  28. ;etc.  It has been tested on 5-1/4" and 8" floppy, and
  29. ;10 megabyte hard disk systems.
  30. ;
  31. ;Because of the automatic adaption feature, no conditional
  32. ;assembly options are included.  The only alteration that
  33. ;needs to be done is to use DDT to set the byte at 103h
  34. ;to zero for systems using a 2 mHz clock or non-zero for
  35. ;4 mHz clock.  This only affects the time delay used in
  36. ;the 'sleep' command.
  37. ;
  38. ;For DU2, the additional value of PAGSIZ at 104h should
  39. ;be set for the size of the display (in lines) on the user's
  40. ;CON: device.  Under DU2, all output is paged, and this
  41. ;determines the page limit.
  42. ;
  43. ;*************************************************
  44. ;*                          *
  45. ;*   This program has been heavily modified     *
  46. ;* to allow it to work without modification     *
  47. ;* on most versions of CP/M 1.4 and, hopefully,     *
  48. ;* all versions of CP/M 2.x.             *
  49. ;*   One known possible problem involves the     *
  50. ;* system tracks on some systems, and results     *
  51. ;* from the system sectors being skewed. There     *
  52. ;* is NO way for a program executing under CP/M     *
  53. ;* to know about this.  This program assumes the *
  54. ;* standard convention of no skew being used on     *
  55. ;: the system tracks. This usually isn't a prob- *
  56. ;* lem because the SYSGEN program can be used to *
  57. ;* get the system from the disk so that    it can     *
  58. ;* be modified.                     *
  59. ;*   This program should work under standard     *
  60. ;* versions of CP/M 1.4.  The only requirement     *
  61. ;* is that the BIOS "SETSEC" routine not modify     *
  62. ;* the sector number passed to it in the B      *
  63. ;* register.  Again, system tracks with skewed     *
  64. ;* sectors will be a problem.             *
  65. ;*   If you add any features or make any useful     *
  66. ;* changes to this program, please modem a copy     *
  67. ;* to the above CBBS, so the currency of the     *
  68. ;* program can be maintained.             *
  69. ;*                          *
  70. ;*         Ron Fowler             *
  71. ;*                          *
  72. ;*************************************************
  73. ;
  74. ;  The last few revision notes for note are --
  75. ;
  76.  
  77. ;
  78. ;System equates
  79. ;
  80. BASE    EQU    0    ;SET TO 4200H FOR HEATH OR TRS-80 ALTCPM
  81. ;
  82. ;CP/M Key Areas
  83. ;
  84. FCB    EQU    BASE+5CH    ;CP/M FCB
  85. BDOS    EQU    BASE+5        ;CP/M BDOS ENTRY POINT
  86. TBUFF    EQU    BASE+80H    ;CP/M TEMPORARY DISK I/O BUFFER
  87. TPA    EQU    BASE+100H    ;CP/M TRANSCIENT PROGRAM AREA
  88. ;
  89. ;  Some Key Variables in DU2
  90. ;
  91. EOLCH    equ    ','        ;Marks logical end of line
  92. SEPCH    equ    ' '        ;Argument Separator
  93. MULCH    equ    '*'        ;Multiplication Command
  94.  
  95. ;
  96. ;CP/M BDOS Function Codes
  97. ;
  98. PRINT    EQU    9
  99. GVERS    EQU    12
  100. RESETDK EQU    13    ;RESET SYSTEM
  101. SELDK    EQU    14    ;SELECT DISK
  102. CLOSEF    EQU    16    ;CLOSE FILE
  103. SRCHF    EQU    17    ;SEARCH FIRST
  104. DELF    EQU    19    ;DELETE FILE
  105. WRITEF    EQU    21    ;WRITE BLOCK TO FILE
  106. MAKEF    EQU    22    ;CREATE FILE
  107. SUSER    EQU    32    ;SELECT USER
  108. GETDSK    EQU    25
  109. GETDPB    EQU    31
  110. ;
  111. ;CP/M 1.4 Offsets and Some Key Values
  112. ;
  113. TRNOFF    EQU    15    ;CP/M 1.4 OFFSET FROM BASE
  114.             ;OF BDOS TO SECTRAN ROUTINE
  115. SKWOFF    EQU    1AH    ;CP/M 1.4 OFFSET TO SKEW TABLE
  116. S2OFF    EQU    14    ;OFFSET INTO FCB FOR S2 BYTE
  117. DPBOFF    EQU    3AH    ;CP/M 1.4 OFFSET TO DPB WITHIN BDOS
  118. S2MASK    EQU    0FH    ;MASK FOR EXTENDED RC BITS OF S2
  119. DPBLEN    EQU    15    ;SIZE OF CP/M 2.x DISK PARM BLOCK
  120. ;
  121. ;Define ASCII characters
  122. ;
  123. CR    EQU    0DH    ;CARRIAGE RETURN
  124. LF    EQU    0AH    ;LINE FEED
  125. TAB    EQU    09H    ;TAB
  126. BS    EQU    08H    ;BACKSPACE
  127.  
  128. ;
  129. ; MACROS TO PROVIDE Z80 EXTENSIONS
  130. ;   MACROS INCLUDE:
  131. ;
  132. $-MACRO         ;FIRST TURN OFF THE EXPANSIONS
  133. ;
  134. ;    JR    - JUMP RELATIVE
  135. ;    JRC    - JUMP RELATIVE IF CARRY
  136. ;    JRNC    - JUMP RELATIVE IF NO CARRY
  137. ;    JRZ    - JUMP RELATIVE IF ZERO
  138. ;    JRNZ    - JUMP RELATIVE IF NO ZERO
  139. ;    DJNZ    - DECREMENT B AND JUMP RELATIVE IF NO ZERO
  140. ;    LDIR    - MOV @HL TO @DE FOR COUNT IN BC
  141. ;    LXXD    - LOAD DOUBLE REG DIRECT
  142. ;    SXXD    - STORE DOUBLE REG DIRECT
  143. ;    EXX    - EXCHANGE BC, DE, HL WITH BC', DE', HL'
  144. ;
  145. ;
  146. ;
  147. ;    @GENDD MACRO USED FOR CHECKING AND GENERATING
  148. ;    8-BIT JUMP RELATIVE DISPLACEMENTS
  149. ;
  150. @GENDD    MACRO    ?DD    ;;USED FOR CHECKING RANGE OF 8-BIT DISPLACEMENTS
  151.     IF (?DD GT 7FH) AND (?DD LT 0FF80H)
  152.     DB    100H    ;Displacement Range Error on Jump Relative
  153.     ELSE
  154.     DB    ?DD
  155.     ENDIF        ;;RANGE ERROR
  156.     ENDM
  157. ;
  158. ;
  159. ; Z80 MACRO EXTENSIONS
  160. ;
  161. JR    MACRO    ?N    ;;JUMP RELATIVE
  162.     DB    18H
  163.     @GENDD    ?N-$-1
  164.     ENDM
  165. ;
  166. JRC    MACRO    ?N    ;;JUMP RELATIVE ON CARRY
  167.     DB    38H
  168.     @GENDD    ?N-$-1
  169.     ENDM
  170. ;
  171. JRNC    MACRO    ?N    ;;JUMP RELATIVE ON NO CARRY
  172.     DB    30H
  173.     @GENDD    ?N-$-1
  174.     ENDM
  175. ;
  176. JRZ    MACRO    ?N    ;;JUMP RELATIVE ON ZERO
  177.     DB    28H
  178.     @GENDD    ?N-$-1
  179.     ENDM
  180. ;
  181. JRNZ    MACRO    ?N    ;;JUMP RELATIVE ON NO ZERO
  182.     DB    20H
  183.     @GENDD    ?N-$-1
  184.     ENDM
  185. ;
  186. DJNZ    MACRO    ?N    ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
  187.     DB    10H
  188.     @GENDD    ?N-$-1
  189.     ENDM
  190. ;
  191. LDIR    MACRO        ;;LDIR
  192.     DB    0EDH,0B0H
  193.     ENDM
  194. ;
  195. LDED    MACRO    ?N    ;;LOAD DE DIRECT
  196.     DB    0EDH,05BH
  197.     DW    ?N
  198.     ENDM
  199. ;
  200. LBCD    MACRO    ?N    ;;LOAD BC DIRECT
  201.     DB    0EDH,4BH
  202.     DW    ?N
  203.     ENDM
  204. ;
  205. SDED    MACRO    ?N    ;;STORE DE DIRECT
  206.     DB    0EDH,53H
  207.     DW    ?N
  208.     ENDM
  209. ;
  210. SBCD    MACRO    ?N    ;;STORE BC DIRECT
  211.     DB    0EDH,43H
  212.     DW    ?N
  213.     ENDM
  214. ;
  215. EXX    MACRO        ;;EXCHANGE PRIMARY AND ALTERNATE REGISTERS
  216.     DB    0D9H
  217.     ENDM
  218. ;
  219. ; END OF Z80 MACRO EXTENSIONS
  220. ;
  221.  
  222.  
  223. ;
  224. ;Beginning of Program
  225. ;
  226.     ORG    TPA
  227.     jmp    start
  228.  
  229. ;
  230. ;******************************************************************
  231. ;
  232. ;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
  233. ;
  234. ;    This data block precisely defines the data format for
  235. ; initial features of a ZCPR2 system which are required for proper
  236. ; initialization of the ZCPR2-Specific Routines in SYSLIB.
  237. ;
  238.  
  239. ;
  240. ;  EXTERNAL PATH DATA
  241. ;
  242. EPAVAIL:
  243.     DB    0FFH    ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
  244. EPADR:
  245.     DW    40H    ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
  246.  
  247. ;
  248. ;  INTERNAL PATH DATA
  249. ;
  250. INTPATH:
  251.     DB    0,0    ; DISK, USER FOR FIRST PATH ELEMENT
  252.             ; DISK = 1 FOR A, '$' FOR CURRENT
  253.             ; USER = NUMBER, '$' FOR CURRENT
  254.     DB    0,0
  255.     DB    0,0
  256.     DB    0,0
  257.     DB    0,0
  258.     DB    0,0
  259.     DB    0,0
  260.     DB    0,0    ; DISK, USER FOR 8TH PATH ELEMENT
  261.     DB    0    ; END OF PATH
  262.  
  263. ;
  264. ;  MULTIPLE COMMAND LINE BUFFER DATA
  265. ;
  266. MCAVAIL:
  267.     DB    0FFH    ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
  268. MCADR:
  269.     DW    0FF00H    ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
  270.  
  271. ;
  272. ;  DISK/USER LIMITS
  273. ;
  274. MDISK:
  275.     DB    4    ; MAXIMUM NUMBER OF DISKS
  276. MUSER:
  277.     DB    31    ; MAXIMUM USER NUMBER
  278.  
  279. ;
  280. ;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
  281. ;
  282. ;DOK:
  283.     DB    0FFH    ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
  284. ;UOK:
  285.     DB    0FFH    ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
  286.  
  287. ;
  288. ;  PRIVILEGED USER DATA
  289. ;
  290. PUSER:
  291.     DB    10    ; BEGINNING OF PRIVILEGED USER AREAS
  292. PPASS:
  293.     DB    'chdir',0    ; PASSWORD FOR MOVING INTO PRIV USER AREAS
  294.     DS    41-($-PPASS)    ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
  295.  
  296. ;
  297. ;  CURRENT USER/DISK INDICATOR
  298. ;
  299. CINDIC:
  300.     DB    '$'    ; USUAL VALUE (FOR PATH EXPRESSIONS)
  301.  
  302. ;
  303. ;  DMA ADDRESS FOR DISK TRANSFERS
  304. ;
  305. DMADR:
  306.     DW    80H    ; TBUFF AREA
  307.  
  308. ;
  309. ;  NAMED DIRECTORY INFORMATION
  310. ;
  311. NDRADR:
  312.     DW    00000H    ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
  313. NDNAMES:
  314.     DB    64    ; MAX NUMBER OF DIRECTORY NAMES
  315. DNFILE:
  316.     DB    'NAMES   '    ; NAME OF DISK NAME FILE
  317.     DB    'DIR'        ; TYPE OF DISK NAME FILE
  318.  
  319. ;
  320. ;  REQUIREMENTS FLAGS
  321. ;
  322. EPREQD:
  323.     DB    000H    ; EXTERNAL PATH?
  324. MCREQD:
  325.     DB    000H    ; MULTIPLE COMMAND LINE?
  326. MXREQD:
  327.     DB    0FFH    ; MAX USER/DISK?
  328. UDREQD:
  329.     DB    000H    ; ALLOW USER/DISK CHANGE?
  330. PUREQD:
  331.     DB    000H    ; PRIVILEGED USER?
  332. CDREQD:
  333.     DB    000H    ; CURRENT INDIC AND DMA?
  334. NDREQD:
  335.     DB    000H    ; NAMED DIRECTORIES?
  336. Z2CLASS:
  337.     DB    6    ; CLASS 6
  338.     DB    'ZCPR2'
  339.     DS    10    ; RESERVED
  340.  
  341. ;
  342. ;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
  343. ;
  344. ;******************************************************************
  345. ;
  346.  
  347. ;
  348. ;  Extra Buffers et al
  349. ;
  350. CLOCK:
  351.     DB    2    ;<---Put Processor Speed Here (1=1MHZ, 2=2MHZ, etc)
  352. PAGSIZ:
  353.     DB    24    ;<---Put CRT Screen Size Here (24 Lines default)
  354.     DB    'DU2.COM from DU.COM ver 7.5 1/23/81 by RLC'
  355. ;
  356. ;  Start of Program
  357. ;
  358. START:
  359.     LXI    H,0    ;GET PTR TO CP/M STACK
  360.     DAD    SP    ;HL=SP
  361.     SHLD    DUTSTK    ;SAVE IT
  362. ;
  363.     LXI    SP,DUTSTK    ; SET STACK
  364. ;
  365.     MVI    C,GVERS    ;GET CP/M VERSION NR
  366.     CALL    BDOS
  367.     MOV    A,H    ;MUST NOT BE VERSION 1.4
  368.     ORA    L
  369.     JRNZ    START1
  370.     CALL    ILPRT
  371.     DB    CR,LF,'DU2 cannot run on CP/M Version 1.4 -- Aborting',0
  372.     JMP    EXIT1
  373. ;
  374. ;Set up local jumps to BIOS
  375. ;
  376. START1:
  377.     LHLD    BASE+1    ;WARM BOOT POINTER
  378.     LXI    D,3    ;READY FOR ADD
  379.     DAD    D    
  380.     SHLD    VCONST+1    ;CON: Status
  381.     DAD    D
  382.     SHLD    VCONIN+1    ;CON: Input
  383.     DAD    D
  384.     SHLD    VCONOT+1    ;CON: Output
  385.     DAD    D
  386.     SHLD    VLIST+1        ;LST: Output
  387.     DAD    D    ;Skip PUNCH
  388.     DAD    D    ;Skip RDR
  389.     DAD    D
  390.     SHLD    VHOME+1        ;Home Disk
  391.     DAD    D
  392.     SHLD    VSELDK+1    ;Select Disk
  393.     DAD    D
  394.     SHLD    VSETRK+1    ;Set Track
  395.     DAD    D
  396.     SHLD    VSTSEC+1    ;Set Sector
  397.     DAD    D
  398.     SHLD    SETDMA+1    ;Set DMA Address
  399.     DAD    D
  400.     SHLD    VREAD+1        ;Read Block From Disk
  401.     DAD    D
  402.     SHLD    VWRITE+1    ;Write Block To Disk
  403.     DAD    D    ;Skip LISTST
  404.     DAD    D
  405.     SHLD    VSCTRN+1    ;CP/M 2.x Sector Translation Table
  406.     JR    HELLO
  407. ;
  408. ;Initialization Complete -- Print Signon Message and Begin Command Processing
  409. ;
  410. HELLO:
  411.     CALL    GETSTP    ;SET UP CP/M PARAMETERS
  412.     CALL    INITP    ;INITIALIZE BUFFER PARAMETERS
  413.     CALL    ILPRT
  414.     DB    CR,LF,'DU2 - Disk Utility II, Version '
  415.     DB    VERS/10+'0','.',(VERS MOD 10)+'0'
  416.     DB    CR,LF
  417.     DB    'Type ? for Help'
  418.     DB    CR,LF,0
  419.     LXI    H,TBUFF    ;TO INPUT BUFF
  420.     MOV    A,M
  421.     ORA    A
  422.     JRZ    PRMPTR    ;NO INITIAL COMMAND FROM COMMAND LINE
  423. ;
  424. ;Got initial command, set it up
  425. ;
  426.     MOV    B,A    ;SAVE LENGTH
  427.     DCR    B    ;JUST A SPACE?
  428.     JRZ    PRMPTR    ;GOTO COMMAND PROCESSOR IF SO
  429.     LXI    D,INBUF    ;PT TO INLINE BUFFER
  430.     INX    H    ;SKIP LEN
  431.     INX    H    ;SKIP ' '
  432.     MOV    A,M    ;GET FIRST CHAR
  433.     CPI    '/'    ;IF SLASH, PRINT INITIAL HELP (TOOLSET CONVENTION)
  434.     JZ    IHELP    ;PRINT INITIAL HELP INFO
  435.     CALL    MOVE    ;COPY INPUT LINE INTO INLINE BUFFER
  436.     MVI    A,CR    ;STORE ENDING <CR>
  437.     STAX    D
  438.     LXI    H,INBUF    ;PT TO FIRST BYTE OF INLINE BUFFER
  439.     JR    PRMPTI    ;PROCESS AS THOUGH IT WAS TYPED
  440. ;
  441. ;Input Command Line From User at Console
  442. ;
  443. PRMPTR:
  444.     XRA    A    ;A=0
  445.     STA    IHFLG    ;Set No Initial Help
  446.     CALL    SINBUF    ;Save old INBUF into PINBUF
  447.     CALL    RDBUF    ;Read Input Line
  448.     CALL    EXMAC    ;Expand Macros
  449. ;
  450. ;Begin Processing Command Line in INBUF
  451. ;  At this point, HL points to next character to process
  452. ;
  453. PRMPTI:
  454.     MVI    A,0FFH    ;SET INFINITE LOOP COUNT
  455.     STA    TOGO    ;LOOP COUNT FOR MULTIPLE LOOPS
  456.     STA    TOGO+1
  457. ;
  458. ;Minor Command Loop; This is the entry point for each individual command in
  459. ;  a Command Line; Commands may be separated by semicolons in this manner
  460. ;
  461. PROMPT    EQU    $
  462. SETSTK:
  463.     LXI    SP,DUTSTK    ;RESET STACK
  464.     XRA    A    ;ZERO 2-UP PRINT FOR DUAL-COLUMN PRINT
  465.     STA    TWOUP    ;..SWITCH
  466.     MVI    A,1
  467.     STA    FTSW    ;TELL SEARCH NOT TO INCR
  468.     PUSH    H
  469.     LXI    H,TBUFF    ;SET NO-READ INPUT BUFFER ADDRESS
  470.     SHLD    BUFAD    ;FOR RDBYTE
  471.     POP    H
  472.     CALL    CTLCS    ;ABORT?
  473.     JRZ    PRMPTR    ;..YES, READ BUFFER
  474. ;
  475. ;Do we have to position in directory after find?
  476. ;
  477.     LDA    FINDFL
  478.     ORA    A
  479.     JNZ    POSDIR    ;POSITION IN DIRECTORY
  480. ;
  481. ;Begin Command Evaluation -- Check for EOL and Capitalize
  482. ;
  483.     MOV    A,M    ;GET NEXT CHAR IN COMMAND LINE
  484.     INX    H    ;POINT TO FOLLOWING CHAR
  485.     CPI    CR    ;END OF LINE PHYSICALLY?
  486.     JRZ    PRMPTR    ;INPUT NEW COMMAND LINE IF SO
  487.     CPI    EOLCH    ;END OF LINE LOGICALLY?
  488.     JRZ    PROMPT    ;PROCESS NEXT ELEMENT IF SO
  489.     CALL    UPCASE    ;CAPITALIZE COMMAND
  490.     STA    DUMTYP    ;TYPE OF DUMP (A,D,H)
  491. ;
  492. ;Command dispatcher
  493. ;  If command not found, abort with error message
  494. ;  If command file, process command with HL pting to next command char and
  495. ;    A containing command letter
  496. ;
  497.     PUSH    H    ;SAVE HL
  498.     MOV    B,A    ;COMMAND IN B
  499.     LXI    H,CMDTBL    ;SCAN COMMAND TABLE FOR USER COMMAND
  500. CMDLP:
  501.     MOV    A,M    ;GET COMMAND
  502.     ORA    A    ;0=END OF TABLE
  503.     JZ    WHAT
  504.     CMP    B    ;COMPARE COMMAND
  505.     JRZ    CMDGO
  506.     INX    H    ;PT TO ADR
  507.     INX    H
  508.     INX    H    ;PT TO NEXT CMND
  509.     JR    CMDLP
  510. CMDGO:
  511.     INX    H    ;PT TO ADDRESS LOW
  512.     MOV    E,M
  513.     INX    H    ;PT TO ADDRESS HIGH
  514.     MOV    D,M
  515.     MOV    A,B    ;COMMAND BACK INTO A
  516.     POP    H    ;RESTORE HL
  517.     PUSH    D    ;PLACE ADDRESS ON STACK
  518.     RET        ;"RUN COMMAND"
  519. ;
  520. ;Macro Expansion Routine -- Expand Macros
  521. ;
  522. EXMAC:
  523.     LXI    H,INBUF    ;PT TO INPUT LINE
  524.     LXI    D,CTEMP    ;BUILD INTO TEMPORARY BUFFER
  525. EXMAC1:
  526.     MOV    A,M    ;GET CHAR
  527.     CPI    '0'    ;SKIP IF LESS THAN '0'
  528.     JRC    EXMAC2
  529.     CPI    '9'+1    ;CHECK FOR RANGE
  530.     JRNC    EXMAC2
  531.     INX    H    ;PT TO NEXT CHAR
  532.     PUSH    H    ;SAVE PTR TO NEXT CHAR IN LINE
  533.     SUI    '0'    ;CONVERT TO BINARY (0-9)
  534.     MOV    B,A    ;RESULT IN B
  535.     MVI    C,0
  536.     LXI    H,MTABL    ;PT TO BASE OF MACROS
  537.     DAD    B    ;PT TO MACRO
  538.     CALL    COPYM    ;COPY MACRO INTO LINE
  539.     DCX    D    ;BACK UP OVER <CR>
  540.     POP    H    ;GET PTR TO NEXT CHAR IN COMMAND LINE
  541. EXMAC2:
  542.     MOV    A,M    ;GET CHAR
  543.     STAX    D    ;PUT CHAR
  544.     INX    H    ;PT TO NEXT
  545.     INX    D
  546.     CALL    MTEST    ;TEST FOR END OF BUFFER
  547.     CPI    CR    ;DONE?
  548.     JRZ    EXMAC3
  549.     CPI    EOLCH    ;LOGICAL EOL?
  550.     JRNZ    EXMAC2
  551.     JR    EXMAC1    ;PROCESS NEXT COMMAND
  552. EXMAC3:
  553.     LXI    H,CTEMP    ;COPY COMMAND LINE BACK
  554.     LXI    D,INBUF    ;INTO INBUF
  555.     CALL    COPYCR    ;COPY TO <CR>
  556.     LXI    H,INBUF    ;PT TO INBUF
  557.     RET        ;EXPANSION COMPLETE
  558. ;
  559. ;Copy Macro Into Command Line Buffer
  560. ;
  561. COPYM:
  562.     MOV    A,M    ;GET CHAR
  563.     STAX    D    ;PUT CHAR
  564.     INX    H    ;PT TO NEXT
  565.     INX    D
  566.     CALL    MTEST    ;CHECK FOR LIMIT
  567.     CPI    CR    ;END OF MACRO?
  568.     JRNZ    COPYM
  569.     RET
  570. ;
  571. ;Test for Buffer Full
  572. ;
  573. MTEST:
  574.     PUSH    H    ;SAVE HL
  575.     PUSH    PSW    ;SAVE A
  576.     LXI    H,CTEMPX    ;CHECK FOR END OF BUFFER
  577.     MOV    A,H    ;GET PAGE
  578.     CMP    D    ;CHECK PAGE
  579.     JRZ    MACERR
  580.     POP    PSW    ;GET A
  581.     POP    H    ;GET HL
  582.     RET
  583. ;
  584. ;Macro Command Expansion Error
  585. ;
  586. MACERR:
  587.     CALL    ILPRT
  588.     DB    CR,LF,'Error -- Macro Expanded Command Line too Long',0
  589.     JMP    PRMPTR    ;NEW COMMAND
  590. ;
  591. ;Save INBUF into PINBUF for later processing by '@' command
  592. ;
  593. SINBUF:
  594.     LXI    H,INBUF        ;PT TO INBUF
  595.     LXI    D,PINBUF    ;PT TO PINBUF (PREVIOUS INBUF)
  596. ;
  597. ;Copy (HL) to (DE) until <CR> Encountered
  598. ;
  599. COPYCR:
  600.     MOV    A,M    ;GET CHAR
  601.     STAX    D    ;PUT CHAR
  602.     INX    H    ;PT TO NEXT
  603.     INX    D
  604.     CPI    CR    ;DONE?
  605.     JRNZ    COPYCR
  606.     RET
  607.  
  608. ;
  609. ;Command Not Found Error
  610. ;
  611. WHAT:
  612.     POP    H    ; RESTORE HL
  613.     CALL    ILPRT
  614.     DB    'Invalid Command at or after ',0
  615.     MOV    A,B    ;GET COMMAND LETTER
  616.     CALL    TYPE    ;PRINT IT
  617.     JMP    PRMPTR
  618. ;
  619. ;Memory full error
  620. ;
  621. MEMFUL:
  622.     CALL    ILPRT
  623.     DB    '+++ Out of memory +++'
  624.     DB    CR,LF,0
  625.     JMP    PRMPTR
  626. ;
  627. ;COMMAND:  @
  628. ;Repeat Previous Command Line
  629. ;
  630. PCMD:
  631.     MOV    A,M    ;GET NEXT CHAR
  632.     CPI    CR    ;SHOULD BE <CR>
  633.     JRZ    PCMD1
  634.     CALL    ILPRT
  635.     DB    CR,LF,'Warning:  Remainder of Command Line after "@" Deleted',0
  636. PCMD1:
  637.     CALL    ILPRT
  638.     DB    CR,LF,'Command --',CR,LF,0
  639.     LXI    H,PINBUF    ;GET PREVIOUS COMMAND
  640.     LXI    D,INBUF        ;COPY INTO INBUF
  641. PCMD2:
  642.     MOV    A,M    ;GET CHAR
  643.     STAX    D    ;PUT CHAR
  644.     INX    H    ;PT TO NEXT
  645.     INX    D
  646.     CPI    CR    ;END OF LINE?
  647.     PUSH    PSW    ;SAVE FLAG
  648.     CALL    TYPE    ;PRINT CHAR
  649.     POP    PSW    ;GET FLAG
  650.     JRNZ    PCMD2
  651.     MVI    A,LF    ;<LF>
  652.     CALL    TYPE
  653.     LXI    H,INBUF    ;RESTART COMMAND PROCESSING
  654.     JMP    PRMPTI    ;INCLUDE LOOP CAPABILITY
  655. ;
  656. ;COMMAND:  :
  657. ;Define or Print Macro
  658. ;:n<text> Defines Macro n, 0<=n<=9; ::n Prints Macro n, 0<=n<=9
  659. ;
  660. MAC:
  661.     MOV    A,M    ;GET NEXT CHAR
  662.     CALL    UPCASE    ;CAPITALIZE
  663.     CPI    'P'    ;PRINT MACRO?
  664.     JNZ    MACROD    ;IF NOT, DEFINE MACRO
  665.     INX    H    ;PT TO MACRO NUMBER
  666.     MOV    A,M    ;GET IT
  667.     CALL    UPCASE    ;CAPITALIZE
  668.     CPI    '@'    ;PRINT PREVIOUS COMMAND?
  669.     JRZ    PCPR
  670.     PUSH    PSW    ;SAVE A
  671.     CALL    ILPRT
  672.     DB    'Macro Definitions --',0
  673.     POP    PSW    ;GET A
  674.     CPI    'A'    ;PRINT ALL MACROS?
  675.     JRZ    AMACPR
  676.     CALL    MNUM    ;CHECK FOR VALID NUMBER AND RETURN # IN D
  677.     INX    H    ;PT TO CHAR AFTER MACRO NUMBER
  678.     CALL    MACPR    ;PRINT MACRO WHOSE NUMBER IS IN D
  679.     JMP    PROMPT
  680. ;
  681. ;Print Previous Command
  682. ;
  683. PCPR:
  684.     INX    H    ;PT TO CHAR AFTER '@'
  685.     LXI    D,PROMPT    ;SET UP RET ADR
  686.     PUSH    D    ;RETURN ADR ON STACK
  687.     PUSH    H    ;SAVE PTR
  688.     CALL    ILPRT
  689.     DB    'Previous Command Line Definition --'
  690.     DB    CR,LF,'@: ',0
  691.     LXI    H,PINBUF    ;PT TO PREVIOUS COMMAND
  692.     JMP    MPRINT        ;USE MACRO PRINT FACILITY
  693. ;
  694. ;Print All Macros
  695. ;
  696. AMACPR:
  697.     INX    H    ;PT TO CHAR AFTER 'A'
  698.     MVI    D,0    ;SET FOR FIRST MACRO
  699. AMPRL:
  700.     CALL    MACPR    ;PRINT MACRO WHOSE NUMBER IS IN D
  701.     INR    D    ;INCREMENT MACRO NUMBER
  702.     MOV    A,D    ;GET VALUE
  703.     CPI    10    ;DONE?
  704.     JRNZ    AMPRL
  705.     JMP    PROMPT    ;CONTINUE PROCESSING
  706. ;
  707. ;Print Macro Whose Number (0-9) is in D
  708. ;
  709. MACPR:
  710.     PUSH    H    ;SAVE PTR
  711.     CALL    ILPRT    ;PRINT HEADER
  712.     DB    CR,LF,0
  713.     MOV    A,D    ;GET NUMBER
  714.     ADI    '0'    ;CONVERT TO ASCII
  715.     CALL    TYPE    ;PRINT
  716.     CALL    ILPRT
  717.     DB    ': ',0
  718.     LXI    H,MTABL    ;PT TO TABLE OF MACROS
  719.     MVI    E,0    ;PAGE OFFSET OF ZERO; MACRO NUMBER ALREADY IN D
  720.     DAD    D    ;PT TO MACRO
  721. MPRINT:
  722.     MOV    A,M    ;GET CHAR
  723.     INX    H    ;PT TO NEXT
  724.     CPI    CR    ;END OF MACRO?
  725.     PUSH    PSW    ;SAVE FLAG
  726.     CALL    TYPE    ;PRINT CHAR
  727.     POP    PSW    ;GET FLAG
  728.     JRNZ    MPRINT
  729.     MVI    A,LF    ;<LF>
  730.     CALL    TYPE
  731.     POP    H    ;GET PTR TO NEXT CHAR
  732.     RET
  733. ;
  734. ;Check char in A for valid Macro Number (0-9), print error message if
  735. ; not, return number in D if so
  736. ;
  737. MNUM:
  738.     SUI    '0'    ;CONVERT TO 0-9
  739.     JRC    MNERR    ;ERROR IF LESS
  740.     CPI    10    ;RANGE?
  741.     JRNC    MNERR
  742.     MOV    D,A    ;RESULT IN D
  743.     RET
  744. MNERR:
  745.     CALL    ILPRT
  746.     DB    CR,LF,'Invalid Macro Number Specified in Command',0
  747.     JMP    PRMPTR    ;NEW COMMAND
  748. ;
  749. ;Define Macro
  750. ;
  751. MACROD:
  752.     CALL    MNUM    ;CHECK NUMBER AND RETURN IN D
  753.     INX    H    ;PT TO CHAR AFTER MACRO NUMBER
  754.     PUSH    H    ;SAVE PTR
  755.     LXI    H,MTABL    ;PT TO MACRO TABLE
  756.     MVI    E,0    ;SET EVEN PAGE
  757.     DAD    D    ;PT TO MACRO ENTRY IN HL
  758.     XCHG        ;... IN DE
  759.     POP    H    ;PT TO MACRO TEXT
  760.     CALL    COPYCR    ;COPY TO <CR>
  761.     JMP    PRMPTR    ;NEW COMMAND
  762. ;
  763. ;COMMAND:  !
  764. ;Delay for user input
  765. ;
  766. UWAIT:
  767.     CALL    WAIT    ; USE WAIT ROUTINE
  768.     JMP    PROMPT
  769. ;
  770. ;COMMAND:  #
  771. ;Print disk statistics
  772. ;
  773. STATS:
  774.     PUSH    H    ;SAVE POINTER TO NEXT COMMAND
  775.     CALL    ILPRT
  776.     DB    '+=============================+',CR,LF
  777.     DB    '|    -- Queue Information --  |',CR,LF
  778.     DB    '+-----------------------------+',CR,LF
  779.     DB    0
  780.     CALL    QSTATS    ;PRINT STATUS INFO
  781.     CALL    ILPRT
  782.     DB    CR,LF,CR,LF
  783.     DB    '+=============================+',CR,LF
  784.     DB    '|    -- Disk Information --   |',CR,LF
  785.     DB    '+-----------------------------+',CR,LF
  786.     DB    CR,LF,'Disk Drive:        ',0
  787.     LDA    DRIVE
  788.     ADI    'A'    ;CONVERT TO ASCII
  789.     CALL    TYPE    ;PRINT DRIVE LETTER
  790.     CALL    ILPRT
  791.     DB    CR,LF,'Tracks:            ',0
  792.     LHLD    MAXTRK    ;PRINT NUMBER OF TRACKS
  793.     INX    H
  794.     CALL    DEC
  795.     CALL    ILPRT
  796.     DB    CR,LF,'Sectors/Track:        ',0
  797.     LHLD    SPT    ;PRINT NUMBER OF SECTORS/TRACK
  798.     CALL    DEC
  799.     CALL    ILPRT
  800.     DB    CR,LF,'Group Size:        ',0
  801.     LDA    BLM    ;PRINT SIZE OF A GROUP
  802.     INR    A
  803.     MOV    L,A
  804.     MVI    H,0
  805.     CALL    DEC
  806.     CALL    ILPRT
  807.     DB    ' Blocks/Group'
  808.     DB    CR,LF,'Total Groups:        ',0
  809.     LHLD    DSM    ;PRINT TOTAL NUMBER OF GROUPS ON A DISK
  810.     CALL    DEC
  811.     CALL    ILPRT
  812.     DB    CR,LF,'Directory Entries:    ',0
  813.     LHLD    DRM    ;PRINT NUMBER OF DIRECTORY ENTRIES
  814.     INX    H
  815.     CALL    DEC
  816.     CALL    ILPRT
  817.     DB    CR,LF,'System Tracks:        ',0
  818.     LHLD    SYSTRK    ;PRINT NUMBER OF SYSTEM TRACKS
  819.     CALL    DEC
  820.     CALL    ILPRT
  821.     DB    CR,LF
  822.     DB    '===============================',CR,LF,0
  823.     POP    H    ;RESTORE POINTER TO NEXT COMMAND
  824.     JMP    PROMPT
  825. ;
  826. ;COMMAND:  N
  827. ;The following command resets the disk
  828. ;system thru CP/M, and may be usable for
  829. ;changing the disk density or format.
  830. ;This can only be done if your BIOS resets
  831. ;the auto-density select parameters at
  832. ;every track-zero access.
  833. ;
  834. NEWDSK:
  835.     PUSH    H    ;SAVE POINTER TO NEXT LETTER
  836.     MVI    C,RESETDK    ;BDOS RESET DISK FUNCTION
  837.     CALL    BDOS
  838.     LDA    DRIVE    ;RESELECT CURRENT DRIVE
  839.     MOV    C,A
  840.     POP    H
  841.     CALL    SELECT
  842.     JMP    PROMPT
  843. ;
  844. ;COMMAND:  Q
  845. ;Queue Control
  846. ;
  847. QUEUER:
  848.     MOV    A,M    ;GET 2ND ARGUMENT
  849.     CALL    UPCASE    ;CAPITALIZE
  850.     CPI    EOLCH    ;END OF LINE?
  851.     JRZ    QSTAT    ;STATUS REPORT
  852.     CPI    CR    ;END OF LINE?
  853.     JRZ    QSTAT
  854.     INX    H    ;PT TO AFTER KEY CHAR
  855.     PUSH    H    ;SAVE PTR
  856.     CPI    'Z'    ;ZERO QUEUE?
  857.     JRZ    QZERO
  858.     CPI    'S'    ;SAVE QUEUE?
  859.     JZ    QFSAVE
  860.     POP    H    ;GET PTR
  861.     CALL    ILPRT
  862.     DB    'Invalid Queue Command',CR,LF,0
  863.     JMP    PRMPTR    ;ABORT LINE ON ERROR
  864. ;
  865. ;  Zero the Queue
  866. ;
  867. QZERO:
  868.     LXI    H,DIRECT    ;ZERO QUEUE
  869.     SHLD    QNXT    ;SET NEXT
  870.     SHLD    QLST    ;SET LAST
  871.     LXI    H,0    ;ZERO COUNT
  872.     SHLD    QCNT
  873.     POP    H    ;GET PTR AND FALL THRU TO QSTAT
  874. ;
  875. ;  Print Status of Queue
  876. ;
  877. QSTAT:
  878.     PUSH    H    ;SAVE PTR TO NEXT CHAR
  879.     CALL    ILPRT
  880.     DB    '** Queue Status Summary **',CR,LF,0
  881.     CALL    QSTATS    ;PRINT STATUS
  882.     POP    H    ;RESTORE PTR
  883.     JMP    PROMPT
  884. QSTATS:
  885.     LHLD    QCNT    ;GET SIZE OF QUEUE
  886.     CALL    PRQCNT    ;PRINT DATA
  887.     CALL    PRQSPAC    ;PRINT SPACE AVAILABLE INFO
  888.     CALL    ILPRT
  889.     DB    'Address of Head of Queue: ',0
  890.     LHLD    QNXT    ;PRINT ADDRESS OF HEAD OF QUEUE
  891.     MOV    B,H    ;... ADDRESS IN BC
  892.     MOV    C,L
  893.     CALL    HEXB    ;PRINT IN HEX
  894.     CALL    ILPRT
  895.     DB    ' Hex',CR,LF
  896.     DB    'Address of Tail of Queue: ',0
  897.     LHLD    QLST    ;PRINT ADDRESS OF TAIL OF QUEUE
  898.     MOV    B,H
  899.     MOV    C,L
  900.     CALL    HEXB
  901.     CALL    ILPRT
  902.     DB    ' Hex',CR,LF,0
  903.     RET
  904. ;
  905. ;  Print Amount of Space Left in Queue
  906. ;
  907. PRQSPAC:
  908.     LXI    B,-1    ;SET COUNT
  909.     LHLD    QLST    ;GET PTR TO QUEUE TAIL
  910. QSTAT1:
  911.     INX    B    ;INCREMENT COUNT
  912.     LXI    D,80H    ;PT TO NEXT QUEUE ELEMENT
  913.     DAD    D
  914.     XCHG        ;WRAP AROUND
  915.     CALL    QWRAP
  916.     LHLD    QNXT    ;GET PTR TO FIRST ELEMENT
  917.     XCHG
  918.     MOV    A,H    ;COMPARE
  919.     CMP    D
  920.     JRNZ    QSTAT1
  921.     MOV    A,L
  922.     CMP    E
  923.     JRNZ    QSTAT1
  924.     MOV    H,B    ;HL=BLOCK COUNT
  925.     MOV    L,C
  926.     CALL    DEC    ;PRINT AS DECIMAL
  927.     CALL    ILPRT
  928.     DB    ' Blocks Left in Queue',CR,LF,0
  929.     RET
  930. ;
  931. ;  Save Queue as a File
  932. ;
  933. QFSAVE:
  934.     MOV    A,M    ;GET FIRST CHAR OF FILE NAME
  935.     CPI    EOLCH    ;EOL?
  936.     JZ    WHAT
  937.     CPI    CR    ;EOL?
  938.     JZ    WHAT
  939.     LXI    D,FCB    ;START TO FILL FCB
  940.     XRA    A    ;A=0
  941.     STAX    D    ;SELECT DEFAULT DRIVE
  942.     INX    D    ;PT TO FILE NAME
  943.     MVI    B,8    ;SAVE FILE NAME
  944.     CALL    MVNAME
  945.     MVI    B,3    ;SAVE FILE TYPE
  946.     CALL    MVNAME
  947.     PUSH    H    ;SAVE PTR TO NEXT CHAR
  948.     LHLD    QCNT    ;ANY ELEMENTS IN QUEUE?
  949.     MOV    A,H
  950.     ORA    L
  951.     JZ    QEMPTY
  952.     PUSH    H    ;SAVE QUEUE COUNT
  953.     CALL    NORITE    ;CAN'T WRITE NOW
  954.     LXI    D,FCB    ;PT TO FCB
  955.     CALL    FCBINIT    ;INIT FCB
  956.     MVI    C,DELF    ;DELETE FILE
  957.     PUSH    D    ;SAVE DE
  958.     CALL    BDOS
  959.     POP    D
  960.     CALL    FCBINIT    ;INIT FCB AGAIN
  961.     MVI    C,MAKEF    ;CREATE FILE
  962.     CALL    BDOS
  963.     POP    B    ;GET QUEUE COUNT IN BC
  964.     LHLD    QNXT    ;PT TO NEXT BLOCK IN QUEUE
  965. QFS1:
  966.     PUSH    B    ;SAVE COUNT
  967.     LXI    D,TBUFF    ;COPY INTO TBUFF
  968.     MVI    B,128    ;128 BYTES
  969.     CALL    MOVE
  970.     XCHG        ;PT TO NEXT QUEUE BLOCK IN DE
  971.     CALL    QWRAP    ;WRAP AROUND
  972.     PUSH    D    ;SAVE PTRS
  973.     LXI    D,FCB    ;PT TO FCB
  974.     MVI    C,WRITEF    ;WRITE BLOCK TO FILE
  975.     CALL    BDOS
  976.     POP    H    ;GET PTR TO NEXT BLOCK
  977.     POP    B    ;GET COUNT
  978.     DCX    B    ;COUNT DOWN
  979.     MOV    A,B    ;DONE?
  980.     ORA    C
  981.     JRNZ    QFS1
  982.     LXI    D,FCB    ;CLOSE FILE
  983.     MVI    C,CLOSEF
  984.     CALL    BDOS
  985.     CALL    ILPRT
  986.     DB    'Queue Saved in File',CR,LF,0
  987.     POP    H    ;PT TO NEXT CHAR
  988.     JMP    PROMPT
  989. FCBINIT:
  990.     PUSH    D    ;SAVE PTR
  991.     LXI    H,12    ;SKIP TO EX FIELD
  992.     DAD    D
  993.     MVI    B,24    ;ZERO 36 BYTES
  994.     XRA    A    ;A=0
  995. FCBIN1:
  996.     MOV    M,A    ;STORE ZEROES
  997.     INX    H
  998.     DJNZ    FCBIN1
  999.     POP    D    ;RESTORE PTR
  1000.     RET
  1001. ;
  1002. ;COMMAND:  *
  1003. ;Repeat buffer contents
  1004. ;
  1005. REPEAT:
  1006.     CALL    DECIN    ;NN SPECIFIED?
  1007.     MOV    A,D
  1008.     ORA    E
  1009.     JRZ    NNN    ;NO -- SET FOR INFINITE LOOP OR SIMPLE REPEAT
  1010.     LHLD    TOGO    ;LOAD LOOP FLAG
  1011.     INX    H    ;TEST FOR FIRST TIME
  1012.     MOV    A,H
  1013.     ORA    L    ;WAS IT 0FFFFH?; IF SO, WE HAVE NEW VALUE
  1014.     JRNZ    NNN    ;NO: COUNTING
  1015.     XCHG        ;GET COUNT
  1016.     SHLD    TOGO    ;SET COUNT
  1017. ;
  1018. NNN:
  1019.     LHLD    TOGO    ;GET CURRENT COUNT
  1020.     XCHG        ;DE=CURRENT COUNT, HL=COUNT LIMIT
  1021.     LXI    H,INBUF    ;PT TO FIRST CHAR FOR REPEAT
  1022.     INX    D    ;TEST FOR 0FFFFH
  1023.     MOV    A,D    ;IF 0FFFFH, INX D MADE DE=0
  1024.     ORA    E
  1025.     JZ    PROMPT    ;CONTINOUS LOOP IF 0FFFFH
  1026.     DCX    D    ;COUNT DOWN
  1027.     DCX    D    ;MAKE UP FOR PREV INX D
  1028.     XCHG
  1029.     SHLD    TOGO    ;SET NEW COUNT (1 LESS THAN BEFORE)
  1030.     MOV    A,H    ;ALL DONE?
  1031.     ORA    L
  1032.     XCHG        ;GET BACK INBUF PTR IN HL
  1033.     JNZ    PROMPT    ;KEEP GOING IF NOT YET ZERO
  1034.     JMP    PRMPTR    ;ALL DONE
  1035. ;
  1036. ;COMMAND:  U
  1037. ;Set CP/M 2.x user number
  1038. ;
  1039. USER:
  1040.     CALL    DECIN    ;GET REQUESTED USER NO.
  1041.     LDA    MUSER    ;GET MAX USER
  1042.     MOV    B,A    ;... IN B
  1043.     MOV    A,E
  1044.     CMP    B    ;VALID?
  1045.     JNC    USRERR
  1046.     MOV    A,D    ;HIGH-ORDER BYTE MUST BE ZERO FOR VALID NUMBER
  1047.     ORA    A
  1048.     JNZ    USRERR
  1049.     MOV    A,E    ;SAVE USER NUMBER
  1050.     STA    UNUM
  1051.     MVI    C,SUSER    ;SET USER NUMBER
  1052.     PUSH    H        ;SAVE CHAR POINTER
  1053.     CALL    BDOS        ;SET USER NO.
  1054.     POP    H
  1055.     JMP    PROMPT
  1056. USRERR:
  1057.     CALL    ILPRT
  1058.     DB    'User Number Out of Range',CR,LF,0
  1059.     JMP    PRMPTR
  1060. ;
  1061. ;COMMAND:  P
  1062. ;Toggle print flag
  1063. ;
  1064. PRNTFF:
  1065.     LDA    PFLAG    ;TOGGLE PRINT FLAG
  1066.     XRI    1
  1067.     STA    PFLAG
  1068.     JMP    PROMPT
  1069. ;
  1070. ;COMMAND:  Z
  1071. ;Sleep routine, in seconds
  1072. ;
  1073. SLEEP:
  1074.     CALL    DECIN    ;GET COUNT IF ANY
  1075.     MOV    A,E    ;ANY?
  1076.     ORA    A
  1077.     JRNZ    SLEPLP
  1078.     MVI    E,1    ; 1 SEC DEFAULT
  1079. ;
  1080. SLEPLP:
  1081.     LDA    CLOCK    ; GET CLOCK SPEED
  1082.     MOV    D,A
  1083. ;
  1084. SLEEP1:
  1085.     LXI    B,41700    ; APPROX 1 SEC @ 1MHz
  1086. ;
  1087. SLEEP2:
  1088.     DCX    B    ;COUNT DOWN FOR 1 MHz [5 CYCLES]
  1089.     MOV    A,B    ;[5 CYCLES] <-- TOTAL TIME: 24 CYCLES
  1090.     ORA    C    ;[4 CYCLES] <-- (24 MU-SECS AT 1MHz)
  1091.     JNZ    SLEEP2    ;[10 CYCLES]
  1092.     PUSH    D
  1093.     CALL    CTLCS    ;ABORT?
  1094.     POP    D
  1095.     JZ    PRMPTR
  1096.     DCR    D    ;COUNT DOWN FOR CLOCK SPEED
  1097.     JNZ    SLEEP1
  1098.     DCR    E    ;COUNT DOWN NUMBER OF REQUESTED SECONDS
  1099.     JNZ    SLEPLP
  1100.     JMP    PROMPT
  1101. ;
  1102. ;Check for control-C or S
  1103. ;
  1104. CTLCS:
  1105.     CALL    CONST    ;CHAR AVAILABLE?
  1106.     ORA    A
  1107.     JRNZ    GETC
  1108.     ORI    1    ;NO CHAR, RETURN NZ
  1109.     RET
  1110. ;
  1111. GETC:    CALL    CONIN    ;INPUT CHAR
  1112.     ANI    1FH    ;ALLOW ASCII
  1113.     CPI    'S'-40H    ;WAIT FOR NEXT CHAR IF ^S OR S OR s
  1114.     CZ    CONIN
  1115.     CPI    'C'-40H    ;CHECK FOR ^C OR C OR c
  1116.     RET        ;0 SET IF CTL-C
  1117. ;
  1118. ;Initialize Memory Buffers
  1119. ;
  1120. INITP:
  1121.     XRA    A    ;A=0
  1122.     STA    HEXAD    ;CLEAR ADDRESS
  1123.     STA    HEXAD+1
  1124.     STA    PFLAG    ;SET NO PRINT
  1125.     STA    SAVEFL    ;SET NO SAVE DONE
  1126.     STA    WRFLG    ;MAY NOT WRITE
  1127.     STA    DIRPOS    ;SET NO DIRECTORY POSITION
  1128.     STA    FINDFL    ;SET NO POSITION
  1129.     INR    A    ;A=1
  1130.     STA    FTSW    ;SET SEARCH WITHOUT INCREMENT
  1131.     STA    NOTPOS    ;NOT POSITIONED
  1132.     LXI    H,0    ;HL=0
  1133.     SHLD    QCNT    ;SET NO ELEMENTS IN QUEUE
  1134.     SHLD    MFPTR    ;SET NO MULTI FILE PTR
  1135.     SHLD    CURTRK    ;SET TRACK 0
  1136.     INX    H    ;HL=1
  1137.     SHLD    CURSEC    ;SET LOGICAL SECTOR 1
  1138.     SHLD    PHYSEC    ;SET PHYSICAL SECTOR 1
  1139.     MVI    A,CR    ;CLEAR PREVIOUS COMMAND
  1140.     STA    PINBUF    ;SET PREVIOUS COMMAND TO NIL
  1141.     LXI    H,DIRECT    ;SET FIRST AND LAST QUEUE ELEMENT PTRS
  1142.     SHLD    QNXT
  1143.     SHLD    QLST
  1144.     LXI    H,MTABL    ;CLEAR MACRO TABLE
  1145.     MVI    B,10    ;10 ENTRIES
  1146. INITP1:
  1147.     MVI    M,CR    ;STORE <CR>
  1148.     INR    H    ;PT TO NEXT PAGE
  1149.     DJNZ    INITP1
  1150.     RET
  1151. ;
  1152. ;Set up flags, etc, at initialization
  1153. ;Find our way at initialization
  1154. ;
  1155. GETSTP:
  1156.     MVI    A,CR    ;INITIALIZE INPUT BUFFER
  1157.     STA    INBUF    ;EMPTY BUFFER
  1158.     MVI    C,SUSER    ;GET USER NUMBER
  1159.     MVI    E,0FFH    ;GET USER
  1160.     CALL    BDOS
  1161.     STA    UNUM    ;SET USER NUMBER
  1162.     MVI    C,GETDSK
  1163.     CALL    BDOS    ;GET CURRENT DISK
  1164.     MOV    C,A    ;WE HAVE TO SELECT
  1165.     JMP    SELECT    ;TO GET THE DPH
  1166. ;
  1167. ;COMMAND:  L
  1168. ;Log in the selected disk
  1169. ;
  1170. LOGIN:
  1171.     CALL    DOLOG
  1172.     JMP    PROMPT
  1173. ;
  1174. DOLOG:
  1175.     MOV    A,M    ;DISK REQUESTED?
  1176.     LXI    D,0
  1177.     CPI    CR    ;NO REQUEST OF PHYSICAL EOL
  1178.     JRZ    LGNODK
  1179.     CPI    EOLCH    ;NO REQUEST IF LOGICAL EOL
  1180.     JRZ    LGNODK
  1181.     CALL    UPCASE    ;CAPITALIZE
  1182.     INX    H    ;POINT TO NEXT CHAR
  1183.     SUI    'A'    ;CONVERT TO 0-15
  1184.     MOV    C,A    ;DISK NUMBER IN C
  1185.     LDA    MDISK    ;GET MAX DISK
  1186.     MOV    B,A    ;... IN B
  1187.     MOV    A,C
  1188.     CMP    B
  1189.     JRC    SELECT
  1190.     CALL    ILPRT
  1191.     DB    'Disk Letter Out of Range',CR,LF,0
  1192.     JMP    PRMPTR
  1193. ;
  1194. ;Select Disk Whose Number is in C (A=0, B=1, etc)
  1195. ;
  1196. SELECT:
  1197.     PUSH    H    ;SAVE PTR TO NEXT COMMAND LETTER
  1198.     MOV    A,C
  1199.     STA    DRIVE    ;REMEMBER LATER WHERE WE ARE
  1200. ;
  1201. VSELDK: CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  1202.     MOV    A,H
  1203.     ORA    L
  1204.     JZ    WHAT    ;SELECT ERROR
  1205.     MOV    E,M    ;GET THE SECTOR TABLE PNTR
  1206.     INX    H
  1207.     MOV    D,M
  1208.     INX    H
  1209.     XCHG
  1210.     SHLD    SECTBL    ;SET THE SECTOR TABLE PTR
  1211.     LXI    H,8    ;OFFSET TO DPBPTR
  1212.     DAD    D
  1213.     MOV    A,M    ;PICK UP DPB POINTER
  1214.     INX    H    ;  TO USE
  1215.     MOV    H,M    ;  AS PARAMETER
  1216.     MOV    L,A    ;  TO LOGIT
  1217.     CALL    LOGIT
  1218.     LHLD    SYSTRK    ;RESET TRACK AND SECTOR
  1219.     XCHG        ;  TO DIRECTORY
  1220.     CALL    SETTRK    ;  ON EVERY
  1221.     LXI    D,1    ;  LOGIN
  1222.     CALL    SETSEC    ;  CHANGE
  1223.     LHLD    PHYSEC    ;THIS LOGIC WILL TELL
  1224.     MOV    A,H    ;  IF FIRST SEC
  1225.     ORA    L    ;  IS PHYSICAL 0
  1226.     STA    FIRST0
  1227.     CALL    CLCSUB    ;CALCULATE WHAT GROUP/GRPDISP WE ARE IN
  1228.     POP    H    ;GET PTR TO NEXT LETTER
  1229. ;
  1230. LGNODK:
  1231.     CALL    NORITE    ;SET NO DISK I/O DONE (NO POSITION)
  1232.     RET
  1233. ;
  1234. ;Read in the disk directory
  1235. ;
  1236. REDDIR:
  1237.     PUSH    H    ;SAVE PTR TO NEXT LETTER
  1238.     CALL    NORITE    ;POSITIONING LOST
  1239.     LHLD    SYSTRK    ;SAVE CURRENT TRACK
  1240.     SHLD    CURTRK
  1241.     LXI    H,1    ;SET SECTOR 1
  1242.     SHLD    CURSEC
  1243.     LHLD    DRM    ;GET DIR SIZE FROM DPB
  1244.     INX    H    ;MAKE 1-RELATIVE
  1245.     CALL    ROTRHL
  1246.     CALL    ROTRHL    ;DIVIDE BY 4 (4 NAMES/SECTOR)
  1247.     MOV    B,H    ;BC=NUMBER OF BLOCKS TO READ
  1248.     MOV    C,L
  1249.     LXI    D,DIRECT    ;DMA ADDR
  1250. ;
  1251. ;Read Disk Directory Loop
  1252. ;
  1253. RDIRLP:
  1254.     PUSH    B    ;SAVE REGS
  1255.     PUSH    D
  1256.     MOV    B,D    ;BC=DMA ADDRESS
  1257.     MOV    C,E
  1258.     LDA    BDOS+2    ;CHECK MEM AVAIL
  1259.     DCR    A    ;ARE WE RNNING INTO BDOS?
  1260.     CMP    D
  1261.     JC    MEMFUL    ;MEMORY FULL ERROR IF SO
  1262.     CALL    SETDMA    ;SET DMA ADDRESS TO THAT IN BC
  1263.     LHLD    CURTRK    ;SET TRACK
  1264.     XCHG
  1265.     CALL    SETTRK
  1266.     LHLD    CURSEC    ;SET SECTOR
  1267.     XCHG
  1268.     CALL    SETSEC
  1269.     CALL    READ    ;READ DIRECTORY BLOCK
  1270.     CALL    NXTSEC    ;INCREMENT TO NEXT SECTOR
  1271.     POP    D
  1272.     POP    B
  1273.     LXI    H,80H    ;ADVANCE TO NEXT DMA ADDRESS
  1274.     DAD    D
  1275.     XCHG        ;DE=NEXT DMA ADDRESS
  1276.     DCX    B    ;COUNT DOWN DIRECTORY BLOCKS
  1277.     MOV    A,B
  1278.     ORA    C
  1279.     JRNZ    RDIRLP
  1280.     LXI    B,TBUFF    ;RESET DMA ADDRESS TO TBUFF
  1281.     CALL    SETDMA
  1282.     POP    H    ;GET PTR TO NEXT CHAR
  1283.     RET
  1284. ;
  1285. ;COMMAND:  M
  1286. ;Map the directory
  1287. ;
  1288. MAP:
  1289.     PUSH    H    ;SAVE PTR
  1290.     LHLD    QCNT    ;GET COUNT
  1291.     MOV    A,H
  1292.     ORA    L
  1293.     POP    H
  1294.     JZ    MAP1    ;PROCEED IF QUEUE EMPTY
  1295.     CALL    ILPRT    ;PRINT ABORT MESSAGE
  1296.     DB    CR,LF,'MAP not permitted -- Block Queue would be overlaid',0
  1297.     JMP    PRMPTR
  1298. MAP1:
  1299.     CALL    PAGSET    ;SET PAGING COUNTER
  1300.     XRA    A
  1301.     STA    ONLY1    ;SET FLAG FOR ALL GROUPS (NOT ONLY 1)
  1302.     CALL    REDDIR    ;READ IN DIRECTORY
  1303.     MVI    C,0    ;INIT START GRP #
  1304.     LDA    AL0    ;READ DIR GRP BITS
  1305.     CALL    COLECT    ;COLLECT COUNT OF DIR GRPS..
  1306.     LDA    AL1    ;..IN REGISTER C
  1307.     CALL    COLECT
  1308.     MVI    B,0    ;BC NOW HAS A DEFAULT START GRP #
  1309.     CALL    HEXIN    ;GET SPECIFIED GROUP IF ANY
  1310.     PUSH    H    ;SAVE INBUF PTR
  1311.     MOV    A,E    ;GET START
  1312.     ORA    D    ;NOTHING?
  1313.     JRZ    MAPDF    ;..YES, DFLT
  1314.     MVI    A,0FFH    ;SET FLAG FOR ONLY 1 GROUP
  1315.     STA    ONLY1
  1316.     MOV    B,D    ;GET VALUE IN BC
  1317.     MOV    C,E
  1318. ;
  1319. MAPDF:
  1320.     CALL    HEXB    ;PRINT FIRST GROUP NUMBER
  1321.     MVI    A,'-'    ;PRINT SEPARATOR
  1322.     CALL    TYPE
  1323.     MVI    A,' '    ;SET NO DUPLICATES
  1324.     STA    DUPFLG
  1325.     CALL    GETGRP    ;GET GRP(C) TO HL
  1326. ;
  1327. MAPCNT:
  1328.     INX    B    ;NEXT GRP #
  1329.     PUSH    H
  1330.     LHLD    DSM    ;GET HIGHEST GRP #
  1331.     INX    H    ;PLUS 1 FOR COMPARISON
  1332.     MOV    A,L    ;WHEN BC REACHES DSM+1..
  1333.     CMP    C    ;..THEN WE HAVE EXCEEDED..
  1334.     JRNZ    MAPC1    ;..THE DISK CAPACITY..
  1335.     MOV    A,H
  1336.     CMP    B
  1337. ;
  1338. MAPC1:
  1339.     POP    H
  1340.     JRZ    MAPEND    ;..AND WE ARE DONE
  1341.     PUSH    H
  1342.     CALL    GETGRP    ;GET ANOTHER
  1343.     POP    D    ;SEE IF SAME
  1344.     CALL    CTLCS    ;ABORT?
  1345.     JRZ    MAPND2
  1346.     MOV    A,D
  1347.     CMP    H
  1348.     JRNZ    MAPDIF
  1349.     MOV    A,E
  1350.     CMP    L
  1351.     JRZ    MAPCNT    ;SAME, CONTINUE
  1352. ;
  1353. ;Different file encountered
  1354. ;
  1355. MAPDIF:
  1356.     DCX    B
  1357.     CALL    HEXB    ;PRINT ENDING GROUP NUMBER
  1358.     INX    B
  1359.     XCHG
  1360.     CALL    MAPNAM    ;PRINT FILE NAME
  1361.     LDA    ONLY1    ;ONLY 1 NAME TO BE PRINTED?
  1362.     ORA    A    ;0=NO
  1363.     JRNZ    MAPND1
  1364.     JR    MAPDF
  1365. ;
  1366. ;End of map
  1367. ;
  1368. MAPEND:
  1369.     DCX    B    ;GET LAST
  1370.     CALL    HEXB    ;PRINT LAST GROUP NUMBER
  1371.     CALL    MAPNAM    ;PRINT FILE NAME
  1372.     CALL    WAIT    ;DELAY FOR USER
  1373. MAPND1:
  1374.     POP    H
  1375.     CALL    CRLF    ;NEW LINE
  1376. ;
  1377. ;End of map - reposition to previous group
  1378. ;
  1379. MAPND2:
  1380.     PUSH    H
  1381.     LHLD    GROUP    ;POINT TO GROUP IN DE
  1382.     XCHG
  1383.     JMP    POSGP2
  1384. ;
  1385. ;Print file name pointed to by HL
  1386. ;
  1387. MAPNAM:
  1388.     CALL    SPACE    ;LEADING SPACE
  1389.     MOV    A,H
  1390.     ORA    L    ;NONE?
  1391.     JZ    NONAME
  1392.     MOV    A,M    ;SEE IF ALLOC
  1393.     CPI    0E5H    ;FREE?
  1394.     MVI    A,' '    ;MARK ALLOCATED
  1395.     JRNZ    MPNSP1
  1396.     MVI    A,'('    ;MARK NOT ALLOCATED (ERASED FILE)
  1397. ;
  1398. MPNSP1:
  1399.     CALL    TYPE    ;PRINT ALLOCATION INDICATOR (SPACE OR '(')
  1400.     PUSH    H    ;SAVE POINTER
  1401.     MOV    A,M
  1402.     CALL    HEX    ;SHOW USER NUMBER
  1403.     CALL    SPACE
  1404.     INX    H    ;SKIP USER BYTE
  1405.     PUSH    B
  1406.     MVI    B,8    ;PRINT FILE NAME
  1407.     CALL    MAPN2
  1408.     MVI    A,'.'    ;PRINT DECIMAL SEPARATOR
  1409.     CALL    TYPE
  1410.     MVI    B,3    ;PRINT FILE TYPE
  1411.     CALL    MAPN2
  1412.     LDA    DUPFLG    ;DUPLICATE?
  1413.     CALL    TYPE    ;SPACE OR STAR
  1414.     POP    B
  1415.     MOV    A,M    ;GET EXT
  1416.     CALL    HEX    ;PRINT EXTENT NUMBER
  1417.     POP    H
  1418.     MOV    A,M
  1419.     CPI    0E5H    ;DELETED ENTRY?
  1420.     MVI    A,' '    ;PRINT ENDING SPACE
  1421.     JNZ    MPNSP2
  1422.     MVI    A,')'    ;PRINT ALLOCATION FLAG
  1423. ;
  1424. MPNSP2:
  1425.     CALL    TYPE    ;")" IF ERASED FILE OR SPACE IF NOT
  1426.     JR    FLIP
  1427. ;
  1428. NONAME:
  1429.     CALL    ILPRT
  1430.     DB    '    ++ Free ++      ',0
  1431. ;
  1432. FLIP:
  1433.     LDA    TWOUP    ;FLIP FLAG FOR TWO ENTRIES PER LINE
  1434.     XRI    1
  1435.     STA    TWOUP
  1436.     JZ    PAGER    ;NEW LINE WITH PAGING IF REQUIRED
  1437. ;
  1438. DELIM:
  1439.     MVI    A,':'    ;PRINT DELIMITER BETWEEN ADJACENT ENTRIES ON LINE
  1440.     CALL    TYPE
  1441.     JMP    SPACE
  1442. ;
  1443. ;Print name pted to by HL, length in B
  1444. ;
  1445. MAPN2:
  1446.     MOV    A,M
  1447.     ANI    7FH    ;STRIP POSSIBLE 2.x ATTRIBUTE BIT
  1448.     INX    H
  1449.     CPI    ' '    ;PRINTABLE?
  1450.     JRC    MAPN2H    ;..NO, IN HEX
  1451.     CPI    7EH    ;7E IS LEADIN ON SOME CRTS
  1452.     JRC    MAPN2A
  1453. ;
  1454. MAPN2H:
  1455.     CALL    BHEX    ;PRINT A AS HEX CHARS
  1456.     JMP    MAPN2Z
  1457. ;
  1458. MAPN2A:
  1459.     CALL    TYPE    ;PRINT AS CHAR
  1460. ;
  1461. MAPN2Z:
  1462.     DJNZ    MAPN2
  1463.     RET
  1464. ;
  1465. ;Find which file group (BC) belongs to
  1466. ;
  1467. GETGRP:
  1468.     LHLD    DRM    ;MAX DIR ENTRY #
  1469.     INX    H    ;MAKE 1-RELATIVE
  1470.     SHLD    FILECT
  1471.     LXI    H,0
  1472.     SHLD    MFPTR    ;SET MULTI-FILE (MORE THAN ONE USER) PTR
  1473.     LXI    H,DIRECT    ;PT TO DIRECTORY
  1474. ;
  1475. GETGLP:
  1476.     PUSH    H    ;SAVE POINTER TO NAME
  1477.     MOV    A,M    ;PICK UP DN BYTE
  1478.     CPI    0E5H    ;ERASED?
  1479.     JRZ    GETGNF
  1480.     LXI    D,14    ;NOW GET RECORD COUNT
  1481.     DAD    D    ;  S2 PORTION ..
  1482.     MOV    A,M    ;  IS 0 IN CP/M 1.4
  1483.     ANI    0FH
  1484.     MOV    E,A
  1485.     INX    H
  1486.     MOV    A,M
  1487.     ORA    E
  1488.     JZ    GETGNF
  1489.     MVI    E,16    ;FIRST SET FOR 8-BIT GRPS
  1490.     LDA    DSM+1
  1491.     ORA    A
  1492.     JRZ    SMALGP
  1493.     MVI    E,8    ;NOPE, BIG GROUPS
  1494. ;
  1495. SMALGP:
  1496.     MOV    D,A    ;SAVE GRP SIZE INDICATOR
  1497. ;
  1498. GETGL2:
  1499.     INX    H    ;POINTING INTO DM FIELD
  1500.     CALL    GRPCMP    ;COMPARE BC GP # AGAINST 1 DM FLD
  1501.     JRNZ    NOTGOT    ;JUMP IF NOT FOUND
  1502. ;
  1503. ;Found the file
  1504. ;
  1505.     PUSH    H    ;SAVE GROUP PTR
  1506.     LHLD    MFPTR
  1507.     MOV    A,H    ;ANY ENTRIES?
  1508.     ORA    L
  1509.     POP    H    ;GET PTR
  1510.     XTHL        ;SAVE ENTRY START AND SAVE PTR
  1511.     JRZ    MPFRST    ;IF ZERO, THEN FIRST ENTRY
  1512.     MVI    A,'*'    ;SET MULTI FLAG
  1513.     STA    DUPFLG
  1514. MPFRST:
  1515.     SHLD    MFPTR    ;SAVE POINTER
  1516.     XTHL        ;RESTORE ENTRY START AND GET PTR
  1517. NOTGOT:
  1518.     DCR    E    ;COUNT DOWN
  1519.     JRNZ    GETGL2    ;GO TEST SOME MORE
  1520. ;
  1521. GETGNF:
  1522.     POP    H    ;NOT THIS ONE
  1523.     LXI    D,32    ;SO GO TO NEXT
  1524.     DAD    D
  1525.     XCHG
  1526.     LHLD    FILECT    ;THERE IS LIMIT TO EVERYTHING
  1527.     DCX    H
  1528.     SHLD    FILECT
  1529.     MOV    A,H
  1530.     ORA    L
  1531.     XCHG        ;RE-ALIGN
  1532.     JRNZ    GETGLP
  1533. ;
  1534. ;Set the allocation address, if any
  1535. ;
  1536.     LHLD    MFPTR    ;GET ADDRESS
  1537.     RET
  1538. ;
  1539. ;COMMAND:  <
  1540. ;Save the current sector
  1541. ;    Special Form of <S saves current block onto queue
  1542. ;    Special Form of <G saves indicated group onto queue
  1543. ;
  1544. SAVE:
  1545.     LDA    WRFLG    ;READ DONE?
  1546.     ORA    A
  1547.     JZ    BADW    ;NONE TO SAVE
  1548.     MOV    A,M    ;CHECK FOR 'S'
  1549.     CALL    UPCASE    ;CAPITALIZE
  1550.     CPI    'B'    ;BLOCK SAVE
  1551.     JRZ    QSAV    ;SAVE ON STACK
  1552.     CPI    'G'    ;GROUP SAVE
  1553.     JZ    SAVEG
  1554.     PUSH    H
  1555.     LXI    H,TBUFF    ;COPY FROM TBUFF
  1556.     LXI    D,SAVBUF    ;INTO SAVBUF
  1557.     MVI    B,128    ;128 BYTES
  1558.     CALL    MOVE
  1559.     MVI    A,1    ;..SHOW
  1560.     STA    SAVEFL    ;..SAVED EXISTS
  1561.     POP    H    ;GET PTR TO NEXT CHAR
  1562.     JMP    PROMPT
  1563. ;
  1564. ;  Save Block on Queue
  1565. ;
  1566. QSAV:
  1567.     INX    H    ;SKIP OVER 2ND <
  1568.     PUSH    H    ;SAVE PTR TO NEXT CHAR
  1569.     LHLD    QLST    ;SEE IF ANOTHER SAVE WILL FILL QUEUE
  1570.     LXI    D,128    ;SET HL TO PT TO END OF NEXT SECTOR IN QUEUE
  1571.     DAD    D
  1572.     XCHG        ;DE PTS TO END OF NEXT BLOCK
  1573. QSAV0:
  1574.     LHLD    QNXT    ;SEE IF QUEUE IS FULL NOW
  1575.     MOV    A,H    ;MAY BE SAME
  1576.     CMP    D
  1577.     JRNZ    QSAV1
  1578.     MOV    A,L    ;MAY NOT BE SAME
  1579.     CMP    E
  1580.     JRZ    QSAV2    ;QUEUE IS FULL, SO ABORT
  1581. QSAV1:
  1582.     LHLD    QLST    ;GET PTR TO LAST QUEUE ELEMENT
  1583.     XCHG        ;... IN DE
  1584.     LXI    H,TBUFF    ;COPY FROM TBUFF
  1585.     MVI    B,128    ;128 BYTES
  1586.     CALL    MOVE
  1587.     CALL    QWRAP    ;CHECK FOR WRAP AROUND
  1588.     XCHG        ;HL PTS TO NEW LAST QUEUE POSITION
  1589.     SHLD    QLST    ;SAVE HL
  1590.     LHLD    QCNT    ;INCREMENT SECTOR COUNT
  1591.     INX    H
  1592.     SHLD    QCNT
  1593.     CALL    PRQCNT    ;PRINT QUEUE COUNT
  1594.     POP    H    ;PT TO NEXT CHAR
  1595.     JMP    PROMPT
  1596. QSAV2:
  1597.     CALL    ILPRT
  1598.     DB    'Block Queue is Full -- Block Not Saved',CR,LF,0
  1599.     LHLD    QCNT    ;GET COUNT
  1600.     CALL    PRQCNT    ;PRINT COUNT
  1601.     POP    H    ;PT TO NEXT CHAR
  1602.     JMP    PRMPTR
  1603. ;
  1604. ;  PRINT NUMBER OF ELEMENTS IN QUEUE
  1605. ;
  1606. PRQCNT:
  1607.     CALL    DEC    ;PRINT AS DECIMAL
  1608.     CALL    ILPRT
  1609.     DB    ' Blocks in Queue',CR,LF,0
  1610.     RET
  1611. ;
  1612. ;  CHECK TO SEE IF QUEUE ELEMENT PTED TO BY DE SHOULD BE WRAPPED AROUND
  1613. ;    ON EXIT, DE PTS TO QUEUE ELEMENT WITH WRAP AROUND
  1614. ;
  1615. QWRAP:
  1616.     LHLD    BDOS+1    ;CHECK FOR WRAP AROUND
  1617.     MOV    A,H
  1618.     SUI    10    ;BELOW CCP
  1619.     CMP    D    ;WRAP AROUND IF EQUAL
  1620.     RNZ
  1621.     LXI    D,DIRECT    ;NEXT ELEMENT IS HERE
  1622.     RET
  1623. ;
  1624. ;This routine is common to Save Group (RG) and Write Group (WG); it is used
  1625. ;  to extract the group number, check it, and position DU2 to it
  1626. ;  On exit, GROUP = Group Number, GRPDIS = 0, and DU2 is positioned
  1627. ;
  1628. COMG:
  1629.     INX    H    ;PT TO CHAR AFTER 'G' OF '<G' COMMAND
  1630.     PUSH    H    ;SAVE PTR TO NEXT CHAR
  1631.     MOV    A,M    ;GET CHAR AFTER 'G'
  1632.     LHLD    GROUP    ;GET CURRENT GROUP
  1633.     CALL    UPCASE    ;CAPITALIZE
  1634.     CPI    EOLCH    ;CURRENT IF LOGICAL EOL
  1635.     JRZ    COMG1
  1636.     CPI    CR    ;CURRENT IF PHYSICAL EOL
  1637.     JRZ    COMG1
  1638.     CALL    HEXIN    ;GET GROUP NUMBER IN HEX
  1639.     LHLD    DSM    ;CHECK FOR BOUNDS ERROR
  1640.     CALL    SUBDE    ;SUBTRACT GROUP NUMBER FROM DSM
  1641.     POP    H    ;RESTORE PTR
  1642.     JC    OUTLIM    ;LIMIT ERROR IF CARRY
  1643.     PUSH    H    ;SAVE PTR AGAIN
  1644.     XCHG        ;SAVE GROUP NUMBER
  1645.     SHLD    GROUP
  1646. COMG1:
  1647.     SHLD    TGRP    ;TEMPORARY GROUP NUMBER
  1648.     XCHG        ;GROUP NUMBER IN DE
  1649.     XRA    A    ;A=0
  1650.     STA    GRPDIS    ;SET GROUP DISPLACEMENT
  1651.     CALL    GTKSEC    ;CONVERT GROUP NUMBER TO TRACK AND SECTOR
  1652.     CALL    SETTRK    ;SET TRACK
  1653.     XCHG
  1654.     CALL    SETSEC    ;SET SECTOR
  1655.     POP    H    ;GET PTR TO NEXT CHAR
  1656.     RET
  1657. ;
  1658. ;This is the Save Group Routine; it copies the indicated group into the save
  1659. ;  buffer.
  1660. ;
  1661. SAVEG:
  1662.     CALL    COMG    ;EXTRACT COMMON GROUP INFO -- GROUP NUMBER AND POS
  1663.     PUSH    H
  1664.     CALL    ILPRT
  1665.     DB    'Reading from Group ',0
  1666.     LHLD    GROUP    ;GET CURRENT GROUP
  1667.     MOV    B,H    ;VALUE IN BC
  1668.     MOV    C,L
  1669.     CALL    HEXB    ;PRINT AS HEX
  1670.     CALL    ILPRT
  1671.     DB    CR,LF,0
  1672.     LHLD    QLST    ;LAST PTR USED FOR READ
  1673.     SHLD    QPTR
  1674.     POP    H
  1675.     MVI    A,0    ;SET COPY FUNCTION TO SAVE
  1676.     STA    CPYFCT    ;0=READ, 0FFH=WRITE
  1677. ;
  1678. ;Group Copy Routine -- if CPYFCT = 0, Read Group; if CPYFCT = 0FFH, Write Group
  1679. ;
  1680. COPYG:
  1681.     PUSH    H    ;SAVE PTR TO NEXT CHAR IN COMMAND LINE
  1682.     CALL    NORITE    ;POSITIONING LOST
  1683.     XCHG        ;SAVE HL
  1684.     LHLD    QPTR    ;PT TO NEXT QUEUE POSITION
  1685.     XCHG        ;... IN DE
  1686.     LDA    BLM    ;GET NUMBER OF BLOCKS/GROUP
  1687.     INR    A    ; ADD 1 TO BLM FOR CORRECT COUNT
  1688.     MOV    B,A    ;COUNT IN B
  1689. ;
  1690. COPYGL:
  1691.     PUSH    B    ;SAVE COUNT
  1692.     PUSH    D    ;SAVE PTR TO NEXT BLOCK TO LOAD
  1693.     MOV    B,D    ;SET BC=DE FOR SET DMA
  1694.     MOV    C,E
  1695.     CALL    SETDMA    ;SET ADDRESS TO LOAD
  1696.     LDA    CPYFCT    ;READ OR WRITE?
  1697.     ORA    A    ;0=READ
  1698.     JRNZ    COPYGLW
  1699.     CALL    READ    ;READ BLOCK
  1700.     LHLD    QCNT    ;INCREMENT QUEUE ELEMENT COUNT
  1701.     INX    H
  1702.     SHLD    QCNT
  1703.     JR    COPYGL0
  1704. COPYGLW:
  1705.     LHLD    QCNT    ;QUEUE EMPTY?
  1706.     MOV    A,H
  1707.     ORA    L
  1708.     JZ    QEMPTY
  1709.     CALL    PWRITE    ;WRITE BLOCK (NO CHECK)
  1710.     LHLD    QCNT    ;DECREMENT QUEUE ELEMENT COUNT
  1711.     DCX    H
  1712.     SHLD    QCNT
  1713. COPYGL0:
  1714.     CALL    NXTSEC    ;COMPUTE NEXT SECTOR ADDRESS
  1715.     LHLD    CURTRK    ;GET NEXT TRACK ADDRESS
  1716.     XCHG        ;... IN DE
  1717.     CALL    SETTRK    ;SET IT
  1718.     LHLD    CURSEC    ;GET NEXT SECTOR ADDRESS
  1719.     XCHG        ;... IN DE
  1720.     CALL    SETSEC    ;SET IT
  1721.     POP    D    ;GET PTR TO NEXT BLOCK
  1722.     POP    B    ;GET COUNTER
  1723.     LXI    H,80H    ;OFFSET TO NEXT BLOCK
  1724.     DAD    D
  1725.     SHLD    QPTR
  1726.     XCHG        ;DE PTS TO NEXT BLOCK
  1727.     CALL    QWRAP    ;ALLOW WRAP AROUND IN QUEUE
  1728.     LDA    CPYFCT    ;0=READ
  1729.     ORA    A    ;NO QUEUE OVERFLOW CHECK IF WRITE
  1730.     JRNZ    COPYGL1
  1731.     LHLD    QNXT    ;CHECK FOR QUEUE OVERFLOW
  1732.     MOV    A,H    ;MUST NOT BE EQUAL
  1733.     CMP    D
  1734.     JRNZ    COPYGL1
  1735.     MOV    A,L
  1736.     CMP    E
  1737.     JZ    QSAV2
  1738. COPYGL1:
  1739.     DJNZ    COPYGL    ;LOOP UNTIL FINISHED
  1740.     LHLD    QCNT    ;PRINT COUNT
  1741.     CALL    PRQCNT
  1742.     LHLD    QPTR    ;GET QUEUE PTR
  1743.     LDA    CPYFCT    ;RESET PROPER QUEUE PTR
  1744.     ORA    A    ;0=READ
  1745.     JRZ    COPYGL2
  1746.     SHLD    QNXT    ;NEXT PTR USED FOR WRITE
  1747.     JR    COPYGL3
  1748. COPYGL2:
  1749.     SHLD    QLST    ;LAST PTR USED FOR READ
  1750. COPYGL3:
  1751.     LXI    B,TBUFF    ;RESET DMA ADDRESS
  1752.     CALL    SETDMA
  1753.     XRA    A    ;A=0
  1754.     STA    WRFLG    ;SET NO READ DONE
  1755.     LHLD    TGRP    ;GET GROUP NUMBER
  1756.     XCHG        ;... IN DE
  1757.     POP    H    ;GET PTR TO NEXT CHAR
  1758.     JMP    POSGRP    ;POSITION TO GROUP IN DE AND CONTINUE PROCESSING
  1759. ;
  1760. ;COMMAND:  >
  1761. ;Restore the current sector
  1762. ;    Special Form >S gets next block from queue
  1763. ;    Special Form >G gets next group from queue
  1764. ;
  1765. RESTOR:
  1766.     MOV    A,M    ;CHECK FOR SPECIAL FORM
  1767.     CALL    UPCASE    ;CAPITALIZE
  1768.     CPI    'B'    ;BLOCK SAVE?
  1769.     JRZ    QRESTOR
  1770.     CPI    'G'    ;GROUP SAVE?
  1771.     JZ    RESTRG
  1772.     LDA    SAVEFL    ;SAVE DONE PREVIOUSLY?
  1773.     ORA    A
  1774.     JZ    NOSAVE    ;NONE TO SAVE
  1775.     PUSH    H
  1776.     LXI    H,SAVBUF    ;COPY FROM SAVBUF
  1777.     LXI    D,TBUFF    ;INTO TBUFF
  1778.     MVI    B,128    ;128 BYTES
  1779.     CALL    MOVE
  1780.     POP    H    ;GET PTR TO NEXT CHAR
  1781.     JMP    PROMPT
  1782. ;
  1783. ;  Restore Sector from Queue
  1784. ;
  1785. QRESTOR:
  1786.     INX    H    ;PT TO NEXT CHAR
  1787.     PUSH    H    ;SAVE PTR ON STACK
  1788.     LHLD    QCNT    ;GET ELEMENT COUNT
  1789.     MOV    A,H    ;EMPTY?
  1790.     ORA    L
  1791.     JRZ    QEMPTY    ;ABORT IF EMPTY
  1792.     DCX    H    ;COUNT DOWN
  1793.     SHLD    QCNT
  1794.     CALL    PRQCNT    ;PRINT COUNT
  1795.     LHLD    QNXT    ;PT TO NEXT ELEMENT IN QUEUE
  1796.     LXI    D,TBUFF    ;COPY INTO TBUFF
  1797.     MVI    B,128    ;128 BYTES
  1798.     CALL    MOVE
  1799.     XCHG        ;DE=PTR TO NEXT ELEMENT IN QUEUE
  1800.     CALL    QWRAP    ;CHECK FOR WRAP AROUND
  1801.     XCHG        ;HL PTS TO NEXT ELEMENT IN QUEUE
  1802.     SHLD    QNXT    ;SAVE PTR
  1803.     POP    H    ;RESTORE PTR
  1804.     JMP    PROMPT
  1805. QEMPTY:
  1806.     CALL    ILPRT
  1807.     DB    'Error -- Queue Empty',CR,LF,0
  1808.     POP    H    ;RESTORE NEXT CHAR PTR
  1809.     JMP    PRMPTR
  1810. ;
  1811. ;Write Group Loaded in GBUFF to Disk
  1812. ;
  1813. RESTRG:
  1814.     CALL    COMG    ;GET GROUP NUMBER FROM COMMAND LINE AND POS
  1815.     PUSH    H
  1816.     CALL    ILPRT
  1817.     DB    'Writing to Group ',0
  1818.     LHLD    GROUP    ;GET GROUP NUMBER
  1819.     MOV    B,H    ;VALUE IN BC
  1820.     MOV    C,L
  1821.     CALL    HEXB    ;PRINT IN HEX
  1822.     CALL    ILPRT
  1823.     DB    CR,LF,0
  1824.     LHLD    QNXT    ;NEXT PTR USED FOR WRITE
  1825.     SHLD    QPTR
  1826.     POP    H
  1827.     MVI    A,0FFH    ;WRITE FUNCTION
  1828.     STA    CPYFCT    ;COPY FUNCTION FOR GROUP COPY ROUTINE
  1829.     JMP    COPYG    ;GROUP COPY ROUTINE
  1830. ;
  1831. NOSAVE:
  1832.     CALL    ILPRT
  1833.     DB    '++ No "<" Save Command Issued ++'
  1834.     DB    CR,LF,0
  1835.     JMP    PRMPTR
  1836. ;
  1837. ;Move (HL) to (DE) length in B
  1838. ;
  1839. MOVE:
  1840.     MOV    A,M
  1841.     STAX    D
  1842.     INX    H
  1843.     INX    D
  1844.     DJNZ    MOVE
  1845.     RET
  1846. ;
  1847. NORITE:
  1848.     XRA    A    ;GET 0
  1849.     STA    WRFLG    ;CAN'T WRITE NOW
  1850.     RET
  1851. ;
  1852. ;No match in search, try next char
  1853. ;
  1854. SRNOMT:
  1855.     POP    H
  1856.     CALL    CTLCS    ;ABORT?
  1857.     JRNZ    SEARCH    ;..YES
  1858.     LXI    H,INBUF
  1859.     MVI    M,CR
  1860.     JMP    CLCGRP    ;SHOW WHERE STOPPED
  1861. ;
  1862. ;COMMAND:  =
  1863. ;Search for character string
  1864. ;
  1865. SEARCH:
  1866.     PUSH    H    ;SAVE STRING POINTER
  1867. ;
  1868. SRCHL:
  1869.     CALL    RDBYTE    ;GET A BYTE
  1870.     MOV    B,A    ;SAVE IT
  1871.     MOV    A,M    ;CHECK NEXT MATCH CHAR.
  1872.     CPI    '<'    ;WILL IT BE HEX?
  1873.     MOV    A,B    ;RESTORE DISK CHAR
  1874.     JRZ    SRCHL1
  1875.     ANI    7FH    ;NEXT CHAR IS ASCII...STRIP BIT 7
  1876. ;
  1877. SRCHL1:
  1878.     PUSH    PSW
  1879.     CALL    GETVAL    ;GET SEARCH VALUE
  1880.     MOV    B,A
  1881.     POP    PSW
  1882.     CMP    B    ;MATCH?
  1883.     JNZ    SRNOMT    ;NO MATCH
  1884.     INX    H
  1885.     MOV    A,M    ;DONE?
  1886.     CPI    CR    ;END OF LINE?
  1887.     JRZ    SREQU
  1888.     CPI    EOLCH    ;LOGICAL EOL?
  1889.     JRNZ    SRCHL
  1890. ;
  1891. ;Got match
  1892. ;
  1893. SREQU:
  1894.     CALL    ILPRT
  1895.     DB    '= at ',0
  1896.     LDA    BUFAD
  1897.     ANI    7FH
  1898.     CALL    HEX
  1899.     CALL    CRLF
  1900.     JMP    CLCGRP
  1901. ;
  1902. ;Get value from input buffer
  1903. ;
  1904. GETVAL:
  1905.     MOV    A,M    ;GET NEXT CHAR
  1906.     CPI    '<'    ;HEX ESCAPE?
  1907.     RNZ        ;NO, RETURN
  1908. ;"<<" means one "<"
  1909.     INX    H
  1910.     MOV    A,M
  1911.     CPI    '<'
  1912.     RZ
  1913. ;Got hex
  1914.     PUSH    D
  1915.     CALL    HEXIN    ;GET VALUE
  1916.     CPI    '>'    ;PROPER DELIM?
  1917.     MOV    A,E    ;GET VALUE
  1918.     POP    D
  1919.     JNZ    WHAT    ;ERROR
  1920.     RET
  1921. ;
  1922. ;Read a byte at a time from disk
  1923. ;
  1924. RDBYTE:
  1925.     PUSH    H
  1926.     LDA    FTSW    ;FIRST READ?
  1927.     ORA    A
  1928.     JRNZ    READ1
  1929.     LHLD    BUFAD
  1930.     MOV    A,L
  1931.     ORA    A    ;IN BUFFER?
  1932.     JM    NORD    ;YES, SKIP READ
  1933. ;
  1934. ;Have to read
  1935. ;
  1936.     CALL    NXTSEC    ;ADVANCE TO NEXT BLOCK
  1937. ;
  1938. READ1:
  1939.     XRA    A
  1940.     STA    FTSW    ;NOT FIRST READ
  1941.     LHLD    CURSEC
  1942.     XCHG
  1943.     CALL    SETSEC
  1944.     LHLD    CURTRK
  1945.     XCHG
  1946.     CALL    SETTRK
  1947.     CALL    READ
  1948.     CALL    CLCSUB
  1949.     LXI    H,TBUFF
  1950. ;
  1951. NORD:
  1952.     MOV    A,M
  1953.     INX    H
  1954.     SHLD    BUFAD
  1955.     POP    H
  1956.     RET
  1957. ;
  1958. ;COMMAND:  V
  1959. ;View the file in ASCII starting at
  1960. ;current sector, stepping thru the disk
  1961. ;
  1962. VIEW:
  1963.     LDA    WRFLG
  1964.     ORA    A
  1965.     JZ    BADDMP
  1966.     CALL    DECIN    ;GET DISPL IF ANY
  1967.     PUSH    H
  1968.     MOV    A,E
  1969.     ORA    A
  1970.     JRNZ    VIEWLP
  1971.     INR    E    ;DFLT=1
  1972. ;
  1973. VIEWLP:
  1974.     LXI    H,TBUFF    ;TO DATA
  1975. ;
  1976. VEWCHR:
  1977.     CALL    CTLCS    ;ABORT?
  1978.     JRZ    VEWEND
  1979.     MOV    A,M    ;GET NEXT CHAR
  1980.     CPI    1AH    ;EOF?
  1981.     JRZ    VEWEOF
  1982.     ANI    7FH    ;MASK
  1983.     CPI    7EH    ;ESC CHAR FOR H1500
  1984.     JRNC    VIEWHX    ;SHOW RUBOUT AND TILDE AS HEX
  1985.     CPI    ' '
  1986.     JRNC    VIEWPR
  1987.     CPI    CR    ;CR PASS
  1988.     JRZ    VIEWPR
  1989.     CPI    LF    ;LF PASS
  1990.     JRZ    VIEWPR
  1991.     CPI    TAB    ;TAB PASS
  1992.     JRZ    VIEWPR
  1993. ;
  1994. VIEWHX:
  1995.     MOV    A,M    ;NOT ASCII...PRINT AS <NN>
  1996.     CALL    BHEX
  1997.     JR    VIEWNP
  1998. ;
  1999. VIEWPR:
  2000.     CALL    TYPE
  2001. ;
  2002. VIEWNP:
  2003.     INR    L
  2004.     JRNZ    VEWCHR
  2005.     DCR    E
  2006.     JRZ    VEWEND
  2007.     PUSH    D    ;SAVE COUNT
  2008.     CALL    NXTSEC
  2009.     LHLD    CURSEC
  2010.     XCHG
  2011.     CALL    SETSEC    
  2012.     LHLD    CURTRK
  2013.     XCHG
  2014.     CALL    SETTRK
  2015.     CALL    READ
  2016.     POP    D    ;RESTORE COUNT
  2017.     JR    VIEWLP
  2018. ;
  2019. VEWEOF:
  2020.     CALL    ILPRT
  2021.     DB    CR,LF,'    ++ EOF ++',CR,LF,0
  2022. ;
  2023. VEWEND:
  2024.     POP    H
  2025.     CALL    CRLF
  2026.     JMP    CLCGRP
  2027. ;
  2028. ;COMMAND:  A or D
  2029. ;Dump in hex or ASCII
  2030. ;
  2031. DUMP:
  2032.     LDA    WRFLG
  2033.     ORA    A
  2034.     JRNZ    DUMPOK
  2035. ;
  2036. BADDMP:
  2037.     CALL    ILPRT
  2038.     DB    '++ Can''t dump, no sector read ++',CR,LF,0
  2039. ;
  2040. EXPL:
  2041.     CALL    ILPRT
  2042.     DB    'Use G command following F,',CR,LF
  2043.     DB    'or R or S following T',CR,LF,0
  2044.     JMP    PRMPTR
  2045. ;
  2046. DUMPOK:
  2047.     MOV    A,M    ;GET NEXT CHAR
  2048.     CPI    EOLCH    ;LOGICAL EOL?
  2049.     JRZ    DUMPDF    ;DFLT
  2050.     CPI    CR    ;PHYSICAL EOL?
  2051.     JRNZ    DMPNDF
  2052. ;
  2053. ;Use default
  2054. ;
  2055. DUMPDF:
  2056.     LXI    B,TBUFF
  2057.     LXI    D,0FFH
  2058.     JR    DUMP1
  2059. ;
  2060. DMPNDF:
  2061.     CALL    DISP
  2062.     MOV    B,D
  2063.     MOV    C,E
  2064.     CPI    CR
  2065.     JRZ    DUMP1
  2066.     CPI    EOLCH
  2067.     JRZ    DUMP1
  2068.     INX    H    ;SKIP SEPCH
  2069.     CALL    DISP
  2070. ;
  2071. ;BC = start, DE = end
  2072. ;
  2073. DUMP1:
  2074.     PUSH    H    ;SAVE COMMAND POINTER
  2075.     MOV    H,B
  2076.     MOV    L,C
  2077. ;
  2078. DUMPLP:
  2079.     MOV    A,L
  2080.     ANI    7FH
  2081.     CALL    HEX    ;PRINT HEX VALUE
  2082.     CALL    SPACE
  2083.     CALL    SPACE
  2084.     LDA    DUMTYP
  2085.     CPI    'A'
  2086.     JRZ    DUMPAS
  2087.     PUSH    H    ;SAVE START
  2088. ;
  2089. DHEX:
  2090.     MOV    A,M
  2091.     CALL    HEX    ;PRINT HEX VALUE PTED TO BY HL
  2092.     MOV    A,L
  2093.     ANI    3
  2094.     CPI    3    ;EXTRA SPACE EVERY 4
  2095.     CZ    SPACE
  2096.     MOV    A,L
  2097.     ANI    7
  2098.     CPI    7    ;TWO EXTRA SPACES EVERY 8
  2099.     CZ    SPACE
  2100.     MOV    A,E
  2101.     CMP    L
  2102.     JRZ    DPOP
  2103.     INX    H
  2104.     MOV    A,L
  2105.     ANI    0FH
  2106.     JRNZ    DHEX
  2107. ;
  2108. DPOP:
  2109.     CALL    CTLCS    ;ABORT?
  2110.     JZ    PRMPTR
  2111.     LDA    DUMTYP
  2112.     CPI    'H'
  2113.     JRZ    DNOAS    ;HEX ONLY
  2114.     POP    H    ;GET START ADDR
  2115. ;
  2116. DUMPAS:
  2117.     CALL    ASTER    ;PRINT FIRST ASTERISK TO SEPARATE TEXT
  2118. ;
  2119. DCHR:
  2120.     MOV    A,M    ;GET CHAR
  2121.     ANI    7FH
  2122.     CPI    ' '
  2123.     JRC    DPER
  2124.     CPI    7EH    ;TRAP ESC FOR H1500
  2125.     JRC    DOK
  2126. ;
  2127. DPER:
  2128.     MVI    A,'.'    ;PRINT PRINTING CHAR
  2129. ;
  2130. DOK:
  2131.     CALL    TYPE    ;PRINT CHAR
  2132.     MOV    A,E
  2133.     CMP    L
  2134.     JRZ    DEND
  2135.     INX    H
  2136.     MOV    A,L
  2137.     ANI    0FH
  2138.     JRNZ    DCHR
  2139. ;
  2140. DEND:
  2141.     CALL    ASTER    ;PRINT ENDING ASTERISK
  2142.     CALL    CRLF    ;NEW LINE
  2143.     PUSH    D
  2144.     CALL    CTLCS    ;ABORT?
  2145.     POP    D
  2146.     JZ    PRMPTR
  2147.     MOV    A,E
  2148.     CMP    L
  2149.     JRNZ    DUMPLP
  2150.     POP    H
  2151.     JMP    PROMPT
  2152. ;
  2153. DNOAS:
  2154.     POP    B
  2155.     CALL    CRLF
  2156.     MOV    A,E
  2157.     CMP    L
  2158.     JRNZ    DUMPLP
  2159.     POP    H
  2160.     JMP    PROMPT
  2161. ;
  2162. ;COMMAND:  G
  2163. ;Position
  2164. ;
  2165. POS:
  2166.     PUSH    PSW
  2167.     MOV    A,M
  2168.     CPI    EOLCH    ;LOGICAL EOL?
  2169.     JRZ    POSINQ
  2170.     CPI    CR    ;PHYSICAL EOL?
  2171.     JRNZ    POSOK
  2172. ;
  2173. POSINQ:
  2174.     POP    PSW
  2175.     JMP    INQ
  2176. ;
  2177. POSOK:
  2178.     POP    PSW
  2179.     CPI    'T'    ;TRACK?
  2180.     JRZ    POSTKD
  2181.     CPI    'S'    ;SECTOR?
  2182.     JRZ    POSSCD
  2183.     CPI    'G'    ;GROUP?
  2184.     JZ    POSGPH
  2185.     JMP    WHAT    ;ERROR OTHERWISE
  2186. ;
  2187. ;Position to Track
  2188. ;
  2189. POSTKD:
  2190.     CALL    DECIN    ;GET NUMBER IN DECIMAL
  2191. ;
  2192. POSTRK:
  2193.     PUSH    H
  2194.     LHLD    MAXTRK    ;CHECK FOR BEYOND END OF DISK
  2195.     CALL    SUBDE
  2196.     POP    H
  2197.     JC    OUTLIM
  2198.     CALL    SETTRK    ;SET TRACK
  2199.     CALL    NORITE    ;TRACK DOESN'T READ
  2200.     MVI    A,1
  2201.     STA    NOTPOS    ;SHOW NOT POSITIONED
  2202.     JR    CLCGRP
  2203. ;
  2204. ;Position to Sector
  2205. ;
  2206. POSSCD:
  2207.     CALL    DECIN    ;GET NUMBER IN DECIMAL
  2208.     MOV    A,D
  2209.     ORA    E
  2210.     JZ    WHAT    ;DON'T ALLOW SECTOR 0
  2211. ;
  2212. POSSEC:
  2213.     PUSH    H
  2214.     LHLD    SPT    ;CHECK FOR WITHIN RANGE
  2215.     CALL    SUBDE
  2216.     POP    H
  2217.     JC    WHAT
  2218.     CALL    SETSEC    ;SET SECTOR
  2219.     CALL    READ    ;READ
  2220.     XRA    A
  2221.     STA    NOTPOS    ;POSITIONED OK
  2222. ;
  2223. ;Calculate Group Number/Group Displacement and Print
  2224. ;
  2225. CLCGRP:
  2226.     CALL    CLCSUB
  2227.     JMP    INQ
  2228. ;
  2229. ;Calculate group from track and sector
  2230. ;  On exit, GROUP = Group Number and GRPDIS = Displacement within Group
  2231. ;
  2232. CLCSUB:
  2233.     PUSH    H
  2234.     LHLD    SYSTRK
  2235.     XCHG
  2236.     LHLD    CURTRK
  2237.     CALL    SUBDE    ;COMPUTE RELATIVE TRACK NUMBER (SKIP SYSTEM TRACKS)
  2238.     XCHG
  2239.     LHLD    SPT    ;MULTIPLY BY NUMBER OF SECTORS/TRACK
  2240.     CALL    MULT
  2241.     XCHG        ;DE=TOTAL NUMBER OF SECTORS IN TRACKS
  2242.     LHLD    CURSEC    ;GET SECTOR OFFSET FROM BEGINNING OF TRACK
  2243.     DCX    H
  2244.     DAD    D    ;HL=TOTAL NUMBER OF SECTORS WITH OFFSET
  2245.     LDA    BLM
  2246.     MOV    B,A
  2247.     MOV    A,L
  2248.     ANA    B
  2249.     STA    GRPDIS    ;DISPLACEMENT WITHIN GROUP
  2250.     LDA    BSH
  2251.     MOV    B,A
  2252. ;
  2253. CLCLOP:
  2254.     CALL    ROTRHL
  2255.     DJNZ    CLCLOP
  2256.     SHLD    GROUP    ;GROUP NUMBER
  2257.     POP    H
  2258.     RET
  2259. ;
  2260. ;Position in the directory after a find
  2261. ;(Does not work in CP/M-2.x)
  2262. ;
  2263. POSDIR:
  2264.     PUSH    H    ;SAVE INBUF
  2265.     LHLD    BSH
  2266.     XRA    A
  2267.     STA    FINDFL    ;CANCEL POS REQ
  2268.     LDA    DIRPOS    ;GET POSITION
  2269.     RAR
  2270.     RAR
  2271.     PUSH    PSW
  2272.     ANA    H
  2273.     STA    GRPDIS
  2274.     POP    PSW
  2275. ;
  2276. POSDLP:
  2277.     RAR
  2278.     DCR    L
  2279.     JRNZ    POSDLP
  2280.     ANI    1    ;GET GROUP
  2281.     MOV    L,A    ;SETUP FOR POSGP2
  2282.     MVI    H,0
  2283.     SHLD    GROUP
  2284.     XCHG
  2285.     JR    POSGP2    ;POSITION TO IT
  2286. ;
  2287. ;Position to Group
  2288. ;
  2289. POSGPH:
  2290.     CALL    HEXIN    ;GET PARAMETER
  2291. ;
  2292. ;Position to Group Numbered in DE and Print Position
  2293. ;
  2294. POSGRP:
  2295.     PUSH    H
  2296.     LHLD    DSM    ;CHECK FOR WITHIN BOUNDS
  2297.     CALL    SUBDE
  2298.     POP    H
  2299.     JC    OUTLIM
  2300.     XCHG
  2301.     SHLD    GROUP    ;SET GROUP NUMBER
  2302.     XCHG
  2303.     XRA    A
  2304.     STA    GRPDIS    ;SET ZERO DISPLACEMENT
  2305.     PUSH    H
  2306. ;
  2307. POSGP2:
  2308.     CALL    GTKSEC    ;CONVERT GROUP TO SECTOR/TRACK
  2309.     CALL    SETTRK    ;SET TRACK
  2310.     XCHG
  2311.     CALL    SETSEC    ;SET SECTOR
  2312.     CALL    READ    ;READ BLOCK
  2313.     XRA    A
  2314.     STA    NOTPOS    ;NOW POSITIONED
  2315.     POP    H
  2316.     JMP    INQ
  2317. ;
  2318. ;Convert Group Number in DE to Sector and Track; also, GRPDIS = Offset in Grp
  2319. ;  On exit, DE = Track Number, HL = Sector Number
  2320. ;
  2321. GTKSEC:
  2322.     MOV    H,D    ;HL=GROUP NUMBER
  2323.     MOV    L,E
  2324.     LDA    BSH    ;GET NUMBER OF SECTORS IN GROUP
  2325. ;
  2326. GLOOP:
  2327.     DAD    H
  2328.     DCR    A
  2329.     JRNZ    GLOOP
  2330.     LDA    GRPDIS    ;ADD IN DISPLACEMENT WITHIN GROUP
  2331.     ADD    L    ;CAN'T CARRY
  2332.     MOV    L,A
  2333. ;
  2334. ;Divide by number of sectors, quotient=track, remainder=sector
  2335. ;
  2336.     XCHG        ;DE=TOTAL NUMBER OF SECTORS
  2337.     LHLD    SPT    ;GET NUMBER OF SECTORS/TRACK
  2338.     CALL    NEG    ;HL = -SECTORS/TRACK
  2339.     XCHG
  2340.     LXI    B,0    ;SET TRACK COUNTER TO ZERO
  2341. ;
  2342. DIVLP:
  2343.     INX    B    ;INCREMENT TRACK COUNT
  2344.     DAD    D    ;SUBTRACT SECTORS/TRACK FROM SECTORS TOTAL
  2345.     JRC    DIVLP
  2346.     DCX    B    ;ADJUST TRACK COUNT
  2347.     XCHG
  2348.     LHLD    SPT    ;ADD SECTORS/TRACK BACK IN TO ADJUST
  2349.     DAD    D    ;HL=NUMBER OF SECTORS ON LAST TRACK OF GROUP
  2350.     PUSH    H
  2351.     LHLD    SYSTRK    ;ADD IN NUMBER OF SYSTEM TRACKS
  2352.     DAD    B
  2353.     XCHG        ;DE=TRACK NUMBER
  2354.     POP    H
  2355.     INX    H    ;HL=SECTOR NUMBER
  2356.     RET
  2357. ;
  2358. ;COMMAND:  F
  2359. ;Find Directory Entry for specified file
  2360. ;
  2361. POSFIL:
  2362.     CALL    NORITE
  2363.     MVI    A,1
  2364.     STA    FINDFL    ;SO WE POSITION LATER
  2365.     LXI    D,FCB
  2366.     XRA    A    ;LOGGED IN DISK
  2367.     STAX    D
  2368.     INX    D
  2369.     MVI    B,8
  2370.     CALL    MVNAME
  2371.     MVI    B,3
  2372.     CALL    MVNAME
  2373.     LXI    D,FCB
  2374.     MVI    C,SRCHF
  2375.     PUSH    H
  2376.     CALL    BDOS
  2377.     INR    A
  2378.     JRNZ    FLOK
  2379.     STA    DIRPOS    ;GRP 0 IF NOT FOUND
  2380.     CALL    ILPRT
  2381.     DB    '++ File Not Found ++',CR,LF,0
  2382.     POP    H
  2383.     JMP    PROMPT
  2384. ;
  2385. FLOK:
  2386.     DCR    A
  2387.     STA    DIRPOS    ;SAVE POS. IN DIR
  2388.     ANI    3
  2389.     MOV    L,A
  2390.     MVI    H,0
  2391.     DAD    H    ;X32 BYTES/ENTRY
  2392.     DAD    H
  2393.     DAD    H
  2394.     DAD    H
  2395.     DAD    H
  2396.     LXI    D,TBUFF
  2397.     DAD    D    ;HL POINTS TO ENTRY
  2398.     LXI    D,32
  2399.     XCHG
  2400.     DAD    D
  2401.     XCHG
  2402.     MVI    A,'D'
  2403.     STA    DUMTYP
  2404.     JMP    DUMPLP    ;WHICH POPS H
  2405. ;
  2406. MVNAME:
  2407.     MOV    A,M    ;GET NEXT CHAR OF FILE NAME/TYPE
  2408.     CPI    '.'    ;END OF FILE NAME?
  2409.     JRZ    MVIPAD    ;PAD OUT IF SO
  2410.     CPI    CR    ;END OF ENTRY?
  2411.     JRZ    PAD    ;PAD OUT IF SO
  2412.     CPI    EOLCH    ;END OF ENTRY?
  2413.     JRZ    PAD    ;PAD OUT IF SO
  2414.     CALL    UPCASE    ;CAPITALIZE
  2415.     STAX    D    ;STORE
  2416.     INX    H    ;PT TO NEXT
  2417.     INX    D
  2418.     DJNZ    MVNAME
  2419.     MOV    A,M    ;CHECK FOR ERROR
  2420.     CPI    CR    ;OK IF EOL
  2421.     RZ
  2422.     CPI    EOLCH    ;OK IF LOGICAL EOL
  2423.     RZ
  2424.     INX    H
  2425.     CPI    '.'    ;OK IF DECIMAL
  2426.     RZ
  2427.     JMP    WHAT
  2428. ;
  2429. MVIPAD:
  2430.     INX    H
  2431. ;
  2432. PAD:
  2433.     MVI    A,' '    ;PRINT PADDING SPACES
  2434.     STAX    D
  2435.     INX    D
  2436.     DJNZ    PAD
  2437.     RET
  2438. ;
  2439. ;COMMAND:  +
  2440. ;Advance to Next Logical Sector
  2441. ;
  2442. PLUS:
  2443.     LXI    D,1    ;DFLT TO 1 SECT
  2444.     MOV    A,M    ;GET NEXT CHAR
  2445.     CPI    CR    ;CR?
  2446.     JRZ    PLUSGO    ;..YES, DFLT TO 1
  2447.     CPI    EOLCH
  2448.     JRZ    PLUSGO
  2449.     CALL    DECIN    ;GET #
  2450.     MOV    A,D
  2451.     ORA    E
  2452.     JRNZ    PLUSGO
  2453.     LXI    D,1    ;SET 1 IF VALUE OF ZERO
  2454. ;
  2455. PLUSGO:
  2456.     CALL    NXTSEC    ;ADVANCE TO NEXT LOGICAL SECTOR
  2457.     DCX    D    ;MORE TO GO?
  2458.     MOV    A,D
  2459.     ORA    E
  2460.     JRNZ    PLUSGO    ;..YES
  2461. ;
  2462. ;Ok, incremented to sector.  Setup and read
  2463. ;
  2464. PLUSMI:
  2465.     PUSH    H
  2466.     LHLD    CURSEC
  2467.     XCHG
  2468.     CALL    SETSEC    ;SET SECTOR
  2469.     LHLD    CURTRK
  2470.     XCHG
  2471.     CALL    SETTRK    ;SET TRACK
  2472.     POP    H
  2473.     CALL    READ    ;READ IT
  2474.     JMP    CLCGRP    ;CALCULATE GROUP AND DISPLAY
  2475. ;
  2476. ;COMMAND:  -
  2477. ;Back up to previous sector
  2478. ;
  2479. MINUS:
  2480.     LXI    D,1    ;SET DFLT
  2481.     MOV    A,M    ;GET CHAR
  2482.     CPI    CR    ;CR?
  2483.     JRZ    MINGO    ;..YES, DFLT=1
  2484.     CPI    EOLCH
  2485.     JRZ    MINGO
  2486.     CALL    DECIN    ;..NO, GET ##
  2487.     MOV    A,D
  2488.     ORA    E
  2489.     JRNZ    MINGO
  2490.     LXI    D,1    ;ASSUME 1
  2491. ;
  2492. MINGO:
  2493.     PUSH    H
  2494.     LHLD    CURSEC    ;BACK UP SECTOR
  2495.     DCX    H
  2496.     MOV    A,H
  2497.     ORA    L
  2498.     JRNZ    MINOK
  2499.     LHLD    CURTRK    ;BEYOND SECTOR ZERO, SO BACK UP TRACK
  2500.     MOV    A,H
  2501.     ORA    L
  2502.     JRNZ    SEASH
  2503.     LHLD    MAXTRK    ;WRAP TO END OF DISK
  2504.     SHLD    CURTRK
  2505.     LHLD    MAXSEC
  2506.     JR    MINOK
  2507. ;
  2508. SEASH:
  2509.     DCX    H
  2510.     SHLD    CURTRK
  2511.     LHLD    SPT    ;GET NUMBER OF SECTORS/TRACK
  2512. ;
  2513. MINOK:
  2514.     SHLD    CURSEC    ;SET NEW CURRENT SECTOR
  2515.     POP    H
  2516.     DCX    D    ;COUNT DOWN ON NUMBER OF TIMES TO BACKUP
  2517.     MOV    A,D
  2518.     ORA    E
  2519.     JRNZ    MINGO
  2520.     JR    PLUSMI    ;READ BLOCK
  2521. ;
  2522. ;Go to next sector
  2523. ;  On exit, CURSEC = Current Sector and CURTRK = Current Track
  2524. ;
  2525. NXTSEC:
  2526.     PUSH    H
  2527.     PUSH    D
  2528.     LHLD    CURSEC    ;INCREMENT CURRENT SECTOR
  2529.     INX    H
  2530.     XCHG
  2531.     LHLD    SPT    ;CHECK TO SEE IF BEYOND END OF TRACK
  2532.     CALL    SUBDE
  2533.     XCHG
  2534.     JRNC    NEXTOK
  2535.     LHLD    CURTRK    ;BEYOND END OF TRACK, SO INCR CURRENT TRACK
  2536.     INX    H
  2537.     XCHG
  2538.     LHLD    MAXTRK    ;SEE IF BEYOND END OF DISK
  2539.     CALL    SUBDE
  2540.     JRNC    TRASK
  2541.     LXI    D,0    ;WRAP TO START OF DISK
  2542. ;
  2543. TRASK:
  2544.     XCHG
  2545.     SHLD    CURTRK    ;SET NEW CURRENT TRACK
  2546.     LXI    H,1    ;SET SECTOR 1
  2547. ;
  2548. NEXTOK:
  2549.     SHLD    CURSEC    ;SET NEW CURRENT SECTOR
  2550.     POP    D
  2551.     POP    H
  2552.     RET
  2553. ;
  2554. ;Tell what group, displacement, track, sector, physical sector
  2555. ;
  2556. INQ:
  2557.     CALL    INQSUB
  2558.     JMP    PROMPT
  2559. ;
  2560. ;Position inquiry subroutine
  2561. ;Executed via: G S or T (with no operands)
  2562. ;
  2563. INQSUB:
  2564.     PUSH    H
  2565.     LHLD    SYSTRK    ;CHECK IF IN SYSTEM TRACKS
  2566.     XCHG
  2567.     LHLD    CURTRK
  2568.     CALL    SUBDE
  2569.     JRC    NOGRP
  2570.     CALL    ILPRT    ;PRINT GROUP NUMBER IF NOT IN SYSTEM TRACKS
  2571.     DB    'Group = ',0
  2572.     LHLD    GROUP
  2573.     MOV    B,H
  2574.     MOV    C,L
  2575.     CALL    HEXB    ;PRINT GROUP NUMBER IN BC
  2576.     MVI    A,':'
  2577.     CALL    TYPE
  2578.     LDA    GRPDIS
  2579.     CALL    HEX    ;PRINT GROUP DISPLACEMENT IN A
  2580.     MVI    A,','
  2581.     CALL    TYPE
  2582. ;
  2583. NOGRP:
  2584.     CALL    ILPRT    ;PRINT TRACK NUMBER
  2585.     DB    ' Track = ',0
  2586.     LHLD    CURTRK
  2587.     CALL    DEC    ;TRACK NUMBER IN DECIMAL
  2588.     CALL    ILPRT    ;PRINT SECTOR NUMBER
  2589.     DB    ', Sector = ',0
  2590.     LHLD    CURSEC
  2591.     CALL    DEC    ;SECTOR NUMBER IN DECIMAL
  2592.     CALL    ILPRT    ;PRINT PHYSCIAL SECTOR NUMBER
  2593.     DB    ', Physical Sector = ',0
  2594.     LHLD    PHYSEC
  2595.     CALL    DEC    ;PHYSICAL SECTOR NUMBER IN DECIMAL
  2596.     CALL    CRLF
  2597.     POP    H
  2598.     RET
  2599. ;
  2600. ;COMMAND:  C
  2601. ;Change Contents of Current Block
  2602. ;
  2603. CHG:
  2604.     MOV    A,M    ;GET TYPE (HEX, ASCII)
  2605.     CALL    UPCASE
  2606.     PUSH    PSW    ;SAVE "H" OR "A"
  2607.     INX    H
  2608.     CALL    HEXIN    ;GET DISP IN HEX
  2609.     CALL    DISP1    ;VALIDATE DISP TO DE
  2610.     INX    H
  2611.     LXI    B,0    ;SHOW NO 'THRU' ADDR
  2612.     CPI    '-'    ;TEST DELIM FR. DISP
  2613.     JRNZ    CHGNTH    ;NO THRU
  2614.     PUSH    D    ;SAVE FROM
  2615.     CALL    HEXIN
  2616.     CALL    DISP1    ;GET THRU
  2617.     INX    H    ;SKIP END DELIM
  2618.     MOV    B,D
  2619.     MOV    C,E    ;BC = THRU
  2620.     POP    D    ;GET FROM
  2621.     JR    CHGAH
  2622. ;
  2623. CHGNTH:
  2624.     CPI    SEPCH
  2625.     JNZ    WHAT
  2626. ;
  2627. CHGAH:
  2628.     POP    PSW
  2629.     CPI    'H'    ;HEX?
  2630.     JRZ    CHGHEX
  2631.     CPI    'A'    ;ASCII?
  2632.     JNZ    WHAT
  2633. ;
  2634. ;Change ASCII
  2635. ;
  2636. CHGALP:
  2637.     MOV    A,M    ;GET CHAR
  2638.     CPI    CR
  2639.     JZ    PROMPT
  2640.     CPI    EOLCH
  2641.     JZ    PROMPT
  2642. ;
  2643. ;The following print of the deleted byte is commented out; if leading
  2644. ;  semicolons are removed, deleted bytes will be printed
  2645. ;
  2646. ;    LDAX    D    ;GET BYTE THAT IS REPLACED
  2647. ;    CPI    ' '
  2648. ;    JC    CHGAHX
  2649. ;    CPI    7EH    ;DON'T PRINT ESC CHAR FOR H1500
  2650. ;    JNC    CHGAHX
  2651. ;    JMP    CHGA2
  2652. ;
  2653. ;CHGAHX:
  2654. ;    CALL    BHEX
  2655. ;    JMP    CHGA3
  2656. ;
  2657. ;CHGA2:
  2658. ;    CALL    TYPE
  2659. ;
  2660. ;End of print of delete bytes
  2661. ;
  2662. CHGA3:
  2663.     SHLD    BACK    ;IN CASE "THRU"
  2664.     CALL    GETVAL    ;GET ASCII OR <HEX> VALUE
  2665.     STAX    D    ;UPDATE BYTE
  2666.     INX    H    ;PT TO NEXT INPUT CHAR
  2667. ;
  2668. ;See if 'THRU' requested
  2669. ;
  2670.     MOV    A,C
  2671.     ORA    A
  2672.     JRZ    CHANTH
  2673.     CMP    E    ;DONE?..
  2674.     JZ    PROMPT    ;..YES
  2675.     LHLD    BACK
  2676. ;
  2677. CHANTH:
  2678.     INR    E
  2679.     JNZ    CHGALP
  2680.     MOV    A,M
  2681.     CPI    CR
  2682.     JZ    PROMPT
  2683.     CPI    EOLCH
  2684.     JZ    PROMPT
  2685.     JMP    WHAT
  2686. ;
  2687. ;Change hex
  2688. ;
  2689. CHGHCM:
  2690.     INX    H
  2691. ;
  2692. CHGHEX:
  2693.     MOV    A,M    ;GET HEX DIGIT
  2694.     CPI    CR
  2695.     JZ    PROMPT
  2696.     CPI    EOLCH
  2697.     JZ    PROMPT
  2698.     CPI    SEPCH    ;DELIM?
  2699.     JRZ    CHGHCM
  2700.     PUSH    D
  2701.     SHLD    HEXAD    ;IN CASE 'THRU'
  2702.     CALL    HEXIN    ;POSITIONS TO DELIM
  2703.     MOV    A,E    ;GET VALUE
  2704.     POP    D    ;..ADDR
  2705. ;
  2706. ;The following comments out the echo of the deleted byte; removing the
  2707. ;  leading semicolons restores the echo
  2708. ;
  2709. ;    PUSH    PSW    ;SAVE VALUE
  2710. ;    LDAX    D    ;GET OLD
  2711. ;    CALL    HEX    ;ECHO IN HEX
  2712. ;    POP    PSW    ;GET NEW
  2713. ;
  2714. ;End of echo of bytes
  2715. ;
  2716.     STAX    D    ;SAVE NEW BYTE
  2717.     MOV    A,C    ;SEE IF 'THRU'
  2718.     ORA    A
  2719.     JRZ    CHHNTH    ;..NO.
  2720.     CMP    E    ;..YES, DONE?
  2721.     JZ    PROMPT
  2722.     LHLD    HEXAD    ;..NO: MORE
  2723. ;
  2724. CHHNTH:
  2725.     INR    E
  2726.     JRNZ    CHGHEX
  2727.     MOV    A,M
  2728.     CPI    CR
  2729.     JZ    PROMPT
  2730.     CPI    EOLCH
  2731.     JZ    PROMPT
  2732.     JMP    WHAT
  2733. ;
  2734. ;COMMAND:  R
  2735. ;Read Current Block into TBUFF
  2736. ;COMMAND:  RG
  2737. ;Read Specified Group into GBUFF
  2738. ;
  2739. DOREAD:
  2740.     LDA    NOTPOS    ;POSITIONED?
  2741.     ORA    A
  2742.     JRNZ    CANTRD
  2743.     CALL    READ    ;READ BLOCK
  2744.     JMP    PROMPT
  2745. ;
  2746. CANTRD:
  2747.     CALL    ILPRT
  2748.     DB    '++ Can''t read - not positioned ++',CR,LF
  2749.     DB    'Position by:',CR,LF
  2750.     DB    '    Track then Sector, or',CR,LF
  2751.     DB    '    Group',CR,LF,0
  2752.     JMP    PROMPT
  2753. ;
  2754. ;COMMAND:  W
  2755. ;Write Current Block to Disk
  2756. ;COMMAND:  WG
  2757. ;Write Specified Group from GBUFF
  2758. ;
  2759. DORITE:
  2760.     CALL    WRITE    ;DO WRITE
  2761.     JMP    PROMPT
  2762. ;
  2763. ;Print Byte in A as Hex Digits
  2764. ;
  2765. BHEX:
  2766.     PUSH    PSW
  2767.     MVI    A,'<'
  2768.     CALL    TYPE
  2769.     POP    PSW
  2770.     CALL    HEX
  2771.     MVI    A,'>'
  2772.     CALL    TYPE
  2773.     RET
  2774. ;
  2775. ;Print Number in BC as Hex Digits
  2776. ;
  2777. HEXB:
  2778.     LDA    DSM+1
  2779.     ORA    A
  2780.     JZ    HEXX
  2781.     MOV    A,B
  2782.     CALL    HEX
  2783. ;
  2784. HEXX:
  2785.     MOV    A,C
  2786. ;
  2787. ;Print Byte in A as 2 Hex Digits
  2788. ;
  2789. HEX:
  2790.     PUSH    PSW
  2791.     RAR        ;GET HIGH NYBBLE
  2792.     RAR
  2793.     RAR
  2794.     RAR
  2795.     CALL    NIBBL    ;PRINT IT
  2796.     POP    PSW    ;GET LOW NYBBLE
  2797. ;
  2798. NIBBL:
  2799.     ANI    0FH    ;MASK LOW NYBBLE
  2800.     CPI    10    ;0-9?
  2801.     JRC    HEXNU
  2802.     ADI    7    ;CONVERT TO A-F
  2803. ;
  2804. HEXNU:
  2805.     ADI    '0'    ;CONVERT TO ASCII
  2806.     JMP    TYPE    ;PRINT IT
  2807. ;
  2808. ;Decimal output routine
  2809. ;  Print Number in HL as decimal digits
  2810. ;
  2811. DEC:
  2812.     PUSH    B
  2813.     PUSH    D
  2814.     PUSH    H
  2815.     XRA    A    ;SET NO LEADING DIGIT
  2816.     STA    DDIG
  2817.     LXI    B,10000
  2818.     CALL    DPRT
  2819.     DAD    B
  2820.     LXI    B,1000
  2821.     CALL    DPRT
  2822.     DAD    B
  2823.     LXI    B,100
  2824.     CALL    DPRT
  2825.     DAD    B
  2826.     LXI    B,10
  2827.     CALL    DPRT
  2828.     DAD    B
  2829.     MOV    A,L    ;ALWAYS PRINT LSD
  2830.     ADI    '0'    ;ASCII
  2831.     CALL    TYPE
  2832.     POP    H
  2833.     POP    D
  2834.     POP    B
  2835.     RET
  2836. DPRT:
  2837.     PUSH    B    ;SAVE BC
  2838.     MVI    D,0FFH    ;SET -1
  2839. DPRTL:
  2840.     INR    D    ;ADD 1 TO OUTPUT DIGIT
  2841.     MOV    A,L    ;L-C
  2842.     SUB    C
  2843.     MOV    L,A
  2844.     MOV    A,H    ;H-B
  2845.     SBB    B
  2846.     MOV    H,A
  2847.     JRNC    DPRTL
  2848.     POP    B    ;RESTORE BC
  2849.     LDA    DDIG    ;GET LEADING DIGIT FLAG
  2850.     ORA    D    ;CHECK FOR ZERO STILL
  2851.     STA    DDIG    ;SET FLAG
  2852.     MOV    A,D    ;GET DIGIT TO PRINT
  2853.     RZ        ;ABORT IF BOTH ZERO
  2854.     ADI    '0'    ;ASCII
  2855.     JMP    TYPE
  2856. DDIG:    DS    1    ;TEMP FOR DEC USE ONLY
  2857. ;
  2858. ;Print <SP>
  2859. ;
  2860. SPACE:    MVI    A,' '
  2861.     JMP    TYPE
  2862. ;
  2863. ;Print '*'
  2864. ;
  2865. ASTER:    MVI    A,'*'
  2866.     JMP    TYPE
  2867. ;
  2868. ;Inline print routine
  2869. ;  Print Chars ending in 0 pted to by Return Address; return to byte after
  2870. ;
  2871. ILPRT:
  2872.     XTHL        ;GET PTR AND SAVE HL
  2873. ;
  2874. ILPLP:
  2875.     CALL    CTLCS    ;ABORT?
  2876.     JZ    PRMPTR
  2877.     MOV    A,M    ;GET CHAR
  2878.     CPI    1    ;PAUSE? -- ^A
  2879.     JRNZ    ILPOK
  2880.     CALL    CONIN    ;WAIT FOR ANY CHAR
  2881.     CPI    3    ;ABORT?
  2882.     JZ    PRMPTR
  2883.     JR    ILPNX
  2884. ;
  2885. ILPOK:
  2886.     CALL    TYPE    ;PRINT CHAR
  2887. ;
  2888. ILPNX:
  2889.     INX    H    ;PT TO NEXT
  2890.     MOV    A,M    ;GET IT
  2891.     ORA    A    ;DONE?
  2892.     JRNZ    ILPLP
  2893.     INX    H    ;PT TO BYTE AFTER ENDING 0
  2894.     XTHL        ;RESTORE HL AND RET ADR
  2895.     RET
  2896. ;
  2897. ;DISP calls DECIN, and validates a sector
  2898. ;displacement, then converts it to an address
  2899. ;
  2900. DISP:
  2901.     CALL    DECIN
  2902. DISP1:
  2903.     PUSH    PSW    ;SAVE DELIMITER
  2904.     MOV    A,D
  2905.     ORA    A
  2906.     JRNZ    BADISP
  2907.     MOV    A,E
  2908.     ORA    A
  2909.     JM    BADISP
  2910.     ADI    80H    ;TO POINT TO BUFFER AT BASE+80H
  2911.     MOV    E,A
  2912.     MVI    D,BASE/256
  2913.     POP    PSW    ;GET DELIM
  2914.     RET
  2915. ;
  2916. BADISP:
  2917.     CALL    ILPRT
  2918.     DB    '++ Bad Displacement (Not 0-7FH) ++'
  2919.     DB    CR,LF,0
  2920.     JMP    PRMPTR
  2921. ;
  2922. ;Input Number from Command Line -- Assume it to be Hex
  2923. ;  Number returned in DE
  2924. ;
  2925. HEXIN:
  2926.     LXI    D,0
  2927.     MOV    A,M
  2928.     CPI    '#'    ;DECIMAL?
  2929.     JRZ    HDIN    ;MAKE DECIMAL
  2930. ;
  2931. HINLP:
  2932.     MOV    A,M    ;GET CHAR
  2933.     CALL    UPCASE    ;CAPITALIZE
  2934.     CPI    CR    ;EOL?
  2935.     RZ
  2936.     CPI    EOLCH    ;EOL?
  2937.     RZ
  2938.     CPI    SEPCH
  2939.     RZ
  2940.     CPI    '-'    ;'THRU'?
  2941.     RZ
  2942.     CPI    '>'
  2943.     RZ
  2944.     INX    H    ;PT TO NEXT CHAR
  2945.     CPI    '0'    ;RANGE?
  2946.     JC    WHAT
  2947.     CPI    '9'+1    ;RANGE?
  2948.     JRC    HINNUM
  2949.     CPI    'A'    ;RANGE?
  2950.     JC    WHAT
  2951.     CPI    'F'+1    ;RANGE?
  2952.     JNC    WHAT
  2953.     SUI    7    ;ADJUST FROM A-F TO 10-15
  2954. ;
  2955. HINNUM:
  2956.     SUI    '0'    ;CONVERT FROM ASCII TO BINARY
  2957.     XCHG
  2958.     DAD    H    ;MULT PREVIOUS VALUE BY 16
  2959.     DAD    H
  2960.     DAD    H
  2961.     DAD    H
  2962.     ADD    L    ;ADD IN NEW DIGIT
  2963.     MOV    L,A
  2964.     XCHG
  2965.     JR    HINLP
  2966. ;
  2967. HDIN:
  2968.     INX    H    ;SKIP '.'
  2969. ;
  2970. ;Input Number in Command Line as Decimal
  2971. ;  Number is returned in DE
  2972. ;
  2973. DECIN:
  2974.     LXI    D,0
  2975.     MOV    A,M    ; GET 1ST CHAR
  2976.     CPI    '#'    ; HEX?
  2977.     JRNZ    DINLP
  2978.     INX    H    ; PT TO DIGIT
  2979.     JR    HINLP    ; DO HEX PROCESSING
  2980. ;
  2981. DINLP:
  2982.     MOV    A,M    ;GET DIGIT
  2983.     CALL    UPCASE    ;CAPITALIZE
  2984.     CPI    '0'    ;RANGE?
  2985.     RC
  2986.     CPI    '9'+1    ;RANGE?
  2987.     RNC
  2988.     SUI    '0'    ;CONVERT TO BINARY
  2989.     INX    H    ;PT TO NEXT
  2990.     PUSH    H
  2991.     MOV    H,D
  2992.     MOV    L,E
  2993.     DAD    H    ;X2
  2994.     DAD    H    ;X4
  2995.     DAD    D    ;X5
  2996.     DAD    H    ;X10
  2997.     ADD    L    ;ADD IN DIGIT
  2998.     MOV    L,A
  2999.     MOV    A,H
  3000.     ACI    0
  3001.     MOV    H,A
  3002.     XCHG        ;RESULT IN DE
  3003.     POP    H
  3004.     JR    DINLP
  3005. ;
  3006. ;Read in a console buffer
  3007. ;
  3008. RDBUF:
  3009.     CALL    ILPRT    ;PRINT PROMPT
  3010.     DB    CR,LF,'DU2  ',0
  3011.     LDA    DRIVE    ;GET DRIVE NUMBER
  3012.     ADI    'A'    ;CONVERT TO ASCII
  3013.     CALL    TYPE
  3014.     LDA    UNUM    ;DISPLAY USER NUMBER
  3015.     MOV    L,A    ;VALUE IN HL
  3016.     MVI    H,0
  3017.     CALL    DEC    ;PRINT IN DECIMAL
  3018.     CALL    ILPRT    ;PRINT PROMPT
  3019.     DB    '? ',0
  3020.     LXI    D,INBUF-2    ;USE CP/M READLN
  3021.     MVI    C,10
  3022.     CALL    BDOS
  3023.     LDA    INBUF-1    ;GET CHAR COUNT
  3024.     MOV    B,A    ;CHAR COUNT IN B
  3025.     LXI    H,INBUF    ;STORE ENDING <CR>
  3026.     ADD    L    ;ADD CHAR COUNT TO HL
  3027.     MOV    L,A
  3028.     MOV    A,H
  3029.     ACI    0
  3030.     MOV    H,A
  3031.     MVI    A,CR    ;STORE ENDING <CR>
  3032.     MOV    M,A    ;SAVE IT
  3033.     CALL    TYPE    ;ECHO IT
  3034.     MVI    A,LF    ;ECHO..
  3035.     CALL    TYPE    ;..LF
  3036.     LXI    H,INBUF    ;SET PTR TO FIRST CHAR IN LINE
  3037.     RET
  3038. ;
  3039. ;Set paging flag for page routine
  3040. ;
  3041. PAGSET:
  3042.     LDA    PAGSIZ    ;GET SIZE OF PAGE
  3043.     STA    PAGFLG    ;SET FLAG
  3044.     RET
  3045. ;
  3046. ;Page output
  3047. ;
  3048. PAGER:
  3049.     LDA    PAGFLG    ;GET FLAG
  3050.     CPI    2    ;2 LINES LEFT?
  3051.     JRZ    WAIT    ;SAME AS USER DELAY
  3052.     DCR    A    ;COUNT DOWN
  3053.     STA    PAGFLG
  3054.     JMP    CRLF
  3055. ;
  3056. ;Delay Routine
  3057. ;
  3058. WAIT:
  3059.     PUSH    H
  3060.     CALL    ILPRT
  3061.     DB    CR,LF,'Type Any Character to Continue or ^C to Abort - ',0
  3062.     POP    H
  3063.     CALL    CONIN    ;GET RESPONSE
  3064.     CPI    'C'-40H    ;^C?
  3065.     JRZ    WAIT1
  3066.     CALL    CRLF    ;NEW LINE
  3067.     CALL    PAGSET    ;RESET PAGE COUNT
  3068.     RET
  3069. WAIT1:
  3070.     LDA    IHFLG    ;INITIAL HELP?
  3071.     ORA    A    ;0=NO
  3072.     JZ    PRMPTR    ;ABORT TO COMMAND PROMPT
  3073.     JMP    EXIT1    ;ABORT TO CP/M
  3074. ;
  3075. ;CRLF Routine
  3076. ;
  3077. CRLF:
  3078.     MVI    A,CR
  3079.     CALL    TYPE
  3080.     MVI    A,LF
  3081.     JMP    TYPE
  3082. ;
  3083. ;Convert to Upper Case
  3084. ;
  3085. UPCASE:
  3086.     ANI    7FH    ;MASK OUT MSB
  3087.     CPI    60H    ;LESS THAN SMALL A?
  3088.     RC        ;RETURN IF SO
  3089.     ANI    5FH    ;MAKE UPPER CASE
  3090.     RET
  3091. ;
  3092. ;CON: Status Routine
  3093. ;
  3094. CONST:
  3095.     PUSH    B
  3096.     PUSH    D
  3097.     PUSH    H
  3098. VCONST:
  3099.     CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3100.     POP    H
  3101.     POP    D
  3102.     POP    B
  3103.     RET
  3104. ;
  3105. ;CON: Input Routine
  3106. ;
  3107. CONIN:
  3108.     PUSH    B
  3109.     PUSH    D
  3110.     PUSH    H
  3111. VCONIN:
  3112.     CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3113.     POP    H
  3114.     POP    D
  3115.     POP    B
  3116.     RET
  3117. ;
  3118. ;Console out with TAB expansion
  3119. ;  Char in A
  3120. ;
  3121. TYPE:
  3122.     PUSH    B    ;SAVE REGS
  3123.     PUSH    D
  3124.     PUSH    H
  3125.     MOV    C,A    ;FOR OUTPUT ROUTINE
  3126.     CPI    TAB
  3127.     JRNZ    TYPE2
  3128. ;Tabulate
  3129. TYPTAB:
  3130.     MVI    A,' '    ;PRINT SPACE
  3131.     CALL    TYPE
  3132.     LDA    TABCOL    ;GET COL COUNT
  3133.     ANI    7    ;DONE?
  3134.     JRNZ    TYPTAB
  3135.     JR    TYPRET
  3136. ;
  3137. ;Filter out control characters to
  3138. ;prevent garbage during view of file
  3139. ;
  3140. TYPE2:
  3141.     CPI    ' '
  3142.     JRNC    TYPEQ
  3143.     CPI    CR
  3144.     JRZ    TYPEQ
  3145.     CPI    LF
  3146.     JRNZ    TYPNCR
  3147. ;
  3148. TYPEQ:
  3149. ;
  3150. ;CON: Output Routine
  3151. ;
  3152. VCONOT:    CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3153. ;
  3154. ;Update column used in tab expansion
  3155. ;
  3156.     MOV    A,C    ;GET CHAR
  3157.     CPI    CR
  3158.     JRNZ    TYPNCR
  3159.     MVI    A,0    ;RESET TAB COLUMN IF <CR>
  3160.     STA    TABCOL
  3161.     JR    TYPLST
  3162. ;
  3163. TYPNCR:
  3164.     CPI    ' '    ;CTL CHAR?
  3165.     JRC    TYPLST    ;..NO CHANGE IN COL
  3166.     LDA    TABCOL    ;INCR TAB COUNT
  3167.     INR    A
  3168.     STA    TABCOL
  3169. ;
  3170. TYPLST:
  3171.     LDA    PFLAG    ;CHECK FOR PRINTER OUTPUT
  3172.     ANI    1
  3173.     CNZ    LIST    ;FROM C REG
  3174. ;
  3175. TYPRET:
  3176.     POP    H    ;RESTORE REGS
  3177.     POP    D
  3178.     POP    B
  3179.     RET
  3180. ;
  3181. ;LST: Output Routine
  3182. ;  Char in C
  3183. ;
  3184. LIST:
  3185.     PUSH    B    ;SAVED REGS
  3186.     PUSH    D
  3187.     PUSH    H
  3188. VLIST:
  3189.     CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3190.     POP    H
  3191.     POP    D
  3192.     POP    B
  3193.     RET
  3194. ;
  3195. ;Home Disk Routine
  3196. ;
  3197. HOME:
  3198.     PUSH    H
  3199. VHOME:
  3200.     CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3201.     POP    H
  3202.     RET
  3203. ;
  3204. ;Set track # in DE
  3205. ;
  3206. SETTRK:
  3207.     PUSH    H
  3208.     LHLD    MAXTRK    ;CHECK FOR WITHIN BOUNDS
  3209.     CALL    SUBDE    ;IF TRACK # IN DE > MAX, THEN ERROR
  3210.     POP    H
  3211.     JC    OUTLIM
  3212.     XCHG        ;RESET CURRENT TRACK
  3213.     SHLD    CURTRK
  3214.     XCHG
  3215.     MOV    B,D    ;BC=TRACK NUMBER
  3216.     MOV    C,E
  3217.     PUSH    H
  3218. ;
  3219. VSETRK:
  3220.     CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3221.     POP    H
  3222.     RET
  3223. ;
  3224. ;Set Sector Number in DE
  3225. ;
  3226. SETSEC:
  3227.     PUSH    H
  3228.     PUSH    D
  3229.     LHLD    SYSTRK    ;GET NUMBER OF SYSTEM TRACKS
  3230.     XCHG
  3231.     SHLD    CURSEC    ;SET CURRENT SECTOR
  3232.     LHLD    CURTRK    ;GET CURRENT TRACK
  3233.     CALL    SUBDE    ;SEE IF WE ARE IN THE SYSTEM TRACKS
  3234.     POP    B    ;BC=SECTOR NUMBER
  3235.     MOV    H,B    ;HL=SECTOR NUMBER
  3236.     MOV    L,C
  3237.     JRNC    NOTSYS    ;IF NO CARRY FOR SUBDE, WE ARE NOT IN SYSTEM TRACKS
  3238.     LDA    FIRST0    ;SEE IF FIRST SEC 0
  3239.     ORA    A
  3240.     JRNZ    GSTSEC    ;NO, JUMP AWAY
  3241.     DCX    H    ;YES, SO DECREMENT
  3242.     JR    GSTSEC    ;REQUESTED, THEN GO
  3243. ;
  3244. ;Not in System Tracks, so Skew Factor is effective
  3245. ;
  3246. NOTSYS:
  3247.     LHLD    SECTBL    ;GET PTR TO SECTOR TABLE
  3248.     XCHG        ;... IN DE
  3249.     DCX    B    ;DECREMENT SECTOR NUMBER BY 1
  3250. ;
  3251. VSCTRN:
  3252.     CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3253.     LDA    SPT+1    ;IF SPT<256 (HI-ORD = 0)
  3254.     ORA    A    ; THEN FORCE 8-BIT TRANSLATION
  3255.     JRNZ    GSTSEC    ; ELSE KEEP ALL 16 BITS
  3256.     MOV    H,A
  3257. GSTSEC:
  3258.     SHLD    PHYSEC
  3259.     MOV    B,H
  3260.     MOV    C,L
  3261. ;
  3262. VSTSEC:
  3263.     CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3264.     POP    H    ;RESTORE PTR TO NEXT CHAR
  3265.     RET
  3266. ;
  3267. ;Out of Disk Track Limit
  3268. ;
  3269. OUTLIM:
  3270.     CALL    ILPRT
  3271.     DB    '++ Not Within Tracks 0-',0
  3272.     PUSH    H
  3273.     LHLD    MAXTRK    ;PRINT MAX TRACK NUMBER
  3274.     CALL    DEC
  3275.     POP    H
  3276.     CALL    ILPRT
  3277.     DB    ' ++',CR,LF,0
  3278.     CALL    NORITE    ;NOT POSITIONED
  3279.     JMP    PRMPTR
  3280. ;
  3281. ;Set DMA Address
  3282. ;
  3283. SETDMA:
  3284.     JMP    $-$    ;ADDR FILLED IN BY 'INIT'
  3285. ;
  3286. ;Read Next Block into DMA Address
  3287. ;
  3288. READ:
  3289.     MVI    A,1    ;SET FLAG
  3290.     STA    WRFLG
  3291.     PUSH    H    ;SAVE PTR TO NEXT CHAR
  3292. ;
  3293. VREAD:
  3294.     CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3295.     ORA    A    ;ERROR?
  3296.     JRZ    READOK
  3297.     CALL    ILPRT
  3298.     DB    '++ READ Failed, Sector may be Invalid ++'
  3299.     DB    CR,LF,0
  3300. ;
  3301. READOK:
  3302.     POP    H    ;GET PTR TO NEXT CHAR
  3303.     RET
  3304. ;
  3305. ;Write Block in DMA Address to Disk
  3306. ;
  3307. WRITE:
  3308.     LDA    WRFLG    ;READ ALREADY PERFORMED?
  3309.     ORA    A    ;ERROR IF NOT
  3310.     JRNZ    PWRITE
  3311. ;
  3312. BADW:
  3313.     CALL    ILPRT
  3314.     DB    '++ Cannot Write Unless Read Issued ++'
  3315.     DB    CR,LF,0
  3316.     JMP    EXPL
  3317. ;
  3318. ;Do Write
  3319. ;
  3320. PWRITE:
  3321.     PUSH    H    ;SAVE PTR TO NEXT CHAR
  3322.     MVI    C,1    ;FORCE WRITE TYPE 1 IN CASE 2.x DEBLOCK USED
  3323. ;
  3324. VWRITE:
  3325.     CALL    $-$    ;ADDR FILLED IN BY 'INIT'
  3326.     ORA    A    ;ERROR?
  3327.     JRZ    WRITOK
  3328.     CALL    ILPRT
  3329.     DB    '++ WRITE Failed ++',CR,LF,0
  3330. ;
  3331. WRITOK:
  3332.     POP    H
  3333.     RET
  3334. ;
  3335. ;Help; HELP is entry point for HELP (?) command, HELP1 is entry point for
  3336. ; Initial Help Command, and IHELP is entry point for HELP (/) from command
  3337. ; line
  3338. ;
  3339. IHELP:
  3340.     CALL    ILPRT
  3341.     DB    'Introductory HELP on DU2 (Disk Utility)',CR,LF
  3342.     DB    '  The DU2 program is designed to provide the user with'
  3343.     DB    CR,LF
  3344.     DB    'the ability to manipulate information on the disk as easily'
  3345.     DB    CR,LF
  3346.     DB    'as the DDT and SID utilities allow the user to manipulate'
  3347.     DB    CR,LF
  3348.     DB    'information in memory.',CR,LF
  3349.     DB    '  The following is a summary of the commands available to'
  3350.     DB    CR,LF
  3351.     DB    'the DU2 user.  This same list is invoked internally by the'
  3352.     DB    CR,LF
  3353.     DB    '? Command of DU2.  For additional information on disk'
  3354.     DB    CR,LF
  3355.     DB    'structures and how to use DU2 in general, refer to the'
  3356.     DB    CR,LF
  3357.     DB    'files DU2.DOC and DU2.HLP.',CR,LF,0
  3358.     MVI    A,0FFH    ;A=0FFH
  3359.     STA    IHFLG    ;SET INITIAL HELP
  3360.     CALL    WAIT
  3361.     JR    HELP1    ;PROCESS NORMALLY
  3362. HELP:
  3363.     XRA    A    ;A=0
  3364.     STA    IHFLG    ;SET NO INITIAL HELP
  3365. HELP1:
  3366.     CALL    ILPRT
  3367.     DB    '=======================================================',CR,LF
  3368.     DB    '           -- Command Summary --        ',CR,LF
  3369.     DB    '-------------------------------------------------------',CR,LF
  3370.     DB    CR,LF
  3371.     DB    'Operands in brackets [...] are optional'
  3372.     DB    CR,LF,CR,LF
  3373.     DB    '@    Repeat Previous Non-@ Command Line'
  3374.     DB    CR,LF
  3375.     DB    '+[nn]    Step In [nn (decimal)] Sectors;    -[nn]  Step Out '
  3376.     DB    'Sectors'
  3377.     DB    CR,LF
  3378.     DB    '    Note:  + or - need not be followed by a "," to '
  3379.     DB    'delimit commands.'
  3380.     DB    CR,LF
  3381.     DB    '#    Print Disk Parameters for Current Drive'
  3382.     DB    CR,LF
  3383.     DB    '=xxx    Search for ASCII xxx from Current Sector'
  3384.     DB    CR,LF
  3385.     DB    '    Note:  upper/lower case matters.  Use <xx> for hex:'
  3386.     DB    CR,LF
  3387.     DB    '      To find "IN 0" use: =<db><0>     or'
  3388.     DB    CR,LF
  3389.     DB    '      "(tab)H,0(CR)(LF)" use: =<9>H,0<D><A>'
  3390.     DB    CR,LF
  3391.     DB    '*[nn]    Repeat [nn (decimal) times];    !    Pause for User'
  3392.     DB    CR,LF
  3393.     DB    ':ntext    Define ''text'' to be Macro n;    n    Perform Macro'
  3394.     DB    ' n, 0<=n<=9'
  3395.     DB    CR,LF
  3396.     DB    ':Pn    Print Macro n, 0<=n<=9'
  3397.     DB    CR,LF
  3398.     DB    ':Px    Print All Macros if x=A or Print Prev Line if x=@'
  3399.     DB    CR,LF,CR,LF,0
  3400.     CALL    WAIT
  3401.     CALL    ILPRT
  3402.     DB    '-------------------------------------------------------',CR,LF
  3403.     DB    'A[ff,tt]    ASCII Dump'
  3404.     DB    CR,LF
  3405.     DB    'C    Change:'
  3406.     DB    CR,LF
  3407.     DB    '     CHaddr byte byte... (hex)'
  3408.     DB    CR,LF
  3409.     DB    '     or CAaddr data...  (Ascii)'
  3410.     DB    CR,LF
  3411.     DB    '         <xx> Allowed for imbedded hex.'
  3412.     DB    CR,LF
  3413.     DB    '     or CHfrom-thru byte  e.g. ch0-7f,e5'
  3414.     DB    CR,LF
  3415.     DB    '     or CAfrom-thru byte'
  3416.     DB    CR,LF
  3417.     DB    'D[ff,tt]    Dump (Hex and ASCII)'
  3418.     DB    CR,LF
  3419.     DB    'Ffn.ft    Find File'
  3420.     DB    CR,LF
  3421.     DB    'Gnn    CP/M Allocation Group nn (hex)'
  3422.     DB    CR,LF
  3423.     DB    'H[ff,tt]    Hex Dump'
  3424.     DB    CR,LF
  3425.     DB    'L[d]    Log in Current Drive or Drive d'
  3426.     DB    CR,LF
  3427.     DB    'M[nn]    Map [from group nn (hex)]'
  3428.     DB    CR,LF,CR,LF,0
  3429.     CALL    WAIT
  3430.     CALL    ILPRT
  3431.     DB    '-------------------------------------------------------',CR,LF
  3432.     DB    CR,LF
  3433.     DB    'N    Load New Disk;    P    Toggle Printer Switch'
  3434.     DB    CR,LF
  3435.     DB    'Q    Queue Status;    QZ    Zero (Empty) Queue'
  3436.     DB    CR,LF
  3437.     DB    'QSfn.ft Save Queue as a File on Disk'
  3438.     DB    CR,LF
  3439.     DB    '<    Save Current Block into Temp;    >    Restore Temp '
  3440.     DB    'Block'
  3441.     DB    CR,LF
  3442.     DB    '<B    Save Block into Queue;        >B    Restore Queue '
  3443.     DB    'Block'
  3444.     DB    CR,LF
  3445.     DB    '<G[n]    Save Group into Queue;        >G[n]    Restore Queue '
  3446.     DB    'Group'
  3447.     DB    CR,LF
  3448.     DB    'Snn    Sector nn (decimal)'
  3449.     DB    CR,LF
  3450.     DB    'Tnn    Track nn (decimal)'
  3451.     DB    CR,LF
  3452.     DB    'Unn    Set User nn (decimal) for Find command (CP/M-2 only)'
  3453.     DB    CR,LF
  3454.     DB    'V[nn]    View [nn (decimal)] ASCII Blocks'
  3455.     DB    CR,LF
  3456.     DB    'R    Read Current Block;    W    Write Current Block'
  3457.     DB    CR,LF
  3458.     DB    'X    Exit Program'
  3459.     DB    CR,LF
  3460.     DB    'Z[nn]    Sleep [nn (decimal) seconds]'
  3461.     DB    CR,LF,CR,LF,0
  3462.     CALL    WAIT
  3463.     CALL    ILPRT
  3464.     DB    '-------------------------------------------------------',CR,LF
  3465.     DB    CR,LF
  3466.     DB    'Command Line is of the form:  DU2 du?',CR,LF
  3467.     DB    '    "d" is Logged-In Disk, "u" is Current User',CR,LF
  3468.     DB    CR,LF
  3469.     DB    'Cancel a function with C or Ctrl-C.'
  3470.     DB    CR,LF
  3471.     DB    'Suspend output with S or Ctrl-S.'
  3472.     DB    CR,LF
  3473.     DB    'Separate commands with ",".'
  3474.     DB    CR,LF
  3475.     DB    '    Example: g0'
  3476.     DB    CR,LF
  3477.     DB    '    +,d,z2,*'
  3478.     DB    CR,LF
  3479.     DB    '     would step in, dump, sleep 2 sec, '
  3480.     DB    CR,LF
  3481.     DB    '     and repeat until control-c typed.'
  3482.     DB    CR,LF
  3483.     DB    '"nn" usage varies with command as follows:',CR,LF
  3484.     DB    '    +, -, *, T, S, U, V, Z    nn in Decimal',CR,LF
  3485.     DB    '                (use #nn for Hex)',CR,LF
  3486.     DB    '    G, M            nn in Hexadecimal',CR,LF
  3487.     DB    '                (use #nn for Decimal)'
  3488.     DB    CR,LF
  3489.     DB    '"ff" and "tt" are in Hexadecimal (use #ff or #tt for Decimal)'
  3490.     DB    CR,LF,CR,LF
  3491.     DB    '=======================================================',CR,LF
  3492.     DB    0
  3493.     CALL    WAIT
  3494.     CALL    ILPRT
  3495.     DB    '=======================================================',CR,LF
  3496.     DB    'DU2 Status Information',CR,LF
  3497.     DB    '-------------------------------------------------------',CR,LF
  3498.     DB    'Processor Speed:  ',0
  3499.     LDA    CLOCK    ;GET CLOCK SPEED
  3500.     ADI    '0'    ;CONVERT TO ASCII
  3501.     CALL    TYPE    ;PRINT
  3502.     CALL    ILPRT
  3503.     DB    ' MHz',CR,LF
  3504.     DB    'Number of Lines on CON:  ',0
  3505.     LDA    PAGSIZ    ;GET PAGE SIZE
  3506.     MOV    L,A    ;NUMBER IN HL
  3507.     MVI    H,0
  3508.     CALL    DEC    ;PRINT NUMBER IN DECIMAL
  3509.     CALL    ILPRT
  3510.     DB    CR,LF,'Group Save Buffer Address:  ',0
  3511.     LXI    B,GBUFF    ;BC=ADDRESS
  3512.     CALL    HEXB    ;PRINT AS HEX
  3513.     CALL    ILPRT
  3514.     DB    ' Hex',CR,LF
  3515.     DB    '=======================================================',CR,LF
  3516.     DB    0
  3517.     LDA    IHFLG    ;INITIAL HELP?
  3518.     ORA    A    ;0=NO
  3519.     JRNZ    EXIT1    ;RETURN TO CP/M IF SO
  3520.     JMP    PRMPTR    ;NEW LINE INPUT IF NOT
  3521. ;
  3522. ;COMMAND:  X
  3523. ;Exit to CP/M
  3524. ;
  3525. EXIT:
  3526.     CALL    ILPRT    ;PRINT
  3527.     DB    CR,LF,'Exit to CP/M -- Do you wish to Warm Boot (Y/N/<CR>=N)?'
  3528.     DB    ' ',0
  3529.     CALL    CONIN    ;GET RESPONSE
  3530.     CALL    UPCASE    ;CAPITALIZE
  3531.     CPI    'Y'    ;YES?
  3532.     JZ    BASE    ;WARM BOOT IF SO
  3533. ;
  3534. ;Quick Exit to CP/M
  3535. ;
  3536. EXIT1:
  3537.     LHLD    DUTSTK    ;GET CP/M STACK PTR
  3538.     SPHL        ;SET SP
  3539.     RET
  3540.  
  3541. ;
  3542. ;********************************
  3543. ;*                *
  3544. ;*    Utility Subroutines    *
  3545. ;*                *
  3546. ;********************************
  3547. ;
  3548. GRPCMP:
  3549.     MOV    A,C
  3550.     INR    D
  3551.     DCR    D
  3552.     JRZ    CMP8
  3553.     CMP    M
  3554.     INX    H
  3555.     RNZ
  3556.     MOV    A,B
  3557. ;
  3558. CMP8:
  3559.     CMP    M
  3560.     RET
  3561. ;
  3562. ;2's complement HL ==> HL
  3563. ;
  3564. NEG:
  3565.     MOV    A,L
  3566.     CMA
  3567.     MOV    L,A
  3568.     MOV    A,H
  3569.     CMA
  3570.     MOV    H,A
  3571.     INX    H
  3572.     RET
  3573. ;
  3574. ;HL/2 ==> HL
  3575. ;
  3576. ROTRHL:
  3577.     ORA    A
  3578.     MOV    A,H
  3579.     RAR
  3580.     MOV    H,A
  3581.     MOV    A,L
  3582.     RAR
  3583.     MOV    L,A
  3584.     RET
  3585. ;
  3586. ;Collect the number of '1' bits
  3587. ;in A as a count in C
  3588. ;
  3589. COLECT:
  3590.     MVI    B,8    ;NUMBER OF BITS
  3591. ;
  3592. COLOP:
  3593.     RAL
  3594.     JRNC    COSKIP
  3595.     INR    C
  3596. ;
  3597. COSKIP:
  3598.     DCR    B
  3599.     JRNZ    COLOP
  3600.     RET
  3601. ;
  3602. ;HL-DE ==> HL
  3603. ;  Carry Flag is Significant
  3604. ;
  3605. SUBDE:
  3606.     MOV    A,L
  3607.     SUB    E
  3608.     MOV    L,A
  3609.     MOV    A,H
  3610.     SBB    D
  3611.     MOV    H,A
  3612.     RET
  3613. ;
  3614. ;Quick Kludge multiply
  3615. ;HL*DE ==> HL
  3616. ;
  3617. MULT:
  3618.     PUSH    B
  3619.     PUSH    D
  3620.     XCHG
  3621.     MOV    B,D
  3622.     MOV    C,E
  3623.     MOV    A,B
  3624.     ORA    C
  3625.     JRNZ    MULCON
  3626.     LXI    H,0    ;FILTER SPECIAL CASE
  3627.     JR    MLDONE    ;  OF MULTIPLY BY 0
  3628. ;
  3629. MULCON:
  3630.     DCX    B
  3631.     MOV    D,H
  3632.     MOV    E,L
  3633. ;
  3634. MULTLP:
  3635.     MOV    A,B
  3636.     ORA    C
  3637.     JRZ    MLDONE
  3638.     DAD    D
  3639.     DCX    B
  3640.     JR    MULTLP
  3641. ;
  3642. MLDONE:
  3643.     POP    D
  3644.     POP    B
  3645.     RET
  3646. ;
  3647. ;Routine to fill in disk params
  3648. ;with every drive change
  3649. ;
  3650. LOGIT:
  3651.     LXI    D,DPB    ;   THEN MOVE TO LOCAL
  3652.     MVI    B,DPBLEN ;  WORKSPACE
  3653.     CALL    MOVE
  3654.     LXI    H,GRPDIS
  3655.     MOV    A,M
  3656.     PUSH    PSW
  3657.     LDA    BLM
  3658.     MOV    M,A
  3659.     PUSH    H
  3660.     LHLD    DSM
  3661.     XCHG
  3662.     CALL    GTKSEC
  3663.     SHLD    MAXSEC
  3664.     XCHG
  3665.     SHLD    MAXTRK
  3666.     POP    H
  3667.     POP    PSW
  3668.     MOV    M,A
  3669.     RET
  3670.  
  3671. ;***********************************
  3672. ;
  3673. ;  DU2 Command Table
  3674. ;
  3675. ;***********************************
  3676. CMDTBL:
  3677.     DB    ':'
  3678.     DW    MAC
  3679. ;
  3680.     DB    '@'
  3681.     DW    PCMD
  3682. ;
  3683.     DB    '+'    
  3684.     DW     PLUS
  3685. ;
  3686.     DB    '-'
  3687.     DW    MINUS
  3688. ;
  3689.     DB    '='
  3690.     DW    SEARCH
  3691. ;
  3692.     DB    '<'
  3693.     DW    SAVE
  3694. ;
  3695.     DB    '>'
  3696.     DW    RESTOR
  3697. ;
  3698.     DB    '#'
  3699.     DW    STATS
  3700. ;
  3701.     DB    '?'
  3702.     DW    HELP
  3703. ;
  3704.     DB    MULCH
  3705.     DW    REPEAT
  3706. ;
  3707.     DB    '!'
  3708.     DW    UWAIT
  3709. ;
  3710.     DB    'A'
  3711.     DW    DUMP
  3712. ;
  3713.     DB    'C'
  3714.     DW    CHG
  3715. ;
  3716.     DB    'D'
  3717.     DW    DUMP
  3718. ;
  3719.     DB    'F'
  3720.     DW    POSFIL
  3721. ;
  3722.     DB    'G'
  3723.     DW    POS
  3724. ;
  3725.     DB    'H'
  3726.     DW    DUMP
  3727. ;
  3728.     DB    'L'
  3729.     DW    LOGIN
  3730. ;
  3731.     DB    'M'
  3732.     DW    MAP
  3733. ;
  3734.     DB    'N'
  3735.     DW    NEWDSK
  3736. ;
  3737.     DB    'P'
  3738.     DW    PRNTFF
  3739. ;
  3740.     DB    'Q'
  3741.     DW    QUEUER
  3742. ;
  3743.     DB    'R'
  3744.     DW    DOREAD
  3745. ;
  3746.     DB    'S'
  3747.     DW    POS
  3748. ;
  3749.     DB    'T'
  3750.     DW    POS
  3751. ;
  3752.     DB    'U'    ;******CP/M 2.x ONLY******
  3753.     DW    USER
  3754. ;
  3755.     DB    'V'
  3756.     DW    VIEW
  3757. ;
  3758.     DB    'W'
  3759.     DW    DORITE
  3760. ;
  3761.     DB    'X'
  3762.     DW    EXIT
  3763. ;
  3764.     DB    'Z'
  3765.     DW    SLEEP
  3766. ;
  3767.     DB    0    ; End of Table
  3768. ;*************************************
  3769.  
  3770. ;
  3771. ;Temporary storage area
  3772. ;
  3773.     DS    100    ;50-ELT STACK
  3774. DUTSTK:
  3775.     DS    2    ;OLD CP/M STACK POINTER; TOP OF DU2 STACK
  3776. BUFAD:
  3777.     DS    2    ;FORCES INITIAL READ
  3778. QCNT:
  3779.     DS    2    ;NUMBER OF SECTORS IN QUEUE
  3780. QNXT:
  3781.     DS    2    ;PTR TO NEXT SECTOR IN QUEUE
  3782. QLST:
  3783.     DS    2    ;PTR TO LAST SECTOR IN QUEUE
  3784. QPTR:
  3785.     DS    2    ;G-P QUEUE PTR
  3786. HEXAD:
  3787.     DS    2    ;TO RE-FETCH A VALUE
  3788. TOGO:
  3789.     DS    2    ;REPEAT COUNT (FFFF=CONT)
  3790. TWOUP:
  3791.     DS    1
  3792. UNUM:
  3793.     DS    1    ;NUMBER OF CURRENT USER
  3794. ONLY1:
  3795.     DS    1    ;FLAG TO PRINT ONLY 1 MAP ENTRY (0=NO)
  3796. MFPTR:
  3797.     DS    2    ;MULTI FILE PTR FOR GETGRP
  3798. PAGFLG:
  3799.     DS    1    ;LINE COUNTER FOR PAGING
  3800. PFLAG:
  3801.     DS    1    ;1=PRINT
  3802. GROUP:
  3803.     DS    2    ;GROUP NUMBER
  3804. GRPDIS:
  3805.     DS    1    ;DISPLACEMENT INTO GROUP
  3806. SAVEFL:
  3807.     DS    1    ;SAVE FLAG
  3808. CURTRK:
  3809.     DS    2    ;CURRENT TRACK NUMBER
  3810. CURSEC:
  3811.     DS    2    ;CURRENT SECTOR NUMBER
  3812. PHYSEC:
  3813.     DS    2    ;CURRENT PHYSICAL SECTOR NUMBER
  3814. TABCOL:
  3815.     DS    1    ;TAB COLUMN
  3816. CPYFCT:
  3817.     DS    1    ;GROUP COPY FUNCTION; 0=READ, 0FFH=WRITE
  3818. FILECT:
  3819.     DS    2    ;FILE COUNT
  3820. DIRPOS:
  3821.     DS    1    ;POSITION IN DIRECTORY
  3822. FINDFL:
  3823.     DS    1    ;1=MUST POSITION AFTER FIND
  3824. FTSW:
  3825.     DS    1    ;SEARCH W/O INCREMENT
  3826. NOTPOS:
  3827.     DS    1    ;INITIALLY NOT POSITIONED
  3828. WRFLG:
  3829.     DS    1    ;MAY NOT WRITE UNTIL '+', '-',
  3830. ;             OR 'G' COMMAND
  3831. TGRP:
  3832.     DS    2    ;TEMPORARY GROUP FLAG
  3833. FIRST0:
  3834.     DS    1    ;SETS TO 0 IF FIRST SEC # IS 0
  3835. DRIVE:
  3836.     DS    1    ;DRIVE NUMBER
  3837. MAXTRK:
  3838.     DS    2    ;MAX TRACK NUMBER
  3839. MAXSEC:
  3840.     DS    2    ;MAX SECTOR NUMBER
  3841. SECTBL:
  3842.     DS    2    ;POINTER TO SECTOR SKEW TABLE
  3843. ;
  3844. IHFLG:
  3845.     DS    1    ;0=NOT AT INITIAL HELP, 0FFH=AT INITIAL HELP
  3846. DUPFLG:
  3847.     DS    1    ;SPACE OR STAR TO INDICATE MULTIPLE USERS
  3848. BACK:
  3849.     DS    2    ;TO BACK UP IN "CA0-7F,X"
  3850. DUMTYP:
  3851.     DS    1
  3852. ;
  3853. ;The disk parameter block
  3854. ;is moved here from CP/M
  3855. ;
  3856. DPB    EQU    $    ;DISK PARAMETER BLOCK (COPY)
  3857. SPT:
  3858.     DS    2
  3859. BSH:
  3860.     DS    1
  3861. BLM:
  3862.     DS    1
  3863. EXM:
  3864.     DS    1
  3865. DSM:
  3866.     DS    2
  3867. DRM:
  3868.     DS    2
  3869. AL0:
  3870.     DS    1
  3871. AL1:
  3872.     DS    1
  3873. CKS:
  3874.     DS    2
  3875. SYSTRK:
  3876.     DS    2
  3877. ;
  3878. ;End of disk parameter block
  3879. ;
  3880. SAVBUF:
  3881.     DS    128+2+2
  3882. ;
  3883. ;Set INBUF to a Page Boundary
  3884. ;
  3885.     ORG    $/100H*100H+100H-2
  3886.     DB    126    ; SIZE OF BUFFER FOR CP/M
  3887.     DS    1
  3888. INBUF:
  3889.     DS    400H    ;EXTRA SPACE FOR MACRO EXPANSION
  3890. PINBUF:
  3891.     DS    400H    ;PREVIOUS CONTENTS OF INPUT BUFFER
  3892. CTEMP:
  3893.     DS    400H    ;BUILD NEW COMMAND LINE BUFFER
  3894. CTEMPX    EQU    $    ;END OF CTEMP
  3895. ;
  3896. ;Directory read in here; also loaded group area and Macros
  3897. ;
  3898. MTABL:    DS    100H*10            ;10 PAGES FOR 10 MACROS
  3899. GBUFF    EQU    $
  3900. DIRECT    EQU    $
  3901. ;
  3902.     END
  3903.