*###################################################################### * PROGRAM UNDEL...Undelete File Utility * * Dr. David C. Wilcox * DCW Industries, Inc. * 5354 Palm Drive, La Canada, CA 91011 * 818/790-3844 * * February 1, 1986 *###################################################################### boot equ 0 *warm boot msgf equ 9 *write console message rdcf equ 10 *read console line verf equ 12 *read CP/M version self equ 14 *select disk clof equ 16 *close file sfef equ 17 *find first occurance sfnf equ 18 *find next occurance makf equ 22 *create file dmaf equ 26 *set DMA dpbf equ 31 *get dpb fwa rsdf equ 37 *reset (log-out) disk drive lf equ 10 *line feed cr equ 13 *carriage return bdos equ $0002 *BDOS entry point *###################################################################### * Special registers: * * a6 = address of DMA buffer * d6 = directory-entry buffer index (dbndx) * d7 = temporary count index (dbtmp) *###################################################################### * * Locate DMA (for portability) * link a6,#0 *mark stack frame move.l 8(a6),a0 *get base page address lea $80(a0),a6 *get address of DMA and save it in a6 * * Clear data registers * clr.l d3 clr.l d4 clr.l d5 * * Set up local stack * movea.l #stack,a7 * * Get the filename * movea.l a6,a2 *load DMA address suba.w #$23,a2 *adjust to FCB+1 movea.l #fcb+1,a1 move.w #11,d2 jsr mmc * * Select disk * movea.l a6,a0 *load DMA address suba.w #$24,a0 *adjust to FCB move.b (a0),d0 or.b d0,d0 beq ref1 *if no selection * subq #1,d0 move.w d0,d1 move.w #self,d0 trap #bdos * ref1: move.l #0,d6 *reset directory-entry buffer * move.l #cdpb,d1 *get extent mask move.w #dpbf,d0 trap #bdos movea.l #cdpb+4,a2 move.b (a2),d0 not.b d0 move.b d0,mfna * move.l a6,d1 *set dma move.w #dmaf,d0 trap #bdos * move.w #sfef,d0 *find first occurance move.l #fcb,d1 trap #bdos cmpi.b #$ff,d0 beq ref5 *if file not found * ref2: jsr ffa *set a2=fnt address movea.l a2,a5 movea.l #fcb+1,a1 adda #1,a2 move.l #8,d2 jsr kst *compare strings bne ref3 *if not our filename * * we have a directory entry with matching filename. * movea.l a5,a1 move.b d6,d0 *get buffer index addq.b #1,d6 *advance buffer index mulu #32,d0 *set a2=next buffer location movea.l #mbuff,a2 adda.l d0,a2 * exg a1,a2 *save the directory entry move.w #32,d2 jsr mmc * * search for next occurence. * ref3: movea.l a5,a1 move.w #sfnf,d0 trap #bdos cmpi.b #$ff,d0 bne ref2 *loop to end of directory * * we have searched the entire directory. * move.b d6,d0 *check file found or.b d0,d0 beq ref5 *if file not found * * if file not erased, then don't restore it. * jsr cfe *check file erased bne ref7 *if file not erased * * if multiple erased files, issue a warning * jsr cme *check multiple entries bne ref8 *if more than one file * * restore the file * jsr rae *restore all extents ref4: move.w #boot,d0 *warmboot trap #bdos * * file not found. * ref5: move.l #refa,d1 *"file not found" ref6: move.w #msgf,d0 trap #bdos jmp ref4 * * file not erased * ref7: move.l #refb,d1 *"file not erased" jmp ref6 * * multiple identical extent numbers found * ref8: move.l #refc,d1 *"multiple files found" move.b #msgf,d0 trap #bdos move.w #rdcf,d0 *read response move.l #cbuff,d1 trap #bdos movea.l #cbuff+2,a0 move.b (a0),d0 andi.b #$5f,d0 cmpi.b #'Y',d0 bne ref4 *if not "yes" * * close each extent under a unique name. * jsr mfn *modify all file names jsr rae *restore all jsr dfn *display new filenames jmp ref4 * * MFN - Modify all filenames. * insert unique 2nd character into each filename * set 3rd filename char to "A" for phy ext 0, "B" for 1, * mark all extents 00. * mfn: move.b d6,d7 movea.l #mbuff+2,a2 *2nd char movea.l #mbuff+$0c,a1 *ext move.b #'A',d0 * mfn1: move.b d0,(a2) *insert new 2nd char addq.b #1,d0 move.b d0,chtmp move.b (a1),d0 *set 3rd char = "ext" andi.b #$ff,d0 mfna equ *-1 addi.b #'A',d0 adda #1,a2 move.b d0,(a2) suba #1,a2 eor.b d0,d0 *set extent = 00 move.b d0,(a1) * adda #32,a1 adda #32,a2 * subq.b #1,d7 movea.l #chtmp,a0 move.b (a0),d0 or.b d7,d7 bne mfn1 *loop over all extents rts * * RAE - Restore all extents * rae: move.b #0,fcb move.b d6,d0 move.b d0,d5 movea.l #mbuff+1,a2 * rae1: move.w #15,d2 movea.l #fcb+1,a1 jsr mmc *move filename movea.l a2,a4 move.l #fcb,d1 move.w #makf,d0 *create directory entry trap #bdos movea.l #fcb+$0e,a0 *clear "not-written" bit move.b (a0),d0 andi.b #$7f,d0 move.b d0,fcb+$0e movea.l a4,a2 *point to rbt image suba #1,a2 *get record count move.b (a2)+,d0 movea.l #fcb+15,a1 move.b d0,(a1)+ move.w #16,d2 jsr mmc move.l #fcb,d1 *close current extent move.w #clof,d0 trap #bdos move.w d5,d1 adda #1,a2 subq #1,d5 bne rae1 *loop over all extents rts * * DFN - Display new filenames. * dfn: move.l #dfna,d1 *"file names created" move.w #msgf,d0 trap #bdos move.w d6,d0 movea.l #mbuff+1,a2 * dfn1: movea.l a2,a3 move.b d0,d7 movea.l #dfnb,a1 *move file name move.w #8,d2 jsr mmc addq #1,(a1) *move file type move.w #3,d2 jsr mmc move.l #dfnb,d1 move.w #msgf,d0 trap #bdos movea.l a3,a2 adda #32,a2 move.b d7,d0 subq #1,d0 bne dfn1 *loop for all extents rts * * CME - Check multiple erased entries * exit z = true, if one file found * d3 = file count * cme: move.b d6,d3 movea.l #mbuff+$0c,a2 *point to ext bytes * cme1: move.b (a2),d0 *current extent number -> d0 jsr cie *count identical extents beq cme11 rts *if multiple files found * cme11: adda #32,a2 subq #1,d3 bne cme1 *loop over all extents rts * * CIE - Count identical extents * entry d0 = current extent * exit z = true, if one such extent found * d4 = extent count * cie: movea.l a2,a3 move.l #0,d4 move.b d6,d2 movea.l #mbuff+$0c,a2 * cie1: move.b (a2),d1 cmp.b d0,d1 bne cie2 *if not same extent addq #1,d4 *advance extent count * cie2: adda #32,a2 subq #1,d2 bne cie1 *loop over all extents * move.b d4,d0 *check extents found movea.l a3,a2 cmpi.b #1,d0 rts * * CFE - Check file erased * exit z = true, if file erased * cfe: move.b d6,d2 movea.l #mbuff,a2 * cfe1: cmpi.b #$e5,(a2) beq skip rts *if unerased extent found * skip: adda #32,a2 subq #1,d2 bne cfe1 *loop over all extents rts * * FFA - Form file address * entry d0 = FNT ordinal * exit a2 = FNT address * ffa: or.b d0,d0 mulu #32,d0 * Multiply by 32 movea.l a6,a2 adda d0,a2 rts * * KST - Compare strings * entry a2 = string 1 fwa * a1 = string 2 fwa * d2 = string compare length * exit z = true, if string 1 equal string 2 * kst: cmpm.b (a1)+,(a2)+ *First check filename beq kstnxt rts *if mismatch * kstnxt: subq #1,d2 bne kst *loop over compare length move.w #3,d2 *Now check the extension kst2: move.b (a2)+,d0 andi.b #$7f,d0 cmp.b (a1)+,d0 beq kstnx2 rts *if mismatch * kstnx2: subq #1,d2 bne kst2 *loop over compare length rts * * MMC - Move memory * entry a2 = source fwa * a1 = destination fwa * d2 = byte count * mmc: move.b (a2)+,(a1)+ subq #1,d2 bne mmc *loop for d2 bytes rts *###################################################################### * console messages *###################################################################### even refa: dc.b 'File not found.$' refb: dc.b 'File not erased.$' refc: dc.b 'Multiple files found.' dc.b cr,lf,'Restore all? (Y/N):$' dfna: dc.b cr,lf,'File names created:',cr,lf,'$' dfnb: dc.b ' . ',cr,lf,'$' *###################################################################### * data space *###################################################################### even cdpb: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 chtmp: dc.b 0 *temp for 2nd char even fcb: dc.b '?' dc.b 0,0,0,0,0,0,0,0 dc.b 0,0,0 ext: dc.b 0,0,0,0 dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 nr: dc.b 0,0,0,0 cbuff: dc.b 64 *console input buffer ds.b 64+2 ds.l 32 stack equ * even mbuff equ *+128 *###################################################################### end