home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / hdutl / multcopy.asm < prev    next >
Assembly Source File  |  1994-07-13  |  14KB  |  584 lines

  1. ; MULTIPLE FILE COPY PROGRAM
  2. ; COPYRIGHT 1982, G. YOUNG, INC. 
  3. ; UPDATED 10/9/82
  4. * TO EXECUTE, ENTER THE PROGRAM NAME FOLLOWED BY THE FILE MASK:
  5. *       A>MULTCOPY *.COM
  6. *
  7. * THE PURPOSE OF THIS PROGRAM IS TO COPY MULTIPLE FILES TO A FLOPPY DISK
  8. * FROM A HARD DISK.  IF YOU USED PIP FOR D:=*.COM AND THER WERE MORE 
  9. * COM FILES THAN WOULD FIT ON ONE DISK, PIP WOULD STOP WHEN THE FIRST
  10. * DISK WAS FULL.  IF MULTCOPY, WHEN ONE DISK WAS FULL, IT WOULD ASK
  11. * YOU TO MOUNT A NEW DISK AND CONTINUE COPYING.  THE FLOPPY DISK DRIVE
  12. * IS HARD CODED INTO THE PROGRAM.  THE SOURCE MAY BE ANY HARD DISK.
  13. *    EXAMPLE MULTCOPY B:LN*.ASM
  14. * CHANGED 10/9/82 TO ASK DESTINATION FLOPPY DRIVE
  15.  
  16.  
  17.  
  18. * WRITTEN BY GARY YOUNG, BOX 3218, NO. HOLLYWOOD, CA 91609
  19.  
  20.     TITLE    '*** MULTCOPY FILE COPY PROGRAM ***'
  21. BDOS    EQU    5
  22. RECSIZE EQU    12
  23. BOOT    EQU    0
  24.     ORG    100H
  25.     JMP    START
  26.     DB    'COPYRIGHT 1982, G. YOUNG, INC.'
  27. START    LXI    SP,STACK+80
  28.     LDA    5DH        ;SEE IF A MASK WAS ENTERED
  29.     CPI    20H        ;BUFFER WILL BE BLANK IF NOT
  30.     JZ    NOMASK
  31.     MVI    C,0DH        ;DISK RESET
  32.     CALL    BDOS
  33.     LXI    H,RAM        ;SET UP TABLE ADDRESS
  34.     SHLD    TABADDR
  35.     LXI    H,0000H
  36.     SHLD    TABCNT
  37.     XRA    A        ;THE TABLE REFERS TO THE REMAINING AREA
  38.     STA    ABORT        ;OF RAM TO HOLD AS MANY DIRECTORY ENTRIES
  39.     STA    EOF        ;AS POSSIBLE
  40.     LXI    D,SIGNON    ;PRINT SIGNON MESSAGE
  41.     CALL    OUTPUT
  42.     LXI    D,DESTFLPMSG
  43.     CALL    QUESTION
  44.     ORA    A
  45.     JNZ    QUEST1A
  46.     LDA    DESTFLP
  47.     JMP    QUEST1B
  48. QUEST1A    LDA    INREC
  49. QUEST1B    STA    FLOPPY
  50.     CALL    EXTRACT        ;GET DIRECTORY ENTRIES
  51. NOMORE    CALL    SORT
  52.     CALL    KILLDUPS    ;REMOVE ENTRIES FROM MULTIPLE EXTENTS
  53.     LDA    5CH        ;SOURCE DISK
  54.     STA    SRCE
  55.     LDA    FLOPPY        ;FLOPPY DISK IS ALWAYS THE DESTINATION
  56.     ANI    0FH
  57.     STA    DEST
  58.     LXI    D,MNTBLANK
  59.     CALL    QUESTION
  60.     MVI    C,0DH
  61.     CALL    BDOS
  62.     CALL    CPYFILE    
  63.     JMP    BOOT        ;RESET AND RETURN TO CPM
  64. NOMASK    LXI    D,ERRNOMSK
  65.     CALL    OUTPUT
  66.     JMP    BOOT
  67. *
  68. * THE EXTRACT ROUTINE SCANS THE DIRECTORY ON THE FLOPPY DISK 
  69. * AND CREATES A LIST OF FILES TO BE COPIED.  AFTERS SORTING,
  70. * DUPLICATE ENTRIES RESULTING FROM MULTIPLE EXTENT ENTRIES WILL 
  71. * BE REMOVED.
  72. *
  73. * THE DUMMYFCB SETS UP A SKELETON TO READ ALL FILES ON THE DIRECTORY
  74. * TO BE MODIFIED BY THE SKELATON SETUP IN THE CALL (EX: FLOPCOPY *.ASC).
  75. *
  76. DUMMYFCB    DB    0,'????????????',0,0,0,0,0,0,0,0,0
  77.         DB    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  78. EXTRACT    EQU    $
  79.     LXI    D,DUMMYFCB    ;COPY THE MASK SET UP BY CCP
  80.     LXI    H,5CH        ;OVER THE DUMMY FCB TO LIMIT WHAT IS COPIED
  81.     MVI    B,12
  82.     CALL    MOVE
  83.     LDA    DUMMYFCB
  84.     ORI    40H
  85.     STA    RDISK
  86.     LXI    D,DISKBUF    ;SET A DMA ADDRESS FOR DIRECTORY ENTRIES
  87.     MVI    C,1AH
  88.     CALL    BDOS        ;SET DMA
  89.     LXI    D,DUMMYFCB    ;GET FIRST DIRECTORY ENTRY
  90.     MVI    C,11H
  91.     CALL    BDOS        ;GET DIRECTORY
  92.     INR    A
  93.     RZ
  94.     JMP    GETFCB        ;EXTRACT DATA FROM FCB
  95. NEXTFCB    LXI    D,DUMMYFCB    ;GET NEXT ENTRY AFTER THE FIRST
  96.     MVI    C,12H
  97.     CALL    BDOS
  98.     INR    A
  99.     RZ
  100. GETFCB    LXI    D,32        ;EACH ENTRY IS 32 BYTES LONG
  101.     LXI    H,DISKBUF    ;DIRECTORY RECORD IS IN DISKBUF
  102.     CPI    1        ;FIRST ENTRY IN RECORD???
  103.     JZ    FORMREC        ;YES
  104.     DAD    D        ;ADD 32 TO ADDRESS IN RECORD
  105.     CPI    2        ;SECOND ENTRY IN RECORD???
  106.     JZ    FORMREC
  107.     DAD    D        ;ADD 64 TO ADDRESS OF RECORD
  108.     CPI    3        ;THIRD ENTRY IN RECORD???
  109.     JZ    FORMREC
  110.     DAD    D        ;ADD 96 TO ADDRESS OF RECORD
  111. FORMREC    INX    H        ;PASS DRIVE BYTE
  112.     LXI    D,RFILE        ;MOVE FILE NAME
  113.     MVI    B,8        ;MOVE 8 CHARACTERS
  114.     CALL    MOVE
  115.     LXI    D,8        ;POSITION PAST NAME TO TYPE
  116.     DAD    D
  117.     LXI    D,RTYPE        ;MOVE TYPE
  118.     MVI    B,3        ;MOVE 3 CHARACTERS
  119.     CALL    MOVE
  120.     INX    H        ;POSITION TO THE EXTENT NUMBER
  121.     INX    H
  122.     INX    H
  123.     LXI    H,RTYPE        ;STRIP OFF THE HIGH BIT SET BY
  124.     MVI    B,11        ;THE VERSION PROGRAM
  125. STRIP    MOV    A,M
  126.     ANI    07FH
  127.     MOV    M,A
  128.     INX    H
  129.     DCR    B
  130.     JNZ    STRIP
  131.     LXI    H,RTYPE        ;SKIP OVER JUNK DISK ENTRIES
  132.     MVI    B,11        ;CONTAINING NONPRINTING CHARACTERS
  133. NONPRNT MOV    A,M
  134.     CPI    20H        ;ANY CHAR LESS THAN A BLANK
  135.     JC    NEXTFCB        ;GO TO NEXT ONE IF SO
  136.     INX    H
  137.     DCR    B
  138.     JNZ    NONPRNT
  139. FIRSTEXT    EQU    $    ;GOT THE FIRST EXTENT
  140.     LHLD    TABADDR        ;GET MEMORY TABLE ADDRESS
  141.     LXI    D,RTYPE        ;GET MEMORY RECORD ADDRESS
  142.     XCHG            ;RTYPE (HL) TO TABADDR (DE)
  143.     MVI    B,RECSIZE    ;MOVE RECSIZE BYTES
  144.     CALL    MOVE
  145.     LHLD    TABADDR        ;INCREMENT FOR NEXT ENTRY
  146.     LXI    D,RECSIZE        ;RECSIZE BYTES IN RECORD
  147.     DAD    D
  148.     SHLD    TABADDR        ;SAVE NEW ADDRESS
  149.     MVI    M,1AH        ;SET AN END-OF-TABLE INDICATOR
  150.     LHLD    TABCNT        ;GET RECORD COUNT
  151.     INX    H
  152.     SHLD    TABCNT        ;INCREMENT RECORD COUNT
  153.     LHLD    TABADDR        ;SEE IF NEW ADDRESS IS GREATER
  154.     XCHG            ;THAN THE TOP OF TPA-128
  155.     LHLD    BDOS+1        ;HL=TOP...DE=TABLE+RECSIZE
  156.     LXI    B,-128
  157.     DAD    B        ;SUBTRACT 128 FROM TOP
  158.     CALL    COMPREG        ;COMPARE REGISTER VALUES
  159.     JNC    NEXTFCB        ;THERE IS ROOM FOR MORE
  160.     MVI    A,1        ;NO MORE ROOM...ABORT NOW
  161.     STA    ABORT
  162.     RET
  163.  
  164. * COPY THE FILE FROM ONE DISK TO ANOTHER
  165. * THIS CODE WAS TAKEN FROM BACKUP.ASM SO HDFCB REFERS TO THE SOURCE DISK
  166. * AND FPFCB REFERS TO THE DESTINATION DISK REGARDLESS OF FLOPPY OR HARD.
  167.  
  168. CPYFILE    EQU    $
  169.     LHLD    ADDR2        ;GET THE CURRENT END OF TABLE
  170.     INX    H        ;PLUS ONE FOR THE START OF THE
  171.     SHLD    ADDR3        ;READ/WRITE BUFFER
  172.     LXI    H,RAM        ;SET THE ADDRESS OF THE FIRST ENTRY
  173.     SHLD    ADDR1
  174.     JMP    PASSMOVE
  175. NEXTFILE    EQU    $
  176.     LHLD    ADDR1
  177.     LXI    D,RECSIZE
  178.     DAD    D
  179.     SHLD    ADDR1
  180. PASSMOVE LHLD    ADDR1
  181.     MOV    A,M
  182.     CPI    1AH
  183.     RZ
  184. FORMFCB    LXI    D,HDFCB        ;CLEAR THE FCB
  185.     MVI    B,36
  186.     XRA    A
  187. ZEROFCB    STAX    D
  188.     INX    D
  189.     DCR    B
  190.     JNZ    ZEROFCB
  191.     LHLD    ADDR1        ;GET ADDRESS OF TABLE ENTRY
  192.     LXI    D,HDTYPE    ;MOVE IN THE TYPE
  193.     MVI    B,3
  194.     CALL    MOVE
  195.     INX    H
  196.     INX    H        ;POSITION TO NAME
  197.     INX    H
  198.     LXI    D,HDFILE    ;MOVE THE FILE NAME
  199.     MVI    B,8
  200.     CALL    MOVE
  201.     LXI    D,8
  202.     DAD    D        ;POSITION TO DISK ID, A:, B: ETC
  203.     LDA    SRCE
  204.     STA    HDFCB
  205.     LXI    D,FPFCB        ;COPY THE HDFCB TO THE FLOPPY FCB
  206.     LXI    H,HDFCB
  207.     MVI    B,36
  208.     CALL    MOVE
  209.     LDA    DEST
  210.     STA    FPFCB
  211.     LHLD    ADDR1
  212.     CALL    FORMAT
  213.     LXI    D,PRNTREC
  214.     CALL    OUTPUT
  215.     LXI    D,HDFCB        ;OPEN THE SOURCE FILE DRIVE
  216.     MVI    C,0FH
  217.     CALL    BDOS        
  218.     INR    A
  219.     JZ    NOTFOUND
  220.     LXI    D,FPFCB        ;SEE IF THE FILE IS ON THE DESTINATION DRV
  221.     MVI    C,0FH
  222.     CALL    BDOS        ;DUMMY OPEN
  223.     INR    A
  224.     JZ    MAKEIT        ;NOT THERE...MAKE IT
  225. ERAIT    EQU    $
  226.      LXI    D,FPFCB        ;DELETE THE FILE ON FLOPPY IF IT
  227.     MVI    C,13H        ;EXISTS
  228.     CALL    BDOS
  229. MAKEIT    EQU    $
  230.     LXI    D,FPFCB        ;CREATE THE FILE ON FLOPPY 
  231.     MVI    C,16H
  232.     CALL    BDOS        ;MAKE FILE
  233.     INR    A
  234.     JZ    DISKFULL
  235. COPYLOOP    CALL    LOADBUFF    ;LOAD MEMORY WITH FILE
  236.     CALL    WRITEBUF        ;WRITE MEMORY FILE
  237.     LDA    EOF
  238.     CPI    1
  239.     JZ    ENDOFFILE
  240.     CPI    2
  241.     JZ    DISKFULL
  242.     JMP    COPYLOOP
  243. ENDOFFILE    LXI    D,FPFCB        ;CLOSE FLOPPY FILE
  244.     MVI    C,10H
  245.     CALL    BDOS            ;CLOSE
  246.     JMP    NEXTFILE
  247. DISKFULL    LXI    D,FPFCB
  248.     MVI    C,13H        ;DELETE FILE ON FLOPPY
  249.     CALL    BDOS
  250.     LXI    D,MNTBLANK
  251.     CALL    QUESTION
  252.     MVI    C,0DH
  253.     CALL    BDOS
  254.     JMP    FORMFCB
  255. NOTFOUND LHLD    ADDR1
  256.     CALL    FORMAT
  257.     LXI    D,NFMSG
  258.     CALL    OUTPUT
  259.     LXI    D,PRNTREC
  260.     CALL    OUTPUT
  261.     RET
  262.  
  263.  
  264. * THE FOLLOWING ROUTINE IS A BUBBLE SORT.  IN PSEUDOBASIC
  265. * IS WOULD BE DONE AS FOLLOWS:
  266. *SORT    ADDR1=BOTTOM(RAM)-RECSIZE (RECSIZE IS COUNT OF BYTES IN ONE RECORD)
  267. *    MAX1=0
  268. *LOOP1    MAX1=MAX1+1
  269. *    ADDR1=ADDR1+RECSIZE    (FIRST TIME THIS WOULD BE THE BOTTOM)
  270. *    IF MAX1>TABCNT-1 THEN GO TO SORTED
  271. *    ADDR2=ADDR1
  272. *    MAX2=MAX1
  273. *LOOP2    MAX2=MAX2+1
  274. *    ADDR2=ADDR2+RECSIZE
  275. *    IF MAX2>TABCNT THEN GO TO LOOP1
  276. *    IF TABLE(ADDR1)<TABLE(ADDR2) THEN GO TO LOOP2
  277. *    TEMP=TABLE(ADDR1)
  278. *    TABLE(ADDR1)=TABLE(ADDR2)
  279. *    TABLE(ADDR2)=TEMP
  280. *    GO TO LOOP2
  281. *SORTED    RETURN
  282. *
  283. *NOW THAT THIS LOGIC IS INTUITIVELY OBVIOUS, HERE'S THE NOT SO
  284. *OBVIOUS CODE:
  285.  
  286. SORT    
  287.     LXI    H,0000        ;INITIALIZE COUNT
  288.     SHLD    MAX1        ;SINCE IT WILL DECREMENT FIRST
  289.     LXI    D,-RECSIZE    ;SUBTRACT RECSIZE FROM THE BEGINNING
  290.     LXI    H,RAM        ;OF THE TABLE SINCE IT WILL ADD
  291.     DAD    D        ;RECSIZE TO IT FIRST
  292.     SHLD    ADDR1
  293. LOOP1    LHLD    ADDR1        ;GET THE CURRENT ADDRESS
  294.     LXI    D,RECSIZE        ;INCREMENT IT BY RECSIZE
  295.     DAD    D        ;PAST THE NEXT ENTRY
  296.     SHLD    ADDR1
  297.     LHLD    MAX1        ;SEE IF THE COUNT HAS REACHED THE LIMIT
  298.     INX    H        ;INCREMENT THE COUNTER
  299.     SHLD    MAX1
  300.     XCHG            ;MOVE TO DE TO COMPARE TO LIMIT
  301.     LHLD    TABCNT
  302.     DCX    H        ; IS MAX1 > TABCNT - 1 ???
  303.     CALL    COMPREG        ;COMPARE DE (CURRENT COUNT) TO HL (TABCNT-1)
  304.     JC    SORTED        ;FINISHED WHEN MAX1 > TABCNT-1
  305.     LHLD    ADDR1        ;SETUP FOR THE INNER LOOP
  306.     SHLD    ADDR2
  307.     LHLD    MAX1
  308.     SHLD    MAX2
  309. LOOP2    LHLD    ADDR2        ;START WITH ONE ENTRY GREATER THEN
  310.     LXI    D,RECSIZE        ;THE OUTER LOOP AND INCREMENT
  311.     DAD    D        ;BY RECSIZE EACH TIME PAST THE NEXT RECORD
  312.     SHLD    ADDR2        ;POINTER TO THE CURRENT RECORD
  313.     LHLD    MAX2        ;LIKEWISE SEE IF THE COUNTER FOR THE
  314.     INX    H
  315.     SHLD    MAX2
  316.     XCHG
  317.     LHLD    TABCNT
  318.     CALL    COMPREG
  319.     JC    LOOP1        ;WHEN FINISHED, INCREMENT OUTER LOOP
  320.     LHLD    ADDR2
  321.     XCHG            ;ADDR2 NOW IN DE
  322.     LHLD    ADDR1
  323.     CALL    COMPARE        ;COMPARE STRINGS POINTED TO BY DE/HL
  324.     JNC    LOOP2        ;TABLE(HL) < TABLE (DE)
  325. * EXCHANGE THE TWO ENTRIES VIA A TEMPORARY RECORD
  326.     LXI    D,TEMP
  327.     LHLD    ADDR1
  328.     MVI    B,RECSIZE
  329.     CALL    MOVE        ;TEMP=TABLE(ADDR1)
  330.     XCHG            ;ADDR1=DESTINATION
  331.     LHLD    ADDR2        ;ADDR2=SOURCE
  332.     CALL    MOVE        ;TABLE(ADDR1)=TABLE(ADDR2)
  333.     XCHG            ;ADDR2 = DESTINATION
  334.     LXI    H,TEMP
  335.     CALL    MOVE        ;TABLE(ADDR2)=TEMP
  336.     JMP    LOOP2
  337. SORTED    RET            ;FINISHED SORTING
  338.  
  339.  
  340.  
  341. KILLDUPS EQU    $    ;KILL DUPLICATE ENTRIES FROM MULTIPLE EXTENTS
  342.     LXI    H,RAM
  343.     SHLD    ADDR1            ;SET THE START OF THE TABLE
  344. NEXTEQUAL    LHLD    ADDR1        ;CHECK EACH ENTRY AGAINST THE NEXT
  345.     LXI    D,RECSIZE
  346.     DAD    D
  347.     SHLD    ADDR2
  348. NEXTCHK    MOV    A,M            ;CHECK FOR END OF TABLE
  349.     CPI    1AH
  350.     RZ
  351.     XCHG
  352.     LHLD    ADDR1            ;COMPARE ADDR1 WITH ADDR2
  353.     MVI    B,RECSIZE
  354.     CALL    COMPARE
  355.     JNZ    SAVELAST
  356.     PUSH    H            ;SAVE CURRENT POSITION
  357.     LHLD    ADDR2            ;SET UP FOR MOVING LIST
  358.     SHLD    ADDR1            ;DOWN ONE ENTRY
  359.     LXI    D,RECSIZE
  360.     DAD    D            ;MOVE THIRD ENTRY TO THE SECOND
  361.     SHLD    ADDR2
  362.     CALL    MOVELIST
  363.     LHLD    TABCNT
  364.     DCX    H
  365.     SHLD    TABCNT
  366.     POP    H            ;RESTORE CURRENT POSITION
  367.     SHLD    ADDR1            ;NOW COMPARE 1ST & 3RD
  368.     JMP    NEXTEQUAL
  369. SAVELAST    LHLD    ADDR2        ;MAKE NEW ONE THE CURRENT ONE
  370.     SHLD    ADDR1
  371.     JMP    NEXTEQUAL        ;COMPARE
  372.  
  373. MOVELIST    LHLD    ADDR2        ;MOVE THE TABLE FROM ADDR2 DOWN
  374.     XCHG                ;TO ADDR1 THEREBY ELIMINATING
  375.     LHLD    ADDR1            ;UNWANTED ENTRIES
  376. MOVENEXT    LDAX    D        ;AND MAKING MORE ROOM FOR THE
  377.     MOV    M,A
  378.     CPI    1AH
  379.     RZ
  380.     INX    H
  381.     INX    D
  382.     JMP    MOVENEXT
  383.  
  384.  
  385. * ASSORTED ROUTINES
  386.  
  387.  
  388. LOADBUFF    EQU    $    ;THIS ROUTINE LOADS AS MUCH OF
  389.     LXI    H,0000        ;MEMORY WITH THE FILE AS POSSIBLE
  390.     SHLD    MAX1
  391.     LHLD    ADDR3        ;NEW TOP OF TABLE +2
  392.     SHLD    TEMP
  393.     XRA    A
  394.     STA    EOF        ;CLEAR EOF FLAG
  395. LOADNEXT    LHLD    TEMP
  396.     XCHG            ;SET DMA ADDRESS
  397.     MVI    C,1AH
  398.     CALL    BDOS
  399.     LXI    D,HDFCB        ;READ HARD DISK
  400.     MVI    C,14H
  401.     CALL    BDOS
  402.     ORA    A
  403.     JNZ    HDEOF        ;EOF?
  404.     LHLD    MAX1
  405.     INX    H        ;INCREMENT RECORD COUNT
  406.     SHLD    MAX1
  407.     LHLD    TEMP        ;SEE IF NEXT RECORD WOULD EXCEED THE
  408.     LXI    D,128        ;TPA AREA
  409.     DAD    D
  410.     SHLD    TEMP
  411.     DAD    D        ;WILL THE NEXT RECORD OVERWRITE BDOS?
  412.     XCHG
  413.     LHLD    BDOS+1        ;FIND THE TOP OF MEMORY
  414.     CALL    COMPREG        ;COMPARE REGISTERS
  415.     RC            ;RETURN IF MEMORY ALREADY FULL
  416.     JMP    LOADNEXT    ;GET ANOTHER RECORD
  417. HDEOF    MVI    A,1        ;SET FILE EOF
  418.     STA    EOF
  419.     RET
  420.  
  421. WRITEBUF    EQU    $    ;WRITE FROM THE MEMORY BUFFER
  422.     LHLD    ADDR3
  423.     SHLD    TEMP
  424.     LHLD    MAX1        ;ALLOW FOR FILES THAT HAVE NO 
  425.     LXI    D,0000        ;RECORDS SUCH AS RESTART
  426.     CALL    COMPREG
  427.     RZ
  428. WRITENEXT    LHLD    TEMP
  429.     XCHG            ;SET DMA ADDRESS
  430.     MVI    C,1AH
  431.     CALL    BDOS
  432.     LXI    D,FPFCB
  433.     MVI    C,15H        ;WRITE SEQUENTIAL
  434.     CALL    BDOS
  435.     ORA    A
  436.     JNZ    FPFULL        ;FLOPPY DISK FULL
  437.     LHLD    MAX1        ;DECREASE RECORD COUNT
  438.     DCX    H
  439.     SHLD    MAX1
  440.     LXI    D,0000        ;CHECK FOR NO MORE TO WRITE
  441.     CALL    COMPREG
  442.     RZ
  443.     LHLD    TEMP
  444.     LXI    D,128        ;INCREMENT WRITE ADDRESS
  445.     DAD    D
  446.     SHLD    TEMP
  447.     JMP    WRITENEXT
  448. FPFULL    MVI    A,2        ;FULL DISKETTE
  449.     STA    EOF
  450.     RET
  451.  
  452. FORMAT    LXI    D,PRNTYPE    ;FORMAT THE ENTRY FROM THE TABLE
  453.     MVI    B,3        ;FORMAT TO THE PRINT FORMAT
  454.     CALL    MOVE        ;THE TABLE ADDRESS IS ASSUMMED TO BE
  455.     LXI    D,3        ;IN HL. FIRST MOVE THE TYPE
  456.     DAD    D        ;NOW POSITION TO THE FILE NAME
  457.     LXI    D,PRNFILE    ;MOVE THE FILE NAME
  458.     MVI    B,8
  459.     CALL    MOVE
  460.     LXI    D,8        ;POSITION TO THE DISK ID
  461.     DAD    D
  462.     LDA    SRCE
  463.     ORI    40H
  464.     STA    PRNTREC
  465.     MVI    A,':'
  466.     STA    PRNTREC+1
  467.     MVI    A,'.'
  468.     STA    PRNTYPE-1
  469.     RET
  470.  
  471. COMPREG    MOV    A,H        ;COMPARE HL TO DE
  472.     CMP    D
  473.     RNZ
  474.     MOV    A,L
  475.     CMP    E
  476.     RET
  477.  
  478. OUTPUT    PUSH    D        ;PUT OUT A CRLF
  479.     LXI    D,CRLF
  480.     MVI    C,09
  481.     CALL    BDOS
  482.     POP    D        ;NOW PUT OUT THE MESSAGE
  483. OUT1    MVI    C,09
  484.     JMP    BDOS
  485.  
  486.  
  487. QUESTION    CALL    OUTPUT    ;PUT OUT THE QUESTION
  488.     LXI    D,INBUF
  489.     MVI    C,0AH        ;INPUT THE REPLY
  490.     CALL    BDOS
  491.     LDA    INCNT        ;SEE IF ANYTHING WAS ENTERED
  492.     RET
  493.  
  494. MOVE    PUSH    H        ;MOVE DATA POINTED TO IN HL
  495.     PUSH    D        ;TO THE AREA POINTED TO IN DE
  496.     PUSH    B        ;BY THE BYTE COUNT IN B
  497. MOVE1    MOV    A,M
  498.     ANI    7FH        ;RESET THE HIGH ORDER BIT BECAUSE IT
  499.                 ;MAY HAVE BEEN TURNED ON FOR THE TYPE
  500.     STAX    D
  501.     INX    H
  502.     INX    D
  503.     DCR    B
  504.     JNZ    MOVE1
  505.     POP    B        ;RESTORE THE TOTAL ENVIRONMENT
  506.     POP    D
  507.     POP    H
  508.     RET
  509.  
  510. COMPARE    PUSH    H        ;COMPARE THE STRINGS POINTED TO IN HL
  511.     PUSH    D        ;TO THE STRING POINTED TO IN DE
  512.     PUSH    B        ;FOR A LENGTH OF B CHARACTERS
  513. COMP1    LDAX    D        ; JC IF HL > DE
  514.     CMP    M        ; JZ IF HL = DE
  515.     JNZ    COMP2        ;JNC IF HL < DE
  516.     INX    H
  517.     INX    D
  518.     DCR    B
  519.     JNZ    COMP1
  520. COMP2    POP    B
  521.     POP    D
  522.     POP    H
  523.     RET
  524.  
  525.  
  526. SIGNON    DB    'MULTIPLE FILE COPY PROGRAM '
  527.     DB    '10/9/82$'
  528. ERRNOMSK DB    'ERROR...NO FILE MASK IN COMMAND'
  529.     DB    CR,LF,'COMMAND MUST BE IN THE FORMAT "MULTCOPY *.*"'
  530.     DB    CR,LF,'$'
  531. NFMSG    DB    'FILE NOT FOUND...ABORTING$'
  532. DMNTMSG    DB    'DISMOUNT DISKETTE AND ENTER RETURN$'
  533. MNTBLANK DB    'MOUNT A FORMATTED BLANK DISKETTE AND ENTER RETURN$'
  534. PRNTREC    DS    1
  535.     DB    ':'
  536. PRNFILE    DS    8
  537.     DB    '.'
  538. PRNTYPE    DS    3
  539.     DB    '    $'
  540. CRLFLFLF    DB    0DH,0AH,0AH,0AH,'$'
  541. CRLF    DB    0DH,0AH,'$'
  542. BIGMSG    DB    0DH,0AH,'FILE TOO LARGE TO FIT ON ONE DISKETTE '
  543.     DB    'SO NOT BACKED UP **** $'
  544. DESTFLPMSG DB    'DESTINATION FLOPPY DRIVE (DEFAULT='
  545. DESTFLP    DB    'D) $'
  546. HDFCB    DS    1
  547. HDFILE    DS    8
  548. HDTYPE    DS    3
  549.     DS    24
  550. FPFCB    DS    36
  551. FLOPPY    DS    1
  552. SRCE    DS    1
  553. DEST    DS    1
  554. INBUF    DB    30
  555. INCNT    DS    1
  556. INREC    DS    30
  557. STACK    DS    80
  558. EOF    DS    1
  559. ABORT    DS    1
  560. LINECNT    DS    1
  561. LASTTYPE DS     3
  562. LASTFILE DS    8
  563. TABADDR    DS    2
  564. TABCNT    DS    2
  565. SELFLAG    DS    1
  566. TOOBIG    DS    1
  567. ADDR1    DS    2
  568. ADDR2    DS    2
  569. ADDR3    DS    2
  570. MAX1    DS    2
  571. MAX2    DS    2
  572. RTYPE    DS    3
  573. RFILE    DS    8
  574. RDISK    DS    3
  575.     DB    '$'
  576. TEMP    DS    RECSIZE
  577. DISKBUF    DS    128
  578. COMPSIZE DS    1
  579. CR    EQU    0DH
  580. LF    EQU    0AH
  581. RAM    EQU    $
  582.     END    100H
  583.