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 / HDUTL / FLOPCOPY.ASM < prev    next >
Assembly Source File  |  2000-06-30  |  17KB  |  709 lines

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