; DIRPAT v3.40 Copyright S. Kluger - ESKAY SOFTWARE ; All Rights Reserved ; ; A TurboDOS directory dump/patch utility ; .z80 .request timedif .request syslib ;use SYSLIB3 to assemble/link ; cr equ 0dh lf equ 0ah dfcb equ 5ch dbuf equ 80h ;default dma ; curdk equ 25 ;return current disk rrand equ 33 ;read random wrand equ 34 ;write random fsize equ 35 ;compute filesize gtime equ 105 ;get time parse equ 152 ;parse filename ; tdos equ 50h ;TD system call entry point stabo equ 8 ;set abort address fxmap equ 11 ;fix disk map vers equ 12 ;version number flush equ 26 ;flush disk buffers lockd equ 25 ;lock drive function fxdir equ 42 ;fix directory ; ; SYSLIB equates ; extrn f$open,f$close,scanner extrn print,cin,cout,phl4hc,eval16,eval10 extrn bbline,crlf,bdos,phlfdc,comphd,pa2hc extrn fname,capin,pstr,condin,initfcb ; cseg ; begin: jr ..strt ; cls: db 1bh,'E',0,0,0,0 ; clear screen curpos: db 1bh,'F',0,0,0,0 ; cursor pos xory: db 0 ; 0=xy, nz=yx coffs: db 32 ; cursor offset timeon: db 0ffh ; time on/off flag wyse: db 0 ; delay flag ; ..strt: ld sp,stack ld c,stabo ld de,abort call tdos ld c,gtime ; get time ld de,datim call bdos call atoh ld (sttime+6),hl ld a,(mmm) call atoh ld (sttime+3),hl ld a,(hhh) call atoh ld (sttime),hl ld a,(5ch) ld (dirfcb),a ; set drive or a jr nz,.ncd. ld c,25 call bdos inc a .ncd.: add a,40h ld (cdrv),a ld (cdrv1),a rstrt: call clrscr call print db 9,9,'+------------------------------------+',cr,lf db 9,9,'| DIRPAT ver 3.40 01/23/86 (c) ESKAY |',cr,lf db 9,9,'| TurboDOS directory patch utility |',cr,lf db 9,9,'+------------------------------------+',cr,lf,lf,0 xor a ld (frsttm),a ld (wrtn),a ld (hash),a ld (force),a ld (dfcb),a ld l,a ld h,a ld (curs),hl ld c,vers call tdos ;get version number ld a,c cp 13h call z,unrel bit 7,b jp z,noprv ;not privileged call print db 'Do you wish to lock drive ' cdrv: db 'A: (Y/N) ? [ ]',8,8,0 ld a,1 call bbline call crlf ld a,(hl) cp 'Y' ld a,0 jr nz,nolock ld c,curdk call bdos ld e,a ld (curd),a ld d,-1 ld c,lockd call tdos ;lock this drive or a jp nz,busy ld a,0ffh nolock: ld (locked),a ld de,dirfcb ;open directory file call f$open or a jp nz,direrr ld c,fsize call bdos ld hl,(rec) ld (tots),hl call fillbf ld a,(dbuf+12) ld (hash),a ld bc,12*256+18 call gotoxy call print 'Press RETURN to display directory and begin',0 ; ; This is the main command loop ; cloop: ld hl,(curs) ;get current sector ld (rec),hl ;stash it away ld a,(frsttm) or a ld a,1 ld (frsttm),a ld (dcall),a call nz,dsply xor a ld (dcall),a ld bc,16*256+20 call gotoxy call print db 'Command (or ? for help) [ ]',8,8,0 .gtcc.: ld bc,16*256+45 call gotoxy call condin ; see if input jr nz,.gotc. ; yes, process it call putt jr .gtcc. ; .gotc.: cp 'a' jr c,.nlcs. and 5fh .nlcs.: call cout ld hl,fcntbl ld b,nmbfcn .slfcn: cp (hl) inc hl jr z,.gofcn inc hl inc hl djnz .slfcn cp cr ld a,7 call nz,cout jp cloop ; .gofcn: ld a,(hl) inc hl ld h,(hl) ld l,a jp (hl) ; fcntbl: db '>' dw nxtact db '!' dw home db '?' dw help db 'Q' dw quit db '+' dw advanc db '=' dw advanc db '-' dw decrem db 'A' dw again db 'D' dw drives db 'R' dw fillb db 'W' dw purgbf db 'G' dw goto db 'H' dw dohash db 'F' dw find db 'L' dw fasc db 'E' dw erasef db 'U' dw unera db 'S' dw edit db 'X' dw hextgl nmbfcn equ ($-fcntbl)/3 ; find: ld bc,16*256+20 call gotoxy call print db ' Enter hex to be found, RET to stop',cr,lf,0 ld de,tmpbf ld b,0 fhl: call print db cr,lf,'Hex : ',0 ld a,1 call bbline or a jr z,fhd push de call eval16 ld a,e pop de ld (de),a inc de inc b jr fhl ; fhd: ld a,b or a jp z,cloop ld (vecl),a ld hl,tmpbf ld (vect),hl jr fntry ; fasc: ld bc,16*256+20 call gotoxy call print db ' Enter filename to be found : ',0 ld a,1 call bbline or a jp z,cloop cp 16 jr nc,fasc ld de,dfcb ; parse filename call fname jr z,fasc ld a,c ; get user number flag cp 0ffh ld a,'?' ; preload false jr z,..fau. ; skip if no user number ld a,c ; else get user # ..fau.: ld (de),a ; and store in fcb ld hl,previ push de ld bc,12 ex de,hl ldir pop de ..fa: ld (vect),de ld a,12 ; file name is 12 chars ld (vecl),a ld hl,(curs) ld (temp),hl xor a fntry: ld (ascis),a floop: call fillbf nofas: ld a,(vecl) ld c,a ld hl,dbuf ld de,(vect) ld b,127 call scan jr z,found ld hl,(curs) ;get current sector inc hl ;advance to next ld de,(tots) ;get total sectors call comphd ;check if we're at the end jr z,notfd ;not found. ld (curs),hl jr floop ; found: ld a,l and 7fh ld (fbyt),a ld a,1 ld (loctd),a ld hl,(curs) jp fillb ; notfd: call print db cr,lf,lf db 9,9,'*** end of file ***',cr,lf,7,0 call delay ld hl,(temp) ld (curs),hl call fillbf jp cloop ; scan: ld a,(ascis) or a jp nz,scanner ld hl,dbuf ..sl1: res 7,(hl) inc l jr nz,..sl1 ld hl,dbuf ld de,20h ld bc,5ch ..sm1: push hl push bc ..sm2: ld a,(bc) cp '?' jr z,..smw cp (hl) jr nz,..smn ..smw: inc hl inc bc ld a,68h cp c jr nz,..sm2 pop bc pop hl ret ; ..smn: pop bc pop hl add hl,de ld a,l or a jr nz,..sm1 inc a ret ; home: ld de,0 jp secok ; hextgl: ld a,(hexfl) cpl ld (hexfl),a jp cloop ; ; go to specified sector ; goto: ld bc,23*256+0 call gotoxy call print db 'Enter sector number to jump to (in decimal) : ',0 call bbline or a jp z,cloop ld bc,20*256+0 call cleol ld bc,23*256+0 call cleol call eval10 ld hl,(tots) dec hl call comphd jr nc,secok ld bc,20*256+27 call gotoxy call print db 'Sector number out of range',7,0 jr goto ; secok: dec de ld (curs),de jp advanc ; ; display current sector ; dsply: ld a,1 ld (dison),a call clrscr call print 9,'Sec [',0 ld hl,(curs) call prthl call print '] Hash=O',0 ld a,(hash) or a jr nz,..hs. call print 'FF',0 jr ..hx. ; ..hs.: call print 'N',0 ..hx.: call print ' Size ',0 ld hl,(tots) call prthl call print ' sectors ',0 ld a,(wrtn) or a ld a,' ' jr z,..nwr. ld a,'W' ..nwr.: call cout ld a,(locked) or a ld a,' ' jr z,..nlk. ld a,'L' ..nlk.: call cout call print db ' ' cdrv1: db 'A:',0 ld hl,loctd ld a,(hl) ld (hl),0 or a jr z,..nlcd call print ' Found: byte ',0 ld a,(fbyt) call pa2hc push af and 0fh ld b,a pop af and 0f0h rra rra rra rra add a,3 ld h,a ld c,3 ld a,-3 .clh..: add a,c dec b jp p,.clh.. add a,6 ld l,a ld (editpt),hl ld a,1 ld (dcall),a call ..nlcd xor a ld (dcall),a jp edlp ; ..nlcd: ld hl,dbuf ;hl=buffer pointer call print db cr,lf db 'ADDR 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F' db ' 0123456789ABCDEF',cr,lf,0 lp10: call crlf push hl res 7,l ;reset bit for display call phl4hc ;print address pop hl call spc call spc push hl ;save for ascii display lpln: ld a,(hl) call pa2hc call spc inc l ld a,l and 0fh ;done this line? jr nz,lpln call spc pop hl ;back for ascii asclp: ld a,(hl) and 7fh cp 7fh jr z,noprc cp ' ' jr nc,prasc noprc: ld a,'.' prasc: call cout inc l jr z,ddone ld a,l and 0fh jr z,lp10 jr asclp ; spc: ld a,' ' jp cout ; ddone: call crlf ld a,(dcall) or a ret nz jp cloop ; decrem: ld hl,(curs) ;get current sector ld a,h or l dec hl jr nz,nonda ;skip if not at start ld hl,(tots) ;get total sectors dec hl ;minus 1 (0..end) jr nonda ; advanc: ld hl,(curs) ;get current sector inc hl ;advance to next ld de,(tots) ;get total sectors call comphd ;check if we're at the end jr nz,nonda ;skip if not at end .wrp..: ld hl,0 ;go to start (wrap around) nonda: ld (curs),hl ;save new sector fillb: call fillbf jp cloop ; ; got to next active dir sector ; nxtact: ld hl,(curs) inc hl ld de,(tots) call comphd jr z,.wrp.. ld (curs),hl call fillbf ;get buffer ld hl,80h ld de,20h ld b,4 ..nx..: ld a,(hl) cp 0e5h jr nz,fillb add hl,de djnz ..nx.. jr nxtact ; fillbf: ld hl,(curs) ld (rec),hl ld c,rrand rdwr: ld de,dirfcb call bdos or a ret z call print db cr,lf,lf,7 db 'Read/write error code ',0 call pa2hc call print db '.',cr,lf,'Ignoring error.',cr,lf,0 jp delay ; purgbf: ld a,(locked) or a jr nz,purg1 ld bc,23*256+10 call gotoxy call print db 7,'WARNING - DRIVE NOT LOCKED - PROCEED (Y/N) ? ',0 ld a,1 call bbline ld bc,23*256+0 call cleol ld a,(hl) cp 'Y' jr z,purg1 jp cloop ; purg1: ld hl,(curs) ld (rec),hl ld c,wrand call rdwr ld a,1 ld (wrtn),a jp cloop ; dohash: ld hl,0 ld (curs),hl call fillbf ld bc,23*256+10 call gotoxy call print db 'Hash directory after exiting (Y=YES) ? ',0 ld a,1 ld (force),a call bbline ld bc,23*256+0 call cleol ld a,(hl) cp 'Y' ld a,80h jr z,yhash xor a yhash: ld (dbuf+0ch),a ld (hash),a jp purgbf ; ; delete all directory entries of a file ; (unless already deleted) ; report count ; erasef: call print db cr,lf,lf db 'Enter filename (no user # = all entries,',cr,lf db 'else only entries in that user) RET=quit : ',0 ld a,0e5h ld (eracmd),a ld a,1 call bbline or a jp z,cloop ld (pfcb),hl ;save hl ld hl,sfcb ld (pfcb+2),hl ld c,parse ld de,pfcb call bdos ld a,(sfcb+15) or a jr z,nofu ld a,(sfcb+13) inc a nofu: dec a ld (sfcb),a inc a jp nz,noall call print db cr,lf db 'WARNING - you are about to delete ALL those',cr,lf db 'directory entries. Say "NO" to change your mind : ',0 ld a,1 call bbline ld a,(hl) cp 'N' jp z,cloop noall: ld hl,0 ld (curs),hl ;set current sector to 0 erasl: call fillbf ;get buffer ld ix,dbuf ;ix=pointer to buffer ld de,32 ;de=increment count ld c,4 ;c=field counter xor a ld (noche),a ;set no change erase flag erasl1: ld hl,sfcb ;hl=fcb ptr ld b,12 ;b=byte counter push ix ;move ix... pop iy ;...to iy ld a,(hl) inc a jr nz,erasl2 inc ix inc hl dec b erasl2: ld a,'?' cp (hl) jr z,..qmk ld a,(ix+0) and 7fh cp (hl) jr nz,eranxt ..qmk: inc ix inc hl djnz erasl2 ld a,(eracmd) ; get erase/unerase byte ld (iy+0),a ld a,0ffh ld (noche),a eranxt: dec c jr z,eradun push iy pop ix add ix,de jr erasl1 ; eradun: ld hl,(curs) ld (rec),hl ld c,wrand ld a,(noche) or a jr z,nowrt ld (dcall),a call dsply ld a,(eracmd) cp 0e5h jr z,..due call print cr,lf 'UN-DELETE FILE(S) above? ',0 ld a,1 call bbline or a jr z,nowrt ld a,(hl) cp 'Y' jr nz,nowrt ..due: xor a ld (dcall),a call rdwr nowrt: ld a,1 ld (wrtn),a ld hl,(curs) ;get current sector inc hl ;advance to next ld (curs),hl ld de,(tots) ;get total sectors call comphd ;check if we're at the end jp z,cloop jp erasl ; unera: ld c,32 ld e,0ffh call bdos ld (eracmd),a ; current user # ld a,(locked) or a jr nz,..unel call print cr,lf,lf,7 'WARNING: drive is not locked - proceed anyway? ',0 ld a,1 call bbline or a jp z,cloop ld a,(hl) cp 'Y' jp nz,cloop ..unel: call print cr,lf,lf 'File will be undeleted to current user area. NOTE that multiple',cr,lf 'occurrences of the same filename can ALSO be unerased causing',cr,lf 'garbled information.',cr,lf 'Enter name of file to be undeleted (RET=quit) : ',0 ld a,1 call bbline or a jp z,cloop ld (pfcb),hl ld hl,sfcb ld (pfcb+2),hl ld c,parse ld de,pfcb call bdos ld hl,sfcb ld (hl),65h ; E5 and 7F inc hl ld a,'?' ld b,11 ..xxx: cp (hl) jp nz,noall inc hl djnz ..xxx call print cr,lf,7 'ERROR: cannot undelete *.*!',cr,lf,0 call delay jp cloop ; help: call clrscr call print db cr,lf db 'DIRPAT COMMANDS (single commands only, no stacking) :' db cr,lf,lf db '! = HOME (go to sector 0)',cr,lf db '? = this message',cr,lf db 'D = change logged drive',cr,lf db 'E = delete (Erase) all entries of one file',cr,lf db 'F = find hex data in directory',cr,lf db 'G = goto record (prompting for decimal number)',cr,lf db 'H = set hashed status (effective after exit)',cr,lf db 'L = locate a file name',cr,lf db 'Q = quit to TurboDOS',cr,lf db 'R = re-read current record and display',cr,lf db 'S = substitute onscreen (hex/ASCII edit)',cr,lf db 'U = UNDELETE a deleted file',cr,lf db 'W = write current record',cr,lf db 'X = toggle hex/decimal sector DISPLAY',cr,lf db '+ = advance pointer to next record and display',cr,lf db '- = move pointer to previous record and display',cr,lf,lf db 'Use this program with extreme caution!',cr,lf,lf db '----> press any key to continue <----',0 call cin call clrscr jp cloop ; prthl: ld a,(hexfl) or a jp z,phl4hc jp phlfdc ; busy: call print db cr,lf,lf,7 db 'ERROR - cannot lock drive. Cause all other users to',cr,lf db 'log off and try again',cr,lf,0 rst 0 ; direrr: call print db cr,lf,lf,lf db 'FATAL ERROR - $.DIR NOT FOUND.',cr,lf db 'Are you not running under TurboDOS?',cr,lf,lf,0 quit: ld de,dirfcb call f$close ld a,(wrtn) or a jr nz,fixit jp noth ; fixit: ld a,(locked) or a jr nz,fixok call print db cr,lf,lf db 9,'WARNING - UNABLE TO FIX UNLOCKED DRIVE',cr,lf db 9,'YOU MUST RUN FIXMAP AND FIXDIR MANUALLY',7,cr,lf,lf,0 jp noth ; fixok: call print db cr,lf db 'Now rebuilding disk map - stand by',0 ld a,(curd) ;get current disk ld e,a ld c,fxmap call tdos or a jp nz,nofm ;error... ld a,(force) or a jr nz,forcef ld a,(hash) or a jr z,noth forcef: call print db cr,lf db 'Now reorganizing directory - DO NOT ABORT',cr,lf,lf,0 ld a,(curd) ld e,a ld c,fxdir call tdos or a jp nz,nofd noth: call print db cr,lf,lf 9,9,' Time spent in DIRPAT: ',0 ld c,gtime ld de,datim call bdos call atoh ld (entime+6),hl ld a,(mmm) call atoh ld (entime+3),hl ld a,(hhh) call atoh ld (entime),hl call timdif## ld hl,elaptm call pstr call print cr,lf,lf 9,' Thanks for using DIRPAT, an ESKAY product',cr,lf,lf,0 ld c,lockd ;unlock drive ld d,0 ld a,(curd) ld e,a call tdos ld c,flush ;flush buffers ld a,(curd) ld e,a ld d,80h call tdos rst 0 ; nofd: call print db cr,lf,lf,7 db 'ERROR - cannot reorganize directory, aborting',cr,lf,0 rst 0 ; nofm: call print db cr,lf,lf,7 db 'ERROR - cannot fix disk map, aborting.',cr,lf,0 rst 0 ; noprv: call print db cr,lf,lf,7 db 'Not authorized to use DIRPAT',cr,lf,0 rst 0 ; unrel: push psw call print db cr,lf,7 db 'NOTE: Operation under TurboDOS 1.3 has not been fully',cr,lf db 'tested. Directory size is reported as 0 and system may',cr,lf db 'crash on exit. Proceed at your own risk.',cr,lf,lf,0 pop psw abort: ret ; delay: push bc ld a,10 ld bc,0 ....d.: dec c push hl pop hl jr nz,....d. djnz ....d. dec a jr nz,....d. pop bc ret ; delay1: ld a,(wyse) or a ret z push bc ld bc,1000 ...d1.: dec c jr nz,...d1. djnz ...d1. pop bc ret ; ; a to h ; atoh: push af ld hl,3030h and 0fh or h ld h,a pop af and 0f0h rra rra rra rra or l ld l,a ret ; ahlo: call atoh ld a,l call cout ld a,h jp cout ; ; edit command ; edit: ld a,(dison) dec a jr z,.eact. ld a,7 call cout jp cloop ; .eact.: ld bc,3*256+6 ; beginning of field ld (editpt),bc edlp: ld bc,(editpt) call gotoxy xor a ld (frsttm),a call condin jr nz,.char. call putt jr edlp ; .char.: cp 'a' jr c,..nl.. and 5fh ..nl..: cp 3 ; exit jp z,cloop cp 'E'-40h ; ^E = up jr z,.edup. cp 'X'-40h ; ^X = down jr z,.eddn. cp 'S'-40h ; ^S = left jr z,.edlf. cp 'D'-40h ; ^D = right jr z,.edrt. cp 27h ; check ' jp z,.edasc ; edit ascii call nybble ; see if nybble jp nc,.edda. ; it is, edit data ld a,7 call cout jr edlp ; .edup.: ld a,(editpt+1) ; get row dec a cp 2 jr nz,.esnt. ld a,10 ; set bottom .esnt.: ld (editpt+1),a jr edlp ; .eddn.: ld a,(editpt+1) inc a cp 11 jr nz,.esnt. ld a,3 jr .esnt. ; .edlf.: ld a,(editpt) sub 3 cp 3 jr nz,.eslt. ld a,51 ld (editpt),a jr .edup. ; .eslt.: ld (editpt),a jp edlp ; .edrt.: ld a,(editpt) add a,3 cp 54 jr nz,.eslt. ld a,6 ld (editpt),a jr .eddn. ; .edasc: call cin ; get ascii character call pa2hc jr ..asci ; .edda.: call hexo ; display high nybble cp 'A' jr c,...x sub 7 ...x: and 0fh rla rla rla rla ld b,a ; save it .ede..: call capin call nybble jr c,.ede.. call hexo cp 'A' jr c,...y sub 7 ...y: and 0fh or b ; a has byte now ..asci: push af call calcbp ; calculate buffer pointer pop af ld (hl),a ld a,l and 0fh add a,55 ld bc,(editpt) ld c,a call gotoxy ld a,(hl) and 7fh cp 7fh jr z,.ed... cp ' ' jr nc,.edn.. cp 7fh .ed...: ld a,'.' .edn..: call cout jp .edrt. ; go to next hex on same line ; ; calculate buffer from screen address ; calcbp: ld hl,(editpt) ld a,l ; get column ld b,0 sub 6 .div3.: inc b sub 3 jr nc,.div3. ld l,b ld a,h ld h,0 sub 3 rla rla rla rla add a,7fh add a,l ld l,a ret ; ; test a if valid nybble ; nybble: cp '0' ret c cp 'F'+1 ccf ret c cp '9'+1 ccf ret nc sub 7 cp '9'+1 ret ; ; hex out ; hexo: cp '9'+1 jp c,cout add a,7 jp cout ; ; position cursor. b=x, c=y ; gotoxy: push hl ld hl,curpos call pstrg ld a,(xory) ; check xy or yx or a ; if zero, then xy jr z,..xy ld a,b ld b,c ld c,a ; exchange b and c ..xy: call delay1 ld a,(coffs) ; get cursor offset push af ; save for next add a,b call cout call delay1 pop af add a,c call cout pop hl ret ; cleol: push hl call gotoxy ld b,79 ld a,' ' ..ceol: call cout djnz ..ceol pop hl ret ; clrscr: push hl ld hl,cls call pstrg pop hl ret ; pstrg: ld a,(hl) or a ret z call cout inc hl jr pstrg ; putt: ld a,(timeon) or a ret z ld c,gtime ld de,datim call bdos ld b,a ld a,(lsec) cp b ret z ld a,b ld (lsec),a ld bc,16*256+0 call gotoxy ld a,(hhh) call ahlo ld a,':' call cout ld a,(mmm) call ahlo ld a,':' call cout ld a,(lsec) jp ahlo ; ; select new drive ; drives: call clrscr call print db cr,lf,lf db 'Enter new drive (A..P, any other = no change) :',0 call capin cp 'A' jp c,cloop cp 'Q' jp nc,cloop ld (cdrv),a ld (cdrv1),a push af ld de,dirfcb call f$close call initfcb pop af sub 40h ld (dirfcb),a jp rstrt ; ; find again (repeat "l" command) ; again: ld hl,previ ld a,(hl) inc a jp z,cloop ; ignore if no previous fn ex de,hl jp ..fa ; dseg ; editpt: dw 0 ; sttime::db '00:00:00' entime::db '00:00:00' elaptm::db '00:00:00',0 dison: db 0 frsttm: db 0 locked: db 0 ;0=drive not locked noche: db 0 ;no change (erase) dcall: db 0 ;NZ=dsply called, else JMPed curs: dw 0 ;current sector tots: dw 0 ;total number of sectors eracmd: db 0 ;E5 if erase, user # if unera temp: dw 0 vect: dw 0 vecl: db 0 ascis: db 0 ;0=ascii search, nz=binary wrtn: db 0 ;0=no changes made, else changes were made hash: db 0 ;0=linear, 1=hashed curd: db 0 ;current drive lsec: db 0 hexfl: db 0 loctd: db 0 fbyt: db 0 force: db 0 ;force fixdir dirfcb: db 0,'$ DIR',0 db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 rec: db 0,0,0 sfcb: ds 36 pfcb: ds 4 tmpbf: ds 64 ;temp buffer space ; previ: db 0ffh ds 11 ; datim: dw 0 hhh: db 0 mmm: db 0 ; ds 80 stack equ $ end  jp rstrt ; ; find again (repeat "l" command) ;