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