TITLE 'CP/M "DCOPY" FUNCTION 1/78' ; ; DISK COPY FUNCTION, COPIES FROM DISK A TO DISK B UNTIL 0E5H'S ; ; COPYRIGHT (C) 1977, 1978 ; DIGITAL RESEARCH ; BOX 579 PACIFIC GROVE ; CALIFORNIA, 93950 ; ORG 100H JMP START DB 'COPYRIGHT (C) 1978, DIGITAL RESEARCH ' ; ; GLOBAL EQUATES BOOT EQU 0000H BDOS EQU 0005H ; SPT EQU 58 ;SECTORS PER TRACK BPS EQU 128 ;BYTES PER SECTOR BPT EQU BPS*SPT ;BYTES PER TRACK TPD EQU 77 ;TRACKS PER DISK OSTRKS EQU 2 ;TRACKS FOR OS ; CONIN EQU 1 ;READ CONSOLE DEVICE RDBUFF EQU 10 ;READ BUFFER PBUFF EQU 9 ;PRINT BUFFER CR EQU 0DH LF EQU 0AH ; READTRK EQU $ WRITTRK EQU $+3 REREAD EQU $+6 JMP READ$DISK JMP WRITE$DISK JMP RE$READ$DISK TRACK: DS 1 ;SET TO TRACK TO READ/WRITE BUFFA: DS 2 ;SET TO BUFFER ADDRESS TO READ/WRITE IOF: DS 1 ;IO FUNCTION 0 = READ, 1 = WRITE ; READ$DISK: ;READ DISK DRIVE A, FROM TRACK 'TRACK' ;INTO THE ADDRESS GIVEN BY 'BUFFA' XRA A! CALL SEL ;SELECT DRIVE A JMP READ$D ; ; WRITE$DISK: ;WRITE TO DISK DRIVE B, TO TRACK 'TRACK' ;FROM THE ADDRESS GIVEN BY 'BUFFA' MVI A,1! STA IOF ;SET IOFUNCTION TO WRITE CALL SEL ;SELECT DRIVE B JMP RW$DISK ; RE$READ$DISK: ;READ FROM DISK DRIVE B, FROM TRACK 'TRACK' ;TO THE ADDRESS GIVEN BY 'BUFFA' MVI A,1! CALL SEL ;DRIVE B SELECTED READ$D: XRA A! STA IOF ;SET TO READ FUNCTION RW$DISK: ;READ OR WRITE DISK LXI H,TRACK! MOV C,M ;GET TRACK NUMBER CALL TRK ;TRACK SELECTED LHLD BUFFA ;GET DMA ADDRESS LXI D,spt ;D = 0, E = spt RW$LOOP: ;READ/WRITE LOOP INR D ;TO NEXT SECTOR PUSH D! PUSH H mov c,d! mvi b,0 lxi h,skewtbl-1! dad b MOV C,m! CALL SEC ;SECTOR SET POP B! PUSH B ;GET DMA ADDRESS CALL DMA ;DMA ADDRESS SET ;PERFORM IO FUNCTION LDA IOF! ORA A ;SET FLAGS, 0=READ, 1=WRITE JNZ WRITEFUNC ;READ DISK CALL DREAD JMP RWCOMPLETE WRITEFUNC: ;WRITE DISK CALL DWRITE RWCOMPLETE: ;FUNCTION COMPLETE POP H ;RECALL DMA ADDRESS LXI D,80H! DAD D ;TO NEXT DMA POP D ;RECALL SECTOR AND COUNT ; CHECK ERROR CONDITIONS ORA A! RNZ ;RETURN WITH NON ZERO FLAG SET DCR E ;COUNT = COUNT - 1 JNZ RW$LOOP ;FOR ANOTHER SECTOR RET ;WITH ZERO FLAG SET FOR IO COMPLETE ; ; ; ; UTILITY SUBROUTINES FOR DIRECT DISK IO WBOOT EQU 1 ;WARM BOOT ADDRESS SELDSK EQU 24 ;SELECT DISK SETTRK EQU 27 ;SET TRACK SETSEC EQU 30 ;SET SECTOR SETDMA EQU 33 ;SET DMA ADDRESS READF EQU 36 ;READ DISK WRITF EQU 39 ;WRITE DISK ; SEL: ;SELECT DRIVE GIVEN BY REGISTER A MOV C,A! LHLD WBOOT! LXI D,SELDSK! DAD D! PCHL ; TRK: ;SET TRACK GIVEN BY C LHLD WBOOT! LXI D,SETTRK! DAD D! PCHL ; SEC: ;SET SECTOR GIVEN BY C LHLD WBOOT! LXI D,SETSEC! DAD D! PCHL ; DMA: ;SET DMA ADDRESS TO VALUE OF B,C LHLD WBOOT! LXI D,SETDMA! DAD D! PCHL ; DREAD: ;PERFORM READ OPERATION LHLD WBOOT! LXI D,READF! DAD D! PCHL ; DWRITE: ;PERFORM WRITE OPERATION LHLD WBOOT! LXI D,WRITF! DAD D! PCHL ; START: LXI SP,STACK RDDSK: ;PRINT PROMPT AND WAIT FOR RESPONSE TO CONTINUE CALL INSMSG! CALL CI ;WAIT FOR RESPONSE cpi 03! jz boot! cpi 0dh! jnz rddsk ; ;NEW DISK IS READY, TRY THE COPY OPERATION LXI H,TRACK! MVI M,ostrks ;CLEAR THE TRACK NUMBER LXI H,TRCOUNT! MVI M,'0'! INX H! MVI M,'0' ; RDTRK: ;READ THE NEXT SOURCE TRACK, COMPARE WITH 0E5H FOR END LXI H,IBUFF! SHLD BUFFA! CALL READTRK JZ READOK! CALL READ0MSG! JMP RDDSK READOK: LDA TRACK! CPI OSTRKS! JC WRTRK ;MAY BE DATA DISK ;TRACK IN MEMORY, CHECK FOR LAST TRACK LXI H,IBUFF! LXI B,TRLEN TRCOMP: MVI A,0E5H! CMP M! JNZ WRTRK INX H! DCX B! MOV A,C! ORA B! JNZ TRCOMP ;END OF COPY, ALL 0E5H'S JMP ENDCOPY ;TERMINATE COPY AND RETURN ; ;NOT END OF COPY, WRITE TRACK TO DISK FROM IBUFF WRTRK: CALL WRITTRK JZ WROK! CALL WRITE0MSG! JMP RDDSK WROK: ;WRITTEN TO DISK, NOW READ IT BACK AND COMPARE LXI H,OBUFF! SHLD BUFFA! CALL REREAD JZ READ1OK! CALL READ1MSG! JMP RDDSK READ1OK: LXI H,IBUFF! LXI D,OBUFF! LXI B,TRLEN WRCOMP: LDAX D! CMP M! JNZ WRERR INX H! INX D! DCX B! MOV A,C! ORA B JNZ WRCOMP ;COMPARE WENT OK, INCREMENT TRACK COUNT AND CYCLE LXI H,TRACK! INR M MOV A,M! CPI TPD! JNC ENDCOPY ;TERMINATE BY END OF DISK LXI H,TRCOUNT+1! INR M! MOV A,M! CPI '9'+1 JC RDTRK ;OVERFLOW TO HIGH ORDER TRACK NUMBER MVI M,'0'! DCX H! INR M! JMP RDTRK ; WRERR: ;VERIFY ERROR CALL VERERR! JMP RDDSK ; ; ENDCOPY: ; ARRIVE HERE AT END OF COPY TO PRINT FINAL MESSAGE AND BOOT LXI D,TRMSG! CALL PRMSG ;NUMBER OF TRACKS JMP RDDSK ; ; ; ; UTILITY SUBROUTINES CI: MVI C,CONIN! JMP BDOS ;READ A CHARACTER ; PRMSG: MVI C,PBUFF! JMP BDOS ;PRINT A BUFFER ; ; ; ; PRINT STRINGS INSMSG: LXI D,$+6! JMP PRMSG db cr,lf,'DCS-2 Double Density' DB CR,LF,'INSERT SOURCE DISK IN A, NEW DISK IN B, TYPE RETURN$' ; ; VERERR: LXI D,$+6! JMP PRMSG DB CR,LF,'VERIFICATION ERROR, BAD DISK$' ; READ0MSG: LXI D,$+6! JMP PRMSG DB CR,LF,'ERROR ON SOURCE DISK, REPLACE$' ; WRITE0MSG: LXI D,$+6! JMP PRMSG DB CR,LF,'CANNOT WRITE NEW DISK, REPLACE$' ; READ1MSG: LXI D,$+6! JMP PRMSG DB CR,LF,'CANNOT RE-READ NEW DISK, REPLACE$' ; ; ; MISCELLANEOUS DATA AREAS ; TRMSG: DB CR,LF TRCOUNT: DB '00 TRACKS VERIFIED$' ; SKEWTBL: DB 1,19,37,55 DB 15,33,51,11 DB 29,47,7,25 DB 43,3,21,39 DB 57,17,35,53 DB 13,31,49,9 DB 27,45,5,23 DB 41,10,28,46 DB 6,24,42,2 DB 20,38,56,16 DB 34,52,12,30 DB 48,8,26,44 DB 4,22,40,58 DB 18,36,54,14 DB 32,50 DS 32 ;STACK STACK: TRLEN EQU SPT*BPS ;BUFFER SIZE IBUFF: DS TRLEN OBUFF: DS TRLEN END 100H