mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-29 00:55:47 +00:00
876 lines
23 KiB
NASM
876 lines
23 KiB
NASM
|
TITLE RECOVER MS-DOS File/Disk Recovery Utility
|
|||
|
;----------------------------------------------------------
|
|||
|
;
|
|||
|
; Recover - Program to rebuild an ms.dos directory
|
|||
|
;
|
|||
|
; Copyright 1982 by Microsoft Corporation
|
|||
|
; Written by Chris Peters, April 1982
|
|||
|
;
|
|||
|
;-----------------------------------------------------------
|
|||
|
;
|
|||
|
;REV 1.5 added header message ARR
|
|||
|
;
|
|||
|
|
|||
|
FALSE EQU 0
|
|||
|
TRUE EQU NOT FALSE
|
|||
|
|
|||
|
|
|||
|
IBMVER EQU true
|
|||
|
KANJI EQU FALSE
|
|||
|
|
|||
|
bdos equ 21h
|
|||
|
boot equ 20h
|
|||
|
aread equ 25h
|
|||
|
awrite equ 26h
|
|||
|
|
|||
|
INCLUDE DOSSYM.ASM
|
|||
|
|
|||
|
;
|
|||
|
cr equ 0dh
|
|||
|
lf equ 0ah
|
|||
|
;
|
|||
|
fcb equ 5ch
|
|||
|
|
|||
|
code segment public
|
|||
|
code ends
|
|||
|
|
|||
|
const segment public byte
|
|||
|
const ends
|
|||
|
|
|||
|
data segment public byte
|
|||
|
data ends
|
|||
|
|
|||
|
|
|||
|
dg group code,const,data
|
|||
|
|
|||
|
code segment public
|
|||
|
assume cs:dg,ds:dg,es:dg,ss:dg
|
|||
|
|
|||
|
PUBLIC PCRLF,PRINT,INT_23,convert
|
|||
|
EXTRN dskwrt:NEAR,dskrd:NEAR,DSKERR:NEAR,report:NEAR
|
|||
|
|
|||
|
org 100h
|
|||
|
|
|||
|
recover:jmp rec_start
|
|||
|
|
|||
|
HEADER DB "Vers 1.50"
|
|||
|
|
|||
|
;-----------------------------------------------------------------------;
|
|||
|
hardch dd ?
|
|||
|
|
|||
|
the_root db 0 ;root directory flag
|
|||
|
|
|||
|
fudge db 0 ;directory changed flag
|
|||
|
user_drive db 0
|
|||
|
drive db 0
|
|||
|
|
|||
|
|
|||
|
dirchar db "/",0
|
|||
|
|
|||
|
|
|||
|
userdir db "/",0
|
|||
|
db (dirstrlen) dup(0)
|
|||
|
|
|||
|
fname_buffer db 128 dup(0)
|
|||
|
;-----------------------------------------------------------------------;
|
|||
|
|
|||
|
pcrlf: mov dx,offset dg: crlf
|
|||
|
print: mov ah,STD_CON_STRING_OUTPUT
|
|||
|
int bdos
|
|||
|
pret: ret
|
|||
|
;
|
|||
|
convert:push bx
|
|||
|
xor ax,ax
|
|||
|
mov bx,ax
|
|||
|
mov bp,ax
|
|||
|
mov cx,32
|
|||
|
convlp: shl si,1
|
|||
|
rcl di,1
|
|||
|
xchg ax,bp
|
|||
|
call convwrd
|
|||
|
xchg ax,bp
|
|||
|
xchg ax,bx
|
|||
|
call convwrd
|
|||
|
xchg ax,bx
|
|||
|
adc al,0
|
|||
|
loop convlp
|
|||
|
|
|||
|
mov cx,1810h
|
|||
|
xchg dx,ax
|
|||
|
call digit
|
|||
|
xchg ax,bx
|
|||
|
call outword
|
|||
|
mov ax,bp
|
|||
|
call outword
|
|||
|
pop dx
|
|||
|
call print
|
|||
|
ret2: ret
|
|||
|
;
|
|||
|
outword:push ax
|
|||
|
mov dl,ah
|
|||
|
call outbyte
|
|||
|
pop dx
|
|||
|
outbyte:mov dh,dl
|
|||
|
shr dl,1
|
|||
|
shr dl,1
|
|||
|
shr dl,1
|
|||
|
shr dl,1
|
|||
|
call digit
|
|||
|
mov dl,dh
|
|||
|
digit: and dl,0fh
|
|||
|
jz blankzer
|
|||
|
xor cl,cl
|
|||
|
blankzer:
|
|||
|
dec ch
|
|||
|
and cl,ch
|
|||
|
or dl,30h
|
|||
|
sub dl,cl
|
|||
|
cmp dl,30h
|
|||
|
jl ret2
|
|||
|
mov ah,STD_CON_OUTPUT
|
|||
|
int bdos
|
|||
|
ret
|
|||
|
;
|
|||
|
convwrd:adc al,al
|
|||
|
daa
|
|||
|
xchg al,ah
|
|||
|
adc al,al
|
|||
|
daa
|
|||
|
xchg al,ah
|
|||
|
ret
|
|||
|
;
|
|||
|
; bx = fat[ax]
|
|||
|
;
|
|||
|
getfat: mov bx,offset dg: fattbl
|
|||
|
push ax
|
|||
|
mov si,ax
|
|||
|
sar ax,1
|
|||
|
pushf
|
|||
|
add si,ax
|
|||
|
mov bx,word ptr [bx][si]
|
|||
|
popf
|
|||
|
jnc getfat1
|
|||
|
mov cl,4
|
|||
|
shr bx,cl
|
|||
|
getfat1:and bh,00001111b
|
|||
|
pop ax
|
|||
|
mov cx,secsiz
|
|||
|
ret
|
|||
|
;
|
|||
|
; fat[ax] = dx
|
|||
|
;
|
|||
|
setfat: mov bx,offset dg: fattbl
|
|||
|
push ax
|
|||
|
push dx
|
|||
|
mov si,ax
|
|||
|
sar ax,1
|
|||
|
pushf
|
|||
|
add si,ax
|
|||
|
mov ax,word ptr [bx][si]
|
|||
|
popf
|
|||
|
jnc setfat2
|
|||
|
and ax,000fh
|
|||
|
mov cl,4
|
|||
|
shl dx,cl
|
|||
|
setfat1:or ax,dx
|
|||
|
mov word ptr [bx][si],ax
|
|||
|
pop dx
|
|||
|
pop ax
|
|||
|
ret
|
|||
|
|
|||
|
setfat2:and ax,0f000h
|
|||
|
jmp setfat1
|
|||
|
|
|||
|
load: mov dx,firfat
|
|||
|
mov al,byte ptr fatnum
|
|||
|
mov byte ptr fatcnt,al
|
|||
|
mov al,byte ptr drive
|
|||
|
mov cx,fatsiz
|
|||
|
mov bx,offset dg: fattbl
|
|||
|
ret66: ret
|
|||
|
|
|||
|
readft: call load
|
|||
|
readit: call dskrd
|
|||
|
cmp [fndfat],0 ;save location of readable fat sector
|
|||
|
jnz fdfat
|
|||
|
mov [fndfat],dx
|
|||
|
fdfat: cmp word ptr [bx+1],-1
|
|||
|
jz ret66
|
|||
|
|
|||
|
add dx,cx ;try to read the other fats
|
|||
|
dec byte ptr fatcnt
|
|||
|
jnz readit
|
|||
|
|
|||
|
mov dx,[fndfat] ;see if any readable at all
|
|||
|
or dx,dx
|
|||
|
jz readft ;if not disk is blown, keep trying
|
|||
|
call dskrd
|
|||
|
ret
|
|||
|
|
|||
|
wrtfat: call load
|
|||
|
wrtit: push ax
|
|||
|
push bx
|
|||
|
push cx
|
|||
|
push dx
|
|||
|
call dskwrt
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
pop bx
|
|||
|
pop ax
|
|||
|
|
|||
|
wrtok: add dx,cx
|
|||
|
dec byte ptr fatcnt
|
|||
|
jnz wrtit
|
|||
|
ret
|
|||
|
|
|||
|
printerr:
|
|||
|
call print
|
|||
|
jmp rabort
|
|||
|
|
|||
|
|
|||
|
rec_start:
|
|||
|
|
|||
|
;Code to print header
|
|||
|
; PUSH AX
|
|||
|
; MOV DX,OFFSET DG:HEADER
|
|||
|
; CALL print
|
|||
|
; POP AX
|
|||
|
|
|||
|
DOSVER_HIGH EQU 0200H ;2.00 in hex
|
|||
|
PUSH AX ;Save DRIVE validity info
|
|||
|
MOV AH,GET_VERSION
|
|||
|
INT 21H
|
|||
|
XCHG AH,AL ;Turn it around to AH.AL
|
|||
|
CMP AX,DOSVER_HIGH
|
|||
|
JAE OKDOS
|
|||
|
GOTBADDOS:
|
|||
|
MOV DX,OFFSET DG:BADVER
|
|||
|
CALL PRINT
|
|||
|
INT 20H
|
|||
|
|
|||
|
OKDOS: POP AX
|
|||
|
|
|||
|
cmp al,0ffH
|
|||
|
JZ BADDRVSPECJ
|
|||
|
mov si,80h
|
|||
|
lodsb
|
|||
|
or al,al
|
|||
|
jz noparm
|
|||
|
look: lodsb
|
|||
|
cmp al," "
|
|||
|
jz look
|
|||
|
cmp al,9
|
|||
|
jz look
|
|||
|
cmp al,13
|
|||
|
jnz gotparm
|
|||
|
noparm:
|
|||
|
jmp noname
|
|||
|
|
|||
|
BADDRVSPECJ: JMP BADDRVSPEC
|
|||
|
|
|||
|
gotparm:
|
|||
|
mov ah,DISK_RESET
|
|||
|
int bdos ;empty buffer queue
|
|||
|
|
|||
|
mov ah,get_default_drive ;save current drive
|
|||
|
int 21h
|
|||
|
mov [user_drive],al
|
|||
|
|
|||
|
mov bx,fcb ;determine input command
|
|||
|
mov al,[bx]
|
|||
|
dec al
|
|||
|
cmp al,-1
|
|||
|
jnz drvok1
|
|||
|
mov al,[user_drive]
|
|||
|
drvok1:
|
|||
|
mov [drive],al
|
|||
|
add [drvlet],al
|
|||
|
add [drvlet1],al
|
|||
|
mov dx,offset dg: askmsg
|
|||
|
call print
|
|||
|
mov ah,STD_CON_INPUT_FLUSH
|
|||
|
mov al,1 ;wait for a key
|
|||
|
int bdos
|
|||
|
|
|||
|
cmp al,17h
|
|||
|
jnz drvok2
|
|||
|
mov dx,offset dg: egomes
|
|||
|
jmp printerr
|
|||
|
egomes: db "Chris Peters helped with the new dos!",cr,lf
|
|||
|
db "Microsoft rules ok$"
|
|||
|
|
|||
|
drvok2:
|
|||
|
IF IBMVER
|
|||
|
MOV AL,DRIVE ;This is for ibm's single drive sys
|
|||
|
PUSH DS
|
|||
|
MOV BX,50H
|
|||
|
MOV DS,BX
|
|||
|
MOV DS:(BYTE PTR 4),AL ;Indicate drive changed
|
|||
|
POP DS
|
|||
|
ENDIF
|
|||
|
|
|||
|
;----- Process Pathnames -----------------------------------------------;
|
|||
|
mov ax,(char_oper shl 8) ;get switch character
|
|||
|
int 21h
|
|||
|
cmp dl,"/"
|
|||
|
jnz slashok ;if not / , then not PC
|
|||
|
mov [dirchar],"\" ;in PC, dir separator = \
|
|||
|
mov [userdir],"\"
|
|||
|
|
|||
|
slashok:
|
|||
|
mov si,81h ;point to cammand line
|
|||
|
mov di,offset dg: fname_buffer
|
|||
|
xor cx,cx ;zero pathname length
|
|||
|
|
|||
|
kill_bl:
|
|||
|
lodsb ;get rid of blanks
|
|||
|
cmp al,9
|
|||
|
je kill_bl
|
|||
|
cmp al,' '
|
|||
|
je kill_bl
|
|||
|
cmp al,13 ;A carriage return?
|
|||
|
jne next_char
|
|||
|
jmp noname ;yes, file name missing
|
|||
|
|
|||
|
next_char:
|
|||
|
stosb ;put patname in buffer
|
|||
|
inc cx
|
|||
|
lodsb
|
|||
|
cmp al,' '
|
|||
|
je name_copied
|
|||
|
cmp al,9
|
|||
|
je name_copied
|
|||
|
cmp al,13 ; a CR ?
|
|||
|
jne next_char
|
|||
|
|
|||
|
name_copied:
|
|||
|
mov byte ptr [di],0 ;nul terminate the pathname
|
|||
|
dec di ;adjust to the end of the pathname
|
|||
|
|
|||
|
;----- Scan for directory ----------------------------------------------;
|
|||
|
|
|||
|
IF KANJI
|
|||
|
mov dx,offset dg: [fname_buffer]
|
|||
|
PUSH DX
|
|||
|
PUSH DI
|
|||
|
MOV BX,DI
|
|||
|
MOV DI,DX
|
|||
|
DELLOOP:
|
|||
|
CMP DI,BX
|
|||
|
JZ GOTDELE
|
|||
|
MOV AL,[DI]
|
|||
|
INC DI
|
|||
|
CALL TESTKANJ
|
|||
|
JZ NOTKANJ11
|
|||
|
INC DI
|
|||
|
JMP DELLOOP
|
|||
|
|
|||
|
NOTKANJ11:
|
|||
|
cmp al,[dirchar]
|
|||
|
JNZ DELLOOP
|
|||
|
MOV DX,DI ;Point to char after '/'
|
|||
|
DEC DX
|
|||
|
DEC DX ;Point to char before '/'
|
|||
|
JMP DELLOOP
|
|||
|
|
|||
|
GOTDELE:
|
|||
|
MOV DI,DX
|
|||
|
POP AX ;Initial DI
|
|||
|
POP DX
|
|||
|
SUB AX,DI ;Distance moved
|
|||
|
SUB CX,AX ;Set correct CX
|
|||
|
CMP DX,DI
|
|||
|
JB sja ;Found a pathsep
|
|||
|
JA sjb ;Started with a pathsep, root
|
|||
|
MOV AX,[DI]
|
|||
|
CALL TESTKANJ
|
|||
|
JNZ same_dirj
|
|||
|
XCHG AH,AL
|
|||
|
cmp al,[dirchar]
|
|||
|
jz sja ;One character directory
|
|||
|
same_dirj:
|
|||
|
ELSE
|
|||
|
mov al,[dirchar] ;get directory separator character
|
|||
|
std ;scan backwards
|
|||
|
repnz scasb ;(cx has the pathname length)
|
|||
|
cld ;reset direction, just in case
|
|||
|
jz sja
|
|||
|
ENDIF
|
|||
|
|
|||
|
jmp same_dir ;no dir separator char. found, the
|
|||
|
; file is in the current directory
|
|||
|
; of the corresponding drive. Ergo,
|
|||
|
; the FCB contains the data already.
|
|||
|
|
|||
|
sja:
|
|||
|
jcxz sjb ;no more chars left, it refers to root
|
|||
|
cmp byte ptr [di],':' ;is the prvious character a disk def?
|
|||
|
jne not_root
|
|||
|
sjb:
|
|||
|
mov [the_root],01h ;file is in the root
|
|||
|
not_root:
|
|||
|
inc di ;point to dir separator char.
|
|||
|
mov al,0
|
|||
|
stosb ;nul terminate directory name
|
|||
|
pop ax
|
|||
|
push di ;save pointer to file name
|
|||
|
mov [fudge],01h ;remember that the current directory
|
|||
|
; has been changed.
|
|||
|
|
|||
|
;----- Save current directory for exit ---------------------------------;
|
|||
|
mov dl,byte ptr ds:[fcb] ;get specified drive if any
|
|||
|
or dl,dl ;default disk?
|
|||
|
jz same_drive
|
|||
|
dec dl ;adjust to real drive (a=0,b=1,...)
|
|||
|
mov ah,set_default_drive ;change disks
|
|||
|
int 21h
|
|||
|
cmp al,-1 ;error?
|
|||
|
jne same_drive
|
|||
|
BADDRVSPEC:
|
|||
|
mov dx,offset dg: baddrv
|
|||
|
jmp printerr
|
|||
|
|
|||
|
same_drive:
|
|||
|
mov ah,get_default_dpb
|
|||
|
int 21h
|
|||
|
|
|||
|
assume ds:nothing
|
|||
|
|
|||
|
cmp al,-1 ;bad drive? (should always be ok)
|
|||
|
jne drvisok
|
|||
|
mov dx,offset dg: baddrv
|
|||
|
jmp printerr
|
|||
|
|
|||
|
drvisok:
|
|||
|
cmp [bx.dpb_current_dir],0
|
|||
|
je curr_is_root
|
|||
|
mov si,bx
|
|||
|
add si,dpb_dir_text
|
|||
|
mov di,offset dg: userdir + 1
|
|||
|
|
|||
|
dir_save_loop:
|
|||
|
lodsb
|
|||
|
stosb
|
|||
|
or al,al
|
|||
|
jnz dir_save_loop
|
|||
|
|
|||
|
curr_is_root:
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
assume ds:dg
|
|||
|
|
|||
|
|
|||
|
;----- Change directories ----------------------------------------------;
|
|||
|
cmp [the_root],01h
|
|||
|
mov dx,offset dg: [dirchar] ;assume the root
|
|||
|
je sj1
|
|||
|
mov dx,offset dg: [fname_buffer]
|
|||
|
sj1:
|
|||
|
mov ah,chdir ;change directory
|
|||
|
int 21h
|
|||
|
mov dx,offset dg: baddrv
|
|||
|
jnc no_errors
|
|||
|
jmp printerr
|
|||
|
no_errors:
|
|||
|
|
|||
|
;----- Set Up int 24 intercept -----------------------------------------;
|
|||
|
|
|||
|
mov ax,(get_interrupt_vector shl 8) or 24h
|
|||
|
int 21h
|
|||
|
mov word ptr [hardch],bx
|
|||
|
mov word ptr [hardch+2],es
|
|||
|
mov ax,(set_interrupt_vector shl 8) or 23h
|
|||
|
mov dx,offset dg: int_23
|
|||
|
int 21h
|
|||
|
mov ax,(set_interrupt_vector shl 8) or 24h
|
|||
|
mov dx,offset dg: int_24
|
|||
|
int 21h
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
|
|||
|
;----- Parse filename to FCB -------------------------------------------;
|
|||
|
pop si
|
|||
|
mov di,fcb
|
|||
|
mov ax,(parse_file_descriptor shl 8) or 1
|
|||
|
int 21h
|
|||
|
push ax
|
|||
|
;-----------------------------------------------------------------------;
|
|||
|
same_dir:
|
|||
|
pop ax
|
|||
|
|
|||
|
mov bx,fcb
|
|||
|
cmp byte ptr [bx+1],' ' ;must specify file name
|
|||
|
jnz drvok
|
|||
|
cmp byte ptr [bx],0 ;or drive specifier
|
|||
|
jnz drvok
|
|||
|
noname: mov dx,offset dg: drverr
|
|||
|
call print
|
|||
|
jmp int_23
|
|||
|
|
|||
|
drvok: push ds
|
|||
|
mov dl,drive
|
|||
|
inc dl
|
|||
|
mov ah,GET_DPB
|
|||
|
int bdos
|
|||
|
mov ax,word ptr [bx+2] ;get physical sector size
|
|||
|
mov cl,byte ptr [bx+4] ;get sectors/cluster - 1
|
|||
|
xor ch,ch
|
|||
|
inc cx
|
|||
|
mov cs:secall,cx ;save sectors per cluster
|
|||
|
mul cx ;ax = bytes per cluster
|
|||
|
mov bp,word ptr [bx+11] ;get record of first sector
|
|||
|
mov dx,word ptr [bx+16] ;get record of first directory entry
|
|||
|
mov si,word ptr [bx+6] ;get record of first fat
|
|||
|
mov cl,byte ptr [bx+15] ;get size of fat
|
|||
|
mov di,word ptr [bx+13] ;get number of clusters
|
|||
|
mov ch,byte ptr [bx+8] ;get number of fats on drive
|
|||
|
mov bx,word ptr [bx+9] ;get max number of dir entries
|
|||
|
pop ds
|
|||
|
|
|||
|
mov maxent,bx
|
|||
|
mov firfat,si
|
|||
|
mov firrec,bp
|
|||
|
mov firdir,dx
|
|||
|
mov byte ptr fatsiz,cl
|
|||
|
mov lastfat,di ;number of fat entries
|
|||
|
mov byte ptr fatnum,ch ;save number of fats on disk
|
|||
|
|
|||
|
mov secsiz,ax
|
|||
|
|
|||
|
mov di,table ;di points into constructed directory
|
|||
|
mov ax,0e5e5h ;deleted file magic number
|
|||
|
shl bx,1 ;16 words in a dir entry
|
|||
|
shl bx,1
|
|||
|
shl bx,1
|
|||
|
shl bx,1
|
|||
|
mov cx,bx
|
|||
|
rep stosw
|
|||
|
|
|||
|
call readft
|
|||
|
mov bx,fcb
|
|||
|
cmp byte ptr [bx+1],' '
|
|||
|
jz recdsk
|
|||
|
jmp recfil
|
|||
|
|
|||
|
recdsk: mov di,table
|
|||
|
mov fatptr,2
|
|||
|
mov ax,fatptr
|
|||
|
step1: call getfat
|
|||
|
cmp bx,0fffh
|
|||
|
jz step1a
|
|||
|
jmp step6
|
|||
|
step1a: mov filsiz,0
|
|||
|
mov word ptr filsiz+2,0
|
|||
|
mov dx,lastfat
|
|||
|
mov target,ax
|
|||
|
step2: mov ax,2
|
|||
|
add filsiz,cx
|
|||
|
adc word ptr filsiz+2,0
|
|||
|
step3: call getfat
|
|||
|
cmp bx,target
|
|||
|
jne step4
|
|||
|
mov target,ax
|
|||
|
jmp step2
|
|||
|
step4: inc ax
|
|||
|
cmp ax,dx
|
|||
|
jle step3
|
|||
|
;
|
|||
|
; at this point target = head of list, filsiz = file size
|
|||
|
;
|
|||
|
inc filcnt ;increment file count
|
|||
|
mov ax,maxent
|
|||
|
cmp filcnt,ax ;compare with max number of entries
|
|||
|
ja direrr
|
|||
|
|
|||
|
mov si,(offset dg: dirent)+7
|
|||
|
nam0: inc byte ptr [si] ;increment file name
|
|||
|
cmp byte ptr [si],'9'
|
|||
|
jle nam1
|
|||
|
mov byte ptr [si],'0'
|
|||
|
dec si
|
|||
|
jmp nam0
|
|||
|
|
|||
|
nam1: mov ah,GET_DATE
|
|||
|
int bdos ;set the date
|
|||
|
sub cx,1980
|
|||
|
add dh,dh
|
|||
|
add dh,dh
|
|||
|
add dh,dh
|
|||
|
add dh,dh
|
|||
|
add dh,dh
|
|||
|
rcl cl,1
|
|||
|
or dh,dl
|
|||
|
mov byte ptr dirent+24,dh
|
|||
|
mov byte ptr dirent+25,cl
|
|||
|
mov ah,GET_TIME
|
|||
|
int bdos ;set the time
|
|||
|
shr dh,1
|
|||
|
add cl,cl
|
|||
|
add cl,cl
|
|||
|
add cl,cl
|
|||
|
rcl ch,1
|
|||
|
add cl,cl
|
|||
|
rcl ch,1
|
|||
|
add cl,cl
|
|||
|
rcl ch,1
|
|||
|
or dh,cl
|
|||
|
mov byte ptr dirent+22,dh
|
|||
|
mov byte ptr dirent+23,ch
|
|||
|
|
|||
|
mov ax,filsiz ;set file size
|
|||
|
mov word ptr dirent+28,ax
|
|||
|
mov ax,word ptr filsiz+2
|
|||
|
mov word ptr dirent+30,ax
|
|||
|
mov ax,target ;set first cluster location
|
|||
|
mov word ptr dirent+26,ax
|
|||
|
|
|||
|
mov si,offset dg: dirent ;copy in new dir entry
|
|||
|
mov cx,32
|
|||
|
rep movsb
|
|||
|
|
|||
|
step6: inc fatptr ;keep looking for eof's
|
|||
|
mov ax,fatptr
|
|||
|
cmp ax,lastfat
|
|||
|
jg step7
|
|||
|
jmp step1
|
|||
|
|
|||
|
direrr: dec filcnt
|
|||
|
mov dx,offset dg: dirmsg
|
|||
|
call print
|
|||
|
|
|||
|
step7:
|
|||
|
mov al,drive
|
|||
|
mov dx,firdir ;write out constructed directory
|
|||
|
mov cx,firrec
|
|||
|
sub cx,dx
|
|||
|
mov bx,table
|
|||
|
call dskwrt
|
|||
|
call pcrlf
|
|||
|
mov dx,offset dg: recmsg_pre
|
|||
|
call print
|
|||
|
mov bx,offset dg: recmsg_post
|
|||
|
mov si,filcnt
|
|||
|
xor di,di ;output number of files created
|
|||
|
call convert
|
|||
|
jmp rexit
|
|||
|
recfil: mov dx,fcb
|
|||
|
mov ah,FCB_OPEN
|
|||
|
int bdos
|
|||
|
inc al
|
|||
|
jnz recfil0
|
|||
|
mov dx,offset dg: opnerr
|
|||
|
call print
|
|||
|
jmp rexit
|
|||
|
|
|||
|
recfil0:mov lastfat,1 ;indicate location of list head
|
|||
|
mov di,fcb
|
|||
|
mov ax,[di+16] ;get file size
|
|||
|
mov filsiz,ax
|
|||
|
mov siztmp,ax
|
|||
|
mov ax,[di+18]
|
|||
|
mov filsiz+2,ax
|
|||
|
mov siztmp+2,ax
|
|||
|
mov ax,[di+25] ;get list head
|
|||
|
or ax,ax
|
|||
|
mov fatptr,ax
|
|||
|
jnz recfil1
|
|||
|
recvec: jmp recfil6
|
|||
|
|
|||
|
recfil1:cmp fatptr,0fffh
|
|||
|
jz recvec ;terminate loop at e-o-f
|
|||
|
|
|||
|
mov cx,secall
|
|||
|
mov ax,fatptr
|
|||
|
dec ax
|
|||
|
dec ax
|
|||
|
mul cx
|
|||
|
add ax,firrec
|
|||
|
mov dx,ax
|
|||
|
mov bx,table
|
|||
|
mov al,drive
|
|||
|
int aread
|
|||
|
pop di ;restore stack pointer
|
|||
|
mov di,fcb ;restore pointer to fcb
|
|||
|
jnc recfil4 ;if no error continue reading
|
|||
|
|
|||
|
mov ax,fatptr
|
|||
|
call getfat
|
|||
|
cmp lastfat,1
|
|||
|
jnz recfil2
|
|||
|
|
|||
|
cmp bx,0fffh
|
|||
|
jnz noteof
|
|||
|
xor bx,bx
|
|||
|
noteof: mov word ptr [di+25],bx
|
|||
|
jmp recfil3
|
|||
|
|
|||
|
recfil2:mov dx,bx ;jump around bad sector
|
|||
|
mov ax,lastfat
|
|||
|
call setfat
|
|||
|
|
|||
|
recfil3:mov ax,fatptr ;mark sector bad
|
|||
|
mov dx,0ff7h
|
|||
|
call setfat
|
|||
|
mov ax,secsiz ;prepare to dec filsiz by secsiz
|
|||
|
cmp siztmp+2,0
|
|||
|
jnz recfilx
|
|||
|
cmp siztmp,ax
|
|||
|
ja recfilx
|
|||
|
mov ax,siztmp
|
|||
|
|
|||
|
recfilx:sub word ptr [di+16],ax
|
|||
|
sbb word ptr [di+18],0
|
|||
|
sub siztmp,ax
|
|||
|
sbb siztmp,0
|
|||
|
|
|||
|
and byte ptr [di+24],10111111b ;mark file dirty
|
|||
|
|
|||
|
mov ax,lastfat ;point to next sector to check
|
|||
|
jmp recfil5
|
|||
|
|
|||
|
recfil4:
|
|||
|
mov ax,secsiz ;set bytes remaining to be read
|
|||
|
sub siztmp,ax
|
|||
|
sbb siztmp+2,0
|
|||
|
jnc recok
|
|||
|
xor ax,ax ;if < 0, then set to zero
|
|||
|
mov siztmp,ax
|
|||
|
mov siztmp+2,ax
|
|||
|
|
|||
|
recok: mov ax,fatptr ;get next sector to test
|
|||
|
mov lastfat,ax
|
|||
|
recfil5:call getfat
|
|||
|
mov fatptr,bx
|
|||
|
jmp recfil1
|
|||
|
|
|||
|
recfil6: ;all done
|
|||
|
mov dx,fcb
|
|||
|
mov ah,FCB_CLOSE
|
|||
|
int bdos ;close the file
|
|||
|
call pcrlf
|
|||
|
call report
|
|||
|
|
|||
|
;
|
|||
|
rexit: mov ah,DISK_RESET
|
|||
|
int bdos
|
|||
|
call wrtfat ;save the fat
|
|||
|
int_23: call rest_dir
|
|||
|
rabort: int boot ;home, james...
|
|||
|
|
|||
|
;----- Restore INT 24 vector and old current directory -----------------;
|
|||
|
rest_dir:
|
|||
|
cmp [fudge],0
|
|||
|
je no_fudge
|
|||
|
|
|||
|
mov ax,(set_interrupt_vector shl 8) or 24h
|
|||
|
lds dx,[hardch]
|
|||
|
int 21h
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
mov dx,offset dg: userdir ;restore directory
|
|||
|
mov ah,chdir
|
|||
|
int 21h
|
|||
|
mov dl,[user_drive] ;restore old current drive
|
|||
|
mov ah,set_default_drive
|
|||
|
int 21h
|
|||
|
|
|||
|
no_fudge:
|
|||
|
ret
|
|||
|
|
|||
|
;----- INT 24 Processing -----------------------------------------------;
|
|||
|
|
|||
|
int_24_retaddr dw int_24_back
|
|||
|
|
|||
|
int_24 proc far
|
|||
|
assume ds:nothing,es:nothing,ss:nothing
|
|||
|
|
|||
|
pushf
|
|||
|
push cs
|
|||
|
push [int_24_retaddr]
|
|||
|
push word ptr [hardch+2]
|
|||
|
push word ptr [hardch]
|
|||
|
ret
|
|||
|
int_24 endp
|
|||
|
|
|||
|
int_24_back:
|
|||
|
cmp al,2 ;abort?
|
|||
|
jnz ireti
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
assume ds:dg
|
|||
|
|
|||
|
call rest_dir
|
|||
|
int 20h
|
|||
|
ireti:
|
|||
|
iret
|
|||
|
|
|||
|
IF KANJI
|
|||
|
TESTKANJ:
|
|||
|
CMP AL,81H
|
|||
|
JB NOTLEAD
|
|||
|
CMP AL,9FH
|
|||
|
JBE ISLEAD
|
|||
|
CMP AL,0E0H
|
|||
|
JB NOTLEAD
|
|||
|
CMP AL,0FCH
|
|||
|
JBE ISLEAD
|
|||
|
NOTLEAD:
|
|||
|
PUSH AX
|
|||
|
XOR AX,AX ;Set zero
|
|||
|
POP AX
|
|||
|
RET
|
|||
|
|
|||
|
ISLEAD:
|
|||
|
PUSH AX
|
|||
|
XOR AX,AX ;Set zero
|
|||
|
INC AX ;Reset zero
|
|||
|
POP AX
|
|||
|
RET
|
|||
|
ENDIF
|
|||
|
|
|||
|
code ends
|
|||
|
|
|||
|
const segment public byte
|
|||
|
|
|||
|
EXTRN BADVER:BYTE,askmsg:BYTE,drvlet:BYTE,dirmsg:BYTE
|
|||
|
EXTRN recmsg_pre:BYTE,DRVLET1:BYTE,recmsg_post:BYTE
|
|||
|
EXTRN crlf:BYTE,drverr:BYTE,baddrv:BYTE,opnerr:BYTE
|
|||
|
|
|||
|
const ends
|
|||
|
|
|||
|
data segment byte
|
|||
|
|
|||
|
PUBLIC filsiz
|
|||
|
|
|||
|
dirent db 'FILE0000REC'
|
|||
|
db 21 dup (00)
|
|||
|
|
|||
|
fndfat dw 0000 ;sector of first good fat
|
|||
|
filcnt dw 0000
|
|||
|
fatcnt db 00
|
|||
|
fatnum db 00
|
|||
|
fatsiz dw 0000
|
|||
|
firfat dw 0000
|
|||
|
fatptr dw 0000
|
|||
|
secall dw 0000 ;sectors per cluster
|
|||
|
target dw 0000
|
|||
|
maxent dw 0000
|
|||
|
firrec dw 0000
|
|||
|
firdir dw 0000
|
|||
|
secsiz dw 0000
|
|||
|
siztmp dw 0000
|
|||
|
dw 0000
|
|||
|
filsiz dw 0000
|
|||
|
dw 0000
|
|||
|
lastfat dw 0000
|
|||
|
;
|
|||
|
table dw offset dg:fattbl + 6 * 1024
|
|||
|
fattbl db 0
|
|||
|
|
|||
|
data ends
|
|||
|
|
|||
|
end recover
|
|||
|
|