ţţčX;SAVE #D2:DUPDUP.M65ňAŽDUPLICATE DISKAü+X; **** DUPLICATE DISK ROUTINE ****X;X;)X; FMS equates needed for VTOC access:$X;.*†DVDWRQ;; Write required flag offset8)†DVDSMP ;; Offset of start of bitmapVX;`X;j,„DDMG AœDUP DISK-SOURCE,DEST DRIVES?A=‚CRt<‚OK A…TYPE A="=AYA="=Aš IF OK TO USE PROGRAM AREAA=‚CR~X;ˆ?„CMSI A‹CAUTION: A A="=AYA="=A• INVALIDATES MEM.SAV.A=‚CR’X;œ7X; RVTOC READS VOLUME TABLE OF CONTENTS SECTORŚX;°2…RVTOCQ>5„DBUF;; Use data buffer as VTOC bufferşP‡VTOCPTRÄ Q>4„DBUFÎ P‡VTOCPTRŘ1Q„UNNO;; Use source drive number for VTOC readâ P†ICDNOZě&Q>;; Turn off write required flagö)P„DBUF†DVDWRQ;; so VTOC will be read. ‰CALLRVTOC 6I‡:READOK;; If error occurred, tell user and abort. !†CIOER1X;(‡:READOKQ>†DVDSMP2PƒPTR<Q„DBUF†DVDSMPFP„CSRC;;BYTE OF ALLOC MAPPQ>ZP„IPTR;;COUNT BITS IN BYTEdQ>nP„DSHI;;POINT TO SECTOR ONExQ>‚ P„DSLOŒ:–X; X;ކDUPDSK „DDMG´Q>;;ASSUME SINGLE DRIVEžP†TWODRV;;CLEAR FLAGČ †GETLINŇ …GETDNÜP„UNNO;;UNIT NO FOR READć …GETDNđ#P„CDES;;CDES IS THE DEST DRIVE #ú „PERXX;2X; CHECK IF TWO DRIVE OR SINGLE DRIVE DUPX;"„SAMEQ„UNNO,!R„CDES;;IF BOTH UNITS THE SAME6FƒSDD;;SINGLE DRIVE DUP@ $>5ƒIBDJ Q>4ƒIBDT( †DSPLIN;;PROMPT TO INSERT BOTH DISKS^ †CHRGETh"†TWODRV;;SET TWO DRIVE FLAGrG†DODKDP;;GO DUP DISK|-ƒIBD AžINSERT BOTH DISKS, TYPE RETURNA=‚CR†X;X;šX;¤LX;USED BY BOTH SINGLE & DOUBLE DRIVE DUP. WILL NOT ASK TO SWAP IF 2 DRIVEŽX;FLAG (TWODRV) IS SET.¸(X;IF THE TWO DRIVE FLAG IS CLEAR WILLÂ6X;FILL FROM SOURCE DISK, SWAP, EMPTY, SWAP, REPEAT.ĚX;Ö*ƒSDDQ>4ƒISD;;TELL USER TO INSERT SOURCEŕ3$>5ƒISD;;FOR INITIAL READ - USED ONLY FOR SINGLEę †DSPLIN;;DRIVE DUPLICATEô †CHRGETţ-†DODKDPQ>4…NMDUP;;SET BUFFER AT END OF DUP P…STVEC Q>5…NMDUP P…STVEC&X;04X; BUFFER BOTTOM MOVES FROM NMDUP TO MEMTOP:@X; SET END OF BUFFER TO MEMTOP MINUS 1 SECTOR IN BYTES.DFX; WHEN BUFFER BOTTOM IS LESS THAN OR EQUAL TO BUFFER END, ATN5X; LEAST ONE MORE SECTOR WILL FIT IN MEMORY.XX;b Q†MEMTOPl;v"S>4†SECSIZ;;T1 IS END OF BUFFER€P‚T1ŠQ†MEMTOP” S>5†SECSIZž+P‚T1;;T1 IS MEMTOP MINUS SECTOR SIZE.¨X;˛)X;SEE IF ROOM FOR AT LEAST ONE SECTOR!źX;Ć!Q‚T1;;DO DOUBLE PRECISION TESTĐR…STVEC;;TO SEE IF ROOMÚ+Q‚T1;;IF T1 IS = STVEC THEN ENUF ROOMäS…STVEC;;FOR ONE SECTORî"E„ENUF;;BRANCH IF (T1)>=(STVEC)ř„NORMQ>4ƒNRM $>5ƒNRM  †DSPLIN !†MENUSL X;*+„ENUF …CKMEM;;SEE IF OK TO USE USER AREA4Q>>)PƒOPT;;SET UP FOR READ HERE FIRST PASSH0P‰FIRSTTIME;; and set the pass number to zeroR …RVTOC;;READ VTOC\&Q„DSLO;;COPY INITIAL WRITE POINTERSf#P„SWDP;;TO INITIAL READ POINTERSp Q„DSHIz P„SWDP„QƒPTRŽ P„SWDP˜ Q„IPTR˘ P„SWDPŹ Q„CSRCś P„SWDPŔ!!„LRS1;;SKIP FIRST READ PROMPTĘX;Ô7X;READ FROM SOURCE DISK TIL BUF FULL OR END OF DATA.ŢX;č!„DORDQ>;;FLAG WE ARE READINGňPƒOPTü*†TWODRV;;TEST FOR 2 DRIVES G„LRS1;;YES, SKIP THE SWAP Q>4ƒISD;;INSERT SRC DISK $>5ƒISD$ †DSPLIN. †CHRGET8 X;B "X;SWAP POINTERS TO WHERE WE AREL X;V 1„LRS1 †DOSWDP;;SWAP SECTOR AND BITMAP POINTERS` X;j 0X;LOOP READING/WRITING SECTORS TO BUFFER AREAt X;~ $ƒLRS ƒAAM;;ADVANCE ALLOCATION MAPˆ 0G„ASPT;;IF FREE, ADV SECTR POINTER & TRY AGIN’ *ƒOPT;;SEE WHAT MODEœ GƒDOW;;BR IF WRITEŚ  …RSEC1;;DO READ° !ƒIODş ƒDOW …DKWRT;;DO WRITEÄ 'ƒIODQ†DBUFLO;;ADVANCE BUFFER POINTERÎ #N>€;; Add 128 to buffer pointerŘ P†DBUFLOâ G„ASPTě #†DBUFHI („ASPT ƒASP;;GO ADVANCE SECTOR POINTER 0QƒPTR;; Check to see if we're past end of map R‡MAXVTOC( /F…STDD1;;ALL SECTORS DONE, SWAP TO DEST DISK2 Q‚T1;;SEE IF ROOM FOR ANOTHER< R†DBUFLO;;SECTOR BELOW MEMTOPF Q‚T1P S†DBUFHIZ 2EƒLRS;;BRANCH IF (DBUF)<=(T1) - ROOM FOR MORE.d X;n X;SWAP DISKS AND CONTINUEx X;‚ „STDDQƒOPTŒ G„DORD;;IF WAS WRITE, GO READ– …STDD2"ƒOPT;;CHANGE TO WRITE  %*†TWODRV;;ARE 2 DRIVES BEING USED?Ş G‡:CHKFMT;;YES, SKIP THE SWAP´ Q>4ƒIDD;;INSERT DEST DISKž $>5ƒIDDż †DSPLINŔ †CHRGETČ X;Ň 6‡:CHKFMTQ‰FIRSTTIME;; Is this the first write pass?Ü H„LRS1ć #‰FIRSTTIMEç 1Q„CDES;; Set destination drive as format driveč L> 0é P„CDSKđ X;ú X; Format destination disk X; +%> !;; Use single density format command !Q‡MAXVTOC;; unless in MFM mode" I‡:NOTMFM, %> "6 9‡:NOTMFMQ„DSLO;; Save ending sector of first read pass7 58 Q„DSHI9 5? Q>ˆFORCEFMT@  …DOFMT;; Try to format diskB 7C P„DSHID 7E P„DSLOT !„LRS1^ X;h …STDD1QƒOPT;;END OF DATAr I…STDD2;;IF READ GO WRITE| +Q„CDES;; Write VTOC to destination drive† P†ICDNOZ‡ 3Q>4„DBUF;; Set VTOC buffer address to our bufferˆ P‡VTOCPTR‰ Q>5„DBUFŠ P‡VTOCPTR  ‰CALLWVTOCš ,Iˆ:WRITEOK;; Report error if write failed¤ !†CIOER1Ž *ˆ:WRITEOK!†MENUSL;;IF WRITE WE ARE DONE¸ X; AX;DOSWDP - EXCHANGE CURRENT AND SAVED BITMAP & SECTOR POINTERSĚ X;ALSO INIT BUFFER POINTERÖ X;ŕ †DOSWDP%>ę …SWLOPQ…SWATL8ô P…RAMLOţ Q…SWATH8 .P…RAMLO;;GET ADDRESS FROM TABLE TO RAMLO $> Q@…RAMLO6;;GET WHAT'S THERE& 50 Q„SWDP8: P@…RAMLO6D 7N P„SWDP8X 1b I…SWLOPl Q…STVECv P†DBUFLO€ Q…STVECŠ P†DBUFHI” :ž X;¨ ‰FIRSTTIME˛ X;ź Ć +…SWATL 4„DSLO=4„DSHI=4ƒPTR=4„IPTR=4„CSRCĐ +…SWATH 5„DSLO=5„DSHI=5ƒPTR=5„IPTR=5„CSRCÚ X;ä X;î ƒNRM ANOT ENOUGH ROOMA=‚CRř -ƒISD AžINSERT SOURCE DISK,TYPE RETURNA=‚CR 2ƒIDD AŁINSERT DESTINATION DISK,TYPE RETURNA=‚CR X; X; +X; AAM - ADVANCE ALLOCATION MAP ONE BIT.* X; RETURN MINUS IF FREE.4 X;> $ƒAAMT„CSRC;;NEXT BIT OF ALLOC MAPH "„IPTRR !H„CBIT;;IF DONE WITH THIS BYTE\ #ƒPTR;;GET NEXT ONEf $ƒPTRp 3Q„DBUF9;;VTOC IS DBUF & BITMAP STRTS IN 10TH BYTz P„CSRC„ Q>Ž P„IPTR˜ „CBITQ„CSRC;;CHECK THE BIT˘ :Ź X;ś X;Ŕ *X; ASP - ADVANCE SECTOR POINTER IN DCB.Ę X;Ô ƒASP#„DSLOŢ H„ASPXč #„DSHIň „ASPX:ü X;2X; RSEC1 - READ A SECTOR WHOSE NUMBER IS IN DCBX;…RSEC1Q„UNNO$*,;;TELL DISK HANDLER DOING A GET SECTOR. D†:SECIO8X;BX; DKWRT - WRITE A SECTORLX;V …DKWRTQ„CDES;;PUT DEST UNIT #`*;;;TELL DISK HANDLER DOING WRITE SECTORj †:SECIOt P…DUNIT~! …BSIOR;;GOTO FMS DISK HANDLERˆ I„DRTS;;RETURN IF GOOD STATUS’$!†CIOER1;;CIO ERROR, GO SAY WHICHœ„DRTS:;; just returnŚX;°.X; CKMEM - ASK IF OK TO USE USER AREAşX;Ä'…CKMEMQ†WARMST;;IF MEMORY WAS INTACTÎF…CPTR1;;QUERY TO BOMB ITŘ Q>4‚OKâ$>5‚OK;;PRINT PROMPTě †DSPLINöQ>4„CMSI;;PRINT CAUTION MSG/$>5„CMSI;;Y RESPONSE WILL INVALIDATE MEM.SAV  †DSPLIN †CHRGET&R> Y;;TEST FOR OK TO BOMB USER AREA(&H„DDXT;;IF SAY NO THEN DON'T DO DUP2Q><*P†WARMST;;TELL CART NO GOOD USER MEMORYF(P†MEMFLG;;TELL LOADER NO GOOD MEM.SAVP …CPTR1:ZX;d„DDXT7;;POP RETURN ADDRESSn7x$!†MENUSL;;GOTO MENU, DON'T DO DUP‚X;