home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol145 / vfiler.asm < prev    next >
Assembly Source File  |  1984-04-29  |  82KB  |  3,913 lines

  1. ;  PROGRAM:  VFILER
  2. ;  VERSION:  1.7
  3. ;  DATE:  9 Sep 83
  4. ;  AUTHOR:  Richard Conn
  5. ;  PREVIOUS VERSIONS:  1.6 (18 Aug 83), 1.5 (20 July 83)
  6. ;  PREVIOUS VERSIONS:  1.4 (19 July 83), 1.3 (18 July 83)
  7. ;  PREVIOUS VERSIONS:  1.2 (18 July 83), 1.1 (17 July 83), 1.0 (16 July 83)
  8. ;  DERIVATION:  From FILER (Version 1.6) by Richard Conn
  9. ;
  10. VERS    EQU    17        ;version number
  11.  
  12. ; VFILER from DISK7, Version 7.6C
  13. ; DISK7, Version 7.6C, copyright (c) 1983 by Frank Gaude'.  All rights reserved
  14. ; released to the public domain for non-commercial use.
  15. ; Monetary gain in not permitted under
  16. ; any circumstance by individual, partnership, or corporation.
  17.  
  18. ; DISK7 is based on common ideas presented in CLEANUP, WASH, and SWEEP,
  19. ; written by Ward Christensen, Michael Karas, and Robert Fisher, respectively.
  20. ; Existence of these programs generated impetus for writing DISK7.
  21.  
  22. ; VFILER is a screen-oriented, ZCPR2-specific file utility.  It can be
  23. ; installed to run under conventional CP/M by turning all of the ZCPR2-specific
  24. ; options off, but it is highly recommended to obtain ZCPR2 (or the 8080
  25. ; version called ZC8080) and use VFILER in conjunction with it.  VFILER
  26. ; extensively employs cursor addressing to position a pointer on the
  27. ; screen, allow the user to manipulate the pointer (up, down, right, left,
  28. ; next screen, previous screen, GOTO file).  The pointer points to files
  29. ; in the current user directory and displays the user's position dynamically
  30. ; on the screen.  Once pointing to a file, user commands can be used to
  31. ; manipulate the file (delete, copy, view on console, print on printer, tag
  32. ; for later copy or delete, and untag).  In the way of being ZCPR2-specific,
  33. ; VFILER can chain to external programs via the MCL and then return (ala
  34. ; MENU), and it recognizes Named Directories (so the user can log into B:, B4:,
  35. ; and MYDIR:, for example).
  36.  
  37. ; VFILER is installed by GENINS.
  38.  
  39. ; VFILER works with CP/M 2.2 only, with 24k or more of RAM.  File copy
  40. ; functions are faster with large amounts of RAM.  It is slightly larger
  41. ; than DISK7, occupying 5-6K bytes of memory.  VFILER includes some Z80-
  42. ; specific code, while DISK7 is totally 8080.
  43.  
  44. ; starting definitions
  45.  
  46. TRUE     EQU    0FFH        ;define true and..
  47. FALSE     EQU    0           ;..false.
  48. Z80     EQU    TRUE         ;TRUE to use Z80 Instructions
  49. WARMBOOT EQU    FALSE        ;set true to warmboot on exit
  50. CPM$BASE EQU    000H        ;cp/m system base..
  51. TPA     EQU    100H        ;..'transient program area' start..
  52. CCP     EQU    800H        ;..and 'ccp' length in bytes.
  53. GET     EQU    0FFH        ;get user area e-reg value
  54. EPS     EQU    16*4        ;16 lines x 4 cols per screen
  55.                 ;  EPS = Entries Per Screen
  56.  
  57. ; cursor positioning as per the user's particular terminal
  58. ;   this is set for the TVI 950 function keys
  59.  
  60. USER$UP        EQU    0BH    ;^K
  61. USER$DOWN    EQU    16H    ;^V
  62. USER$RIGHT    EQU    0CH    ;^L
  63. USER$LEFT    EQU    08H    ;^H
  64. SCR$FOR        EQU    06H    ;^F
  65. SCR$BACK    EQU    01H    ;^A
  66.  
  67. ; cursor positioning addresses
  68.  
  69. EPSLINE    EQU    (EPS/4)+5    ;position of last line of EPS
  70. BANADR    EQU    1*256+24    ;banner address
  71. SDMADR    EQU    3*256+30    ;screen directory message
  72. CURHOME    EQU    4*256+1        ;home address of cursor
  73. BOTADR    EQU    23*256+1    ;bottom of screen
  74. CPMADR    EQU    EPSLINE*256+1    ;command prompt message
  75. CPADR    EQU    EPSLINE*256+30    ;command prompt
  76. ERADR    EQU    (EPSLINE+1)*256+30    ;error message
  77. FSADR    EQU    ERADR        ;file size message
  78. FNADR    EQU    (EPSLINE+1)*256+15    ;address of file name
  79.  
  80. ; ASCII definitions
  81.  
  82. CTRLC    EQU    'C'-'@'        ;..control-C..
  83. CTRLD    EQU    'D'-'@'
  84. CTRLE    EQU    'E'-'@'
  85. CTRLR    EQU    'R'-'@'
  86. CTRLS    EQU    'S'-'@'        ;..XOFF..
  87. CTRLX    EQU    'X'-'@'
  88. BS    EQU    08H        ;..backspace..
  89. TAB    EQU    09H        ;..tab..
  90. LF    EQU    0AH        ;..linefeed..
  91. CR    EQU    0DH        ;..carriage return..
  92. CAN    EQU    18H        ;..cancel..
  93. EOFCHAR    EQU    1AH        ;..end-of-file..
  94. CTRLZ    EQU    1AH        ;..clear screen..
  95. ESC    EQU    1BH        ;..and escape character.
  96.  
  97. ;
  98. ; MACROS TO PROVIDE Z80 EXTENSIONS
  99. ;   MACROS INCLUDE:
  100. ;
  101. $-MACRO         ;FIRST TURN OFF THE EXPANSIONS
  102. ;
  103. ;    JR    - JUMP RELATIVE
  104. ;    JRC    - JUMP RELATIVE IF CARRY
  105. ;    JRNC    - JUMP RELATIVE IF NO CARRY
  106. ;    JRZ    - JUMP RELATIVE IF ZERO
  107. ;    JRNZ    - JUMP RELATIVE IF NO ZERO
  108. ;    DJNZ    - DECREMENT B AND JUMP RELATIVE IF NO ZERO
  109. ;
  110. ;
  111. ;
  112. ;    @GENDD MACRO USED FOR CHECKING AND GENERATING
  113. ;    8-BIT JUMP RELATIVE DISPLACEMENTS
  114. ;
  115. @GENDD    MACRO    ?DD    ;;USED FOR CHECKING RANGE OF 8-BIT DISPLACEMENTS
  116.     IF (?DD GT 7FH) AND (?DD LT 0FF80H)
  117.     DB    100H    ;Displacement Range Error on Jump Relative
  118.     ELSE
  119.     DB    ?DD
  120.     ENDIF
  121.     ENDM
  122. ;
  123. ;
  124. ; Z80 MACRO EXTENSIONS
  125. ;
  126. JR    MACRO    ?N    ;;JUMP RELATIVE
  127.      IF    Z80
  128.     DB    18H
  129.     @GENDD    ?N-$-1
  130.      ELSE
  131.     JMP    ?N
  132.      ENDIF
  133.     ENDM
  134. ;
  135. JRC    MACRO    ?N    ;;JUMP RELATIVE ON CARRY
  136.      IF    Z80
  137.     DB    38H
  138.     @GENDD    ?N-$-1
  139.      ELSE
  140.     JC    ?N
  141.      ENDIF
  142.     ENDM
  143. ;
  144. JRNC    MACRO    ?N    ;;JUMP RELATIVE ON NO CARRY
  145.      IF    Z80
  146.     DB    30H
  147.     @GENDD    ?N-$-1
  148.      ELSE
  149.     JNC    ?N
  150.      ENDIF
  151.     ENDM
  152. ;
  153. JRZ    MACRO    ?N    ;;JUMP RELATIVE ON ZERO
  154.      IF    Z80
  155.     DB    28H
  156.     @GENDD    ?N-$-1
  157.      ELSE
  158.     JZ    ?N
  159.      ENDIF
  160.     ENDM
  161. ;
  162. JRNZ    MACRO    ?N    ;;JUMP RELATIVE ON NO ZERO
  163.      IF    Z80
  164.     DB    20H
  165.     @GENDD    ?N-$-1
  166.      ELSE
  167.     JNZ    ?N
  168.      ENDIF
  169.     ENDM
  170. ;
  171. DJNZ    MACRO    ?N    ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
  172.      IF    Z80
  173.     DB    10H
  174.     @GENDD    ?N-$-1
  175.      ELSE
  176.     DCR    B
  177.     JNZ    ?N
  178.      ENDIF
  179.     ENDM
  180. ;
  181. ; END OF Z80 MACRO EXTENSIONS
  182. ;
  183.  
  184. ; assembly origin (load address) and program beginning
  185.  
  186.     ORG    CPM$BASE+TPA
  187. SOURCE:
  188.     JMP    FILER
  189.  
  190.  
  191. ;
  192. ;    ZCPR2 and its utilities, including this one, are released
  193. ; to the public domain.  Anyone who wishes to USE them may do so with
  194. ; no strings attached.  The author assumes no responsibility or
  195. ; liability for the use of ZCPR2 and its utilities.
  196. ;
  197.  
  198. ;
  199. ;******************************************************************
  200. ;
  201. ;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
  202. ;
  203. ;    This data block precisely defines the data format for
  204. ; initial features of a ZCPR2 system which are required for proper
  205. ; initialization of the ZCPR2-Specific Routines in SYSLIB.
  206. ;
  207.  
  208. ;
  209. ;  EXTERNAL PATH DATA
  210. ;
  211. EPAVAIL:
  212.     DB    0FFH    ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
  213. EPADR:
  214.     DW    40H    ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
  215.  
  216. ;
  217. ;  INTERNAL PATH DATA
  218. ;
  219. INTPATH:
  220.     DB    0,0    ; DISK, USER FOR FIRST PATH ELEMENT
  221.             ; DISK = 1 FOR A, '$' FOR CURRENT
  222.             ; USER = NUMBER, '$' FOR CURRENT
  223.     DB    0,0
  224.     DB    0,0
  225.     DB    0,0
  226.     DB    0,0
  227.     DB    0,0
  228.     DB    0,0
  229.     DB    0,0    ; DISK, USER FOR 8TH PATH ELEMENT
  230.     DB    0    ; END OF PATH
  231.  
  232. ;
  233. ;  MULTIPLE COMMAND LINE BUFFER DATA
  234. ;
  235. MCAVAIL:
  236.     DB    0FFH    ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
  237. MCADR:
  238.     DW    0FF00H    ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
  239.  
  240. ;
  241. ;  DISK/USER LIMITS
  242. ;
  243. MDISK:
  244.     DB    4    ; MAXIMUM NUMBER OF DISKS
  245. MUSER:
  246.     DB    31    ; MAXIMUM USER NUMBER
  247.  
  248. ;
  249. ;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
  250. ;
  251. DOK:
  252.     DB    0FFH    ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
  253. UOK:
  254.     DB    0FFH    ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
  255.  
  256. ;
  257. ;  PRIVILEGED USER DATA
  258. ;
  259. PUSER:
  260.     DB    10    ; BEGINNING OF PRIVILEGED USER AREAS
  261. PPASS:
  262.     DB    'chdir',0    ; PASSWORD FOR MOVING INTO PRIV USER AREAS
  263.     DS    41-($-PPASS)    ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
  264.  
  265. ;
  266. ;  CURRENT USER/DISK INDICATOR
  267. ;
  268. CINDIC:
  269.     DB    '$'    ; USUAL VALUE (FOR PATH EXPRESSIONS)
  270.  
  271. ;
  272. ;  DMA ADDRESS FOR DISK TRANSFERS
  273. ;
  274. DMADR:
  275.     DW    80H    ; TBUFF AREA
  276.  
  277. ;
  278. ;  NAMED DIRECTORY INFORMATION
  279. ;
  280. NDRADR:
  281.     DW    00000H    ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
  282. NDNAMES:
  283.     DB    64    ; MAX NUMBER OF DIRECTORY NAMES
  284. DNFILE:
  285.     DB    'NAMES   '    ; NAME OF DISK NAME FILE
  286.     DB    'DIR'        ; TYPE OF DISK NAME FILE
  287.  
  288. ;
  289. ;  REQUIREMENTS FLAGS
  290. ;
  291. EPREQD:
  292.     DB    0FFH    ; EXTERNAL PATH?
  293. MCREQD:
  294.     DB    0FFH    ; MULTIPLE COMMAND LINE?
  295. MXREQD:
  296.     DB    0FFH    ; MAX USER/DISK?
  297. UDREQD:
  298.     DB    0FFH    ; ALLOW USER/DISK CHANGE?
  299. PUREQD:
  300.     DB    000H    ; PRIVILEGED USER?
  301. CDREQD:
  302.     DB    0FFH    ; CURRENT INDIC AND DMA?
  303. NDREQD:
  304.     DB    0FFH    ; NAMED DIRECTORIES?
  305. Z2CLASS:
  306.     DB    11    ; CLASS 11
  307.     DB    'ZCPR2'
  308.     DS    10    ; RESERVED
  309.  
  310. ;
  311. ;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
  312. ;
  313. ;******************************************************************
  314. ;
  315.  
  316. ;
  317. ;  **** Special Initial Value Area for GENINS
  318. ;
  319. LWIDTH:
  320.     DB    132    ; WIDTH OF LINE
  321. LTPP:
  322.     DB    44    ; LINES OF TEXT PER PAGE
  323. LSPP:
  324.     DB    5    ; LINES TO SKIP PER PAGE
  325. CWIDTH:
  326.     DB    80    ; WIDTH OF SCREEN
  327. CTPP:
  328.     DB    22    ; LINES OF TEXT PER SCREEN
  329. CSPP:
  330.     DB    1    ; LINES TO SKIP PER SCREEN
  331.  
  332. ; concealed copyright notice
  333.  
  334. ;    DB    ' DISK7 Copyright (c) 1983 by Frank Gaude'''
  335. ;    DB    ' All Rights Reserved'
  336.  
  337. ;
  338. ;  Screen Routines
  339. ;
  340.     org    200h        ; base page for screen routines
  341. CLS:
  342.     JMP    CLS950
  343. GOTOXY:
  344.     JMP    GOTO950
  345. EREOL:
  346.     JMP    EREOL950
  347.  
  348. CURTABLE:
  349.     DB    USER$UP,USER$DOWN,USER$RIGHT,USER$LEFT    ; up, down, right, left
  350.     DB    SCR$FOR,SCR$BACK            ; screen forward, back
  351.  
  352. ; screen routines (for TVI 950)
  353.  
  354. ;  clear screen
  355. CLS950:
  356.     MVI    A,CTRLZ        ;clear screen
  357.     JMP    TYPE
  358.  
  359. ;  position cursor (H=row, L=col) where 1,1=upper left
  360. GOTO950:
  361.     MVI    A,ESC        ;ESCape
  362.     CALL    TYPE
  363.     MVI    A,'='
  364.     CALL    TYPE
  365.     MOV    A,H        ;row
  366.     ADI    ' '
  367.     CALL    TYPE
  368.     MOV    A,L        ;column
  369.     ADI    ' '
  370.     JMP    TYPE
  371.  
  372. ;  erase to end of line
  373. EREOL950:
  374.     MVI    A,ESC        ;ESCape
  375.     CALL    TYPE
  376.     MVI    A,'T'
  377.     JMP    TYPE
  378.  
  379. ; start of program
  380.  
  381.     org    300h        ;page address
  382.     JMP    TYPE        ;I/O support for package
  383.  
  384. FILER:
  385.      IF    NOT WARMBOOT
  386.     LXI    H,0        ;clear hl-pair then..
  387.     DAD    SP        ;..add cp/m's stack address.
  388.     SHLD    STACK
  389.      ENDIF            ;not warmboot
  390.  
  391.     LXI    SP,STACK    ;start local stack
  392.     LXI    H,CURTABLE    ;init cursor commands
  393.     LXI    D,CTABLE    ;pt to area
  394.     MVI    B,6        ;6 commands
  395. CURINIT:
  396.     MOV    A,M        ;get command
  397.     STAX    D        ;put it
  398.     INX    H        ;pt to next
  399.     INX    D
  400.     INX    D
  401.     INX    D
  402.     DJNZ    CURINIT
  403.     CALL    IDU        ;set initial disk/user
  404.     LDA    NDNAMES        ;size of disk-based named directory
  405.     LXI    H,0
  406.     MOV    E,A        ;... in DE
  407.     MVI    D,0
  408.     DAD    D        ;*1
  409.     DAD    H        ;*2
  410.     DAD    H        ;*4
  411.     DAD    D        ;*5
  412.     DAD    H        ;*10
  413.     INR    H        ;next page
  414.     MVI    L,0
  415.     LXI    D,BUFENTRY    ;base address
  416.     DAD    D
  417.     SHLD    RING        ;beginning of ring
  418.     XCHG            ;HL pts to BUFENTRY
  419.     CALL    ZDNAME        ;scan for and load NAMES.DIR
  420.     JRZ    FILERPASS
  421.     MOV    A,C        ;set count
  422.     STA    BUFENTRY-1
  423. FILERPASS:
  424.     LDA    MDISK        ;get max disk number
  425.     ADI    'A'-1
  426.     STA    MAXDR        ;set letter
  427.     LDA    FCB+1        ;check for initial help
  428.     CPI    '/'
  429.     JRZ    FILERH
  430.     LDA    FCB2+1        ;check for wait
  431.     CPI    'W'
  432.     JRNZ    FILER0
  433. FILERSAK:
  434.     CALL    ILPRT
  435.     DB    CR,LF,'Strike Any Key to Enter VFILER -- ',0
  436.     CALL    DKEYIN
  437.     JR    FILER0
  438. FILERH:
  439.     CALL    HELPMSG        ;print help message
  440.     JR    FILERSAK
  441. FILER0:
  442.     CALL    HELPCHK        ;check for availability of HELP Files
  443.     JMP    EMBARK
  444.  
  445. ;  set initial disk/user
  446. IDU:
  447.     LXI    H,FCB+1        ;check for DU specification
  448.     MOV    A,M
  449.     CPI    ' '        ;<SP>=none
  450.     JRZ    IDU1
  451.     CALL    DEF$DU0        ;extrace drive/user
  452.     MOV    A,C        ;get current user
  453.     CALL    IDU$USET    ;set it
  454.     MOV    A,B        ;get current disk
  455.     CALL    IDU$DSET    ;set it
  456.     JMP    LOG1Z        ;log it in
  457. IDU1:
  458.     MVI    E,GET        ;determine..
  459.     CALL    GET$USR        ;..user area then..
  460.     CALL    IDU$USET    ;set current user
  461.     MVI    C,INQDISK    ;determine current disk
  462.     CALL    BDOS
  463.     CALL    IDU$DSET    ;set current disk
  464.     JMP    LOG1Z        ;set current user and disk
  465. IDU$USET:
  466.     STA    C$U$A        ;..store as current and..
  467.     STA    O$USR        ;..as original for exit.
  468.     STA    R$U$A        ;..requested user area
  469.     RET
  470. IDU$DSET:
  471.     STA    C$DR
  472.     STA    R$DR        ;requested disk
  473.     RET
  474.  
  475. ; check for availability of HELP Files (HELP.COM and FILER.HLP)
  476.  
  477. HELPCHK:
  478.     XRA    A        ;assume NO
  479.     STA    HELPFLG        ;set flag
  480.     LXI    D,HELPFCB
  481.     CALL    FILECHK        ;check for file
  482.     ORA    A        ;0=no
  483.     RZ
  484.     MVI    A,0FFH        ;set flag
  485.     STA    HELPFLG
  486.     RET
  487.  
  488. ; check for existance of file whose first 12 FCB bytes are pted to by DE
  489. ;   return with A=0 if not found, A=0FFH if found
  490.  
  491. FILECHK:
  492.     LXI    H,S$FCB        ;copy into FCB
  493.     XCHG
  494.     MVI    B,12        ;12 bytes
  495.     CALL    MOVE        ;copied into S$FCB
  496.     XCHG            ;HL pts to FCB
  497.     CALL    INITFCB        ;init FCB
  498.     LXI    D,S$FCB        ;pt to FCB
  499.     JMP    FFIND
  500.  
  501. ; determine if specific file(s) requested -- show remaining storage
  502.  
  503. EMBARK:
  504.     CALL    FRESTOR        ;get bytes remaining on drive (decode default)
  505.     LXI    H,JOKER        ;..treat as '*.*' with 'joker'..
  506.     LXI    D,FCB+1        ;..loaded here.
  507.     MVI    B,11        ; # of characters to move
  508.     CALL    MOVE        ;set field to *.*
  509.  
  510. ; build 'ring' with filename positioned in default 'fcb' area
  511.  
  512. PLUNGE:
  513.     MVI    C,SETDMA    ;initialize dma address..
  514.     LXI    D,TBUF        ;..to default buffer.
  515.     CALL    BDOS
  516.     XRA    A        ;clear search 'fcb'..
  517.     STA    FCBEXT        ;extent byte..
  518.     STA    FCBRNO        ;..and record number.
  519.     CMA
  520.     STA    CANFLG        ;make cancel flag true
  521.     LXI    D,FCB        ;default 'fcb' for search..
  522.     MVI    C,SRCHF        ;..of first occurrence.
  523.     CALL    BDOS
  524.     INR    A        ; 0ffh --> 00h if no file found
  525.     JNZ    SETRING        ;if found, branch and build ring.
  526.     STA    CANFLG        ;make log-cancel toggle false
  527.     CALL    ERMSG        ;else say none found, fall thru to log.
  528.     DB    'No File Found',0
  529.  
  530. ; l o g
  531.  
  532. ; select drive and user area (system reset for disk change on-the-fly)
  533.  
  534. LOG:
  535.     CALL    CPRMPT        ;prompt to get drive/user selection
  536.     DB    'Login DIR: ',0
  537.     CALL    DEF$D$U
  538. LOG1:
  539.     CALL    LOG1Z        ;set current and log in
  540.     CALL    CRLF        ;new line
  541.     JMP    EMBARK        ;..restart
  542.  
  543. ;  set current user and disk
  544.  
  545. LOG1X:
  546.     LXI    H,LOG$DU$MSG
  547.     LDA    R$DR        ;set prompt message
  548.     ADI    'A'        ;adjust to letter
  549.     MOV    M,A
  550.     INX    H
  551.     MVI    M,' '        ;prep for user < 10
  552.     LDA    R$U$A        ;get user
  553.     CPI    10        ;less than 10?
  554.     JRC    LOG2
  555.     MVI    B,'1'        ;set digits
  556. LOG1A:
  557.     SUI    10        ;adjust user
  558.     CPI    10        ;less?
  559.     JRC    LOG1B
  560.     INR    B        ;incr 10's
  561.     JR    LOG1A
  562. LOG1B:
  563.     MOV    M,B        ;set 10's
  564. LOG2:
  565.     INX    H        ;pt to 1's
  566.     ADI    '0'        ;to ASCII
  567.     MOV    M,A
  568.     RET
  569.  
  570. ;  actually log into DU requested
  571.  
  572. LOG1Y:
  573.     LDA    R$U$A        ;establish requested area..
  574.     STA    C$U$A        ;..as current area.
  575.     CALL    SET$USR
  576.     CALL    RESET        ;reset disk system, make requested current.
  577.     LXI    H,0        ;initialize tagged..
  578.     SHLD    TAG$TOT        ;..file size accumulator.
  579.     RET
  580.  
  581. ;  set current DU and log into it
  582.  
  583. LOG1Z:
  584.     CALL    LOG1X        ;set current
  585.     CALL    LOG1Y        ;actually log in
  586.     RET
  587.  
  588. ; routine to define current drive and user area with full error trapping.
  589. ; (check validity of user area entry first, then drive validity, then proceed
  590. ; with implementation.)
  591.  
  592. DEF$D$U:
  593.     LXI    H,CMDBUF+2
  594.     MVI    B,20        ; # of blanks to..
  595.     CALL    FILL        ;..clear 'cmdbuf'.
  596.     LXI    D,CMDBUF    ;get DU selection from..
  597.     MVI    C,RDBUF        ;..console buffer read.
  598.     CALL    BDOS
  599.     CALL    CONVERT        ;make sure alpha is upper case
  600.     LXI    H,CMDBUF+2    ;pt to possible drive
  601. DEF$DU0:
  602.     CALL    ZDNFIND        ;look for DU or DIR form and return DU
  603.     JRZ    ERRET        ;error
  604.     MOV    A,B        ;return disk and user
  605.     STA    R$DR
  606.     INR    A        ;set FCB
  607.     STA    FCB
  608.     MOV    A,C
  609.     STA    R$U$A
  610.     RET
  611.  
  612. ; error return and recovery from command cancellation
  613.  
  614. ERRET:
  615.     CALL    ERMSG
  616.     DB    'DIR Entry Error',0
  617.     JMP    NEUTRAL
  618. COMCAN:
  619.     LXI    SP,STACK    ;reset stack..
  620.     LDA    CANFLG
  621.     ORA    A        ;..from..
  622.     JZ    PLUNGE
  623.     CALL    REFRESH        ;refresh screen
  624.     JMP    LOOPFN        ;..error/command abort.
  625.  
  626. ; find file along path (file FCB pted to by DE)
  627. ;   on return, A=0FFH if found, A=0 if not found, and flags set
  628.  
  629. FFIND:
  630.     PUSH    D        ;save ptr to FCB
  631.     MVI    E,GET        ;get and save current DU
  632.     CALL    GET$USR
  633.     STA    C$U$A
  634.     STA    Z$U$A
  635.     MVI    C,INQDISK
  636.     CALL    BDOS
  637.     STA    C$DR
  638.     STA    Z$DR
  639.     POP    D        ;get ptr to FCB
  640.     CALL    GETPATH        ;HL pts to current path
  641. FFINDL:
  642.     CALL    SEARF        ;look for file
  643.     JRNZ    FFOUND        ;found file
  644.     LDA    CINDIC        ;get current indictor
  645.     MOV    C,A        ;... in C
  646.     MOV    A,M        ;get drive
  647.     ORA    A        ;0=done=not found
  648.     JRZ    FNFOUND
  649.     CMP    C        ;current disk?
  650.     JRNZ    FF1
  651.     LDA    C$DR        ;get current disk
  652.     INR    A        ;increment for following DCR
  653. FF1:
  654.     DCR    A        ;adjust to 0 for A
  655.     MOV    B,A        ;disk in B
  656.     STA    Z$DR        ;note disk
  657.     INX    H        ;pt to user
  658.     MOV    A,M        ;user in A
  659.     CMP    C        ;current?
  660.     JRNZ    FF2
  661.     LDA    C$U$A        ;get current user
  662. FF2:
  663.     MOV    C,A        ;user in C
  664.     STA    Z$U$A        ;note user
  665.     INX    H        ;pt to next entry
  666.     CALL    SLOGIN        ;log in DU
  667.     JR    FFINDL
  668. FFOUND:
  669.     CALL    DLOGIN        ;log in default
  670.     MVI    A,0FFH        ;set flag
  671.     ORA    A
  672.     RET
  673. FNFOUND:
  674.     CALL    DLOGIN        ;log in default
  675.     XRA    A        ;set flag
  676.     RET
  677. ; get starting address of path in HL
  678. GETPATH:
  679.     LDA    EPAVAIL        ;external path available?
  680.     ORA    A
  681.     JRZ    GPINT
  682.     LHLD    EPADR        ;get address of external path
  683.     RET
  684. GPINT:
  685.     LXI    H,INTPATH    ;internal path
  686.     RET
  687. ; search for file pted to by DE; don't affect DE or HL; ret code in A
  688. SEARF:
  689.     PUSH    H        ;save regs
  690.     PUSH    D
  691.     MVI    C,SRCHF        ;search for file
  692.     CALL    BDOS
  693.     INR    A        ;set flags
  694.     POP    D        ;get regs
  695.     POP    H
  696.     RET
  697. ; log in default directory
  698. DLOGIN:
  699.     LDA    C$DR        ;disk in B
  700.     MOV    B,A
  701.     LDA    C$U$A        ;user in C
  702.     MOV    C,A        ;fall thru to SLOGIN
  703. ; log in DU in BC
  704. SLOGIN:
  705.     PUSH    H        ;save regs
  706.     PUSH    D
  707.     PUSH    B
  708.     MOV    A,C        ;set user
  709.     CALL    SET$USR
  710.     POP    B
  711.     MOV    A,B        ;set disk
  712.     CALL    SET$DR
  713.     POP    D        ;restore regs
  714.     POP    H
  715.     RET
  716.  
  717. ; e x i t
  718.  
  719. ; return to cp/m ccp
  720.  
  721. CPM$CCP:
  722.     LDA    O$USR        ;get and set original..
  723.     CALL    SET$USR        ;..user area and..
  724.     LXI    D,TBUF        ;..tidy up..
  725.     MVI    C,SETDMA    ;..before going home.
  726.     CALL    BDOS
  727.     CALL    CLS
  728.  
  729.      IF WARMBOOT
  730.     JMP    CPM$BASE
  731.      ENDIF            ;warmboot
  732.  
  733.      IF    NOT WARMBOOT
  734.     LHLD    STACK        ;put cp/m's pointer..
  735.     SPHL            ;..back to 'sp'.
  736.     RET            ;return to cp/m ccp
  737.      ENDIF            ;not warmboot
  738.  
  739. ; establish ring (circular list) of filenames
  740.  
  741. SETRING:
  742.     LHLD    RING        ;initialize ring pointer
  743.     SHLD    RINGPOS        ;start --> current position of ring
  744.  
  745. ; put each found name in ring.  a-reg --> offset into 'tbuf' name storage
  746.  
  747. TO$RING:
  748.     DCR    A        ;un-do 'inr' from above and below
  749.     ADD    A        ;times 32 --> position index
  750.      ADD    A
  751.     ADD    A
  752.     ADD    A
  753.     ADD    A
  754.     ADI    TBUF        ;add page offset and..
  755.     MOV    L,A        ;..put address into..
  756.     MVI    H,0        ;..hl-pair.
  757.     LDA    FCB        ;get drive/user designator and..
  758.     MOV    M,A        ;..put into 'fcb' buffer.
  759.     XCHG
  760.     LHLD    RINGPOS        ;pointer to current load point in ring
  761.     XCHG
  762.     MVI    B,12        ;move drive designator and name to ring
  763.     CALL    MOVE
  764.     XCHG            ;de-pair contains next load point address
  765.     MVI    M,' '        ;space for potential..
  766.     INX    H        ;..tagging of files for mass copy.
  767.     SHLD    RINGPOS        ;store and search..
  768.     MVI    C,SRCHN        ;..for next occurrence.
  769.     LXI    D,FCB        ;filename address field
  770.     CALL    BDOS
  771.     INR    A        ;if all done, 0ffh --> 00h.
  772.     JRNZ    TO$RING        ;if not, put next name into ring.
  773.  
  774. ; all filenames in ring -- setup ring size and copy-buffer start point
  775.  
  776.     LHLD    RINGPOS        ;next load point of ring is start of buffer
  777.     SHLD    RINGEND        ;set ring end..
  778.     SHLD    BUFSTART    ;..and copy-buffer start.
  779.     PUSH    H
  780.     LHLD    RING
  781.     LXI    D,13        ;compare 'ringend' (tab base+13)
  782.     DAD    D
  783.     XCHG
  784.     POP    H
  785.     CALL    CMPDEHL
  786.     JZ    CMDLOOP        ;go to command loop, if no sort.
  787.  
  788. ; sort ring of filenames
  789.  
  790. SORT:
  791.     LHLD    RING        ;initialize 'i' sort variable and..
  792.     SHLD    RINGI
  793.     LXI    D,13        ;..also 'j' variable.
  794.     DAD    D
  795.     SHLD    RINGJ
  796. SORTLP:
  797.     LHLD    RINGJ        ;compare names 'i & j'
  798.     XCHG
  799.     LHLD    RINGI
  800.     PUSH    H        ;save position pointers..
  801.     PUSH    D        ;..for potential swap.
  802.     MVI    B,13        ; # of characters to compare
  803.  
  804. ; left to right compare of two strings (de-pair points to 'a' string;
  805. ; hl-pair, to 'b'; b-reg contains string length.)
  806.  
  807. CMPSTR:
  808.     LDAX    D        ;get an 'a' string character and..
  809.     CMP    M        ;..check against 'b' string character.
  810.     JRNZ    NOCMP        ;if not equal, set flag.
  811.     INX    H        ;bump compare..
  812.     INX    D        ;..pointers and..
  813.     DCR    B        ; (if compare, set as equal.)
  814.     JRNZ    CMPSTR        ;..do next character.
  815. NOCMP:
  816.     POP    D
  817.     POP    H
  818.     MVI    B,13
  819.     JRNC    NOSWAP
  820.  
  821. ; swap if 'j' string larger than 'i'
  822.  
  823. SWAP:
  824.     MOV    C,M        ;get character from one string..
  825.     LDAX    D        ;..and one from other string.
  826.     MOV    M,A        ;second into first
  827.     MOV    A,C        ;first into second
  828.     STAX    D
  829.     INX    H        ;bump swap pointers
  830.     INX    D
  831.     DJNZ    SWAP
  832. NOSWAP:
  833.     LHLD    RINGJ        ;increment 'j' pointer
  834.     LXI    D,13
  835.     DAD    D
  836.     SHLD    RINGJ
  837.     XCHG            ;see if end of 'j' loop
  838.     LHLD    RINGEND
  839.     CALL    CMPDEHL
  840.     JNZ    SORTLP        ;no, so more 'j' looping.
  841.     LHLD    RINGI        ;bump 'i' pointer
  842.     LXI    D,13
  843.     DAD    D
  844.     SHLD    RINGI
  845.     DAD    D        ;set start over 'j' pointer
  846.     SHLD    RINGJ
  847.     XCHG            ;see if end of 'i' loop
  848.     LHLD    RINGEND
  849.     CALL    CMPDEHL
  850.     JNZ    SORTLP        ;must be more 'i' loop to do
  851.  
  852. ; sort done -- initialize tables for fast crc calculations
  853.  
  854.     CALL    INITCRC
  855.  
  856. ; calculate buffer maximum available record capacity
  857.  
  858. B$SIZE:
  859.     LXI    B,0        ;count records
  860.     LHLD    BDOS+1        ;get 'bdos' entry (fbase)
  861.  
  862.      IF    NOT WARMBOOT
  863.     LXI    D,-(CCP)
  864.     DAD    D
  865.      ENDIF            ;not warmboot
  866.  
  867.     DCX    H
  868.     XCHG            ;de-pair --> highest address of buffer
  869.     LHLD    BUFSTART    ;start address of buffer (end of ring list)
  870. B$SIZE2:
  871.     INX    B        ;increase record count by one
  872.     PUSH    D
  873.     LXI    D,128        ; 128-byte record
  874.     DAD    D        ;buffer address + record size
  875.     POP    D
  876.     CALL    CMPDEHL        ;compare for all done
  877.     JRNC    B$SIZE2        ;more will fit?
  878.     DCX    B        ;set maximum record count less one
  879.     MOV    A,B        ;memory available for copy?
  880.     ORA    C
  881.     JRNZ    B$SIZE3        ;yes, buffer memory space available.
  882.     CALL    ERMSG
  883.     DB    'No Memory for Copy Buffer',0
  884.     JMP    NEUTRAL
  885.  
  886. B$SIZE3:
  887.     MOV    L,C        ;store..
  888.     MOV    H,B        ;..maximum..
  889.     SHLD    REC$MAX        ;..record count.
  890.     JMP    CMDLOOP
  891.  
  892. ; buffer size suitable -- process file/display loop
  893.  
  894. LOOPFN:
  895.     LXI    H,FNADR        ;position cursor for file name print
  896.     CALL    GOTOXY
  897.     LHLD    RINGPOS        ;pt to current file name
  898.     INX    H        ;pt to first char
  899.     CALL    PRFN        ;print file name
  900. LOOP:
  901.     CALL    ATCMD        ;position at command prompt
  902.     CALL    DKEYIN        ;wait for character from keyboard
  903.     PUSH    PSW        ;save command
  904.     LDA    ERMFLG        ;error message?
  905.     ORA    A        ;0=no
  906.     JRZ    CPROC
  907.     CALL    ERCLR        ;erase old error message
  908. CPROC:
  909.     POP    PSW        ;get command
  910.     CALL    CTPROC        ;process command or return if not found
  911.     CALL    ERMSG
  912.     DB    'Invalid Command: ',0
  913.     MOV    A,B        ;get char
  914.     CPI    ' '        ;expand if less than space
  915.     JRNC    CPROC1
  916.     MVI    A,'^'        ;control
  917.     CALL    TYPE
  918.     MOV    A,B        ;get byte
  919.     ADI    '@'        ;convert to letter
  920. CPROC1:
  921.     CALL    TYPE
  922. NEUTRAL:
  923.     JMP    LOOP        ;..position.
  924.  
  925. ; process command from table
  926.  
  927. CTPROC:
  928.     LXI    H,CTABLE    ;pt to table
  929.     MOV    B,A        ;command in B
  930. CTPR1:
  931.     MOV    A,M        ;get table command char
  932.     ORA    A        ;end of table?
  933.     RZ            ;done if so
  934.     CMP    B        ;match?
  935.     JRZ    CTPR2
  936.     INX    H        ;skip to next entry
  937.     INX    H
  938.     INX    H
  939.     JR    CTPR1
  940. CTPR2:
  941.     INX    H        ;pt to address
  942.     MOV    A,M        ;get low
  943.     INX    H
  944.     MOV    H,M        ;get high
  945.     MOV    L,A
  946.     XTHL            ;address on stack
  947.     RET            ;"jump" to routine
  948.  
  949. ; Command Table
  950. CTABLE:
  951.     DB    0        ;user cursor positioning
  952.     DW    UP
  953.     DB    0
  954.     DW    DOWN
  955.     DB    0
  956.     DW    FORWARD
  957.     DB    0
  958.     DW    REVERSE
  959.     DB    0        ;user screen jumps
  960.     DW    JUMPF
  961.     DB    0
  962.     DW    JUMPB
  963.     DB    CTRLE        ;system cursor positioning
  964.     DW    UP
  965.     DB    CTRLX
  966.     DW    DOWN
  967.     DB    CTRLD
  968.     DW    FORWARD
  969.     DB    CTRLS
  970.     DW    REVERSE
  971.     DB    '+'        ;jump forward
  972.     DW    JUMPF
  973.     DB    '-'        ;jump backward
  974.     DW    JUMPB
  975.     DB    ' '        ;go forward
  976.     DW    FORWARD
  977.     DB    BS        ;back up?
  978.     DW    REVERSE
  979.     DB    'B'        ;back up?
  980.     DW    REVERSE
  981.     DB    'C'        ;copy a file?
  982.     DW    COPY
  983.     DB    'D'        ;delete a file?
  984.     DW    DELETE
  985.     DB    'F'        ;show file size?
  986.     DW    FIL$SIZ
  987.     DB    'G'        ;goto a file?
  988.     DW    GOTO
  989.     DB    'H'        ;external help?
  990.     DW    EXTHELP
  991.     DB    'L'        ;log-in another drive?
  992.     DW    LOG
  993.     DB    'M'        ;tagged multiple file copy?
  994.     DW    MASS$COPY
  995.     DB    'N'        ;go forward
  996.     DW    FORWARD
  997.     DB    'P'        ;output file to 'list' device?
  998.     DW    LSTFILE
  999.     DB    'Q'
  1000.     DW    SCREFRESH
  1001.     DB    'R'        ;if rename, get to work.
  1002.     DW    RENAME
  1003.     DB    'S'        ;free bytes on..
  1004.     DW    R$DR$ST        ;..requested drive?
  1005.     DB    'T'        ;if tag, put '*' in..
  1006.     DW    TAG$EM        ;..front of cursor.
  1007.     DB    'U'        ;remove '*' from..
  1008.     DW    UNTAG        ;..in front of cursor?
  1009.     DB    'W'        ;mass tag/untag?
  1010.     DW    MASS$TU
  1011.     DB    'V'        ; 'view' file at console?
  1012.     DW    VIEW
  1013.     DB    'X'        ;if exit, then to cp/m ccp.
  1014.     DW    CPM$CCP
  1015.     DB    'Y'        ;mass delete?
  1016.     DW    MASS$DEL
  1017.     DB    'Z'        ;run ZCPR2 command
  1018.     DW    RUNZCPR2
  1019.     DB    ESC        ; 'esc' exits to cp/m ccp also.
  1020.     DW    CPM$CCP
  1021.     DB    '?'        ;help
  1022.     DW    HELP
  1023.     DB    '/'        ;help also
  1024.     DW    HELP
  1025.     DB    0        ;end of table
  1026.  
  1027. ; h e l p  (menu)
  1028.  
  1029. HELPMSG:
  1030.     CALL    CLS
  1031.     CALL    ILPRT
  1032.     DB    '-- VFILER '
  1033.     DB    VERS/10+'0','.',VERS MOD 10+'0'
  1034.     DB    ':  ZCPR2 File Manipulation Program -- '
  1035.     DB    CR,LF,CR,LF
  1036.     DB    '-- Tagging Commands --    -- File Operations --',CR,LF
  1037.     DB    '    T - Tag File              C - Copy File',CR,LF
  1038.     DB    '    U - Untag File            D - Delete File',CR,LF
  1039.     DB    '    W - Mass Tag/Untag        F - File Size',CR,LF
  1040.     DB    '                              M - Mass Copy',CR,LF
  1041.     DB    '-- File Print & View --       R - Rename File',CR,LF
  1042.     DB    'P - Print      V - View       Y - Mass Delete',CR,LF
  1043.     DB    CR,LF
  1044.     DB    '-- Movement Commands --   -- Miscellaneous --',CR,LF
  1045.     DB    '    <SP> - File Forward       H - Detailed Help',CR,LF
  1046.     DB    '     N   - File Forward       L - Login DIR',CR,LF
  1047.     DB    '    <BS> - File Backward      Q - Refresh Screen',CR,LF
  1048.     DB    '     B   - File Backward      S - Status of Disk',CR,LF
  1049.     DB    '     G   - Go To a File       X - Exit',CR,LF
  1050.     DB    '     +   - Screen Forward     Z - Run ZCPR2 Command',CR,LF
  1051.     DB    '     -   - Screen Backward    / - This Summary',CR,LF
  1052.     DB    CR,LF
  1053.     DB    '                -- Screen Movement --',CR,LF
  1054.     DB    'File:    ^S - LEFT   ^D - RIGHT   ^E - UP   ^X - DOWN',CR,LF
  1055.     DB    'Screen:  ^A - LEFT   ^F - RIGHT',CR,LF
  1056.     DB    0
  1057.     CALL    BOTTOM
  1058.     RET
  1059. HELP:
  1060.     CALL    HELPMSG        ;print message
  1061.     CALL    REFRESH        ;refresh screen
  1062.     JMP    LOOPFN
  1063. EXTHELP:
  1064.     LDA    HELPFLG        ;check for further help
  1065.     ORA    A        ;0=no
  1066.     JRZ    EHLP1
  1067.     CALL    CLS
  1068.     CALL    ILPRT
  1069.     DB    'Chaining to External HELP ...',0
  1070.     LXI    H,MOREHELP    ;run HELP Command
  1071.     CALL    CHAIN        ;chain to it
  1072.     JMP    LOOPFN
  1073. EHLP1:
  1074.     CALL    ERMSG
  1075.     DB    'External HELP Facility Not Available',0
  1076.     JMP    LOOPFN
  1077.  
  1078. ; refresh screen
  1079.  
  1080. SCREFRESH:
  1081.     CALL    REFRESH        ;do it
  1082.     JMP    LOOPFN        ;reprint name
  1083.  
  1084. ; execute ZCPR2 command line
  1085.  
  1086. RUNZCPR2:
  1087.     CALL    ERMSG
  1088.     DB    'ZCPR2 Command Line? ',0
  1089.     LXI    H,CRCTBL+256    ;use last half of CRC Table
  1090.     MVI    M,126        ;store length of line
  1091.     INX    H
  1092.     MVI    M,0        ;store count
  1093.     LXI    D,CRCTBL+256
  1094.     PUSH    D
  1095.     MVI    C,RDBUF        ;Read Line from User
  1096.     CALL    BDOS
  1097.     POP    H
  1098.     INX    H        ;pt to char count
  1099.     MOV    E,M
  1100.     INX    H        ;pt to first char
  1101.     MVI    D,0        ;set no high-order offset
  1102.     PUSH    H        ;save current ptr for later
  1103.     DAD    D
  1104.     MVI    M,0        ;store ending zero
  1105.     POP    H        ;pt to first char of command line
  1106.     MOV    A,M        ;abort if no first char
  1107.     ORA    A
  1108.     JZ    NEUTRAL
  1109.     CALL    CHAIN        ;chain to it
  1110.     JMP    LOOPFN        ;continue
  1111.  
  1112. ; chain to command pted to by HL ending in zero
  1113.  
  1114. CHAIN:
  1115.     LDA    MCAVAIL        ;multiple commands available?
  1116.     ORA    A        ;Z=NO
  1117.     JRNZ    CHAIN1
  1118.     CALL    ERMSG
  1119.     DB    'Chaining Error -- No MCL',0
  1120.     RET
  1121. CHAIN1:
  1122.     PUSH    H
  1123.     LHLD    MCADR        ;pt to MCL
  1124.     XCHG
  1125.     LXI    H,4
  1126.     DAD    D
  1127.     XCHG
  1128.     MOV    C,M        ;save ptr to next command
  1129.     MOV    M,E        ;store address of first character
  1130.     INX    H
  1131.     MOV    B,M
  1132.     MOV    M,D
  1133.     PUSH    B        ;ptr to next command saved
  1134.     INX    H        ;get buffer size
  1135.     MOV    B,M        ;...in B
  1136.     XCHG            ;HL pts to first character
  1137.     POP    D        ;get ptr to rest of current command
  1138.     PUSH    H        ;save HL
  1139.     LXI    H,CRCTBL    ;save command in CRCTBL
  1140. CHAIN2:
  1141.     LDAX    D        ;copy rest of command line for later
  1142.     MOV    M,A
  1143.     INX    H
  1144.     INX    D
  1145.     ORA    A
  1146.     JRNZ    CHAIN2
  1147.     POP    H        ;get ptr to beginning of buffer
  1148.     POP    D        ;DE pts to new command
  1149. ;
  1150. ;  Copy Desired Command into MCL
  1151. ;
  1152.     CALL    CHAINC        ;copy into command line
  1153. ;
  1154. ;  Copy Command to Return to FILER into MCL
  1155. ;
  1156.     PUSH    H        ;save ptr to MCL
  1157.     PUSH    B        ;save B counter
  1158.     LDA    C$DR        ;get current disk
  1159.     ADI    'A'        ;convert disk to letter
  1160.     STA    FILE$D        ;store in proper place
  1161.     LDA    C$U$A        ;get current user
  1162.     LXI    H,FILE$U    ;store user number
  1163.     MVI    C,'0'        ;set char
  1164. CHAIN3:
  1165.     SUI    10        ;convert to ASCII
  1166.     JRC    CHAIN4
  1167.     INR    C        ;increment 10's char
  1168.     JR    CHAIN3
  1169. CHAIN4:
  1170.     MOV    M,C        ;store 10's digit char
  1171.     INX    H        ;pt to 1's digit
  1172.     ADI    10+'0'        ;add back for 1's digit
  1173.     MOV    M,A        ;store 1's digit char
  1174.     POP    B        ;restore B counter
  1175.     POP    H        ;restore ptr and continue
  1176.     LXI    D,FILERCMD    ;return to FILER
  1177.     CALL    CHAINC        ;copy rest
  1178. ;
  1179. ;  Copy Rest of Original Command Line into MCL
  1180. ;
  1181.     LXI    D,CRCTBL    ;pt to rest of original command line
  1182.     CALL    CHAINC        ;copy it in
  1183. ;
  1184. ;  Close MCL and Run New Command Line
  1185. ;
  1186.     MVI    M,0        ;store ending zero
  1187.     JMP    CPM$CCP
  1188. CHAINC:
  1189.     LDAX    D        ;copy into MCL
  1190.     ORA    A        ;done?
  1191.     RZ
  1192.     DCR    B        ;check for buffer overflow
  1193.     JRZ    CHAINERR
  1194.     MOV    M,A
  1195.     INX    D
  1196.     INX    H
  1197.     JR    CHAINC
  1198. CHAINERR:
  1199.     POP    D        ;clear stack
  1200.     CALL    ERMSG
  1201.     DB    'Chaining Error -- MCL Overflow',0
  1202.     LHLD    MCADR        ;clear command line
  1203.     LXI    D,4
  1204.     DAD    D
  1205.     MVI    M,0        ;no command left
  1206.     RET
  1207.  
  1208. ; mass tag or untag
  1209. MASS$TU:
  1210.     MVI    A,TRUE        ;update file totals
  1211.     STA    FS$FLG        ;of tagged/untagged files
  1212.     CALL    CPRMPT
  1213.     DB    'Mass Tag or Untag (T/U)? ',0
  1214.     CALL    KEYIN        ;get response
  1215.     CPI    'T'
  1216.     JRZ    MASS$TAG
  1217.     CPI    'U'
  1218.     JNZ    NEUTRAL        ;fall thru to MASS$UNTAG
  1219.  
  1220. ; mass   u n t a g
  1221.  
  1222. MASS$UNTAG:
  1223.     XRA    A        ;set tag/untag..
  1224.     STA    T$UN$FG        ;..flag to untag
  1225.     STA    FSDFLG        ;no file size display
  1226.     CALL    WORKMSG
  1227. MUTLOOP:
  1228.     LHLD    RINGPOS        ;move to tag
  1229.     LXI    D,12
  1230.     DAD    D
  1231.     MOV    A,M        ;get tag
  1232.     CPI    '*'        ;check for tag
  1233.     MVI    M,' '        ;clear tag
  1234.     CZ    FSIZ        ;adjust sizes
  1235.     LHLD    RINGPOS        ;advance to next
  1236.     LXI    D,13
  1237.     DAD    D
  1238.     SHLD    RINGPOS
  1239.     XCHG            ;done?
  1240.     LHLD    LOCEND
  1241.     CALL    CMPDEHL
  1242.     JRNZ    MUTLOOP
  1243.     LXI    H,CURHOME    ;reset cursor
  1244.     SHLD    CURAT
  1245.     LHLD    LOCBEG        ;set ring position
  1246.     JMP    JFW0
  1247.  
  1248. ; mass   t a g
  1249.  
  1250. MASS$TAG:
  1251.     XRA    A
  1252.     STA    FSDFLG        ;no file size display
  1253.     MVI    A,TRUE        ;set tag/untag..
  1254.     STA    T$UN$FG        ;..flag to untag
  1255.     CALL    WORKMSG
  1256. MTLOOP:
  1257.     LHLD    RINGPOS        ;move to tag
  1258.     LXI    D,12
  1259.     DAD    D
  1260.     MOV    A,M        ;get tag
  1261.     CPI    '*'        ;check for tag
  1262.     MVI    M,'*'        ;clear tag
  1263.     CNZ    FSIZ        ;adjust sizes
  1264.     LHLD    RINGPOS        ;advance to next
  1265.     LXI    D,13
  1266.     DAD    D
  1267.     SHLD    RINGPOS
  1268.     XCHG            ;done?
  1269.     LHLD    LOCEND
  1270.     CALL    CMPDEHL
  1271.     JRNZ    MTLOOP
  1272.     LXI    H,CURHOME    ;reset cursor
  1273.     SHLD    CURAT
  1274.     LHLD    LOCBEG        ;set ring position
  1275.     JMP    JFW0
  1276.  
  1277. ; u n t a g
  1278.  
  1279. UNTAG:
  1280.     XRA    A        ;set tag/untag..
  1281.     STA    T$UN$FG        ;..flag to untag.
  1282.     CMA
  1283.     STA    FS$FLG        ;set flag to compute file size
  1284.     LHLD    RINGPOS        ;move back one..
  1285.     LXI    D,12        ;..character position..
  1286.     DAD    D        ;..and check tagging status.
  1287.     MOV    A,M        ;if file previously tagged, remove..
  1288.     CPI    '*'        ;..size from..
  1289.     PUSH    PSW        ;save flag
  1290.     MVI    M,' '        ; (untag character, to next ring position.)
  1291.     CALL    REFFN        ;refresh file name
  1292.     POP    PSW        ;get flag
  1293.     JRZ    FS2        ;..summation.
  1294.     JMP    FORWARD
  1295.  
  1296. ; t a g
  1297.  
  1298. TAG$EM:
  1299.     MVI    A,TRUE        ;set..
  1300.     STA    T$UN$FG        ;..tag/untag and..
  1301.     STA    FS$FLG        ;..file size flags to tag.
  1302.     LHLD    RINGPOS
  1303.     LXI    D,12        ;move back one..
  1304.     DAD    D        ;..position..
  1305.     MOV    A,M        ; (if file
  1306.     CPI    '*'        ; already tagged, skip
  1307.     JZ    FORWARD        ; to next file.)
  1308.     MVI    M,'*'        ;..and store a '*' tag character.
  1309.     CALL    REFFN        ;refresh file name
  1310.     JR    FS2        ;get file size
  1311.  
  1312. ; refresh file name with new tag
  1313. REFFN:
  1314.     CALL    CLRCUR        ;clear cursor
  1315.     MVI    A,' '        ;one more space
  1316.     CALL    TYPE
  1317.     LHLD    RINGPOS        ;reprint file name
  1318.     INX    H
  1319.     CALL    PRFN
  1320.     MOV    A,M        ;print tag
  1321.     JMP    TYPE
  1322.  
  1323. ; f i l e   s i z e
  1324.  
  1325. ; determine and display file size in kilobytes -- round up to next disk
  1326. ; allocation block -- accumulate tagged file summation
  1327.  
  1328. FIL$SIZ:
  1329.     XRA    A        ;set file size/tagged..
  1330.     STA    FS$FLG        ;..file flag to file size.
  1331.     CMA
  1332.     STA    FSDFLG        ;display file size
  1333.     CALL    FSIZ        ;compute and print file size
  1334.     JMP    LOOPFN
  1335. FS2:
  1336.     MVI    A,TRUE
  1337.     STA    FSDFLG        ;display file size
  1338.     CALL    FSIZ        ;compute and print file size
  1339.     JMP    FORWARD
  1340.  
  1341. ;  print file size
  1342. FSIZ:
  1343.     LDA    FSDFLG        ;display file size?
  1344.     ORA    A        ;0=no
  1345.     CNZ    FSNOTE
  1346.     CALL    RINGFCB        ;move name to 's$fcb'
  1347.  
  1348. ; determine file record count and save in 'rcnt'
  1349.  
  1350.     MVI    C,COMPSZ
  1351.     LXI    D,S$FCB
  1352.     CALL    BDOS
  1353.     LHLD    S$FCB+33
  1354.     SHLD    RCNT        ;save record count and..
  1355.     LXI    H,0
  1356.     SHLD    S$FCB+33    ;..reset cp/m.
  1357.  
  1358. ; round up to next disk allocation block
  1359.  
  1360.     LDA    B$MASK        ;sectors/block - 1
  1361.     PUSH    PSW        ;save 'blm'
  1362.     MOV    L,A
  1363.     XCHG
  1364.     LHLD    RCNT        ;..use here.
  1365.     DAD    D        ;round up to next block
  1366.     MVI    B,3+1        ;convert from..
  1367.     CALL    SHIFTLP        ;..records to kilobytes.
  1368.     POP    PSW        ;retrieve 'blm'
  1369.     RRC            ;convert..
  1370.     RRC            ;..to..
  1371.     RRC            ;..kilobytes/block.
  1372.     ANI    1FH
  1373.     CMA            ;finish rounding
  1374.     ANA    L
  1375.     MOV    L,A        ;hl-pair contains # of kilobytes
  1376.     LDA    FS$FLG
  1377.     ORA    A
  1378.     JRZ    D$F$SIZ        ;branch if 'f' function
  1379.  
  1380. ; tagged file size summation
  1381.  
  1382.     XCHG            ;file size to de-pair
  1383.     LDA    T$UN$FG
  1384.     ORA    A
  1385.     JRZ    TAKE        ;if untag, take size from total.
  1386.     LHLD    TAG$TOT        ;accumulate..
  1387.     DAD    D        ;..sum of..
  1388.     SHLD    TAG$TOT        ;..tagged file sizes.
  1389.     XCHG            ;file size to hl-pair
  1390.     JR    D$F$SIZ        ;branch to display sizes
  1391.  
  1392. TAKE:
  1393.     LHLD    TAG$TOT        ;subtract..
  1394.     MOV    A,L        ;..file..
  1395.     SUB    E        ;..size..
  1396.     MOV    L,A        ;..from..
  1397.     MOV    A,H        ;..summation..
  1398.     SBB    D        ;..total.
  1399.     MOV    H,A        ;then put..
  1400.     SHLD    TAG$TOT        ; (save total)
  1401.     XCHG            ;..file size in hl-pair.
  1402.  
  1403. ; display file size in kilobytes -- right justify tagged file total
  1404.  
  1405. D$F$SIZ:
  1406.     LDA    FSDFLG        ;display file size?
  1407.     ORA    A        ;0=no
  1408.     RZ
  1409.     PUSH    H        ;save value
  1410.     CALL    ATFS        ;position for file size print
  1411.     LHLD    RINGPOS        ;print file name of current file
  1412.     INX    H
  1413.     CALL    PRFN
  1414.     MVI    A,':'
  1415.     CALL    TYPE
  1416.     POP    H        ;get value
  1417.     CALL    DECOUT          ;print individual file size
  1418.     MVI    A,'K'
  1419.     CALL    TYPE
  1420.  
  1421. ; determine # of digits in tagged summation
  1422.  
  1423.     LHLD    TAG$TOT        ;get present summation
  1424.     CALL    ILPRT
  1425.     DB    ' Tagged:',0
  1426.     CALL    DECOUT          ;print tagged file summation
  1427.     MVI    A,'K'
  1428.     JMP    TYPE
  1429.  
  1430. ; j u m p
  1431.  
  1432. ; backward
  1433. JUMPB:
  1434.     LXI    H,CURHOME    ;set cursor home
  1435.     SHLD    CURAT
  1436.     LHLD    RING        ;at front?
  1437.     XCHG
  1438.     LHLD    LOCBEG
  1439.     CALL    CMPDEHL
  1440.     JRZ    JUMPBW        ;back up and wrap around
  1441.     SHLD    LOCEND        ;set new end
  1442.     LXI    D,-EPS*13    ;back up
  1443.     DAD    D
  1444.     SHLD    LOCBEG        ;new beginning
  1445.     SHLD    RINGPOS        ;new position
  1446.     CALL    REFRESH        ;refresh screen
  1447.     JMP    LOOPFN
  1448. JUMPBW:
  1449.     LHLD    LOCBEG        ;at first screen?
  1450.     XCHG
  1451.     LHLD    RING        ;pt to first element of ring
  1452.     CALL    CMPDEHL
  1453.     JRZ    JBW0        ;advance to end
  1454.     LXI    H,-EPS*13    ;back up
  1455.     DAD    D
  1456.     JR    JFW0
  1457. JBW0:
  1458.     LXI    D,EPS*13    ;pt to next screen
  1459.     DAD    D
  1460.     XCHG
  1461.     LHLD    RINGEND
  1462.     CALL    CMPDEHL
  1463.     XCHG
  1464.     JRZ    JBW1
  1465.     JRC    JBW0
  1466. JBW1:
  1467.     LXI    D,-EPS*13
  1468.     DAD    D        ;pt to first element of local ring
  1469.     JR    JFW0
  1470. JUMPF:
  1471.     LXI    H,CURHOME    ;set cursor to home
  1472.     SHLD    CURAT
  1473.     LHLD    LOCEND        ;see if Local End <= Ring End
  1474.     XCHG
  1475.     LHLD    RINGEND
  1476.     CALL    CMPDEHL
  1477.     JRZ    CMDLOOP
  1478.     LHLD    LOCEND        ;new screen
  1479.     JR    JFW0
  1480. CMDLOOP:
  1481.     LXI    H,CURHOME    ;set cursor home
  1482.     SHLD    CURAT
  1483.     LHLD    RING        ;set ring position
  1484. JFW0:
  1485.     SHLD    RINGPOS
  1486. JFW0A:
  1487.     SHLD    LOCBEG        ;front of ring
  1488.     LXI    D,EPS*13    ;new end?
  1489.     DAD    D
  1490.     XCHG
  1491.     LHLD    RINGEND        ;end of ring
  1492.     XCHG
  1493.     CALL    CMPDEHL
  1494.     JRC    JFW1
  1495.     XCHG
  1496. JFW1:
  1497.     XCHG
  1498.     SHLD    LOCEND
  1499.     CALL    REFRESH
  1500.     JMP    LOOPFN
  1501.  
  1502. ; f o r w a r d
  1503.  
  1504. FORWARD:
  1505.     CALL    CLRCUR        ;clear cursor
  1506.     CALL    FOR0        ;position on screen and in ring
  1507.     CALL    SETCUR        ;set cursor
  1508.     JMP    LOOPFN
  1509. ;  advance routine
  1510. FOR0:
  1511.     LHLD    RINGPOS        ;at end of loop yet?
  1512.     LXI    D,13        ;i.e., will we be at end of loop?
  1513.     DAD    D
  1514.     XCHG
  1515.     LHLD    LOCEND
  1516.     CALL    CMPDEHL        ;compare 'present' to 'end'
  1517.     JRNZ    FORW        ;to next print position
  1518.     CALL    CUR$FIRST    ;position cursor
  1519.     LHLD    LOCBEG        ;set position pointer to beginning and..
  1520.     SHLD    RINGPOS
  1521.     RET
  1522. FORW:
  1523.     LHLD    RINGPOS        ;advance in ring
  1524.     LXI    D,13
  1525.     DAD    D
  1526.     SHLD    RINGPOS        ;new position
  1527.     CALL    CUR$NEXT    ;position cursor
  1528.     RET
  1529.  
  1530. ; r e v e r s e
  1531.  
  1532. REVERSE:
  1533.     CALL    CLRCUR        ;clear cursor
  1534.     CALL    REV0        ;position on screen and in ring
  1535.     CALL    SETCUR        ;set cursor
  1536.     JMP    LOOPFN
  1537. ;  Back Up Routine
  1538. REV0:
  1539.     LHLD    LOCBEG
  1540.     XCHG
  1541.     LHLD    RINGPOS        ;see if at beginning of ring
  1542.     CALL    CMPDEHL
  1543.     JRNZ    REV1        ;skip position pointer reset if not..
  1544.     CALL    CUR$LAST    ;end of local ring
  1545.     LHLD    LOCEND        ;set to end +1 to backup to end
  1546.     LXI    D,-13
  1547.     DAD    D
  1548.     SHLD    RINGPOS
  1549.     RET
  1550. REV1:
  1551.     CALL    CUR$BACK    ;back up 1
  1552. REV2:
  1553.     LHLD    RINGPOS
  1554.     LXI    D,-13        ;one ring position..
  1555.     DAD    D        ;..backwards.
  1556.     SHLD    RINGPOS
  1557.     RET
  1558.  
  1559. ; u p
  1560.  
  1561. UP:
  1562.     CALL    CLRCUR        ;clear cursor
  1563.     LHLD    RINGPOS        ;see if wrap around
  1564.     LXI    D,-13*4        ;4 entries
  1565.     DAD    D
  1566.     XCHG
  1567.     LHLD    LOCBEG        ;beginning of local screen
  1568.     CALL    CMPDEHL
  1569.     JRC    UP2        ;wrap around
  1570.     MVI    B,4        ;back up 4 entries
  1571. UP1:
  1572.     PUSH    B        ;save count
  1573.     CALL    REV0        ;back up in ring and on screen (no print)
  1574.     POP    B        ;get count
  1575.     DJNZ    UP1
  1576.     JR    DOWN1A
  1577. UP2:
  1578.     LHLD    RINGPOS        ;advance to beyond end
  1579.     LXI    D,13*4
  1580.     DAD    D
  1581.     XCHG
  1582.     LHLD    LOCEND        ;compare to local end
  1583.     XCHG
  1584.     CALL    CMPDEHL
  1585.     JRZ    DOWN1A        ;at end, so too far
  1586.     JRC    DOWN1A        ;beyond end, so back up
  1587.     SHLD    RINGPOS        ;new ring position
  1588.     LHLD    CURAT        ;advance cursor
  1589.     INR    H        ;next line
  1590.     SHLD    CURAT
  1591.     JR    UP2
  1592.  
  1593. ; d o w n
  1594.  
  1595. DOWN:
  1596.     CALL    CLRCUR        ;clear cursor
  1597.     LHLD    RINGPOS        ;see if wrap around
  1598.     LXI    D,13*4        ;4 entries
  1599.     DAD    D
  1600.     XCHG
  1601.     LHLD    LOCEND        ;end of local screen
  1602.     XCHG
  1603.     CALL    CMPDEHL
  1604.     JRZ    DOWN2        ;wrap around
  1605.     JRC    DOWN2        ;wrap around
  1606.     MVI    B,4        ;forward 4 entries
  1607. DOWN1:
  1608.     PUSH    B        ;save count
  1609.     CALL    FOR0        ;advance in ring and on screen (no print)
  1610.     POP    B        ;get count
  1611.     DJNZ    DOWN1
  1612. DOWN1A:
  1613.     CALL    SETCUR        ;set cursor
  1614.     JMP    LOOPFN
  1615. DOWN2:
  1616.     LHLD    CURAT        ;preserve column
  1617.     MOV    B,L        ;column number in B
  1618.     LXI    H,CURHOME    ;home position
  1619.     SHLD    CURAT        ;set new position
  1620.     LHLD    LOCBEG        ;beginning of local ring
  1621.     SHLD    RINGPOS        ;new ring position
  1622. DOWN3:
  1623.     LHLD    CURAT        ;check for at top of column
  1624.     MOV    A,L        ;get col
  1625.     CMP    B        ;there?
  1626.     JRZ    DOWN1A
  1627.     LHLD    RINGPOS        ;advance in ring
  1628.     LXI    D,13        ;13 bytes/entry
  1629.     DAD    D
  1630.     SHLD    RINGPOS
  1631.     LHLD    CURAT        ;get cursor position
  1632.     LXI    D,19        ;advance 19 bytes/screen entry
  1633.     DAD    D
  1634.     SHLD    CURAT
  1635.     JR    DOWN3
  1636.  
  1637. ; s t a t
  1638.  
  1639. ; determine remaining storage on requested disk
  1640.  
  1641. R$DR$ST:
  1642.     CALL    CPRMPT
  1643.     DB    'Status of Disk: ',0
  1644.     CALL    KEYIN        ;get char
  1645.     PUSH    PSW
  1646.     CALL    CRLF
  1647.     POP    PSW
  1648.     SUI    'A'        ;convert to number
  1649.     JC    NEUTRAL
  1650.     MOV    B,A        ;... in B
  1651.     LDA    MAXDR        ;compare to max
  1652.     SUI    'A'
  1653.     CMP    B
  1654.     JC    LOOPFN
  1655.     MOV    A,B        ;get disk
  1656.     STA    R$DR        ;requested drive
  1657.     CALL    RESET        ;..login as current.
  1658.     CALL    FRESTOR        ;determine free space remaining
  1659.     CALL    PRINT$FRE    ;print value
  1660.     LDA    C$DR        ;login original as..
  1661.     CALL    SET$DR        ;..current drive.
  1662. ; compute file count
  1663.     LXI    H,0        ;set count
  1664.     SHLD    LOCPOS        ;dummy area
  1665.     LHLD    RING        ;pt to ring
  1666. R$DR1:
  1667.     XCHG            ;position in DE
  1668.     LHLD    RINGEND
  1669.     CALL    CMPDEHL        ;at end of ring?
  1670.     JRZ    R$DR2
  1671.     LHLD    LOCPOS        ;increment count
  1672.     INX    H
  1673.     SHLD    LOCPOS
  1674.     LXI    H,13        ;advance to next ring element
  1675.     DAD    D        ;HL pts to next
  1676.     JR    R$DR1
  1677. R$DR2:
  1678.     LHLD    LOCPOS        ;get count
  1679.     CALL    DECOUT        ;print count
  1680.     CALL    ILPRT
  1681.     DB    ' Files in DIR',0
  1682.     JMP    LOOPFN
  1683.  
  1684. ; d e l e t e
  1685.  
  1686. ; mass delete
  1687.  
  1688. MASS$DEL:
  1689.     CALL    CPRMPT
  1690.     DB    'Mass Delete (Y/N/V=Verify Each)? ',0
  1691.     CALL    KEYIN        ;get response
  1692.     CPI    'Y'
  1693.     JRZ    MD1
  1694.     CPI    'V'
  1695.     JNZ    NEUTRAL        ;return to position
  1696. MD1:
  1697.     STA    MDFLG        ;set flag
  1698.     XRA    A        ;set for mass delete
  1699.     STA    MFLAG
  1700.     LHLD    RING
  1701.     SHLD    RINGPOS        ;set ring position
  1702. MD$LP:
  1703.     LHLD    RINGPOS        ;get current position
  1704.     LXI    D,12        ;pt to tag
  1705.     DAD    D
  1706.     MOV    A,M        ;get tag
  1707.     CPI    '*'
  1708.     JRNZ    MD$LOOP
  1709.     CALL    RINGFCB        ;set up file name
  1710.     LDA    MDFLG        ;verify?
  1711.     CPI    'V'
  1712.     JRZ    MDEL1        ;delete with verify
  1713.     JR    DEL1        ;delete without verify
  1714. MD$LOOP:
  1715.     LHLD    RINGPOS        ;re-entry point for next file mass-copy
  1716.     LXI    D,13        ;advance to next
  1717.     DAD    D
  1718.     SHLD    RINGPOS
  1719. MD1$LOOP:
  1720.     XCHG            ;at ring..
  1721.     LHLD    RINGEND        ;..end yet?
  1722.     CALL    CMPDEHL        ; (compare present position with end)
  1723.     JRNZ    MD$LP        ;no, loop 'till thru ring list.
  1724.  
  1725. MD$EXIT:
  1726.     MVI    A,TRUE        ;set no
  1727.     STA    MFLAG        ;..mass-delete request.
  1728.     JMP    CMDLOOP        ;jump to 'ring' beginning
  1729.  
  1730.  
  1731. ; set up to delete filename at cursor position
  1732.  
  1733. DELETE:
  1734.     MVI    A,TRUE        ;set for no mass delete
  1735.     STA    MFLAG
  1736.     STA    MDFLG
  1737. MDELETE:
  1738.     CALL    RINGFCB        ;move file name
  1739. MDEL1:
  1740.     CALL    CPRMPT
  1741.     DB    'Delete ',0
  1742.     CALL    PRFNS        ;print file name in S$FCB
  1743.     CALL    ILPRT
  1744.     DB    ' (Y/N)? ',0
  1745.     CALL    KEYIN
  1746.     CPI    'Y'
  1747.     JRZ    DEL1
  1748.     LDA    MFLAG        ;mass delete?
  1749.     ORA    A
  1750.     JRZ    MD$LOOP
  1751. MDEL2:
  1752.     LHLD    LOCEND        ;move in end
  1753.     LXI    D,-13
  1754.     DAD    D
  1755.     SHLD    LOCEND
  1756.     XCHG
  1757.     LHLD    RINGPOS        ;position beyond end of ring?
  1758.     CALL    CMPDEHL
  1759.     JRNZ    MDEL3
  1760.     CALL    CUR$BACK    ;back up cursor
  1761.     LHLD    LOCEND        ;reset position
  1762.     LXI    D,-13
  1763.     DAD    D
  1764.     SHLD    RINGPOS
  1765.     LHLD    LOCEND        ;get end
  1766.     XCHG
  1767. MDEL3:
  1768.     LHLD    LOCBEG        ;erased all local files?
  1769.     CALL    CMPDEHL
  1770.     JZ    CMDLOOP        ;reset
  1771.     JMP    JFW0A        ;rescreen
  1772.  
  1773. ; delete file
  1774.  
  1775. DEL1:
  1776.     LDA    MDFLG        ;Y option on Mass Delete?
  1777.     CPI    'Y'
  1778.     JRNZ    DEL1A
  1779.     CALL    ERMSG
  1780.     DB    'Deleting File ',0
  1781.     CALL    PRFNS
  1782. DEL1A:
  1783.     LXI    H,S$FCB        ;set file to R/W
  1784.     CALL    ATTRIB
  1785.     LXI    D,S$FCB        ;point at delete 'fcb'
  1786.     MVI    C,ERASE        ;erase function
  1787.     CALL    BDOS
  1788.     INR    A
  1789.     JRZ    FNF$MSG        ;print error message
  1790.     CALL    DEL2        ;close up erased position
  1791.     LDA    MFLAG        ;check for mass delete
  1792.     ORA    A
  1793.     JRNZ    MDEL2
  1794.     LHLD    RINGPOS        ;no advance because of close up
  1795.     JMP    MD1$LOOP
  1796. FNF$MSG:
  1797.     CALL    ERMSG        ;show error message
  1798.     DB    'No File Found',0
  1799.     JMP    LOOPFN
  1800.  
  1801. ; reverse ring to close up erased position
  1802.  
  1803. DEL2:
  1804.     LHLD    RINGPOS        ;prepare move up pointers
  1805.     PUSH    H
  1806.     LXI    D,13        ;13 bytes/entry
  1807.     DAD    D        ;de-pair = 'to' location
  1808.     POP    D        ;hl-pair = 'from' location
  1809. MOVUP:
  1810.     XCHG
  1811.     PUSH    H        ;check if at end
  1812.     LHLD    RINGEND        ;get old end pointer
  1813.     CALL    CMPDEHL        ;check against current end location
  1814.     POP    H
  1815.     XCHG
  1816.     JRZ    MOVDONE        ;must be at end of ring
  1817.     MVI    B,13        ;one name size
  1818.     CALL    MOVE        ;move one name up
  1819.     JR    MOVUP        ;go check end parameters
  1820.  
  1821. MOVDONE:
  1822.     LHLD    RING        ;see if ring is empty
  1823.     XCHG
  1824.     SHLD    RINGEND        ;set new ring end if all moved
  1825.     CALL    CMPDEHL        ;..(listend --> listpos --> ring)
  1826.     RNZ
  1827.     LHLD    RINGPOS
  1828.     CALL    CMPDEHL
  1829.     RNZ            ;neither equal so not empty
  1830.     LXI    SP,STACK    ;reset stack
  1831.     CALL    ERMSG
  1832.     DB    'List Empty',0
  1833.     JMP    LOG        ;go to drive/user area with files
  1834.  
  1835. ; r e n a m e
  1836.  
  1837. ; set-up to rename file at cursor position -- scan keyboard buffer and
  1838. ; move filename to 'rename' destination 'fcb' (dfcb)
  1839.  
  1840. RENAME:
  1841.     LHLD    RINGPOS        ;move name from ring to rename 'fcb'
  1842.     LXI    D,D$FCB        ;place to move name
  1843.     MVI    B,12        ;amount to move
  1844.     CALL    MOVE
  1845.     CALL    CPRMPT        ;new name prompt
  1846.     DB    'Rename File to: ',0
  1847.     LXI    D,D$FCB+16    ;pt to FCB to fill
  1848.     CALL    FILENAME    ;get file name
  1849.     LXI    H,D$FCB+1    ;check for any wild cards -- none permitted
  1850.     MVI    B,11        ;11 bytes
  1851. WILDCHK:
  1852.     MOV    A,M        ;get char
  1853.     INX    H        ;pt to next
  1854.     CPI    '?'        ;wild?
  1855.     JRZ    WILDFND
  1856.     DJNZ    WILDCHK
  1857.  
  1858. ; copy old file status bit ($r/o or $sys) to new filename
  1859.  
  1860. CPYBITS:
  1861.     LXI    D,D$FCB+1    ;first character of old name..
  1862.     LXI    H,D$FCB+17    ;..and of new name.
  1863.     MVI    B,11        ; # of bytes with tag bits
  1864. CBITS1:
  1865.     LDAX    D        ;fetch bit of old name character
  1866.     ANI    128        ;strip upper bit and..
  1867.     MOV    C,A        ;..save in b-reg.
  1868.     MVI    A,7FH        ;mask for character only
  1869.     ANA    M        ;put masked character into a-reg
  1870.     ORA    C        ;add old bit
  1871.     MOV    M,A        ;copy new byte back
  1872.     INX    H        ;bump copy pointers
  1873.     INX    D
  1874.     DJNZ    CBITS1
  1875.  
  1876. ; check if new filename already exists.  if so, say so.  then go
  1877. ; to command loop without moving ring position
  1878.  
  1879.     LDA    D$FCB        ;copy new name to source 'fcb'
  1880.     STA    S$FCB
  1881.     MVI    B,11
  1882.     LXI    H,D$FCB+17    ;copy new name to..
  1883.     LXI    D,S$FCB+1    ;..source 'fcb' for existence check.
  1884.     CALL    MOVE
  1885.     LXI    H,S$FCB+12    ;clear cp/m 'fcb' system..
  1886.     CALL    INITFCB        ;..fields.
  1887.     LXI    D,S$FCB        ;search to see if this file exists
  1888.     MVI    C,SRCHF        ;search first function
  1889.     CALL    BDOS
  1890.     INR    A        ; 0ffh --> 00h if file not found
  1891.     JRZ    RENFILE        ;to rename, if duplicate doesn't exists.
  1892.     CALL    ERMSG        ;announce the situation
  1893.     DB    'File Already Exists',0
  1894.     JMP    COMCAN        ;try again?
  1895.  
  1896. ; wild char found in file name -- error
  1897.  
  1898. WILDFND:
  1899.     CALL    ERMSG
  1900.     DB    'Ambiguous File Name NOT Allowed',0
  1901.     JMP    COMCAN
  1902.  
  1903. ; copy new name into ring position
  1904.  
  1905. RENFILE:
  1906.     LHLD    RINGPOS        ;get ring position pointer
  1907.     INX    H        ;pt to name
  1908.     PUSH    H        ;save ptr
  1909.     XCHG
  1910.     LXI    H,D$FCB+17    ;point at new name and..
  1911.     MVI    B,11
  1912.     CALL    MOVE        ;..move.
  1913.     LHLD    CURAT        ;get current position on screen
  1914.     LXI    D,4        ;advance 4 chars
  1915.     DAD    D
  1916.     CALL    GOTOXY
  1917.     POP    H        ;get ptr
  1918.     CALL    PRFN        ;print file name
  1919.     MOV    A,M        ;print tag
  1920.     CALL    TYPE
  1921.     LXI    D,D$FCB        ;rename 'fcb' location
  1922.     MVI    C,REN        ;rename function
  1923.     CALL    BDOS
  1924.     INR    A        ; 0ffh --> 00h if rename error
  1925.     JNZ    NEUTRAL        ;if okay, proceed, else..
  1926.     JMP    FNF$MSG        ;..show no-file msg.
  1927.  
  1928. ; get file name from user and process into FCB pted to by DE
  1929. FILENAME:
  1930.     PUSH    D        ;save ptr
  1931.     LXI    D,CMDBUF    ;command line location
  1932.     MVI    C,RDBUF        ;console read-buffer function
  1933.     CALL    BDOS
  1934.     CALL    CONVERT        ;capitalize alpha
  1935.     POP    H        ;set to null drive
  1936.     MVI    M,0        ;..required by 'bdos'.
  1937.     INX    H
  1938.  
  1939. ; initialize new filename field with spaces
  1940.  
  1941.     PUSH    H        ;save start pointer
  1942.     MVI    B,11        ; # of spaces to 'blank'
  1943.     CALL    FILL
  1944.     POP    H
  1945.     XCHG
  1946.     LXI    H,CMDBUF+1    ;put length..
  1947.     MOV    C,M        ;..in c-reg.
  1948.     INX    H
  1949.     XCHG            ;de-pair --> buffer pointer and hl-pair..
  1950.     CALL    UNSPACE        ;..--> 'fcb' pointer.  remove leading spaces.
  1951.  
  1952. ; extend buffer to spaces beyond command length
  1953.  
  1954. EXTEND:
  1955.     PUSH    H
  1956.     MOV    L,C        ;double-byte remaining length
  1957.     MVI    H,0
  1958.     DAD    D        ;to buffer end +1
  1959.     MVI    M,' '        ;force illegal character end
  1960.     POP    H
  1961.  
  1962. ; start filename scan
  1963.  
  1964. SCAN:
  1965.     MVI    B,8        ; 8 characters in filename
  1966. SCAN1:
  1967.     CALL    CKLEGAL        ;get and see if legal character
  1968.     JC    COMCAN        ;all of command line?
  1969.     CPI    ' '        ;see if end of parameter field
  1970.     RZ            ;rename file
  1971.     CPI    '.'        ;at end of filename
  1972.     JRZ    SCAN2        ;process filetype field
  1973.     CPI    '*'        ;rest wild?
  1974.     JRZ    SCAN1B
  1975.     MOV    M,A        ;put character into destination 'fcb'
  1976.     INX    H
  1977.     DJNZ    SCAN1
  1978.  
  1979. ; entry if eight characters without a 'period'
  1980.  
  1981. SCAN1A:
  1982.     CALL    CKLEGAL        ;scan buffer up to period or end
  1983.     RC            ;no extent if not legal
  1984.     CPI    ' '        ;end of parameter field?
  1985.     RZ
  1986.     CPI    '.'
  1987.     JRNZ    SCAN1A        ;do till end or period
  1988.     JR    SCAN2A        ;continue at correct place
  1989.  
  1990. ; make rest of entry wild
  1991.  
  1992. SCAN1B:
  1993.     MVI    M,'?'        ;fill with ?'s
  1994.     INX    H
  1995.     DJNZ    SCAN1B
  1996.     LDAX    D        ;get next char
  1997.     INX    D        ;pt to after dot
  1998.     CPI    '.'        ;must be dot
  1999.     JNZ    COMCAN        ;cancel if not
  2000.     JR    SCAN2A
  2001.  
  2002. ; build filetype field
  2003.  
  2004. SCAN2:
  2005.     INX    H        ;advance ptr to file type field
  2006.     DJNZ    SCAN2
  2007. SCAN2A:
  2008.     MVI    B,3        ;length of filetype field
  2009. SCAN3:
  2010.     CALL    CKLEGAL        ;get and check character
  2011.     JRC    SCAN4        ;name done if illegal
  2012.     CPI    ' '        ;end of parameter field?
  2013.     JRZ    SCAN4
  2014.     CPI    '.'        ;check if another period
  2015.     JRZ    SCAN4
  2016.     CPI    '*'        ;rest wild?
  2017.     JRZ    SCAN4B
  2018.     MOV    M,A
  2019.     INX    H
  2020.     DJNZ    SCAN3        ;get next character
  2021.     JR    SCAN4A
  2022. SCAN4:
  2023.     INX    H        ;advance to end of type field
  2024.     DJNZ    SCAN4
  2025. SCAN4A:
  2026.     CALL    INITFCB        ;..and zero counter fields.
  2027.     RET
  2028. SCAN4B:
  2029.     MVI    M,'?'        ;make wild
  2030.     INX    H
  2031.     DJNZ    SCAN4B
  2032.     JR    SCAN4A        ;complete rest
  2033.  
  2034. ; goto file
  2035.  
  2036. GOTO:
  2037.     CALL    CPRMPT
  2038.     DB    'Goto Filename: ',0
  2039.     LXI    D,D$FCB        ;pt to FCB
  2040.     CALL    FILENAME    ;get file name
  2041.     LHLD    RING        ;pt to first element of ring
  2042.     SHLD    RINGPOS        ;set position
  2043.     SHLD    LOCBEG        ;set local beginning
  2044.     XRA    A        ;set local counter
  2045.     STA    CRCTBL        ;use this buffer
  2046. GOTOL:
  2047.     CALL    GOTOCOMP    ;compare
  2048.     JRZ    GOTOF        ;we are there
  2049.     LDA    CRCTBL        ;increment count
  2050.     INR    A
  2051.     STA    CRCTBL
  2052.     CPI    EPS
  2053.     JRNZ    GOTOL1
  2054.     XRA    A        ;reset count
  2055.     STA    CRCTBL
  2056.     LHLD    LOCBEG        ;reset local beginning
  2057.     LXI    D,EPS*13
  2058.     DAD    D
  2059.     SHLD    LOCBEG
  2060. GOTOL1:
  2061.     LHLD    RINGPOS        ;advance to next entry
  2062.     LXI    D,13
  2063.     DAD    D
  2064.     SHLD    RINGPOS        ;new position
  2065.     XCHG            ;position in DE
  2066.     LHLD    RINGEND        ;check for completion
  2067.     CALL    CMPDEHL        ;compare current position with end of ring
  2068.     JRNZ    GOTOL
  2069.     LHLD    RING        ;pt to first element
  2070.     SHLD    RINGPOS        ;set position
  2071.     CALL    ERMSG
  2072.     DB    'File NOT Found',0
  2073.     JMP    CMDLOOP
  2074. GOTOF:
  2075.     LHLD    LOCBEG        ;we have local beginning
  2076.     PUSH    H
  2077.     XCHG            ;ring location in DE
  2078.     LXI    H,CURHOME    ;set cursor ptr
  2079.     SHLD    CURAT
  2080. GOTOF0:
  2081.     LHLD    RINGPOS        ;at position?
  2082.     CALL    CMPDEHL
  2083.     JRZ    GOTOF1
  2084.     LXI    H,13        ;advance location
  2085.     DAD    D
  2086.     PUSH    H
  2087.     CALL    CUR$NEXT    ;advance cursor
  2088.     POP    D        ;pt to next ring position
  2089.     JR    GOTOF0
  2090. GOTOF1:
  2091.     POP    H        ;pt to local ring
  2092.     JMP    JFW0A        ;process
  2093. GOTOCOMP:
  2094.     LHLD    RINGPOS        ;pt to current entry
  2095.     INX    H        ;pt to first char of file name
  2096.     LXI    D,D$FCB+1    ;pt to first char of new file
  2097.     MVI    B,11        ;11 bytes
  2098. GOTOC1:
  2099.     LDAX    D        ;get char
  2100.     CPI    '?'        ;match?
  2101.     JRZ    GOTOC2
  2102.     CMP    M        ;match?
  2103.     RNZ            ;no match
  2104. GOTOC2:
  2105.     INX    D        ;pt to next
  2106.     INX    H
  2107.     DJNZ    GOTOC1
  2108.     RET
  2109.  
  2110. ; v i e w
  2111.  
  2112. ; type file to console with pagination set to 'lps' -- single-line scroll
  2113. ; using <space> bar , <ctrl-x> to cancel, any other key to page screen.
  2114.  
  2115. VIEW:
  2116.     CALL    CLS
  2117.     CALL    ILPRT
  2118.     DB    CR,LF,'<CTRL-C> Cancels, <SP> Turns Up One Line, '
  2119.     DB    'Other Keys Page Screen',CR,LF,LF,0
  2120.     MVI    A,1        ;initialize..
  2121.     STA    LPSCNT        ;..lines-per-screen counter.
  2122.     STA    VIEWFLG        ; 'view' paginate if not zero
  2123.     MVI    A,WRCON        ;write console out function
  2124.     JR    CURRENT        ;to common i/o processing
  2125.  
  2126. ; p r i n t e r
  2127.  
  2128. ; send file to logical list device -- any keypress cancels
  2129.  
  2130. LSTFILE:
  2131.     CALL    CPRMPT
  2132.     DB    'Print on LST Device (Y/N)? ',0
  2133.     CALL    KEYIN        ;get response
  2134.     CPI    'Y'
  2135.     JNZ    NEUTRAL
  2136.     CALL    ERMSG
  2137.     DB    'Printing ',0
  2138.     LHLD    RINGPOS        ;pt to file name
  2139.     INX    H
  2140.     CALL    PRFN        ;print it
  2141.     MVI    A,1        ;one for..
  2142.     STA    VIEWFLG        ;..output to printer.
  2143.     DCR    A        ;zero for..
  2144.     STA    LPSCNT        ;..lines-per-page counter
  2145.     MVI    A,LIST        ;out to 'list' device function and fall thru
  2146.  
  2147. ; output character for console/list/punch processing
  2148.  
  2149. CURRENT:
  2150.     STA    CON$LST        ;save bdos function
  2151.  
  2152. ; output file to console/printer/punch
  2153.  
  2154.     CALL    RINGFCB        ;position name to 'fcb'
  2155.     XCHG            ;HL pts to S$FCB
  2156.     CALL    INITFCB        ;set 'fcb' for use
  2157.     LXI    D,TBUF        ;set to use default cp/m dma buffer
  2158.     MVI    C,SETDMA    ;address set function
  2159.     CALL    BDOS
  2160.     LXI    D,S$FCB        ;open file for reading
  2161.     MVI    C,OPEN        ;file open function code
  2162.     CALL    BDOS
  2163.     INR    A        ; 0ffh --> 00h if open not okay
  2164.     JRNZ    ZEROCR        ;if not okay, show error message.
  2165.     CALL    ERMSG
  2166.     DB    'Unable to Open File',0
  2167.     JMP    NEUTRAL
  2168.  
  2169. ZEROCR:
  2170.     XRA    A
  2171.     STA    S$FCB+32    ;zero file 'current record' field
  2172.     STA    CHARCNT        ;zero char count for tabbing
  2173.     CALL    PHEAD        ;print heading if output to LST device
  2174. READMR:
  2175.     LXI    D,S$FCB        ;point at file 'fcb' for reading
  2176.     MVI    C,READ        ;record read function
  2177.     CALL    BDOS
  2178.     ORA    A        ;check if read okay
  2179.     JRNZ    CURDONE        ;eof?
  2180.     LXI    H,TBUF        ;point at record just read
  2181.     MVI    B,128        ;set record character counter to output
  2182. READLP:
  2183.     MOV    A,M        ;get a character
  2184.     ANI    7FH        ;force to 'ascii'
  2185.     CPI    EOFCHAR        ;see if end-of-file
  2186.     JRZ    CURDONE        ;back to ring loop if 'eof'
  2187.     MOV    E,A        ;put character for 'bdos' call
  2188.     PUSH    B
  2189.     PUSH    H
  2190.     PUSH    D        ; (character in e-reg)
  2191.     LDA    CON$LST        ;get function for punch/list/console output
  2192.     MOV    C,A
  2193.     MOV    A,E        ;check char
  2194.     CPI    TAB        ;tabulate?
  2195.     JRNZ    NOTAB
  2196.     MVI    E,' '        ;space over
  2197. TABL:
  2198.     PUSH    B        ;save key regs
  2199.     PUSH    D
  2200.     CALL    BDOS
  2201.     POP    D        ;get key regs
  2202.     POP    B
  2203.     CALL    INCCCNT        ;increment char count
  2204.     ANI    7        ;check for done at every 8
  2205.     JRNZ    TABL
  2206.     JR    TABDN
  2207. NOTAB:
  2208.     CALL    BDOS        ;send character
  2209.     CALL    INCCCNT        ;increment char count
  2210. TABDN:
  2211.     LDA    VIEWFLG        ;if 'view'..
  2212.     ORA    A
  2213.     POP    D        ;get char in E in case PAGER is called
  2214.     CNZ    PAGER        ;..check for 'lf'.
  2215.     MVI    E,GET        ;get status or char
  2216.     MVI    C,DIRCON    ;console status function
  2217.     CALL    BDOS        ;status?
  2218.     POP    H
  2219.     POP    B
  2220.     ANI    7FH        ;if character there, then abort..
  2221.     CNZ    CANVIEW        ;already got char
  2222.     INX    H        ;if not, bump buffer pointer.
  2223.     DJNZ    READLP        ;no, more in present record.
  2224.     JR    READMR        ;yes, get next record.
  2225. CURDONE:
  2226.     LDA    CON$LST        ;console?
  2227.     CPI    WRCON
  2228.     CZ    BOTTOM        ;prompt for user
  2229.     CALL    REFRESH        ;refresh screen
  2230.     JMP    LOOPFN
  2231. PAGER:
  2232.     MOV    A,E        ; (character in e-reg)
  2233.     CPI    LF
  2234.     RNZ
  2235.     XRA    A        ;zero char count
  2236.     STA    CHARCNT
  2237.     LDA    CON$LST        ;printer or console?
  2238.     CPI    LIST        ;check for printer
  2239.     JRZ    PAGEP
  2240.     LDA    CTPP        ;get number of lines of text per screen
  2241.     MOV    B,A        ;... in B
  2242.     LDA    LPSCNT        ;is counter..
  2243.     INR    A        ;..at..
  2244.     STA    LPSCNT        ;..limit..
  2245.     CMP    B        ;..of lines-per-screen?
  2246.     RC            ;no, return.
  2247.     XRA    A        ;yes, initialize..
  2248.     STA    LPSCNT        ;..for next screen full.
  2249.     CALL    ILPRT
  2250.     DB    '  [View More...]',CR,0    ;show msg line
  2251.     CALL    DKEYIN        ;wait for keyboard input
  2252.     CPI    ' '        ;see if <space> bar..
  2253.     PUSH    PSW
  2254.     CALL    ILPRT
  2255.     DB    '                ',CR,0    ;clear above msg line
  2256.     POP    PSW
  2257.     JRNZ    CANVIEW        ;..if not, see if cancel.
  2258.     LDA    CTPP        ;set for single line
  2259.     DCR    A
  2260.     STA    LPSCNT        ;..scroll and..
  2261.     RET            ;..return for one more line.
  2262.  
  2263. PAGEP:
  2264.     LDA    LTPP        ;get number of lines of text per page
  2265.     MOV    B,A        ;... in B
  2266.     LDA    LPSCNT        ;is counter..
  2267.     INR    A        ;..at..
  2268.     STA    LPSCNT        ;..limit..
  2269.     CMP    B        ;..of lines-per-screen?
  2270.     RC            ;no, return.
  2271.     XRA    A        ;zero for..
  2272.     STA    LPSCNT        ;..lines-per-page counter
  2273.     LDA    LSPP        ;number of lines to skip
  2274.     MOV    B,A        ;number of lines to skip
  2275.     MVI    C,LIST        ;LST output
  2276. PAGELST:
  2277.     CALL    LCRLF        ;new line on LST
  2278.     DJNZ    PAGELST
  2279.     CALL    PHEAD        ;print heading
  2280.     RET            ;done!
  2281.  
  2282. CANVIEW:
  2283.     CPI    CTRLC        ;^C?
  2284.     JZ    COMCAN
  2285.     RET            ;return for another page
  2286.  
  2287. INCCCNT:
  2288.     LDA    CHARCNT        ;increment char count
  2289.     INR    A
  2290.     STA    CHARCNT
  2291.     RET
  2292.  
  2293. PHEAD:
  2294.     LDA    CON$LST        ;printing to printer?
  2295.     CPI    LIST
  2296.     RNZ
  2297.     LXI    H,HEADMSG    ;print heading
  2298. PHEAD1:
  2299.     MOV    A,M        ;get char
  2300.     ORA    A        ;done?
  2301.     JRZ    PHEAD2
  2302.     CALL    LOUT        ;send to printer
  2303.     INX    H        ;pt to next
  2304.     JR    PHEAD1
  2305. PHEAD2:
  2306.     LXI    H,S$FCB+1    ;pt to file name
  2307.     MVI    B,8        ;8 chars
  2308.     CALL    PHEAD3
  2309.     MVI    A,'.'        ;dot
  2310.     CALL    LOUT
  2311.     MVI    B,3        ;3 more chars
  2312.     CALL    PHEAD3
  2313.     CALL    LCRLF        ;new line
  2314.     CALL    LCRLF        ;blank line
  2315.     RET
  2316. PHEAD3:
  2317.     MOV    A,M        ;get char
  2318.     CALL    LOUT        ;LST it
  2319.     INX    H        ;pt to next
  2320.     DJNZ    PHEAD3
  2321.     RET
  2322.  
  2323. ; m a s s   c o p y
  2324.  
  2325. ; copy files tagged using the 't' command.  auto-erase if file exists
  2326. ; on requested destination drive or in user area.
  2327.  
  2328. MASS$COPY:
  2329.     CALL    ERMSG
  2330.     DB    'Mass Copy',0
  2331.     LHLD    RINGPOS        ;save position
  2332.     SHLD    SRINGPOS
  2333.     LHLD    RING
  2334.     SHLD    RINGPOS        ;set position
  2335. MASS$LP:
  2336.     LHLD    RINGPOS        ;get position
  2337.     LXI    D,12        ;get 1st possible tag location
  2338.     DAD    D
  2339.     MOV    A,M        ;get tag
  2340.     CPI    '*'
  2341.     JRZ    MCOPY        ;copy filename with tag character (*)
  2342. M$LP:
  2343.     LHLD    RINGPOS        ;re-entry point for next file mass-copy
  2344.     LXI    D,13        ;advance to next
  2345.     DAD    D
  2346.     SHLD    RINGPOS
  2347.     XCHG            ;at ring..
  2348.     LHLD    RINGEND        ;..end yet?
  2349.     CALL    CMPDEHL        ; (compare present position with end)
  2350.     JRNZ    MASS$LP        ;loop 'till thru ring list.
  2351.  
  2352. MF$EXIT:
  2353.     XRA    A        ;reset flags..
  2354.     STA    FIRST$M        ;..for..
  2355.     CMA            ;..next..
  2356.     STA    MFLAG        ;..mass-copy request.
  2357.     LHLD    SRINGPOS    ;reset ring position
  2358.     SHLD    RINGPOS
  2359.     LHLD    LOCBEG        ;local ring
  2360.     JMP    JFW0A        ;rescreen
  2361.  
  2362. ; c o p y
  2363.  
  2364. ; copy source file at current 'ring' position to another drive.  set-up
  2365. ; fcb's and buffer area and check for correct keyboard inputs.  contains
  2366. ; auto-crc file copy verification.
  2367.  
  2368. MCOPY:
  2369.     XRA    A        ;zero flag to..
  2370.     STA    MFLAG        ;..mass copy.
  2371. COPY:
  2372.     LXI    H,0        ;initialize storage for..
  2373.     SHLD    CRCVAL        ;..'crc' working value.
  2374.     CALL    RINGFCB        ;move from 'ring' to 'sfcb'
  2375.     LXI    H,S$FCB+12    ;set pointer to source extent field
  2376.     CALL    INITFCB
  2377.     XRA    A        ;zero fcb 'cr' field
  2378.     STA    S$FCB+32
  2379.     MVI    B,32        ;copy source 'fcb' to destination 'fcb'
  2380.     LXI    H,S$FCB+1    ;from point..
  2381.     LXI    D,D$FCB+1    ;..to point..
  2382.     CALL    MOVE        ;..move across.
  2383.     LXI    D,S$FCB        ;open file for reading
  2384.     MVI    C,OPEN        ;open function
  2385.     CALL    BDOS
  2386.     INR    A        ; 0ffh --> 00h if bad open
  2387.     JRNZ    COPY2        ;if okay, skip error message.
  2388.     CALL    ERMSG
  2389.     DB    'Unable to Open Source',0
  2390.     JMP    NEUTRAL
  2391.  
  2392. COPY2:
  2393.     LDA    FIRST$M        ;by-pass prompt, drive/user compatibility..
  2394.     ORA    A        ;..test, and disk reset after..
  2395.     JRNZ    COPY3M        ;..1st time thru in mass-copy mode.
  2396.     CALL    CPRMPT        ;prompt for drive selection
  2397.     DB    'Copy to DIR: ',0
  2398.     CALL    DEF$D$U
  2399.  
  2400. ; either drives or user areas must be different
  2401.  
  2402.     LDA    DOK        ;OK to change drive?
  2403.     ORA    A
  2404.     JRNZ    CDOK
  2405.     LDA    S$FCB        ;make source and destination the same
  2406.     STA    FCB
  2407. CDOK:
  2408.     LDA    UOK        ;OK to change user?
  2409.     ORA    A
  2410.     JRNZ    CUOK
  2411.     LDA    C$U$A        ;make current user and requested the same
  2412.     STA    R$U$A
  2413. CUOK:
  2414.     LDA    FCB        ;get requested drive from 'fcb' and..
  2415.     MOV    B,A        ;..put into b-reg for..
  2416.     LDA    S$FCB        ;..comparison.
  2417.     CMP    B
  2418.     JRNZ    COPY3        ;branch if different
  2419.     LDA    R$U$A        ;requested user area --> rua
  2420.     MOV    B,A
  2421.     LDA    C$U$A        ;current user area --> cua
  2422.     CMP    B
  2423.     JRNZ    COPY3
  2424.     CALL    ERMSG        ;if not, show error condition:
  2425.     DB    'Drives or User Areas must be different',0
  2426.     JMP    NEUTRAL        ;try again?
  2427.  
  2428. COPY3:
  2429.     CALL    RESET        ;make sure disk is read/write
  2430. COPY3M:
  2431.     LDA    FCB        ;put requested drive into..
  2432.     STA    D$FCB        ;..place in destination fcb.
  2433.     LDA    R$U$A        ;toggle to..
  2434.     CALL    SET$USR        ;..requested user area.
  2435.     LXI    D,D$FCB        ;search for duplicate
  2436.     MVI    C,SRCHF        ; 'search first' function
  2437.     CALL    BDOS
  2438.     INR    A        ;if not found, 0ffh --> 00h.  then..
  2439.     JRZ    COPY5        ;go to 'make' function for new file.
  2440.     LDA    MFLAG        ;auto-erase..
  2441.     ORA    A        ;..if..
  2442.     JRZ    COPY4M        ;..in mass-copy mode.
  2443.     CALL    ERMSG        ;CPR2 - if found, ask to replace:
  2444.     DB    'Copy Exists -- Erase (Y/N)? ',0
  2445.     CALL    KEYIN        ;get answer
  2446.     CPI    'Y'        ;if yes, then..
  2447.     JRZ    COPY4M        ;..delete and overlay.
  2448.     LDA    C$U$A        ;reset to..
  2449.     CALL    SET$USR        ;..current user area.
  2450.     JMP    FORWARD        ;if re-copy not wanted, to next position.
  2451.  
  2452. COPY4M:
  2453.     LXI    H,D$FCB        ;pt to FCB
  2454.     CALL    ATTRIB        ;clear bytes in FCB and set attr of file
  2455.     LXI    D,D$FCB        ;delete file already existing
  2456.     MVI    C,ERASE        ;erase function
  2457.     CALL    BDOS
  2458. COPY5:
  2459.     LXI    D,D$FCB        ;create new file and open for writing
  2460.     MVI    C,MAKE        ;make function
  2461.     CALL    BDOS
  2462.     INR    A        ;if directory full, 0ffh --> 00h.
  2463.     JRNZ    COPY6        ;if not, branch.
  2464.     CALL    ERMSG
  2465.     DB    'Destination Directory Full',0
  2466.     JMP    LOOPFN        ;if error, back to ring processor.
  2467.  
  2468. COPY6:
  2469.     CALL    ERMSG
  2470.     DB    'Copying File ',0
  2471.     LXI    H,D$FCB+1    ;print file name
  2472.     CALL    PRFNSX
  2473.     XRA    A        ;clear 'eof'..
  2474.     STA    EOFLAG        ;..flag.
  2475. COPY6A:
  2476.     LDA    C$U$A        ;reset user area..
  2477.     CALL    SET$USR        ;..to current.
  2478.     LXI    H,0        ;clear current-record..
  2479.     SHLD    REC$CNT        ;..counter.
  2480.     LHLD    BUFSTART    ;set buffer start pointer..
  2481.     SHLD    BUF$PT        ;..to begin pointer.
  2482.  
  2483. ; read source file -- fill buffer memory or stop on 'eof' -- update 'crc'
  2484. ; on-the-fly
  2485.  
  2486. COPY7:
  2487.     LHLD    BUF$PT        ;set dma address to buffer pointer
  2488.     XCHG            ; de-pair --> dma address
  2489.     MVI    C,SETDMA
  2490.     CALL    BDOS
  2491.     LXI    D,S$FCB        ;source 'fcb' for reading
  2492.     MVI    C,READ        ;record read function
  2493.     CALL    BDOS
  2494.     ORA    A        ; 00h --> read okay
  2495.     JRZ    S$RD$OK
  2496.     DCR    A        ;eof?
  2497.     JRZ    COPY8        ;yes, end-of-file, set 'eof' flag.
  2498.     CALL    ERMSG
  2499.     DB    'Source Read Error',0
  2500.     JMP    LOOPFN
  2501.  
  2502. S$RD$OK:
  2503.     LHLD    BUF$PT
  2504.     MVI    B,128
  2505. COPY7A:
  2506.     MOV    A,M        ;get character and..
  2507.     CALL    UPDCRC        ;..add to 'crc' value.
  2508.     INX    H
  2509.     DCR    B
  2510.     JRNZ    COPY7A        ;loop 'till record read finished
  2511.     LHLD    BUF$PT        ;bump buffer pointer..
  2512.     LXI    D,128        ;..by..
  2513.     DAD    D        ;..one..
  2514.     SHLD    BUF$PT        ;..record.
  2515.     LHLD    REC$CNT        ;bump buffer..
  2516.     INX    H        ;..record count and..
  2517.     SHLD    REC$CNT        ;..store.
  2518.     XCHG            ;ready to compare to..
  2519.     LHLD    REC$MAX        ;..maximum record count (full-buffer).
  2520.     CALL    CMPDEHL        ;compare
  2521.     JRNZ    COPY7        ;if not full, get next record.
  2522.     JR    COPY9        ;full, start first write session.
  2523.  
  2524. ; indicate end-of-file read
  2525.  
  2526. COPY8:
  2527.     MVI    A,TRUE        ;set 'eof' flag
  2528.     STA    EOFLAG
  2529.  
  2530. ; write 'read-file' from memory buffer to destination 'written-file'
  2531.  
  2532. COPY9:
  2533.     LDA    R$U$A        ;set user to requested..
  2534.     CALL    SET$USR        ;..area.
  2535.     LHLD    BUFSTART    ;adjust buffer pointer..
  2536.     SHLD    BUF$PT        ;..to start address.
  2537. COPY10:
  2538.     LHLD    REC$CNT        ;buffer empty?
  2539.     MOV    A,H
  2540.     ORA    L
  2541.     JRZ    COPY11        ;buffer empty, check 'eof' flag.
  2542.     DCX    H        ;dec buffer record count for each write
  2543.     SHLD    REC$CNT
  2544.     LHLD    BUF$PT        ;set up dma address
  2545.     PUSH    H        ;save for size bump
  2546.     XCHG            ;pointer in de-pair
  2547.     MVI    C,SETDMA
  2548.     CALL    BDOS
  2549.     POP    H
  2550.     LXI    D,128        ;bump pointer one record length
  2551.     DAD    D
  2552.     SHLD    BUF$PT
  2553.     LXI    D,D$FCB        ;destination file 'fcb'
  2554.     MVI    C,WRITE        ;write record function
  2555.     CALL    BDOS
  2556.     ORA    A           ; 00h --> write okay
  2557.     JRZ    COPY10        ;okay, do next record.  else..
  2558.     CALL    ERMSG        ;..say disk write error.
  2559.     DB    'Copy Disk Full',0
  2560. C$ERA:
  2561.     LXI    D,D$FCB        ;delete..
  2562.     MVI    C,ERASE        ;..partial..
  2563.     CALL    BDOS        ;..from directory.
  2564.     XRA    A              ;reset 1st-time-thru tag flag..
  2565.     STA    FIRST$M        ;..for continuation of mass copying.
  2566.     JMP    LOOPFN        ;back to ring
  2567.  
  2568. COPY11:
  2569.     LDA    EOFLAG        ;buffer all written, check for 'eof'.
  2570.     ORA    A
  2571.     JZ    COPY6A        ;branch to read next buffer full
  2572.     LXI    D,D$FCB        ;point at 'fcb' for file closure
  2573.     MVI    C,CLOSE
  2574.     CALL    BDOS
  2575.     INR    A        ;if no-close-error then..
  2576.     JRNZ    CRC$CMP        ;..compare file crc's.
  2577.     CALL    ERMSG
  2578.     DB    'Copy Close Error',0
  2579.     JMP    C$ERA
  2580.  
  2581. ; read destination 'written-file' and compare crc's
  2582.  
  2583. CRC$CMP:
  2584.     LHLD    CRCVAL        ;transfer 'crc' value to..
  2585.     SHLD    CRCVAL2        ;..new storage area.
  2586.     LXI    H,0        ;clear working storage..
  2587.     SHLD    CRCVAL        ;..to continue.
  2588.     LXI    D,TBUF
  2589.     MVI    C,SETDMA
  2590.     CALL    BDOS
  2591.     LXI    H,D$FCB+12
  2592.     CALL    INITFCB
  2593.     LXI    D,D$FCB
  2594.     MVI    C,OPEN
  2595.     CALL    BDOS
  2596.     INR    A        ; 0ffh --> 00h if bad open
  2597.     JZ    BADCRC        ;if bad open, just say 'bad-crc'.
  2598.     XRA    A        ;zero 'fcb'..
  2599.     STA    D$FCB+32    ;..'cr' field.
  2600. CRCWF1:
  2601.     LXI    D,D$FCB
  2602.     MVI    C,READ
  2603.     CALL    BDOS
  2604.     ORA    A        ;read okay?
  2605.     JRZ    D$RD$OK        ;yes, read more.
  2606.     DCR    A        ;eof?
  2607.     JZ    FINCRC        ;yes, finish up and make 'crc' comparison.
  2608.     CALL    ERMSG
  2609.     DB    'Copy Read Error',0
  2610.     JMP    NEUTRAL
  2611.  
  2612. D$RD$OK:
  2613.     LXI    H,TBUF
  2614.     MVI    B,128
  2615. CRCWF2:
  2616.     MOV    A,M        ;get character to..
  2617.     CALL    UPDCRC        ;..add to 'crc' value. 
  2618.     INX    H
  2619.     DJNZ    CRCWF2
  2620.     JR    CRCWF1
  2621.  
  2622. ; clear attributes of file (HL) and set attributes on disk
  2623. ATTRIB:
  2624.     PUSH    H        ;save ptr
  2625.     INX    H        ;pt to first char
  2626.     MVI    B,11        ;11 Bytes
  2627. ATTRIB1:
  2628.     MOV    A,M        ;get byte
  2629.     ANI    7FH        ;mask it
  2630.     MOV    M,A        ;put byte
  2631.     INX    H        ;pt to next
  2632.     DCR    B        ;count down
  2633.     JNZ    ATTRIB1
  2634.     POP    D        ;pt to FCB
  2635.     MVI    C,ATTR
  2636.     JMP    BDOS
  2637.  
  2638. ; crc subroutines
  2639.  
  2640. ; initialize tables for fast crc calculations
  2641.  
  2642. INITCRC:
  2643.     LXI    H,CRCTBL
  2644.     MVI    C,0        ;table index
  2645. GLOOP:
  2646.     XCHG
  2647.     LXI    H,0        ;initialize crc register pair
  2648.     MOV    A,C
  2649.     PUSH    B        ;save index in c-reg
  2650.     MVI    B,8
  2651.     XRA    H
  2652.     MOV    H,A
  2653. LLOOP:
  2654.     DAD    H
  2655.     JRNC    LSKIP
  2656.     MVI    A,10H        ;generator is x^16 + x^12 + x^5 + x^0 as..
  2657.     XRA    H        ;..recommended by ccitt for asynchronous..
  2658.     MOV    H,A        ;..communications.  produces the same..
  2659.     MVI    A,21H        ;..results as public domain programs..
  2660.     XRA    L        ;..chek, comm7, mdm7, and modem7.
  2661.     MOV    L,A
  2662. LSKIP:
  2663.     DJNZ    LLOOP
  2664.     POP    B
  2665.     XCHG            ;de-pair now has crc, hl pointing into table.
  2666.     MOV    M,D        ;store high byte of crc..
  2667.     INR    H
  2668.     MOV    M,E        ;..and store low byte.
  2669.     DCR    H
  2670.     INX    H        ;move to next table entry
  2671.     INR    C        ;next index
  2672.     JRNZ    GLOOP
  2673.     RET
  2674.  
  2675. UPDCRC:
  2676.     PUSH    B        ;update 'crc'..
  2677.     PUSH    H        ;..accumulator..
  2678.     LHLD    CRCVAL        ;pick up partial remainder
  2679.     XCHG            ;de-pair now has partial
  2680.     MVI    B,0
  2681.     XRA    D
  2682.     MOV    C,A
  2683.     LXI    H,CRCTBL
  2684.     DAD    B
  2685.     MOV    A,M
  2686.     XRA    E
  2687.     MOV    D,A
  2688.     INR    H
  2689.     MOV    E,M
  2690.     XCHG
  2691.     SHLD    CRCVAL
  2692.     POP    H
  2693.     POP    B
  2694.     RET
  2695.  
  2696. FINCRC:
  2697.     LDA    C$U$A        ;reset user from 'requested'..
  2698.     CALL    SET$USR        ;..to 'current' area.
  2699.     LHLD    CRCVAL        ;put written-file 'crc' into..
  2700.     XCHG            ;..de-pair.
  2701.     LHLD    CRCVAL2        ;put read-file 'crc' and..
  2702.     CALL    CMPDEHL        ;..compare 'de/hl' for equality.
  2703.     JRNZ    BADCRC        ;if not zero, show copy-error message.
  2704.     CALL    ILPRT        ;if zero, show 'verified' message.
  2705.     DB    ' -- CRC Verified',0
  2706.     LDA    MFLAG        ;if not mass-copy mode, return..
  2707.     ORA    A        ;..to next 'ring' position.
  2708.     JNZ    FORWARD        ;else..
  2709.     CMA            ;..set 1st-time-thru flag..
  2710.     STA    FIRST$M        ;..and..
  2711.     JMP    M$LP        ;..get next file to copy, if one.
  2712.  
  2713. BADCRC:
  2714.     CALL    ERMSG
  2715.     DB    'Error on CRC compare',0
  2716.     JMP    FORWARD        ;move to next 'ring' position
  2717.  
  2718. ; w o r k h o r s e   r o u t i n e s
  2719.  
  2720. ; inline print of message
  2721.  
  2722. ILPRT:
  2723.     XTHL            ;save hl, get msg pointer.
  2724. ILPLP:
  2725.     MOV    A,M        ;get character
  2726.     INX    H        ;pt to next
  2727.     ANI    7FH        ;strip type bits
  2728.     JRZ    ILPLP1
  2729.     CALL    TYPE        ;show on console
  2730.     JR    ILPLP
  2731. ILPLP1:
  2732.     XTHL            ;set hl-pair and..
  2733.     RET            ;..return past message.
  2734.  
  2735. ; output 'crlf' to console
  2736.  
  2737. CRLF:
  2738.     MVI    A,CR
  2739.     CALL    TYPE
  2740.     MVI    A,LF
  2741.  
  2742. ; conout routine
  2743.  
  2744. TYPE:
  2745.     PUSH    PSW
  2746.     PUSH    B
  2747.     PUSH    D
  2748.     PUSH    H
  2749.     PUSH    PSW    ; check for flow control
  2750.     CALL    CST    ; BIOS console status
  2751.     ORA    A    ; 0 means nothing
  2752.     JRZ    TYPE1
  2753.     CALL    CIN    ; BIOS console input
  2754.     CPI    CTRLS    ; pause?
  2755.     JRNZ    TYPE1
  2756.     CALL    CIN    ; BIOS console input
  2757. TYPE1:
  2758.     POP    PSW    ; get char
  2759.     MOV    E,A
  2760.     MVI    C,WRCON
  2761.     CALL    BDOS
  2762.     POP    H
  2763.     POP    D
  2764.     POP    B
  2765.     POP    PSW
  2766.     RET
  2767.  
  2768. ; direct BIOS I/O
  2769. CST:
  2770.     LHLD    CPM$BASE+1    ; get BIOS Base Address
  2771.     MVI    L,6        ; console status routine
  2772.     PCHL            ; jump to it
  2773. CIN:
  2774.     LHLD    CPM$BASE+1    ; get BIOS Base Address
  2775.     MVI    L,9        ; console input routine
  2776.     PCHL
  2777.  
  2778. ; output 'crlf' to printer
  2779.  
  2780. LCRLF:
  2781.     MVI    A,CR
  2782.     CALL    LOUT
  2783.     MVI    A,LF
  2784.  
  2785. ; printer routine
  2786.  
  2787. LOUT:
  2788.     PUSH    PSW
  2789.     PUSH    B
  2790.     PUSH    D
  2791.     PUSH    H
  2792.     MOV    E,A
  2793.     MVI    C,LIST
  2794.     CALL    BDOS
  2795.     POP    H
  2796.     POP    D
  2797.     POP    B
  2798.     POP    PSW
  2799.     RET
  2800.  
  2801. ; crt clear-line function
  2802.  
  2803. CLR$L:
  2804.     MVI    A,CR
  2805.     CALL    TYPE
  2806.     MVI    B,30        ;blank # of characters on line
  2807.     MVI    A,' '
  2808. CL$LP:
  2809.     CALL    TYPE
  2810.     DJNZ    CL$LP
  2811.     RET
  2812.  
  2813. ; conin routine (waits for response)
  2814.  
  2815. KEYIN:
  2816.     MVI    C,RDCON
  2817.     CALL    BDOS
  2818.  
  2819. ; convert character in a-reg to upper case
  2820.  
  2821. UCASE:
  2822.     CPI    61H        ;less than small 'a'?
  2823.     RC            ;if so, no convert needed.
  2824.     CPI    7AH+1        ; >small 'z'?
  2825.     RNC            ;if so, ignore.
  2826.     ANI    5FH        ;otherwise convert
  2827.     RET
  2828.  
  2829. ; direct console input w/o echo (waits for input)
  2830.  
  2831. DKEYIN:
  2832.     CALL    CIN        ;get char from BIOS
  2833.     ANI    7FH        ;mask MSB
  2834.     JR    UCASE        ;capitalize
  2835.  
  2836. ; convert keyboard input to upper case
  2837.  
  2838. CONVERT:
  2839.     LXI    H,CMDBUF+1    ; 'current keyboard buffer length'..
  2840.     MOV    B,M        ;..to b-reg.
  2841.     MOV    A,B
  2842.     ORA    A        ;if zero length, skip conversion.
  2843.     JZ    COMCAN
  2844. CONVLP:
  2845.     INX    H        ;point at character to capitalize
  2846.     MOV    A,M
  2847.     CALL    UCASE
  2848.     MOV    M,A        ;put back into buffer
  2849.     DJNZ    CONVLP
  2850.     RET
  2851.  
  2852. ; fill buffer with 'spaces' with count in b-reg
  2853.  
  2854. FILL:
  2855.     MVI    M,' '        ;put in space character
  2856.     INX    H
  2857.     DJNZ    FILL        ;no, branch.
  2858.     RET
  2859.  
  2860. ; ignore leading spaces (ls) in buffer, length in c-reg.
  2861.  
  2862. UNSPACE:
  2863.     LDAX    D        ;get character
  2864.     CPI    ' '
  2865.     RNZ            ;not blank, a file is entered.
  2866.     INX    D        ;to next character
  2867.     DCR    C
  2868.     JZ    COMCAN        ;all spaces --> command recovery error
  2869.     JR    UNSPACE
  2870.  
  2871. ; check for legal cp/m filename character -- return with carry set if illegal
  2872.  
  2873. CKLEGAL:
  2874.     LDAX    D        ;get character from de-pair
  2875.     INX    D        ;point at next character
  2876.     CPI    ' '        ;less than space?
  2877.     RC            ;return carry if unpermitted character
  2878.     PUSH    H
  2879.         PUSH    B
  2880.     CPI    '['        ;if greater than 'z', exit with..
  2881.     JRNC    CKERR        ;..carry set.
  2882.     MVI    B,CHR$TEND-CHR$TBL
  2883.     LXI    H,CHR$TBL
  2884. CHR$LP:
  2885.     CMP    M  
  2886.     JRZ    CKERR
  2887.     INX    H
  2888.     DJNZ    CHR$LP
  2889.     ORA    A        ;clear carry for good character
  2890.     POP    B
  2891.     POP    H
  2892.     RET
  2893.  
  2894. CKERR:
  2895.     POP    B
  2896.     POP    H
  2897.     STC                 ;error exit with carry set
  2898.     RET
  2899.  
  2900. CHR$TBL:
  2901.     DB    ',',':',';','<','=','>'    ;invalid character table
  2902. CHR$TEND:
  2903.     DS    0
  2904.  
  2905. ; print file name in S$FCB
  2906.  
  2907. PRFNSX:
  2908.     PUSH    H        ;save regs
  2909.     PUSH    B
  2910.     JR    PRFNS0
  2911. PRFNS:
  2912.     PUSH    H        ;affect only PSW
  2913.     PUSH    B
  2914.     LXI    H,S$FCB+1
  2915. PRFNS0:
  2916.     CALL    PRFN        ;print file name
  2917.     POP    B        ;restore
  2918.     POP    H
  2919.     RET
  2920.  
  2921. ; print file name pted to by HL
  2922.  
  2923. PRFN:
  2924.     MVI    B,8        ;8 chars
  2925.     CALL    PRFNS1
  2926.     MVI    A,'.'
  2927.     CALL    TYPE
  2928.     MVI    B,3        ;file type and fall thru
  2929. PRFNS1:
  2930.     MOV    A,M        ;get char
  2931.     CALL    TYPE
  2932.     INX    H        ;pt to next
  2933.     DJNZ    PRFNS1
  2934.     RET
  2935.  
  2936. ; filename from 'ring' to 'sfcb'
  2937.  
  2938. RINGFCB:
  2939.     LHLD    RINGPOS        ;move name from ring to source 'fcb'
  2940.     LXI    D,S$FCB        ;place to move filename and..
  2941.     MVI    B,12        ;..amount to move.
  2942.  
  2943. ; move subroutine -- move b-reg # of bytes from hl-pair to de-pair
  2944.  
  2945. MOVE:
  2946.     MOV    A,M        ;get hl-pair referenced source byte
  2947.     ANI    7FH        ;strip cp/m 2.x attributes
  2948.     STAX    D        ;put to de-pair referenced destination
  2949.     INX    H        ;fix pointers for next search
  2950.     INX    D
  2951.     DJNZ    MOVE
  2952.     RET
  2953.  
  2954. ; initialize 'fcb' cp/m system fields (entry with hl-pair pointing to 'fcb')
  2955.  
  2956. INITFCB:
  2957.     MVI    B,4        ;fill ex, s1, s2, rc counters with zeros.
  2958. INITLP:
  2959.     MVI    M,0        ;put zero (null) in memory
  2960.     INX    H
  2961.     DJNZ    INITLP
  2962.     RET
  2963.  
  2964. ; disk system reset -- login requested drive
  2965.  
  2966. RESET:
  2967.     MVI    C,INQDISK    ;determine and..
  2968.     CALL    BDOS        ;..save..
  2969.     STA    C$DR        ;..current drive.
  2970.     MVI    C,RESETDK    ;reset system
  2971.     CALL    BDOS
  2972.     LDA    R$DR        ;make requested drive..
  2973. SET$DR:
  2974.     MOV    E,A        ;..current.
  2975.     MVI    C,LOGIN
  2976.     JMP    BDOS        ;return to caller
  2977.  
  2978. ; set/reset (or get) user area (call with binary user area in a-reg)
  2979.  
  2980. SET$USR:
  2981.     MOV    E,A        ; 0 --> 0, 1 --> 1, etc.
  2982. GET$USR:
  2983.     MVI    C,SGUSER
  2984.     JMP    BDOS        ;return to caller
  2985.  
  2986. ; compare de-pair to hl-pair and set flags accordingly
  2987.  
  2988. CMPDEHL:
  2989.     MOV    A,D        ;see if high bytes set flags
  2990.     CMP    H
  2991.     RNZ            ;return if not equal
  2992.     MOV    A,E
  2993.     CMP    L        ;low bytes set flags instead
  2994.     RET
  2995.  
  2996. ; shift hl-pair b-reg bits (-1) to right (divider routine)
  2997.  
  2998. SHIFTLP:
  2999.     DCR    B
  3000.     RZ
  3001.     MOV    A,H
  3002.     ORA    A
  3003.     RAR
  3004.     MOV    H,A
  3005.     MOV    A,L
  3006.     RAR
  3007.     MOV    L,A
  3008.     JR    SHIFTLP
  3009.  
  3010. ; decimal pretty print (h-reg contains msb; l-reg, the lsb.)
  3011.  
  3012. DECOUT:
  3013.     MVI    A,5        ;set leading space count
  3014.     STA    LDSP
  3015. DECOU1:
  3016.     PUSH    PSW
  3017.     PUSH    B
  3018.     PUSH    D
  3019.     PUSH    H
  3020.     LDA    LDSP        ;count down
  3021.     DCR    A
  3022.     STA    LDSP
  3023.     LXI    B,-10        ;radix
  3024.     LXI    D,-1
  3025. DECOU2:
  3026.     DAD    B        ;sets..
  3027.     INX    D
  3028.     JRC    DECOU2        ;..carry.    
  3029.     LXI    B,10
  3030.     DAD    B
  3031.     XCHG
  3032.     MOV    A,H
  3033.     ORA    L
  3034.     CNZ    DECOU1        ; (recursive)
  3035.     LDA    LDSP        ; any spaces?
  3036.     ORA    A        ; 0=none
  3037.     JRZ    DECOU4
  3038.     MOV    B,A        ; count in B
  3039.     MVI    A,' '
  3040. DECOU3:
  3041.     CALL    TYPE
  3042.     DJNZ    DECOU3
  3043.     XRA    A        ;A=0
  3044.     STA    LDSP        ;set flag
  3045. DECOU4:
  3046.     MOV    A,E
  3047.     ADI    '0'        ;make ascii
  3048.     CALL    TYPE
  3049.     POP    H
  3050.     POP    D
  3051.     POP    B
  3052.     POP    PSW
  3053.     RET
  3054.  
  3055. ; determine free storage remaining on selected drive
  3056.  
  3057. FRESTOR:
  3058.     MVI    C,INQDISK    ;determine current drive
  3059.     CALL    BDOS        ;returns 0 as a:, 1 as b:, etc.
  3060.     INR    A        ;make 1 --> a:, 2 --> b:, etc.
  3061.     STA    FCB
  3062.     MVI    C,GETPARM    ;current disk parameter block
  3063.     CALL    BDOS
  3064.     INX    H        ;bump to..
  3065.     INX    H
  3066.     MOV    A,M        ;..block shift factor.
  3067.     STA    BSHIFTF        ; 'bsh'
  3068.     INX    H        ;bump to..
  3069.     MOV    A,M        ;..block mask.
  3070.     STA    B$MASK        ; 'blm'
  3071.     INX    H        ;bump to..
  3072.     INX    H        ;..get..
  3073.     MOV    E,M        ;..maximum block number..
  3074.     INX    H        ;..double..
  3075.     MOV    D,M        ;..byte.
  3076.     XCHG
  3077.     SHLD    B$MAX        ; 'dsm'
  3078.     MVI    C,INQALC    ;address of cp/m allocation vector
  3079.     CALL    BDOS
  3080.     XCHG            ;get its length
  3081.     LHLD    B$MAX
  3082.     INX    H
  3083.     LXI    B,0        ;initialize block count to zero
  3084. GSPBYT:
  3085.     PUSH    D        ;save allocation address
  3086.     LDAX    D
  3087.     MVI    E,8        ;set to process 8 bits (blocks)
  3088. GSPLUP:
  3089.     RAL            ;test bit
  3090.     JRC    NOT$FRE
  3091.     INX    B
  3092. NOT$FRE:
  3093.     MOV    D,A        ;save bits
  3094.     DCX    H
  3095.     MOV    A,L
  3096.     ORA    H    
  3097.     JRZ    END$ALC        ;quit if out of blocks
  3098.     MOV    A,D        ;restore bits
  3099.     DCR    E        ;count down 8 bits
  3100.     JRNZ    GSPLUP        ;branch to do another bit
  3101.     POP    D        ;bump to next count..
  3102.     INX    D        ;..of allocation vector.
  3103.     JR    GSPBYT        ;process it
  3104.  
  3105. END$ALC:
  3106.     POP    D        ;clear alloc vector pointer from stack
  3107.     MOV    L,C        ;copy # blocks to hl-pair
  3108.     MOV    H,B
  3109.     LDA    BSHIFTF        ;get block shift factor
  3110.     SUI    3        ;convert from sectors to thousands (k)
  3111.     JRZ    PRT$FRE        ;skip shifts if 1k blocks
  3112. FREK$LP:
  3113.     DAD    H        ;multiply blocks by k-bytes per block
  3114.     DCR    A        ;multiply by 2, 4, 8, or 16.
  3115.     JRNZ    FREK$LP
  3116. PRT$FRE:
  3117.     SHLD    DISKSP        ;save disk space
  3118.     RET
  3119. ;
  3120. ;  Print free space on disk
  3121. ;
  3122. PRINT$FRE:
  3123.     CALL    ERMSG        ;position and set flags
  3124.     DB    0
  3125.     LHLD    DISKSP
  3126.     CALL     DECOUT        ; # of free k-bytes in hl-pair
  3127.     CALL    ILPRT
  3128.     DB    'K Bytes on Disk',0
  3129.     RET
  3130.  
  3131. ;*
  3132. ;*  ZDNAME -- LOAD THE CONTENTS OF THE NAMES.DIR FILE INTO THE MEMORY
  3133. ;*    BUFFER PTED TO BY HL
  3134. ;*    ON ENTRY, HL PTS TO THE MEMORY BUFFER EXTENDING TO THE BASE OF
  3135. ;*        THE BDOS
  3136. ;*    ON EXIT, BC IS THE NUMBER OF VALID ENTRIES, A IS THE ERROR FLAG (A=0FFH
  3137. ;*        AND NZ IF NO ERROR, A=0 AND Z IF ERROR)
  3138. ;*            ERRORS MAY BE EITHER MEMORY OVERFLOW OR NAMES.DIR
  3139. ;*            NOT FOUND
  3140. ;*    EACH NAMES.DIR ENTRY IS 10 BYTES LONG, STRUCTURED AS FOLLOWS:
  3141. ;*        BYTE 0: DISK NUMBER (A=0)
  3142. ;*        BYTE 1: USER NUMBER
  3143. ;*        BYTES 2-9: DIRECTORY NAME, 8 CHARS MAX, <SP> FILL AT END
  3144. ;*
  3145. ZDNAME:
  3146.     PUSH    D    ; SAVE UNCHANGED REG
  3147.     SHLD    DIRNAME    ; SAVE PTR TO BUFFER
  3148.     LXI    H,DNFILE    ; PT TO NAMES.DIR FILE NAME
  3149.     LXI    D,S$FCB+1    ; PT TO FCB
  3150.     MVI    B,11    ; 11 BYTES
  3151.     CALL    MOVE
  3152.     XCHG        ; HL PTS TO S$FCB+12
  3153.     CALL    INITFCB    ; INIT FCB
  3154.     LXI    H,S$FCB    ; PT TO FCB
  3155.     MVI    M,0    ; ZERO DRIVE
  3156.     XCHG        ; DE PTS TO FCB
  3157.     CALL    FFIND    ; LOOK FOR NAMES.DIR FILE
  3158.     JZ    DIRNERR    ; FILE NOT FOUND ERROR
  3159. ;
  3160. ;  FOUND NAMES.DIR, SO LOAD IT
  3161. ;
  3162.     LDA    Z$U$A    ; GET USER
  3163.     MOV    C,A
  3164.     LDA    Z$DR    ; GET DISK
  3165.     MOV    B,A
  3166.     CALL    SLOGIN    ; LOG INTO IT
  3167.     LXI    H,S$FCB+12
  3168.     CALL    INITFCB
  3169.     LXI    D,S$FCB    ; PT TO FCB
  3170.     XRA    A
  3171.     STAX    D    ; ZERO FCB DISK
  3172.     STA    S$FCB+32    ; ZERO CURRENT RECORD
  3173.     CALL    FIOPEN    ; OPEN FOR INPUT
  3174.     ORA    A    ; ERROR?
  3175.     JRNZ    ZDNA3
  3176. ;
  3177. ;  LOAD NAMES.DIR FILE
  3178. ;
  3179.     MVI    C,0    ; SET ENTRY COUNT
  3180.     LDA    NDNAMES    ; GET MAX NUMBER OF NAMES
  3181.     MOV    B,A    ; ... IN B
  3182. ZDNA1:
  3183.     LXI    H,ENTRY    ; PT TO ENTRY BUFFER
  3184.     CALL    GETNAME    ; GET NAME FROM DISK
  3185.     JRNZ    ZDNA3    ; DONE?
  3186.     LDA    ENTRY+2    ; LOOK AT FIRST LETTER OF DIR NAME
  3187.     ORA    A    ; NO ENTRY?
  3188.     JZ    ZDNA2
  3189.     LHLD    DIRNAME    ; PT TO BUFFER ENTRY
  3190.     LXI    D,ENTRY    ; PT TO NEW ENTRY
  3191.     INR    C    ; INCREMENT ENTRY COUNTER
  3192.     PUSH    B    ; SAVE COUNTERS
  3193.     XCHG        ; HL PTS TO NEW ENTRY, DE PTS TO DEST
  3194.     MOV    A,M    ; GET DISK NUMBER
  3195.     STAX    D    ; STORE DISK NUMBER
  3196.     INX    H    ; PT TO USER NUMBER
  3197.     INX    D
  3198.     MOV    A,M    ; GET USER
  3199.     STAX    D    ; PUT USER
  3200.     MVI    B,8    ; AT MOST 8 MORE BYTES
  3201. ZDNA1A:
  3202.     INX    H    ; PT TO NEXT BYTE
  3203.     INX    D
  3204.     MOV    A,M    ; GET NEXT BYTE
  3205.     ORA    A    ; END OF NAME?
  3206.     JRZ    ZDNA1B    ; <SP> FILL
  3207.     STAX    D    ; PUT BYTE
  3208.     DJNZ    ZDNA1A
  3209.     INX    D    ; PT TO FIRST BYTE OF NEXT ENTRY
  3210.     JR    ZDNA1C
  3211. ZDNA1B:
  3212.     MVI    A,' '    ; <SP> FILL
  3213.     STAX    D    ; PLACE <SP>
  3214.     INX    D    ; PT TO NEXT
  3215.     DJNZ    ZDNA1B
  3216. ZDNA1C:
  3217.     POP    B    ; RESTORE COUNTERS
  3218.     XCHG        ; HL PTS TO NEXT BUFFER POSITION
  3219.     SHLD    DIRNAME    ; SAVE PTR
  3220. ;
  3221. ;  CONTINUE LOOPING
  3222. ;
  3223. ZDNA2:
  3224.     DJNZ    ZDNA1
  3225. ;
  3226. ;  COMPLETION EXIT
  3227. ;
  3228. ZDNA3:
  3229.     PUSH    B    ; SAVE COUNTER
  3230.     CALL    DLOGIN    ; RESTORE USER/DISK
  3231.     POP    B    ; RESTORE COUNTER IN C
  3232.     MVI    A,0FFH    ; SET NO ERROR
  3233.     ORA    A    ; SET FLAGS
  3234.     STA    DNLOAD    ; SET LOAD FLAG
  3235.     POP    D    ; RESTORE DE
  3236.     RET
  3237.  
  3238. ;*
  3239. ;*  ZDNFIND -- SCAN FOR POSSIBLE DISK DIRECTORY NAME
  3240. ;*    THIS ROUTINE EXAMINES THE DIR: PREFIX FOR EITHER A DIRECTORY NAME
  3241. ;*        OR THE DU FORM
  3242. ;*    ON ENTRY, HL PTS TO DIRECTORY NAME ENDING IN ANY VALID DELIMITER
  3243. ;*    RETURN DISK IN B, USER IN C, NZ IF OK, HL PTS TO COLON
  3244. ;*    DE IS NOT AFFECTED
  3245. ;*
  3246. ZDNFIND:
  3247.     PUSH    D    ; SAVE DE
  3248.     SHLD    DIRNAME    ; SAVE DIRECTORY NAME AWAY
  3249.     MVI    C,INQDISK    ; SAVE CURRENT POSITION
  3250.     CALL    BDOS
  3251.     STA    DISK
  3252.     STA    T$DR
  3253.     MVI    E,GET
  3254.     CALL    GET$USR
  3255.     STA    USER
  3256.     LHLD    DIRNAME    ; PT TO NAME
  3257.     JMP    SVDISK    ; CHECK DU FORM FIRST
  3258. ;
  3259. ;  LOOK FOR DIR: FORM
  3260. ;
  3261. DIRNXX:
  3262. ;
  3263. ;  SCAN MEMORY-RESIDENT BUFFER IF ONE IS AVAILABLE
  3264. ;
  3265.     LDA    T$DR    ; SET DISK
  3266.     STA    DISK
  3267.     LHLD    NDRADR    ; GET ADDRESS
  3268.     MOV    A,L    ; CHECK FOR ZERO
  3269.     ORA    H
  3270.     CNZ    NBSCAN    ; SCAN BUFFER
  3271.     JRNZ    NAMEF    ; FOUND
  3272.     LXI    H,BUFENTRY-2    ; PT TO BYTE BEFORE ENTRY COUNT OF DIR BUFFER
  3273.     LDA    DNLOAD    ; LOADED?
  3274.     ORA    A    ; 0=NO
  3275.     CNZ    NBSCAN    ; SCAN BUFFER
  3276.     JRNZ    NAMEF
  3277.     POP    D    ; RESTORE DE
  3278.     XRA    A    ; NOT FOUND
  3279.     RET
  3280. NAMEF:
  3281.     POP    D    ; RESTORE DE
  3282.     MVI    A,0FFH    ; FOUND
  3283.     ORA    A    ; DISK/USER IN B/C
  3284.     RET
  3285.  
  3286. ;
  3287. ;  SCAN MEMORY-RESIDENT BUFFER PTED TO BY HL
  3288. ;    ON EXIT, A=0 AND ZERO FLAG IF NOT FOUND
  3289. ;        IF FOUND, B=DISK AND C=USER
  3290. ;
  3291. NBSCAN:
  3292.     INX    H    ; PT TO ENTRY COUNT
  3293.     MOV    A,M    ; GET ENTRY COUNT
  3294.     ORA    A    ; CHECK FOR NO ENTRIES
  3295.     RZ        ; ABORT IF NO ENTRIES
  3296.     MOV    B,A    ; ENTRY COUNT IN B
  3297.     INX    H    ; PT TO FIRST ENTRY
  3298.     XCHG        ; DE PTS TO FIRST ENTRY IN MEMORY
  3299. ;
  3300. ;  MAIN SCANNING LOOP FOR MEMORY-RESIDENT BUFFER
  3301. ;
  3302. NBS0:
  3303.     LHLD    DIRNAME    ; HL PTS TO DIR NAME
  3304.     PUSH    D    ; SAVE PTR TO CURRENT MEMORY ENTRY
  3305.     MVI    C,8    ; SCAN UP TO 8 BYTES
  3306.     INX    D    ; SKIP DISK
  3307.     INX    D    ; SKIP USER
  3308.     XCHG        ; SWITCH PTRS
  3309. NBS1:
  3310.     LDAX    D    ; GET CHAR IN BUFFER
  3311.     CPI    ':'    ; COLON?
  3312.     JRNZ    NBS1A
  3313.     MVI    A,' '    ; SUBSTITUTE SPACE FOR IT
  3314. NBS1A:
  3315.     CMP    M    ; COMPARE AGAINST TARGET NAME
  3316.     JRNZ    NBS2
  3317.     INX    H    ; PT TO NEXT
  3318.     INX    D
  3319.     DCR    C    ; COUNT DOWN
  3320.     JRNZ    NBS1
  3321.     JR    NBS3    ; FOUND
  3322. NBS2:
  3323.     POP    H    ; GET PTR TO CURRENT BUFFER ENTRY
  3324.     LXI    D,10    ; SKIP TO NEXT ENTRY
  3325.     DAD    D    ; HL PTS TO NEXT ENTRY
  3326.     XCHG        ; DE PTS TO NEXT ENTRY
  3327.     DJNZ    NBS0
  3328. ;
  3329. ;  ENTRY NOT FOUND
  3330. ;
  3331.     XRA    A    ; A=0 AND ZERO FLAG SET
  3332.     RET
  3333. ;
  3334. ;  ENTRY FOUND
  3335. ;
  3336. NBS3:
  3337.     POP    H    ; GET PTR TO ENTRY
  3338.     MOV    B,M    ; DISK IN B
  3339.     INX    H    ; PT TO USER
  3340.     MOV    C,M    ; USER IN C
  3341.     MVI    A,0FFH    ; SET FOUND FLAG
  3342.     ORA    A
  3343.     RET
  3344.  
  3345. ;
  3346. ;  LOOK AT START OF DU: FORM
  3347. ;    ON ENTRY, HL PTS TO FIRST CHAR OF DIRECTORY NAME
  3348. ;
  3349. SVDISK:
  3350.     LDA    MDISK    ; GET MAX DISK
  3351.     INR    A    ; +1 FOR LATER COMPARE
  3352.     MOV    B,A    ; ... IN B
  3353.     MOV    A,M    ; GET DISK LETTER
  3354.     CPI    'A'    ; DIGIT?
  3355.     JRC    USERCK    ; IF NO DIGIT, MUST BE USER OR COLON
  3356.     SUI    'A'    ; CONVERT TO NUMBER
  3357.     CMP    B    ; LIMIT?
  3358.     JNC    DIRNXX    ; NAME IF OUT OF LIMIT
  3359.     STA    DISK    ; SAVE DISK
  3360.     INX    H    ; PT TO NEXT CHAR
  3361. ;
  3362. ;  CHECK FOR USER
  3363. ;
  3364. USERCK:
  3365.     MOV    A,M    ; GET POSSIBLE USER NUMBER
  3366.     CPI    ':'    ; NO USER NUMBER
  3367.     JRZ    DIRNX    ; EXIT IF SO
  3368.     CPI    ' '    ; NO USER NUMBER
  3369.     JRZ    DIRNX
  3370.     ORA    A
  3371.     JRZ    DIRNX
  3372.     XRA    A    ; ZERO USER NUMBER
  3373.     MOV    B,A    ; B=ACCUMULATOR FOR USER NUMBER
  3374. USRLOOP:
  3375.     MOV    A,M    ; GET DIGIT
  3376.     INX    H    ; PT TO NEXT
  3377.     CPI    ':'    ; DONE?
  3378.     JRZ    USRDN
  3379.     CPI    ' '    ; DONE?
  3380.     JRZ    USRDN
  3381.     SUI    '0'    ; CONVERT TO BINARY
  3382.     JC    DIRNXX    ; NAME IF USER NUMBER ERROR
  3383.     CPI    10
  3384.     JNC    DIRNXX
  3385.     MOV    C,A    ; NEXT DIGIT IN C
  3386.     MOV    A,B    ; OLD NUMBER IN A
  3387.     ADD    A    ; *2
  3388.     ADD    A    ; *4
  3389.     ADD    B    ; *5
  3390.     ADD    A    ; *10
  3391.     ADD    C    ; *10+NEW DIGIT
  3392.     MOV    B,A    ; RESULT IN B
  3393.     JR    USRLOOP
  3394. USRDN:
  3395.     MOV    A,B    ; GET NEW USER NUMBER
  3396.     CPI    32    ; WITHIN RANGE?
  3397.     JNC    DIRNXX    ; NAME IF OUT OF RANGE
  3398.     STA    USER    ; SAVE IN FLAG
  3399. ;
  3400. ;  VALID EXIT -- FOUND IT, SO LOAD BC AND EXIT FLAG; ON ENTRY, HL PTS TO :
  3401. ;
  3402. DIRNX:
  3403.     LDA    USER    ; RETURN USER IN C, DISK IN B
  3404.     MOV    C,A
  3405.     LDA    DISK
  3406.     MOV    B,A
  3407.     MVI    A,0FFH    ; SET NO ERROR
  3408.     ORA    A    ; SET FLAGS
  3409.     POP    D    ; RESTORE DE
  3410.     RET
  3411. ;
  3412. ;  INVALID EXIT -- NOT FOUND OR ERROR
  3413. ;    NO VALID RETURN PARAMETERS (BC, HL)
  3414. ;
  3415. DIRNERR:
  3416.     XRA    A    ; ERROR CODE
  3417.     STA    DNLOAD    ; SET LOAD FLAG TO NO LOAD
  3418.     POP    D    ; RESTORE DE
  3419.     RET
  3420.  
  3421. ;
  3422. ;  GET NAME FROM NAMES.DIR INTO BUFFER PTED TO BY HL
  3423. ;    DO NOT AFFECT BC OR HL; RET W/NZ IF ERROR
  3424. ;
  3425. GETNAME:
  3426.     PUSH    B    ; SAVE BC
  3427.     PUSH    H    ; SAVE HL
  3428.     CALL    FGET    ; GET DISK LETTER
  3429.     JRNZ    GNERR    ; ERROR?
  3430.     SUI    'A'    ; CONVERT TO NUMBER
  3431.     MOV    M,A    ; STORE IT
  3432.     INX    H    ; PT TO NEXT
  3433.     MVI    B,10    ; GET USER AND DIRECTORY NAME
  3434. GETN1:
  3435.     CALL    FGET    ; GET BYTE
  3436.     JRNZ    GNERR    ; ERROR?
  3437.     MOV    M,A    ; STORE IT
  3438.     INX    H    ; PT TO NEXT
  3439.     DJNZ    GETN1
  3440.     XRA    A    ; OK
  3441. GNERR:
  3442.     POP    H    ; RESTORE HL
  3443.     POP    B    ; RESTORE BC
  3444.     RET
  3445.  
  3446. ;
  3447. ;  OPEN FILE FOR GET
  3448. ;
  3449. FIOPEN:
  3450.     PUSH    D
  3451.     MVI    C,OPEN    ; OPEN FILE
  3452.     CALL    BDOS
  3453.     POP    D
  3454. FIO1:
  3455.     MVI    C,READ    ; READ FIRST BLOCK
  3456.     CALL    BDOS
  3457.     LXI    H,TBUF    ; SET PTR
  3458.     SHLD    FIPTR
  3459.     RET
  3460. ;
  3461. ;  GET NEXT BYTE FROM FILE
  3462. ;
  3463. FGET:
  3464.     PUSH    H    ; SAVE REGS
  3465.     PUSH    D
  3466.     PUSH    B
  3467.     LHLD    FIPTR    ; PT TO NEXT CHAR
  3468.     MOV    A,M    ; GET IT
  3469.     STA    FICHAR    ; SAVE IT
  3470.     INX    H    ; PT TO NEXT
  3471.     SHLD    FIPTR    ; SET PTR
  3472.     LXI    D,TBUF+80H    ; END OF BUFFER?
  3473.     CALL    CMPDEHL    ; COMPARE
  3474.     JRNZ    FGETD    ; DONE IF NOT
  3475.     LXI    D,S$FCB    ; PT TO FCB
  3476.     CALL    FIO1    ; READ BLOCK AND SET PTR
  3477.     ORA    A    ; SET FLAG (NZ = ERROR)
  3478.     JR    FGETD1
  3479. FGETD:
  3480.     XRA    A    ; NO ERROR (Z)
  3481. FGETD1:
  3482.     POP    B    ; GET REGS
  3483.     POP    D
  3484.     POP    H
  3485.     LDA    FICHAR    ; GET CHAR
  3486.     RET
  3487.  
  3488. ; message routines
  3489.  
  3490. ; print VFILER banner
  3491. BANNER:
  3492.     CALL    CLS        ;clear screen
  3493.     LXI    H,BANADR
  3494.     CALL    GOTOXY
  3495.     CALL    ILPRT        ;print banner
  3496.     DB    'VFILER, Version '
  3497.     DB    VERS/10+'0','.',(VERS MOD 10)+'0'
  3498.      IF    Z80
  3499.     DB    '  [Z80  Code]'
  3500.      ELSE
  3501.     DB    '  [8080 Code]'
  3502.      ENDIF
  3503.     DB    0
  3504.     RET
  3505. ; home the cursor
  3506. CUR$FIRST:
  3507.     LXI    H,CURHOME    ; HOME ADDRESS
  3508.     SHLD    CURAT        ; SET CURSOR POSITION
  3509.     JMP    GOTOXY
  3510. ; last file position
  3511. CUR$LAST:
  3512.     LHLD    RINGPOS        ; ADVANCE
  3513.     SHLD    LOCPOS        ; SET LOCAL POSITION
  3514. CL0:
  3515.     LXI    D,13
  3516.     DAD    D
  3517.     XCHG
  3518.     LHLD    LOCEND        ; END OF LOCAL RING?
  3519.     CALL    CMPDEHL
  3520.     RZ
  3521.     XCHG            ; NEW POSITION
  3522.     SHLD    LOCPOS
  3523.     PUSH    H        ; SAVE POSITION
  3524.     CALL    CUR$NEXT    ; ADVANCE CURSOR
  3525.     POP    H        ; GET POSITION
  3526.     JR    CL0
  3527. ; advance the cursor
  3528. CUR$NEXT:
  3529.     LHLD    CURAT        ; COMPUTE NEW POSITION
  3530.     MOV    A,L        ; CHECK FOR NEW LINE
  3531.     ADI    19        ; SIZE OF EACH ENTRY
  3532.     CPI    70
  3533.     JRNC    CN1        ; ADVANCE TO NEXT LINE
  3534.     MOV    L,A        ; NEW POSITION
  3535.     SHLD    CURAT
  3536.     JMP    GOTOXY
  3537. CN1:
  3538.     MOV    A,H        ; GET LINE
  3539.     LXI    H,CURHOME    ; GET COL
  3540.     MOV    H,A        ; SET LINE AND FALL GO TO CUR$DOWN
  3541.     SHLD    CURAT
  3542.     JR    CUR$DOWN
  3543. ; back up the cursor
  3544. CUR$BACK:
  3545.     LXI    H,CURHOME    ; GET HOME
  3546.     XCHG            ; ... IN DE
  3547.     LHLD    CURAT
  3548.     CALL    CMPDEHL        ; COMPARE
  3549.     JRZ    CUR$LAST    ; GOTO END IF LAST
  3550.     MOV    A,L        ; CHECK FOR FIRST COL
  3551.     CMP    E
  3552.     JRZ    CB1
  3553.     SUI    19        ; BACK UP ONE COL
  3554.     MOV    L,A
  3555.     SHLD    CURAT        ; NEW POS
  3556.     JMP    GOTOXY
  3557. CB1:
  3558.     MOV    A,E        ; GET HOME COL
  3559.     ADI    19*3        ; GET LAST COL
  3560.     MOV    L,A
  3561.     DCR    H        ; PREV LINE
  3562.     SHLD    CURAT
  3563.     JMP    GOTOXY
  3564. ; move cursor down one line
  3565. CUR$DOWN:
  3566.     LXI    H,CURHOME    ; GET HOME ADDRESS
  3567.     MOV    B,H        ; LINE IN B
  3568.     LHLD    CURAT        ; GET CURRENT ADDRESS
  3569.     INR    H        ; MOVE DOWN
  3570.     MOV    A,H        ; CHECK FOR TOO FAR
  3571.     SUB    B
  3572.     CPI    EPS/4
  3573.     JRNC    CD1
  3574.     SHLD    CURAT        ; OK, SO SET POSITION
  3575.     JMP    GOTOXY
  3576. CD1:
  3577.     MOV    A,L        ; GET COL
  3578.     LXI    H,CURHOME
  3579.     MOV    L,A
  3580.     SHLD    CURAT
  3581.     JMP    GOTOXY
  3582. ; refresh screen
  3583. REFRESH:
  3584.     LHLD    CURAT    ; SAVE CURSOR AND RING POSITIONS
  3585.     SHLD    SCURAT
  3586.     LHLD    RINGPOS
  3587.     SHLD    SRINGPOS
  3588.     CALL    BANNER    ; PRINT BANNER
  3589.     CALL    NEWPOS    ; DISPLAY FILES
  3590.     LXI    H,CPMADR    ; COMMAND PROMPT MESSAGE
  3591.     CALL    GOTOXY
  3592.     CALL    ILPRT        ; PROMPT WITH DRIVE PREFIX
  3593. LOG$DU$MSG:
  3594.     DB    '   :  '
  3595.     DB    'Command (? for Help)?',0
  3596.     LXI    H,SDMADR    ; SCREEN DIRECTORY MESSAGE
  3597.     CALL    GOTOXY
  3598.     CALL    ILPRT
  3599.     DB    '-- Screen Directory --',0
  3600.     LXI    H,FNADR        ; PT TO WHERE FILE NAME IS PRINTED
  3601.     MVI    L,1        ; COL 1 FOR THIS MESSAGE
  3602.     CALL    GOTOXY        ; GO THERE
  3603.     CALL    ILPRT
  3604.     DB    'Current File:',0
  3605.     LHLD    SCURAT        ; RESTORE CURSOR AND RING POSITIONS
  3606.     SHLD    CURAT
  3607.     LHLD    SRINGPOS
  3608.     SHLD    RINGPOS
  3609.     CALL    SETCUR        ; RESTORE CURSOR ON SCREEN
  3610.     RET
  3611. ; refresh file display
  3612. NEWPOS:
  3613.     CALL    CUR$FIRST    ; POSITION CURSOR AT FIRST POSITION
  3614.     MVI    B,EPS/4        ; # LINES
  3615. NEWP0:
  3616.     PUSH    B
  3617.     CALL    EREOL        ; ERASE TO EOL
  3618.     LHLD    CURAT        ; GET ADDRESS OF CURSOR
  3619.     INR    H        ; NEXT LINE
  3620.     SHLD    CURAT
  3621.     CALL    GOTOXY
  3622.     POP    B
  3623.     DJNZ    NEWP0
  3624.     CALL    CUR$FIRST    ; POSITION CURSOR AT FIRST POSITION
  3625.     LHLD    LOCBEG        ; PT TO FIRST FILE NAME
  3626.     SHLD    LOCPOS        ; SAVE LOCAL POSITION
  3627. NEWP1:
  3628.     LHLD    LOCEND        ; AT END?
  3629.     XCHG
  3630.     LHLD    LOCPOS
  3631.     CALL    CMPDEHL
  3632.     JZ    CUR$FIRST    ; POSITION AT FIRST ENTRY AND RETURN
  3633.     MVI    B,4        ; 4 SPACE
  3634.     MVI    A,' '
  3635. T4:
  3636.     CALL    TYPE
  3637.     DJNZ    T4
  3638.     PUSH    H        ; SAVE CURRENT LOCAL POSITION IN RING
  3639.     INX    H        ; PT TO FILE NAME
  3640.     CALL    PRFN        ; PRINT FILE NAME
  3641.     MOV    A,M        ; PRINT TAG
  3642.     CALL    TYPE
  3643.     POP    H        ; GET CURRENT LOCAL POSITION
  3644.     LXI    D,13
  3645.     DAD    D
  3646.     SHLD    LOCPOS
  3647.     CALL    CUR$NEXT    ; ADVANCE CURSOR
  3648.     JR    NEWP1
  3649. ; position cursor at CURAT
  3650. SETCUR:
  3651.     LHLD    CURAT
  3652.     CALL    GOTOXY
  3653.     CALL    ILPRT
  3654.     DB    '-->',0
  3655.     RET
  3656. ; clear cursor
  3657. CLRCUR:
  3658.     LHLD    CURAT
  3659.     CALL    GOTOXY
  3660.     CALL    ILPRT
  3661.     DB    '   ',0
  3662.     RET
  3663. ; command prompt
  3664. CPRMPT:
  3665.     LXI    H,CPADR    ; GET ADDRESS
  3666. MPRINT:
  3667.     PUSH    H    ; SAVE ADDRESS
  3668.     CALL    GOTOXY
  3669.     CALL    EREOL    ; ERASE TO EOL
  3670.     POP    H    ; GET ADDRESS
  3671.     CALL    GOTOXY    ; POSITION CURSOR
  3672.     JMP    ILPRT    ; PRINT MESSAGE AND RETURN
  3673. ; working message
  3674. WORKMSG:
  3675.     CALL    ERMSG
  3676.     DB    'Working ...',0
  3677.     RET
  3678. ; error message
  3679. ERMSG:
  3680.     MVI    A,0FFH    ; SET ERROR MESSAGE FLAG
  3681.     STA    ERMFLG
  3682.     LXI    H,ERADR    ; GET ADDRESS
  3683.     JR    MPRINT
  3684. ; print file size info
  3685. FSNOTE:
  3686.     CALL    ERMSG    ; USE THIS ROUTINE
  3687.     DB    'File Size of ',0
  3688.     RET
  3689. ; position for file size print
  3690. ATFS:
  3691.     LXI    H,FSADR+13    ; POSITION FOR PRINT OF FILE SIZE
  3692.     JMP    GOTOXY
  3693. ; clear error message
  3694. ERCLR:
  3695.     XRA    A    ; CLEAR FLAG
  3696.     STA    ERMFLG
  3697.     LXI    H,ERADR    ; POSITION
  3698.     CALL    GOTOXY
  3699.     JMP    EREOL    ; ERASE TO EOL
  3700. ; position at command prompt and clear it
  3701. ATCMD:
  3702.     LXI    H,CPADR    ; POSITION
  3703.     CALL    GOTOXY
  3704.     CALL    EREOL    ; CLEAR MESSAGE
  3705.     LXI    H,CPADR    ; REPOSITION
  3706.     JMP    GOTOXY
  3707. ; position at bottom of screen and prompt for continuation
  3708. BOTTOM:
  3709.     LXI    H,BOTADR    ; POSITION
  3710.     CALL    GOTOXY
  3711.     CALL    ILPRT
  3712.     DB    'Strike Any Key to Continue -- ',0
  3713.     JMP    KEYIN
  3714.  
  3715.  
  3716. ; s t o r a g e
  3717.  
  3718. ; initialized
  3719.  
  3720. HEADMSG:
  3721.      DB    'File: ',0
  3722. MOREHELP:
  3723.      DB    'HELP VFILER',0    ;HELP Command for further info
  3724. HELPFCB:
  3725.      DB    0,'HELP    COM'
  3726. FILERCMD:
  3727.      DB    ';VFILER '
  3728. FILE$D:
  3729.      DB    'x'
  3730. FILE$U:
  3731.      DB    'xx'
  3732.      DB    ' W'    ;WAIT option
  3733.      DB    0
  3734. JOKER:
  3735.      DB    '???????????'    ; *.* equivalent
  3736. FIRST$M:
  3737.      DB    FALSE        ; 1st time thru in mass-copy mode
  3738. MFLAG:
  3739.      DB    TRUE        ;multiple file copy flag --> 0 for mass copy
  3740. TAG$TOT:
  3741.      DW    0        ;summation of tagged file sizes
  3742. CMDBUF:
  3743.      DB    32,0        ;command buffer maximum length, usage, and..
  3744.  
  3745. ; uninitialized
  3746.  
  3747.      DS    100        ;..storage for buffer and local stack.
  3748. STACK:
  3749.      DS    2        ;cp/m's stack pointer stored here
  3750. B$MAX:
  3751.      DS    2        ;highest block number on drive
  3752. B$MASK:
  3753.      DS    1        ;sec/blk - 1
  3754. BSHIFTF:
  3755.      DS    1        ; # of shifts to multiply by sec/blk
  3756. BUF$PT:
  3757.      DS    2        ;copy buffer current pointer..
  3758. BUFSTART:
  3759.      DS    2        ;..and begin pointer.
  3760. CANFLG:
  3761.      DS    1        ;no-file-found cancel flag
  3762. C$DR:
  3763.      DS    1        ; 'current drive'
  3764. CHARCNT:
  3765.      DS    1        ;character count for tab expansion
  3766. CON$LST:
  3767.      DS    1        ;bdos function storage
  3768. CRCTBL:
  3769.      DS    512        ;tables for 'crc' calculations
  3770. CRCVAL:
  3771.      DS    2        ; 2-byte 'crc' value of working file and..
  3772. CRCVAL2:
  3773.      DS    2        ;..of finished source read-file.
  3774. C$U$A:
  3775.      DS    1        ; 'current user area'
  3776. CURAT:
  3777.      DS    2        ;current cursor position
  3778. D$FCB:
  3779.      DS    33        ;fcb for destination file/new name if rename
  3780. DIRNAME:
  3781.      DS    2        ;ptr to DIR prefix
  3782. DISK:
  3783.      DS    1        ;selected disk for ZDNAME
  3784. DISKSP:
  3785.      DS    2        ;space remaining on disk
  3786. DNLOAD:
  3787.      DS    1        ;NAMES.DIR loaded flag
  3788. DRLET:
  3789.      DS    1        ;scratch for drive letter
  3790. ENTRY:
  3791.      DS    11        ;scratch for ZDNAME/ZDNFIND
  3792. EOFLAG:
  3793.      DS    1        ;file copy loop 'eof' flag
  3794. ERMFLG:
  3795.      DS    1        ;error message present flag
  3796. FICHAR:
  3797.      DS    1        ;byte-oriented input char
  3798. FIPTR:
  3799.      DS    2        ;byte-oriented input ptr
  3800. FSDFLG:
  3801.      DS    1        ;display file size flag (yes/no)
  3802. FS$FLG:
  3803.      DS    1        ;tag total versus file size flag
  3804. HELPFLG:
  3805.      DS    1        ;is HELP available externally?  0=No
  3806. LDSP:
  3807.      DS    1        ;leading space count for DECOUT
  3808. LPSCNT:
  3809.      DS    1        ;lines-per-screen for 'view'
  3810. LOCBEG:
  3811.      DS    2        ;local beginning of ring
  3812. LOCEND:
  3813.      DS    2        ;local end of ring
  3814. LOCPOS:
  3815.      DS    2        ;local ring position (temp)
  3816. MAXDR:
  3817.      DS    1        ;max driver letter
  3818. MDFLG:
  3819.      DS    1        ;mass delete verify flag
  3820. O$USR:
  3821.      DS    1        ;store initial user area for exit
  3822. R$DR:
  3823.      DS    1        ; 'requested drive'
  3824. RCNT:
  3825.      DS    2        ; # of records in file and..
  3826. REC$CNT:
  3827.      DS    2        ;..currently in ram buffer.
  3828. REC$MAX:
  3829.      DS    2        ;maximum 128-byte record capacity of buffer
  3830. RING:
  3831.      DS    2        ;ptr to beginning of ring
  3832. RINGI:
  3833.      DS    2        ;ring sort pointer
  3834. RINGJ:
  3835.      DS    2        ;another ring sort pointer
  3836. RINGEND:
  3837.      DS    2        ;current ring end pointer
  3838. RINGPOS:
  3839.      DS    2        ;current ring position in scan
  3840. R$U$A:
  3841.      DS    1        ; 'requested user area'
  3842. SCURAT:
  3843.      DS    2        ;save cursor position
  3844. S$FCB:
  3845.      DS    36        ;fcb for source (random record) file
  3846. SRINGPOS:
  3847.      DS    2        ;save ring position
  3848. T$DR:
  3849.      DS    1        ;temp disk
  3850. TEST$RT:
  3851.      DS    1        ;intermediate right-justify data
  3852. T$U$A:
  3853.      DS    1        ;temp user
  3854. T$UN$FG:
  3855.      DS    1        ;tag/untag file summation switch
  3856. USER:
  3857.      DS    1        ;temp user buffer
  3858. VIEWFLG:
  3859.      DS    1        ; 00h --> to list/punch else to crt 'view'
  3860. Z$DR:
  3861.      DS    1        ;disk for ZDNAME
  3862. Z$U$A:
  3863.      DS    1        ;user area for ZDNAME
  3864.  
  3865. ; cp/m system functions
  3866.  
  3867. RDCON    EQU    1        ;console input function
  3868. WRCON    EQU    2        ;write character to console..
  3869. PUNCH    EQU    4        ;..punch and..
  3870. LIST    EQU    5        ;..to list logical devices.
  3871. DIRCON    EQU    6        ;direct console i/o
  3872. RDBUF    EQU    10        ;read input string
  3873. CONST    EQU    11        ;get console status
  3874. RESETDK    EQU    13        ;reset disk system
  3875. LOGIN    EQU    14        ;log-in new drive
  3876. OPEN    EQU    15        ;open file
  3877. CLOSE    EQU    16        ;close file
  3878. SRCHF    EQU    17        ;search directory for first..
  3879. SRCHN    EQU    18        ;..and next occurrence.
  3880. ERASE    EQU    19        ;erase file
  3881. READ    EQU    20        ;read and..
  3882. WRITE    EQU    21        ;..write 128-record.
  3883. MAKE    EQU    22        ;make file
  3884. REN    EQU    23        ;rename file
  3885. INQDISK    EQU    25        ;get current (default) drive
  3886. SETDMA    EQU    26        ;set dma address
  3887. INQALC    EQU    27        ;allocation vector
  3888. ATTR    EQU    30        ;set file attributes
  3889. GETPARM    EQU    31        ;current drive parameters address
  3890. SGUSER    EQU    32        ;set or get user area
  3891. COMPSZ    EQU    35        ; # of records in file
  3892.  
  3893. ; system addresses
  3894.  
  3895. BDOS     EQU    CPM$BASE+05H    ;bdos function entry address
  3896. FCB     EQU    CPM$BASE+5CH    ;default file control block
  3897. FCBEXT     EQU    FCB+12          ;extent byte in 'fcb'
  3898. FCBRNO     EQU    FCB+32        ;record number in 'fcb'
  3899. FCB2     EQU    CPM$BASE+6CH    ;2nd FCB
  3900. TBUF     EQU    CPM$BASE+80H    ;default cp/m buffer
  3901.  
  3902. ; assembled 'com' and 'ram-loaded' file size (0c00h = 3k)
  3903.  
  3904. COMFILE     EQU    (CMDBUF+2)-256    ; 'prn' listing shows 'com'..
  3905. LAST:     DS    1        ; 1 for byte before BUFENTRY
  3906. ; even-page base of filename ring storage
  3907.  
  3908. BUFENTRY    EQU    $/100H*100H+100H
  3909.  
  3910.  
  3911.      END            ;..and loaded file size.
  3912.  
  3913.