home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / lambda / soundpot / a / d7-4-db2.lbr / D7-DB.AZM / D7-DB.ASM
Encoding:
Assembly Source File  |  1993-10-26  |  49.0 KB  |  1,807 lines

  1. ; title 'disk7 -- cp/m file manipulation program'
  2.  
  3. VERS    EQU    7$6        ;version number..
  4. MONTH    EQU    07        ;..month..
  5. DAY    EQU    01        ;..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 'sweep',
  13. ; written by ward christensen, michael karas, and robert fisher, respectively.
  14. ; existence of these programs generated impetus for writing 'disk7'.
  15.  
  16. ; a single-screen menu is provided after entering 'disk7' followed by cursor
  17. ; return.  wildcard filenames and optional drive declaration are permitted.
  18. ; disk7 [d:]*.asm shows only 'asm' files on [selected] or current drive.
  19. ; any other than a command key causes the menu to reappear.  full error
  20. ; trapping and command cancellation recovery is provided.  cancellation occurs
  21. ; by entering a <return>, if no other entry has been made and execution has
  22. ; not begun.
  23.  
  24. ; display is circular, single-file columnar, with crt console cursor moved
  25. ; 'forward' with <space> or <return>, and 'reverse' with 'b'.  drive
  26. ; remaining storage in kilobytes is automatically displayed whenever disks
  27. ; are logged-in or menu recalled.  if a user area with no files is logged-in,
  28. ; new drive/user area prompt is presented.
  29.  
  30. ; command functions of 'disk7' are:
  31.  
  32. ;     c - copy file to another drive/user with automatic 'crc' verification.
  33. ;         format is --> to drive/user: 'd[nn]<return>' where 'd' is drive and
  34. ;         'n' is optional user area.  a 'colon' after the drive or user area
  35. ;         is optional.  d, d:, dn, dn:, dnn, dnn: are all valid entries.
  36. ;         (system reset occurs for disk change.)  prompts to erase already
  37. ;         existing file on other drive or in other user area.
  38. ;     d - delete file from disk, prompts for certainty.
  39. ;     f - file size in kilobytes, rounded up to next disk allocation block.
  40. ;     j - jump 'forward' 22 file names.  used to quickly scan through lengthy
  41. ;         disk directories.
  42. ;     l - log-in new drive/user for display and reset system for disk changes.
  43. ;         format is same as 'c' for copy.
  44. ;     m - mass copy of tagged files to another drive/user area.  auto-erase
  45. ;         occurs if file(s) already exist(s).  prompts for desired drive/user
  46. ;         area as with 'c' and 'l'.  mass copy function can be repeated
  47. ;         without re-tagging files.  simply enter 'm' again to copy previously
  48. ;         tagged files to another drive/user area.  (entering 'm' without any
  49. ;         files tagged causes cursor to move to directory beginning.)
  50. ;     p - print text file to cp/m list device (printer), any keypress cancels.
  51. ;     r - rename file on current drive, only cp/m convention names permitted.
  52. ;     s - stat of requested drive, shows remaining disk storage in kilobytes.
  53. ;     t - tag file for inclusion for mass copy to another drive/user area.
  54. ;         file remains tagged until either a disk log-in or 'u' is used to
  55. ;         untag it.  a '*' marker is placed on the tagged filename cursor
  56. ;         line as a reminder the file is tagged for mass copy.  tagged file
  57. ;         size is shown, totals accumulated and presented in parentheses.
  58. ;     u - untag file previously tagged for mass copy.  'u' can be used to move
  59. ;         cursor 'forward' for quick untagging of files.  logging-in drive
  60. ;         again with 'l' also quickly untags all files.
  61. ;     v - view text file on console, with pagination and single-line turn-up.
  62. ;         <crtl-x> or <esc> cancels function.  only 'ascii' characters are
  63. ;         processed.
  64. ;     w - write ascii file to cp/m logical punch device, any keypress cancels.
  65. ;     x - exit to cp/m (to ccp without rebooting, or optionally warmboot if
  66. ;         program assembled with 'warmboot' equate set true.)  <esc> can be
  67. ;         used also to exit to cp/m.
  68.  
  69. ; 'disk7' is an alternative to 'pip' and 'sweep'.  conveniently, it can be
  70. ; added as a subroutine to application programs that require file manipulation
  71. ; but without returning to the cp/m operating system.  'disk7' loads fast and
  72. ; copies files at near theoretical speed using an 8-bit 'crc' table-driven
  73. ; ccitt recommended routine.  the compact menu makes operation essentially
  74. ; self-documenting.  the program occupies less than 4k bytes of memory.
  75.  
  76. ; installation requires setting maximum allowed drive to be logged-in or
  77. ; copied to, and deciding if to warmboot or not on returning to cp/m.  these
  78. ; equate options plus several others are at program 'starting definitions'
  79. ; below.
  80.  
  81. ; disk7 works with cp/m 2.2 only, with 24k or more of ram.  file copy
  82. ; functions are faster with large amounts of ram.
  83.  
  84. ; please report bugs noted or improvements incorporated to frank gaude'
  85. ; at 10925 stonebrook drive, los altos hills, ca 94022.  telephone is
  86. ; 415/941-2219, 6pm to 10pm daily, pacific time.
  87.  
  88. ; latest changes
  89.  
  90. ; 07/01/83  updated menu to reflect new commands.  doc file combined with
  91. ; asm file.  (76c)  fg
  92.  
  93. ; 06/19/83  tagged file summation displayed right-justified.  added new
  94. ; command ('j') to jump forward 22 files.  (76a/b)  fg
  95.  
  96. ; 06/04/83  added 'ani 7fh' to 'v' read function to force text to ascii.
  97. ; also added 'w' command to output ascii text to cp/m punch device (tnx to
  98. ; bill silvert for recommending these changes).  file size now accumulated
  99. ; as tagged ('t') and presented in parentheses on cursor line.  (76)  fg
  100.  
  101. ; starting definitions
  102.  
  103. TRUE     EQU    0FFH        ;define true and..
  104. FALSE     EQU    0           ;..false.
  105. WARMBOOT EQU    FALSE        ;set true to warmboot on exit
  106. CPM$BASE EQU    000H        ;cp/m system base..
  107. TPA     EQU    100H        ;..'transient program area' start..
  108. CCP     EQU    800H        ;..and 'ccp' length in bytes.
  109. LPS     EQU    24-2        ;lines-per-screen for 'view' pagination
  110. GET     EQU    0FFH        ;get user area e-reg value
  111.  
  112. ; ascii definitions
  113.  
  114. BELL    EQU    07H        ;ascii bell character..
  115. BS    EQU    08H        ;..backspace..
  116. LF    EQU    0AH        ;..linefeed..
  117. CR    EQU    0DH        ;..carriage return..
  118. CAN    EQU    18H        ;..cancel..
  119. EOFCHAR    EQU    1AH        ;..end-of-file..
  120. ESC    EQU    1BH        ;..and escape character.
  121.  
  122. ; even-page base of filename ring storage
  123.  
  124. RING    SET    LAST+100H AND 0FF00H
  125.  
  126. ; assembly origin (load address) and program beginning
  127.  
  128. SOURCE    ORG    42000
  129. START   SHLD    SAVEHL
  130.     JMP    DISK7
  131.  
  132. ; highest disk drive letter in system (at 103h in 'com' file)
  133.  
  134. MAXDR    DB    'B'        ; 'a', 'b', 'c', etc.
  135.  
  136. ; concealed copyright notice
  137.  
  138.     DB    ' Copyright (c) 1983 by Frank Gaude'''
  139.     DB    ' All Rights Reserved'
  140.  
  141. ; start of program
  142.  
  143. DISK7     IF    NOT WARMBOOT
  144.     LXI    H,0        ;clear hl-pair then..
  145.     DAD    SP        ;..add cp/m's stack address.
  146.     SHLD    STACK
  147.      ENDIF            ;not warmboot
  148.  
  149.     LXI    SP,STACK    ;start local stack
  150.     CALL    HELP        ;show 'menu'
  151.     MVI    E,GET        ;determine..
  152.     CALL    GET$USR        ;..user area then..
  153.     STA    C$U$A        ;..store as current and..
  154.     STA    O$USR        ;..as original for exit.
  155.     LDA    FCB        ;default drive?
  156.     ORA    A
  157.     JZ    EMBARK        ;if so, branch.
  158.     DCR    A
  159.     STA    C$DR        ;store 0 --> 'a', 1 --> 'b',etc.
  160.     CALL    SET$DR        ;select requested drive as current
  161.  
  162. ; determine if specific file(s) requested -- show remaining storage
  163.  
  164. EMBARK    CALL    FRESTOR        ;get bytes remaining on drive (decode default)
  165.     LDA    FCB+1        ;check if a filename was entered
  166.     CPI    ' '        ;filename a space?
  167.     JNZ    PLUNGE        ;no, name was entered.
  168.     LDA    FCB+9        ;filetype also space?
  169.     CPI    ' '        ;if so, then..
  170.     JNZ    PLUNGE
  171.     LXI    H,JOKER        ;..treat as '*.*' with 'joker'..
  172.     LXI    D,FCB+1        ;..loaded here.
  173.     MVI    B,11        ; # of characters to move
  174.     CALL    MOVE        ;set field to *.*
  175.  
  176. ; build 'ring' with filename positioned in default 'fcb' area
  177.  
  178. PLUNGE    MVI    C,SETDMA    ;initialize dma address..
  179.     LXI    D,TBUF        ;..to default buffer.
  180.     CALL    BDOS
  181.     XRA    A        ;clear search 'fcb'..
  182.     STA    FCBEXT        ;extent byte..
  183.     STA    FCBRNO        ;..and record number.
  184.     CMA
  185.     STA    CANFLG        ;make cancel flag true
  186.     LXI    D,FCB        ;default 'fcb' for search..
  187.     MVI    C,SRCHF        ;..of first occurrence.
  188.     CALL    BDOS
  189.     INR    A        ; 0ffh --> 00h if no file found
  190.     JNZ    SETRING        ;if found, branch and build ring.
  191.     STA    CANFLG        ;make log-cancel toggle false
  192.     CALL    ILPRT        ;else say none found, fall thru to log.
  193.     DB    CR,LF,'++ NO FILE FOUND ++',CR,LF,LF,' --->  ',0
  194.  
  195. ; l o g
  196.  
  197. ; select drive and user area (system reset for disk change on-the-fly)
  198.  
  199. LOG    CALL    ILPRT        ;prompt to get drive/user selection
  200.     DB    BS,'Log-in drive/user: ',0
  201.     CALL    DEF$D$U
  202.     LDA    R$U$A        ;establish requested area..
  203.     STA    C$U$A        ;..as current area.
  204.     CALL    SET$USR
  205.     CALL    RESET        ;reset disk system, make requested current.
  206.     MVI    A,' '        ;set default 'fcb' to look like *.*
  207.     STA    FCB+1
  208.     STA    FCB+9
  209.     LXI    H,0        ;initialize tagged..
  210.     SHLD    TAG$TOT        ;..file size accumulator.
  211.     CALL    ILPRT
  212.     DB    CR,LF,LF,0    ;fresh line and..
  213.     JMP    EMBARK        ;..restart.
  214.  
  215. ; routine to define current drive and user area with full error trapping.
  216. ; (check validity of user area entry first, then drive validity, then proceed
  217. ; with implementation.)
  218.  
  219. DEF$D$U    LXI    H,CMDBUF+2
  220.     MVI    B,7        ; # of blanks to..
  221.     CALL    FILL        ;..clear 'cmdbuf'.
  222.     LXI    D,CMDBUF    ;get drive/user selection from..
  223.     MVI    C,RDBUF        ;..console buffer read.
  224.     CALL    BDOS
  225.     CALL    CONVERT        ;make sure alpha is upper case
  226.      XRA    A        ;initialize..
  227.     STA    R$U$A        ;..user area to zero.
  228.     LDA    CMDBUF+3    ; 1st digit of user area?
  229.     CPI    ':'        ;allow ':' after drive declaration
  230.     JZ    SETEXIT
  231.     CPI    '0'        ;if no valid user area request..
  232.     JC    SETEXIT        ;..then to new drive and ring list.
  233.     CPI    '9'+1
  234.     JNC    ERRET        ;error, not a user area.
  235.     SUI    30H        ;convert to binary and..
  236.     CPI    1        ;..test if 10's digit.
  237.     JNZ    SETUSER        ;if none, then set user area now.
  238.     LDA    CMDBUF+4    ;a second user area digit?
  239.     CPI    ':'        ;allow ':' here
  240.     JZ    SETUONE
  241.     CPI    '0'        ;test for 1's digit
  242.     JC    SETUONE
  243.     CPI    '5'+1        ;if user area >15, go..
  244.     JNC    ERRET        ;..error msg, show file line.
  245.     SUI    30H-10        ;make 1 --> 11, 2 --> 12, etc.
  246.     STA    R$U$A        ;save as 'requested user area' here..
  247.     JMP    SETEXIT
  248.  
  249. SETUONE    MVI    A,1        ;set to user area 'one'
  250. SETUSER    MOV    B,A
  251.     LDA    CMDBUF+4
  252.     CPI    ':'        ;double dot (colon)?
  253.     JZ    DDPASS
  254.     CPI    '0'        ;if >19 user area, go error msg.
  255.     JNC    ERRET
  256. DDPASS    MOV    A,B
  257.     STA    R$U$A        ;..and here.
  258. SETEXIT    LDA    MAXDR        ;check if system maximum and..
  259.     INR    A
  260.     MOV    B,A
  261.     LDA    CMDBUF+2    ;..requested drive are compatible.
  262.     CMP    B        ;if input too big..
  263.     JNC    ERRET        ;..or..
  264.     MVI    B,'A'-1        ;..too..
  265.     CMP    B        ;..small, show..
  266.     JC    ERRET        ;..error msg.
  267.     SUI    'A'-1        ;ready for fcb use
  268.     STA    FCB        ;store 1 --> a:, 2 --> b:, etc.
  269.     DCR    A
  270.     STA    R$DR        ;ready for 'login' request
  271.     RET
  272.  
  273. ; error return and recovery from command cancellation
  274.  
  275. ERRET    CALL    ILPRT
  276.     DB    CR,LF,'++ Drive/User Entry Error ++',BELL,0
  277. COMCAN    LXI    SP,STACK    ;reset stack..
  278.     LDA    CANFLG
  279.     ORA    A        ;..from..
  280.     CZ    CRLF
  281.     JZ    PLUNGE
  282.     JMP    NEUTRAL        ;..error/command abort.
  283.  
  284. ; e x i t
  285.  
  286. ; return to cp/m ccp
  287.  
  288. CPM$CCP    LDA    O$USR        ;get and set original..
  289.     CALL    SET$USR        ;..user area and..
  290.     LXI    D,TBUF        ;..tidy up..
  291.     MVI    C,SETDMA    ;..before going home.
  292.     CALL    BDOS
  293.     CALL    CRLF
  294.  
  295.      IF WARMBOOT
  296.     JMP    CPM$BASE
  297.      ENDIF            ;warmboot
  298.  
  299.      IF    NOT WARMBOOT
  300.     LHLD    STACK        ;put cp/m's pointer..
  301.     SPHL            ;..back to 'sp'.
  302.         LHLD    SAVEHL
  303.     RET            ;return to cp/m ccp
  304.      ENDIF            ;not warmboot
  305.  
  306. ; h e l p  (menu)
  307.  
  308. HELP    CALL    CLS        ;show menu but 'clear-screen' first
  309.     CALL    ILPRT
  310.     DB    CR,'              DISK '
  311.     DB    VERS/10+'0','.',VERS MOD 10+'0'
  312.     DB    ' - MODIFIED TO RUN INSIDE dBII - G. Pareja'
  313.     DB    CR,LF
  314.     DB    '   C - Copy file   | D - Delete file  | F - File size  | J '
  315.     DB    '- Jump 22 files',CR,LF
  316.     DB    '   L - Log drive   | M - Mass copy    | P - Print text | R '
  317.     DB    '- Rename file',CR,LF
  318.     DB    '   S - Stat drive  | T - Tag file     | U - Untag file | V '
  319.     DB    '- View text file',CR,LF
  320.     DB    '   ?,/ - MENU      | X - Exit to dBII | <space> advances '
  321.     DB    'cursor -- B backs up',CR,LF,LF,0
  322.       RET
  323.  
  324. ; establish ring (circular list) of filenames
  325.  
  326. SETRING    LXI    H,RING        ;initialize ring pointer
  327.     SHLD    RINGPOS        ;start --> current position of ring
  328.  
  329. ; put each found name in ring.  a-reg --> offset into 'tbuf' name storage
  330.  
  331. TO$RING    DCR    A        ;un-do 'inr' from above and below
  332.     ADD    A        ;times 32 --> position index
  333.      ADD    A
  334.     ADD    A
  335.     ADD    A
  336.     ADD    A
  337.     ADI    TBUF        ;add page offset and..
  338.     MOV    L,A        ;..put address into..
  339.     MVI    H,0        ;..hl-pair.
  340.     LDA    FCB        ;get drive/user designator and..
  341.     MOV    M,A        ;..put into 'fcb' buffer.
  342.     XCHG
  343.     LHLD    RINGPOS        ;pointer to current load point in ring
  344.     XCHG
  345.     MVI    B,12        ;move drive designator and name to ring
  346.     CALL    MOVE
  347.     XCHG            ;de-pair contains next load point address
  348.     MVI    M,' '        ;space for potential..
  349.     INX    H        ;..tagging of files for mass copy.
  350.     SHLD    RINGPOS        ;store and search..
  351.     MVI    C,SRCHN        ;..for next occurrence.
  352.     LXI    D,FCB        ;filename address field
  353.     CALL    BDOS
  354.     INR    A        ;if all done, 0ffh --> 00h.
  355.     JNZ    TO$RING        ;if not, put next name into ring.
  356.  
  357. ; all filenames in ring -- setup ring size and copy-buffer start point
  358.  
  359.     LHLD    RINGPOS        ;next load point of ring is start of buffer
  360.     SHLD    RINGEND        ;set ring end..
  361.     SHLD    BUFSTART    ;..and copy-buffer start.
  362.     LXI    D,RING+13    ;compare 'ringend' (tab base+13)
  363.     CALL    CMPDEHL
  364.     JZ    CMDLOOP        ;go to command loop, if no sort.
  365.  
  366. ; sort ring of filenames
  367.  
  368. SORT    LXI    H,RING        ;initialize 'i' sort variable and..
  369.     SHLD    RINGI
  370.     LXI    D,13        ;..also 'j' variable.
  371.     DAD    D
  372.     SHLD    RINGJ
  373. SORTLP    LHLD    RINGJ        ;compare names 'i & j'
  374.     XCHG
  375.     LHLD    RINGI
  376.     PUSH    H        ;save position pointers..
  377.     PUSH    D        ;..for potential swap.
  378.     MVI    B,13        ; # of characters to compare
  379.  
  380. ; left to right compare of two strings (de-pair points to 'a' string;
  381. ; hl-pair, to 'b'; b-reg contains string length.)
  382.  
  383. CMPSTR    LDAX    D        ;get an 'a' string character and..
  384.     CMP    M        ;..check against 'b' string character.
  385.     JNZ    NOCMP        ;if not equal, set flag.
  386.     INX    H        ;bump compare..
  387.     INX    D        ;..pointers and..
  388.     DCR    B        ; (if compare, set as equal.)
  389.     JNZ    CMPSTR        ;..do next character.
  390. NOCMP    POP    D
  391.     POP    H
  392.     MVI    B,13
  393.     JNC    NOSWAP
  394.  
  395. ; swap if 'j' string larger than 'i'
  396.  
  397. SWAP    MOV    C,M        ;get character from one string..
  398.     LDAX    D        ;..and one from other string.
  399.     MOV    M,A        ;second into first
  400.     MOV    A,C        ;first into second
  401.     STAX    D
  402.     INX    H        ;bump swap pointers
  403.     INX    D
  404.     DCR    B        ;all bytes swapped yet?
  405.     JNZ    SWAP
  406. NOSWAP    LHLD    RINGJ        ;increment 'j' pointer
  407.     LXI    D,13
  408.     DAD    D
  409.     SHLD    RINGJ
  410.     XCHG            ;see if end of 'j' loop
  411.     LHLD    RINGEND
  412.     CALL    CMPDEHL
  413.     JNZ    SORTLP        ;no, so more 'j' looping.
  414.     LHLD    RINGI        ;bump 'i' pointer
  415.     LXI    D,13
  416.     DAD    D
  417.     SHLD    RINGI
  418.     DAD    D        ;set start over 'j' pointer
  419.     SHLD    RINGJ
  420.     XCHG            ;see if end of 'i' loop
  421.     LHLD    RINGEND
  422.     CALL    CMPDEHL
  423.     JNZ    SORTLP        ;must be more 'i' loop to do
  424.  
  425. ; sort done -- initialize tables for fast crc calculations
  426.  
  427.     CALL    INITCRC
  428.  
  429. ; calculate buffer maximum available record capacity
  430.  
  431. B$SIZE    LXI    B,0        ;count records
  432.     LHLD    BDOS+1        ;get 'bdos' entry (fbase)
  433.  
  434.      IF    NOT WARMBOOT
  435.     LXI    D,-(CCP)
  436.     DAD    D
  437.      ENDIF            ;not warmboot
  438.  
  439.     DCX    H
  440.     XCHG            ;de-pair --> highest address of buffer
  441.     LHLD    BUFSTART    ;start address of buffer (end of ring list)
  442. B$SIZE2    INX    B        ;increase record count by one
  443.     PUSH    D
  444.     LXI    D,128        ; 128-byte record
  445.     DAD    D        ;buffer address + record size
  446.     POP    D
  447.     CALL    CMPDEHL        ;compare for all done
  448.     JNC    B$SIZE2        ;more will fit?
  449.     DCX    B        ;set maximum record count less one
  450.     MOV    A,B        ;memory available for copy?
  451.     ORA    C
  452.     JNZ    B$SIZE3        ;yes, buffer memory space available.
  453.     CALL    ILPRT
  454.     DB    CR,LF,BELL,'++ NO MEMORY FOR COPY BUFFER ++',0
  455.     JMP    NEUTRAL
  456.  
  457. B$SIZE3    MOV    L,C        ;store..
  458.     MOV    H,B        ;..maximum..
  459.     SHLD    REC$MAX        ;..record count.
  460.  
  461. ; buffer size suitable -- process file/display loop
  462.  
  463. CMDLOOP    LXI    H,RING        ;set start point of listing
  464.     SHLD    RINGPOS
  465. LOOP    CALL    ILPRT
  466.     DB    CR,LF,'   ',0
  467. LOOP2    LHLD    RINGPOS        ;ring filename location
  468.     MOV    A,M        ;move 'fcb' to a-reg and..
  469.     ADI    'A'-1        ;..make drive printable (a - p).
  470.     CALL    TYPE
  471.     LDA    C$U$A        ;get current (last requested) user area
  472.     ORA    A        ;branch if 'user..
  473.     JZ    UAZ        ;..area zero'.
  474.     CPI    10        ;less then ten?
  475.     JC    LT$TEN        ;if yes, branch.
  476.     SUI    10        ;if not, suppress leading 10's digit.
  477.     PUSH    PSW
  478.     MVI    A,'1'        ;print 10's digit as 'one'
  479.     CALL    TYPE
  480.     POP    PSW
  481. LT$TEN    ADI    '0'        ;make 1's digit printable
  482.     CALL    TYPE
  483. UAZ    CALL    ILPRT        ;fence between 'drive/user' and..
  484.     DB    ': ',0        ;..'fn.ft'.
  485.     INX    H        ;beginning of 'fn.ft' string
  486.     MVI    B,8        ; 8 filename characters
  487. PRT$FN    MOV    A,M
  488.     CALL    TYPE
  489.     INX    H
  490.     DCR    B
  491.     JNZ    PRT$FN
  492.     MVI    A,'.'        ;period between 'fn' and 'ft'
  493.     CALL    TYPE
  494.     MVI    B,3        ; 3 filetype characters
  495. PRT$FT    MOV    A,M
  496.     CALL    TYPE
  497.     INX    H
  498.     DCR    B
  499.     JNZ    PRT$FT
  500.     MOV    A,M        ;get tag (*) and..
  501.     STA    TAG+2        ;..put after colon.
  502.     INX    H
  503.     SHLD    RINGPOS        ;save ring position
  504.     CALL    ILPRT
  505. TAG    DB    ' : ',0        ;space, colon, space or * before cursor.
  506.     LDA    J$FLG        ;jump..
  507.     ORA    A        ;..forward?
  508.     JZ    PRE$FOR
  509. K$WAIT    CALL    KEYIN        ;wait for character from keyboard
  510.     CPI    ' '        ;if 'space' or..tract one ring position.
  511.     JZ    FORWARD
  512.     CPI    CR        ;..'cursor return', move to next file.
  513.     JZ    FORWARD
  514.     CPI    'B'        ;if reverse, subtract one ring position.
  515.     JZ    REVERSE
  516.     CPI    'C'        ;copy file to another disk?
  517.     JZ    COPY
  518.     CPI    'D'        ;delete a file?
  519.     JZ    DELETE
  520.     CPI    'F'        ;show file size?
  521.     JZ    FIL$SIZ
  522.     CPI    'J'        ;jump forward?
  523.     JZ    JUMP22
  524.     CPI    'L'        ;log-in another drive?
  525.     JZ    LOG
  526.     CPI    'M'        ;tagged multiple file copy?
  527.     JZ    MASS
  528.     CPI    'P'        ;output file to 'list' device?
  529.     JZ    LSTFILE
  530.     CPI    'R'        ;if rename, get to work.
  531.     JZ    RENAME
  532.     CPI    'S'        ;free bytes on..
  533.     JZ    R$DR$ST        ;..requested drive?
  534.     CPI    'T'        ;if tag, put '*' in..
  535.     JZ    TAG$EM        ;..front of cursor.
  536.     CPI    'U'        ;remove '*' from..
  537.     JZ    UNTAG        ;..in front of cursor?
  538.     CPI    'V'        ; 'view' file at console?
  539.     JZ    VIEW
  540. ;    CPI    'W'        ;file to punch?
  541. ;    JZ    PUNFILE
  542.     CPI    'X'        ;if exit, then to cp/m ccp.
  543.     JZ    CPM$CCP
  544.     CPI    ESC        ; 'esc' exits to cp/m ccp also.
  545.     JZ    CPM$CCP
  546.     CALL    HELP          ;get help message (menu) and..
  547.     CALL    FRESTOR        ;..show free storage remaining.
  548. NEUTRAL    LHLD    RINGPOS        ;stay..
  549.     LXI    D,-13        ;..in..
  550.     DAD    D        ;..the..
  551.     SHLD    RINGPOS        ;..same..
  552.     JMP    LOOP        ;..position.
  553.  
  554. ; jump forward 22 files
  555.  
  556. PRE$FOR    LDA    J$CNT        ;adjust jump..
  557.     INR    A        ;..counter..
  558.     STA    J$CNT        ;..until..
  559.     CPI    22        ;..at top limit.
  560.     JNZ    FORWARD
  561.     MVI    A,TRUE        ;at top, so..
  562.     STA    J$FLG        ;..turn off jump switch and..
  563.     JMP    K$WAIT        ;..wait for next keyboard input.
  564.  
  565. ; u n t a g
  566.  
  567. UNTAG    XRA    A        ;set tag/untag..
  568.     STA    T$UN$FG        ;..flag to untag.
  569.     LHLD    RINGPOS        ;move back one..
  570.     LXI    D,-1        ;..character position..
  571.     DAD    D        ;..and check tagging status.
  572.     MOV    A,M        ;if file previously tagged, remove..
  573.     CPI    '*'        ;..size from..
  574.     MVI    M,' '        ; (untag character, to next ring position.)
  575.     JZ    FS2        ;..summation.
  576.     JMP    FORWARD
  577.  
  578. ; t a g
  579.  
  580. TAG$EM    LHLD    RINGPOS
  581.     LXI    D,-1        ;move back one..
  582.     DAD    D        ;..position..
  583.     MOV    A,M        ; (if file
  584.     CPI    '*'        ; already tagged, skip
  585.     JZ    FORWARD        ; to next file.)
  586.     MVI    M,'*'        ;..and store a '*' tag character.
  587.     MVI    A,TRUE        ;set..
  588.     STA    T$UN$FG        ;..tag/untag and..
  589.     STA    FS$FLG        ;..file size flags to tag.
  590.     JMP    FS2        ;get file size
  591.  
  592. ; f i l e   s i z e
  593.  
  594. ; determine and display file size in kilobytes -- round up to next disk
  595. ; allocation block -- accumulate tagged file summation
  596.  
  597. FIL$SIZ    XRA    A        ;set file size/tagged..
  598.     STA    FS$FLG        ;..file flag to file size.
  599. FS2    MVI    A,BS        ;backspace over..
  600.     CALL    TYPE        ;..command character.
  601.     CALL    RINGFCB        ;move name to 's$fcb'
  602.  
  603. ; determine file record count and save in 'rcnt'
  604.  
  605.     MVI    C,COMPSZ
  606.     LXI    D,S$FCB
  607.     CALL    BDOS
  608.     LHLD    S$FCB+33
  609.     SHLD    RCNT        ;save record count and..
  610.     LXI    H,0
  611.     SHLD    S$FCB+33    ;..reset cp/m.
  612.  
  613. ; round up to next disk allocation block
  614.  
  615.     LDA    B$MASK        ;sectors/block - 1
  616.     PUSH    PSW        ;save 'blm'
  617.     MOV    L,A
  618.     XCHG
  619.     LHLD    RCNT        ;..use here.
  620.     DAD    D        ;round up to next block
  621.     MVI    B,3+1        ;convert from..
  622.     CALL    SHIFTLP        ;..records to kilobytes.
  623.     POP    PSW        ;retrieve 'blm'
  624.     RRC            ;convert..
  625.     RRC            ;..to..
  626.     RRC            ;..kilobytes/block.
  627.     ANI    1FH
  628.     CMA            ;finish rounding
  629.     ANA    L
  630.     MOV    L,A        ;hl-pair contains # of kilobytes
  631.     LDA    FS$FLG
  632.     ORA    A
  633.     JZ    D$F$SIZ        ;branch if 'f' function
  634.  
  635. ; tagged file size summation
  636.  
  637.     XCHG            ;file size to de-pair
  638.     LDA    T$UN$FG
  639.     ORA    A
  640.     JZ    TAKE        ;if untag, take size from total.
  641.     LHLD    TAG$TOT        ;accumulate..
  642.     DAD    D        ;..sum of..
  643.     SHLD    TAG$TOT        ;..tagged file sizes.
  644.     XCHG            ;file size to hl-pair
  645.     JMP    D$F$SIZ        ;branch to display sizes
  646.  
  647. TAKE    LHLD    TAG$TOT        ;subtract..
  648.     MOV    A,L        ;..file..
  649.     SUB    E        ;..size..
  650.     MOV    L,A        ;..from..
  651.     MOV    A,H        ;..summation..
  652.     SBB    D        ;..total.
  653.     MOV    H,A        ;then put..
  654.     SHLD    TAG$TOT        ; (save total)
  655.     XCHG            ;..file size in hl-pair.
  656.  
  657. ; display file size in kilobytes -- right justify tagged file total
  658.  
  659. D$F$SIZ    CALL    DET$BCD        ;determine # of bcd digits in hl-pair
  660.     MVI    A,9        ;limit of right margin (good for max cp/m 2.2)
  661.     SUB    B        ; # of digits returned in b-reg from det$bcd
  662.     STA    TEST$RT        ;save intermediate right-justify data
  663.     CALL    DECOUT          ;print individual file size
  664.     CALL    ILPRT
  665.     DB    'k',0
  666.     LDA    FS$FLG
  667.     ORA    A
  668.     JZ    FORWARD         ;show next file if not tagging
  669.  
  670. ; determine # of digits in tagged summation
  671.  
  672.     LHLD    TAG$TOT        ;get present summation
  673.     CALL    DET$BCD
  674.  
  675. ; insert necessary spaces (blanks) to right justify display
  676.  
  677.     LDA    TEST$RT        ;get intermediate right-justify data
  678.     SUB    B
  679.     MOV    B,A
  680.     MVI    A,' '        ;adjust..
  681. ADD$SP    CALL    TYPE        ;..to..
  682.     DCR    B        ;..achieve..
  683.     JNZ    ADD$SP        ;..right justification.
  684.     MVI    A,'('
  685.     CALL    TYPE
  686.     CALL    DECOUT          ;print tagged file summation
  687.     CALL    ILPRT
  688.     DB    'k)',0          ;to next file..
  689.     JMP    FORWARD        ;..cursor line.
  690.  
  691. ; j u m p
  692.  
  693. JUMP22    XRA    A        ;clear..
  694.     STA    J$FLG        ;..jump forward flag and..
  695.     STA    J$CNT        ;..file counter.  fall-thru to next filename.
  696.  
  697. ; f o r w a r d
  698.  
  699. FORWARD    LHLD    RINGPOS        ;at end of loop yet?
  700.     XCHG
  701.     LHLD    RINGEND
  702.     CALL    CMPDEHL        ;compare 'present' to 'end'
  703.     JNZ    LOOP        ;to next print position
  704.     CALL    CRLF        ;end-of-directory shows with fresh line
  705.     LXI    H,RING        ;set position pointer to beginning and..
  706.     SHLD    RINGPOS
  707.     JMP    LOOP        ;..redisplay start entry.
  708.  
  709. ; r e v e r s e
  710.  
  711. REVERSE    LHLD    RINGPOS        ;see if at beginning of ring
  712.     LXI    D,RING+13
  713.     CALL    CMPDEHL
  714.     JNZ    REV1        ;skip position pointer reset if not..
  715.     CALL    CRLF        ;..at beginning.  skip line at junction.
  716.     LHLD    RINGEND        ;set to end +1 to backup to end
  717.     LXI    D,13
  718.     DAD    D
  719.     SHLD    RINGPOS
  720. REV1    CALL    ILPRT        ;indicate reverse
  721.     DB    CR,LF,'<- ',0
  722.     LHLD    RINGPOS
  723.     LXI    D,-(13*2)    ;one ring position..
  724.     DAD    D        ;..backwards.
  725.     SHLD    RINGPOS
  726.      JMP    LOOP2        ;display without 'crlf'
  727.  
  728. ; s t a t
  729.  
  730. ; determine remaining storage on requested drive
  731.  
  732. R$DR$ST    CALL    ILPRT
  733.     DB    'torage remaining on drive: ',0
  734.     CALL    DEF$D$U        ;determine drive requested and..
  735.     CALL    RESET        ;..login as current.
  736.     CALL    ILPRT
  737.     DB    CR,LF,LF,0
  738.     CALL    FRESTOR        ;determine free space remaining
  739.     LDA    C$DR        ;login original as..
  740.     CALL    SET$DR        ;..current drive.
  741.     JMP    NEUTRAL
  742.  
  743. ; d e l e t e
  744.  
  745. ; set up to delete filename at cursor position
  746.  
  747. DELETE    CALL    RINGFCB        ;move name from ring to 'rename fcb'
  748.     CALL    ILPRT
  749.     DB    'elete? (Y/N): ',0
  750.     CALL    KEYIN
  751.     CPI    'Y'
  752.     JNZ    NEUTRAL    
  753.  
  754. ; delete file
  755.  
  756.     LXI    D,S$FCB        ;point at delete 'fcb'
  757.     MVI    C,ERASE        ;erase function
  758.     CALL    BDOS
  759.     INR    A
  760.     JNZ    DEL2        ;file deleted okay
  761. FNF$MSG    CALL    ILPRT        ;show error message
  762.     DB    CR,LF,'++ NO FILE FOUND ++',0
  763.     JMP    NEUTRAL
  764.  
  765. ; reverse ring to close up erased position
  766.  
  767. DEL2    LHLD    RINGPOS        ;prepare move up pointers
  768.     PUSH    H
  769.     LXI    D,-13
  770.     DAD    D
  771.     SHLD    RINGPOS        ;reset current position for move
  772.     XCHG            ;de-pair = 'to' location
  773.     POP    H        ;hl-pair = 'from' location
  774. MOVUP    XCHG
  775.     PUSH    H        ;check if at end
  776.     LHLD    RINGEND        ;get old end pointer
  777.     CALL    CMPDEHL        ;check against current end location
  778.     POP    H
  779.     XCHG
  780.     JZ    MOVDONE        ;must be at end of ring
  781.     MVI    B,13        ;one name size
  782.     CALL    MOVE        ;move one name up
  783.     JMP    MOVUP        ;go check end parameters
  784.  
  785. MOVDONE    XCHG
  786.     SHLD    RINGEND        ;set new ring end if all moved
  787.     LXI    D,RING        ;see if ring is empty..
  788.     CALL    CMPDEHL        ;..(listend --> listpos --> ring)
  789.     JNZ    FORWARD
  790.     LHLD    RINGPOS
  791.     CALL    CMPDEHL
  792.     JNZ    FORWARD        ;neither equal so not empty
  793.     CALL    ILPRT
  794.     DB    CR,LF,LF,'    ++ List Empty ++',CR,LF,LF,' --->  ',0
  795.     JMP    LOG        ;go to drive/user area with files
  796.  
  797. ; r e n a m e
  798.  
  799. ; set-up to rename file at cursor position -- scan keyboard buffer and
  800. ; move filename to 'rename' destination 'fcb' (dfcb)
  801.  
  802. RENAME    LHLD    RINGPOS        ;move name from ring to rename 'fcb'
  803.     LXI    D,-13
  804.     DAD    D        ;point to name position
  805.     LXI    D,D$FCB        ;place to move name
  806.     MVI    B,12        ;amount to move
  807.     CALL    MOVE
  808.     CALL    ILPRT        ;new name prompt
  809.     DB    'ename file to: ',0
  810.     LXI    D,CMDBUF    ;command line location
  811.     MVI    C,RDBUF        ;console read-buffer function
  812.     CALL    BDOS
  813.     CALL    CONVERT        ;capitalize alpha
  814.     LXI    H,D$FCB+16    ;set drive to null as..
  815.     MVI    M,0        ;..required by 'bdos'.
  816.     INX    H
  817.  
  818. ; initialize new filename field with spaces
  819.  
  820.     PUSH    H        ;save start pointer
  821.     MVI    B,11        ; # of spaces to 'blank'
  822.     CALL    FILL
  823.     POP    H
  824.     XCHG
  825.     LXI    H,CMDBUF+1    ;put length..
  826.     MOV    C,M        ;..in c-reg.
  827.     INX    H
  828.     XCHG            ;de-pair --> buffer pointer and hl-pair..
  829.     CALL    UNSPACE        ;..--> 'fcb' pointer.  remove leading spaces.
  830.  
  831. ; extend buffer to spaces beyond command length
  832.  
  833. EXTEND    PUSH    H
  834.     MOV    L,C        ;double-byte remaining length
  835.     MVI    H,0
  836.     DAD    D        ;to buffer end +1
  837.     MVI    M,' '        ;force illegal character end
  838.     POP    H
  839.  
  840. ; start filename scan
  841.  
  842. SCAN    MVI    B,8        ; 8 characters in filename
  843. SCAN1    CALL    CKLEGAL        ;get and see if legal character
  844.     JC    COMCAN        ;all of command line?
  845.     CPI    ' '        ;see if end of parameter field
  846.     JZ    CPYBITS        ;rename file
  847.     CPI    '.'        ;at end of filename
  848.     JZ    SCAN2        ;process filetype field
  849.     MOV    M,A        ;put character into destination 'fcb'
  850.     INX    H
  851.     DCR    B        ;check name character count
  852.     JNZ    SCAN1
  853.  
  854. ; entry if eight characters without a 'period'
  855.  
  856. SCAN1A    CALL    CKLEGAL        ;scan buffer up to period or end
  857.     JC    CPYBITS        ;no extent if not legal
  858.     CPI    ' '        ;end of parameter field?
  859.     JZ    CPYBITS
  860.     CPI    '.'
  861.     JNZ    SCAN1A        ;do till end or period
  862.  
  863. ; build filetype field
  864.  
  865. SCAN2    MVI    B,3        ;length of filetype field
  866.     LXI    H,D$FCB+25    ;destination 'rename' filetype start
  867. SCAN3    CALL    CKLEGAL        ;get and check character
  868.     JC    SCAN4        ;name done if illegal
  869.     CPI    ' '        ;end of parameter field?
  870.     JZ    SCAN4
  871.     CPI    '.'        ;check if another period
  872.     JZ    SCAN4
  873.     MOV    M,A
  874.     INX    H
  875.     DCR    B
  876.     JNZ    SCAN3        ;get next character
  877. SCAN4    LXI    H,D$FCB+28    ;set pointer to 'rename' filetype end
  878.     CALL    INITFCB        ;..and zero counter fields.
  879.  
  880. ; copy old file status bit ($r/o or $sys) to new filename
  881.  
  882. CPYBITS    LXI    D,D$FCB+1    ;first character of old name..
  883.     LXI    H,D$FCB+17    ;..and of new name.
  884.     MVI    C,11        ; # of bytes with tag bits
  885. CBITS1    LDAX    D        ;fetch bit of old name character
  886.     ANI    128        ;strip upper bit and..
  887.     MOV    B,A        ;..save in b-reg.
  888.     MVI    A,7FH        ;mask for character only
  889.     ANA    M        ;put masked character into a-reg
  890.     ORA    B        ;add old bit
  891.     MOV    M,A        ;copy new byte back
  892.     INX    H        ;bump copy pointers
  893.     INX    D
  894.     DCR    C        ;bump copy counter
  895.     JNZ    CBITS1
  896.  
  897. ; check if new filename already exists.  if so, say so.  then go
  898. ; to command loop without moving ring position
  899.  
  900.     LDA    D$FCB        ;copy new name to source 'fcb'
  901.     STA    S$FCB
  902.     MVI    B,11
  903.     LXI    H,D$FCB+17    ;copy new name to..
  904.     LXI    D,S$FCB+1    ;..source 'fcb' for existence check.
  905.     CALL    MOVE
  906.     LXI    H,S$FCB+12    ;clear cp/m 'fcb' system..
  907.     CALL    INITFCB        ;..fields.
  908.     LXI    D,S$FCB        ;search to see if this file exists
  909.     MVI    C,SRCHF        ;search first function
  910.     CALL    BDOS
  911.     INR    A        ; 0ffh --> 00h if file not found
  912.     JZ    RENFILE        ;to rename, if duplicate doesn't exists.
  913.     CALL    ILPRT        ;announce the situation
  914.     DB    CR,LF,'++ FILE ALREADY EXISTS ++',CR,LF,BELL,'   ',0
  915.     JMP    NEUTRAL        ;try again?
  916.  
  917. ; copy new name into ring position
  918.  
  919. RENFILE    LHLD    RINGPOS        ;get ring position pointer
  920.     LXI    D,-12        ;back 12 leaves drive designation intact
  921.     DAD    D
  922.     XCHG
  923.     LXI    H,D$FCB+17    ;point at new name and..
  924.     MVI    B,11
  925.     CALL    MOVE        ;..move.
  926.     LXI    D,D$FCB        ;rename 'fcb' location
  927.     MVI    C,REN        ;rename function
  928.     CALL    BDOS
  929.     INR    A        ; 0ffh --> 00h if rename error
  930.     JNZ    NEUTRAL        ;if okay, proceed, else..
  931.     JMP    FNF$MSG        ;..show no-file msg.
  932.  
  933. ; v i e w
  934.  
  935. ; type file to console with pagination set to 'lps' -- single-line scroll
  936. ; using <space> bar , <ctrl-x> to cancel, any other key to page screen.
  937.  
  938. VIEW    CALL    ILPRT
  939.     DB    CR,LF,'<CTRL-X> cancels, <space> turns up one line, '
  940.     DB    'other keys page screen.',CR,LF,LF,0
  941.     MVI    A,1        ;initialize..
  942.     STA    
  943. LPSCNT        ;..lines-per-screen counter.
  944.     STA    VIEWFLG        ; 'view' paginate if not zero
  945.     MVI    A,WRCON        ;write console out function
  946.     JMP    CURRENT        ;to common i/o processing
  947.  
  948. ; p r i n t e r
  949.  
  950. ; send file to logical list device -- any keypress cancels
  951.  
  952. LSTFILE    XRA    A        ;zero for..
  953.     STA    VIEWFLG        ;..output to printer.
  954.     MVI    A,LIST        ;out to 'list' device function
  955.     JMP    CURRENT
  956.  
  957. ; p u n c h
  958.  
  959. ; write file to cp/m logical punch device
  960.  
  961. PUNFILE    XRA    A
  962.     STA    VIEWFLG
  963.     MVI    A,PUNCH        ;put to 'punch' device function
  964.  
  965. ; output character for console/list/punch processing
  966.  
  967. CURRENT    STA    CON$LST        ;save bdos function
  968.  
  969. ; output file to console/printer/punch
  970.  
  971.     CALL    RINGFCB        ;position name to 'fcb'
  972.     LXI    D,TBUF        ;set to use default cp/m dma buffer
  973.     MVI    C,SETDMA    ;address set function
  974.     CALL    BDOS
  975.     LXI    H,S$FCB+12    ;set pointer to source extent field
  976.     CALL    INITFCB        ;fix-up 'fcb' before use
  977.     LXI    D,S$FCB        ;open file for reading
  978.     MVI    C,OPEN        ;file open function code
  979.     CALL    BDOS
  980.     INR    A        ; 0ffh --> 00h if open okay
  981.     JNZ    ZEROCR        ;if not okay, show error message.
  982.     CALL    ILPRT
  983.     DB    '++ UNABLE TO OPEN FILE ++',0
  984.     JMP    NEUTRAL
  985.  
  986. ZEROCR    XRA    A        ;zero file 'current record' field
  987.     STA    S$FCB+32
  988. READMR    LXI    D,S$FCB        ;point at file 'fcb' for reading
  989.     MVI    C,READ        ;record read function
  990.     CALL    BDOS
  991.     ORA    A        ;check if read okay
  992.     JNZ    NEUTRAL        ;eof?
  993.     LXI    H,TBUF        ;point at record just read
  994.     MVI    B,128        ;set record character counter to output
  995. READLP    MOV    A,M        ;get a character
  996.     ANI    7FH        ;force to 'ascii'
  997.     CPI    EOFCHAR        ;see if end-of-file
  998.     JZ    NEUTRAL        ;back to ring loop if 'eof'
  999.     MOV    E,A        ;put character for 'bdos' call
  1000.     PUSH    B
  1001.     PUSH    H
  1002.     PUSH    D        ; (character in e-reg)
  1003.     LDA    CON$LST        ;get function for punch/list/console output
  1004.     MOV    C,A
  1005.     CALL    BDOS        ;send character
  1006.     LDA    VIEWFLG        ;if 'view'..
  1007.     ORA    A
  1008.     POP    D
  1009.     CNZ    PAGER        ;..check for 'lf'.
  1010.     MVI    C,CONST        ;console status function
  1011.     CALL    BDOS        ;status?
  1012.     POP    H
  1013.     POP    B
  1014.     ORA    A        ;if character there, then abort..
  1015.     JNZ    NEUTRAL     ;..to same ring position.
  1016.     INX    H        ;if not, bump buffer pointer.
  1017.     DCR    B        ;all bytes of record sent yet?
  1018.     JNZ    READLP        ;no, more in present record.
  1019.     JMP    READMR        ;yes, get next record.
  1020.  
  1021. PAGER    MOV    A,E        ; (character in e-reg)
  1022.     CPI    LF
  1023.     RNZ
  1024.     LDA    LPSCNT        ;is counter..
  1025.     INR    A        ;..at..
  1026.     STA    LPSCNT        ;..limit..
  1027.     CPI    LPS        ;..of lines-per-screen?
  1028.     RC            ;no, return.
  1029.     XRA    A        ;yes, initialize..
  1030.     STA    LPSCNT        ;..for next screen full.
  1031.     CALL    ILPRT
  1032.     DB    '  [more...]',CR,0    ;show msg line
  1033.     CALL    DKEYIN        ;wait for keyboard input
  1034.     CPI    ' '        ;see if <space> bar..
  1035.     PUSH    PSW
  1036.     CALL    ILPRT
  1037.     DB    '           ',CR,0    ;clear above msg line
  1038.     POP    PSW
  1039.     JNZ    CANVIEW        ;..if not, see if cancel.
  1040.     MVI    A,LPS-1        ;if so, set up for single-line..
  1041.     STA    LPSCNT        ;..scroll and..
  1042.     RET            ;..return for one more line.
  1043.  
  1044. CANVIEW    CPI    ESC        ;escape?
  1045.     JZ    COMCAN
  1046.     CPI    CAN        ;cancel?
  1047.     JZ    COMCAN        ;retain ring position
  1048.     RET            ;return for another page
  1049.  
  1050. ; m a s s   c o p y
  1051.  
  1052. ; copy files tagged using the 't' command.  auto-erase if file exists
  1053. ; on requested destination drive or in user area.
  1054.  
  1055. MASS    LXI    H,RING+12    ;get 1st possible tag location
  1056.     SHLD    RINGPOS
  1057. MASS$LP    MVI    A,'*'
  1058.     CMP    M
  1059.     INX    H        ;get in filename synchronization
  1060.     SHLD    RINGPOS
  1061.     JZ    MCOPY        ;copy filename with tag character (*)
  1062. M$LP    LHLD    RINGPOS        ;re-entry point for next file mass-copy
  1063.     XCHG            ;at ring..
  1064.     LHLD    RINGEND        ;..end yet?
  1065.     CALL    CMPDEHL        ; (compare present position with end)
  1066.     JZ    MF$EXIT        ;yes, jump to beginning of ring.
  1067.     LHLD    RINGPOS
  1068.     JMP    MASS$LP        ;no, loop 'till thru ring list.
  1069.  
  1070. MF$EXIT    XRA    A        ;reset flags..
  1071.     STA    FIRST$M        ;..for..
  1072.     CMA            ;..next..
  1073.     STA    MFLAG        ;..mass-copy request.
  1074.     JMP    CMDLOOP        ;jump to 'ring' beginning
  1075.  
  1076. ; c o p y
  1077.  
  1078. ; copy source file at current 'ring' position to another drive.  set-up
  1079. ; fcb's and buffer area and check for correct keyboard inputs.  contains
  1080. ; auto-crc file copy verification.
  1081.  
  1082. MCOPY    XRA    A        ;zero flag to..
  1083.     STA    MFLAG        ;..mass copy.
  1084. COPY    LXI    H,0        ;initialize storage for..
  1085.     SHLD    CRCVAL        ;..'crc' working value.
  1086.     CALL    RINGFCB        ;move from 'ring' to 'sfcb'
  1087.     LXI    H,S$FCB+12    ;set pointer to source extent field
  1088.     CALL    INITFCB
  1089.     XRA    A        ;zero fcb 'cr' field
  1090.     STA    S$FCB+32
  1091.     MVI    B,32        ;copy source 'fcb' to destination 'fcb'
  1092.     LXI    H,S$FCB+1    ;from point..
  1093.     LXI    D,D$FCB+1    ;..to point..
  1094.     CALL    MOVE        ;..move across.
  1095.     LXI    D,S$FCB        ;open file for reading
  1096.     MVI    C,OPEN        ;open function
  1097.     CALL    BDOS
  1098.     INR    A        ; 0ffh --> 00h if bad open
  1099.     JNZ    COPY2        ;if okay, skip error message.
  1100.     CALL    ILPRT
  1101.     DB    CR,LF,'++ UNABLE TO OPEN SOURCE ++',0
  1102.     JMP    NEUTRAL
  1103.  
  1104. COPY2    LDA    FIRST$M        ;by-pass prompt, drive/userAD    D
  1105.     SHLD    BUF$PT
  1106.     LXI    D,D$FCB        ;destination file 'fcb'
  1107.     MVI    C,WRITE        ;write record function
  1108.     CALL    BDOS
  1109.     ORA    A           ; 00h --> write okay
  1110.     JZ    COPY10        ;okay, do next record.  else..
  1111.     CALL    ILPRT        ;..say disk write error.
  1112.     DB    CR,LF,'++ COPY DISK FULL ++',BELL,0
  1113. C$ERA    LXI    D,D$FCB        ;delete..
  1114.     MVI    C,ERASE        ;..partial..
  1115.     CALL    BDOS        ;..from directory.
  1116.     XRA    A              ;reset 1st-time-thru tag flag..
  1117.     STA    FIRST$M        ;..for continuation of mass copying.
  1118.     JMP    NEUTRAL        ;back to ring
  1119.  
  1120. COPY11    LDA    EOFLAG        ;buffer all written, check for 'eof'.
  1121.     ORA    A
  1122.     JZ    COPY6A        ;branch to read next buffer full
  1123.     LXI    D,D$FCB        ;point at 'fcb' for file closure
  1124.     MVI    C,CLOSE
  1125.     CALL    BDOS
  1126.     INR    A        ;if no-close-error then..
  1127.     JNZ    CRC$CMP        ;..compare file crc's.
  1128.     CALL    ILPRT
  1129.     DB    CR,LF,'++ COPY CLOSE ERROR ++',BELL,0
  1130.     JMP    C$ERA
  1131.  
  1132. ; read destination 'written-file' and compare crc's
  1133.  
  1134. CRC$CMP    LHLD    CRCVAL        ;transfer 'crc' value to..
  1135.     SHLD    CRCVAL2        ;..new storage area.
  1136.     LXI    H,0        ;clear working storage..
  1137.     SHLD    CRCVAL        ;..to continue.
  1138.     LXI    D,TBUF
  1139.     MVI    C,SETDMA
  1140.     CALL    BDOS
  1141.     LXI    H,D$FCB+12
  1142.     CALL    INITFCB
  1143.     LXI    D,D$FCB
  1144.     MVI    C,OPEN
  1145.     CALL    BDOS
  1146.     INR    A        ; 0ffh --> 00h if bad open
  1147.     JZ    BADCRC        ;if bad open, just say 'bad-crc'.
  1148.     XRA    A        ;zero 'fcb'..
  1149.     STA    D$FCB+32    ;..'cr' field.
  1150. CRCWF1    LXI    D,D$FCB
  1151.     MVI    C,READ
  1152.     CALL    BDOS
  1153.     ORA    A        ;read okay?
  1154.     JZ    D$RD$OK        ;yes, read more.
  1155.     DCR    A        ;eof?
  1156.     JZ    FINCRC        ;yes, finish up and make 'crc' comparison.
  1157.     CALL    ILPRT
  1158.     DB    CR,LF,'++ COPY READ ERROR ++',BELL,0
  1159.     JMP    NEUTRAL
  1160.  
  1161. D$RD$OK    LXI    H,TBUF
  1162.     MVI    B,128
  1163. CRCWF2    MOV    A,M        ;get character to..
  1164.     CALL    UPDCRC        ;..add to 'crc' value. 
  1165.     INX    H
  1166.     DCR    B
  1167.     JNZ    CRCWF2
  1168.     JMP    CRCWF1
  1169.  
  1170. ; crc subroutines
  1171.  
  1172. ; initialize tables for fast crc calculations
  1173.  
  1174. INITCRC    LXI    H,CRCTBL
  1175.     MVI    C,0        ;table index
  1176. GLOOP    XCHG
  1177.     LXI    H,0        ;initialize crc register pair
  1178.     MOV    A,C
  1179.     PUSH    B        ;save index in c-reg
  1180.     MVI    B,8
  1181.     XRA    H
  1182.     MOV    H,A
  1183. LLOOP    DAD    H
  1184.     JNC    LSKIP
  1185.     MVI    A,10H        ;generator is x^16 + x^12 + x^5 + x^0 as..
  1186.     XRA    H        ;..recommended by ccitt for asynchronous..
  1187.     MOV    H,A        ;..comPE
  1188.     CALL    CLR$L        ;clear line
  1189.     CALL    ILPRT
  1190.     DB    CR,' ---> Copying file '
  1191. COPYMFN    DB    '        .    ',0
  1192.     XRA    A        ;clear 'eof'..
  1193.     STA    EOFLAG        ;..flag.
  1194. COPY6A    LDA    C$U$A        ;reset user area..
  1195.     CALL    SET$USR        ;..to current.
  1196.     LXI    H,0        ;clear current-record..
  1197.     SHLD    REC$CNT        ;..counter.
  1198.     LHLD    BUFSTART    ;set buffer start pointer..
  1199.     SHLD    BUF$PT        ;..to begin pointer.
  1200.  
  1201. ; read source file -- fill buffer memory or stop on 'eof' -- update 'crc'
  1202. ; on-the-fly
  1203.  
  1204. COPY7    LHLD    BUF$PT        ;set dma address to buffer pointer
  1205.     XCHG            ; de-pair --> dma address
  1206.     MVI    C,SETDMA
  1207.     CALL    BDOS
  1208.     LXI    D,S$FCB        ;source 'fcb' for reading
  1209.     MVI    C,READ        ;record read function
  1210.     CALL    BDOS
  1211.     ORA    A        ; 00h --> read okay
  1212.     JZ    S$RD$OK
  1213.     DCR    A        ;eof?
  1214.     JZ    COPY8        ;yes, end-of-file, set 'eof' flag.
  1215.     CALL    ILPRT
  1216.     DB    CR,LF,'++ SOURCE READ ERROR ++',BELL,0
  1217.     JMP    NEUTRAL
  1218.  
  1219. S$RD$OK    LHLD    BUF$PT
  1220.     MVI    B,128
  1221. COPY7A    MOV    A,M        ;get character and..
  1222.     CALL    UPDCRC        ;..add to 'crc' value.
  1223.     INX    H
  1224.     DCR    B
  1225.     JNZ    COPY7A        ;loop 'till record read finished
  1226.     LHLD    BUF$PT        ;bump buffer pointer..
  1227.     LXI    D,128        ;..by..
  1228.     DAD    D        ;..one..
  1229.     SHLD    BUF$PT        ;..record.
  1230.     LHLD    REC$CNT        ;bump buffer..
  1231.     INX    H        ;..record count and..
  1232.     SHLD    REC$CNT        ;..store.
  1233.     XCHG            ;ready to compare to..
  1234.     LHLD    REC$MAX        ;..maximum record count (full-buffer).
  1235.     CALL    CMPDEHL        ;compare
  1236.     JNZ    COPY7        ;if not full, get next record.
  1237.     JMP    COPY9        ;full, start first write session.
  1238.  
  1239. ; indicate end-of-file read
  1240.  
  1241. COPY8    MVI    A,TRUE        ;set 'eof' flag
  1242.     STA    EOFLAG
  1243.  
  1244. ; write 'read-file' from memory buffer to destination 'written-file'
  1245.  
  1246. COPY9    LDA    R$U$A        ;set user to requested..
  1247.     CALL    SET$USR        ;..area.
  1248.     LHLD    BUFSTART    ;adjust buffer pointer..
  1249.     SHLD    BUF$PT        ;..to start address.
  1250. COPY10    LHLD    REC$CNT        ;buffer empty?
  1251.     MOV    A,H
  1252.     ORA    L
  1253.     JZ    COPY11        ;buffer empty, check 'eof' flag.
  1254.     DCX    H        ;dec buffer record count for each write
  1255.     SHLD    REC$CNT
  1256.     LHLD    BUF$PT        ;set up dma address
  1257.     PUSH    H        ;save for size bump
  1258.     XCHG            ;pointer in de-pair
  1259.     MVI    C,SETDMA
  1260.     CALL    BDOS
  1261.     POP    H
  1262.     LXI    D,128        ;bump pointer one record length
  1263.     DAD    D
  1264.     SHLD    BUF$PT
  1265.     LXI    D,D$FCB        ;destination file 'fcb'
  1266.     MVI    C,WRITE        ;write record function
  1267.     CALL    BDOS
  1268.     ORA    A           ; 00h --> write okay
  1269.     JZ    COPY10        ;okay, do next record.  else..
  1270.     CALL    ILPRT        ;..say disk write error.
  1271.     DB    CR,LF,'++ COPY DISK FULL ++',BELL,0
  1272. C$ERA    LXI    D,D$FCB        ;delete..
  1273.     MVI    C,ERASE        ;..partial..
  1274.     CALL    BDOS        ;..from directory.
  1275.     XRA    A              ;reset 1st-time-thru tag flag..
  1276.     STA    FIRST$M        ;..for continuation of mass copying.
  1277.     JMP    NEUTRAL        ;back to ring
  1278.  
  1279. COPY11    LDA    EOFLAG        ;buffer all written, check for 'eof'.
  1280.     ORA    A
  1281.     JZ    COPY6A        ;branch to read next buffer full
  1282.     LXI    D,D$FCB        ;point at 'fcb' for file closure
  1283.     MVI    C,CLOSE
  1284.     CALL    BDOS
  1285.     INR    A        ;if no-close-error then..
  1286.     JNZ    CRC$CMP        ;..compare file crc's.
  1287.     CALL    ILPRT
  1288.     DB    CR,LF,'++ COPY CLOSE ERROR ++',BELL,0
  1289.     JMP    C$ERA
  1290.  
  1291. ; read destination 'written-file' and compare crc's
  1292.  
  1293. CRC$CMP    LHLD    CRCVAL        ;transfer 'crc' value to..
  1294.     SHLD    CRCVAL2        ;..new storage area.
  1295.     LXI    H,0        ;clear working storage..
  1296.     SHLD    CRCVAL        ;..to continue.
  1297.     LXI    D,TBUF
  1298.     MVI    C,SETDMA
  1299.     CALL    BDOS
  1300.     LXI    H,D$FCB+12
  1301.     CALL    INITFCB
  1302.     LXI    D,D$FCB
  1303.     MVI    C,OPEN
  1304.     CALL    BDOS
  1305.     INR    A        ; 0ffh --> 00h if bad open
  1306.     JZ    BADCRC        ;if bad open, just say 'bad-crc'.
  1307.     XRA    A        ;zero 'fcb'..
  1308.     STA    D$FCB+32    ;..'cr' field.
  1309. CRCWF1    LXI    D,D$FCB
  1310.     MVI    C,READ
  1311.     CALL    BDOS
  1312.     ORA    A        ;read okay?
  1313.     JZ    D$RD$OK        ;yes, read more.
  1314.     DCR    A        ;eof?
  1315.     JZ    FINCRC        ;yes, finish up and make 'crc' comparison.
  1316.     CALL    ILPRT
  1317.     DB    CR,LF,'++ COPY READ ERROR ++',BELL,0
  1318.     JMP    NEUTRAL
  1319.  
  1320. D$RD$OK    LXI    H,TBUF
  1321.     MVI    B,128
  1322. CRCWF2    MOV    A,M        ;get character to..
  1323.     CALL    UPDCRC        ;..add to 'crc' value. 
  1324.     INX    H
  1325.     DCR    B
  1326.     JNZ    CRCWF2
  1327.     JMP    CRCWF1
  1328.  
  1329. ; crc subroutines
  1330.  
  1331. ; initialize tables for fast crc calculations
  1332.  
  1333. INITCRC    LXI    H,CRCTBL
  1334.     MVI    C,0        ;table index
  1335. GLOOP    XCHG
  1336.     LXI    H,0        ;initialize crc register pair
  1337.     MOV    A,C
  1338.     PUSH    B        ;save index in c-reg
  1339.     MVI    B,8
  1340.     XRA    H
  1341.     MOV    H,A
  1342. LLOOP    DAD    H
  1343.     JNC    LSKIP
  1344.     MVI    A,10H        ;generator is x^16 + x^12 + x^5 + x^0 as..
  1345.     XRA    H        ;..recommended by ccitt for asynchronous..
  1346.     MOV    H,A        ;..communications.  produces the same..
  1347.     MVI    A,21H        ;..results as public domain programs..
  1348.     XRA    L        ;..chek, comm7, mdm7, and modem7.
  1349.     MOV    L,A
  1350. LSKIP    DCR    B
  1351.     JNZ    LLOOP
  1352.     POP    B
  1353.     XCHG            ;de-pair now has crc, hl pointing into table.
  1354.     MOV    M,D        ;store high byte of crc..
  1355.     INR    H
  1356.     MOV    M,E        ;..and store low byte.
  1357.     DCR    H
  1358.     INX    H        ;move to next table entry
  1359.     INR    C        ;next index
  1360.     JNZ    GLOOP
  1361.     RET
  1362.  
  1363. UPDCRC    PUSH    B        ;update 'crc'..
  1364.     PUSH    H        ;..accumulator..
  1365.     LHLD    CRCVAL        ;pick up partial remainder
  1366.     XCHG            ;de-pair now has partial
  1367.     MVI    B,0
  1368.     XRA    D
  1369.     MOV    C,A
  1370.     LXI    H,CRCTBL
  1371.     DAD    B
  1372.     MOV    A,M
  1373.     XRA    E
  1374.     MOV    D,A
  1375.     INR    H
  1376.     MOV    E,M
  1377.     XCHG
  1378.     SHLD    CRCVAL
  1379.     POP    H
  1380.     POP    B
  1381.     RET
  1382.  
  1383. FINCRC    LDA    C$U$A        ;reset user from 'requested'..
  1384.     CALL    SET$USR        ;..to 'current' area.
  1385.     LHLD    CRCVAL        ;put written-file 'crc' into..
  1386.     XCHG            ;..de-pair.
  1387.     LHLD    CRCVAL2        ;put read-file 'crc' and..
  1388.     CALL    CMPDEHL        ;..compare 'de/hl' for equality.
  1389.     JNZ    BADCRC        ;if not zero, show copy-error message.
  1390.     CALL    ILPRT        ;if zero, show 'verified' message.
  1391.     DB    CR,' ---> Copy CRC verified         ',0
  1392.     LDA    MFLAG        ;if not mass-copy mode, return..
  1393.     ORA    A        ;..to next 'ring' position.
  1394.     JNZ    FORWARD        ;else..
  1395.     CMA            ;..set 1st-time-thru flag..
  1396.     STA    FIRST$M        ;..and..
  1397.     JMP    M$LP        ;..get next file to copy, if one.
  1398.  
  1399. BADCRC    CALL    ILPRT
  1400.     DB    CR,LF,BELL,'++ Error on CRC compare ++',0
  1401.     JMP    FORWARD        ;move to next 'ring' position
  1402.  
  1403. ; w o r k h o r s e   r o u t i n e s
  1404.  
  1405. ; inline print of message
  1406.  
  1407. ILPRT    XTHL            ;save hl, get msg pointer.
  1408. ILPLP    MOV    A,M        ;get character
  1409.     ANI    7FH        ;strip type bits
  1410.     CALL    TYPE        ;show on console
  1411.     INX    H        ;point to the next character and..
  1412.     MOV    A,M
  1413.     ORA    A        ;..test for end-of-text.
  1414.     JNZ    ILPLP
  1415.     XTHL            ;set hl-pair and..
  1416.     RET            ;..return past message.
  1417.  
  1418. ; clear console crt screen
  1419.  
  1420. CLS    MVI    B,17        ;output lf's
  1421. LFLP    MVI    A,LF
  1422.     CALL    TYPE
  1423.     DCR    B        ;count-down b-reg --> zero
  1424.     JNZ    LFLP
  1425.     RET
  1426.  
  1427. ; output 'crlf' to console
  1428.  
  1429. CRLF    MVI    A,CR
  1430.     CALL    TYPE
  1431.     MVI    A,LF
  1432.  
  1433. ; conout routine (re-entrant)
  1434.  
  1435. TYPE    PUSH    PSW
  1436.     PUSH    B
  1437.     PUSH    D
  1438.     PUSH    H
  1439.     MOV    E,A
  1440.     MVI    C,WRCON
  1441.     CALL    BDOS
  1442.     POP    H
  1443.     POP    D
  1444.     POP    B
  1445.     POP    PSW
  1446.     RET
  1447.  
  1448. ; crt clear-line function
  1449.  
  1450. CLR$L    MVI    A,CR
  1451.     CALL    TYPE
  1452.     MVI    B,30        ;blank # of characters on line
  1453.     MVI    A,' '
  1454. CL$LP    CALL    TYPE
  1455.     DCR    B
  1456.     JNZ    CL$LP
  1457.     RET
  1458.  
  1459. ; conin routine (waits for response)
  1460.  
  1461. KEYIN    MVI    C,RDCON
  1462.     CALL    BDOS
  1463.  
  1464. ; convert character in a-reg to upper case
  1465.  
  1466. UCASE    CPI    61H        ;less than small 'a'?
  1467.     RC            ;if so, no convert needed.
  1468.     CPI    7AH+1        ; >small 'z'?
  1469.     RNC            ;if so, ignore.
  1470.     ANI    5FH        ;otherwise convert
  1471.     RET
  1472.  
  1473. ; direct console input w/o echo (waits for input)
  1474.  
  1475. DKEYIN    MVI    C,DIRCON    ;cp/m function 6
  1476.     MVI    E,0FFH
  1477.     CALL    BDOS
  1478.     ORA    A
  1479.     JZ    DKEYIN
  1480.     RET
  1481.  
  1482. ; convert keyboard input to upper case
  1483.  
  1484. CONVERT    LXI    H,CMDBUF+1    ; 'current keyboard buffer length'..
  1485.     MOV    B,M        ;..to b-reg.
  1486.     MOV    A,B
  1487.     ORA    A        ;if zero length, skip conversion.
  1488.     JZ    COMCAN
  1489. CONVLP    INX    H        ;point at character to capitalize
  1490.     MOV    A,M
  1491.     CALL    UCASE
  1492.     MOV    M,A        ;put back into buffer
  1493.     DCR    B
  1494.     JNZ    CONVLP
  1495.     RET
  1496.  
  1497. ; fill buffer with 'spaces' with count in b-reg
  1498.  
  1499. FILL    MVI    M,' '        ;put in space character
  1500.     INX    H
  1501.     DCR    B        ;count done?
  1502.     JNZ    FILL        ;no, branch.
  1503.     RET
  1504.  
  1505. ; ignore leading spaces (ls) in buffer, length in c-reg.
  1506.  
  1507. UNSPACE    LDAX    D        ;get character
  1508.     CPI    ' '
  1509.     RNZ            ;not blank, a file is entered.
  1510.     INX    D        ;to next character
  1511.     DCR    C
  1512.     JZ    COMCAN        ;all spaces --> command recovery error
  1513.     JMP    UNSPACE
  1514.  
  1515. ; check for legal cp/m filename character -- return with carry set if illegal
  1516.  
  1517. CKLEGAL    LDAX    D        ;get character from de-pair
  1518.     INX    D        ;point at next character
  1519.     CPI    ' '        ;less than space?
  1520.     RC            ;return carry if unpermitted character
  1521.     PUSH    H
  1522.         PUSH    B
  1523.     CPI    '['        ;if greater than 'z', exit with..
  1524.     JNC    CKERR        ;..carry set.
  1525.     MVI    B,8
  1526.     LXI    H,CHR$TBL
  1527. CHR$LP    CMP    M  
  1528.     JZ    CKERR
  1529.     INX    H
  1530.     DCR    B
  1531.     JNZ    CHR$LP
  1532.     ORA    A        ;clear carry for good character
  1533.     POP    B
  1534.     POP    H
  1535.     RET
  1536.  
  1537. CKERR    POP    B
  1538.     POP    H
  1539.     STC                 ;error exit with carry set
  1540.     RET
  1541.  
  1542. CHR$TBL    DB    '*',',',':',';','<','=','>','?'    ;invalid character table
  1543.  
  1544. ; filename from 'ring' to 'sfcb'
  1545.  
  1546. RINGFCB    LHLD    RINGPOS        ;move name from ring to source 'fcb'
  1547.     LXI    D,-13        ;subtract 13 to..
  1548.     DAD    D        ;..point to name position.
  1549.     LXI    D,S$FCB        ;place to move filename and..
  1550.     MVI    B,12        ;..amount to move.
  1551.  
  1552. ; move subroutine -- move b-reg # of bytes from hl-pair to de-pair
  1553.  
  1554. MOVE    MOV    A,M        ;get hl-pair referenced source byte
  1555.     ANI    7FH        ;strip cp/m 2.x attributes
  1556.     STAX    D        ;put to de-pair referenced destination
  1557.     INX    H        ;fix pointers for next search
  1558.     INX    D
  1559.     DCR    B        ;dec byte count and see if done
  1560.     JNZ    MOVE
  1561.     RET
  1562.  
  1563. ; initialize 'fcb' cp/m system fields (entry with hl-pair pointing to 'fcb')
  1564.  
  1565. INITFCB    MVI    B,4        ;fill ex, s1, s2, rc counters with zeros.
  1566. INITLP    MVI    M,0        ;put zero (null) in memory
  1567.     INX    H
  1568.     DCR    B
  1569.     JNZ    INITLP
  1570.     RET
  1571.  
  1572. ; disk system reset -- login requested drive
  1573.  
  1574. RESET    MVI    C,INQDISK    ;determine and..
  1575.     CALL    BDOS        ;..save..
  1576.     STA    C$DR        ;..current drive.
  1577.     MVI    C,RESETDK    ;reset system
  1578.     CALL    BDOS
  1579.     LDA    R$DR        ;make requested drive..
  1580. SET$DR    MOV    E,A        ;..current.
  1581.     MVI    C,LOGIN
  1582.     JMP    BDOS        ;return to caller
  1583.  
  1584. ; set/reset (or get) user area (call with binary user area in a-reg)
  1585.  
  1586. SET$USR    MOV    E,A        ; 0 --> 0, 1 --> 1, etc.
  1587. GET$USR    MVI    C,SGUSER
  1588.     JMP    BDOS        ;return to caller
  1589.  
  1590. ; compare de-pair to hl-pair and set flags accordingly
  1591.  
  1592. CMPDEHL    MOV    A,D        ;see if high bytes set flags
  1593.     CMP    H
  1594.     RNZ            ;return if not equal
  1595.     MOV    A,E
  1596.     CMP    L        ;low bytes set flags instead
  1597.     RET
  1598.  
  1599. ; shift hl-pair b-reg bits (-1) to right (divider routine)
  1600.  
  1601. SHIFTLP    DCR    B
  1602.     RZ
  1603.     MOV    A,H
  1604.     ORA    A
  1605.     RAR
  1606.     MOV    H,A
  1607.     MOV    A,L
  1608.     RAR
  1609.     MOV    L,A
  1610.     JMP    SHIFTLP
  1611.  
  1612. ; decimal pretty print (h-reg contains msb; l-reg, the lsb.)
  1613.  
  1614. DECOUT    PUSH    PSW
  1615.     PUSH    B
  1616.     PUSH    D
  1617.     PUSH    H
  1618.     LXI    B,-10        ;radix
  1619.     LXI    D,-1
  1620. DECOU2    DAD    B        ;sets..
  1621.     INX    D
  1622.     JC    DECOU2        ;..carry.    
  1623.     LXI    B,10
  1624.     DAD    B
  1625.     XCHG
  1626.     MOV    A,H
  1627.     ORA    L
  1628.     CNZ    DECOUT        ; (recursive)
  1629.     MOV    A,E
  1630.     ADI    '0'        ;make ascii
  1631.     CALL    TYPE
  1632.     POP    H
  1633.     POP    D
  1634.     POP    B
  1635.     POP    PSW
  1636.     RET
  1637.  
  1638. ; determine # of bcd digits in hl-pair -- place # in b-reg
  1639.  
  1640. DET$BCD    LXI    D,9        ;test for less than 10
  1641.     CALL    CMPDEHL        ;compare and..
  1642.     MVI    B,1        ; (one bcd digit)
  1643.     RNC                ;..return if not carry.
  1644.     MVI    E,99        ;less than 100?
  1645.     CALL    CMPDEHL
  1646.     MVI    B,2
  1647.     RNC
  1648.     LXI    D,999        ; <1000?
  1649.     CALL    CMPDEHL
  1650.     MVI    B,3
  1651.     RNC
  1652.     MVI    B,4        ;assume >999  (4 digits)
  1653.     RET
  1654.  
  1655. ; determine free storage remaining on selected drive
  1656.  
  1657. FRESTOR    MVI    C,INQDISK    ;determine current drive
  1658.     CALL    BDOS        ;returns 0 as a:, 1 as b:, etc.
  1659.     INR    A        ;make 1 --> a:, 2 --> b:, etc.
  1660.     STA    FCB
  1661.     ADI    'A'-1        ;make printable and..
  1662.     STA    DRNAME        ;..use as drive designator.
  1663.     MVI    C,GETPARM    ;current disk parameter block
  1664.     CALL    BDOS
  1665.     INX    H        ;bump to..
  1666.     INX    H
  1667.     MOV    A,M        ;..block shift factor.
  1668.     STA    BSHIFTF        ; 'bsh'
  1669.     INX    H        ;bump to..
  1670.     MOV    A,M        ;..block mask.
  1671.     STA    B$MASK        ; 'blm'
  1672.     INX    H        ;bump to..
  1673.     INX    H        ;..get..
  1674.     MOV    E,M        ;..maximum block number..
  1675.     INX    H        ;..double..
  1676.     MOV    D,M        ;..byte.
  1677.     XCHG
  1678.     SHLD    B$MAX        ; 'dsm'
  1679.     MVI    C,INQALC    ;address of cp/m allocation vector
  1680.     CALL    BDOS
  1681.     XCHG            ;get its length
  1682.     LHLD    B$MAX
  1683.     INX    H
  1684.     LXI    B,0        ;initialize block count to zero
  1685. GSPBYT    PUSH    D        ;save allocation address
  1686.     LDAX    D
  1687.     MVI    E,8        ;set to process 8 bits (blocks)
  1688. GSPLUP    RAL            ;test bit
  1689.     JC    NOT$FRE
  1690.     INX    B
  1691. NOT$FRE    MOV    D,A        ;save bits
  1692.     DCX    H
  1693.     MOV    A,L
  1694.     ORA    H    
  1695.     JZ    END$ALC        ;quit if out of blocks
  1696.     MOV    A,D        ;restore bits
  1697.     DCR    E        ;count down 8 bits
  1698.     JNZ    GSPLUP        ;branch to do another bit
  1699.     POP    D        ;bump to next count..
  1700.     INX    D        ;..of allocation vector.
  1701.     JMP    GSPBYT        ;process it
  1702.  
  1703. END$ALC    POP    D        ;clear alloc vector pointer from stack
  1704.     MOV    L,C        ;copy # blocks to hl-pair
  1705.     MOV    H,B
  1706.     LDA    BSHIFTF        ;get block shift factor
  1707.     SUI    3        ;convert from sectors to thousands (k)
  1708.     JZ    PRT$FRE        ;skip shifts if 1k blocks
  1709. FREK$LP    DAD    H        ;multiply blocks by k-bytes per block
  1710.     DCR    A        ;multiply by 2, 4, 8, or 16.
  1711.     JNZ    FREK$LP
  1712. PRT$FRE    CALL     DECOUT        ; # of free k-bytes in hl-pair
  1713.     CALL    ILPRT
  1714.     DB    'k bytes free on drive '
  1715. DRNAME    DB    ' :',CR,LF,'   ',0
  1716. SAVEHL  DB      0,0
  1717.     RET
  1718.  
  1719. ; s t o r a g e
  1720.  
  1721. ; initialized
  1722.  
  1723. JOKER     DB    '???????????'    ; *.* equivalent
  1724. J$FLG     DB    TRUE        ;default jump 22-files command flag
  1725. FIRST$M     DB    FALSE        ; 1st time thru in mass-copy mode
  1726. MFLAG     DB    TRUE        ;multiple file copy flag --> 0 for mass copy
  1727. TAG$TOT     DW    0        ;summation of tagged file sizes
  1728. CMDBUF     DB    32,0        ;command buffer maximum length, usage, and..
  1729.  
  1730. ; uninitialized
  1731.  
  1732.      DS    100        ;..storage for buffer and local stack.
  1733. STACK     DS    2        ;cp/m's stack pointer stored here
  1734. B$MAX     DS    2        ;highest block number on drive
  1735. B$MASK     DS    1        ;sec/blk - 1
  1736. BSHIFTF     DS    1        ; # of shifts to multiply by sec/blk
  1737. BUF$PT     DS    2        ;copy buffer current pointer..
  1738. BUFSTART DS    2        ;..and begin pointer.
  1739. CANFLG     DS    1        ;no-file-found cancel flag
  1740. C$DR     DS    1        ; 'current drive'
  1741. CON$LST     DS    1        ;bdos function storage
  1742. CRCTBL     DS    512        ;tables for 'crc' calculations
  1743. CRCVAL     DS    2        ; 2-byte 'crc' value of working file and..
  1744. CRCVAL2     DS    2        ;..of finished source read-file.
  1745. C$U$A     DS    1        ; 'current user area'
  1746. D$FCB     DS    33        ;fcb for destination file/new name if rename
  1747. EOFLAG     DS    1        ;file copy loop 'eof' flag
  1748. FS$FLG     DS    1        ;tag total versus file size flag
  1749. J$CNT     DS    1        ;jump forward file counter
  1750. LPSCNT     DS    1        ;lines-per-screen for 'view'
  1751. O$USR     DS    1        ;store initial user area for exit
  1752. R$DR     DS    1        ; 'requested drive'
  1753. RCNT     DS    2        ; # of records in file and..
  1754. REC$CNT     DS    2        ;..currently in ram buffer.
  1755. REC$MAX     DS    2        ;maximum 128-byte record capacity of buffer
  1756. RINGI     DS    2        ;ring sort pointer
  1757. RINGJ     DS    2        ;another ring sort pointer
  1758. RINGEND     DS    2        ;current ring end pointer
  1759. RINGPOS     DS    2        ;current ring position in scan
  1760. R$U$A     DS    1        ; 'requested user area'
  1761. S$FCB     DS    36        ;fcb for source (random record) file
  1762. TEST$RT     DS    1        ;intermediate right-justify data
  1763. T$UN$FG     DS    1        ;tag/untag file summation switch
  1764. VIEWFLG     DS    1        ; 00h --> to list/punch else to crt 'view'
  1765.  
  1766. ; cp/m system functions
  1767.  
  1768. RDCON    EQU    1        ;console input function
  1769. WRCON    EQU    2        ;write character to console..
  1770. PUNCH    EQU    4        ;..punch and..
  1771. LIST    EQU    5        ;..to list logical devices.
  1772. DIRCON    EQU    6        ;direct console i/o
  1773. RDBUF    EQU    10        ;read input string
  1774. CONST    EQU    11        ;get console status
  1775. RESETDK    EQU    13        ;reset disk system
  1776. LOGIN    EQU    14        ;log-in new drive
  1777. OPEN    EQU    15        ;open file
  1778. CLOSE    EQU    16        ;close file
  1779. SRCHF    EQU    17        ;search directory for first..
  1780. SRCHN    EQU    18        ;..and next occurrence.
  1781. ERASE    EQU    19        ;erase file
  1782. READ    EQU    20        ;read and..
  1783. WRITE    EQU    21        ;..write 128-record.
  1784. MAKE    EQU    22        ;make file
  1785. REN    EQU    23        ;rename file
  1786. INQDISK    EQU    25        ;get current (default) drive
  1787. SETDMA    EQU    26        ;set dma address
  1788. INQALC    EQU    27        ;allocation vector
  1789. GETPARM    EQU    31        ;current drive parameters address
  1790. SGUSER    EQU    32        ;set or get user area
  1791. COMPSZ    EQU    35        ; # of records in file
  1792.  
  1793. ; system addresses
  1794.  
  1795. BDOS     EQU    CPM$BASE+05H    ;bdos function entry address
  1796. FCB     EQU    CPM$BASE+5CH    ;default file control block
  1797. FCBEXT     EQU    FCB+12          ;extent byte in 'fcb'
  1798. FCBRNO     EQU    FCB+32        ;record number in 'fcb'
  1799. TBUF     EQU    CPM$BASE+80H    ;default cp/m buffer
  1800.  
  1801. ; assembled 'com' and 'ram-loaded' file size (0c00h = 3k)
  1802.  
  1803. COMFILE     EQU    (CMDBUF+2)-256    ; 'prn' listing shows 'com'..
  1804. LAST     END    SOURCE        ;..and loaded file size.
  1805. le size (0c00h = 3k)
  1806.  
  1807. COMFILE     EQU    (CMDBUF+2)-256    ; 'prn'