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 / UTILS / DIRUTL / MAKE26.LBR / MAKE26.AZM / MAKE26.ASM
Assembly Source File  |  2000-06-30  |  39KB  |  1,382 lines

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