title KAYPRO COPY (diskette copying utility) 2.0 Copyright (C) 1982 NLS, Inc. ;############################################################### ;## High speed diskette copy program ## ;## Copyright (C) 1982 by Non-Linear Systems, Inc. ## ;## No warranty is made, expressed, or implied. ## ;## ## ;############################################################### ;## Last update: july 13,1982 [001] ## ;## by jim nickerson ## ;## fix spelling of verifing=verifying ## ;############################################################### .z80 maxsec equ 10 ; sectors/track maxtrk equ 40 ; tracks/disk cmnd equ 10H ; command port data equ 13H ; data port secp equ 12H ; sector port trkp equ 11H ; track port status equ 10H ; status port rdcmd equ 80H ; read sector command rdmask equ 9CH ; read status mask wrtcmd equ 0A0H ; write sector command wrtmask equ 0FCH ; write status mask ficmd equ 0D0H ; force int command seekcmd equ 10H ; seek command rstcmd equ 00 ; home command bitport equ 1CH ; system bit port cr equ 0DH ; ascii return lf equ 0AH ; ascii line feed bdos equ 5 ; bdos entry point ; print a message print macro x ld c,9 ld de,x call 5 endm ; get a char from console, up case input macro ld c,1 call 5 res 5,a endm ; ; ;******************************************************** ; ; call disdoff ask: call endoff ld a,0FFH ld (some),a ;reset error flag=no errors print menu input ; get a character call disdoff cp 'C' ; copy? jp z,copy1 cp 'F' ;fast copy? jp z,fcopy1 cp 'V' ;verify? jp z,veri1 cp 'E' ; Exit? jr nz,ask call endoff jp 0 ; ; ;fix so disk won't turn off when any key hit ; disdoff: push hl push de ld hl,(0FA0AH) ;orig conin jmp in cbios ld (oldconin),hl ;save it ld de,0AH add hl,de ld (0FA0AH),hl pop de pop hl ret ; endoff: push hl ld hl,(oldconin) ;get original ld (0FA0AH),hl ;restore it pop hl ret ; oldconin: defw 0 ; ; copy1: call copy ; copy disk veri1: call verify ; verify disk jr wifer fcopy1: call copy ; copy disk only jr ask wifer: ;wait for char if error has occured call endoff ld a,(some) ;error flag cp 0 ;0=some errors jr nz,getout print pause input jp ask ; getout: print adone jp ask ; copy: ld a,(66H) ; get and save byte at nmi ex af,af' ld a,0C9H ; RET op code ld (66H),a print crlf print crlf call diskon ; turn on disk drives call home ; home both disk drives xor a ; zero track number dotrk: ld (track),a ; set track number call seeka ; seek track drive a print back call tellt ; tell crt track number ld hl,buff ; starting track image ld (dmaadr),hl xor a ; zero sector number doa: ld (sector),a ; store sector number call read ; read a physical sector to dmaadr call nz,tella ; error, tell track and sector ld a,(sector) ; next sector inc a cp maxsec ; end of track? jr c,doa ; another sector yet to do call seekb ; now write track to b, seek track ld hl,buff ; back to beginning of buffer ld (dmaadr),hl xor a ; reset sector dob: ld (sector),a ; current sector call write ; write sector to disk call nz,tellb ; error, tell track and sector ld a,(sector) ; move to next sector inc a cp maxsec ; end of track? jr c,dob ; more sectors ld a,(track) ; next track inc a cp maxtrk ; end of disk? jp c,dotrk ex af,af' ld (66H),a ; restore byte at nmi vector print adone ret ; go back to main p/g verify: ld a,(66H) ; ‰get and save byte at nmi vector ex af,af' ld a,0C9H ; RET op code ld (66H),a print crlf print crlf print vermsg ; tell crt that verify p/g is beginning print crlf print crlf call diskon ; turn disk drives on call home ; home both disk drives xor a ; zero track number vrtrk: ld (track),a ; set track number call seeka print back call tellt ; tell the track number ld hl,buff ; set up dma adrs ld (dmaadr),hl xor a ; zero sector number vera: ld (sector),a ; store current sector number call read ; read a physical sector to dmaadr call nz,tella ; error, tell track and sector ld a,(sector) ; read all of track inc a cp maxsec jr c,vera call seekb ; seek track drive B ld hl,buffb ; set up dma adrs for disk B ld (dmaadr),hl xor a verb: ld (sector),a ; set up sector call read ; read sector from B call nz,tellb ; tell any errors from read ld a,(sector) ; next sector inc a cp maxsec ; end of track? jr c,verb ; another sector yet to do call vrdata ; go verify data on tracks vert: ld a,(track) ; next track inc a cp maxtrk ; end of disk? jp c,vrtrk ex af,af' ld (66H),a ; restore byte at nmi vector ret ; vrdata: ld bc,0 ; reset error count ld (bytcnt),bc ld de,buff ; starting adrs of disk A buffer ld (adrsa),de ; store it ld hl,buffb ; starting adrs of disk B buffer ld (adrsb),hl ; store it vrdat: ld a,(hl) ; get disk B data byte ld b,a ; save it ld a,(de) ; get disk A data cp b ; is the data the same jp nz,vrerr ; no -- go tell about error ld bc,(bytcnt) ; add one to loop counter inc bc ld (bytcnt),bc ld a,14H cp b ; have 5120 bytes been verrified ret z ; yes -- go read next track ld hl,(adrsb) inc hl ; inc drive B adrs ld (adrsb),hl ld de,(adrsa) inc de ; inc drive A adrs ld (adrsa),de jr vrdat ; loop till done vrerr: print crlf push af ld a,0 ld (some),a ;set error flag pop af print datadrs ; tell which byte number is in error ld bc,(bytcnt) ; get the count and display it ld c,b call outhex ld bc,(bytcnt) call outhex print datis ; drive B data is ld hl,(adrsb) ld a,(hl) ; get data from drive B ld c,a ; set up bad data from B call outhex print datsb ld de,(adrsa) ld a,(de) ; get data from drive A ld c,a ; data should be call outhex print crlf jp vert ; go get next track after one error read: ld de,rdmask*256+rdcmd jr action write: ld de,wrtmask*256+wrtcmd ; action: call xlate ; to physical sector number out (secp),a ; set sector number ld l,6 ; 5 re-tries on bad sector push hl ld hl,(dmaadr) ; address of disk i/o alp: ld bc,data ; b=0, c=port # ld a,e cp wrtcmd ; write op? jr z,wrt ; out (cmnd),a ; read loop rl1: halt ; read in first 256 bytes ini jp nz,rl1 rl2: halt ; read in second 256 bytes (256+256)=512 ini jp nz,rl2 jr done ; wrt: out (cmnd),a ; write loop wrt1: halt ; write first 256 bytes outi jp nz,wrt1 wrt2: halt ; write second 256 bytes outi jp nz,wrt2 ; done: ld (dmaadr),hl ; save new dma address (auto inc on rd/wrt) call busy ; wait for crc and d ; status mask pop hl ; error re-try count ret z ; no error dec l ; down error count jr z,error ; max error count if Z push hl ld hl,(dmaadr) ; correct dma address ld bc,512 or a sbc hl,bc jr alp error: ld a,0 ld (some),a ld a,0FFH or a ret ; ret non-zero (error) xlate: ld hl,tran ; un-skew track (formatted skewed) ld c,a ; copy disk logical sector number ld b,0 add hl,bc ; as index into skew table ld a,(hl) ; got it ret tran: defb 0, 8, 3, 6 defb 1, 9, 4, 7 defb 2,5 ; new translate table seeka: ld b,01H ; select disk mask jr seekx ; seekbv: ld b,02h ;select diak mask jr seekx seekb: ld b,02H in a,(trkp) ; drive b is always one behind or a ; except on track 00 jr z,seekx dec a ; back one out (trkp),a ; seekx: ld a,ficmd ; force int out (cmnd),a in a,(bitport) ; select disk and 0FCH or b out (bitport),a ; done ld a,(track) ; now seek desired track out (data),a ld a,seekcmd out (cmnd),a ; issue command busy: halt ; wait for command done bsy: in a,(status) ; busy? (may be drq not int) bit 0,a jr nz,bsy ret ; done home: in a,(bitport) ; select drive B and 0FCH push af ; save set 1,a out (bitport),a ld a,rstcmd ; home drive B out (cmnd),a call busy ; wait for done pop af set 0,a ; select drive A out (bitport),a ld a,rstcmd ; home drive A out (cmnd),a call busy ; wait for done ret diskon: in a,(bitport) ; turn on disk drive res 6,a out (bitport),a ld b,50 ; delay for motor up to speed don1: ld de,1670 don2: dec de ld a,d or e jp nz,don2 djnz don1 ret outdec: push bc ; save number in c ld a,c ; decimal print the number in c ld e,'0' ; e hold decimal digit hund: sub 100 ; any hundreds digits? jr c,tens inc e ; bump hundreds digit jr hund tens: add a,100 ; put back 100 push af ; save number ld a,e ; leading zero digit? cp '0' jr z,ten1 ld c,2 call bdos ; write digit ten1: pop af ; recover digit ld e,'0' ; tens digit ten2: sub 10 jr c,ones inc e ; bump tens digit jr ten2 ones: add a,10+'0' push af ; save number, print digit ld c,2 call bdos ; tens digit pop af ld e,a ld c,2 call bdos ; ones digit pop bc ; restore number to c ret ; done outhex: push de ; save incomming regs push bc ld a,c ; get data to be output and 0fh ; mask it for lsb nibble ld b,a ; save it push bc rrc c ; adjust msb nibble rrc c rrc c rrc c ld a,c and 0fh ; mask it call outcrt ; output msb to crt pop bc ld a,b call outcrt ; output lsb to crt pop bc ; restore registers pop de ret outcrt: cp 0ah ; is it more than 9 jp c,outc ; no add a,37h ; yes add in alpha displacement outcr: ld e,a ; set up for output to crt ld c,2 call bdos ret outc: add a,30h ; add in numerial displacement jr outcr tellt: print trkmsg ; tell track number ld bc,(track) call outdec ; print track number ret tella: print back ; bad sector on drive a print drva ; "DRIVE A " telerr: ld a,0 ld (some),a call tellt ; "TRACK XX" print secmsg ; " SECTOR " ld a,(sector) ; find physical sector number call xlate ld c,a call outdec ; "XX" print badmsg print crlf call tellt ; still on this track ret tellb: print back ; bad sector on drive b print drvb jr telerr ; common code menu: signon: defb 1AH,cr,lf,lf,lf defb 'KAYPRO II Double density diskette copy/verify program 13 July 1982',cr,lf defb cr,lf defb '-------------------------------------------------------------------' defb cr,lf,lf defb 'This program copies/verifies the diskette in drive A to a diskette in drive B' defb cr,lf,cr,lf defb 'OPTIONS' defb cr,lf defb '-------' defb cr,lf,cr,lf defb 'Copy/verify----> Diskette in drive B must have been formatted',cr,lf,cr,lf defb 'Fast copy------> Does not verify after copy',cr,lf,cr,lf defb 'Verify---------> Verify disk B is the same as disk A',cr,lf,cr,lf defb 'Exit-----------> Exit to CP/M (before typing place system disk in A)',cr,lf,cr,lf defb '(C)opy/verify (F)ast-copy (V)erify (E)xit',cr,lf defb 'Please enter ''C'' or ''F'' or ''V'' or ''E'' ==>','$' crlf: defb cr,lf,'$' trkmsg: defb 'Track ','$' secmsg: defb ' Sector ','$' drva: defb 'Drive A ','$' drvb: defb 'Drive B ','$' badmsg: defb ' {BAD}','$' back: defb cr,'$' adone: defb cr,'DONE ',cr,lf,'$' pause: defb cr,'Please type any key to continue.','$' vermsg: defb 'Verifying disk B to disk A',cr,lf,lf defb ' *** NOTE: only one error per track is displayed (there may be more) ***','$' datadrs: defb 'Drive B byte ','$' datis: defb ' data is ','$' datsb: defb ' should be ','$' dmaadr: defw buff ; dma pointer defb 0 some: defs 1 defb 0 track: defb 0 ; current track sector: defb 0 ; current sector bytcnt: defs 2 ; sector verify loop count adrsa: defs 2 ; storage area for disk A buffer adrsb: defs 2 ; storage area for disk B buffer buff equ $ ; track buffer buffb equ $+5120 ; read buffer end