home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / cpmug / cpmug081.ark / FLOPCOPY.ASM < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  15.6 KB  |  673 lines

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