]>
wirehaze git hosting - MS-DOS.git/blob - v2.0/source/RECOVER.ASM
1 TITLE RECOVER
MS-DOS
File/Disk Recovery Utility
2 ;----------------------------------------------------------
4 ; Recover - Program to rebuild an ms.dos directory
6 ; Copyright 1982 by Microsoft Corporation
7 ; Written by Chris Peters, April 1982
9 ;-----------------------------------------------------------
11 ;REV 1.5 added header message ARR
37 const
segment public byte
40 data segment public byte
44 dg group
code,const
,data
47 assume
cs:dg
,ds:dg
,es:dg
,ss:dg
49 PUBLIC PCRLF
,PRINT
,INT_23
,convert
50 EXTRN dskwrt
:NEAR,dskrd
:NEAR,DSKERR
:NEAR,report
:NEAR
58 ;-----------------------------------------------------------------------;
61 the_root db 0 ;root directory flag
63 fudge db 0 ;directory changed flag
74 fname_buffer db 128 dup(0)
75 ;-----------------------------------------------------------------------;
77 pcrlf: mov dx,offset dg
: crlf
78 print: mov ah,STD_CON_STRING_OUTPUT
130 mov ah,STD_CON_OUTPUT
144 getfat: mov bx,offset dg
: fattbl
150 mov bx,word ptr [bx][si]
155 getfat1:and bh,00001111b
162 setfat: mov bx,offset dg
: fattbl
169 mov ax,word ptr [bx][si]
176 mov word ptr [bx][si],ax
181 setfat2:and ax,0f000h
185 mov al,byte ptr fatnum
186 mov byte ptr fatcnt
,al
187 mov al,byte ptr drive
189 mov bx,offset dg
: fattbl
194 cmp [fndfat
],0 ;save location of readable fat sector
197 fdfat: cmp word ptr [bx+1],-1
200 add dx,cx ;try to read the other fats
204 mov dx,[fndfat
] ;see if any readable at all
206 jz readft
;if not disk is blown, keep trying
233 ;Code to print header
235 ; MOV DX,OFFSET DG:HEADER
239 DOSVER_HIGH EQU
0200H ;2.00 in hex
240 PUSH AX ;Save DRIVE validity info
243 XCHG AH,AL ;Turn it around to AH.AL
247 MOV DX,OFFSET DG
:BADVER
269 BADDRVSPECJ: JMP BADDRVSPEC
273 int bdos
;empty buffer queue
275 mov ah,get_default_drive
;save current drive
279 mov bx,fcb
;determine input command
289 mov dx,offset dg
: askmsg
291 mov ah,STD_CON_INPUT_FLUSH
292 mov al,1 ;wait for a key
297 mov dx,offset dg
: egomes
299 egomes: db "Chris Peters helped with the new dos!",cr
,lf
300 db "Microsoft rules ok$"
304 MOV AL,DRIVE
;This is for ibm's single drive sys
308 MOV DS:(BYTE PTR 4),AL ;Indicate drive changed
312 ;----- Process Pathnames -----------------------------------------------;
313 mov ax,(char_oper
shl 8) ;get switch character
316 jnz slashok
;if not / , then not PC
317 mov [dirchar
],"\" ;in PC, dir separator = \
321 mov si,81h
;point to cammand line
322 mov di,offset dg
: fname_buffer
323 xor cx,cx ;zero pathname length
326 lodsb ;get rid of blanks
331 cmp al,13 ;A carriage return?
333 jmp noname
;yes, file name missing
336 stosb ;put patname in buffer
347 mov byte ptr [di],0 ;nul terminate the pathname
348 dec di ;adjust to the end of the pathname
350 ;----- Scan for directory ----------------------------------------------;
353 mov dx,offset dg
: [fname_buffer
]
371 MOV DX,DI ;Point to char after '/'
373 DEC DX ;Point to char before '/'
380 SUB AX,DI ;Distance moved
381 SUB CX,AX ;Set correct CX
383 JB sja
;Found a pathsep
384 JA sjb
;Started with a pathsep, root
390 jz sja
;One character directory
393 mov al,[dirchar
] ;get directory separator character
395 repnz scasb ;(cx has the pathname length)
396 cld ;reset direction, just in case
400 jmp same_dir
;no dir separator char. found, the
401 ; file is in the current directory
402 ; of the corresponding drive. Ergo,
403 ; the FCB contains the data already.
406 jcxz sjb
;no more chars left, it refers to root
407 cmp byte ptr [di],':' ;is the prvious character a disk def?
410 mov [the_root
],01h ;file is in the root
412 inc di ;point to dir separator char.
414 stosb ;nul terminate directory name
416 push di ;save pointer to file name
417 mov [fudge
],01h ;remember that the current directory
420 ;----- Save current directory for exit ---------------------------------;
421 mov dl,byte ptr ds:[fcb
] ;get specified drive if any
422 or dl,dl ;default disk?
424 dec dl ;adjust to real drive (a=0,b=1,...)
425 mov ah,set_default_drive
;change disks
430 mov dx,offset dg
: baddrv
434 mov ah,get_default_dpb
439 cmp al,-1 ;bad drive? (should always be ok)
441 mov dx,offset dg
: baddrv
445 cmp [bx.dpb_current_dir
],0
449 mov di,offset dg
: userdir
+ 1
464 ;----- Change directories ----------------------------------------------;
466 mov dx,offset dg
: [dirchar
] ;assume the root
468 mov dx,offset dg
: [fname_buffer
]
470 mov ah,chdir
;change directory
472 mov dx,offset dg
: baddrv
477 ;----- Set Up int 24 intercept -----------------------------------------;
479 mov ax,(get_interrupt_vector
shl 8) or 24h
481 mov word ptr [hardch
],bx
482 mov word ptr [hardch
+2],es
483 mov ax,(set_interrupt_vector
shl 8) or 23h
484 mov dx,offset dg
: int_23
486 mov ax,(set_interrupt_vector
shl 8) or 24h
487 mov dx,offset dg
: int_24
492 ;----- Parse filename to FCB -------------------------------------------;
495 mov ax,(parse_file_descriptor
shl 8) or 1
498 ;-----------------------------------------------------------------------;
503 cmp byte ptr [bx+1],' ' ;must specify file name
505 cmp byte ptr [bx],0 ;or drive specifier
507 noname: mov dx,offset dg
: drverr
516 mov ax,word ptr [bx+2] ;get physical sector size
517 mov cl,byte ptr [bx+4] ;get sectors/cluster - 1
520 mov cs:secall
,cx ;save sectors per cluster
521 mul cx ;ax = bytes per cluster
522 mov bp,word ptr [bx+11] ;get record of first sector
523 mov dx,word ptr [bx+16] ;get record of first directory entry
524 mov si,word ptr [bx+6] ;get record of first fat
525 mov cl,byte ptr [bx+15] ;get size of fat
526 mov di,word ptr [bx+13] ;get number of clusters
527 mov ch,byte ptr [bx+8] ;get number of fats on drive
528 mov bx,word ptr [bx+9] ;get max number of dir entries
535 mov byte ptr fatsiz
,cl
536 mov lastfat
,di ;number of fat entries
537 mov byte ptr fatnum
,ch ;save number of fats on disk
541 mov di,table
;di points into constructed directory
542 mov ax,0e5e5h ;deleted file magic number
543 shl bx,1 ;16 words in a dir entry
552 cmp byte ptr [bx+1],' '
564 mov word ptr filsiz
+2,0
569 adc word ptr filsiz
+2,0
579 ; at this point target = head of list, filsiz = file size
581 inc filcnt
;increment file count
583 cmp filcnt
,ax ;compare with max number of entries
586 mov si,(offset dg
: dirent
)+7
587 nam0: inc byte ptr [si] ;increment file name
588 cmp byte ptr [si],'9'
590 mov byte ptr [si],'0'
594 nam1: mov ah,GET_DATE
595 int bdos
;set the date
604 mov byte ptr dirent
+24,dh
605 mov byte ptr dirent
+25,cl
607 int bdos
;set the time
618 mov byte ptr dirent
+22,dh
619 mov byte ptr dirent
+23,ch
621 mov ax,filsiz
;set file size
622 mov word ptr dirent
+28,ax
623 mov ax,word ptr filsiz
+2
624 mov word ptr dirent
+30,ax
625 mov ax,target
;set first cluster location
626 mov word ptr dirent
+26,ax
628 mov si,offset dg
: dirent
;copy in new dir entry
632 step6: inc fatptr
;keep looking for eof's
639 mov dx,offset dg
: dirmsg
644 mov dx,firdir
;write out constructed directory
650 mov dx,offset dg
: recmsg_pre
652 mov bx,offset dg
: recmsg_post
654 xor di,di ;output number of files created
662 mov dx,offset dg
: opnerr
666 recfil0:mov lastfat
,1 ;indicate location of list head
668 mov ax,[di+16] ;get file size
674 mov ax,[di+25] ;get list head
680 recfil1:cmp fatptr
,0fffh
681 jz recvec
;terminate loop at e-o-f
693 pop di ;restore stack pointer
694 mov di,fcb
;restore pointer to fcb
695 jnc recfil4
;if no error continue reading
705 noteof: mov word ptr [di+25],bx
708 recfil2:mov dx,bx ;jump around bad sector
712 recfil3:mov ax,fatptr
;mark sector bad
715 mov ax,secsiz
;prepare to dec filsiz by secsiz
722 recfilx:sub word ptr [di+16],ax
723 sbb word ptr [di+18],0
727 and byte ptr [di+24],10111111b ;mark file dirty
729 mov ax,lastfat
;point to next sector to check
733 mov ax,secsiz
;set bytes remaining to be read
737 xor ax,ax ;if < 0, then set to zero
741 recok: mov ax,fatptr
;get next sector to test
750 int bdos
;close the file
755 rexit: mov ah,DISK_RESET
757 call wrtfat
;save the fat
758 int_23: call rest_dir
759 rabort: int boot
;home, james...
761 ;----- Restore INT 24 vector and old current directory -----------------;
766 mov ax,(set_interrupt_vector
shl 8) or 24h
772 mov dx,offset dg
: userdir
;restore directory
775 mov dl,[user_drive
] ;restore old current drive
776 mov ah,set_default_drive
782 ;----- INT 24 Processing -----------------------------------------------;
784 int_24_retaddr dw int_24_back
787 assume
ds:nothing
,es:nothing
,ss:nothing
791 push [int_24_retaddr
]
792 push word ptr [hardch
+2]
793 push word ptr [hardch
]
836 const
segment public byte
838 EXTRN BADVER
:BYTE,askmsg
:BYTE,drvlet
:BYTE,dirmsg
:BYTE
839 EXTRN recmsg_pre
:BYTE,DRVLET1
:BYTE,recmsg_post
:BYTE
840 EXTRN crlf
:BYTE,drverr
:BYTE,baddrv
:BYTE,opnerr
:BYTE
848 dirent db 'FILE0000REC'
851 fndfat dw 0000 ;sector of first good fat
858 secall dw 0000 ;sectors per cluster
870 table dw offset dg
:fattbl
+ 6 * 1024