home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / ZCPR33 / Z3-33 / Z33MAKE.LBR / Z33MAKE.ZZ0 / Z33MAKE.Z80
Text File  |  2000-06-30  |  38KB  |  1,341 lines

  1.  
  2. ;  PROGRAM:  Z33MAKE.Z80
  3. ;         based on MAKE26, by various authors    
  4. ;  AUTHOR:   Fred Haines
  5. ;  DATE:     November 24, 1987 
  6. ;  PURPOSE:  to change the user number of designated files on a designated 
  7. ;            drive to a different user number.  Z33MAKE may be assembled to
  8. ;            load and run in high memory. 
  9.  
  10. ; Z33MAKE does not copy files and delete the originals; only the user number
  11. ; byte in the disk directory is changed to reflect the new user number.
  12. ; The program also has options to set file attributes of read-only, read-
  13. ; write, system, directory, and archive.  Files can also be erased or unerased.
  14.  
  15. ; The code assumes that the track and sector are set by the BDOS search
  16. ; functions and uses a simple BIOS write to update the directory.  Before using
  17. ; this program, test it on a garbage disk to make sure that it works with your
  18. ; system.
  19.                     
  20. ; Z33MAKE has been adapted from MAKE v2.6 by the addition of a Z33 type 3
  21. ; header which allows it to be assembled to load and run in high memory.  The
  22. ; history below refers to the versions of MAKE:
  23.  
  24. ;  VERSION 1.0        -     07/05/81   R.E.D.
  25. ;       1.1        -     07/15/81   R.E.D.
  26. ;                    
  27. ;       1.2 - 8/1/82         
  28. ;        ENHANCED FILE NAME DISPLAY.
  29. ;             KEN LOVETT    
  30. ;       1.3 - 8/6/83         
  31. ;        FIXED BUG WHICH CAUSED LAST CHAR IN FILE SPEC TO
  32. ;        BE NON-SIGNIFICANT.    
  33. ;             KEN LOVETT    
  34. ;       2.0 - 8/7/83         
  35. ;        ADDED OPTIONS TO SET R/O, R/W, SYS, DIR FLAGS. ALSO
  36. ;        ERASE AND UNERASE FILES.
  37. ;             KEN LOVETT    
  38. ;                    
  39. ;       2.1 - 6/20/85        
  40. ;        Added (actually, just enabled - it was always there)
  41. ;        full 32 (0-31) area capability, extended display routine
  42. ;        to handle the higher user numbers, added a four-byte kludge
  43. ;        of a display fix required by late-model Kaypros and merely
  44. ;        harmless otherwise, other minor display stuff.        
  45. ;            Bruce Morgen    
  46. ;
  47. ;       2.2 - 07/02/85
  48. ;        Major cleanup of the code (which was highly unstructured and
  49. ;        thus hard to read).  Added check on user number of files so
  50. ;        that the code will act only on files in the logged in area.
  51. ;        There is still no checking to make sure that there is not
  52. ;        already a file in the destination user area of the same name
  53. ;        as the file that is being moved in.
  54. ;            Jay Sage
  55. ;
  56. ;       2.3 - 07/14/85
  57. ;        In ZCPR3 systems the CCP processes the DU: and named directory
  58. ;        forms of directory specification.  The drive value is returned
  59. ;        in the usual way in the FCB, and the user number is placed in
  60. ;        the S1 byte.  Version 22Z of MAKE allows the syntax:
  61. ;
  62. ;                MAKE DIR:AFN OPTION
  63. ;
  64. ;        The files to be operated on can be specified using the full
  65. ;        ZCPR3 format.  The option can even take the DIR: form with a
  66. ;        named directory.  The ZCPR3 equate determines whether a
  67. ;        ZCPR3 version or a standard version will be assembled.
  68. ;        For some reason, even though there is no change in allocation,
  69. ;        performing any write to the directory sets the disk to R/O
  70. ;        status.  I have changed the code I originally put it to
  71. ;        reset the disk system whenever any write has occurred.  I had
  72. ;        not noticed this problem because I use the ZRDOS replacement
  73. ;        for the BDOS, and it automatically relogs changed disks.
  74. ;            Jay Sage
  75. ;
  76. ;       2.4 - 06/15/86
  77. ;        Added ability to SET or RESET the ARCHIVE bit, and added
  78. ;        the WHEEL conditional, which makes MAKE disappear
  79. ;        (echoes: MAKE?) unless the wheel byte is set.
  80. ;            Michael Conley
  81. ;
  82. ;       2.5 - (an obsolete version # observed in the Chicago area dated
  83. ;         1984 - skipped to avoid confusion.
  84. ;
  85. ;       2.6 - 07/22/86
  86. ;        Added "All users" switch for any options not involving a
  87. ;        user number.  A number sign after the selected option
  88. ;        makes it operate on ALL user areas, not just the current
  89. ;        one. (e.g.,  MAKE *.BAK E# -- would erase all .BAK files
  90. ;        in all user areas.)
  91. ;            Michael Conley
  92. ;
  93. ;       Z33MAKE 1.0 - 11/24/87
  94. ;        Added type 3 header for Z33, removed conditionals for
  95. ;        CPM versions, changed wheel error message, and altered help 
  96. ;        screen to reflect change to Z33 utility and display load
  97. ;        address if linked to load and run in high memory.
  98. ;            Fred Haines                
  99.  
  100. ;=============================================================================
  101.  
  102. ;        P R O G R A M    E Q U A T E S
  103.  
  104. ;=============================================================================
  105.  
  106. FALSE    EQU    0
  107. TRUE    EQU    NOT FALSE
  108.  
  109. ; User Setable Equates
  110.  
  111. WHEEL    EQU    TRUE        ;true to test wheel byte before running
  112. WHLADR    EQU    0FDFFH        ;wheel byte location
  113. CIM    EQU    FALSE        ;true if file to be linked for high memory
  114. LDADDR    EQU    98        ;set to address at which program is to be
  115.                 ;linked times 1000h, i.e., 98 = 9800h
  116.  
  117. ; Standard Equates
  118.  
  119. VERSION    EQU    10
  120.  
  121. BDOS    EQU    0005H        ;BDOS entry address
  122. DMAADDR    EQU    0080H        ;default CP/M file buffer
  123. FCB    EQU    005CH        ;default CP/M FCB
  124. TFCB    EQU    006CH        ;temporary FCB
  125. Z3ENV    EQU    0FE00H        ;ZCPR3 environment address filled in by Z3INS
  126. CR    EQU    0DH        ;(z3env not presently needed anyway)
  127. LF    EQU    0AH
  128. TAB    EQU    09H
  129. BELL    EQU    07H
  130.  
  131. ;=============================================================================
  132.  
  133. ;        M A I N    P R O G R A M    C O D E
  134.  
  135. ;-----------------------------------------------------------------------------
  136.  
  137. ; TYPE 3 HEADER
  138.  
  139. ; Code modified as suggested by Charles Irvine to function correctly with 
  140. ; interrupts enabled.  Program will abort with an error message when not
  141. ; loaded to the correct address (attempt to run it under CP/M or Z30).
  142.  
  143. ENTRY:
  144.     jr    start0        ; Must use relative jump
  145.     defb    0        ; Filler
  146.     db    'Z3ENV',3    ; Type-3 environment
  147.  
  148. Z33ENV:    
  149.     dw    z3env        ; Filled in by Z33
  150.     dw    entry        ; Intended load address
  151.  
  152. START0:
  153.     ld    hl,0        ; Point to warmboot entry
  154.     ld    a,(hl)        ; Save the byte there
  155.     di            ; Protect against interrupts
  156.     ld    (hl),0c9h    ; Replace warmboot with a return opcode
  157.     rst    0        ; Call address 0, pushing RETADDR onto stack
  158.  
  159. RETADDR:
  160.     ld    (hl),a        ; Restore byte at 0
  161.     dec    sp        ; Get stack pointer to point
  162.     dec    sp        ; ..to the value of RETADDR
  163.     pop    hl        ; Get it into HL and restore stack
  164.     ei            ; We can allow interrupts again
  165.     ld    de,retaddr    ; This is where we should be
  166.     xor    a        ; Clear carry flag
  167.     push    hl        ; Save address again
  168.     sbc    hl,de        ; Subtract -- we should have 0 now
  169.     pop    hl        ; Restore value of RETADDR
  170.     jr    z,start        ; If addresses matched, begin real code
  171.  
  172.     ld    de,notz33msg-retaddr ; Offset to message
  173.     add    hl,de
  174.     ex    de,hl        ; Switch pointer to message into DE
  175.     ld    c,9
  176.     jp    0005h        ; Return via BDOS print string function
  177.  
  178. NOTZ33MSG:
  179.     defb    'Not Z33+$'    ; Abort message if not Z33-compatible
  180.  
  181. ;-----------------------------------------------------------------------
  182.  
  183. START:
  184.                 ;set up local stack pointer
  185.  
  186.     LD    HL,0        ;get CP/M stack pointer
  187.     ADD    HL,SP
  188.     LD    (OLDSTK),HL    ;save it for later return
  189.     LD    SP,NEWSTK    ;set up new local stack
  190.  
  191.                 ;perform setup tasks
  192.  
  193.     LD    A,(WHLADR)    ;get wheel byte
  194.     OR    A        ;is it set?
  195.     JP    Z,EREXIT    ;no/don't run
  196.  
  197.     CALL    SIGNON        ;print signon message
  198.     CALL    CHKHLP        ;see if help requested and go there if so
  199.  
  200.     CALL    INIT        ;set up data areas
  201.     CALL    SETDU        ;handle current and specified DU areas
  202.     CALL    GETOPT        ;get option from command line (abort if bad)
  203.     CALL    CHKRO        ;abort if destination drive is R/O and option
  204.                 ;..requests change in files
  205.  
  206.                 ;begin main work of program
  207.  
  208.     CALL    SRCHF        ;locate first directory entry (abort if none)
  209.  
  210. LOOP:
  211.     CALL    SETPTR        ;set DMAPTR to point to disk directory FCB
  212.     CALL    CHKFIL        ;check for applicable file
  213.     CALL    NC,CALLOPT    ;if applicable file, process option
  214.  
  215. NEXTFIL:            ;go on to next file
  216.     LD    HL,DIRCODE    ;point to the directory code
  217.     INC    (HL)        ;increase it one
  218.     LD    A,(HL)        ;get new value
  219.     CP    04        ;check for four FCB entries completed
  220.     JP    NZ,LOOP        ;if not, go back and continue
  221.                 ;process this group of four files and go on
  222.                 ;to next
  223.     LD    HL,CHGFLAG    ;point to change flag
  224.     LD    A,(HL)        ;get it into A
  225.     LD    (HL),0        ;reset it
  226.     OR    A        ;set flags from original value
  227.     CALL    NZ,WRTDE    ;if changes were made, write the buffer back
  228.  
  229.                 ;sequence through files to get new buffer-full of FCB's
  230.  
  231. SRNXT:
  232.     LD    DE,AMBFIL    ;point to any-match FCB
  233.     LD    C,12H        ;BDOS search-next function
  234.     CALL    BDOS
  235.     CP    0FFH        ;see if end of entries
  236.     JP    Z,QUIT        ;quit if no more files
  237.     CP    0        ;loop until buffer is updated by BDOS
  238.     JP    NZ,SRNXT    ;jump until dircode is zero
  239.     LD    (DIRCODE),A    ;save the 0 in dircode
  240.     JP    LOOP        ; and loop again
  241.  
  242. ;=============================================================================
  243.  
  244. ;    O P T I O N    P R O C E S S I N G    R O U T I N E S
  245.  
  246. ;-----------------------------------------------------------------------------
  247.  
  248. ; Set the file attribute to SYS.  If the file was not already SYS, then the
  249. ; CHGFLAG is set to indicate the need later to write the modified sector out
  250. ; to disk.
  251.  
  252. SETSYS:
  253.     LD    HL,(DMAPTR)    ;point to disk directory FCB entry
  254.     LD    DE,10        ;offset 10 to DIR/SYS byte
  255.     ADD    HL,DE
  256.     LD    A,(HL)        ;get the SYS/DIR byte
  257.     OR    A        ;test current state of SYS bit
  258.     CALL    P,SETCHGFL    ;if not already SYS, set the change flag
  259.     OR    80H        ;make sure it is set
  260.     LD    (HL),A        ;write modified byte back out
  261.     CALL    REPORT        ;report the new file status
  262.     RET
  263.  
  264. ;-----------------------------------------------------------------------------
  265.  
  266. ; Set the file attribute to DIR.  If the file was not already DIR, then the
  267. ; CHGFLAG is set to indicate the need later to write the modified sector out
  268. ; to disk.
  269.  
  270. SETDIR:
  271.     LD    HL,(DMAPTR)    ;point to disk directory FCB entry
  272.     LD    DE,10        ;offset 10 to SYS/DIR byte
  273.     ADD    HL,DE
  274.     LD    A,(HL)
  275.     OR    A        ;sign flag shows state of SYS bit
  276.     CALL    M,SETCHGFL    ;if not already DIR, set change flag
  277.     AND    7FH        ;clear the DIR bit
  278.     LD    (HL),A        ;write modified byte back to buffer
  279.     CALL    REPORT        ;report the new file status
  280.     RET
  281.  
  282. ;-----------------------------------------------------------------------------
  283.  
  284. ; Set the file attribute to R/O.  If the file was not already R/O, then the
  285. ; CHGFLAG is set to indicate the need later to write the modified sector out
  286. ; to disk.
  287.  
  288. SETRO:
  289.     LD    HL,(DMAPTR)    ;point to disk directory FCB entry
  290.     LD    DE,9        ;offset 9 to R/O-R/W byte
  291.     ADD    HL,DE
  292.     LD    A,(HL)
  293.     OR    A        ;test current state of R/O bit
  294.     CALL    P,SETCHGFL    ;if not already R/O, set the change flag
  295.     OR    80H        ;make sure it is set
  296.     LD    (HL),A        ;write modified byte back out
  297.     CALL    REPORT        ;report the new file status
  298.     RET
  299.  
  300. ;-----------------------------------------------------------------------------
  301.  
  302. ; Set the file attribute to R/W.  If the file was not already R/W, then the
  303. ; CHGFLAG is set to indicate the need later to write the modified sector out
  304. ; to disk.
  305.  
  306. SETRW:
  307.     LD    HL,(DMAPTR)    ;point to disk directory FCB entry
  308.     LD    DE,9        ;offset 9 to R/O-R/W byte
  309.     ADD    HL,DE
  310.     LD    A,(HL)
  311.     OR    A        ;sign flag shows state of R/O-R/W bit
  312.     CALL    M,SETCHGFL    ;if not already R/W, set change flag
  313.     AND    7FH        ;clear the R/O bit
  314.     LD    (HL),A        ;write modified byte back to buffer
  315.     CALL    REPORT        ;report the new file status
  316.     RET
  317. ;-----------------------------------------------------------------------------
  318. ; Set the file attribute to ARC.  If the file was not already ARC, then the
  319. ; CHGFLAG is set to indicate the need later to write the modified sector out
  320. ; to disk.
  321.  
  322. SETARC:
  323.     LD    HL,(DMAPTR)    ;point to disk directory FCB entry
  324.     LD    DE,11        ;offset 10 to ARCHIVE byte
  325.     ADD    HL,DE
  326.     LD    A,(HL)        ;get the ARCHIVE byte
  327.     OR    A        ;test current state of ARC bit
  328.     CALL    P,SETCHGFL    ;if not already ARC, set the change flag
  329.     OR    80H        ;make sure it is set
  330.     LD    (HL),A        ;write modified byte back out
  331.     CALL    REPORT        ;report the new file status
  332.     RET
  333.  
  334. ;-----------------------------------------------------------------------------
  335.  
  336. ; RESET the ARCHIVE file attribute.  If the file was already ARC, then the
  337. ; CHGFLAG is set to indicate the need later to write the modified sector out
  338. ; to disk.
  339.  
  340. SETNRC:
  341.     LD    HL,(DMAPTR)    ;point to disk directory FCB entry
  342.     LD    DE,11        ;offset 10 to ARCHIVE byte
  343.     ADD    HL,DE
  344.     LD    A,(HL)
  345.     OR    A        ;sign flag shows state of ARC bit
  346.     CALL    M,SETCHGFL    ;if it was ARC, set change flag
  347.     AND    7FH        ;clear the ARC bit
  348.     LD    (HL),A        ;write modified byte back to buffer
  349.     CALL    REPORT        ;report the new file status
  350.     RET
  351.  
  352. ;-----------------------------------------------------------------------------
  353.  
  354. ; Erase the file by writing E5 as the user number tag.  We know that the file
  355. ; is not already erased because of the work of subroutine CHKFIL earlier.
  356. ; Therefore, we must set the change flag to show the need to write the sector
  357. ; back out to disk.
  358.  
  359. ERASE:
  360.     LD    HL,(DMAPTR)
  361.     LD    (HL),0E5H
  362.     CALL    SETCHGFL    ;show need to write sector back to disk
  363.     CALL    REPORT        ;report the new file status
  364.     RET
  365.  
  366. ;-----------------------------------------------------------------------------
  367.  
  368. ; Unerase the file by writing the current user number into the tag byte in
  369. ; place of the E5.  The comments under ERASE apply here, too.
  370.  
  371. UNERA:
  372.     LD    A,(DEFUSR)    ;get logged in user number
  373.     LD    HL,(DMAPTR)
  374.     LD    (HL),A        ;put it into disk directory user # tag
  375.     CALL    SETCHGFL    ;show need to write sector back to disk
  376.     CALL    REPORT        ;report the new file status
  377.     RET
  378.  
  379. ;-----------------------------------------------------------------------------
  380.  
  381. ; Change the user number of the file.
  382.  
  383. CHUSER:    LD    A,(OPTION)    ;get user number
  384.     LD    HL,(DMAPTR)    ;point to place to put it
  385.     LD    (HL),A        ;put new user number in directory
  386.     CALL    SETCHGFL    ;show need to write sector back out to disk
  387.     CALL    REPORT        ;report the new file status
  388.     RET
  389.  
  390. ;-----------------------------------------------------------------------------
  391.  
  392. ; This code reports the attributes of the files acted on and, if required,
  393. ; the erased or unerased status.  This code is called directly by the blank
  394. ; option and indirectly by all the other option processors after they have
  395. ; finished performing their changes on the files.
  396.  
  397. REPORT:    CALL    PRTFN        ;print the file name
  398.     CALL    ILPRT        ;print spacer and equal sign
  399.     DB    ' = ',0
  400.     CALL    PRTOPT        ;print the option letter or number
  401.     LD    C,3        ;put in three more blank spaces
  402.     CALL    PRTBLK
  403.     CALL    PRTATTR        ;print file attributes
  404.     LD    A,(OPTION)    ;see if files erased
  405.     CP    'E'
  406.     CALL    Z,PRTERA    ;if so, print erased message
  407.     LD    A,(OPTION)
  408.     CP    'U'        ;see if files unerased
  409.     CALL    Z,PRTUNE    ;if so, print unerased message
  410.     RET
  411.  
  412.  
  413. ;=============================================================================
  414.  
  415. ;        P R O G R A M    F L O W    R O U T I N E S
  416.  
  417. ;-----------------------------------------------------------------------------
  418.  
  419. ;                CALLOPT
  420.  
  421. ; This routine uses the value of OPTION to look up the processing routine
  422. ; to which to branch.
  423.  
  424. CALLOPT:
  425.     LD    HL,JMPTBL    ;point to jump table
  426.     LD    A,(OPTION)    ;get user number or option letter
  427.     LD    B,A        ;save it in B
  428.  
  429. LOOKUP:    LD    A,(HL)        ;get option letter from table
  430.     INC    HL        ;point to jump address
  431.     OR    A        ;end of table?
  432.     JP    Z,JMPOPT2    ;if so, jump
  433.     CP    B        ;do we match a table entry
  434.     JP    Z,JMPOPT1    ;if so, go to code to get jump address
  435.     INC    HL        ;else jump over jump address to
  436.     INC    HL        ;..next option character
  437.     JP    LOOKUP        ;and try again
  438.  
  439. JMPOPT1:
  440.     LD    A,(HL)        ;get low part of jump address into A
  441.     INC    HL        ;point to high part of address
  442.     LD    H,(HL)        ;get it into H
  443.     LD    L,A        ;jump address is in HL
  444.     JP    (HL)        ;jump to it
  445.  
  446. JMPOPT2:
  447.     LD    HL,CHUSER    ;default to change user routine
  448.     JP    (HL)        ;jump to it
  449.  
  450. JMPTBL:    DB    ' '
  451.     DW    REPORT
  452.  
  453.     DB    'S'
  454.     DW    SETSYS
  455.  
  456.     DB    'D'
  457.     DW    SETDIR
  458.  
  459.     DB    'R'
  460.     DW    SETRO
  461.  
  462.     DB    'W'
  463.     DW    SETRW
  464.  
  465.     DB    'A'
  466.     DW    SETARC
  467.  
  468.     DB    'N'
  469.     DW    SETNRC
  470.  
  471.     DB    'E'
  472.     DW    ERASE
  473.  
  474.     DB    'U'
  475.     DW    UNERA
  476.  
  477.     DB    0        ;end of table mark
  478.  
  479. ;-----------------------------------------------------------------------------
  480.  
  481. ;                QUIT
  482.  
  483. ; This code sends a CRLF to the console, restores the original CP/M stack,
  484. ; and returns to CP/M.  If indicated by the reset flag, it resets the disk
  485. ; system.  The logged DU area when the program was invoked is restored.  The
  486. ; entry point QUIT2 is used by code (CHKHLP and CHKVER) that have not changed
  487. ; the logged in directory.
  488.  
  489. QUIT:    CALL    CRLF
  490.  
  491.                 ;log in the original drive/user
  492.  
  493.     LD    A,(DEFDRV)    ;get original default drive
  494.     CALL    LOGDRV        ;log it in
  495.     LD    A,(DEFUSR)    ;get original default user
  496.     CALL    LOGUSR        ;log it in
  497.  
  498.                 ;see if we need to reset the disk system
  499.  
  500. QUIT1:    LD    A,(RSTFLAG)
  501.     OR    A        ;if reset flag is clear
  502.     JP    Z,QUIT2        ;..we can skip disk system reset
  503.  
  504.                 ;reset the disk system
  505.  
  506.     LD    C,0DH
  507.     CALL    BDOS
  508.  
  509.                 ;restore the original stack
  510.  
  511. QUIT2:    LD    HL,(OLDSTK)    ;get original stack pointer
  512.     LD    SP,HL        ;set it up
  513.     RET            ;back to CP/M
  514.  
  515. EREXIT:                
  516.     CALL    ILPRT        ;no wheel error message
  517.     DB    ' Wheel is OFF',0
  518.     JP    QUIT2
  519.  
  520. ;=============================================================================
  521.  
  522. ;    F I L E    S E L E C T I O N    S U B R O U T I N E S
  523.  
  524. ;-----------------------------------------------------------------------------
  525.  
  526. ;                CHKFIL
  527.  
  528. ; This subroutine checks to see whether or not the FCB pointed to in the
  529. ; DMA buffer is one that should be acted on.  If not, the routine returns
  530. ; with the zero flag set.
  531.  
  532. CHKFIL:    CALL    CHKUN        ;check user number and erased status of file
  533.     RET    C        ;return with carry set to skip file
  534.     CALL    CHKFN        ;next check the file name for a match
  535.     RET            ;return showing status of name match
  536.  
  537. ;-----------------------------------------------------------------------------
  538.  
  539. ;                CHKUN
  540.  
  541. ; This subroutine checks the user number status of a file and sets the carry
  542. ; flag if the file should be skipped over.  If the option is UNERASE and the
  543. ; file is not an erased file, it should be skipped.  If the option is not
  544. ; unerase and the file is an erased file, then likewise it should be skipped.
  545. ; Finally, if the file is in a user number other than the logged in user, it
  546. ; should also be skipped.
  547.  
  548. CHKUN:                ;test file erased status
  549.  
  550.     LD    HL,(DMAPTR)    ;point to user number tag of file
  551.     LD    A,(HL)        ;get the tag
  552.     CP    0E5H        ;carry flag set if not erased
  553.     PUSH    AF        ;save flag
  554.  
  555.                 ;test program option status
  556.  
  557.     LD    A,(OPTION)    ;get the option
  558.     CP    'U'        ;is it unerase?
  559.     JP    NZ,CHKUN1    ;if not, skip to CHKUN1
  560.  
  561.                 ;case of unerase option
  562.  
  563.     POP    AF        ;carry flag set if not erased
  564.     RET            ;file not erased will be skipped
  565.  
  566.                 ;case of option other than unerase
  567.  
  568. CHKUN1:    POP    AF
  569.     CCF            ;carry flag set if file erased
  570.     RET    C        ;erased file will be skipped
  571.  
  572.                 ;now check for user number in source area
  573.  
  574.     LD    A,(ALLUSR)    ;see if "all users" was requested
  575.     CP    '#'        ;
  576.     JP    Z,CHKUN2    ;if so, skip over compare...
  577.     LD    A,(SRCUSR)    ;get source user number
  578.     CP    (HL)        ;compare to file tag
  579.     RET    Z        ;if OK, return (carry is clear)
  580.     SCF            ;else set carry
  581. CHKUN2:
  582.     RET            ;..and return
  583.  
  584. ;-----------------------------------------------------------------------------
  585.  
  586. ;                CHKFN
  587.  
  588. ; This subroutine compares the name of the file in the FCB in the DMA buffer
  589. ; with the specification from the command line.
  590.  
  591. CHKFN:                ;set up pointers and character count
  592.  
  593.     LD    HL,(DMAPTR)    ;get pointer to FCB in DMA buffer
  594.     INC    HL        ;point to first character in the name
  595.     LD    DE,FCB+1    ;set DE to name in FCB from command line
  596.     LD    C,0BH        ;load count for compare
  597.  
  598. CP1:    LD    A,(DE)        ;get fcb command line character
  599.     CP    '?'        ;see if anything matches
  600.     JP    Z,MATCH        ;if it is '?', consider it a match
  601.     SUB    A,(HL)        ;get difference (see next instruction)
  602.     AND    7FH        ;clear attribute bit
  603.     JP    Z,MATCH        ;if zero, characters match
  604.     SCF            ;else set carry
  605.     RET            ;..and return
  606.  
  607. MATCH:    INC    DE        ;point to next characters
  608.     INC    HL
  609.     DEC    C        ;decrease count of characters
  610.     JP    NZ,CP1        ;loop until zero
  611.     RET            ;carry is clear showing names match
  612.  
  613.  
  614.  
  615. ;=============================================================================
  616.  
  617. ;    D I S K    O P E R A T I O N    S U B R O U T I N E S
  618.  
  619. ;-----------------------------------------------------------------------------
  620.  
  621. ;                SRCHF
  622.  
  623. ; This subroutine uses the fully ambiguous file spec at AMBFIL to locate the
  624. ; first directory entry on the disk.  The directory code (0-3) is saved. If
  625. ; no directory entry is found, then the program gives a message and branches
  626. ; to QUIT for a prompt return.
  627.  
  628. SRCHF:    LD    DE,AMBFIL    ;point to match any filename.typ
  629.     LD    C,11H        ;bdos search first function
  630.     CALL    BDOS        ;do it
  631.     LD    (DIRCODE),A    ;save directory code
  632.     CP    0FFH        ;see if end of entries
  633.     RET    NZ        ;if something found, return
  634.     CALL    ILPRT        ;else give a message
  635.     DB    BELL,CR,LF
  636.     DB    'No Files On Disk',CR,LF,0
  637.     JP    QUIT
  638.  
  639. ;-----------------------------------------------------------------------------
  640.  
  641. ;                WRTDE
  642.  
  643. ; This routine writes the directory buffer back to the disk.  I also sets the
  644. ; reset flag so that the disk system will be reset on program termination.
  645.  
  646. WRTDE:    LD    HL,RSTFLAG    ;point to the flag
  647.     LD    (HL),0FFH    ;set the flag
  648.     LD    C,1H        ;set BIOS write to directory
  649.                 ; C = 0   write to allocated
  650.                 ; C = 1   write to directory
  651.                 ; C = 2   write to unallocated
  652.     CALL    WRITE        ;do the write
  653.     OR    A        ;check for error
  654.     RET    Z        ;if none, return
  655.  
  656.     CALL    ILPRT
  657.     DB    BELL
  658.     DB    CR,LF
  659.     DB    'Bad Sector Write Error',CR,LF,0
  660.  
  661.     JP    QUIT
  662.  
  663. ;-----------------------------------------------------------------------------
  664.  
  665. ;                WRITE
  666.  
  667. ; This routine is filled in during the operation of the program and performs
  668. ; a direct BIOS sector write operation on the currently selected track and
  669. ; sector.
  670.  
  671. WRITE:    JP    0000        ;vector to bios write routine
  672.  
  673.  
  674. ;=============================================================================
  675.  
  676. ;        P R I N T I N G    R O U T I N E S
  677.  
  678. ;-----------------------------------------------------------------------------
  679.  
  680. ;                PRTFN
  681.  
  682. ; This subroutine displays (at the beginning of the next line of the screen)
  683. ; the name of the file pointed to in the DMA buffer.
  684.  
  685. PRTFN:    CALL    CRLF        ;print cr/lf
  686.     LD    HL,(DMAPTR)    ;address of file fcb
  687.     INC    HL        ;skip to file name
  688.     LD    DE,BLNKCNT    ;point to blanks counter
  689.     EX    DE,HL        ;exchange pointers
  690.     LD    (HL),0        ;preset blank count to zero
  691.  
  692.     LD    C,8        ;length of file name
  693.     CALL    PRTSTR        ;print the name first
  694.  
  695.     LD    A,'.'        ;print the period
  696.     CALL    CHAROUT
  697.  
  698.     LD    C,3        ;now print the file type
  699.     CALL    PRTSTR
  700.  
  701.     LD    C,(HL)        ;get number of blanks needed for fill
  702.     CALL    PRTBLK        ;print the blanks
  703.     RET
  704.  
  705. ;-----------------------------------------------------------------------------
  706.  
  707. ;                PRTOPT
  708.  
  709. ; This subroutine prints out the option as a letter or as a number as
  710. ; appropriate.
  711.  
  712. PRTOPT:    LD    A,(OPTION)    ;get the option value
  713.     CP    20H        ;if it's a user number, carry will be set
  714.     JP    NC,CHAROUT    ;if not number, just print the character
  715.     LD    B,'0'-1        ;preset for two-digit calculation later
  716.     CP    10        ;see if single digit
  717.     JP    NC,TWODIG    ;if not, print two digits
  718.     ADD    '0'        ;else convert to ASCII
  719.     JP    CHAROUT        ;and print it
  720. TWODIG:    INC    B        ;count tens digit in B
  721.     SUB    10        ;keep subtracting 10 until carry is set
  722.     JP    NC,TWODIG
  723.     ADD    10        ;get remainder (units digit) back
  724.     LD    C,A        ;save it in C
  725.     LD    A,B        ;print tens digit
  726.     CALL    CHAROUT
  727.     LD    A,C        ;print units digit
  728.     ADD    '0'
  729.     JP    CHAROUT
  730.  
  731. ;-----------------------------------------------------------------------------
  732.  
  733. ;                PRTATTR
  734.  
  735. ; This subroutine prints the attribute status (SYS or DIR and R/O or R/W)
  736. ; of the file currently being worked on.
  737.  
  738. PRTATTR:
  739.     LD    HL,(DMAPTR)    ;point to file FCB
  740.     LD    DE,9        ;offset to R/O-R/W byte
  741.     ADD    HL,DE
  742.     PUSH    HL        ;save pointer for reuse below
  743.     LD    A,(HL)
  744.     RLA            ;move R/O bit into carry
  745.     PUSH    AF        ;save flags
  746.     CALL    C,PRTRO        ;if carry, print read-only
  747.     POP    AF        ;get flags back to test again
  748.     CALL    NC,PRTRW    ;if not carry, print read-write
  749.  
  750.     POP    HL        ;get pointer back
  751.     INC    HL        ;point to SYS/DIR byte
  752.     PUSH    HL        ;save pointer for reuse below
  753.     LD    A,(HL)
  754.     RLA            ;move SYS/DIR bit into carry
  755.     PUSH    AF        ;save flags
  756.     CALL    C,PRTSYS    ;if carry, print SYS
  757.     POP    AF        ;get them back
  758.     CALL    NC,PRTDIR    ;if not carry, print DIR
  759.     POP    HL
  760.     INC    HL
  761.     LD    A,(HL)
  762.     RLA            ;move ARCHIVE bit into carry
  763.     PUSH    AF        ;save flags
  764.     CALL    C,PRTARC    ;if carry, print ARC
  765.     POP    AF        ;get them back
  766.     CALL    NC,PRTNRC    ;if not carry, print Non-ARC
  767.     RET
  768.  
  769. ;-----------------------------------------------------------------------------
  770.  
  771. ;    MESSAGE PRINTING ROUTINES
  772.  
  773. PRTRO:    CALL    ILPRT        ;file is read-only
  774.     DB    '  R/O',0
  775.     RET
  776.  
  777. PRTRW:    CALL    ILPRT        ;file is read-write
  778.     DB    '  R/W',0
  779.     RET
  780.  
  781. PRTSYS:    CALL    ILPRT        ;file has SYS attribute
  782.     DB    '  SYS',0
  783.     RET
  784.  
  785. PRTDIR:    CALL    ILPRT        ;file has DIR attribute
  786.     DB    '  DIR',0
  787.     RET
  788.  
  789. PRTARC:    CALL    ILPRT        ;file has ARC attribute
  790.     DB    '  ARCHIVE',0
  791.     RET
  792.  
  793. PRTNRC:    CALL    ILPRT        ;file has NO ARC attribute
  794.     DB    '  Non-ARC',0
  795.     RET
  796.  
  797. PRTERA:    CALL    ILPRT        ;file erased
  798.     DB    '   *** ERASED ***',0
  799.     RET
  800.  
  801. PRTUNE:    CALL    ILPRT        ;file unerased
  802.     DB    '   *** UNERASED ***',0
  803.     RET
  804.  
  805. ;-----------------------------------------------------------------------------
  806.  
  807. ;                HELP
  808.  
  809. ; This code displays the built in help screen and then jumps to QUIT to
  810. ; return to CP/M.
  811.  
  812. HELP:    CALL    ILPRT
  813.     DB    'Syntax:  ',CR,LF
  814.     DB    '  MAKE [dir:]filename.typ o[#]',CR,LF
  815.     DB    'Options: ',CR,LF
  816.     DB    '  DIR:  move files to named directory DIR',CR,LF
  817.     DB    '  nn    move files to user nn (0-31)',CR,LF
  818.     DB    '  S     make files System',CR,LF
  819.     DB    '  D     make files Directory',CR,LF
  820.     DB    '  R     make files Read/Only',CR,LF
  821.     DB    '  W     make files Read/Write',CR,LF
  822.     DB    '  A     make files Archive',CR,LF
  823.     DB    '  N     make files Non-Archive',CR,LF
  824.     DB    '  E     erase specified files',CR,LF
  825.     DB    '  U     unerase specified files',CR,LF
  826.     DB    '  #     all user areas',CR,LF,0
  827.  
  828.     JP    QUIT2
  829.  
  830.  
  831. ;=============================================================================
  832.  
  833. ;    G E N E R A L - P U R P O S E   S U B R O U T I N E S
  834.  
  835. ;-----------------------------------------------------------------------------
  836.  
  837. ;                CRTOUT
  838.  
  839. ; This subroutine sends the character in register A to the console.  Registers
  840. ; BC, DE, and HL are preserved.
  841.  
  842. CHAROUT:
  843.  
  844.     PUSH    HL        ;save registers
  845.     PUSH    DE
  846.     PUSH    BC
  847.     LD    E,A        ;get character into E
  848.     LD    C,06        ;BDOS direct console I/O
  849.     CALL    BDOS
  850.     POP    BC        ;restore registers
  851.     POP    DE
  852.     POP    HL
  853.     RET
  854.  
  855. ;-----------------------------------------------------------------------------
  856.  
  857. ;                CRLF
  858.  
  859. ; This routine sends a carriage return and linefeed to the console.
  860.  
  861. CRLF:    CALL    ILPRT
  862.     DB    CR,LF,0
  863.     RET
  864.  
  865.  
  866. ;-----------------------------------------------------------------------------
  867.  
  868. ;                FILL
  869.  
  870. ; This subroutine fills memory starting at HL for a length B with the byte
  871. ; in A.
  872.  
  873. FILL:
  874.     LD    (HL),A
  875.     INC    HL
  876.     DEC    B
  877.     JP    NZ,FILL
  878.     RET
  879.  
  880. ;-----------------------------------------------------------------------------
  881.  
  882. ;                ILPRT
  883.  
  884. ; This subroutine prints the string that follows its call.  The string must
  885. ; be terminated with a null (0).
  886.  
  887. ILPRT:    POP    HL        ;get address following call into HL
  888.  
  889. ILPRT1:    LD    A,(HL)        ;get character from message
  890.     INC    HL        ;point to next character
  891.     OR    A        ;test for null indicating end of message
  892.     JP    Z,ILPRT2    ;if end, fix up return address
  893.     LD    E,A        ;have BDOS send character it to console
  894.     LD    C,2
  895.     PUSH    HL        ;save pointer to string
  896.     CALL    BDOS
  897.     POP    HL        ;restore pointer
  898.     JP    ILPRT1        ;process it
  899.  
  900. ILPRT2:    PUSH    HL        ;set up return address to just past message
  901.     RET
  902.  
  903. ;-----------------------------------------------------------------------------
  904.  
  905. ;                PRTSTR
  906.  
  907. ; This subroutine prints a string of characters pointed to by DE.  The number
  908. ; of characters is in the C register.  Blanks are not printed; instead, the
  909. ; blanks counter pointed to by HL is incremented.
  910.  
  911. PRTSTR:    LD    A,(DE)        ;get character
  912.     CP    ' '        ;see if it is a blank
  913.     CALL    Z,UPCOUNT    ;if so, up the count
  914.     CALL    NZ,CHAROUT    ;if not, output the character
  915.     INC    DE
  916.     DEC    C        ;check count
  917.     JP    NZ,PRTSTR
  918.     RET
  919.  
  920. UPCOUNT:
  921.     PUSH    AF        ;save flags
  922.     INC    (HL)        ;increase the blank counter
  923.     POP    AF        ;restore flags
  924.     RET
  925.  
  926. ;-----------------------------------------------------------------------------
  927.  
  928. ;                PRTBLK
  929.  
  930. ; This subroutine prints blank spaces given by the count in C.  The routine
  931. ; will work even for a count of zero.
  932.  
  933. PRTBLK:    INC    C        ;turn 0 into 1
  934. PRTBL1:    DEC    C        ;check count
  935.     RET    Z        ;return if count exhausted
  936.     LD    A,' '        ;set character to print
  937.     CALL    CHAROUT
  938.     JP    PRTBL1
  939.  
  940.  
  941. ;=============================================================================
  942.  
  943. ;        S E T U P    S U B R O U T I N E S
  944.  
  945. ;-----------------------------------------------------------------------------
  946.  
  947. ;                SIGNON
  948.  
  949. ; This subroutine displays the program signon message.
  950.  
  951. SIGNON:    CALL    ILPRT
  952.     DB    'Z33MAKE  Version '
  953.     DB    VERSION / 10 + '0'
  954.     DB    '.'
  955.     DB    VERSION MOD 10 + '0'
  956.       IF CIM
  957.     DB    ' (loaded at '
  958.     DB    LDADDR / 10 + '0'
  959.     DB    LDADDR MOD 10 + '0' 
  960.     DB    '00h)'
  961.       ENDIF    ; CIM
  962.     DB    CR,LF,0
  963.     RET
  964.  
  965. ;-----------------------------------------------------------------------------
  966.  
  967. ;                CHKHLP
  968.  
  969. ; This subroutine checks to see if the user has invoked the program in a
  970. ; way to request the built-in help screen.  The help screen is shown if the
  971. ; command has no tail or if the tail begins with a slash.
  972.  
  973. CHKHLP:    LD    A,(FCB+1)    ;get first character of first parameter
  974.     CP    ' '        ;no name?
  975.     JP    Z,HELP        ;if so, go to HELP
  976.     CP    '/'        ;parameter starts with slash?
  977.     JP    Z,HELP        ;if so, go to HELP
  978.     RET            ;return with flag set appropriately
  979.  
  980. ;-----------------------------------------------------------------------------
  981.  
  982. ;                INIT
  983.  
  984. ; This subroutine initializes the data areas in the program so that GO
  985. ; command will re-run the program correctly.
  986.  
  987. INIT:    XOR    A        ;zero the accumulator
  988.     LD    (CHGFLAG),A    ;preset control flags
  989.     LD    (RSTFLAG),A
  990.     LD    (DIRCODE),A
  991.  
  992.     LD    HL,AMBFIL2
  993.     LD    B,16
  994.     CALL    FILL        ;clear the fcb
  995.  
  996.     LD    A,'?'
  997.     LD    B,16
  998.     LD    HL,AMBFIL
  999.     CALL    FILL
  1000.  
  1001.     LD    HL,(0001)    ;get warmboot address (base of bios + 3)
  1002.     LD    DE,27H        ;offset for jump to bios write
  1003.     ADD    HL,DE        ;compute address for write routine
  1004.     LD    (WRITE + 1),HL    ;load our vector with this address
  1005.  
  1006.     RET
  1007.  
  1008. ;-----------------------------------------------------------------------------
  1009.  
  1010. ;                SETDU
  1011.  
  1012. ; This subroutine gets and saves the values of the currently logged in drive
  1013. ; and user area and the drive and user specified (if any) on the command line
  1014. ; for the files to be operated on.
  1015.  
  1016. SETDU:                ;get currently logged in user number
  1017.  
  1018.     LD    C,20H        ;BDOS get/set user number function
  1019.     LD    E,0FFH        ;get user flag
  1020.     CALL    BDOS
  1021.     LD    (DEFUSR),A
  1022.     LD    (SRCUSR),A    ;save for now as source user also
  1023.  
  1024.                 ;get the currently logged in drive
  1025.  
  1026.     LD    C,19H        ;bdos get drive number function
  1027.     CALL    BDOS        ;get drive number
  1028.     LD    (DEFDRV),A
  1029.     INC    A        ;change range 1-16 and
  1030.     LD    (SRCDRV),A    ;..save for now as source drive also
  1031.  
  1032.                 ;now log in the drive and user in file spec
  1033.  
  1034.     LD    A,(FCB)        ;get drive spec from FCB
  1035.     OR    A        ;see if default specified
  1036.     JP    Z,SETDU1
  1037.     LD    (SRCDRV),A    ;save source drive
  1038.     SUB    1        ;get in range 0-15
  1039.     CALL    LOGDRV        ;log in the drive
  1040.     XOR    A        ;and change FCB to show default drive
  1041.     LD    (FCB),A
  1042.  
  1043. SETDU1:
  1044.  
  1045.     LD    A,(FCB+13)    ;get user number from S1 byte
  1046.     LD    (SRCUSR),A    ;save as source user area
  1047.     CALL    LOGUSR        ;log in the user number
  1048.  
  1049.     RET
  1050.  
  1051. ;-----------------------------------------------------------------------------
  1052.  
  1053. ; These two routines log in the drive or user number given in the A register.
  1054. ; No registers are preserved.
  1055.  
  1056.  
  1057. LOGDRV:    LD    E,A
  1058.     LD    C,0EH
  1059.     CALL    BDOS
  1060.     RET
  1061.  
  1062. LOGUSR:    LD    E,A
  1063.     LD    C,20H
  1064.     CALL    BDOS
  1065.     RET
  1066.  
  1067. ;-----------------------------------------------------------------------------
  1068.  
  1069. ;                GETOPT
  1070.  
  1071. ; Process option specified on the command line.  If there is an error, the
  1072. ; routine jumps to HELP which in turn jumps to QUIT.  If a named directory
  1073. ; is specified for the destination on the command line, then its user number
  1074. ; is obtained from address TFCB+13.  The drive is checked to make sure that
  1075. ; the destination is on the same drive.
  1076.  
  1077. GETOPT:
  1078.  
  1079.                 ;check for destination specified using named directory
  1080.  
  1081.     LD    A,(TFCB)    ;check for drive number
  1082.     OR    A        ;if zero, no DIR: or DU: given
  1083.     JP    Z,GETOPT1
  1084.  
  1085.                 ;check for correct drive spec
  1086.  
  1087.     LD    HL,SRCDRV    ;point to source drive value
  1088.     CP    (HL)
  1089.     JP    NZ,BADDRV    ;if not the same, jump to bad drive message
  1090.  
  1091.                 ;get the user number
  1092.  
  1093.     LD    A,(TFCB + 13)
  1094.     LD    (OPTION),A    ;store user number as option
  1095.     JP    CHKNUM        ;check for valid user number
  1096.  
  1097. BADDRV:    CALL    ILPRT        ;destination and source drives not same
  1098.     DB    BELL
  1099.     DB    CR,LF,LF
  1100.     DB    'Source and Destination Drives',CR,LF
  1101.     DB    'Must be the Same'
  1102.     DB    CR,LF
  1103.     DB    0
  1104.     JP    QUIT
  1105.  
  1106. GETOPT1:
  1107.     LD    HL,TFCB        ;point to parsed second parameter
  1108.     LD    A,(HL)        ;make sure it wasn't of form 'D:'
  1109.     OR    A        ;drive byte should be zero
  1110.     JP    NZ,BADOPT
  1111.     INC    HL        ;now look at data entered
  1112.  
  1113.     LD    A,(HL)        ;get the first character
  1114.     CALL    GETNUM        ;try to read it as a number
  1115.     JP    C,LETTER    ;if not, must be a letter or bad
  1116.     LD    B,A        ;save digit in B
  1117.     LD    (OPTION),A    ;..and as interim option
  1118.     INC    HL        ;try next character
  1119.     LD    A,(HL)
  1120.     CP    ' '        ;if it is a blank
  1121.     JP    Z,CHKNUM    ;..go to test user number value
  1122.  
  1123.     CALL    GETNUM        ;see if second character is a number
  1124.     JP    C,BADOPT    ;if not, we have a bad option spec
  1125.  
  1126.     LD    C,A        ;save second digit
  1127.     LD    A,B        ;get first digit back
  1128.     ADD    A,A        ;double it three times to make 8x
  1129.     ADD    A,A
  1130.     ADD    A,A
  1131.     ADD    A,B        ;now add original in twice to make 10x
  1132.     ADD    A,B
  1133.     ADD    A,C        ;finally, add in second digit
  1134.     LD    (OPTION),A    ;..and save the final result
  1135.  
  1136.                 ;check for valid user number (in range and not same
  1137.                 ;as logged in user number)
  1138.  
  1139. CHKNUM:    LD    A,(OPTION)    ;make sure we have the user number
  1140.     CP    32        ;test for valid user number range
  1141.     JP    NC,BADNUM
  1142.     LD    HL,SRCUSR    ;see if same as source user
  1143.     CP    (HL)
  1144.     JP    Z,SAMENUM    ;if so, give message
  1145.     RET
  1146.  
  1147. LETTER:                ;check for valid letter option
  1148.     PUSH    AF        ;save option letter
  1149.     INC    HL        ;check whether option followed by '#'
  1150.     LD    A,(HL)
  1151.     CP    '#'
  1152.     JP    NZ,LETTER0    ;not "all users" switch, don't save it
  1153.     LD    (ALLUSR),A
  1154. LETTER0:
  1155.     POP    AF        ;get option character back
  1156.     LD    HL,OPTLIST    ;point to list of valid options
  1157.     LD    C,(HL)        ;get number of options in list
  1158. LETTER1:            ;loop through them checking
  1159.     INC    HL
  1160.     CP    (HL)        ;compare to list entry
  1161.     JP    Z,GOODOPT    ;if it matches, we have a good option
  1162.     DEC    C        ;else, count down
  1163.     JP    NZ,LETTER1    ;..and try again
  1164.     JP    HELP        ;we get here if option is not valid
  1165.  
  1166. GOODOPT:            ;we have a good option letter
  1167.     LD    (OPTION),A
  1168.     RET
  1169.  
  1170. BADOPT:                ;we have a bad option specifier
  1171.     CALL    ILPRT
  1172.     DB    BELL,CR,LF
  1173.     DB    TAB,'****  BAD OPTION SPECIFIER  ****',CR,LF,0
  1174.     JP    HELP
  1175.  
  1176. BADNUM:                ;we have an illegal user number
  1177.     CALL    ILPRT
  1178.     DB    BELL,CR,LF
  1179.     DB    TAB,'****  ILLEGAL USER NUMBER  ****',CR,LF,0
  1180.     JP    HELP
  1181.  
  1182. SAMENUM:            ;give message about already in that user area
  1183.     CALL    ILPRT
  1184.     DB    BELL,CR,LF
  1185.     DB    'destination user number is the',CR,LF
  1186.     DB    'same as the source user number'
  1187.     DB    CR,LF,0
  1188.     JP    QUIT
  1189.  
  1190.                 ;subroutine to check for number character
  1191.                 ;returns with carry set if not a number
  1192.  
  1193. GETNUM:    CP    '0'        ;see if less than '0'
  1194.     RET    C        ;if so, set carry flag as signal
  1195.     CP    '9'+1        ;see if more than '9'
  1196.     CCF            ;reverse sense of carry flag
  1197.     RET    C        ;if >9, return with carry set
  1198.     SUB    '0'        ;convert to number value
  1199.     RET            ;carry is clear
  1200.  
  1201.                 ;list of valid options
  1202.  
  1203. OPTLIST:
  1204.     DB    ENDLIST-OPTLIST    ;number of options in list
  1205.     DB    ' SDRWANEU'    ;valid options
  1206. ENDLIST:
  1207.  
  1208. ;-----------------------------------------------------------------------------
  1209.  
  1210. ;                CHKRO
  1211.  
  1212. ; This routine checks to see if the destination drive is read-only.  If it
  1213. ; is, an appropriate error message is displayed and the program aborts with
  1214. ; a jump to QUIT.  If the option is display only (option = space char), then
  1215. ; this test is skipped.
  1216.  
  1217.  
  1218. CHKRO:    LD    A,(OPTION)    ;see if display option is in effect
  1219.     CP    ' '
  1220.     RET    Z        ;if so, skip rest of test
  1221.  
  1222.     LD    C,1DH        ;get R/O vector from BDOS
  1223.     CALL    BDOS
  1224.  
  1225.                 ;calculate number of left-shifts needed
  1226.  
  1227.     LD    A,(SRCDRV)    ;get the target drive number
  1228.     CPL            ;complement it (makes 255-SRCDRV)
  1229.     ADD    17        ;makes A = 16 - SRCDRV (value 1-16)
  1230.  
  1231.                 ;shift word in HL to put bit of R/O vector for
  1232.                 ;specified drive into high bit position
  1233.  
  1234. CHKRO1:    DEC    A        ;test for done
  1235.     JP    Z,CHKRO2    ;if so, jump
  1236.     ADD    HL,HL        ;shift HL to left
  1237.     JP    CHKRO1        ;and loop
  1238.  
  1239. CHKRO2:    ADD    HL,HL        ;move high bit into carry flag
  1240.     RET    NC        ;if not R/O, return
  1241.     CALL    ILPRT        ;else print R/O error message
  1242.     DB    BELL,CR,LF
  1243.     DB    'Drive is set to R/O',CR,LF,0
  1244.  
  1245.     JP    QUIT        ;abort program
  1246.  
  1247.  
  1248. ;=============================================================================
  1249.  
  1250. ;        M I S C E L L A N E O U S    R O U T I N E S
  1251.  
  1252. ;-----------------------------------------------------------------------------
  1253.  
  1254. ;                SETPTR
  1255.  
  1256. ; This subroutine uses the value of the directory code to calculate a pointer
  1257. ; to the FCB in the DMA buffer.  This is done by multiplying the directory code
  1258. ; by 32 and adding it to the DMA address (DMAADDR).  The result is saved in
  1259. ; DMAPTR.
  1260.  
  1261. SETPTR:
  1262.     LD    A,(DIRCODE)    ;get the directory code
  1263.     ADD    A,A        ;offset by 32 bytes per entry
  1264.     ADD    A,A
  1265.     ADD    A,A
  1266.     ADD    A,A
  1267.     ADD    A,A
  1268.     LD    E,A        ;move value into DE
  1269.     LD    D,0
  1270.     LD    HL,DMAADDR    ;get buffer address
  1271.     ADD    HL,DE        ;compute offset into buffer
  1272.     LD    (DMAPTR),HL    ;save the address into the buffer
  1273.     RET
  1274.  
  1275. ;-----------------------------------------------------------------------------
  1276.  
  1277. ;                SETCHGFL
  1278.  
  1279. ; This subroutine sets the change-flag to show that the directory sector
  1280. ; has been modified and needs to be written out to disk.
  1281.  
  1282. SETCHGFL:
  1283.     PUSH    AF
  1284.     LD    A,0FFH        ;set the sector change flag
  1285.     LD    (CHGFLAG),A
  1286.     POP    AF
  1287.     RET
  1288.  
  1289. ;=============================================================================
  1290.  
  1291. ;            D A T A    A R E A
  1292.  
  1293. ;-----------------------------------------------------------------------------
  1294.  
  1295. OLDSTK:                ;place to keep old stack pointer
  1296.     DS    2
  1297.  
  1298. BLNKCNT:            ;count of blank characters in file name
  1299.     DS    1
  1300.  
  1301. CHGFLAG:            ;flag for change requiring write
  1302.     DS    1
  1303.  
  1304. RSTFLAG:            ;flag for need to reset disk system
  1305.     DS    1
  1306.  
  1307. AMBFIL:                ;working fcb
  1308.     DS    16
  1309.  
  1310. AMBFIL2:            ;space for rest of FCB
  1311.     DS    19
  1312.  
  1313. OPTION:                ;storage for new user number or option
  1314.     DS    1
  1315.  
  1316. ALLUSR:                ;storage for "all users" switch
  1317.     DS    1
  1318.  
  1319. DIRCODE:            ;storage for directory code (0-3)
  1320.     DS    1
  1321.  
  1322. DMAPTR:                ;address of FCB in DMA buffer
  1323.     DS    2
  1324.  
  1325. DEFDRV:                ;current default drive
  1326.     DS    1
  1327.  
  1328. SRCDRV:                ;source drive
  1329.     DS    1
  1330.  
  1331. DEFUSR:                ;current default user number
  1332.     DS    1
  1333.  
  1334. SRCUSR:                ;source user area from file spec
  1335.     DS    1
  1336.  
  1337.     DS    60        ;room for local stack
  1338. NEWSTK:
  1339.  
  1340.     END
  1341.