summaryrefslogtreecommitdiff
path: root/v2.0/source/RECOVER.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v2.0/source/RECOVER.ASM')
-rw-r--r--v2.0/source/RECOVER.ASM876
1 files changed, 876 insertions, 0 deletions
diff --git a/v2.0/source/RECOVER.ASM b/v2.0/source/RECOVER.ASM
new file mode 100644
index 0000000..05d27f9
--- /dev/null
+++ b/v2.0/source/RECOVER.ASM
@@ -0,0 +1,876 @@
1TITLE RECOVER MS-DOS File/Disk Recovery Utility
2;----------------------------------------------------------
3;
4; Recover - Program to rebuild an ms.dos directory
5;
6; Copyright 1982 by Microsoft Corporation
7; Written by Chris Peters, April 1982
8;
9;-----------------------------------------------------------
10;
11;REV 1.5 added header message ARR
12;
13
14FALSE EQU 0
15TRUE EQU NOT FALSE
16
17
18IBMVER EQU true
19KANJI EQU FALSE
20
21bdos equ 21h
22boot equ 20h
23aread equ 25h
24awrite equ 26h
25
26 INCLUDE DOSSYM.ASM
27
28;
29cr equ 0dh
30lf equ 0ah
31;
32fcb equ 5ch
33
34code segment public
35code ends
36
37const segment public byte
38const ends
39
40data segment public byte
41data ends
42
43
44dg group code,const,data
45
46code segment public
47 assume cs:dg,ds:dg,es:dg,ss:dg
48
49 PUBLIC PCRLF,PRINT,INT_23,convert
50 EXTRN dskwrt:NEAR,dskrd:NEAR,DSKERR:NEAR,report:NEAR
51
52 org 100h
53
54recover:jmp rec_start
55
56HEADER DB "Vers 1.50"
57
58;-----------------------------------------------------------------------;
59hardch dd ?
60
61the_root db 0 ;root directory flag
62
63fudge db 0 ;directory changed flag
64user_drive db 0
65drive db 0
66
67
68dirchar db "/",0
69
70
71userdir db "/",0
72 db (dirstrlen) dup(0)
73
74fname_buffer db 128 dup(0)
75;-----------------------------------------------------------------------;
76
77pcrlf: mov dx,offset dg: crlf
78print: mov ah,STD_CON_STRING_OUTPUT
79 int bdos
80pret: ret
81;
82convert:push bx
83 xor ax,ax
84 mov bx,ax
85 mov bp,ax
86 mov cx,32
87convlp: shl si,1
88 rcl di,1
89 xchg ax,bp
90 call convwrd
91 xchg ax,bp
92 xchg ax,bx
93 call convwrd
94 xchg ax,bx
95 adc al,0
96 loop convlp
97
98 mov cx,1810h
99 xchg dx,ax
100 call digit
101 xchg ax,bx
102 call outword
103 mov ax,bp
104 call outword
105 pop dx
106 call print
107ret2: ret
108;
109outword:push ax
110 mov dl,ah
111 call outbyte
112 pop dx
113outbyte:mov dh,dl
114 shr dl,1
115 shr dl,1
116 shr dl,1
117 shr dl,1
118 call digit
119 mov dl,dh
120digit: and dl,0fh
121 jz blankzer
122 xor cl,cl
123blankzer:
124 dec ch
125 and cl,ch
126 or dl,30h
127 sub dl,cl
128 cmp dl,30h
129 jl ret2
130 mov ah,STD_CON_OUTPUT
131 int bdos
132 ret
133;
134convwrd:adc al,al
135 daa
136 xchg al,ah
137 adc al,al
138 daa
139 xchg al,ah
140 ret
141;
142; bx = fat[ax]
143;
144getfat: mov bx,offset dg: fattbl
145 push ax
146 mov si,ax
147 sar ax,1
148 pushf
149 add si,ax
150 mov bx,word ptr [bx][si]
151 popf
152 jnc getfat1
153 mov cl,4
154 shr bx,cl
155getfat1:and bh,00001111b
156 pop ax
157 mov cx,secsiz
158 ret
159;
160; fat[ax] = dx
161;
162setfat: mov bx,offset dg: fattbl
163 push ax
164 push dx
165 mov si,ax
166 sar ax,1
167 pushf
168 add si,ax
169 mov ax,word ptr [bx][si]
170 popf
171 jnc setfat2
172 and ax,000fh
173 mov cl,4
174 shl dx,cl
175setfat1:or ax,dx
176 mov word ptr [bx][si],ax
177 pop dx
178 pop ax
179 ret
180
181setfat2:and ax,0f000h
182 jmp setfat1
183
184load: mov dx,firfat
185 mov al,byte ptr fatnum
186 mov byte ptr fatcnt,al
187 mov al,byte ptr drive
188 mov cx,fatsiz
189 mov bx,offset dg: fattbl
190ret66: ret
191
192readft: call load
193readit: call dskrd
194 cmp [fndfat],0 ;save location of readable fat sector
195 jnz fdfat
196 mov [fndfat],dx
197fdfat: cmp word ptr [bx+1],-1
198 jz ret66
199
200 add dx,cx ;try to read the other fats
201 dec byte ptr fatcnt
202 jnz readit
203
204 mov dx,[fndfat] ;see if any readable at all
205 or dx,dx
206 jz readft ;if not disk is blown, keep trying
207 call dskrd
208 ret
209
210wrtfat: call load
211wrtit: push ax
212 push bx
213 push cx
214 push dx
215 call dskwrt
216 pop dx
217 pop cx
218 pop bx
219 pop ax
220
221wrtok: add dx,cx
222 dec byte ptr fatcnt
223 jnz wrtit
224 ret
225
226printerr:
227 call print
228 jmp rabort
229
230
231rec_start:
232
233;Code to print header
234; PUSH AX
235; MOV DX,OFFSET DG:HEADER
236; CALL print
237; POP AX
238
239DOSVER_HIGH EQU 0200H ;2.00 in hex
240 PUSH AX ;Save DRIVE validity info
241 MOV AH,GET_VERSION
242 INT 21H
243 XCHG AH,AL ;Turn it around to AH.AL
244 CMP AX,DOSVER_HIGH
245 JAE OKDOS
246GOTBADDOS:
247 MOV DX,OFFSET DG:BADVER
248 CALL PRINT
249 INT 20H
250
251OKDOS: POP AX
252
253 cmp al,0ffH
254 JZ BADDRVSPECJ
255 mov si,80h
256 lodsb
257 or al,al
258 jz noparm
259look: lodsb
260 cmp al," "
261 jz look
262 cmp al,9
263 jz look
264 cmp al,13
265 jnz gotparm
266noparm:
267 jmp noname
268
269BADDRVSPECJ: JMP BADDRVSPEC
270
271gotparm:
272 mov ah,DISK_RESET
273 int bdos ;empty buffer queue
274
275 mov ah,get_default_drive ;save current drive
276 int 21h
277 mov [user_drive],al
278
279 mov bx,fcb ;determine input command
280 mov al,[bx]
281 dec al
282 cmp al,-1
283 jnz drvok1
284 mov al,[user_drive]
285drvok1:
286 mov [drive],al
287 add [drvlet],al
288 add [drvlet1],al
289 mov dx,offset dg: askmsg
290 call print
291 mov ah,STD_CON_INPUT_FLUSH
292 mov al,1 ;wait for a key
293 int bdos
294
295 cmp al,17h
296 jnz drvok2
297 mov dx,offset dg: egomes
298 jmp printerr
299egomes: db "Chris Peters helped with the new dos!",cr,lf
300 db "Microsoft rules ok$"
301
302drvok2:
303 IF IBMVER
304 MOV AL,DRIVE ;This is for ibm's single drive sys
305 PUSH DS
306 MOV BX,50H
307 MOV DS,BX
308 MOV DS:(BYTE PTR 4),AL ;Indicate drive changed
309 POP DS
310 ENDIF
311
312;----- Process Pathnames -----------------------------------------------;
313 mov ax,(char_oper shl 8) ;get switch character
314 int 21h
315 cmp dl,"/"
316 jnz slashok ;if not / , then not PC
317 mov [dirchar],"\" ;in PC, dir separator = \
318 mov [userdir],"\"
319
320slashok:
321 mov si,81h ;point to cammand line
322 mov di,offset dg: fname_buffer
323 xor cx,cx ;zero pathname length
324
325kill_bl:
326 lodsb ;get rid of blanks
327 cmp al,9
328 je kill_bl
329 cmp al,' '
330 je kill_bl
331 cmp al,13 ;A carriage return?
332 jne next_char
333 jmp noname ;yes, file name missing
334
335next_char:
336 stosb ;put patname in buffer
337 inc cx
338 lodsb
339 cmp al,' '
340 je name_copied
341 cmp al,9
342 je name_copied
343 cmp al,13 ; a CR ?
344 jne next_char
345
346name_copied:
347 mov byte ptr [di],0 ;nul terminate the pathname
348 dec di ;adjust to the end of the pathname
349
350;----- Scan for directory ----------------------------------------------;
351
352 IF KANJI
353 mov dx,offset dg: [fname_buffer]
354 PUSH DX
355 PUSH DI
356 MOV BX,DI
357 MOV DI,DX
358DELLOOP:
359 CMP DI,BX
360 JZ GOTDELE
361 MOV AL,[DI]
362 INC DI
363 CALL TESTKANJ
364 JZ NOTKANJ11
365 INC DI
366 JMP DELLOOP
367
368NOTKANJ11:
369 cmp al,[dirchar]
370 JNZ DELLOOP
371 MOV DX,DI ;Point to char after '/'
372 DEC DX
373 DEC DX ;Point to char before '/'
374 JMP DELLOOP
375
376GOTDELE:
377 MOV DI,DX
378 POP AX ;Initial DI
379 POP DX
380 SUB AX,DI ;Distance moved
381 SUB CX,AX ;Set correct CX
382 CMP DX,DI
383 JB sja ;Found a pathsep
384 JA sjb ;Started with a pathsep, root
385 MOV AX,[DI]
386 CALL TESTKANJ
387 JNZ same_dirj
388 XCHG AH,AL
389 cmp al,[dirchar]
390 jz sja ;One character directory
391same_dirj:
392 ELSE
393 mov al,[dirchar] ;get directory separator character
394 std ;scan backwards
395 repnz scasb ;(cx has the pathname length)
396 cld ;reset direction, just in case
397 jz sja
398 ENDIF
399
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.
404
405sja:
406 jcxz sjb ;no more chars left, it refers to root
407 cmp byte ptr [di],':' ;is the prvious character a disk def?
408 jne not_root
409sjb:
410 mov [the_root],01h ;file is in the root
411not_root:
412 inc di ;point to dir separator char.
413 mov al,0
414 stosb ;nul terminate directory name
415 pop ax
416 push di ;save pointer to file name
417 mov [fudge],01h ;remember that the current directory
418 ; has been changed.
419
420;----- Save current directory for exit ---------------------------------;
421 mov dl,byte ptr ds:[fcb] ;get specified drive if any
422 or dl,dl ;default disk?
423 jz same_drive
424 dec dl ;adjust to real drive (a=0,b=1,...)
425 mov ah,set_default_drive ;change disks
426 int 21h
427 cmp al,-1 ;error?
428 jne same_drive
429BADDRVSPEC:
430 mov dx,offset dg: baddrv
431 jmp printerr
432
433same_drive:
434 mov ah,get_default_dpb
435 int 21h
436
437assume ds:nothing
438
439 cmp al,-1 ;bad drive? (should always be ok)
440 jne drvisok
441 mov dx,offset dg: baddrv
442 jmp printerr
443
444drvisok:
445 cmp [bx.dpb_current_dir],0
446 je curr_is_root
447 mov si,bx
448 add si,dpb_dir_text
449 mov di,offset dg: userdir + 1
450
451dir_save_loop:
452 lodsb
453 stosb
454 or al,al
455 jnz dir_save_loop
456
457curr_is_root:
458 push cs
459 pop ds
460
461assume ds:dg
462
463
464;----- Change directories ----------------------------------------------;
465 cmp [the_root],01h
466 mov dx,offset dg: [dirchar] ;assume the root
467 je sj1
468 mov dx,offset dg: [fname_buffer]
469sj1:
470 mov ah,chdir ;change directory
471 int 21h
472 mov dx,offset dg: baddrv
473 jnc no_errors
474 jmp printerr
475no_errors:
476
477;----- Set Up int 24 intercept -----------------------------------------;
478
479 mov ax,(get_interrupt_vector shl 8) or 24h
480 int 21h
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
485 int 21h
486 mov ax,(set_interrupt_vector shl 8) or 24h
487 mov dx,offset dg: int_24
488 int 21h
489 push cs
490 pop es
491
492;----- Parse filename to FCB -------------------------------------------;
493 pop si
494 mov di,fcb
495 mov ax,(parse_file_descriptor shl 8) or 1
496 int 21h
497 push ax
498;-----------------------------------------------------------------------;
499same_dir:
500 pop ax
501
502 mov bx,fcb
503 cmp byte ptr [bx+1],' ' ;must specify file name
504 jnz drvok
505 cmp byte ptr [bx],0 ;or drive specifier
506 jnz drvok
507noname: mov dx,offset dg: drverr
508 call print
509 jmp int_23
510
511drvok: push ds
512 mov dl,drive
513 inc dl
514 mov ah,GET_DPB
515 int bdos
516 mov ax,word ptr [bx+2] ;get physical sector size
517 mov cl,byte ptr [bx+4] ;get sectors/cluster - 1
518 xor ch,ch
519 inc cx
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
529 pop ds
530
531 mov maxent,bx
532 mov firfat,si
533 mov firrec,bp
534 mov firdir,dx
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
538
539 mov secsiz,ax
540
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
544 shl bx,1
545 shl bx,1
546 shl bx,1
547 mov cx,bx
548 rep stosw
549
550 call readft
551 mov bx,fcb
552 cmp byte ptr [bx+1],' '
553 jz recdsk
554 jmp recfil
555
556recdsk: mov di,table
557 mov fatptr,2
558 mov ax,fatptr
559step1: call getfat
560 cmp bx,0fffh
561 jz step1a
562 jmp step6
563step1a: mov filsiz,0
564 mov word ptr filsiz+2,0
565 mov dx,lastfat
566 mov target,ax
567step2: mov ax,2
568 add filsiz,cx
569 adc word ptr filsiz+2,0
570step3: call getfat
571 cmp bx,target
572 jne step4
573 mov target,ax
574 jmp step2
575step4: inc ax
576 cmp ax,dx
577 jle step3
578;
579; at this point target = head of list, filsiz = file size
580;
581 inc filcnt ;increment file count
582 mov ax,maxent
583 cmp filcnt,ax ;compare with max number of entries
584 ja direrr
585
586 mov si,(offset dg: dirent)+7
587nam0: inc byte ptr [si] ;increment file name
588 cmp byte ptr [si],'9'
589 jle nam1
590 mov byte ptr [si],'0'
591 dec si
592 jmp nam0
593
594nam1: mov ah,GET_DATE
595 int bdos ;set the date
596 sub cx,1980
597 add dh,dh
598 add dh,dh
599 add dh,dh
600 add dh,dh
601 add dh,dh
602 rcl cl,1
603 or dh,dl
604 mov byte ptr dirent+24,dh
605 mov byte ptr dirent+25,cl
606 mov ah,GET_TIME
607 int bdos ;set the time
608 shr dh,1
609 add cl,cl
610 add cl,cl
611 add cl,cl
612 rcl ch,1
613 add cl,cl
614 rcl ch,1
615 add cl,cl
616 rcl ch,1
617 or dh,cl
618 mov byte ptr dirent+22,dh
619 mov byte ptr dirent+23,ch
620
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
627
628 mov si,offset dg: dirent ;copy in new dir entry
629 mov cx,32
630 rep movsb
631
632step6: inc fatptr ;keep looking for eof's
633 mov ax,fatptr
634 cmp ax,lastfat
635 jg step7
636 jmp step1
637
638direrr: dec filcnt
639 mov dx,offset dg: dirmsg
640 call print
641
642step7:
643 mov al,drive
644 mov dx,firdir ;write out constructed directory
645 mov cx,firrec
646 sub cx,dx
647 mov bx,table
648 call dskwrt
649 call pcrlf
650 mov dx,offset dg: recmsg_pre
651 call print
652 mov bx,offset dg: recmsg_post
653 mov si,filcnt
654 xor di,di ;output number of files created
655 call convert
656 jmp rexit
657recfil: mov dx,fcb
658 mov ah,FCB_OPEN
659 int bdos
660 inc al
661 jnz recfil0
662 mov dx,offset dg: opnerr
663 call print
664 jmp rexit
665
666recfil0:mov lastfat,1 ;indicate location of list head
667 mov di,fcb
668 mov ax,[di+16] ;get file size
669 mov filsiz,ax
670 mov siztmp,ax
671 mov ax,[di+18]
672 mov filsiz+2,ax
673 mov siztmp+2,ax
674 mov ax,[di+25] ;get list head
675 or ax,ax
676 mov fatptr,ax
677 jnz recfil1
678recvec: jmp recfil6
679
680recfil1:cmp fatptr,0fffh
681 jz recvec ;terminate loop at e-o-f
682
683 mov cx,secall
684 mov ax,fatptr
685 dec ax
686 dec ax
687 mul cx
688 add ax,firrec
689 mov dx,ax
690 mov bx,table
691 mov al,drive
692 int aread
693 pop di ;restore stack pointer
694 mov di,fcb ;restore pointer to fcb
695 jnc recfil4 ;if no error continue reading
696
697 mov ax,fatptr
698 call getfat
699 cmp lastfat,1
700 jnz recfil2
701
702 cmp bx,0fffh
703 jnz noteof
704 xor bx,bx
705noteof: mov word ptr [di+25],bx
706 jmp recfil3
707
708recfil2:mov dx,bx ;jump around bad sector
709 mov ax,lastfat
710 call setfat
711
712recfil3:mov ax,fatptr ;mark sector bad
713 mov dx,0ff7h
714 call setfat
715 mov ax,secsiz ;prepare to dec filsiz by secsiz
716 cmp siztmp+2,0
717 jnz recfilx
718 cmp siztmp,ax
719 ja recfilx
720 mov ax,siztmp
721
722recfilx:sub word ptr [di+16],ax
723 sbb word ptr [di+18],0
724 sub siztmp,ax
725 sbb siztmp,0
726
727 and byte ptr [di+24],10111111b ;mark file dirty
728
729 mov ax,lastfat ;point to next sector to check
730 jmp recfil5
731
732recfil4:
733 mov ax,secsiz ;set bytes remaining to be read
734 sub siztmp,ax
735 sbb siztmp+2,0
736 jnc recok
737 xor ax,ax ;if < 0, then set to zero
738 mov siztmp,ax
739 mov siztmp+2,ax
740
741recok: mov ax,fatptr ;get next sector to test
742 mov lastfat,ax
743recfil5:call getfat
744 mov fatptr,bx
745 jmp recfil1
746
747recfil6: ;all done
748 mov dx,fcb
749 mov ah,FCB_CLOSE
750 int bdos ;close the file
751 call pcrlf
752 call report
753
754;
755rexit: mov ah,DISK_RESET
756 int bdos
757 call wrtfat ;save the fat
758int_23: call rest_dir
759rabort: int boot ;home, james...
760
761;----- Restore INT 24 vector and old current directory -----------------;
762rest_dir:
763 cmp [fudge],0
764 je no_fudge
765
766 mov ax,(set_interrupt_vector shl 8) or 24h
767 lds dx,[hardch]
768 int 21h
769 push cs
770 pop ds
771
772 mov dx,offset dg: userdir ;restore directory
773 mov ah,chdir
774 int 21h
775 mov dl,[user_drive] ;restore old current drive
776 mov ah,set_default_drive
777 int 21h
778
779no_fudge:
780 ret
781
782;----- INT 24 Processing -----------------------------------------------;
783
784int_24_retaddr dw int_24_back
785
786int_24 proc far
787assume ds:nothing,es:nothing,ss:nothing
788
789 pushf
790 push cs
791 push [int_24_retaddr]
792 push word ptr [hardch+2]
793 push word ptr [hardch]
794 ret
795int_24 endp
796
797int_24_back:
798 cmp al,2 ;abort?
799 jnz ireti
800 push cs
801 pop ds
802
803assume ds:dg
804
805 call rest_dir
806 int 20h
807ireti:
808 iret
809
810 IF KANJI
811TESTKANJ:
812 CMP AL,81H
813 JB NOTLEAD
814 CMP AL,9FH
815 JBE ISLEAD
816 CMP AL,0E0H
817 JB NOTLEAD
818 CMP AL,0FCH
819 JBE ISLEAD
820NOTLEAD:
821 PUSH AX
822 XOR AX,AX ;Set zero
823 POP AX
824 RET
825
826ISLEAD:
827 PUSH AX
828 XOR AX,AX ;Set zero
829 INC AX ;Reset zero
830 POP AX
831 RET
832 ENDIF
833
834code ends
835
836const segment public byte
837
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
841
842const ends
843
844data segment byte
845
846 PUBLIC filsiz
847
848dirent db 'FILE0000REC'
849 db 21 dup (00)
850
851fndfat dw 0000 ;sector of first good fat
852filcnt dw 0000
853fatcnt db 00
854fatnum db 00
855fatsiz dw 0000
856firfat dw 0000
857fatptr dw 0000
858secall dw 0000 ;sectors per cluster
859target dw 0000
860maxent dw 0000
861firrec dw 0000
862firdir dw 0000
863secsiz dw 0000
864siztmp dw 0000
865 dw 0000
866filsiz dw 0000
867 dw 0000
868lastfat dw 0000
869;
870table dw offset dg:fattbl + 6 * 1024
871fattbl db 0
872
873data ends
874
875 end recover
876