home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols100 / vol151 / dsk7-rb3.asm < prev    next >
Encoding:
Assembly Source File  |  1994-07-13  |  64.1 KB  |  2,473 lines

  1. ; title 'disk7 -- cp/m file manipulation program'
  2.  
  3. VERS    EQU    7$6        ;version number..
  4. MONTH    EQU    08        ;..month..
  5. DAY    EQU    25        ;..day..
  6. YEAR    EQU    83        ;..and year.
  7.  
  8. ; copyright (c) 1983 by frank gaude'.  all rights reserved.  released to the
  9. ; public domain for non-commercial use.  monetary gain in not permitted under
  10. ; any circumstance by individual, partnership, or corporation.
  11.  
  12. ; 'disk7' is based on common ideas presented in 'cleanup', 'wash', and 
  13. ; 'sweep', written by ward christensen, michael karas, and robert fisher, 
  14. ; respectively. existence of these programs generated impetus for writing 
  15. ; 'disk7'.
  16.  
  17. ; a single-screen menu is provided after entering 'disk7' followed by cursor
  18. ; return.  wildcard filenames and optional drive declaration are permitted.
  19. ; disk7 [d:]*.asm shows only 'asm' files on [selected] or current drive.
  20. ; any other than a command key causes the menu to reappear.  full error
  21. ; trapping and command cancellation recovery is provided.  cancellation 
  22. ; occurs by entering a <return>, if no other entry has been made and 
  23. ; execution has not begun.
  24.  
  25. ; display is circular, single-file columnar, with crt console cursor moved
  26. ; 'forward' with <space> or <return>, and 'reverse' with 'b'.  drive
  27. ; remaining storage in kilobytes is automatically displayed whenever disks
  28. ; are logged-in or menu recalled.  if a user area with no files is logged-in,
  29. ; new drive/user area prompt is presented.
  30.  
  31. ; command functions of 'disk7' are:
  32.  
  33. ;     c - copy file to another drive/user with automatic 'crc' verification.
  34. ;         format is --> to drive/user: 'd[nn]<return>' where 'd' is drive and
  35. ;         'n' is optional user area.  a 'colon' after the drive or user area
  36. ;         is optional.  d, d:, dn, dn:, dnn, dnn: are all valid entries.
  37. ;         (system reset occurs for disk change.)  prompts to erase already
  38. ;         existing file on other drive or in other user area.
  39. ;     d - delete file from disk, prompts for certainty.
  40. ;     f - file size in kilobytes, rounded up to next disk allocation block.
  41. ;     j - jump 'forward' 15 file names.  used to quickly go through lengthy
  42. ;         disk directories.
  43. ;     l - log-in new drive/user for display and reset system for disk 
  44. ;      changes. format is same as 'c' for copy.
  45. ;     m - mass copy of tagged files to another drive/user area.  auto-erase
  46. ;         occurs if file(s) already exist(s).  prompts for desired drive/user
  47. ;         area as with 'c' and 'l'.  mass copy function can be repeated
  48. ;         without re-tagging files.  simply enter 'm' again to copy 
  49. ;      previously tagged files to another drive/user area. 
  50. ;      (entering 'm' without any files tagged causes cursor to move to 
  51. ;      directory beginning.)
  52. ;     p - print tagged text files to cp/m list device (printer), any 
  53. ;      keypress cancels. allows entry of a date/title (up to 30 char),
  54. ;      and first page printed (1-255). Rainbow 100 w/LA50RA printer left
  55. ;         margin program default is 2
  56. ;     r - rename file on current drive, only cp/m convention names permitted.
  57. ;     s - stat of requested drive, shows remaining disk storage in kilobytes.
  58. ;     t - tag file for inclusion for mass copy to another drive/user area.
  59. ;         file remains tagged until either a disk log-in or 'u' is used to
  60. ;         untag it.  a '*' marker is placed on the tagged filename cursor
  61. ;         line as a reminder the file is tagged for mass copy.  tagged file
  62. ;         size is shown, totals accumulated and presented in parentheses.
  63. ;     u - untag file previously tagged for mass copy. 'u' can be used to move
  64. ;         cursor 'forward' for quick untagging of files.  logging-in drive
  65. ;         again with 'l' also quickly untags all files.
  66. ;     v - view text file on console, with pagination and single-line turn-up.
  67. ;         <crtl-x> or <esc> cancels function.  only 'ascii' characters are
  68. ;         processed.
  69. ;     w - write ascii file to cp/m logical punch device, any keypress 
  70. ;      cancels.
  71. ;     x - exit to cp/m (to ccp without rebooting, or optionally warmboot if
  72. ;         program assembled with 'warmboot' equate set true.)  <esc> can be
  73. ;         used also to exit to cp/m.
  74.  
  75. ; 'disk7' is an alternative to 'pip' and 'sweep'.  conveniently, it can be
  76. ; added as a subroutine to application programs that require file 
  77. ; manipulation but without returning to the cp/m operating system. 
  78. ; 'disk7' loads fast and copies files at near theoretical speed using 
  79. ; an 8-bit 'crc' table-driven ccitt recommended routine.  the compact 
  80. ; menu makes operation essentially self-documenting.  the program occupies 
  81. ; approximately 4.5k bytes of memory.
  82.  
  83. ; installation requires setting maximum allowed drive to be logged-in or
  84. ; copied to, and deciding if to warmboot or not on returning to cp/m.  these
  85. ; equate options plus several others are at program 'starting definitions'
  86. ; below.
  87.  
  88. ; disk7 works with cp/m 2.2 only, with 24k or more of ram.  file copy
  89. ; functions are faster with large amounts of ram.
  90.  
  91. ; please report bugs noted or improvements incorporated to frank gaude'
  92. ; at 10925 stonebrook drive, los altos hills, ca 94022.  telephone is
  93. ; 415/941-2219, 6pm to 10pm daily, pacific time.
  94.  
  95. ; latest changes
  96.  
  97. ; 08/25/83  customize for Rainbow 100 video attributes. customize for 
  98. ; LA50RA printer paginated mass print mods. changed ('j') to 15 files.
  99. ; (76c->rb3)  jrf
  100.  
  101. ; 08/19/83  added paginated mass print mods (76c)  jon kleinhans
  102.  
  103. ; 06/30/83  updated menu to reflect new commands.  (76c)  fg
  104.  
  105. ; 06/19/83  tagged file summation displayed right justified.  added new
  106. ; command ('j') to jump forward 22 files.  (76a)  fg
  107.  
  108. ; 06/04/83  added 'ani 7fh' to 'v' read function to force text to ascii.
  109. ; also added 'w' command to output ascii text to cp/m punch device (tnx to
  110. ; bill silvert for recommending these changes).  file size now accumulated
  111. ; as tagged ('t') and presented in parentheses on cursor line.  (76)  fg
  112.  
  113. ; starting definitions
  114.  
  115. TRUE     EQU    0FFH        ;define true and..
  116. FALSE     EQU    0           ;..false.
  117. WARMBOOT EQU    FALSE        ;set true to warmboot on exit
  118. CPM$BASE EQU    0000H        ;cp/m system base..
  119. TPA     EQU    100H        ;..'transient program area' start..
  120. CCP     EQU    800H        ;..and 'ccp' length in bytes.
  121. LPS     EQU    24-2        ;lines-per-screen for 'view' pagination
  122. GET     EQU    0FFH        ;get user area e-reg value
  123.  
  124. ; ascii definitions
  125.  
  126. BELL    EQU    07H        ;ascii bell character..
  127. BS    EQU    08H        ;..backspace..
  128. LF    EQU    0AH        ;..linefeed..
  129. CR    EQU    0DH        ;..carriage return..
  130. CAN    EQU    18H        ;..cancel..
  131. EOFCHAR    EQU    1AH        ;..end-of-file..
  132. ESC    EQU    1BH        ;..and escape character.
  133.  
  134. ;----------------------------------------------
  135. ; DEC Rainbow 100 Equates
  136. ;      clear screen & home    27 [ 2 J 27 [ H
  137. ;      normal video           27 [ 0 m
  138. ;      bold  video            27 [ 1 m
  139. ;      reverse  video         27 [ 7 ; 1 m
  140. ;      reverse blink video    27 [ 7 ; 1 ; 5 m
  141. ;      bold blink video       27 [ 5 ; 1 m
  142. RAIN1    EQU    27
  143. RAIN2    EQU    '['
  144. RAIN3    EQU    '2'
  145. RAIN4    EQU    'J'
  146. RAIN5    EQU    'H'
  147. RAIN6    EQU    '0'
  148. RAIN7    EQU    '1'
  149. RAIN8    EQU    '5'
  150. RAIN9    EQU    '7'
  151. RAIN10    EQU    ';'
  152. RAIN11  EQU     'm'
  153. ;-------------------------------------------------
  154. ; even-page base of filename ring storage
  155.  
  156. RING    SET    LAST+100H AND 0FF00H
  157.  
  158. ; assembly origin (load address) and program beginning
  159.  
  160. SOURCE    ORG    CPM$BASE+TPA
  161.     JMP    DISK7
  162.  
  163. ; highest disk drive letter in system
  164.  
  165. MAXDR    DB    'C'        ; 'a', 'b', 'c', etc.
  166.  
  167. ; concealed copyright notice
  168.  
  169.     DB    ' Copyright (c) 1983 by Frank Gaude'''
  170.     DB    ' All Rights Reserved'
  171. ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  172. ;                Equates for MASS PRINT
  173. ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  174. FF    EQU    0CH        ; form feed
  175. TAB    EQU    09H        ; tab
  176. SPACE    EQU    20H
  177. NULCHR    EQU    00H
  178. ASCBIAS    EQU    30H
  179. ZERO    EQU    00H
  180.  
  181. PAGEWID  EQU    81        ; 0--80 = 81  Rainbow 100 only
  182.  
  183. PAGELEN  EQU    65        ; 0--65 = 66
  184. HOMELINE EQU    3        ; start position of print head on power up.
  185. TOPMRGN  EQU    1        ; blank lines from home position to HEADER.
  186.                 ;    TOPMRGN must be => one
  187. HEADMRGN EQU    2        ; blank lines between HEADER and text.
  188.                 ;    HEADMRGN must be => one
  189. BOTMRGN  EQU    2        ; blank lines between text and end of page.
  190. LASTLINE EQU    PAGELEN-HOMELINE-BOTMRGN
  191.  
  192. ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  193. ;                Storage for MASS PRINT
  194. ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  195. DECDIG    DB    100,10,1
  196. PAGENO    DS    1
  197. LINENO    DS    1
  198. COLNO    DS    1
  199.  
  200. STRTPG    DB    1        ; start page number, initially = 1
  201. STARTED  DB    0FFH        ; started flag is zero after started
  202. LEFTMRGN DB    2               ; default for Rainbow 100 w/LA50RA printer
  203. TABSIZE  DB    8
  204. ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  205. ;                BEGINNING OF PRINTER ROUTINES.    7/28/83
  206. ;    Must change the "P" command to call MASSLST in the command scan.
  207. ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  208.  
  209. MASSLST
  210. ; get date and/or title for header line.
  211.     LXI    H,CMDBUF
  212.     MVI    B,32         ; # of blankes to ..
  213.     CALL    FILL         ; ..clear 'cmdbuf'.
  214.     CALL    BLBLNK
  215.     CALL    ILPRT        ;new name prompt
  216.     DB    CR,LF,'                          '
  217.       DB    ' ..............................',0
  218.     CALL    NORM
  219.     CALL    BOLD
  220.     CALL    ILPRT
  221.     DB    CR,LF,'Date/Title, up to 30 char: ',0
  222.     CALL    NORM
  223.     LXI    D,CMDBUF    ;command line location
  224.     MVI    C,RDBUF        ;console read-buffer function
  225.     CALL    BDOS
  226.  
  227.     LXI    H,PTITLE
  228.     XCHG            ; DE = destination pointer
  229.     LXI    H,CMDBUF+2    ; HL = source pointer
  230.     MVI    B,30
  231.     CALL    MOVE        ; move title to from CMDBUF to PTITLE
  232.                 ; skip first 2 cells of CMDBUF
  233. ENT2    
  234.     MVI    A,2
  235.     STA    LEFTMRGN
  236. ;    CALL    BOLD
  237. ;    CALL    ILPRT
  238. ;    DB    CR,LF,'Left Margin column number, 0-9 (default ',0
  239. ;    LDA     LEFTMRGN
  240. ;    ADI    ASCBIAS
  241. ;    CALL    TYPE
  242. ;    CALL    ILPRT
  243. ;    DB    '): ',0
  244. ;    CALL    NORM
  245. ;    CALL    KEYIN
  246. ;    CPI    CR
  247. ;    JZ    ENT4
  248. ;    SUI    ASCBIAS
  249. ;    STA    LEFTMRGN
  250. ENT4    
  251.     MVI    A,8
  252.     STA    TABSIZE
  253. ;    CALL    BOLD
  254. ;    CALL    ILPRT
  255. ;    DB    CR,LF,'Tab Size, 1-9 (default ',0
  256. ;    LDA    TABSIZE
  257. ;    ADI    ASCBIAS
  258. ;    CALL    TYPE
  259. ;    CALL    ILPRT
  260. ;    DB    '): ',0
  261. ;    CALL    NORM
  262. ;    CALL    KEYIN
  263. ;    CPI    CR
  264. ;    JZ    ENT6
  265. ;    SUI    ASCBIAS
  266. ;    JZ    ENT6
  267. ;    STA    TABSIZE
  268. ENT6    
  269.     LXI    H,CMDBUF
  270.     MVI    B,32         ; # of blankes to ..
  271.     CALL    FILL         ; ..clear 'cmdbuf'.
  272.  
  273.     MVI    A,0FFH
  274.     STA    STARTED        ; reset started flag, zero = started
  275.     CALL    BOLD
  276.     CALL    ILPRT
  277.     DB    CR,LF,'First Page to be printed, 1-255 (default 1): ',0
  278.     CALL    NORM
  279.     LXI    D,CMDBUF
  280.     MVI    C,RDBUF
  281.     CALL    BDOS
  282.     LXI    H,CMDBUF+4    ; point to third char of start page
  283.     CALL    BININT        ; convert 3 char ascii to binary integer
  284.     STA    STRTPG
  285.  
  286.     CALL    ILPRT
  287.     DB    CR,LF,0
  288.  
  289. ; print files tagged using the 't' command.
  290.     LXI    H,RING+12   ;get 1st possible tag location
  291.     SHLD    RINGPOS
  292. JMASS$LP
  293.     MVI    A,'*'
  294.     CMP    M
  295.     INX    H         ;get in filename synchronization
  296.     SHLD    RINGPOS
  297.     JZ    MPRINT     ;print filename with tag character (*)
  298. ; re-entry point for next file mass print
  299. NXTFILE
  300.     LHLD    RINGPOS        ;re-entry point for next file mass-copy
  301.     XCHG             ;at ring..
  302.     LHLD    RINGEND        ;..end yet?
  303.     CALL    CMPDEHL         ; (compare present position with end)
  304.     JZ    JMF$EXIT    ;yes, jump to beginning of ring.
  305.  
  306.     LHLD    RINGPOS
  307.     JMP    JMASS$LP     ;no, loop 'till thru ring list.
  308. JMF$EXIT
  309.     XRA    A         ;reset flags..
  310.     STA    FIRST$M        ;..for..
  311.     CMA             ;..next..
  312.     JMP    CMDLOOP         ;jump to 'ring' beginning
  313. ; - - - - - - - - - - - - - -
  314. MPRINT
  315.     XRA    A
  316.     STA    LINENO
  317.     STA    COLNO
  318.     MVI    A,1
  319.     STA    PAGENO
  320.     MVI    A,LIST         ;out to 'list' device function
  321.     STA    CON$LST      ;save bdos function
  322.  
  323. ; output file to console/printer/punch
  324.     CALL    RINGFCB         ;position name to 'fcb'
  325.  
  326.     LXI    D,TBUF         ;set to use default cp/m dma buffer
  327.     MVI    C,SETDMA     ;address set function
  328.     CALL    BDOS
  329.  
  330.     LXI    H,S$FCB+12  ;set pointer to source extent field
  331.     CALL    INITFCB         ;fix-up 'fcb' before use
  332.  
  333.     LXI    D,S$FCB     ;open file for reading
  334.     MVI    C,OPEN         ;file open function code
  335.     CALL    BDOS
  336.     INR    A         ; 0ffh --> 00h if open okay
  337.     JNZ    JZEROCR    ;if not okay, show error message.
  338.     CALL    RVBLNK
  339.     CALL    ILPRT
  340.     DB    '++ UNABLE TO OPEN FILE ++',0
  341.     CALL    NORM
  342.     JMP    NXTFILE        ;NEUTRAL
  343. JZEROCR
  344.     CALL    HEADER         ; print filename, date/title and page number
  345.     XRA    A         ;zero file 'current record' field
  346.     STA    S$FCB+32
  347. JREADMR LXI    D,S$FCB     ;point at file 'fcb' for reading
  348.     MVI    C,READ         ;record read function
  349.     CALL    BDOS
  350.     ORA    A         ;check if read okay
  351.     JNZ    PRT15        ;NEUTRAL   ;eof?
  352.     LXI    H,TBUF         ;point at record just read
  353.     MVI    B,128         ;set record character counter to output
  354. JREADLP MOV    A,M         ;get a character
  355.     ANI    7FH         ;force to 'ascii'
  356.     CPI    EOFCHAR         ;see if end-of-file
  357.     JZ    PRT15        ;NEUTRAL    ;back to ring loop if 'eof'
  358.  
  359.     CPI    FF        ; is it a form feed
  360.     CZ    NEWPAGE        ; in case printer cant handle form feed
  361.     CPI    TAB        ; is it a tab
  362.     CZ    TABS
  363.     CPI    LF        ; is it a line feed
  364.     CZ    NEWLINE
  365.     CPI    NULCHR
  366.     JZ    PRT10
  367.     CALL    PROUT        ; not a special character so print it
  368.     LDA    COLNO
  369.     INR    A        ; increment column number
  370.     STA    COLNO
  371. PRT10
  372.     LDA    COLNO
  373.     CPI    PAGEWID        ; check for end of line
  374.     CP    NEWLINE
  375.     LDA    LINENO
  376.     CPI    LASTLINE    ; check for end of page
  377.     CP    NEWPAGE
  378.     LDA    LINENO
  379.     CPI    0        ; print header if new page
  380.     CZ    HEADER
  381.  
  382.     PUSH    B
  383.     PUSH    H
  384.     MVI    C,CONST        ; console status function
  385.     CALL    BDOS
  386.     POP    H
  387.     POP    B
  388.     ORA    A        ; check if character there
  389.     JZ    PRT14
  390.     CALL    NEWPAGE        ; if key pressed, eject page and abort
  391.     JMP    CMDLOOP
  392.  
  393. PRT14    INX    H         ;if not, bump buffer pointer.
  394.     DCR    B         ;all bytes of record sent yet?
  395.     JNZ    JREADLP    ;no, more in present record.
  396.     JMP    JREADMR         ;yes, get next record.
  397.  
  398. PRT15    CALL    NEWPAGE        ; eject paper to end of last page
  399.     JMP    NXTFILE    
  400.  
  401. ; - - - - - - - - - - - - - - - - - -
  402. HEADER
  403.     PUSH    PSW
  404.     PUSH    B
  405.     PUSH    H
  406.     LDA    PAGENO
  407.     LXI    H,STRTPG
  408.     CMP    M        ; is page number => start page ?
  409.     JM    HEAD0
  410.     XRA    A
  411.     STA    STARTED        ; zero if started
  412.     STA    STRTPG        ; clear start page for next file
  413. HEAD0
  414.     MVI    B,TOPMRGN
  415. HEAD1    CALL    NEWLINE        ; minimum of one line
  416.     DCR    B
  417.     JNZ    HEAD1
  418.  
  419.     CALL    PRTMSG
  420.     DB    'Filename: ',0
  421.                 ; print filename
  422.     LDA    LEFTMRGN
  423.     LXI    H,TABSIZE
  424.     ADD    M        ; TABS subtracts (LEFTMRGN-1)
  425.     SUI    11        ; 11 = max filename length +3
  426.     STA    COLNO        ; preset column number for title tab
  427.  
  428.     LXI    H,RINGPOS+4
  429.     MVI    B,8
  430. HEAD2    MOV    A,M
  431.     CPI    SPACE
  432.     CNZ    PR2OUT
  433.     INX    H
  434.     DCR    B
  435.     JNZ    HEAD2
  436.                 ; print dot
  437.     MVI    A,'.'
  438.     CALL    PROUT
  439.                 ; print file type
  440.     MVI    B,3
  441.     CALL    PRTMEM
  442.  
  443.     CALL    TABS        ; tab out to title
  444.  
  445.     CALL    PRTMSG        ; minimum space between filename and title
  446.     DB    ' ',0
  447.  
  448.     CALL    PRTMSG        ; print date/title
  449. PTITLE    DB    '                              ',0    ; storage for title
  450.  
  451.     CALL    PRTMSG
  452.     DB    '   Page ',0
  453.  
  454.     LDA    PAGENO        ; convert binary page number to ascii
  455.     LXI    H,ASCPGNO
  456.     CALL    ASCINT
  457.  
  458. ;    MVI    B,3        ; print page number ( This works also. )
  459. ;    LXI    H,ASCPGNO
  460. ;    CALL    PRTMEM
  461.  
  462.     CALL    PRTMSG        ; print page number
  463. ASCPGNO DB    '000',0
  464.  
  465.     CALL    NEWLINE        ; need CR,LF after header line
  466.  
  467.     MVI    B,HEADMRGN
  468. HEAD8    CALL    NEWLINE        ; minimum of one line
  469.     DCR    B
  470.     JNZ    HEAD8
  471.     POP    H
  472.     POP    B
  473.     POP    PSW
  474.     RET
  475. ; - - - - - - - - - - - - - - - - -
  476. PRTMSG                ; same as ILPRT except to printer
  477.     XTHL             ;save hl, get msg pointer.
  478. JILPLP    MOV    A,M         ;get character
  479.     ANI    7FH         ;strip type bits
  480.     CALL    PROUT        ;TYPE         ;show on console
  481.     INX    H         ;point to the next character and..
  482.     MOV    A,M
  483.     ORA    A         ;..test for end-of-text.
  484.     JNZ    JILPLP
  485.     XTHL             ;set hl-pair and..
  486.     RET             ;..return past message.
  487. ; - - - - - - - - - - - - - - - - -
  488. ; Print from memory locations
  489. ;            B == number of cells
  490. ;            HL points to first cell
  491. PRTMEM    MOV    A,M
  492.     CALL    PROUT
  493.     INX    H        ; next character
  494.     DCR    B
  495.     JNZ    PRTMEM
  496.     RET
  497. ; - - - - - - - - - - - - - - - - -
  498. PROUT    
  499.     CALL    PRINT
  500.     CALL    TYPE
  501.     RET
  502.  
  503. PR2OUT    CALL    PRINT
  504.     CALL    TYPE
  505.     LDA    COLNO
  506.     INR    A        ; increment column number
  507.     STA    COLNO
  508.     RET
  509.  
  510. PRINT    PUSH    PSW
  511.     PUSH    B
  512.     PUSH    H
  513.     PUSH    D
  514.     MOV    E,A             ;**** put character for 'bdos' call
  515.     MVI    C,LIST        ; list function call 5
  516.     LDA    STARTED        ; check started flag
  517.     ORA    A
  518.     CZ    BDOS        ; send character if started
  519.     POP    D
  520.     POP    H
  521.     POP    B
  522.     POP    PSW
  523.     RET
  524. ; - - - - - - - - - - - - - - - - -
  525. NEWPAGE
  526.     PUSH    B
  527.     LDA    LINENO
  528.     MOV    B,A        ; B == line number
  529.     MVI    A,PAGELEN
  530.     SUB    B
  531.     MOV    B,A        ; B == number of lines left
  532.     INR    B        ; need more to get correct page eject
  533.     INR    B
  534. NEWPG2    DCR    B        ; chalk off one line
  535.     JZ    NEWPG4        ; done if B = 0
  536.     CALL    NEWLINE        ; eject one line
  537.     JMP    NEWPG2        ; repeat line feeds until B = 0
  538. NEWPG4    LDA    PAGENO
  539.     INR    A        ; increment page number
  540.     STA    PAGENO
  541.     XRA    A
  542.     STA    LINENO        ; set line number to zero
  543.     POP    B
  544.     RET            ; with nul char in A reg
  545. ; - - - - - - - - - - - - - - - - -
  546. NEWLINE
  547.     PUSH    B
  548.     PUSH    H
  549.     MVI    A,CR
  550.     CALL    PROUT
  551.     MVI    A,LF
  552.     CALL    PROUT
  553.     LDA    LINENO
  554.     INR    A        ; increment line number
  555.     STA    LINENO
  556.  
  557.     LDA    LEFTMRGN
  558.     INR     A
  559.     MOV    B,A
  560.     LXI    H,COLNO
  561.     MVI    M,0        ; preset column to zero
  562.     MVI    A,SPACE
  563. LEFT2    DCR    B
  564.     JZ    LEFT4
  565.     CALL    PROUT        ; output a space for left margin
  566.     INR    M        ; increment column number
  567.     JMP    LEFT2
  568. LEFT4    POP    H
  569.     POP    B
  570.     XRA    A        ; nul char into A reg
  571.     RET
  572. ; - - - - - - - - - - - - - - - - - -
  573. ; Expand tabs to spaces.
  574. TABS    
  575.     PUSH    B
  576.     PUSH    H
  577. TABS2    MVI    A,SPACE
  578.     CALL    PROUT        ; output a space (at least one space)
  579.     LDA    COLNO
  580.     INR    A        ; increment column number
  581.     STA    COLNO
  582.     CPI    PAGEWID        ; check for end of line
  583.     JP    TABS6        ; stop if zero or positive
  584.  
  585.     LXI    H,LEFTMRGN
  586.     SUB    M        ; subtract LEFTMRGN
  587.     LXI    H,TABSIZE
  588. TABS4    SUB    M        ; subtract TABSIZE
  589.     JZ    TABS6        ; on a tab position if zero, finished
  590.     JM    TABS2        ; not on a tab position
  591.     JMP    TABS4
  592. TABS6    POP    H
  593.     POP    B
  594.     XRA    A        ; nul char into A reg
  595.     RET
  596. ; - - - - - - - - - - - - - - - -
  597. ; Convert binary integer in A reg to a three character ascii decimal integer.
  598. ; Store the ascii result in memory pointed to by HL.
  599. ; Range 000 to 255
  600. ASCINT    
  601.     PUSH    PSW
  602.     PUSH    B
  603.     PUSH    D
  604.     PUSH    H
  605.     XCHG            ; DE points to ASCII storage cells
  606.     LXI    H,DECDIG    ; HL points to DECIMAL WEIGHT (100,10,1)
  607.     MVI    B,3        ; 3 ascii characters for 000 to 255
  608. ASCZERO XCHG    
  609.     MVI    M,'0'        ; preset digit to ascii zero
  610.     XCHG    
  611. COMPDIG CMP    M
  612.     JM    NXTDIG        ; go to next dig if binary < decimal weight
  613.     SUB    M        ; subtract if binary number => decimal weight
  614.     XCHG    
  615.     INR    M        ; increment the stored ascii character
  616.     XCHG    
  617.     JMP    COMPDIG
  618. NXTDIG    INX    D        ; point to next storage cell
  619.     INX    H        ; point to next decimal weight
  620.     DCR    B        ; check for last of 3 digits
  621.     JNZ    ASCZERO
  622.     POP    H
  623.     POP    D
  624.     POP    B
  625.     POP    PSW
  626.     RET
  627.  
  628. ; - - - - - - - - - - - - - - - -
  629. ; Convert 3 char ascii integer to a binary integer in A reg.
  630. ; On entry, HL points to 3 character ascii integer
  631. ; At exit, A reg contains binary integer
  632.  
  633. BININT    PUSH    B
  634.     PUSH    D
  635.     PUSH    H
  636.     XRA    A
  637.     MOV    C,A        ; zero binary number in C
  638.     LXI    D,DECDIG+2    ; point to dec 1 (100,10,1)
  639.     MVI    B,3        ; 3 ascii digits
  640. NXTCHR    MOV    A,M        ; get ascii
  641.     SUI    ASCBIAS        ; ascii to binary
  642.     JM    INCPTR        ; skip if < 0
  643.     CPI    10
  644.     JP    INCPTR        ; skip if > 9
  645.  
  646. SCALE    PUSH    B
  647.     PUSH    PSW
  648.     MOV    C,A        ; put binary into C
  649.     XCHG
  650.     MOV    A,M        ; get decimal digit
  651.     XCHG
  652.     MOV    B,A        ; B = dec digit for multiply (100,10,1)
  653.     POP    PSW        ; retrieve binary
  654. SCALE2    DCR    B
  655.     JZ    SCALE3
  656.     ADD    C
  657.     JMP    SCALE2
  658. SCALE3    POP    B        ; get old binary in C
  659.  
  660.     ADD    C        ; add old binary to new binary
  661.     MOV    C,A        ; store updated binary
  662.     DCX    D        ; point to next larger dec digit (100,10,1)
  663. INCPTR    DCX    H        ; point to next ascii digit
  664.     DCR    B
  665.     JNZ    NXTCHR
  666.     MOV    A,C        ; put binary into A reg for return
  667.     POP    H
  668.     POP    D
  669.     POP    B
  670.     RET
  671. ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  672. ;                END OF PRINTER ROUTINES.
  673. ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
  674.  
  675. ; start of program
  676.  
  677. DISK7     IF    NOT WARMBOOT
  678.     LXI    H,0        ;clear hl-pair then..
  679.     DAD    SP        ;..add cp/m's stack address
  680.     SHLD    STACK
  681.      ENDIF            ;not warmboot
  682.  
  683.     LXI    SP,STACK    ;start local stack
  684.     CALL    HELP        ;show 'menu'
  685.     MVI    E,GET        ;determine..
  686.     CALL    GET$USR        ;..user area then..
  687.     STA    C$U$A        ;..store as current and..
  688.     STA    O$USR        ;..as original for exit.
  689.     LDA    FCB        ;default drive?
  690.     ORA    A
  691.     JZ    EMBARK        ;if so, branch.
  692.     DCR    A
  693.     STA    C$DR        ;store 0 --> 'a', 1 --> 'b',etc.
  694.     CALL    SET$DR        ;select requested drive as current
  695.  
  696. ; determine if specific file(s) requested -- show remaining storage
  697.  
  698. EMBARK    CALL    FRESTOR        ;get bytes remaining on drive (decode default)
  699.     LDA    FCB+1        ;check if a filename was entered
  700.     CPI    ' '        ;filename a space?
  701.     JNZ    PLUNGE        ;no, name was entered.
  702.     LDA    FCB+9        ;filetype also space?
  703.     CPI    ' '        ;if so, then..
  704.     JNZ    PLUNGE
  705.     LXI    H,JOKER        ;..treat as '*.*' with 'joker'..
  706.     LXI    D,FCB+1        ;..loaded here.
  707.     MVI    B,11        ; # of characters to move
  708.     CALL    MOVE        ;set field to *.*
  709.  
  710. ; build 'ring' with filename positioned in default 'fcb' area
  711.  
  712. PLUNGE    MVI    C,SETDMA    ;initialize dma address..
  713.     LXI    D,TBUF        ;..to default buffer.
  714.     CALL    BDOS
  715.     XRA    A        ;clear search 'fcb'..
  716.     STA    FCBEXT        ;extent byte..
  717.     STA    FCBRNO        ;..and record number.
  718.     CMA
  719.     STA    CANFLG        ;make cancel flag true
  720.     LXI    D,FCB        ;default 'fcb' for search..
  721.     MVI    C,SRCHF        ;..of first occurrence.
  722.     CALL    BDOS
  723.     INR    A        ; 0ffh --> 00h if no file found
  724.     JNZ    SETRING        ;if found, branch and build ring.
  725.     STA    CANFLG        ;make log-cancel toggle false
  726.     CALL    ILPRT        ;else say none found, fall thru to log.
  727.     DB    CR,LF,0
  728.         CALL    RVBLNK
  729.         CALL    ILPRT
  730.         DB    '++ NO FILE FOUND ++',0
  731.         CALL    BLBLNK
  732.     CALL    ILPRT
  733.      DB    CR,LF,LF,0
  734.         DB      ' --->  ',0
  735.         CALL    NORM
  736.  
  737. ; l o g
  738.  
  739. ; select drive and user area (system reset for disk change on-the-fly)
  740.  
  741. LOG    CALL    BOLD
  742.     CALL    ILPRT        ;prompt to get drive/user selection
  743.     DB    BS,'Log-in drive/user: ',0
  744.     CALL    NORM
  745.     CALL    DEF$D$U
  746.     LDA    R$U$A        ;establish requested area..
  747.     STA    C$U$A        ;..as current area.
  748.     CALL    SET$USR
  749.     CALL    RESET        ;reset disk system, make requested current.
  750.     MVI    A,' '        ;set default 'fcb' to look like *.*
  751.     STA    FCB+1
  752.     STA    FCB+9
  753.     LXI    H,0        ;initialize tagged..
  754.     SHLD    TAG$TOT        ;..file size accumulator.
  755.     CALL    ILPRT
  756.     DB    CR,LF,LF,0    ;fresh line and..
  757.     JMP    EMBARK        ;..restart.
  758.  
  759. ; routine to define current drive and user area with full error trapping.
  760. ; (check validity of user area entry first, then drive validity, then proceed
  761. ; with implementation.)
  762.  
  763. DEF$D$U    LXI    H,CMDBUF+2
  764.     MVI    B,7        ; # of blanks to..
  765.     CALL    FILL        ;..clear 'cmdbuf'.
  766.     LXI    D,CMDBUF    ;get drive/user selection from..
  767.     MVI    C,RDBUF        ;..console buffer read.
  768.     CALL    BDOS
  769.     LDA    CMDBUF+1    ;if only a..
  770.     ORA    A        ;..cursor return, cancel..
  771.     JZ    COMCAN        ;..log function.
  772.     CALL    CONVERT        ;make sure alpha is upper case
  773.      XRA    A        ;initialize..
  774.     STA    R$U$A        ;..user area to zero.
  775.     LDA    CMDBUF+3    ; 1st digit of user area?
  776.     CPI    ':'        ;allow ':' after drive declaration
  777.     JZ    SETEXIT
  778.     CPI    '0'        ;no valid user area request..
  779.     JC    SETEXIT        ;..then to new drive and ring list.
  780.     CPI    '9'+1
  781.     JNC    ERRET        ;error, not a user area.
  782.     SUI    30H        ;convert to binary and..
  783.     CPI    1        ;..test if 10's digit.
  784.     JNZ    SETUSER        ;if none, then set user area now.
  785.     LDA    CMDBUF+4    ;a second user area digit?
  786.     CPI    ':'        ;allow ':' here
  787.     JZ    SETUONE
  788.     CPI    '0'        ;test for 1's digit
  789.     JC    SETUONE
  790.     CPI    '5'+1        ;if user area >15, go..
  791.     JNC    ERRET        ;..error msg, show file line.
  792.     SUI    30H-10        ;make 1 --> 11, 2 --> 12, etc.
  793.     STA    R$U$A        ;save as 'requested user area' here..
  794.     JMP    SETEXIT
  795.  
  796. SETUONE    MVI    A,1        ;set to user area 'one'
  797. SETUSER    MOV    B,A
  798.     LDA    CMDBUF+4
  799.     CPI    ':'        ;double dot (colon)?
  800.     JZ    DDPASS
  801.     CPI    '0'        ;if >19 user area, go error msg.
  802.     JNC    ERRET
  803. DDPASS    MOV    A,B
  804.     STA    R$U$A        ;..and here.
  805. SETEXIT    LDA    MAXDR        ;check if system maximum and..
  806.     INR    A
  807.     MOV    B,A
  808.     LDA    CMDBUF+2    ;..requested drive are compatible.
  809.     CMP    B        ;if input too big..
  810.     JNC    ERRET        ;..or..
  811.     MVI    B,'A'-1        ;..too..
  812.     CMP    B        ;..small, show..
  813.     JC    ERRET        ;..error msg.
  814.     SUI    'A'-1        ;ready for fcb use
  815.     STA    FCB        ;store 1 --> a:, 2 --> b:, etc.
  816.     DCR    A
  817.     STA    R$DR        ;ready for 'login' request
  818.     RET
  819.  
  820. ; error return and recovery from command cancellation
  821.  
  822. ERRET    CALL    ILPRT
  823.     DB    CR,LF,0
  824.         CALL    RVBLNK
  825.         CALL    ILPRT
  826.         DB    '++ Drive/User Entry Error ++',0
  827.         CALL    NORM
  828.         CALL    ILPRT
  829.         DB    BELL,0
  830. COMCAN    LXI    SP,STACK    ;reset stack..
  831.     LDA    CANFLG
  832.     ORA    A        ;..from..
  833.     CZ    CRLF
  834.     JZ    PLUNGE
  835.     JMP    NEUTRAL        ;..error/command abort.
  836.  
  837. ; e x i t
  838.  
  839. ; return to cp/m ccp
  840.  
  841. CPM$CCP    LDA    O$USR        ;get and set original..
  842.     CALL    SET$USR        ;..user area and..
  843.     LXI    D,TBUF        ;..tidy up..
  844.     MVI    C,SETDMA    ;..before going home.
  845.     CALL    BDOS
  846.     CALL    CRLF
  847.  
  848.      IF WARMBOOT
  849.     JMP    CPM$BASE
  850.      ENDIF            ;warmboot
  851.  
  852.      IF    NOT WARMBOOT
  853.     LHLD    STACK        ;put cp/m's pointer..
  854.     SPHL            ;..back to 'sp'.
  855.     RET            ;return to cp/m ccp
  856.      ENDIF            ;not warmboot
  857.  
  858. ; h e l p  (menu)
  859.  
  860. HELP    CALL    CLS        ;show menu but 'clear-screen' first
  861.     CALL    NORM        ;reset to normal video if not....
  862.     CALL    ILPRT
  863.     DB    CR,'      DISK ',VERS/10+'0','.',VERS MOD 10+'0',' for ',0
  864.     CALL    RVBLNK        ;turn on reverse,bold,blink video
  865.     CALL    ILPRT
  866.     DB    'RAINBOW 100',0
  867.     CALL    NORM
  868.     CALL    ILPRT
  869.     DB    ' -- File Manipulation Program -- '
  870.     DB    MONTH/10+'0',MONTH MOD 10+'0','/'
  871.     DB    DAY/10+'0',DAY MOD 10+'0','/'
  872.     DB    YEAR/10+'0',YEAR MOD 10+'0'
  873.     DB    CR,LF,0
  874.     CALL    RVRSE        ;turn on reverse,bold video
  875.     CALL    ILPRT
  876.     DB    '   C - Copy file   | D - Delete file  | F - File size  | J '
  877.     DB    '- Jump 15 files   ',CR,LF
  878.     DB    '   L - Log-in      | M - Mass copy    | P - Mass print | R '
  879.     DB    '- Rename file     ',CR,LF
  880.     DB    '   S - Stat drive  | T - Tag file     | U - Untag file | V '
  881.     DB    '- View text file  ',CR,LF
  882.     DB    '   W - Write punch | X - Exit to CP/M | <space> advances cu'
  883.     DB    'rsor <- B backs up',0
  884.     CALL    NORM
  885.     CALL    ILPRT
  886.         DB      CR,LF,LF,0
  887.     RET
  888.  
  889. ; establish ring (circular list) of filenames
  890.  
  891. SETRING    LXI    H,RING        ;initialize ring pointer
  892.     SHLD    RINGPOS        ;start --> current position of ring
  893.  
  894. ; put each found name in ring.  a-reg --> offset into 'tbuf' name storage
  895.  
  896. TO$RING    DCR    A        ;un-do 'inr' from above and below
  897.     ADD    A        ;times 32 --> position index
  898.      ADD    A
  899.     ADD    A
  900.     ADD    A
  901.     ADD    A
  902.     ADI    TBUF        ;add page offset and..
  903.     MOV    L,A        ;..put address into..
  904.     MVI    H,0        ;..hl-pair.
  905.     LDA    FCB        ;get drive/user designator and..
  906.     MOV    M,A        ;..put into 'fcb' buffer.
  907.     XCHG
  908.     LHLD    RINGPOS        ;pointer to current load point in ring
  909.     XCHG
  910.     MVI    B,12        ;move drive designator and name to ring
  911.     CALL    MOVE
  912.     XCHG            ;de-pair contains next load point address
  913.     MVI    M,' '        ;space for potential..
  914.     INX    H        ;..tagging of files for mass copy.
  915.     SHLD    RINGPOS        ;store and search..
  916.     MVI    C,SRCHN        ;..for next occurrence.
  917.     LXI    D,FCB        ;filename address field
  918.     CALL    BDOS
  919.     INR    A        ;if all done, 0ffh --> 00h.
  920.     JNZ    TO$RING        ;if not, put next name into ring.
  921.  
  922. ; all filenames in ring -- setup ring size and copy-buffer start point
  923.  
  924.     LHLD    RINGPOS        ;next load point of ring is start of buffer
  925.     SHLD    RINGEND        ;set ring end..
  926.     SHLD    BUFSTART    ;..and copy-buffer start.
  927.     LXI    D,RING+13    ;compare 'ringend' (tab base+13)
  928.     CALL    CMPDEHL
  929.     JZ    CMDLOOP        ;go to command loop, if no sort.
  930.  
  931. ; sort ring of filenames
  932.  
  933. SORT    LXI    H,RING        ;initialize 'i' sort variable and..
  934.     SHLD    RINGI
  935.     LXI    D,13        ;..also 'j' variable.
  936.     DAD    D
  937.     SHLD    RINGJ
  938. SORTLP    LHLD    RINGJ        ;compare names 'i & j'
  939.     XCHG
  940.     LHLD    RINGI
  941.     PUSH    H        ;save position pointers..
  942.     PUSH    D        ;..for potential swap.
  943.     MVI    B,13        ; # of characters to compare
  944.  
  945. ; left to right compare of two strings (de-pair points to 'a' string;
  946. ; hl-pair, to 'b'; b-reg contains string length.)
  947.  
  948. CMPSTR    LDAX    D        ;get an 'a' string character and..
  949.     CMP    M        ;..check against 'b' string character.
  950.     JNZ    NOCMP        ;if not equal, set flag.
  951.     INX    H        ;bump compare..
  952.     INX    D        ;..pointers and..
  953.     DCR    B        ; (if compare, set as equal.)
  954.     JNZ    CMPSTR        ;..do next character.
  955. NOCMP    POP    D
  956.     POP    H
  957.     MVI    B,13
  958.     JNC    NOSWAP
  959.  
  960. ; swap if 'j' string larger than 'i'
  961.  
  962. SWAP    MOV    C,M        ;get character from one string..
  963.     LDAX    D        ;..and one from other string.
  964.     MOV    M,A        ;second into first
  965.     MOV    A,C        ;first into second
  966.     STAX    D
  967.     INX    H        ;bump swap pointers
  968.     INX    D
  969.     DCR    B        ;all bytes swapped yet?
  970.     JNZ    SWAP
  971. NOSWAP    LHLD    RINGJ        ;increment 'j' pointer
  972.     LXI    D,13
  973.     DAD    D
  974.     SHLD    RINGJ
  975.     XCHG            ;see if end of 'j' loop
  976.     LHLD    RINGEND
  977.     CALL    CMPDEHL
  978.     JNZ    SORTLP        ;no, so more 'j' looping.
  979.     LHLD    RINGI        ;bump 'i' pointer
  980.     LXI    D,13
  981.     DAD    D
  982.     SHLD    RINGI
  983.     DAD    D        ;set start over 'j' pointer
  984.     SHLD    RINGJ
  985.     XCHG            ;see if end of 'i' loop
  986.     LHLD    RINGEND
  987.     CALL    CMPDEHL
  988.     JNZ    SORTLP        ;must be more 'i' loop to do
  989.  
  990. ; sort done -- initialize tables for fast crc calculations
  991.  
  992.     CALL    INITCRC
  993.  
  994. ; calculate buffer maximum available record capacity
  995.  
  996. B$SIZE    LXI    B,0        ;count records
  997.     LHLD    BDOS+1        ;get 'bdos' entry (fbase)
  998.  
  999.      IF    NOT WARMBOOT
  1000.     LXI    D,-(CCP)
  1001.     DAD    D
  1002.      ENDIF            ;not warmboot
  1003.  
  1004.     DCX    H
  1005.     XCHG            ;de-pair --> highest address of buffer
  1006.     LHLD    BUFSTART    ;start address of buffer (end of ring list)
  1007. B$SIZE2    INX    B        ;increase record count by one
  1008.     PUSH    D
  1009.     LXI    D,128        ; 128-byte record
  1010.     DAD    D        ;buffer address + record size
  1011.     POP    D
  1012.     CALL    CMPDEHL        ;compare for all done
  1013.     JNC    B$SIZE2        ;more will fit?
  1014.     DCX    B        ;set maximum record count less one
  1015.     MOV    A,B        ;memory available for copy?
  1016.     ORA    C
  1017.     JNZ    B$SIZE3        ;yes, buffer memory space available.
  1018.     CALL    ILPRT
  1019.     DB    CR,LF,BELL,0
  1020.         CALL    RVBLNK
  1021.         DB    '++ NO MEMORY FOR COPY BUFFER ++',0
  1022.     CALL    NORM
  1023.     JMP    NEUTRAL
  1024.  
  1025. B$SIZE3    MOV    L,C        ;store..
  1026.     MOV    H,B        ;..maximum..
  1027.     SHLD    REC$MAX        ;..record count.
  1028.  
  1029. ; buffer size suitable -- process file/display loop
  1030.  
  1031. CMDLOOP    LXI    H,RING        ;set start point of listing
  1032.     SHLD    RINGPOS
  1033. LOOP    CALL    ILPRT
  1034.     DB    CR,LF,'   ',0
  1035. LOOP2    LHLD    RINGPOS        ;ring filename location
  1036.     MOV    A,M        ;move 'fcb' to a-reg and..
  1037.     ADI    'A'-1        ;..make drive printable (a - p).
  1038.     CALL    TYPE
  1039.     LDA    C$U$A        ;get current (last requested) user area
  1040.     ORA    A        ;branch if 'user..
  1041.     JZ    UAZ        ;..area zero'.
  1042.     CPI    10        ;less then ten?
  1043.     JC    LT$TEN        ;if yes, branch.
  1044.     SUI    10        ;if not, suppress leading 10's digit.
  1045.     PUSH    PSW
  1046.     MVI    A,'1'        ;print 10's digit as 'one'
  1047.     CALL    TYPE
  1048.     POP    PSW
  1049. LT$TEN    ADI    '0'        ;make 1's digit printable
  1050.     CALL    TYPE
  1051. UAZ    CALL       BOLD
  1052.     CALL    ILPRT        ;fence between 'drive/user' and..
  1053.     DB    ': ',0        ;..'fn.ft'.
  1054.     CALL    NORM
  1055.     INX    H        ;beginning of 'fn.ft' string
  1056.     MVI    B,8        ; 8 filename characters
  1057. PRT$FN    MOV    A,M
  1058.     CALL    TYPE
  1059.     INX    H
  1060.     DCR    B
  1061.     JNZ    PRT$FN
  1062.     MVI    A,'.'        ;period between 'fn' and 'ft'
  1063.     CALL    TYPE
  1064.     MVI    B,3        ; 3 filetype characters
  1065. PRT$FT    MOV    A,M
  1066.     CALL    TYPE
  1067.     INX    H
  1068.     DCR    B
  1069.     JNZ    PRT$FT
  1070.     MOV    A,M        ;get tag (*) and..
  1071.     STA    TAG+2        ;..put after colon.
  1072.     INX    H
  1073.     SHLD    RINGPOS        ;save ring position
  1074.     CALL    BOLD
  1075.     CALL    ILPRT
  1076. TAG    DB    ' : ',0        ;space, colon, space or * before cursor.
  1077.     CALL    NORM
  1078.     LDA    J$FLG        ;jump..
  1079.     ORA    A        ;..forward?
  1080.     JZ    PRE$FOR
  1081. K$WAIT    CALL    KEYIN        ;wait for character from keyboard
  1082.     CPI    ' '        ;if 'space' or..tract one ring position.
  1083.     JZ    FORWARD
  1084.     CPI    CR        ;..'cursor return', move to next file.
  1085.     JZ    FORWARD
  1086.     CPI    'B'        ;if reverse, subtract one ring position.
  1087.     JZ    REVERSE
  1088.     CPI    'C'        ;copy file to another disk?
  1089.     JZ    COPY
  1090.     CPI    'D'        ;delete a file?
  1091.     JZ    DELETE
  1092.     CPI    'F'        ;show file size?
  1093.     JZ    FIL$SIZ
  1094.     CPI    'J'        ;jump forward?
  1095.     JZ    JUMP15
  1096.     CPI    'L'        ;log-in another drive?
  1097.     JZ    LOG
  1098.     CPI    'M'        ;tagged multiple file copy?
  1099.     JZ    MASS
  1100.     CPI    'P'        ;output file to 'list' device?
  1101.     JZ    MASSLST            ;**** MASS PRINT        LSTFILE
  1102.     CPI    'R'        ;if rename, get to work.
  1103.     JZ    RENAME
  1104.     CPI    'S'        ;free bytes on..
  1105.     JZ    R$DR$ST        ;..requested drive?
  1106.     CPI    'T'        ;if tag, put '*' in..
  1107.     JZ    TAG$EM        ;..front of cursor.
  1108.     CPI    'U'        ;remove '*' from..
  1109.     JZ    UNTAG        ;..in front of cursor?
  1110.     CPI    'V'        ; 'view' file at console?
  1111.     JZ    VIEW
  1112.     CPI    'W'        ;file to punch?
  1113.     JZ    PUNFILE
  1114.     CPI    'X'        ;if exit, then to cp/m ccp.
  1115.     JZ    CPM$CCP
  1116.     CPI    ESC        ; 'esc' exits to cp/m ccp also.
  1117.     JZ    CPM$CCP
  1118.     CALL    HELP          ;get help message (menu) and..
  1119.     CALL    FRESTOR        ;..show free storage remaining.
  1120. NEUTRAL    LHLD    RINGPOS        ;stay..
  1121.     LXI    D,-13        ;..in..
  1122.     DAD    D        ;..the..
  1123.     SHLD    RINGPOS        ;..same..
  1124.     JMP    LOOP        ;..position.
  1125.  
  1126. ; jump forward 15 files
  1127.  
  1128. PRE$FOR    LDA    J$CNT        ;adjust jump..
  1129.     INR    A        ;..counter..
  1130.     STA    J$CNT        ;..until..
  1131.     CPI    15        ;..at top limit.
  1132.     JNZ    FORWARD
  1133.     MVI    A,TRUE        ;at top, so..
  1134.     STA    J$FLG        ;..turn off jump switch and..
  1135.     JMP    K$WAIT        ;..wait for next keyboard input.
  1136.  
  1137. ; u n t a g
  1138.  
  1139. UNTAG    XRA    A        ;set tag/untag..
  1140.     STA    T$UN$FG        ;..flag to untag.
  1141.     LHLD    RINGPOS        ;move back one..
  1142.     LXI    D,-1        ;..character position..
  1143.     DAD    D        ;..and check tagging status.
  1144.     MOV    A,M        ;if file previously tagged, remove..
  1145.     CPI    '*'        ;..size from..
  1146.     MVI    M,' '        ; (untag character, to next ring position.)
  1147.     JZ    FS2        ;..summation.
  1148.     JMP    FORWARD
  1149.  
  1150. ; t a g
  1151.  
  1152. TAG$EM    LHLD    RINGPOS
  1153.     LXI    D,-1        ;move back one..
  1154.     DAD    D        ;..position..
  1155.     MOV    A,M        ; (if file
  1156.     CPI    '*'        ; already tagged, skip
  1157.     JZ    FORWARD        ; to next file.)
  1158.     MVI    M,'*'        ;..and store a '*' tag character.
  1159.     MVI    A,TRUE        ;set..
  1160.     STA    T$UN$FG        ;..tag/untag and..
  1161.     STA    FS$FLG        ;..file size flags to tag.
  1162.     JMP    FS2        ;get file size
  1163.  
  1164. ; f i l e   s i z e
  1165.  
  1166. ; determine and display file size in kilobytes -- round up to next disk
  1167. ; allocation block -- accumulate tagged file summation
  1168.  
  1169. FIL$SIZ    XRA    A        ;set file size/tagged..
  1170.     STA    FS$FLG        ;..file flag to file size.
  1171. FS2    MVI    A,BS        ;backspace over..
  1172.     CALL    TYPE        ;..command character.
  1173.     CALL    RINGFCB        ;move name to 's$fcb'
  1174.  
  1175. ; determine file record count and save in 'rcnt'
  1176.  
  1177.     MVI    C,COMPSZ
  1178.     LXI    D,S$FCB
  1179.     CALL    BDOS
  1180.     LHLD    S$FCB+33
  1181.     SHLD    RCNT        ;save record count and..
  1182.     LXI    H,0
  1183.     SHLD    S$FCB+33    ;..reset cp/m.
  1184.  
  1185. ; round up to next disk allocation block
  1186.  
  1187.     LDA    B$MASK        ;sectors/block - 1
  1188.     PUSH    PSW        ;save 'blm'
  1189.     MOV    L,A
  1190.     XCHG
  1191.     LHLD    RCNT        ;..use here.
  1192.     DAD    D        ;round up to next block
  1193.     MVI    B,3+1        ;convert from..
  1194.     CALL    SHIFTLP        ;..records to kilobytes.
  1195.     POP    PSW        ;retrieve 'blm'
  1196.     RRC            ;convert..
  1197.     RRC            ;..to..
  1198.     RRC            ;..kilobytes/block.
  1199.     ANI    1FH
  1200.     CMA            ;finish rounding
  1201.     ANA    L
  1202.     MOV    L,A        ;hl-pair contains # of kilobytes
  1203.     LDA    FS$FLG
  1204.     ORA    A
  1205.     JZ    D$F$SIZ        ;branch if 'f' function
  1206.  
  1207. ; tagged file size summation
  1208.  
  1209.     XCHG            ;file size to de-pair
  1210.     LDA    T$UN$FG
  1211.     ORA    A
  1212.     JZ    TAKE        ;if untag, take size from total.
  1213.     LHLD    TAG$TOT        ;accumulate..
  1214.     DAD    D        ;..sum of..
  1215.     SHLD    TAG$TOT        ;..tagged file sizes.
  1216.     XCHG            ;file size to hl-pair
  1217.     JMP    D$F$SIZ        ;branch to display sizes
  1218.  
  1219. TAKE    LHLD    TAG$TOT        ;subtract..
  1220.     MOV    A,L        ;..file..
  1221.     SUB    E        ;..size..
  1222.     MOV    L,A        ;..from..
  1223.     MOV    A,H        ;..summation..
  1224.     SBB    D        ;..total.
  1225.     MOV    H,A        ;then put..
  1226.     SHLD    TAG$TOT        ; (save total)
  1227.     XCHG            ;..file size in hl-pair.
  1228.  
  1229. ; display file size in kilobytes -- right justify tagged file total
  1230.  
  1231. D$F$SIZ    CALL    DET$BCD        ;determine # of bcd digits in hl-pair
  1232.     MVI    A,9        ;limit of right margin (good for max cp/m 2.2)
  1233.     SUB    B        ; # of digits returned in b-reg from det$bcd
  1234.     STA    TEST$RT        ;save intermediate right-justify data
  1235.     CALL    DECOUT          ;print individual file size
  1236.     CALL    ILPRT
  1237.     DB    'k',0
  1238.     LDA    FS$FLG
  1239.     ORA    A
  1240.     JZ    FORWARD         ;show next file if not tagging
  1241.  
  1242. ; determine # of digits in tagged summation
  1243.  
  1244.     LHLD    TAG$TOT        ;get present summation
  1245.     CALL    DET$BCD
  1246.  
  1247. ; insert necessary spaces (blanks) to right justify display
  1248.  
  1249.     LDA    TEST$RT        ;get intermediate right-justify data
  1250.     SUB    B
  1251.     MOV    B,A
  1252.     MVI    A,' '        ;adjust..
  1253. ADD$SP    CALL    TYPE        ;..to..
  1254.     DCR    B        ;..achieve..
  1255.     JNZ    ADD$SP        ;..right justification.
  1256.     MVI    A,'('
  1257.     CALL    TYPE
  1258.     CALL    DECOUT          ;print tagged file summation
  1259.     CALL    ILPRT
  1260.     DB    'k)',0          ;to next file..
  1261.     JMP    FORWARD        ;..cursor line.
  1262.  
  1263. ; j u m p
  1264.  
  1265. JUMP15    XRA    A        ;clear..
  1266.     STA    J$FLG        ;..jump forward flag and..
  1267.     STA    J$CNT        ;..file counter.  fall-thru to next filename.
  1268.  
  1269. ; f o r w a r d
  1270.  
  1271. FORWARD    LHLD    RINGPOS        ;at end of loop yet?
  1272.     XCHG
  1273.     LHLD    RINGEND
  1274.     CALL    CMPDEHL        ;compare 'present' to 'end'
  1275.     JNZ    LOOP        ;to next print position
  1276.     CALL    CRLF        ;end-of-directory shows with fresh line
  1277.     LXI    H,RING        ;set position pointer to beginning and..
  1278.     SHLD    RINGPOS
  1279.     JMP    LOOP        ;..redisplay start entry.
  1280.  
  1281. ; r e v e r s e
  1282.  
  1283. REVERSE    LHLD    RINGPOS        ;see if at beginning of ring
  1284.     LXI    D,RING+13
  1285.     CALL    CMPDEHL
  1286.     JNZ    REV1        ;skip position pointer reset if not..
  1287.     CALL    CRLF        ;..at beginning.  skip line at junction.
  1288.     LHLD    RINGEND        ;set to end +1 to backup to end
  1289.     LXI    D,13
  1290.     DAD    D
  1291.     SHLD    RINGPOS
  1292. REV1    CALL    BOLD
  1293.     CALL    ILPRT        ;indicate reverse
  1294.     DB    CR,LF,'<- ',0
  1295.     CALL    NORM
  1296.     LHLD    RINGPOS
  1297.     LXI    D,-(13*2)    ;one ring position..
  1298.     DAD    D        ;..backwards.
  1299.     SHLD    RINGPOS
  1300.      JMP    LOOP2        ;display without 'crlf'
  1301.  
  1302. ; s t a t
  1303.  
  1304. ; determine remaining storage on requested drive
  1305.  
  1306. R$DR$ST    CALL    BOLD
  1307.     CALL    ILPRT
  1308.     DB    BS,'Storage remaining on drive: ',0
  1309.     CALL    NORM
  1310.     CALL    DEF$D$U        ;determine drive requested and..
  1311.     CALL    RESET        ;..login as current.
  1312.     CALL    ILPRT
  1313.     DB    CR,LF,LF,0
  1314.     CALL    FRESTOR        ;determine free space remaining
  1315.     LDA    C$DR        ;login original as..
  1316.     CALL    SET$DR        ;..current drive.
  1317.     JMP    NEUTRAL
  1318.  
  1319. ; d e l e t e
  1320.  
  1321. ; set up to delete filename at cursor position
  1322.  
  1323. DELETE    CALL    RINGFCB        ;move name from ring to 'rename fcb'
  1324.     CALL    BLBLNK
  1325.     CALL    ILPRT
  1326.     DB    BS,'Delete? (Y/N): ',0
  1327.     CALL    NORM
  1328.     CALL    KEYIN
  1329.     CPI    'Y'
  1330.     JNZ    NEUTRAL    
  1331.  
  1332. ; delete file
  1333.  
  1334.     LXI    D,S$FCB        ;point at delete 'fcb'
  1335.     MVI    C,ERASE        ;erase function
  1336.     CALL    BDOS
  1337.     INR    A
  1338.     JNZ    DEL2        ;file deleted okay
  1339. FNF$MSG    CALL    ILPRT        ;show error message
  1340.     DB    CR,LF,0
  1341.         CALL    RVBLNK
  1342.         CALL    ILPRT
  1343.     DB    '++ NO FILE FOUND ++',0
  1344.     CALL    NORM
  1345.     JMP    NEUTRAL
  1346.  
  1347. ; reverse ring to close up erased position
  1348.  
  1349. DEL2    LHLD    RINGPOS        ;prepare move up pointers
  1350.     PUSH    H
  1351.     LXI    D,-13
  1352.     DAD    D
  1353.     SHLD    RINGPOS        ;reset current position for move
  1354.     XCHG            ;de-pair = 'to' location
  1355.     POP    H        ;hl-pair = 'from' location
  1356. MOVUP    XCHG
  1357.     PUSH    H        ;check if at end
  1358.     LHLD    RINGEND        ;get old end pointer
  1359.     CALL    CMPDEHL        ;check against current end location
  1360.     POP    H
  1361.     XCHG
  1362.     JZ    MOVDONE        ;must be at end of ring
  1363.     MVI    B,13        ;one name size
  1364.     CALL    MOVE        ;move one name up
  1365.     JMP    MOVUP        ;go check end parameters
  1366.  
  1367. MOVDONE    XCHG
  1368.     SHLD    RINGEND        ;set new ring end if all moved
  1369.     LXI    D,RING        ;see if ring is empty..
  1370.     CALL    CMPDEHL        ;..(listend --> listpos --> ring)
  1371.     JNZ    FORWARD
  1372.     LHLD    RINGPOS
  1373.     CALL    CMPDEHL
  1374.     JNZ    FORWARD        ;neither equal so not empty
  1375.     CALL    ILPRT
  1376.     DB    CR,LF,LF,'    ',0
  1377.            CALL    RVBLNK
  1378.     CALL    ILPRT
  1379.     DB    '++ List Empty ++',0
  1380.         CALL    NORM
  1381.     CALL    ILPRT
  1382.     DB    CR,LF,LF,0
  1383.         CALL    BLBLNK
  1384.     CALL    ILPRT
  1385.     DB    ' --->  ',0
  1386.     CALL    NORM
  1387.     JMP    LOG        ;go to drive/user area with files
  1388.  
  1389. ; r e n a m e
  1390.  
  1391. ; set-up to rename file at cursor position -- scan keyboard buffer and
  1392. ; move filename to 'rename' destination 'fcb' (dfcb)
  1393.  
  1394. RENAME    LHLD    RINGPOS        ;move name from ring to rename 'fcb'
  1395.     LXI    D,-13
  1396.     DAD    D        ;point to name position
  1397.     LXI    D,D$FCB        ;place to move name
  1398.     MVI    B,12        ;amount to move
  1399.     CALL    MOVE
  1400.     CALL       BOLD
  1401.     CALL    ILPRT        ;new name prompt
  1402.     DB    BS,'Rename file to: ',0
  1403.     CALL    NORM
  1404.     LXI    D,CMDBUF    ;command line location
  1405.     MVI    C,RDBUF        ;console read-buffer function
  1406.     CALL    BDOS
  1407.     CALL    CONVERT        ;capitalize alpha
  1408.     LXI    H,D$FCB+16    ;set drive to null as..
  1409.     MVI    M,0        ;..required by 'bdos'.
  1410.     INX    H
  1411.  
  1412. ; initialize new filename field with spaces
  1413.  
  1414.     PUSH    H        ;save start pointer
  1415.     MVI    B,11        ; # of spaces to 'blank'
  1416.     CALL    FILL
  1417.     POP    H
  1418.     XCHG
  1419.     LXI    H,CMDBUF+1    ;put length..
  1420.     MOV    C,M        ;..in c-reg.
  1421.     INX    H
  1422.     XCHG            ;de-pair --> buffer pointer and hl-pair..
  1423.     CALL    UNSPACE        ;..--> 'fcb' pointer.  remove leading spaces.
  1424.  
  1425. ; extend buffer to spaces beyond command length
  1426.  
  1427. EXTEND    PUSH    H
  1428.     MOV    L,C        ;double-byte remaining length
  1429.     MVI    H,0
  1430.     DAD    D        ;to buffer end +1
  1431.     MVI    M,' '        ;force illegal character end
  1432.     POP    H
  1433.  
  1434. ; start filename scan
  1435.  
  1436. SCAN    MVI    B,8        ; 8 characters in filename
  1437. SCAN1    CALL    CKLEGAL        ;get and see if legal character
  1438.     JC    COMCAN        ;all of command line?
  1439.     CPI    ' '        ;see if end of parameter field
  1440.     JZ    CPYBITS        ;rename file
  1441.     CPI    '.'        ;at end of filename
  1442.     JZ    SCAN2        ;process filetype field
  1443.     MOV    M,A        ;put character into destination 'fcb'
  1444.     INX    H
  1445.     DCR    B        ;check name character count
  1446.     JNZ    SCAN1
  1447.  
  1448. ; entry if eight characters without a 'period'
  1449.  
  1450. SCAN1A    CALL    CKLEGAL        ;scan buffer up to period or end
  1451.     JC    CPYBITS        ;no extent if not legal
  1452.     CPI    ' '        ;end of parameter field?
  1453.     JZ    CPYBITS
  1454.     CPI    '.'
  1455.     JNZ    SCAN1A        ;do till end or period
  1456.  
  1457. ; build filetype field
  1458.  
  1459. SCAN2    MVI    B,3        ;length of filetype field
  1460.     LXI    H,D$FCB+25    ;destination 'rename' filetype start
  1461. SCAN3    CALL    CKLEGAL        ;get and check character
  1462.     JC    SCAN4        ;name done if illegal
  1463.     CPI    ' '        ;end of parameter field?
  1464.     JZ    SCAN4
  1465.     CPI    '.'        ;check if another period
  1466.     JZ    SCAN4
  1467.     MOV    M,A
  1468.     INX    H
  1469.     DCR    B
  1470.     JNZ    SCAN3        ;get next character
  1471. SCAN4    LXI    H,D$FCB+28    ;set pointer to 'rename' filetype end
  1472.     CALL    INITFCB        ;..and zero counter fields.
  1473.  
  1474. ; copy old file status bit ($r/o or $sys) to new filename
  1475.  
  1476. CPYBITS    LXI    D,D$FCB+1    ;first character of old name..
  1477.     LXI    H,D$FCB+17    ;..and of new name.
  1478.     MVI    C,11        ; # of bytes with tag bits
  1479. CBITS1    LDAX    D        ;fetch bit of old name character
  1480.     ANI    128        ;strip upper bit and..
  1481.     MOV    B,A        ;..save in b-reg.
  1482.     MVI    A,7FH        ;mask for character only
  1483.     ANA    M        ;put masked character into a-reg
  1484.     ORA    B        ;add old bit
  1485.     MOV    M,A        ;copy new byte back
  1486.     INX    H        ;bump copy pointers
  1487.     INX    D
  1488.     DCR    C        ;bump copy counter
  1489.     JNZ    CBITS1
  1490.  
  1491. ; check if new filename already exists.  if so, say so.  then go
  1492. ; to command loop without moving ring position
  1493.  
  1494.     LDA    D$FCB        ;copy new name to source 'fcb'
  1495.     STA    S$FCB
  1496.     MVI    B,11
  1497.     LXI    H,D$FCB+17    ;copy new name to..
  1498.     LXI    D,S$FCB+1    ;..source 'fcb' for existence check.
  1499.     CALL    MOVE
  1500.     LXI    H,S$FCB+12    ;clear cp/m 'fcb' system..
  1501.     CALL    INITFCB        ;..fields.
  1502.     LXI    D,S$FCB        ;search to see if this file exists
  1503.     MVI    C,SRCHF        ;search first function
  1504.     CALL    BDOS
  1505.     INR    A        ; 0ffh --> 00h if file not found
  1506.     JZ    RENFILE        ;to rename, if duplicate doesn't exists.
  1507.     CALL    ILPRT        ;announce the situation
  1508.     DB    CR,LF,0
  1509.         CALL    RVBLNK
  1510.     CALL    ILPRT
  1511.     DB    '++ FILE ALREADY EXISTS ++',0
  1512.         CALL    NORM
  1513.     CALL    ILPRT
  1514.     DB    CR,LF,BELL,'   ',0
  1515.     JMP    NEUTRAL        ;try again?
  1516.  
  1517. ; copy new name into ring position
  1518.  
  1519. RENFILE    LHLD    RINGPOS        ;get ring position pointer
  1520.     LXI    D,-12        ;back 12 leaves drive designation intact
  1521.     DAD    D
  1522.     XCHG
  1523.     LXI    H,D$FCB+17    ;point at new name and..
  1524.     MVI    B,11
  1525.     CALL    MOVE        ;..move.
  1526.     LXI    D,D$FCB        ;rename 'fcb' location
  1527.     MVI    C,REN        ;rename function
  1528.     CALL    BDOS
  1529.     INR    A        ; 0ffh --> 00h if rename error
  1530.     JNZ    NEUTRAL        ;if okay, proceed, else..
  1531.     JMP    FNF$MSG        ;..show no-file msg.
  1532.  
  1533. ; v i e w
  1534.  
  1535. ; type file to console with pagination set to 'lps' -- single-line scroll
  1536. ; using <space> bar , <ctrl-x> to cancel, any other key to page screen.
  1537.  
  1538. VIEW    CALL    ILPRT
  1539.     DB    CR,LF,0
  1540.     CALL    RVRSE
  1541.     CALL    ILPRT
  1542.     DB    '<CTRL-X> cancels, <space> turns up one line, '
  1543.     DB    'other keys page screen.',0
  1544.         CALL    NORM
  1545.     CALL     ILPRT
  1546.     DB    CR,LF,LF,0
  1547.     MVI    A,1        ;initialize..
  1548.     STA    LPSCNT        ;..lines-per-screen counter.
  1549.     STA    VIEWFLG        ; 'view' paginate if not zero
  1550.     MVI    A,WRCON        ;write console out function
  1551.     JMP    CURRENT        ;to common i/o processing
  1552.  
  1553. ; p r i n t e r
  1554.  
  1555. ; send file to logical list device -- any keypress cancels
  1556.  
  1557. LSTFILE    XRA    A        ;zero for..
  1558.     STA    VIEWFLG        ;..output to printer.
  1559.     MVI    A,LIST        ;out to 'list' device function
  1560.     JMP    CURRENT
  1561.  
  1562. ; p u n c h
  1563.  
  1564. ; write file to cp/m logical punch device
  1565.  
  1566. PUNFILE    XRA    A
  1567.     STA    VIEWFLG
  1568.     MVI    A,PUNCH        ;put to 'punch' device function
  1569.  
  1570. ; output character for console/list/punch processing
  1571.  
  1572. CURRENT    STA    CON$LST        ;save bdos function
  1573.  
  1574. ; output file to console/printer/punch
  1575.  
  1576.     CALL    RINGFCB        ;position name to 'fcb'
  1577.     LXI    D,TBUF        ;set to use default cp/m dma buffer
  1578.     MVI    C,SETDMA    ;address set function
  1579.     CALL    BDOS
  1580.     LXI    H,S$FCB+12    ;set pointer to source extent field
  1581.     CALL    INITFCB        ;fix-up 'fcb' before use
  1582.     LXI    D,S$FCB        ;open file for reading
  1583.     MVI    C,OPEN        ;file open function code
  1584.     CALL    BDOS
  1585.     INR    A        ; 0ffh --> 00h if open okay
  1586.     JNZ    ZEROCR        ;if not okay, show error message.
  1587.     CALL    RVBLNK
  1588.     CALL    ILPRT
  1589.     DB    '++ UNABLE TO OPEN FILE ++',0
  1590.     CALL    NORM
  1591.     JMP    NEUTRAL
  1592.  
  1593. ZEROCR    XRA    A        ;zero file 'current record' field
  1594.     STA    S$FCB+32
  1595. READMR    LXI    D,S$FCB        ;point at file 'fcb' for reading
  1596.     MVI    C,READ        ;record read function
  1597.     CALL    BDOS
  1598.     ORA    A        ;check if read okay
  1599.     JNZ    NEUTRAL        ;eof?
  1600.     LXI    H,TBUF        ;point at record just read
  1601.     MVI    B,128        ;set record character counter to output
  1602. READLP    MOV    A,M        ;get a character
  1603.     ANI    7FH        ;force to 'ascii'
  1604.     CPI    EOFCHAR        ;see if end-of-file
  1605.     JZ    NEUTRAL        ;back to ring loop if 'eof'
  1606.     MOV    E,A        ;put character for 'bdos' call
  1607.     PUSH    B
  1608.     PUSH    H
  1609.     PUSH    D        ; (character in e-reg)
  1610.     LDA    CON$LST        ;get function for punch/list/console output
  1611.     MOV    C,A
  1612.     CALL    BDOS        ;send character
  1613.     LDA    VIEWFLG        ;if 'view'..
  1614.     ORA    A
  1615.     POP    D
  1616.     CNZ    PAGER        ;..check for 'lf'.
  1617.     MVI    C,CONST        ;console status function
  1618.     CALL    BDOS        ;status?
  1619.     POP    H
  1620.     POP    B
  1621.     ORA    A        ;if character there, then abort..
  1622.     JNZ    NEUTRAL     ;..to same ring position.
  1623.     INX    H        ;if not, bump buffer pointer.
  1624.     DCR    B        ;all bytes of record sent yet?
  1625.     JNZ    READLP        ;no, more in present record.
  1626.     JMP    READMR        ;yes, get next record.
  1627.  
  1628. PAGER    MOV    A,E        ; (character in e-reg)
  1629.     CPI    LF
  1630.     RNZ
  1631.     LDA    LPSCNT        ;is counter..
  1632.     INR    A        ;..at..
  1633.     STA    LPSCNT        ;..limit..
  1634.     CPI    LPS        ;..of lines-per-screen?
  1635.     RC            ;no, return.
  1636.     XRA    A        ;yes, initialize..
  1637.     STA    LPSCNT        ;..for next screen full.
  1638.     CALL    RVRSE
  1639.     CALL    ILPRT
  1640.     DB    '  [more...]',CR,0    ;show msg line
  1641.     CALL    NORM
  1642.     CALL    DKEYIN        ;wait for keyboard input
  1643.     CPI    ' '        ;see if <space> bar..
  1644.     PUSH    PSW
  1645.     CALL    ILPRT
  1646.     DB    '           ',CR,0    ;clear above msg line
  1647.     POP    PSW
  1648.     JNZ    CANVIEW        ;..if not, see if cancel.
  1649.     MVI    A,LPS-1        ;if so, set up for single-line..
  1650.     STA    LPSCNT        ;..scroll and..
  1651.     RET            ;..return for one more line.
  1652.  
  1653. CANVIEW    CPI    ESC        ;escape?
  1654.     JZ    COMCAN
  1655.     CPI    CAN        ;cancel?
  1656.     JZ    COMCAN        ;retain ring position
  1657.     RET            ;return for another page
  1658.  
  1659. ; m a s s   c o p y
  1660.  
  1661. ; copy files tagged using the 't' command.  auto-erase if file exists
  1662. ; on requested destination drive or in user area.
  1663.  
  1664. MASS    LXI    H,RING+12    ;get 1st possible tag location
  1665.     SHLD    RINGPOS
  1666. MASS$LP    MVI    A,'*'
  1667.     CMP    M
  1668.     INX    H        ;get in filename synchronization
  1669.     SHLD    RINGPOS
  1670.     JZ    MCOPY        ;copy filename with tag character (*)
  1671. M$LP    LHLD    RINGPOS        ;re-entry point for next file mass-copy
  1672.     XCHG            ;at ring..
  1673.     LHLD    RINGEND        ;..end yet?
  1674.     CALL    CMPDEHL        ; (compare present position with end)
  1675.     JZ    MF$EXIT        ;yes, jump to beginning of ring.
  1676.     LHLD    RINGPOS
  1677.     JMP    MASS$LP        ;no, loop 'till thru ring list.
  1678.  
  1679. MF$EXIT    XRA    A        ;reset flags..
  1680.     STA    FIRST$M        ;..for..
  1681.     CMA            ;..next..
  1682.     STA    MFLAG        ;..mass-copy request.
  1683.     JMP    CMDLOOP        ;jump to 'ring' beginning
  1684.  
  1685. ; c o p y
  1686.  
  1687. ; copy source file at current 'ring' position to another drive.  set-up
  1688. ; fcb's and buffer area and check for correct keyboard inputs.  contains
  1689. ; auto-crc file copy verification.
  1690.  
  1691. MCOPY    XRA    A        ;zero flag to..
  1692.     STA    MFLAG        ;..mass copy.
  1693. COPY    LXI    H,0        ;initialize storage for..
  1694.     SHLD    CRCVAL        ;..'crc' working value.
  1695.     CALL    RINGFCB        ;move from 'ring' to 'sfcb'
  1696.     LXI    H,S$FCB+12    ;set pointer to source extent field
  1697.     CALL    INITFCB
  1698.     XRA    A        ;zero fcb 'cr' field
  1699.     STA    S$FCB+32
  1700.     MVI    B,32        ;copy source 'fcb' to destination 'fcb'
  1701.     LXI    H,S$FCB+1    ;from point..
  1702.     LXI    D,D$FCB+1    ;..to point..
  1703.     CALL    MOVE        ;..move across.
  1704.     LXI    D,S$FCB        ;open file for reading
  1705.     MVI    C,OPEN        ;open function
  1706.     CALL    BDOS
  1707.     INR    A        ; 0ffh --> 00h if bad open
  1708.     JNZ    COPY2        ;if okay, skip error message.
  1709.     CALL    ILPRT
  1710.     DB    '      ',0
  1711.     CALL    RVBLNK
  1712.     CALL    ILPRT
  1713.     DB    '++ UNABLE TO OPEN SOURCE ++',0
  1714.       CALL    NORM
  1715.     CALL    ILPRT
  1716.     DB     CR,LF,0
  1717.     JMP    NEUTRAL
  1718.  
  1719. COPY2    LDA    FIRST$M        ;by-pass prompt, drive/user compatibility..
  1720.     ORA    A        ;..test, and disk reset after..
  1721.     JNZ    COPY3M        ;..1st time thru in mass-copy mode.
  1722.     CALL    BOLD
  1723.     CALL    ILPRT        ;prompt for drive selection
  1724.     DB    BS,'Copy to drive/user: ',0
  1725.     CALL    NORM
  1726.     CALL    DEF$D$U
  1727.  
  1728. ; either drives or user areas must be different
  1729.  
  1730.     LDA    FCB        ;get requested drive from 'fcb' and..
  1731.     MOV    B,A        ;..put into b-reg for..
  1732.     LDA    S$FCB        ;..comparison.
  1733.     CMP    B
  1734.     JNZ    COPY3        ;branch if different
  1735.     LDA    R$U$A        ;requested user area --> rua
  1736.     MOV    B,A
  1737.     LDA    C$U$A        ;current user area --> cua
  1738.     CMP    B
  1739.     JNZ    COPY3
  1740.     CALL    ILPRT        ;if not, show error condition:
  1741.     DB    CR,LF,BELL,0
  1742.     CALL    RVBLNK
  1743.         CALL    ILPRT
  1744.         DB    '++ Drives or User Areas must be different ++',0
  1745.     CALL    NORM
  1746.     JMP    NEUTRAL        ;try again?
  1747.  
  1748. COPY3    CALL    RESET        ;make sure disk is read/write
  1749. COPY3M    LDA    FCB        ;put requested drive into..
  1750.     STA    D$FCB        ;..place in destination fcb.
  1751.     LDA    R$U$A        ;toggle to..
  1752.     CALL    SET$USR        ;..requested user area.
  1753.     LDA    MFLAG        ;auto-erase..
  1754.     ORA    A        ;..if..
  1755.     JZ    COPY4M        ;..in mass-copy mode.
  1756.     LXI    D,D$FCB        ;search for duplicate
  1757.     MVI    C,SRCHF        ; 'search first' function
  1758.     CALL    BDOS
  1759.     INR    A        ;if not found, 0ffh --> 00h.  then..
  1760.     JZ    COPY5        ;go to 'make' function for new file.
  1761.     CALL     BLBLNK
  1762.     CALL    ILPRT        ;if found, ask to replace:
  1763.     DB    CR,LF,' ---> Copy exists, erase? (Y/N): ',0
  1764.     CALL    NORM
  1765.     CALL    KEYIN        ;get answer
  1766.     CPI    'Y'        ;if yes, then..
  1767.     JZ    COPY4M        ;..delete and overlay.
  1768.     LDA    C$U$A        ;reset to..
  1769.     CALL    SET$USR        ;..current user area.
  1770.     JMP    FORWARD        ;if re-copy not wanted, to next position.
  1771.  
  1772. COPY4M    LXI    D,D$FCB        ;delete file already existing
  1773.     MVI    C,ERASE        ;erase function
  1774.     CALL    BDOS
  1775. COPY5    LXI    D,D$FCB        ;create new file and open for writing
  1776.     MVI    C,MAKE        ;make function
  1777.     CALL    BDOS
  1778.     INR    A        ;if directory full, 0ffh --> 00h.
  1779.     JNZ    COPY6        ;if not, branch.
  1780.     CALL    ILPRT
  1781.     DB    '      ',0
  1782.     CALL    RVBLNK
  1783.     CALL    ILPRT
  1784.     DB    '++ Destination Directory Full ++',0
  1785.     CALL    NORM
  1786.     CALL    ILPRT
  1787.     DB    CR,LF,0
  1788.     JMP    NEUTRAL        ;if error, back to ring processor.
  1789.  
  1790. COPY6    MVI    B,8        ;show filename and..
  1791.     LXI    H,D$FCB+1
  1792.     LXI    D,COPYMFN
  1793.     CALL    MOVE
  1794.     INX    D
  1795.     MVI    B,3        ;..filetype during copy.
  1796.     CALL    MOVE
  1797.     LDA    FIRST$M        ;if 1st time thru mass-copy..
  1798.     ORA    A        ;..mode, add..
  1799.     MVI    A,LF        ;..a line feed.
  1800.     CZ    TYPE
  1801.     CALL    CLR$L        ;clear line
  1802.     CALL    BOLD
  1803.     CALL    ILPRT
  1804.     DB    CR,' ---> Copying file    ',0
  1805.     CALL    BLBLNK
  1806.     CALL    ILPRT
  1807. COPYMFN    DB    '        .    ',0
  1808.     CALL    NORM
  1809.     XRA    A        ;clear 'eof'..
  1810.     STA    EOFLAG        ;..flag.
  1811. COPY6A    LDA    C$U$A        ;reset user area..
  1812.     CALL    SET$USR        ;..to current.
  1813.     LXI    H,0        ;clear current-record..
  1814.     SHLD    REC$CNT        ;..counter.
  1815.     LHLD    BUFSTART    ;set buffer start pointer..
  1816.     SHLD    BUF$PT        ;..to begin pointer.
  1817.  
  1818. ; read source file -- fill buffer memory or stop on 'eof' -- update 'crc'
  1819. ; on-the-fly
  1820.  
  1821. COPY7    LHLD    BUF$PT        ;set dma address to buffer pointer
  1822.     XCHG            ; de-pair --> dma address
  1823.     MVI    C,SETDMA
  1824.     CALL    BDOS
  1825.     LXI    D,S$FCB        ;source 'fcb' for reading
  1826.     MVI    C,READ        ;record read function
  1827.     CALL    BDOS
  1828.     ORA    A        ; 00h --> read okay
  1829.     JZ    S$RD$OK
  1830.     DCR    A        ;eof?
  1831.     JZ    COPY8        ;yes, end-of-file, set 'eof' flag.
  1832.     CALL    ILPRT
  1833.     DB    '      ',0
  1834.     CALL     RVBLNK
  1835.     CALL    ILPRT
  1836.     DB    '++ SOURCE READ ERROR ++',0
  1837.     CALL    NORM
  1838.     CALL    ILPRT
  1839.     DB    CR,LF,BELL,0
  1840.     JMP    NEUTRAL
  1841.  
  1842. S$RD$OK    LHLD    BUF$PT
  1843.     MVI    B,128
  1844. COPY7A    MOV    A,M        ;get character and..
  1845.     CALL    UPDCRC        ;..add to 'crc' value.
  1846.     INX    H
  1847.     DCR    B
  1848.     JNZ    COPY7A        ;loop 'till record read finished
  1849.     LHLD    BUF$PT        ;bump buffer pointer..
  1850.     LXI    D,128        ;..by..
  1851.     DAD    D        ;..one..
  1852.     SHLD    BUF$PT        ;..record.
  1853.     LHLD    REC$CNT        ;bump buffer..
  1854.     INX    H        ;..record count and..
  1855.     SHLD    REC$CNT        ;..store.
  1856.     XCHG            ;ready to compare to..
  1857.     LHLD    REC$MAX        ;..maximum record count (full-buffer).
  1858.     CALL    CMPDEHL        ;compare
  1859.     JNZ    COPY7        ;if not full, get next record.
  1860.     JMP    COPY9        ;full, start first write session.
  1861.  
  1862. ; indicate end-of-file read
  1863.  
  1864. COPY8    MVI    A,TRUE        ;set 'eof' flag
  1865.     STA    EOFLAG
  1866.  
  1867. ; write 'read-file' from memory buffer to destination 'written-file'
  1868.  
  1869. COPY9    LDA    R$U$A        ;set user to requested..
  1870.     CALL    SET$USR        ;..area.
  1871.     LHLD    BUFSTART    ;adjust buffer pointer..
  1872.     SHLD    BUF$PT        ;..to start address.
  1873. COPY10    LHLD    REC$CNT        ;buffer empty?
  1874.     MOV    A,H
  1875.     ORA    L
  1876.     JZ    COPY11        ;buffer empty, check 'eof' flag.
  1877.     DCX    H        ;dec buffer record count for each write
  1878.     SHLD    REC$CNT
  1879.     LHLD    BUF$PT        ;set up dma address
  1880.     PUSH    H        ;save for size bump
  1881.     XCHG            ;pointer in de-pair
  1882.     MVI    C,SETDMA
  1883.     CALL    BDOS
  1884.     POP    H
  1885.     LXI    D,128        ;bump pointer one record length
  1886.     DAD    D
  1887.     SHLD    BUF$PT
  1888.     LXI    D,D$FCB        ;destination file 'fcb'
  1889.     MVI    C,WRITE        ;write record function
  1890.     CALL    BDOS
  1891.     ORA    A           ; 00h --> write okay
  1892.     JZ    COPY10        ;okay, do next record.  else..
  1893.     CALL    ILPRT        ;..say disk write error.
  1894.     DB    '      ',0
  1895.     CALL    RVBLNK
  1896.     CALL    ILPRT
  1897.     DB    '++ COPY DISK FULL ++',0
  1898.     CALL    NORM
  1899.     CALL     ILPRT
  1900.     DB    CR,LF,BELL,0
  1901. C$ERA    LXI    D,D$FCB        ;delete..
  1902.     MVI    C,ERASE        ;..partial..
  1903.     CALL    BDOS        ;..from directory.
  1904.     XRA    A              ;reset 1st-time-thru tag flag..
  1905.     STA    FIRST$M        ;..for continuation of mass copying.
  1906.     JMP    NEUTRAL        ;back to ring
  1907.  
  1908. COPY11    LDA    EOFLAG        ;buffer all written, check for 'eof'.
  1909.     ORA    A
  1910.     JZ    COPY6A        ;branch to read next buffer full
  1911.     LXI    D,D$FCB        ;point at 'fcb' for file closure
  1912.     MVI    C,CLOSE
  1913.     CALL    BDOS
  1914.     INR    A        ;if no-close-error then..
  1915.     JNZ    CRC$CMP        ;..compare file crc's.
  1916.     CALL    ILPRT
  1917.     DB    '      ',0
  1918.     CALL    RVBLNK
  1919.     CALL    ILPRT
  1920.     DB    '++ COPY CLOSE ERROR ++',0
  1921.     CALL    NORM
  1922.     CALL     ILPRT
  1923.     DB    CR,LF,BELL,0
  1924.     JMP    C$ERA
  1925.  
  1926. ; read destination 'written-file' and compare crc's
  1927.  
  1928. CRC$CMP    LHLD    CRCVAL        ;transfer 'crc' value to..
  1929.     SHLD    CRCVAL2        ;..new storage area.
  1930.     LXI    H,0        ;clear working storage..
  1931.     SHLD    CRCVAL        ;..to continue.
  1932.     LXI    D,TBUF
  1933.     MVI    C,SETDMA
  1934.     CALL    BDOS
  1935.     LXI    H,D$FCB+12
  1936.     CALL    INITFCB
  1937.     LXI    D,D$FCB
  1938.     MVI    C,OPEN
  1939.     CALL    BDOS
  1940.     INR    A        ; 0ffh --> 00h if bad open
  1941.     JZ    BADCRC        ;if bad open, just say 'bad-crc'.
  1942.     XRA    A        ;zero 'fcb'..
  1943.     STA    D$FCB+32    ;..'cr' field.
  1944. CRCWF1    LXI    D,D$FCB
  1945.     MVI    C,READ
  1946.     CALL    BDOS
  1947.     ORA    A        ;read okay?
  1948.     JZ    D$RD$OK        ;yes, read more.
  1949.     DCR    A        ;eof?
  1950.     JZ    FINCRC        ;yes, finish up and make 'crc' comparison.
  1951.     CALL    ILPRT
  1952.     DB    '      ',0
  1953.     CALL    RVBLNK
  1954.     CALL    ILPRT
  1955.     DB    '++ COPY READ ERROR ++',0
  1956.     CALL    NORM
  1957.     CALL    ILPRT
  1958.     DB    CR,LF,BELL,0
  1959.     JMP    NEUTRAL
  1960.  
  1961. D$RD$OK    LXI    H,TBUF
  1962.     MVI    B,128
  1963. CRCWF2    MOV    A,M        ;get character to..
  1964.     CALL    UPDCRC        ;..add to 'crc' value. 
  1965.     INX    H
  1966.     DCR    B
  1967.     JNZ    CRCWF2
  1968.     JMP    CRCWF1
  1969.  
  1970. ; crc subroutines
  1971.  
  1972. ; initialize tables for fast crc calculations
  1973.  
  1974. INITCRC    LXI    H,CRCTBL
  1975.     MVI    C,0        ;table index
  1976. GLOOP    XCHG
  1977.     LXI    H,0        ;initialize crc register pair
  1978.     MOV    A,C
  1979.     PUSH    B        ;save index in c-reg
  1980.     MVI    B,8
  1981.     XRA    H
  1982.     MOV    H,A
  1983. LLOOP    DAD    H
  1984.     JNC    LSKIP
  1985.     MVI    A,10H        ;generator is x^16 + x^12 + x^5 + x^0 as..
  1986.     XRA    H        ;..recommended by ccitt for asynchronous..
  1987.     MOV    H,A        ;..communications.  produces the same..
  1988.     MVI    A,21H        ;..results as public domain programs..
  1989.     XRA    L        ;..chek, comm7, mdm7, and modem7.
  1990.     MOV    L,A
  1991. LSKIP    DCR    B
  1992.     JNZ    LLOOP
  1993.     POP    B
  1994.     XCHG            ;de-pair now has crc, hl pointing into table.
  1995.     MOV    M,D        ;store high byte of crc..
  1996.     INR    H
  1997.     MOV    M,E        ;..and store low byte.
  1998.     DCR    H
  1999.     INX    H        ;move to next table entry
  2000.     INR    C        ;next index
  2001.     JNZ    GLOOP
  2002.     RET
  2003.  
  2004. UPDCRC    PUSH    B        ;update 'crc'..
  2005.     PUSH    H        ;..accumulator..
  2006.     LHLD    CRCVAL        ;pick up partial remainder
  2007.     XCHG            ;de-pair now has partial
  2008.     MVI    B,0
  2009.     XRA    D
  2010.     MOV    C,A
  2011.     LXI    H,CRCTBL
  2012.     DAD    B
  2013.     MOV    A,M
  2014.     XRA    E
  2015.     MOV    D,A
  2016.     INR    H
  2017.     MOV    E,M
  2018.     XCHG
  2019.     SHLD    CRCVAL
  2020.     POP    H
  2021.     POP    B
  2022.     RET
  2023.  
  2024. FINCRC    LDA    C$U$A        ;reset user from 'requested'..
  2025.     CALL    SET$USR        ;..to 'current' area.
  2026.     LHLD    CRCVAL        ;put written-file 'crc' into..
  2027.     XCHG            ;..de-pair.
  2028.     LHLD    CRCVAL2        ;put read-file 'crc' and..
  2029.     CALL    CMPDEHL        ;..compare 'de/hl' for equality.
  2030.     JNZ    BADCRC        ;if not zero, show copy-error message.
  2031.     CALL     BOLD
  2032.     CALL    ILPRT        ;if zero, show 'verified' message.
  2033.     DB    '      CRC verified',CR,LF,0
  2034.     CALL    NORM
  2035.     LDA    MFLAG        ;if not mass-copy mode, return..
  2036.     ORA    A        ;..to next 'ring' position.
  2037.     JNZ    FORWARD        ;else..
  2038.     CMA            ;..set 1st-time-thru flag..
  2039.     STA    FIRST$M        ;..and..
  2040.     JMP    M$LP        ;..get next file to copy, if one.
  2041.  
  2042. BADCRC    CALL    ILPRT
  2043.     DB    '      ',0
  2044.     CALL    RVBLNK
  2045.     CALL    ILPRT
  2046.     DB     '++ Error on CRC compare ++',0
  2047.     CALL    NORM
  2048.     CALL    ILPRT
  2049.     DB    CR,LF,BELL,0
  2050.     JMP    FORWARD        ;move to next 'ring' position
  2051.  
  2052. ; w o r k h o r s e   r o u t i n e s
  2053.  
  2054. ; inline print of message
  2055.  
  2056. ILPRT    XTHL            ;save hl, get msg pointer.
  2057. ILPLP    MOV    A,M        ;get character
  2058.     ANI    7FH        ;strip type bits
  2059.     CALL    TYPE        ;show on console
  2060.     INX    H        ;point to the next character and..
  2061.     MOV    A,M
  2062.     ORA    A        ;..test for end-of-text.
  2063.     JNZ    ILPLP
  2064.     XTHL            ;set hl-pair and..
  2065.     RET            ;..return past message.
  2066.  
  2067. ; clear console crt screen
  2068.  
  2069. CLS    CALL    ILPRT        ;Rainbow 100 esc sequences to clear screen
  2070.          DB    RAIN1,RAIN2,RAIN3,RAIN4,RAIN1,RAIN2,RAIN5,0
  2071.     RET
  2072. NORM    CALL    ILPRT
  2073.     DB    RAIN1,RAIN2,RAIN6,RAIN11,0
  2074.     RET
  2075. BOLD    CALL    ILPRT
  2076.     DB    RAIN1,RAIN2,RAIN7,RAIN11,0
  2077.     RET
  2078. RVRSE    CALL    ILPRT
  2079.     DB    RAIN1,RAIN2,RAIN9,RAIN10,RAIN7,RAIN11,0
  2080.     RET
  2081. RVBLNK    CALL    ILPRT
  2082.     DB    RAIN1,RAIN2,RAIN9,RAIN10,RAIN7,RAIN10,RAIN8,RAIN11,0
  2083.     RET
  2084. BLBLNK  CALL    ILPRT
  2085.     DB    RAIN1,RAIN2,RAIN7,RAIN10,RAIN8,RAIN11,0
  2086.     RET
  2087.  
  2088. LFLP    MVI    A,LF
  2089.     CALL    TYPE
  2090.     DCR    B        ;count-down b-reg --> zero
  2091.     JNZ    LFLP
  2092.     RET
  2093.  
  2094. ; output 'crlf' to console
  2095.  
  2096. CRLF    MVI    A,CR
  2097.     CALL    TYPE
  2098.     MVI    A,LF
  2099.  
  2100. ; conout routine (re-entrant)
  2101.  
  2102. TYPE    PUSH    PSW
  2103.     PUSH    B
  2104.     PUSH    D
  2105.     PUSH    H
  2106.     MOV    E,A
  2107.     MVI    C,WRCON
  2108.     CALL    BDOS
  2109.     POP    H
  2110.     POP    D
  2111.     POP    B
  2112.     POP    PSW
  2113.     RET
  2114.  
  2115. ; crt clear-line function
  2116.  
  2117. CLR$L    MVI    A,CR
  2118.     CALL    TYPE
  2119.     MVI    B,30        ;blank # of characters on line
  2120.     MVI    A,' '
  2121. CL$LP    CALL    TYPE
  2122.     DCR    B
  2123.     JNZ    CL$LP
  2124.     RET
  2125.  
  2126. ; conin routine (waits for response)
  2127.  
  2128. KEYIN    MVI    C,RDCON
  2129.     CALL    BDOS
  2130.  
  2131. ; convert character in a-reg to upper case
  2132.  
  2133. UCASE    CPI    61H        ;less than small 'a'?
  2134.     RC            ;if so, no convert needed.
  2135.     CPI    7AH+1        ; >small 'z'?
  2136.     RNC            ;if so, ignore.
  2137.     ANI    5FH        ;otherwise convert
  2138.     RET
  2139.  
  2140. ; direct console input w/o echo (waits for input)
  2141.  
  2142. DKEYIN    MVI    C,DIRCON    ;cp/m function 6
  2143.     MVI    E,0FFH
  2144.     CALL    BDOS
  2145.     ORA    A
  2146.     JZ    DKEYIN
  2147.     RET
  2148.  
  2149. ; convert keyboard input to upper case
  2150.  
  2151. CONVERT    LXI    H,CMDBUF+1    ; 'current keyboard buffer length'..
  2152.     MOV    B,M        ;..to b-reg.
  2153.     MOV    A,B
  2154.     ORA    A        ;if zero length, skip conversion.
  2155.     JZ    COMCAN
  2156. CONVLP    INX    H        ;point at character to capitalize
  2157.     MOV    A,M
  2158.     CALL    UCASE
  2159.     MOV    M,A        ;put back into buffer
  2160.     DCR    B
  2161.     JNZ    CONVLP
  2162.     RET
  2163.  
  2164. ; fill buffer with 'spaces' with count in b-reg
  2165.  
  2166. FILL    MVI    M,' '        ;put in space character
  2167.     INX    H
  2168.     DCR    B        ;count done?
  2169.     JNZ    FILL        ;no, branch.
  2170.     RET
  2171.  
  2172. ; ignore leading spaces (ls) in buffer, length in c-reg.
  2173.  
  2174. UNSPACE    LDAX    D        ;get character
  2175.     CPI    ' '
  2176.     RNZ            ;not blank, a file is entered.
  2177.     INX    D        ;to next character
  2178.     DCR    C
  2179.     JZ    COMCAN        ;all spaces --> command recovery error
  2180.     JMP    UNSPACE
  2181.  
  2182. ; check for legal cp/m filename character -- return with carry set if illegal
  2183.  
  2184. CKLEGAL    LDAX    D        ;get character from de-pair
  2185.     INX    D        ;point at next character
  2186.     CPI    ' '        ;less than space?
  2187.     RC            ;return carry if unpermitted character
  2188.     PUSH    H
  2189.         PUSH    B
  2190.     CPI    '['        ;if greater than 'z', exit with..
  2191.     JNC    CKERR        ;..carry set.
  2192.     MVI    B,8
  2193.     LXI    H,CHR$TBL
  2194. CHR$LP    CMP    M  
  2195.     JZ    CKERR
  2196.     INX    H
  2197.     DCR    B
  2198.     JNZ    CHR$LP
  2199.     ORA    A        ;clear carry for good character
  2200.     POP    B
  2201.     POP    H
  2202.     RET
  2203.  
  2204. CKERR    POP    B
  2205.     POP    H
  2206.     STC                 ;error exit with carry set
  2207.     RET
  2208.  
  2209. CHR$TBL    DB    '*',',',':',';','<','=','>','?'    ;invalid character table
  2210.  
  2211. ; filename from 'ring' to 'sfcb'
  2212.  
  2213. RINGFCB    LHLD    RINGPOS        ;move name from ring to source 'fcb'
  2214.     LXI    D,-13        ;subtract 13 to..
  2215.     DAD    D        ;..point to name position.
  2216.     LXI    D,S$FCB        ;place to move filename and..
  2217.     MVI    B,12        ;..amount to move.
  2218.  
  2219. ; move subroutine -- move b-reg # of bytes from hl-pair to de-pair
  2220.  
  2221. MOVE    MOV    A,M        ;get hl-pair referenced source byte
  2222.     ANI    7FH        ;strip cp/m 2.x attributes
  2223.     STAX    D        ;put to de-pair referenced destination
  2224.     INX    H        ;fix pointers for next search
  2225.     INX    D
  2226.     DCR    B        ;dec byte count and see if done
  2227.     JNZ    MOVE
  2228.     RET
  2229.  
  2230. ; initialize 'fcb' cp/m system fields (entry with hl-pair pointing to 'fcb')
  2231.  
  2232. INITFCB    MVI    B,4        ;fill ex, s1, s2, rc counters with zeros.
  2233. INITLP    MVI    M,0        ;put zero (null) in memory
  2234.     INX    H
  2235.     DCR    B
  2236.     JNZ    INITLP
  2237.     RET
  2238.  
  2239. ; disk system reset -- login requested drive
  2240.  
  2241. RESET    MVI    C,INQDISK    ;determine and..
  2242.     CALL    BDOS        ;..save..
  2243.     STA    C$DR        ;..current drive.
  2244.     MVI    C,RESETDK    ;reset system
  2245.     CALL    BDOS
  2246.     LDA    R$DR        ;make requested drive..
  2247. SET$DR    MOV    E,A        ;..current.
  2248.     MVI    C,LOGIN
  2249.     JMP    BDOS        ;return to caller
  2250.  
  2251. ; set/reset (or get) user area (call with binary user area in a-reg)
  2252.  
  2253. SET$USR    MOV    E,A        ; 0 --> 0, 1 --> 1, etc.
  2254. GET$USR    MVI    C,SGUSER
  2255.     JMP    BDOS        ;return to caller
  2256.  
  2257. ; compare de-pair to hl-pair and set flags accordingly
  2258.  
  2259. CMPDEHL    MOV    A,D        ;see if high bytes set flags
  2260.     CMP    H
  2261.     RNZ            ;return if not equal
  2262.     MOV    A,E
  2263.     CMP    L        ;low bytes set flags instead
  2264.     RET
  2265.  
  2266. ; shift hl-pair b-reg bits (-1) to right (divider routine)
  2267.  
  2268. SHIFTLP    DCR    B
  2269.     RZ
  2270.     MOV    A,H
  2271.     ORA    A
  2272.     RAR
  2273.     MOV    H,A
  2274.     MOV    A,L
  2275.     RAR
  2276.     MOV    L,A
  2277.     JMP    SHIFTLP
  2278.  
  2279. ; decimal pretty print (h-reg contains msb; l-reg, the lsb.)
  2280.  
  2281. DECOUT    PUSH    PSW
  2282.     PUSH    B
  2283.     PUSH    D
  2284.     PUSH    H
  2285.     LXI    B,-10        ;radix
  2286.     LXI    D,-1
  2287. DECOU2    DAD    B        ;sets..
  2288.     INX    D
  2289.     JC    DECOU2        ;..carry.    
  2290.     LXI    B,10
  2291.     DAD    B
  2292.     XCHG
  2293.     MOV    A,H
  2294.     ORA    L
  2295.     CNZ    DECOUT        ; (recursive)
  2296.     MOV    A,E
  2297.     ADI    '0'        ;make ascii
  2298.     CALL    TYPE
  2299.     POP    H
  2300.     POP    D
  2301.     POP    B
  2302.     POP    PSW
  2303.     RET
  2304.  
  2305. ; determine # of bcd digits in hl-pair -- place # in b-reg
  2306.  
  2307. DET$BCD    LXI    D,9        ;test for less than 10
  2308.     CALL    CMPDEHL        ;compare and..
  2309.     MVI    B,1        ; (one bcd digit)
  2310.     RNC                ;..return if not carry.
  2311.     MVI    E,99        ;less than 100?
  2312.     CALL    CMPDEHL
  2313.     MVI    B,2
  2314.     RNC
  2315.     LXI    D,999        ; <1000?
  2316.     CALL    CMPDEHL
  2317.     MVI    B,3
  2318.     RNC
  2319.     MVI    B,4        ;assume >999  (4 digits)
  2320.     RET
  2321.  
  2322. ; determine free storage remaining on selected drive
  2323.  
  2324. FRESTOR    MVI    C,INQDISK    ;determine current drive
  2325.     CALL    BDOS        ;returns 0 as a:, 1 as b:, etc.
  2326.     INR    A        ;make 1 --> a:, 2 --> b:, etc.
  2327.     STA    FCB
  2328.     ADI    'A'-1        ;make printable and..
  2329.     STA    DRNAME        ;..use as drive designator.
  2330.     MVI    C,GETPARM    ;current disk parameter block
  2331.     CALL    BDOS
  2332.     INX    H        ;bump to..
  2333.     INX    H
  2334.     MOV    A,M        ;..block shift factor.
  2335.     STA    BSHIFTF        ; 'bsh'
  2336.     INX    H        ;bump to..
  2337.     MOV    A,M        ;..block mask.
  2338.     STA    B$MASK        ; 'blm'
  2339.     INX    H        ;bump to..
  2340.     INX    H        ;..get..
  2341.     MOV    E,M        ;..maximum block number..
  2342.     INX    H        ;..double..
  2343.     MOV    D,M        ;..byte.
  2344.     XCHG
  2345.     SHLD    B$MAX        ; 'dsm'
  2346.     MVI    C,INQALC    ;address of cp/m allocation vector
  2347.     CALL    BDOS
  2348.     XCHG            ;get its length
  2349.     LHLD    B$MAX
  2350.     INX    H
  2351.     LXI    B,0        ;initialize block count to zero
  2352. GSPBYT    PUSH    D        ;save allocation address
  2353.     LDAX    D
  2354.     MVI    E,8        ;set to process 8 bits (blocks)
  2355. GSPLUP    RAL            ;test bit
  2356.     JC    NOT$FRE
  2357.     INX    B
  2358. NOT$FRE    MOV    D,A        ;save bits
  2359.     DCX    H
  2360.     MOV    A,L
  2361.     ORA    H    
  2362.     JZ    END$ALC        ;quit if out of blocks
  2363.     MOV    A,D        ;restore bits
  2364.     DCR    E        ;count down 8 bits
  2365.     JNZ    GSPLUP        ;branch to do another bit
  2366.     POP    D        ;bump to next count..
  2367.     INX    D        ;..of allocation vector.
  2368.     JMP    GSPBYT        ;process it
  2369.  
  2370. END$ALC    POP    D        ;clear alloc vector pointer from stack
  2371.     MOV    L,C        ;copy # blocks to hl-pair
  2372.     MOV    H,B
  2373.     LDA    BSHIFTF        ;get block shift factor
  2374.     SUI    3        ;convert from sectors to thousands (k)
  2375.     JZ    PRT$FRE        ;skip shifts if 1k blocks
  2376. FREK$LP    DAD    H        ;multiply blocks by k-bytes per block
  2377.     DCR    A        ;multiply by 2, 4, 8, or 16.
  2378.     JNZ    FREK$LP
  2379. PRT$FRE    CALL    BOLD
  2380.     CALL     DECOUT        ; # of free k-bytes in hl-pair
  2381.     CALL    ILPRT
  2382.     DB    'k bytes free on drive '
  2383. DRNAME    DB    ' :',CR,LF,'   ',0
  2384.     CALL    NORM
  2385.     RET
  2386.  
  2387. ; s t o r a g e
  2388.  
  2389. ; initialized
  2390.  
  2391. JOKER     DB    '???????????'    ; *.* equivalent
  2392. J$FLG     DB    TRUE        ;default jump 22-files command flag
  2393. FIRST$M     DB    FALSE        ; 1st time thru in mass-copy mode
  2394. MFLAG     DB    TRUE        ;multiple file copy flag --> 0 for mass copy
  2395. TAG$TOT     DW    0        ;summation of tagged file sizes
  2396. CMDBUF     DB    32,0        ;command buffer maximum length, usage, and..
  2397.  
  2398. ; uninitialized
  2399.  
  2400.      DS    100        ;..storage for buffer and local stack.
  2401. STACK     DS    2        ;cp/m's stack pointer stored here
  2402. B$MAX     DS    2        ;highest block number on drive
  2403. B$MASK     DS    1        ;sec/blk - 1
  2404. BSHIFTF     DS    1        ; # of shifts to multiply by sec/blk
  2405. BUF$PT     DS    2        ;copy buffer current pointer..
  2406. BUFSTART DS    2        ;..and begin pointer.
  2407. CANFLG     DS    1        ;no-file-found cancel flag
  2408. C$DR     DS    1        ; 'current drive'
  2409. CON$LST     DS    1        ;bdos function storage
  2410. CRCTBL     DS    512        ;tables for 'crc' calculations
  2411. CRCVAL     DS    2        ; 2-byte 'crc' value of working file and..
  2412. CRCVAL2     DS    2        ;..of finished source read-file.
  2413. C$U$A     DS    1        ; 'current user area'
  2414. D$FCB     DS    33        ;fcb for destination file/new name if rename
  2415. EOFLAG     DS    1        ;file copy loop 'eof' flag
  2416. FS$FLG     DS    1        ;tag total versus file size flag
  2417. J$CNT     DS    1        ;jump forward file counter
  2418. LPSCNT     DS    1        ;lines-per-screen for 'view'
  2419. O$USR     DS    1        ;store initial user area for exit
  2420. R$DR     DS    1        ; 'requested drive'
  2421. RCNT     DS    2        ; # of records in file and..
  2422. REC$CNT     DS    2        ;..currently in ram buffer.
  2423. REC$MAX     DS    2        ;maximum 128-byte record capacity of buffer
  2424. RINGI     DS    2        ;ring sort pointer
  2425. RINGJ     DS    2        ;another ring sort pointer
  2426. RINGEND     DS    2        ;current ring end pointer
  2427. RINGPOS     DS    2        ;current ring position in scan
  2428. R$U$A     DS    1        ; 'requested user area'
  2429. S$FCB     DS    36        ;fcb for source (random record) file
  2430. TEST$RT     DS    1        ;intermediate right-justify data
  2431. T$UN$FG     DS    1        ;tag/untag file summation switch
  2432. VIEWFLG     DS    1        ; 00h --> to list/punch else to crt 'view'
  2433.  
  2434. ; cp/m system functions
  2435.  
  2436. RDCON    EQU    1        ;console input function
  2437. WRCON    EQU    2        ;write character to console..
  2438. PUNCH    EQU    4        ;..punch and..
  2439. LIST    EQU    5        ;..to list logical devices.
  2440. DIRCON    EQU    6        ;direct console i/o
  2441. RDBUF    EQU    10        ;read input string
  2442. CONST    EQU    11        ;get console status
  2443. RESETDK    EQU    13        ;reset disk system
  2444. LOGIN    EQU    14        ;log-in new drive
  2445. OPEN    EQU    15        ;open file
  2446. CLOSE    EQU    16        ;close file
  2447. SRCHF    EQU    17        ;search directory for first..
  2448. SRCHN    EQU    18        ;..and next occurrence.
  2449. ERASE    EQU    19        ;erase file
  2450. READ    EQU    20        ;read and..
  2451. WRITE    EQU    21        ;..write 128-record.
  2452. MAKE    EQU    22        ;make file
  2453. REN    EQU    23        ;rename file
  2454. INQDISK    EQU    25        ;get current (default) drive
  2455. SETDMA    EQU    26        ;set dma address
  2456. INQALC    EQU    27        ;allocation vector
  2457. GETPARM    EQU    31        ;current drive parameters address
  2458. SGUSER    EQU    32        ;set or get user area
  2459. COMPSZ    EQU    35        ; # of records in file
  2460.  
  2461. ; system addresses
  2462.  
  2463. BDOS     EQU    CPM$BASE+05H    ;bdos function entry address
  2464. FCB     EQU    CPM$BASE+5CH    ;default file control block
  2465. FCBEXT     EQU    FCB+12          ;extent byte in 'fcb'
  2466. FCBRNO     EQU    FCB+32        ;record number in 'fcb'
  2467. TBUF     EQU    CPM$BASE+80H    ;default cp/m buffer
  2468.  
  2469. ; assembled 'com' and 'ram-loaded' file size (0c00h = 3k)
  2470.  
  2471. COMFILE     EQU    (CMDBUF+2)-256    ; 'prn' listing shows 'com'..
  2472. LAST     END    SOURCE        ;..and loaded file size.
  2473.