summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/RECOVER
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/RECOVER')
-rw-r--r--v4.0/src/CMD/RECOVER/MAKEFILE64
-rw-r--r--v4.0/src/CMD/RECOVER/PATHMAC.INC32
-rw-r--r--v4.0/src/CMD/RECOVER/RECCHNG.INC161
-rw-r--r--v4.0/src/CMD/RECOVER/RECDATA.INC168
-rw-r--r--v4.0/src/CMD/RECOVER/RECDISP.ASM159
-rw-r--r--v4.0/src/CMD/RECOVER/RECEQU.INC174
-rw-r--r--v4.0/src/CMD/RECOVER/RECINIT.ASM1028
-rw-r--r--v4.0/src/CMD/RECOVER/RECMACRO.INC95
-rw-r--r--v4.0/src/CMD/RECOVER/RECMSG.INC307
-rw-r--r--v4.0/src/CMD/RECOVER/RECOVER.ASM1615
-rw-r--r--v4.0/src/CMD/RECOVER/RECOVER.LNK6
-rw-r--r--v4.0/src/CMD/RECOVER/RECOVER.SKL29
-rw-r--r--v4.0/src/CMD/RECOVER/RECPARSE.INC177
-rw-r--r--v4.0/src/CMD/RECOVER/RECPROC.ASM531
-rw-r--r--v4.0/src/CMD/RECOVER/RECPUB.INC47
-rw-r--r--v4.0/src/CMD/RECOVER/RECSEG.INC21
16 files changed, 4614 insertions, 0 deletions
diff --git a/v4.0/src/CMD/RECOVER/MAKEFILE b/v4.0/src/CMD/RECOVER/MAKEFILE
new file mode 100644
index 0000000..aa93335
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/MAKEFILE
@@ -0,0 +1,64 @@
1#************************** makefile for cmd\... ***************************
2
3msg =..\..\messages
4dos =..\..\dos
5inc =..\..\inc
6hinc =..\..\h
7
8#
9####################### dependencies begin here. #########################
10#
11
12all: recover.com
13
14recover.ctl : recover.skl \
15 $(msg)\$(COUNTRY).msg \
16 makefile
17
18recover.obj: recover.asm \
19 recequ.inc recmacro.inc \
20 recseg.inc recdata.inc recparse.inc \
21 recmsg.inc \
22 recover.ctl recover.cl1 \
23 recover.cl2 recover.cla \
24 $(inc)\dossym.inc $(inc)\syscall.inc \
25 $(inc)\sysmsg.inc $(inc)\parse.asm \
26 makefile
27
28recinit.obj: recinit.asm \
29 recequ.inc recmacro.inc \
30 recseg.inc recdata.inc recparse.inc \
31 recmsg.inc \
32 recover.ctl recover.cl1 \
33 recover.cl2 recover.cla \
34 $(inc)\dossym.inc $(inc)\syscall.inc \
35 $(inc)\sysmsg.inc $(inc)\parse.asm \
36 makefile
37
38
39recproc.obj: recproc.asm \
40 recequ.inc recmacro.inc \
41 recseg.inc recdata.inc recparse.inc \
42 recmsg.inc \
43 recover.ctl recover.cl1 \
44 recover.cl2 recover.cla \
45 $(inc)\dossym.inc $(inc)\syscall.inc \
46 $(inc)\sysmsg.inc $(inc)\parse.asm \
47 makefile
48
49recdisp.obj: recdisp.asm \
50 recequ.inc recmacro.inc \
51 recseg.inc recdata.inc recparse.inc \
52 recmsg.inc \
53 recover.ctl recover.cl1 \
54 recover.cl2 recover.cla \
55 $(inc)\dossym.inc $(inc)\syscall.inc \
56 $(inc)\sysmsg.inc $(inc)\parse.asm \
57 makefile
58
59
60recover.com: recover.obj recproc.obj recinit.obj \
61 recdisp.obj \
62 recover.lnk makefile
63 link @recover.lnk
64 convert recover.exe
diff --git a/v4.0/src/CMD/RECOVER/PATHMAC.INC b/v4.0/src/CMD/RECOVER/PATHMAC.INC
new file mode 100644
index 0000000..17d8aea
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/PATHMAC.INC
@@ -0,0 +1,32 @@
1
2;***********************************************************************
3; NAME: pathlabl
4; DESC: creates a public label at the spot it is placed, using the name
5; given.
6; INPUT: either module name or procedure name
7; OUTPUT: public label
8; LOGIC: if masm is in pass1 (pass2 will gen dup labels)
9; if this label has not been gen before
10; then create the label
11; - $$A to place at begin of map
12; - start means first occurence
13; - use module/proc name last
14; define this label for creation of 'stop' label
15; else create stop label
16; - same as start except name
17;***********************************************************************
18.LALL
19pathlabl MACRO pnam
20IF1 ;if pass 1
21 IFNDEF LBL_&pnam ;switch not defined if first creation
22 $$A_START_&pnam: ;create label
23 PUBLIC $$A_START_&pnam ;make it public
24 LBL_&pnam = 1 ;set switch
25 ELSE ;start label already created
26 $$A_STOP_&pnam: ;create stop label
27 PUBLIC $$A_STOP_&pnam ;make it public
28 ENDIF
29ENDIF
30ENDM
31
32 \ No newline at end of file
diff --git a/v4.0/src/CMD/RECOVER/RECCHNG.INC b/v4.0/src/CMD/RECOVER/RECCHNG.INC
new file mode 100644
index 0000000..016ecfd
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECCHNG.INC
@@ -0,0 +1,161 @@
1.xlist
2;
3;
4;REV 1.0
5;
6;REV 1.5
7; Added header message ARR
8;REV EKE 9/8/83
9; added code for 2.X, it now quits if trying to recover over a net
10;REV EKE 10/13/83
11; Fixed current directory saving.
12;REV NP 10/17/83
13; Use printf for messages.
14; And now it's an .EXE file.
15;REV 2.0
16; MZ 11/1/83
17; Commented the source
18; Used symbols from DOSSYM
19; Fixed for 16-bit fats.
20;
21;*****************************************************************************
22;* *
23;* Change list to RECOVER modules *
24;* *
25;* Lines are tagged ANxxx for new, ACxxx for changed *
26;* --------------------------------------------------------------------------*
27;* 000 - DOS 4.00 Spec additions and DCR's thru unit/function test *
28;* Date: 8/3/87
29;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
30;* 001 - DOS 4.00 PTM P265 - Give 'Can't chkdsk subst drive" when running *
31;* hardfile. Using 1 based drive insted of 0 *
32;* Date: 8/17/87
33;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
34;* 002 - DOS 4.00 PTM P251 - Hang when chkdsk default drive. Not setting up *
35;* drive fields correctly on default drive *
36;* Date: 8/14/87
37;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
38;* *
39;* *
40;* *
41;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
42;* *
43;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
44;* 005 - DOS 4.00 DCR D166 - Enable 128k FAT *
45;* Date: 8/21/87
46;* procedures changed - calc_fat_addr, readft, wrtft, getfat, setfat, fillfat*
47;* read_disk, read_once, write_disk, write_once, read_file, drive_spec *
48;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
49;* 006 - DOS 4.00 ptm p??? - msg when disk full *
50;* Date: 8/21/87
51;* procedures changed - main_loop1 *
52;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
53;* 007 - DOS 4.00 ptm p1682- redirection to file not working *
54;* Date: 10/14/87
55;* procedures changed - recmsg.inc *
56;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
57;* 008 - DOS 4.00 ptm p1845- changes current drive *
58;* Date: 10/20/87
59;* procedures changed - recover.sal *
60;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
61;* 009 - DOS 4.00 ptm p1850- a:recover c: --> 'insert diskette for drive b' *
62;* Date: 10/21/87
63;* procedures changed - recinit.sal *
64;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
65;* 010 - DOS 4.00 ptm p1934- no msg displayed for 'recover a:' *
66;* Date: 10/22/87
67;* procedures changed - recover.sal, recproc.sal *
68;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
69;* 011 - DOS 4.00 ptm p2020- recover doesnt exec *
70;* Date: 10/25/87
71;* procedures changed - recexec.sal *
72;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
73;* 012 - DOS 4.00 ptm p2224 & p2230 - dbcs handling *
74;* Date: 11/02/87
75;* procedures changed - recover.sal, recdbcs.sal *
76;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
77;* 013 - DOS 4.00 ptm p2264 - no low memory error checking *
78;* Date: 11/04/87
79;* procedures changed - recover.sal *
80;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
81;* 014 - DOS 4.00 ptm p2650 - doesnt handle c:\file.nam *
82;* Date: 11/24/87
83;* procedures changed - recover.sal *
84;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
85;* 015 - DOS 4.00 ptm p2702,2730 - doesnt report not writing to fat *
86;* Date: 11/30/87
87;* procedures changed - recover.sal *
88;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
89;* 016 - DOS 4.00 ptm p2868 - recover files gone *
90;* Date: 12/10/87
91;* procedures changed - none - recproc.sal was not exported on 10-22-87 *
92;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
93;* 017 - DOS 4.00 ptm p3013 - ADD CHECK for carry after name translate *
94;* Date: 12/29/87
95;* procedures changed - recinit.sal *
96;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
97;* 018 - DOS 4.00 ptm p2991 - problem with space after drive letter *
98;* Date: 12/29/87
99;* procedures changed - recover.sal *
100;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
101;* 019 - DOS 4.00 ptm p3029 - doesn't handle subdirs *
102;* Date: 1/05/88
103;* procedures changed - recover.sal *
104;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
105;* 020 - DOS 4.00 ptm p3042 - *
106;* Date: 1/06/88
107;* procedures changed - recover.sal *
108;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
109;* 021 - DOS 4.00 ptm p3138 - file not found if a:\filename *
110;* Date: 1/22/88
111;* procedures changed - recover.sal *
112;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
113;* 022 - DOS 4.00 ptm p3130 - remove AFS *
114;* Date: 1/25/88
115;* procedures changed - recexec.sal, recover.mak, recover.arf, recover.skl *
116;* - recmsg.inc, recequ.inc, recdata.inc, recinit.sal *
117;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
118;* 023 - DOS 4.00 ptm p3136 - cannot write fat on hard file *
119;* Date: 1/25/88
120;* procedures changed - recproc.sal *
121;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
122;* 024 - DOS 4.00 ptm p3160 - cannot handle '\' as dbcs second byte *
123;* Date: 1/25/88
124;* procedures changed - recover.sal, recdata.inc *
125;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
126;* 025 - DOS 4.00 ptm p3280 - include basesw for parser *
127;* Date: 1/29/88
128;* procedures changed - recparse.inc *
129;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
130;* 026 - DOS 4.00 ptm p3360 - handle control-break *
131;* Date: 2/04/88
132;* procedures changed - recover.sal *
133;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
134;* 027 - DOS 4.00 ptm p3471 - recover drive on >32M *
135;* Date: 2/17/88
136;* procedures changed - recover.sal *
137;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
138;* 028 - DOS 4.00 ptm p3573 - make changes for pathgen of parser and msg ret *
139;* Date: 2/19/88
140;* procedures changed - recparse.inc, recdisp.asm *
141;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
142;* 029 - DOS 4.00 ptm p3631 - correct changes made for pathgen of msg ret *
143;* Date: 2/26/88
144;* procedures changed - recdisp.asm *
145;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
146;* 030 - DOS 4.00 dcr d490 - make get/set media id same as os/2 1.0 *
147;* Date: 2/26/88
148;* procedures changed - recinit.sal *
149;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
150;* 031 - DOS 4.00 PTM P3923 - DISPLAY INVALID PARMS *
151;* Date: 3/23/88
152;* procedures changed - recinit.sal, recmsg.inc *
153;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
154;* 032 - DOS 4.00 PTM P4387 - remove sf_extclus from source *
155;* Date: 4/18/88
156;* procedures changed - recover.sal *
157;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
158;* *
159;*****************************************************************************
160;* Note: This is file CHKCHNG.INC for updating purposes *
161;*****************************************************************************
diff --git a/v4.0/src/CMD/RECOVER/RECDATA.INC b/v4.0/src/CMD/RECOVER/RECDATA.INC
new file mode 100644
index 0000000..4685790
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECDATA.INC
@@ -0,0 +1,168 @@
1
2 data segment PUBLIC para 'DATA' ;AC000;bgb
3;*****************************************************************************
4; Data Area
5;*****************************************************************************
6;
7lastchar dw 0 ;an024;bgb
8lastbs dw 0 ;an024;bgb
9fndback dw 0 ;point to where backslash found
10old_subdir db 64 dup(0) ;current sub directory
11new_subdir db 64 dup(0) ;new sub directory
12paras_per_64k dw 0
13paras_per_fat dw 0
14secs_per_64k dw 0
15sec_count dw 0
16sixteen dw 16 ; mul ax for 32 bytes / fat entry
17exit_sw dw ? ; loop exit switch ;AN000;bgb
18exit_sw2 dw ? ; loop exit switch ;AN000;bgb
19old_drive db 0 ;original drive to restore to ;an008;bgb
20drvlet db 'A: ',13,10,13,10,0 ; ;AN000;
21rec_num dw ? ; ;AN000;
22x_value_lo dw ? ; ;AN000;
23x_value_hi dw ? ; ;AN000;
24y_value_lo dw ? ; ;AN000;
25y_value_hi dw ? ; ;AN000;
26DRVLET1 db "A",0
27;
28 HEADER DB "Vers 2.00"
29;-----------------------------------------------------------------------;
30 Prompted db 0 ; TRUE => prompt has already been done
31 hardch dd ? ; saved int 24 vector
32 the_root db 0 ; root directory flag
33 fudge db 0 ; directory changed flag
34 user_drive db 0
35 drive db 0
36 dirchar db "/",0
37 userdir db "/",0
38 db (dirstrlen) dup(0)
39 fname_buffer db 128 dup(0)
40
41found db no
42done db no
43PSP_Segment dw 0
44ExitStatus db 0 ;Errorlevel code ;AN000;
45
46 ;
47BPB_Buffer A_DeviceParameters <> ; ;AN000;
48
49TranSrc db "A:\",0 ; ;AN000;
50
51Data_Start_Low dw ? ; ;AN000;
52Data_Start_High dw ? ; ;AN000;
53
54INT_23_Old_Off dw ? ; ;AN000;
55INT_23_Old_Seg dw ? ; ;AN000;
56INT_24_Old_Off dw ? ; ;AN000;
57INT_24_Old_Seg dw ? ; ;AN000;
58
59
60Command_Line_Buffer db 128 dup(0) ; ;AN000;
61Fatal_Error db 0 ; ;AN000;
62
63Command_Line db NO ; ;AN000;
64
65;These should stay together ; ;an022;bgb
66; --------------------------------------- ; ; ;an022;bgb
67ifdef fsexec ;an022;bgb
68 FS_String_Buffer db 13 dup(" ") ; ;AN000; ;an022;bgb
69 FS_String_End db "REC.EXE",0 ; ;AN000; ;an022;bgb
70;---------------------------------------- ; ;an022;bgb
71 FS_Not_Fat db 0 ; ;AN000;;an022;bgb
72FAT12_String db "FAT12 " ;
73FAT16_String db "FAT16 " ;
74
75Media_ID_Buffer Media_ID <> ; ;AN000;
76endif ;an022;bgb
77
78Append db 0 ;
79
80
81dirent db 'FILE0000REC'
82 db 21 dup (00)
83
84fcb_copy db 32 dup (?)
85
86filcnt dw 0000
87fatcnt db 00
88fatnum db 00
89fatsiz dw 0000
90firfat dw 0000
91fatptr dw 0000
92secall dw 0000 ; sectors per cluster
93target dw 0000
94maxent dw 0000
95firrec dw 0000
96firdir dw 0000
97bytes_per_sector dw 0000
98secsiz dw 0000
99siztmp dw 0000
100 dw 0000
101filsiz dw 0000
102 dw 0000 ;carry noted here - 2 bytes after filsiz
103MaxClus DW 0
104lastfat dw 0000
105;
106dbcs_sw db 0 ;zero if not dbcs - one if dbcs found ;an024;bgb
107DBCS_Vector db 0
108DBCS_Vector_Off dw 0
109DBCS_Vector_Seg dw 0
110Read_Write_Relative Relative_Sector_Buffer <>
111Drive_Letter_Msg db "A:",0 ;Drive for exec fail message
112
113ifdef fsexec ;an022;bgb
114;Exec_Block Exec_Block_Parms <> ;an022;bgb
115;EXEC_Path db 66 dup(0) ;an022;bgb
116;These next two should stay together
117; ---------------------------------------
118;Path_String db "PATH=" ; ;an022;bgb
119;Len_Path_String equ 5 ; length of path= string ;AN000;bgb ;an022;bgb
120endif ;an022;bgb
121 ;
122;----------------------------------------
123driveLetter db "X",":",0
124
125
126 ; ; ;
127;----------------------------------------
128
129;Path_SI dw 0
130;Env_DS dw 0
131table dw offset dg:fattbl ;AC000;bgb
132data ends
133
134
135;*****************************************************************************
136; LAST DATA AREA
137; this data area writes over ram, so leave it at the very end of the pgm.
138;*****************************************************************************
139lastseg segment PUBLIC para 'last' ;AC000;bgb
140 assume ds:dg
141fattbl db 0 ;AC000;bgb
142lastseg ends ;AN000;bgb
143
144;
145data segment public para 'DATA' ;AC000;bgb
146;******************************************************************************
147; Public Data
148;******************************************************************************
149 public header, prompted, hardch, the_root, fudge, user_drive, drive, dirchar ;AN000;bgb
150 public userdir, fname_buffer, found, done, driveletter, psp_segment, exitstatus ;AN000;bgb
151 public drvlet, bpb_buffer, transrc, data_start_low, data_start_high, ;AN000;bgb
152 public int_23_old_off, int_23_old_seg, int_24_old_off, int_24_old_seg, append ;AN000;bgb
153 public command_line_buffer, command_line_length, fatal_error, command_line, ;AN000;bgb
154ifdef fsexec ;an022;bgb
155 public fs_string_buffer, fs_string_end, len_fs_string_end, fs_not_fat, ;an022;bgb;AN000;bgb
156 public fat12_string, fat16_string, len_fs_id_string, media_id_buffer, ;an022;bgb;AN000;bgb
157 public exec_block, exec_path, path_string ;AN000;bgb ;an022;bgb
158 public len_path_string ;an022;bgb;AN011;bgb
159 endif ;an022;bgb
160 public dirent, fcb_copy, filcnt, fatcnt, fatnum, fatsiz, firfat, fatptr ;AN000;bgb
161 public secall, target, maxent, firrec, firdir, secsiz, siztmp, filsiz, maxclus ;AN000;bgb
162 public lastfat, table, fattbl, dbcs_vector, dbcs_vector_off, dbcs_vector_seg ;AN000;bgb
163 public read_write_relative, drive_letter_msg ;AN000;bgb ;an022;bgb
164 public drvlet1, rec_num, x_value_lo, x_value_hi, y_value_lo, y_value_hi
165 public bytes_per_sector, exit_sw, exit_sw2, paras_per_fat, secs_per_64k
166 public sec_count, paras_per_64k
167data ends ;put this 1st so that the recmsg works
168 \ No newline at end of file
diff --git a/v4.0/src/CMD/RECOVER/RECDISP.ASM b/v4.0/src/CMD/RECOVER/RECDISP.ASM
new file mode 100644
index 0000000..2a72db2
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECDISP.ASM
@@ -0,0 +1,159 @@
1;
2page ,132 ; ;AN000;bgb
3;;*****************************************************************************
4; Include files
5;*****************************************************************************
6;
7.xlist
8 include pathmac.inc ;an028;bgb
9 include recseg.inc ;AN000;bgb
10 include dossym.inc
11 INCLUDE SYSMSG.INC
12 INCLUDE RECEQU.INC
13 INCLUDE RECMSG.INC
14.list
15;
16;*****************************************************************************
17; external data
18;*****************************************************************************
19data segment public para 'DATA' ;AC000;bgb
20 EXTRN command_line_buffer:byte ;an031;bgb
21 extrn DrvLet1:Byte ;AN000;bgb
22 extrn DrvLet:Byte ;AN000;bgb
23 extrn rec_num:word ;AN000;bgb
24 Extrn Drive_Letter_Msg:Byte ;AN000;BGB
25 extrn fname_buffer:byte ;AN000;BGB
26 EXTRN x_value_lo:WORD ;AN000;bgb ; AC000;SM
27 EXTRN x_value_hi:WORD ;AN000;bgb ; AC000;SM
28 EXTRN y_value_lo:WORD ;AN000;bgb ; AC000;SM
29 EXTRN y_value_hi:WORD ;AN000;bgb ; AC000;SM
30 extrn DriveLetter:Byte
31
32;*****************************************************************************
33; Message Services
34;*****************************************************************************
35.xlist
36MSG_UTILNAME <RECOVER>
37Msg_Services <MSGDATA>
38data ends
39
40
41;
42;***************************************************************************
43; Message Structures
44;***************************************************************************
45;
46code segment PUBLIC para 'CODE'
47Message_Table struc ; ;AN000;
48 ;
49Entry1 dw 0 ; ;AN000;
50Entry2 dw 0 ; ;AN000;
51Entry3 dw 0 ; ;AN000;
52Entry4 dw 0 ; ;AN000;
53Entry5 db 0 ; ;AN000;
54Entry6 db 0 ; ;AN000;
55Entry7 dw 0 ; ;AN000;
56Message_Table ends ; ;AN000;
57
58pathlabl msgret ;an028;bgb
59Msg_Services <NEARmsg>
60Msg_Services <LOADmsg>
61Msg_Services <DISPLAYmsg,CHARmsg,NUMmsg> ;an029;bgb
62pathlabl msgret ;an028;bgb
63Msg_Services <RECOVER.CLA,RECOVER.CL1,RECOVER.CL2,RECOVER.CTL>
64.list
65;
66;*****************************************************************************
67; Public Routines
68;*****************************************************************************
69 Public SysDispMsg
70 Public SysLoadMsg
71 Public Display_Interface
72
73;*****************************************************************************
74;Routine name&gml Display_Interface
75;*****************************************************************************
76;
77;DescriptioN&gml Save all registers, set up registers required for SysDispMsg
78; routine. This information is contained in a message description
79; table pointed to by the DX register. Call SysDispMsg, then
80; restore registers. This routine assumes that the only time an
81; error will be returned is if an extended error message was
82; requested, so it will ignore error returns
83;
84;Called Procedures: Message (macro)
85;
86;Change History&gml Created 4/22/87 MT
87;
88;Input&gml ES&gmlDX = pointer to message description
89;
90;Output&gml None
91;
92;Psuedocode
93;----------
94;
95; Save all registers
96; Setup registers for SysDispMsg from Message Description Tables
97; CALL SysDispMsg
98; Restore registers
99; ret
100;*****************************************************************************
101
102Display_Interface proc ; ;AN000;
103
104 push ds ; ;AN000;
105 push ax ;Save registers ;AN000;
106 push bx ; " " " " ;AN000;
107 push cx ; " " " " ;AN000;
108 push dx ; " " " " ;AN000;
109 push si ; " " " " ;AN000;
110 push di ; " " " " ;AN000;
111 mov di,dx ;Change pointer to table ;AN000;
112 mov dx,DG ;Point to data segment
113 mov ds,dx ;
114 mov ax,[di].Entry1 ;Message number ;AN000;
115 mov bx,[di].Entry2 ;Handle ;AN000;
116 mov si,[di].Entry3 ;Sublist ;AN000;
117 mov cx,[di].Entry4 ;Count ;AN000;
118 mov dh,[di].Entry5 ;Class ;AN000;
119 mov dl,[di].Entry6 ;Function ;AN000;
120 mov di,[di].Entry7 ;Input ;AN000;
121 call SysDispMsg ;Display the message ;AN000;
122 pop di ;Restore registers ;AN000;
123 pop si ; " " " " ;AN000;
124 pop dx ; " " " " ;AN000;
125 pop cx ; " " " " ;AN000;
126 pop bx ; " " " " ;AN000;
127 pop ax ; " " " " ;AN000;
128 pop ds ; ;AN000;
129 ret ;All done ;AN000;
130Display_Interface endp ; ;AN000;
131
132include msgdcl.inc
133
134code ends
135 end
136
137
138;code segment public PARA 'CODE' ;AC000;bgb
139;code ends
140;
141;const segment public para ;AC000;bgb
142;const ends
143;
144;cstack segment stack word 'stack'
145;cstack ends
146;
147;
148;data segment public para 'DATA' ;AC000;bgb
149;data ends
150;
151;dg group code,const,data,cstack
152;
153;code segment public para 'code' ;AC000;bgb
154;code ends
155; assume cs:dg,ds:dg,es:dg,ss:cstack
156;
157;
158;;;;;;;;;;code segment PUBLIC para 'CODE'
159;;;;;;;;;;;;;code ends
diff --git a/v4.0/src/CMD/RECOVER/RECEQU.INC b/v4.0/src/CMD/RECOVER/RECEQU.INC
new file mode 100644
index 0000000..514c956
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECEQU.INC
@@ -0,0 +1,174 @@
1;fsexec equ true
2const segment public para 'const' ;AC000;bgb
3Len_FS_ID_String equ 8 ; length of fat_12 and fat_16 strings ;AN000;bgb
4Command_Line_Length equ 128 ; length of command line area ;AN000;bgb
5Len_FS_String_End equ 8 ; length of rec.exe + 0H ;AN000;bgb
6FALSE EQU 0
7;TRUE EQU -1
8
9bdos equ 21h
10boot equ 20h
11aread equ 25h
12awrite equ 26h
13
14
15;IBMVER EQU false ; not for single drive system ;AC000;bgb
16;KANJI EQU true ; set this to true for assembling jap version ;AC000;bgb
17tab equ 09h
18aread equ 25h
19awrite equ 26h
20fcb equ 5ch
21FCB1 equ 5Ch
22FCB2 equ 6Ch
23FCB_Filename_Length equ 11
24
25NO equ 0 ;AN000;
26YES equ not NO ;AN000;
27
28
29Not_Include equ 0
30Do_Include equ 1
31
32No_Ext_Attrib equ 0 ;AN000;
33No_Entry equ 0
34
35
36FAT12_File_System equ 01h ;AN000;
37FAT16_File_System equ 04h ;AN000;
38New_File_System equ 06h ;AN000;
39
40Bad_Exit equ 0FFh ;Errorlevel = 0FFh ;AN000;
41
42Net_Check equ 1200h ;AN000;
43Assign_Check equ 8000h ;AN000;
44
45DBCS_Lead equ 81h
46DBCS_Blank equ 40h
47DBCS_Vector_Size equ 2
48End_Of_Vector equ 0
49Blank equ " " ;AN000;
50
51Found_Yes equ 1 ;AN000;
52Found_No equ 0 ;AN000;
53
54Asciiz_End equ 0 ;AN000;
55
56Dir_Attribute equ 10h
57Vol_Attribute equ 08h
58
59Dir_Entries_Per_Sector equ 512/32
60
61
62Critical_Error_Fail equ 3
63Write_Protect equ 0
64Drive_Not_Ready equ 2
65
66
67Len_FS_String_Buffer equ 13
68
69;Limits
70BIG_FAT_THRESHOLD equ 4086 ;AN000;
71
72; equates from recinit
73;***********************************************
74Multiplex equ 2Fh ; ;AN000;
75Set_Append_X equ 0B707h ; ;AN000;;
76Append_X equ 0B706h ; ;AN000;;
77Append_X_Set equ 1 ; ;AN000;
78Append_Off equ 0 ; ;AN000;
79Append_ON equ 1 ; ;AN000;
80fcb1 equ 05ch ; ;AN000;bgb
81
82String_Done equ 0
83No_Error equ 0
84rec_error equ 1
85Stderr equ 2
86Len_FS_String_Buffer equ 13
87
88
89
90;-------------------------------------------------------------------------------
91; DATA STRUCTURES
92;-------------------------------------------------------------------------------
93
94Exec_Block_Parms struc
95Segment_Env dw 0
96Offset_Command dw 0
97Segment_Command dw 0
98Offset_FCB1 dw 0
99Segment_FCB1 dw 0
100Offset_FCB2 dw 0
101Segment_FCB2 dw 0
102
103Exec_Block_Parms ends
104
105
106
107;-------------------------------------------------------------------------------
108; media id
109;-------------------------------------------------------------------------------
110Media_ID struc ;AN000;
111Media_ID_Info_Level dw 0 ;AN000;
112Media_ID_Serial_Number dd 0 ;AN000;
113Media_ID_Volume_Label db 11 dup(" ") ;AN000;
114Media_ID_File_System db 8 dup(" ") ;AN000;
115Media_ID ends ;AN000;
116
117;-------------------------------------------------------------------------------
118; device parameters
119;-------------------------------------------------------------------------------
120A_DeviceParameters struc
121
122SpecialFunctions db ?
123DeviceType db ?
124DeviceAttributes dw ?
125NumberOfCylinders dw ?
126MediaType db ?
127BytePerSector dw ?
128SectorsPerCluster db ?
129ReservedSectors dw ?
130NumberOfFATs db ?
131RootEntries dw ?
132TotalSectors dw ?
133MediaDescriptor db ?
134SectorsPerFAT dw ?
135SectorsPerTrack dw ?
136Heads dw ?
137HiddenSectors dd ?
138Ext_Total_Sectors dd ?
139Reserved_Area db 6 dup(?)
140
141A_DeviceParameters ends
142
143
144
145
146;-------------------------------------------------------------------------------
147; relative sector buffer
148;-------------------------------------------------------------------------------
149Relative_Sector_Buffer struc ; ;AN000;
150
151Start_Sector_Low dw ? ;Low word of RBA sector ;AN000;
152Start_Sector_High dw ? ;High word of RBA sector ;AN000;
153Number_Sectors dw ? ;Number of sectors ;AN000;
154Buffer_Offset dw ? ;Address of data buffer ;AN000;
155Buffer_Segment dw ? ; ;AN000;
156
157Relative_Sector_Buffer ends ; ;AN000;
158
159
160;-------------------------------------------------------------------------------
161; xal ????
162;-------------------------------------------------------------------------------
163XAL struc ;AN000;
164
165XAL_Tsize dw ? ;AN000;
166XAL_TCount dw ? ;AN000;
167XAL_LSize dw ? ;AN000;
168XAL_LCount dw ? ;AN000;
169XAL_Data db 512-8 dup(?) ;AN000;
170
171XAL ends ;AN000;
172
173;-------------------------------------------------------------------------------
174const ends
diff --git a/v4.0/src/CMD/RECOVER/RECINIT.ASM b/v4.0/src/CMD/RECOVER/RECINIT.ASM
new file mode 100644
index 0000000..a1f5f84
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECINIT.ASM
@@ -0,0 +1,1028 @@
1 ;AN000;bgb
2page ,132 ;
3TITLE RECINIT.SAL - MS-DOS File/Disk Recovery Utility
4;*****************************************************************************
5;*****************************************************************************
6; Include files
7;*****************************************************************************
8;
9 .xlist
10 include pathmac.inc
11 INCLUDE RECSEG.INC ;AN000;bgb
12 INCLUDE DOSSYM.INC ;AN000;BGB
13INCLUDE SYSCALL.INC ;AN000;BGB
14INCLUDE RECEQU.INC ;AN000;BGB
15INCLUDE RECMACRO.INC ;AN000;BGB
16INCLUDE RECPARSE.INC ;AN000;BGB
17 .list
18
19;
20;*****************************************************************************
21; External Data Declarations
22;*****************************************************************************
23data segment public para 'Data' ;an000;bgb
24 EXTRN movsi:word ;move si pointer here for display of invalid parm ;an031;bgb
25 extrn command_line_buffer:byte ;AN000;bgb
26 extrn ExitStatus:Byte ;AN000;bgb
27 Extrn FATTbl:byte
28 Extrn SubstErr:Byte
29 Extrn NotNetM:Byte
30 Extrn User_Drive:Byte ;AN000;BGB
31 Extrn Baddrv:Byte
32 Extrn Drive_Letter_Msg:Byte ;AN000;BGB
33 Extrn Parse_Error_Msg:Byte
34 extrn fname_buffer:byte ;AN000;BGB
35 extrn PSP_Segment:word ;AN000;bgb
36 extrn fatal_error:byte ;AN000;bgb
37 extrn found:byte ;AN000;bgb
38 extrn done:byte ;AN000;bgb
39 extrn bpb_buffer:byte ;AN000;bgb
40 extrn data_start_low:word ;AN000;bgb
41 extrn data_start_high:word ;AN000;bgb
42 extrn driveletter:byte ;AN000;bgb
43 extrn drive:byte ;AN000;bgb
44 extrn transrc:byte ;AN000;bgb
45 extrn int_23_old_off:word ;AN000;bgb
46 extrn int_23_old_seg:word ;AN000;bgb
47 extrn int_24_old_off:word ;AN000;bgb
48 extrn int_24_old_seg:word ;AN000;bgb
49 extrn append:byte ;AN000;bgb
50ifdef fsexec
51 extrn fat12_string:byte ;AN000;bgb
52 extrn fat16_string:byte ;AN000;bgb
53 extrn media_id_buffer:byte ;AN000;bgb
54 extrn fs_not_fat:byte ;AN000;bgb ;an022;bgb
55 extrn FS_String_Buffer:Byte ;AN011;bgb ;an022;bgb
56 extrn FS_String_end:Byte ;AN011;bgb ;an022;bgb
57endif
58data ends ;an000;bgb
59
60
61code segment public para 'CODE' ;an000;bgb
62 pathlabl recinit
63;*****************************************************************************
64; recinit procedures
65;*****************************************************************************
66public Main_Init, Init_Io, Preload_Messages, Parse_recover
67public Parse_good, Parse_err, Validate_Target_Drive
68public Check_Target_Drive, Check_For_Network, Check_Translate_Drive
69public Hook_interrupts, Clear_Append_X, RECOVER_IFS, Reset_Append_X
70public exitpgm ;an026;bgb
71;*****************************************************************************
72; External Routine Declarations
73;*****************************************************************************
74; Extrn EXEC_FS_Recover:Near ;an022;bgb
75 Extrn SysLoadMsg:Near
76 Extrn SysDispMsg:Near
77 Extrn Main_Routine:Near
78 Extrn INT_23:Near
79 Extrn INT_24:Near
80
81;*****************************************************************************
82;Routine name: MAIN_INIT
83;*****************************************************************************
84;
85;description: Main routine for recover program
86;
87;Called Procedures: get_psp
88; Init_IO
89; Validate_Target_Drive
90; Hook_Interrupts
91; RECOVER_IFS (goes to main-routine)
92;
93;Input: None
94;
95;Output: None
96;
97;Change History: Created 5/8/87 MT
98;
99;Psuedocode
100;----------
101; get info from psp
102; Parse input and load messages (CALL Init_Input_Output)
103; IF no error
104; Check target drive letter (CALL Validate_Target_Drive)
105; IF no error
106; Set up Control Break (CALL Hook_Interrupts)
107; IF no error
108; CALL RECOVER_IFS (goes to main routine)
109; ENDIF
110; ENDIF
111; ENDIF
112; Exit program
113;*****************************************************************************
114procedure Main_Init ;;AN000;
115 xor bp,bp
116 Set_Data_Segment ;Set DS,ES to Data segment ;AN000;bgb
117 call get_psp
118 mov Fatal_Error,No ;Init the error flag ;AN000;
119 call Init_Io ;Setup messages and parse ;AN000;
120 cmp Fatal_Error,Yes ;Error occur? ;AN000;
121; $IF NE ;Nope, keep going ;AN000;
122 JE $$IF1
123 call Validate_Target_Drive ;Check drive letter ;AN000;
124 cmp Fatal_Error,Yes ;Error occur? ;AN000;
125; $IF NE ;Nope, keep going ;AN000;
126 JE $$IF2
127 call Hook_Interrupts ;Set CNTRL -Break hook ;AN000;
128 cmp Fatal_Error,Yes ;Error occur? ;AN000;
129; $IF NE ;Nope, keep going ;AN000;
130 JE $$IF3
131 call RECOVER_IFS ;RECOVER correct file system ;AN000;
132; $ENDIF ; ;AN000;
133$$IF3:
134; $ENDIF ; ;AN000;
135$$IF2:
136; $ENDIF ; ;AN000;
137$$IF1:
138exitpgm: mov al,ExitStatus ;Get Errorlevel ;AN000;
139 DOS_Call Exit ;Exit program ;AN000;
140 int 20h ;If other exit fails ;AN000;
141
142Main_Init endp ; ;AN000;
143
144;*****************************************************************************
145;Routine name: get_psp
146;*****************************************************************************
147;Description: get info from the psp area
148;
149;Called Procedures: get_drive
150;
151;Change History: Created 8/7/87 bgb
152;
153;Input: none
154;
155;Output: psp_segment
156; command_line_buffer
157;
158;Psuedocode
159;----------
160; get addr of psp
161; move command line into data seg
162; get drive number of target
163; get addr of data seg
164; call get_drive
165; ret
166;*****************************************************************************
167Procedure get_psp ;;AN000;
168 DOS_Call GetCurrentPSP ;Get PSP segment address :AN000;bgb
169 mov PSP_Segment,bx ;Save it for later ;AN000;bgb
170; get command line from psp ;AN000;bgb
171 mov cx,PSP_Segment ;point ds to data seg ;AN000;bgb
172 mov ds,cx ; " " " " " ;AN000;bgb
173 assume ds:NOTHING,es:dg ; " " " " " ;AN000;bgb
174 mov si,Command_Line_Parms ;ds:si --> old area in psp ;AN000;bgb
175 LEA di,command_line_buffer ; es:di -> new area in data
176 mov cx,128 ; do for 128 bytes
177 rep movsb ; mov 1 byte until cx=0
178; get the drive number of the target from the psp (0=default, a=1, b=2, c=3) ;AN000;bgb
179 mov bl,ds:[FCB1] ;Get target drive from FCB -74 ;AN000;
180 Set_Data_Segment ;Set DS,ES to Data segment ;AN000;bgb
181 call get_drive
182 ret
183get_psp endp ; ;AN000;
184
185
186;*****************************************************************************
187;Routine name: get_drive
188;*****************************************************************************
189;Description: get drive letter from reg bl
190;
191;Change History: Created 8/7/87 bgb
192;
193;Input: bl = drive num (default=0)
194;
195;Output: driveletter
196; drive_letter_msg
197; user_drive
198;
199;Psuedocode
200;----------
201; IF drive-num = default
202; get default drive number (a=1)
203; convert to letter
204; ELSE
205; convert to letter
206; ENDIF
207; move letter into data areas
208; ret
209;*****************************************************************************
210Procedure get_drive ;;AN000;
211; convert drive number to drive letter
212 cmp bl,0 ;a=1 b=2 c=3 ;Is it default drive? 0=default ;AN000;
213; $IF E ;Yes, turn it into drive letter ;AN000;
214 JNE $$IF7
215; get default drive number
216 DOS_Call Get_Default_Drive ;Get default drive num in al ;AN000;
217 ;a=0, b=1, c=2
218 mov drive,al ; ;AN000;bgb
219; $ELSE ;Not default, A=1 ;AN000;
220 JMP SHORT $$EN7
221$$IF7:
222; bl already contains the correct drive number - save it
223 dec bl ;a=0 b=1 c=2
224 mov drive,bl ; ;AN000;bgb
225 mov al,bl
226; $ENDIF ; 74+40=b4
227$$EN7:
228 add al,"A" ;convert it to letter ;AN000;
229 mov driveletter,al ;set up prompt msg ;AN000;bgb
230 mov Drive_Letter_Msg,al ;Save it in message ;AN000;
231 mov User_Drive,al ;Put it into path strings ; ;
232 ret
233get_drive endp ; ;AN000;
234
235;*****************************************************************************
236;Routine name: Init_Io
237;*****************************************************************************
238;description: Initialize messages, Parse command line if FAT file system
239;
240;Called Procedures: Preload_Messages
241; Parse_Recover
242;
243;Change History: Created 5/10/87 MT
244;
245;Input: PSP command line at 81h and length at 80h
246;
247;Output: FS_Not_FAT = YES/NO
248; Drive_Letter_Msg set up for any future messages that need it
249;
250;Psuedocode
251;----------
252; Load messages (CALL Preload_Messages)
253; IF no fatal error
254; Get file system type (12-bit fat, 16-bit fat, big fat, ifs)
255; IF old-type-diskette, or
256; dos4.00 12-bit fat, or
257; dos4.00 16-bit fat, then
258; Go handle FAT based Recover syntax's (Call Parse_Recover)
259; ELSE
260; FS_Not_FAT = YES
261; ENDIF
262; ENDIF
263; ret
264;*****************************************************************************
265Procedure Init_IO ;;AN000;
266; load the error messages from the system ;an022;bgb
267 call Preload_Messages ;Load up message retriever ;AN000;
268ifdef fsexec ;an022;bgb
269 mov FS_Not_FAT,No ;an022;bgb
270 cmp Fatal_Error,YES ;Quit? ;AN000; ;an022;bgb
271; $IF NE ;Nope, keep going ;AN000; ;an022;bgb
272 JE $$IF10
273; get file system type from ioctl ;an022;bgb
274 mov al,generic_ioctl ;al=0d (get media id) ;AN000;;an030;bgb
275 xor bx,bx ;use default drive ;AN009;b;an022;bgbgb
276 mov ch,Rawio ;8 = disk io ;an030;bgb;an022;bgb
277 mov cl,Get_Media_Id ;66h ;an030;bgb
278 lea dx,Media_ID_Buffer ;Point at buffer ;AN000; ;an022;bgb
279 DOS_Call IOCtl ;Do function call ah=44 ;AN000; ;an022;bgb
280; is it DOS 3.3 or below? ;carry flag means old dos ;an022;bgb
281; $IF C,OR ;Old style diskette, OR ;AN000; ;an022;bgb
282 JC $$LL11
283; is it a new-12 bit fat? ;an022;bgb
284 lea si,FAT12_String ;Check for FAT_12 string ;AN000; ;an022;bgb
285 lea di,Media_ID_Buffer.Media_ID_File_System ; ;AN0;an022;bgb00;
286 mov cx,Len_FS_ID_String ;Length of compare ;AN00;an022;bgb0;
287 repe cmpsb ;Find it? ;AN00;an022;bgb0;
288; $IF E,OR ;Nope, keep going ;AN000; ;an022;bgb
289 JE $$LL11
290; is it a new 16-bit fat? ;an022;bgb
291 lea si,FAT16_String ;Check for FAT_16 string ;AN000; ;an022;bgb
292 lea di,Media_ID_Buffer.Media_ID_File_System ; ;AN0;an022;bgb00;
293 mov cx,Len_FS_ID_String ;Length of compare ;AN00;an022;bgb0;
294 repe cmpsb ;Do compare ;AN00;an022;bgb0;
295; $IF E ; is it new 16-bit fat? ;AN000; ;an022;bgb
296 JNE $$IF11
297$$LL11:
298endif ;an022;bgb
299; file system is fat based, continue (old or new) ;an022;bgb
300 call Parse_Recover ;Yes, go sort out syntax ;an022;bgb
301; ;an022;bgb
302; non-fat based system ;an022;bgb
303ifdef fsexec ;an022;bgb
304; $ELSE ;We got FS other than FAT ;AN000; ;an022;bgb
305 JMP SHORT $$EN11
306$$IF11:
307 mov FS_Not_FAT,Yes ;Indicate exec file system ;AN000; ;an022;bgb
308 mov cx,8 ;an022;bgb;an011;bgb
309 lea si,Media_ID_Buffer.Media_ID_File_System ;get file system;an022;bgb ;an011;bgb
310 lea di,fs_string_buffer ;put it here ;an022;bgb;an011;bgb
311 rep movsb ;an022;bgb;an011;bgb
312 lea di,fs_string_buffer ;point to beginning again ;an022;bgb;an011;bgb
313; $DO COMPLEX ;search th string until eol found ;an022;bgb;an011;bgb
314 JMP SHORT $$SD13
315$$DO13:
316 inc di ;next char ;an022;bgb;an011;bgb
317; $STRTDO ;start loop here ;an022;bgb;an011;bgb
318$$SD13:
319 cmp byte ptr [di],' ' ;end of string ? ;an022;bgb ;an011;bgb
320; $ENDDO E ;end loop when eol found ;an022;bgb;an011;bgb
321 JNE $$DO13
322 lea si,fs_string_end ;get end of string - rec.exe ;an022;bgb;an011;bgb
323 mov cx,8 ; 8 more chars ;an022;bgb;an011;bgb
324 rep movsb ;move it in ;an022;bgb;an011;bgb
325; $ENDIF ; fat based file system ;AN000; ;an022;bgb
326$$EN11:
327; $ENDIF ; no error from msg retreiver ;AN00;an022;bgb0;
328$$IF10:
329endif ;an022;bgb
330 ret ; ;AN000;
331Init_Io endp ; ;AN000;
332
333;*****************************************************************************
334;Routine name: Preload_Messages
335;*****************************************************************************
336;Description: Preload messages using common message retriever routines.
337;
338;Called Procedures: SysLoadMsg
339;
340;Change History: Created 5/1/87 MT
341;
342;Input: Fatal_Error = NO
343;
344;Output: Fatal_Error = YES/NO
345;
346;Psuedocode
347;----------
348; Preload All messages (Call SysLoadMsg)
349; IF error
350; Display SysLoadMsg error message
351; Fatal_Error = YES
352; ENDIF
353; ret
354;*****************************************************************************
355Procedure Preload_Messages ;;AN000; ;
356 call SysLoadMsg ;Preload the messages ;AN000;
357; $IF C ;Error? ;AN000;
358 JNC $$IF18
359 call SysDispMsg ;Display preload msg ;AN000;
360 mov Fatal_Error, YES ;Indicate error exit ;AN000;
361; $ENDIF ; ;AN000;
362$$IF18:
363 ret ; ;AN000;
364
365Preload_Messages endp ; ;AN000;
366
367;*****************************************************************************
368;Routine name: Parse_Command_Line
369;*****************************************************************************
370;Description: Parse the command line. Check for errors, and display error and
371; exit program if found. Use parse error messages except in case
372; of no parameters, which has its own message
373;
374;Called Procedures: Message (macro)
375; SysParse
376; parse_good
377; parse_err
378;
379;Change History: Created 5/1/87 MT
380;
381;Input: Fatal_Error = NO
382;
383;Output: Fatal_Error = YES/NO
384; PARSE-ADDR
385; DRIVELETTER
386; PARSE-ADDR
387;
388;Psuedocode
389;----------
390; set up regs to call sysparse
391;DO UNTIL error=yes or return(ax)=finish(-1)
392; call sysparse
393; IF ax=good return(0)
394; call parse-good
395; ELSE
396; call parse-err
397; ENDIF
398;ENDLOOP
399;ret
400;
401;A. normal proc == 1- ax=good 0
402; 2- ax=done -1
403;B. no parm == 1- ax=error 2
404;
405;C. too many == 1- ax=good 0
406; 2- ax=error 1
407;D. syntax == 1- ax=error 9
408;*****************************************************************************
409Procedure Parse_recover ; ;AN000;bgb
410 push ds ; save ds ;AN000;bgb
411; set up to call sysparse ;AN000;bgb
412 set_data_segment ;ds,es point to data seg
413 LEA si,command_line_buffer ;ds:si -> cmd line
414 LEA di,parms_input_block ;es:di--> parms input block ;AN000;bgb
415 xor cx,cx ;cx = 0 ;AN000;bgb
416 xor dx,dx ;dx = 0 ;AN000;bgb
417 mov done,no
418; call sysparse until error or end of cmd line ;AN000;bgb
419; $DO ;AN000;bgb
420$$DO20:
421 call SysParse ;go parse ;AN000;bgb
422 cmp ax,$p_rc_eol ; -1 end of command line? ;AN000;bgb
423; $LEAVE E ; yes - done ;AN000;bgb
424 JE $$EN20
425 cmp ax,$p_no_error ; good return code ??? (0) ;AN000;bgb
426; $IF E ; yes ;AN000;bgb
427 JNE $$IF22
428 call parse_good ; go get it ;AN000;bgb
429; $ELSE ; ax not= good ;AN000;bgb
430 JMP SHORT $$EN22
431$$IF22:
432 call parse_err ; check for error ;AN000;bgb
433; $ENDIF ; eol ;AN000;bgb
434$$EN22:
435 cmp Fatal_Error,YES ;Can we continue? ;AN000;bgb
436; $LEAVE E ;NO ;AN000;bgb
437 JE $$EN20
438; $ENDDO ; ;AN000;bgb
439 JMP SHORT $$DO20
440$$EN20:
441 pop ds ; ;AN000;bgb
442 ret ; ;AN000;bgb
443 ; ;AN000;bgb
444Parse_recover endp ; ;AN000;bgb
445 ; ;AN000;bgb
446 ;AN000;bgb
447;*****************************************************************************
448;Routine name: parse_good
449;*****************************************************************************
450;
451;Description: when the ax register returned by sysparse indicates and error,
452; this procedure is called. it then determines which error
453; occurred, and calls parse_message to display the msg.
454;
455;Called Procedures: parse_message (macro)
456;
457;Change History: Created 7/23/87 bgb
458;
459;Input:
460;
461;Output: Fatal_Error = YES/NO
462;
463;Psuedocode
464;----------
465;
466; found=yes
467; IF data=drive
468; save drive number and letter
469; ELSE
470; IF data=filespec
471; save filespec
472; ELSE
473; call parse-msg
474; ENDIF
475; ENDIF
476;*****************************************************************************
477;
478Procedure Parse_good ; ;AN000;bgb
479 cmp parse_type,$p_drive ; 6 if data=drive ;AN000;bgb
480; $IF E ; not eol, good syntax, drive entered ;AN000;bgb
481 JNE $$IF27
482 mov bl,byte ptr parse_addr ;AN000;bgb
483 dec bl ;Make drive 0 based ;AN000;bgb
484 mov drive,bl ;AN000;bgb
485 add bl,'A' ;make it character ;AN000;bgb
486 mov driveletter,bl ;save into drive letter ;AN000;bgb
487; $ELSE ; no - filespec entered ;AN000;bgb
488 JMP SHORT $$EN27
489$$IF27:
490 cmp parse_type,$p_file_spec ; 5 if data = filespec ;AN000;bgb
491; $IF E ; was file spec entered ;AN000;bgb
492 JNE $$IF29
493; push si ; save input offset reg ;AN000;bgb
494; push ds ; save input seg reg ;AN000;bgb
495; push cx ; save count ;AN000;bgb
496; push es ; save other seg reg ;AN000;bgb
497; mov cx,ds ;es points to data ;AN000;bgb
498; mov es,cx ;es points to data ;AN000;bgb
499; mov si,word ptr parse_addr ;get offset to filespec ;AN000;bgb
500; mov ds,word ptr parse_addr+2 ;get segment to filespec ;AN000;bgb
501; mov cx,128 ; mov 128 bytes ;AN000;bgb
502; rep movs es:fname_buffer,ds:[si] ;move it ;AN000;bgb
503; pop es ; save other seg reg ;AN000;bgb
504; pop cx ; save other seg reg ;AN000;bgb
505; pop ds ; save other seg reg ;AN000;bgb
506; pop si ; save other seg reg ;AN000;bgb
507; $ELSE ; no, no drive or filespec ;AN000;bgb
508 JMP SHORT $$EN29
509$$IF29:
510 mov ax,$p_syntax ;tell user bad syntax ;AN000;bgb
511 parse_message ;display msg ;AN000;bgb
512 mov Fatal_Error,YES ;Indicate death! ;AN000;bgb
513; $ENDIF ; was drive entered ? ;AN000;bgb
514$$EN29:
515; $ENDIF ;if data=drive ;AN000;bgb
516$$EN27:
517 ret ; ;aN000;bgb
518 ;AN000;bgb
519parse_good endp ; ;AN000;bgb
520
521 ;AN000;bgb
522;*****************************************************************************
523;Routine name: parse_err
524;*****************************************************************************
525;
526;Description: when the ax register returned by sysparse indicates and error,
527; this procedure is called. it then determines which error
528; occurred, and calls parse_message to display the msg.
529;
530;Called Procedures: parse_message (macro)
531;
532;Change History: Created 7/23/87 bgb
533;
534;Input:
535;
536;Output: Fatal_Error = YES/NO
537;
538;Psuedocode
539;----------
540;
541; IF ax=done (end of cmd line?) -1
542; IF found=no (eol, but no parameters listed)
543; call parse-msg
544; ENDIF
545; ELSE (error other than eol)
546; call parse-msg
547; ENDIF
548;*****************************************************************************
549;
550Procedure Parse_err ; ;AN000;bgb
551 mov Fatal_Error,YES ;Indicate death! ;AN000;bgb ;AN000;bgb
552 cmp ax,$P_Op_Missing ; 2 = no parameters ? ;AN000;bgb
553; $IF E ; ;AN000;bgb
554 JNE $$IF33
555 message baddrv ; yes (invalid drive or filename) ;AN000;bgb
556; $ELSE ;AN000;bgb
557 JMP SHORT $$EN33
558$$IF33:
559 mov byte ptr [si],00 ;zero terminate display string ;an031;bgb
560 dec si ;look at previous char ;an031;bgb
561nextsi:
562public nextsi
563 dec si ;look at previous char ;an031;bgb
564 cmp byte ptr [si],' ' ;find parm separator ;an031;bgb
565 jnz nextsi ;loop until begin of parm found
566 mov movsi,si ;mov si into display parms ;an031;bgb
567 parse_message ;no- display parse message ;AN000;bgb ;AN000;bgb
568; $ENDIF ;AN000;bgb
569$$EN33:
570 ret ; ;AN000;bgb
571parse_err endp ; ;AN000;bgb
572
573
574;*****************************************************************************
575;Routine name: Validate_Target_Drive
576;*****************************************************************************
577;
578;Description: Control routine for validating the specified format target drive.
579; If any of the called routines find an error, they will print
580; message and terminate program, without returning to this routine
581;
582;Called Procedures: Check_Target_Drive
583; Check_For_Network
584; Check_Translate_Drive
585;
586;Change History: Created 5/1/87 MT
587;
588;Input: Fatal_Error = NO
589;
590;Output: Fatal_Error = YES/NO
591;
592;Psuedocode
593;----------
594;
595; CALL Check_Target_Drive
596; IF !Fatal_Error
597; CALL Check_For_Network
598; IF !Fatal_Error
599; CALL Check_Translate_Drive
600; ENDIF
601; ENDIF
602; ret
603;*****************************************************************************
604;
605Procedure Validate_Target_Drive ; ;AN000;
606 call Check_For_Network ;See if Network drive letter ;AN000;
607 cmp Fatal_Error,YES ;Can we continue? ;AN000;
608; $IF NE ;Yep ;AN000;
609 JE $$IF36
610 call Check_Translate_Drive ;See if Subst, Assigned ;AN000;
611 call Check_Target_Drive ;See if valid drive letter ;AN000;
612; $ENDIF ;- Fatal_Error passed back ;AN000;
613$$IF36:
614 ret ; ;AN000;
615
616Validate_Target_Drive endp ; ;AN000;
617
618;*****************************************************************************
619;Routine name: Check_Target_Drive
620;*****************************************************************************
621;
622;Description: Check to see if valid DOS drive by checking if drive is
623; removable. If error, the drive is invalid. Save default
624; drive info. Also get target drive BPB information, and compute
625; the start of the data area
626;
627;Called Procedures: Message (macro)
628;
629;Change History: Created 5/1/87 MT
630;
631;Input: Fatal_Error = NO
632;
633;Output: Fatal_Error = YES/NO
634; User_Drive = default drive
635;
636;Psuedocode
637;----------
638;
639; Get default drive
640; See if drive LOCAL (INT 21h, AX=4409h IOCtl)
641; IF error - drive invalid
642; Display Invalid drive message
643; Fatal_Error= YES
644; ENDIF
645; Get BPB of target drive (Generic IOCtl Get Device parameters)
646; Compute start of data area
647; ret
648;*****************************************************************************
649;
650Procedure Check_Target_Drive ; ;AN000;
651 mov al,0Dh ;Get BPB information ;AN000;
652 mov cx,0860h ; " " " " ;AN000;
653;;;;;;;;mov bl,byte ptr parse_addr ; " " " " ;AN000;
654 mov bl,drive ;drive number ;A=0,B=1 ;AN000;bgb
655 inc bl ;a=1 ;AN000;bgb
656 lea dx,BPB_Buffer ; " " " " ;AN000;
657 DOS_Call IOCtl ; " " " " ;AN000;
658 xor cx,cx ;Find # sectors used by FAT's ;AN000;
659 mov cl,BPB_Buffer.NumberOfFATs ; " " " " ;AN000;
660 mov ax,BPB_Buffer.SectorsPerFAT ; " " " " ;AN000;
661 mul cx ; " " " " ;AN000;
662 push dx ;Save results ;AN000;
663 push ax ; " " ;AN000;
664 mov ax,BPB_Buffer.RootEntries ;Find number of sectors in root ;AN000;
665 mov cl,Dir_Entries_Per_Sector ; by dividing RootEntries ;AN000;
666 div cl ; by (512/32) ;AN000;
667 pop bx ;Get low sectors per FAT back ;AN000;
668 pop dx ;Get high part ;AN000;
669 add ax,bx ;Add to get FAT+Dir sectors ;AN000;
670 adc dx,bp ;zero ;High part ;AN000;
671 add ax,ReservedSectors ;Add in Boot record sectors ;AN000;
672 adc dx,bp ;zero ;to get start of data (DX:AX) ;AN000;
673 mov Data_Start_Low,ax ;Save it ;AN000;
674 mov Data_Start_High,dx ; ;AN000;
675 ret ;And we're outa here ;AN000;
676Check_Target_Drive endp ; ;AN000;
677
678;*****************************************************************************
679;Routine name: Check_For_Network
680;*****************************************************************************
681;
682;Description: See if target drive isn't local, or if it is a shared drive. If
683; so, exit with error message. The IOCtl call is not checked for
684; an error because it is called previously in another routine, and
685; invalid drive is the only error it can generate. That condition
686; would not get this far
687;
688;Called Procedures: Message (macro)
689;
690;Change History: Created 5/1/87 MT
691;
692;Input: Drive
693; Fatal_Error = NO
694;
695;Output: Fatal_Error = YES/NO
696;
697;Psuedocode
698;----------
699; See if drive is local (INT 21h, AX=4409 IOCtl)
700; IF not local
701; Display network message
702; Fatal_ERROR = YES
703; ELSE
704; IF 8000h bit set on return
705; Display assign message
706; Fatal_Error = YES
707; ENDIF
708; ENDIF
709; ret
710;*****************************************************************************
711;
712Procedure Check_For_Network ; ;AN000;
713; is device local? int 21, ah=44, al=9
714 mov bl,drive ;drive number ;A=0,B=1 ;AN000;bgb
715 inc bl ;drive number ;A=1,B=2 for IOCtl call;AN000;bgb
716 mov al,09h ;See if drive is local ;AC000;bgb
717 DOS_Call IOCtl ;-this will fail if bad drive ;AC000;
718; $IF C ;CarrY means invalid drive ;AC000;
719 JNC $$IF38
720 Message BadDrv ;Print message ;AC000;
721 mov Fatal_Error,Yes ;Indicate error ;AN000;
722; $ELSE
723 JMP SHORT $$EN38
724$$IF38:
725 test dx,Net_Check ;if (x & 1200H)(redir or shared); ;
726; $IF NZ ;Found a net drive ;AC000;
727 JZ $$IF40
728 Message NotNetM ;Tell 'em ;AC000;
729 mov Fatal_Error,Yes ;Indicate bad stuff ;AN000;
730; $ELSE ;Local drive, now check assign ;AN000;
731 JMP SHORT $$EN40
732$$IF40:
733 test dx,Assign_Check ;8000h bit is bad news ; ;
734; $IF NZ ;Found it ;AC000;
735 JZ $$IF42
736 Message SubstErr ;Tell error ;AC000;
737 mov Fatal_Error,Yes ;Indicate bad stuff ;AN000;
738; $ENDIF ; ;AN000;
739$$IF42:
740; $ENDIF ; ;AN000;
741$$EN40:
742; $ENDIF ; ;AN000;
743$$EN38:
744 ret ; ;AN000;
745
746Check_For_Network endp ; ;AN000;
747
748;*****************************************************************************
749;Routine name: Check_Translate_Drive
750;*****************************************************************************
751;
752;Description: Do a name translate call on the drive letter to see if it is
753; assigned by SUBST or ASSIGN
754;
755;Called Procedures: Message (macro)
756;
757;Change History: Created 5/1/87 MT
758;
759;Input: Drive_Letter_Msg has drive string
760; Fatal_Error = NO
761;
762;Output: Fatal_Error = YES/NO
763;
764;Psuedocode
765;----------
766; Put drive letter in ASCIIZ string "d:\",0
767; Do name translate call (INT 21)
768; IF drive not same
769; Display assigned message
770; Fatal_Error = YES
771; ENDIF
772; ret
773;*****************************************************************************
774;
775Procedure Check_Translate_Drive ; ;AN000;
776 mov al,Drive_Letter_Msg ;Get target drive letter into ;AN000;
777 mov TranSrc,al ; "d:\",0 string ;AN000;
778 lea si,TranSrc ;Point to translate string ;AN000;
779 push ds ;Set ES=DS (Data segment) ; ;
780 pop es ; " " " " ; ;
781 lea di,FatTbl ;Point at output buffer ; ;
782 DOS_Call xNameTrans ;Get real path ;AC000;
783; $IF NC ;an017;bgb
784 JC $$IF46
785 mov bl,byte ptr [TranSrc] ;Get drive letter from path ; ;
786 cmp bl,byte ptr [Fattbl] ;Did drive letter change? ; ;
787; $IF NE ;If not the same, it be bad ;AC000;
788 JE $$IF47
789 Message SubstErr ;Tell user ;AC000;
790 mov Fatal_Error,Yes ;Setup error flag ;AN000;
791; $ENDIF ; ;AN000;
792$$IF47:
793; $ELSE ;an017;bgb
794 JMP SHORT $$EN46
795$$IF46:
796 mov Fatal_Error,Yes ;Setup error flag ;AN000; ;an017;bgb
797 mov bx,1 ;an017;bgb
798 mov cx,bp ;zero ;an017;bgb
799 mov dx,0100h ;an017;bgb
800 call sysdispmsg ;an017;bgb
801; $ENDIF ; ;AN000; ;an017;bgb
802$$EN46:
803 ret ; ;AN000;
804
805Check_Translate_Drive endp ; ;AN000;
806
807;*****************************************************************************
808;Routine name: Hook_Interrupts
809;*****************************************************************************
810;
811;Description: Change the interrupt handler for INT 13h to point to the
812; ControlC_Handler routine
813;
814;Called Procedures: None
815;
816;Change History: Created 4/21/87 MT
817;
818;Input: None
819;
820;Output: None
821;
822;Psuedocode
823;----------
824;
825; Point at ControlC_Handler routine
826; Set interrupt handler (INT 21h, AX=2523h)
827; ret
828;*****************************************************************************
829;
830 Procedure Hook_Interrupts ; ;AN000;
831 mov al,23h
832 DOS_Call Get_Interrupt_Vector ;Get the INT 23h handler ;AC000;
833 mov word ptr INT_23_Old_Off,bx ;
834 mov bx,es ; ;AN000;
835 mov word ptr INT_23_Old_Seg,bx ; ;AN000;
836 mov al,23h ;Specify CNTRL handler ; ;
837 lea dx, INT_23 ;Point at it ; ;
838 push ds ;Save data seg ; ;
839 push cs ;Point to code segment ; ;
840 pop ds ; ; ;
841 DOS_Call Set_Interrupt_Vector ;Set the INT 23h handler ;AC000;
842 pop ds ;Get Data degment back ; ;
843 mov al,24h ;
844 DOS_Call Get_Interrupt_Vector ;Get the INT 24h handler ;AC000;
845 mov word ptr INT_24_Old_Off,bx ;Save it
846 mov bx,es ; ;AN000;
847 mov word ptr INT_24_Old_Seg,bx ;
848 mov al,24h ;Specify handler ; ;
849 lea dx, INT_24 ;Point at it ; ;
850 push ds ;Save data seg ; ;
851 push cs ;Point to code segment ; ;
852 pop ds ; ; ;
853 DOS_Call Set_Interrupt_Vector ;Set the INT 23h handler ;AC000;
854 pop ds ;Get Data degment back ; ;
855 ret ; ;AN000;
856
857 Hook_Interrupts endp ; ;AN000;
858
859;*****************************************************************************
860;Routine name: Hook_CNTRL_C
861;*****************************************************************************
862;
863;Description: Change the interrupt handler for INT 13h to point to the
864; ControlC_Handler routine
865;
866;Called Procedures: None
867;
868;Change History: Created 4/21/87 MT
869;
870;Input: None
871;
872;Output: None
873;
874;Psuedocode
875;----------
876;
877; Point at ControlC_Handler routine
878; Set interrupt handler (INT 21h, AX=2523h)
879; ret
880;*****************************************************************************
881;
882;rocedure Hook_CNTRL_C ; ;AN000;
883; mov al,23H ;Specify CNTRL handler ; ;
884; mov dx, offset ControlC_Handler ;Point at it ; ;
885; push ds ;Save data seg ; ;
886; push cs ;Point to code segment ; ;
887; pop ds ; ; ;
888; DOS_Call Set_Interrupt_Vector ;Set the INT 23h handler ;AC000;
889; pop ds ;Get Data degment back ; ;
890; ret ; ;AN000;
891;ook_CNTRL_C endp ; ;AN000;
892;
893;ontrolC_Handler:
894; set_data_segment
895;;;;;;; Message msgInterrupt ; ;AC000;
896;;;;;;;;mov ExitStatus, ExitCtrlC
897; jmp ExitPgm
898;*****************************************************************************
899;Routine name: Clear_Append_X
900;*****************************************************************************
901;
902;Description: Determine if Append /XA is turned on thru INT 2Fh, and shut
903; off for life of RECOVER if it is.
904;
905;Called Procedures: None
906;
907;
908;Change History: Created 5/13/87 MT
909;
910;Input: None
911;
912;Output: APPEND = YES/NO
913;
914;Psuedocode
915;----------
916;
917; Append = NO
918; See if APPEND /X is present (INT 2Fh, AX=0B706h)
919; IF present
920; Turn append /X off (INT 2Fh, AX=B707h, BX = 0)
921; Append = YES
922; ENDIF
923; ret
924;*****************************************************************************
925;
926Procedure Clear_Append_X ; ;AN000;
927 mov Append,NO ;Init the Append /X flag ;AN000;
928 mov ax,Append_X ;Is Append /X there? ;AN000;
929 int Multiplex ; " " " " ;AN000;
930 cmp bx,Append_X_Set ;Was it turned on? ;AN000;
931; $IF E ;Yep ;AN000;
932 JNE $$IF51
933 mov Append,YES ;Indicate that it was on ;AN000;
934 mov ax,Set_Append_X ;Turn Append /X off ;AN000;
935 xor bx,bx ;Append_Off ; " " " " ;AN000;
936 int Multiplex ; " " " " ;AN000;
937; $ENDIF ; ;AN000;
938$$IF51:
939 ret ; ;AN000;
940
941Clear_Append_X endp ; ;AN000;
942
943
944;*****************************************************************************
945;Routine name: RECOVER_IFS
946;*****************************************************************************
947;
948;description:
949;
950;Called Procedures: Main_Routine
951; EXEC_FS_RECOVER
952;
953;Change History: Created 5/8/87 MT
954;
955;Input: FS_Not_FAT = Yes/No
956;
957;Output: None
958;
959;Psuedocode
960;----------
961;
962; IF File system other than FAT
963; Go call file system specific RECOVER (CALL EXEC_FS_RECOVER)
964; ELSE
965; Do FAT based RECOVER (CALL Main_Routine)
966; ENDIF
967; ret
968;*****************************************************************************
969;
970Procedure RECOVER_IFS ; ;AN000;
971ifdef fsexec ;an022;bgb
972; cmp FS_Not_Fat,YES ;Is the target FS a FAT? ;AN000; ;an022;bgb
973; $IF E ;No, so need to exec the ;AN000; ;an022;bgb
974; call EXEC_FS_RECOVER ; file system specific prog. ;AN000; ;an022;bgb
975; $ELSE ;It's a FAT ;AN000; ;an022;bgb
976endif ;an022;bgb
977 call clear_append_x ;BGB
978 call Main_Routine ;Use canned code! ;AN000;
979 call reset_append_x ;BGB
980ifdef fsexec ;an022;bgb
981; $ENDIF ; ;AN000; ;an022;bgb
982endif ;an022;bgb
983 ret ; ;AN000;
984
985RECOVER_IFS endp ; ;AN000;
986
987;*****************************************************************************
988;Routine name: Reset_Append_X
989;*****************************************************************************
990;
991;description: If APPEND /XA was on originally, turn it back on
992;
993;Called Procedures: None
994;
995;
996;Change History: Created 5/13/87 MT
997;
998;Input: None
999;
1000;Output: APPEND = YES/NO
1001;
1002;Psuedocode
1003;----------
1004;
1005; IF APPEND = YES
1006; Turn append /X on (INT 2Fh, AX=B707h, BX = 1)
1007; ENDIF
1008; ret
1009;*****************************************************************************
1010;
1011Procedure Reset_Append_X ; ;AN000;
1012 cmp Append,Yes ;Was Append /X on to start with?;AN000;
1013; $IF E ;Yep ;AN000;
1014 JNE $$IF53
1015 mov ax,Set_Append_X ;Turn Append /X off ;AN000;
1016 mov bx,Append_On ; " " " " ;AN000;
1017 int Multiplex ; " " " " ;AN000;
1018; $ENDIF ; ;AN000;
1019$$IF53:
1020 ret ; ;AN000;
1021
1022Reset_Append_X endp ; ;AN000;
1023
1024 pathlabl recinit
1025code ends
1026 end main_init ;AC000;bgb
1027
1028 \ No newline at end of file
diff --git a/v4.0/src/CMD/RECOVER/RECMACRO.INC b/v4.0/src/CMD/RECOVER/RECMACRO.INC
new file mode 100644
index 0000000..e2933ed
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECMACRO.INC
@@ -0,0 +1,95 @@
1;
2;******************************************************************************
3; Message Macro Definitions
4;******************************************************************************
5;
6
7 EXTRN Display_Interface:near
8
9
10;-----------------------------------------------------------------------------
11
12Message macro Message_Name ; ;AN000;
13 ;
14 mov dx,offset dg:Message_Name ; ;AN000;
15 call Display_Interface ; ;AN000;
16 endm ; ;AN000;
17
18;-----------------------------------------------------------------------------
19
20Parse_Message macro ; ;AN000;
21
22 ;
23 push ds ; ;AN000;bgb
24 mov dx,dg ; ;AN000;bgb
25 mov ds,dx ; ;AN000;bgb
26 mov word ptr Parse_Error_Msg,ax ; ;AN000;
27 mov dx,offset dg:Parse_Error_Msg ; ;AN000;
28 call Display_Interface ; ;AN000;
29 pop ds ; ;AN000;bgb
30 endm ; ;AN000;
31
32;-----------------------------------------------------------------------------
33
34Extended_Message macro ; ;AN000;
35 ;
36
37 push ds ; ;AN000;bgb
38 mov dx,dg ; ;AN000;bgb
39 mov ds,dx ; ;AN000;bgb
40 mov word ptr Ext_Error_Msg,ax ; ;AN000;
41 mov dx,offset dg:Ext_Error_Msg ; ;AN000;
42 call Display_Interface ; ;AN000;
43 pop ds ; ;AN000;bgb
44 endm ; ;AN000;
45
46;
47;*****************************************************************************
48; General Macro's
49;*****************************************************************************
50;
51
52Procedure macro Proc_Name ; ;AN000;
53 ;
54Public Proc_Name ; ;AN000;
55Proc_Name proc ; ;AN000;
56 ;
57 endm ; ;AN000;
58;-----------------------------------------------------------------------------
59
60DOS_Call macro Function ; ;AN000;
61 ;
62 mov ah,Function ; ;AN000;
63 int 21h ; ;AN000;
64 ;
65 endm ; ;AN000;
66;-----------------------------------------------------------------------------
67
68Popff macro
69
70 jmp $+3
71 iret
72 push cs
73 call $-2
74
75 endm
76
77
78;-----------------------------------------------------------------------------
79
80Set_Data_Segment macro
81
82 push ax
83 mov ax,dg ;Point to data segment
84 mov ds,ax ;
85assume ds:dg,es:dg
86 push ds
87 pop es
88 pop ax
89
90
91 endm
92
93
94
95 \ No newline at end of file
diff --git a/v4.0/src/CMD/RECOVER/RECMSG.INC b/v4.0/src/CMD/RECOVER/RECMSG.INC
new file mode 100644
index 0000000..ff44206
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECMSG.INC
@@ -0,0 +1,307 @@
1data segment PUBLIC para 'DATA' ; AN000;bgb
2;
3;*****************************************************************************
4; Macro's
5;*****************************************************************************
6Define_Msg macro Message_Name ; ;AN000;
7 ;
8Create_Msg Message_Name,Message_Number,Handle,Sublist,Count,Class,Function,Input;AN000;
9 ;
10 endm ; ;AN000;
11
12;-----------------------------------------------------------------------------
13
14Create_Msg macro Parm1,Parm2,Parm3,Parm4,Parm5,Parm6,Parm7,Parm8; ;AN000;
15
16Public Parm1
17Parm1 label word ; ;AN000;
18 dw Parm2 ; ;AN000;
19 dw Parm3 ; ;AN000;
20 dw Parm4 ; ;AN000;
21 dw Parm5 ; ;AN000;
22 db Parm6 ; ;AN000;
23 db Parm7 ; ;AN000;
24 dw Parm8 ; ;AN000;
25 endm ; ;AN000;
26
27;
28;*****************************************************************************
29; Message Retriever equates
30;*****************************************************************************
31
32Format_Msg equ 'C'
33
34N_A equ 0
35Sublist_Length equ 11
36None equ 0
37
38Blank equ " "
39No_Function equ 0
40No_Replace equ 0
41
42Msg_Ser_Class equ 0
43Ext_Err_Class equ 1
44Parse_Err_Class equ 2
45Utility_Msg_Class equ 0FFh
46
47Reserved equ 0
48
49;
50;*****************************************************************************
51; Message Sublist Tables
52;*****************************************************************************
53;
54;The following control blocks are used for messages with
55;replaceable paramters. These control blocks are used by the
56;SysDispMsg routine.
57;
58
59;--------------------------- ;
60Sublist_opnerr label byte ; AN000;SM
61 ;
62 db Sublist_Length ; AN000;SM
63 db Reserved ; AN000;SM
64 dw dg:fname_buffer ; AN000;bgb
65 dw Dg ; AN000;SM
66 db 0 ; AN000;SM
67 db Left_Align+Char_Field_ASCIIZ ; AN000;SM
68 db 14 ; AN000;SM
69 db 1 ; AN000;SM
70 db Blank ; AN000;SM
71;--------------------------- ;
72Sublist_Baddrv label byte ; AN000;SM
73 ;
74 db Sublist_Length ; AN000;SM
75 db Reserved ; AN000;SM
76 dw dg:Drive_Letter_Msg ; AN000;bgb
77 dw Dg ; AN000;SM
78 db 0 ; AN000;SM
79 db Left_Align+Char_Field_ASCIIZ ; AN000;SM
80 db 4 ; AN000;SM
81 db 4 ; AN000;SM
82 db Blank ; AN000;SM
83;--------------------------- ;
84ifdef fsexec ;an022;bgb
85Sublist_msg_EXECFailure label byte ; AN000;SM ;an022;bgb
86 db Sublist_Length ; AN000;SM ;an022;bgb
87 db Reserved ; AN000;SM ;an022;bgb
88 dw dg:Drive_Letter_Msg ; AN000;bgb ;an022;bgb
89 dw Dg ; AN000;SM ;an022;bgb
90 db 1 ; AN000;SM ;an022;bgb
91 db Left_Align+Char_Field_ASCIIZ ; AN000;SM ;an022;bgb
92 db 2 ; AN000;SM ;an022;bgb
93 db 2 ; AN000;SM ;an022;bgb
94 db Blank ; AN000;SM ;an022;bgb
95endif ;an022;bgb
96;--------------------------- ;
97Sublist_msg_recmsg label byte ; AN000;SM
98 ;
99 db Sublist_Length ; AN000;SM
100 db Reserved ; AN000;SM
101 dw dg:rec_num ; AN000;bgb
102 dw Dg ; AN000;SM
103 db 1 ; AN000;SM
104 db Left_Align+Unsgn_Bin_Word ; AN000;SM
105 db 5 ; AN000;SM
106 db 1 ; AN000;SM
107 db Blank ; AN000;SM
108;--------------------------- ;
109Sublist_msg_ofmsg label byte ; AN000;SM
110 ;
111 db Sublist_Length ; AN000;SM
112 db Reserved ; AN000;SM
113 dw dg:x_value_lo ; AN000;bgb
114 dw Dg ; AN000;SM
115 db 1 ; AN000;SM
116 db Left_Align+Unsgn_Bin_DWord ; AN000;SM
117 db 10 ; AN000;SM
118 db 1 ; AN000;SM
119 db Blank ; AN000;SM
120 db Sublist_Length ; AN000;bgb
121 db Reserved ; AN000;SM
122 dw y_value_lo ; AN000;SM
123 dw Dg ; AN000;SM
124 db 2 ; AN000;SM
125 db Left_Align+Unsgn_Bin_DWord ; AN000;SM
126 db 10 ; AN000;SM
127 db 1 ; AN000;SM
128 db Blank ; AN000;SM
129;-----------------------------------------------------------------------
130Drive_sublist label byte ;AN000;bgb
131
132 db 11 ; sublist size ;AN000;bgb
133 db 0 ;reserved ;AN000;bgb
134 dw dg:driveletter ;offset of data ;AN000;bgb
135 dw dg ;seg of data ;AN000;bgb
136 db 1 ; 1st replaceable parm ;AN000;bgb
137 db char_field_asciiz ; type = char ;AN000;bgb
138 db 2 ; max field width ;AN000;bgb
139 db 2 ; min field width ;AN000;bgb
140 db ' ' ; pad char (unused) ;AN000;bgb
141;--------------------------- ; ;an031;bgb
142Sublist_msg_parserr label dword ; ;an031;bgb
143 ;an031;bgb
144 db Sublist_Length ;11 ;an031;bgb
145 db Reserved ;0 ;an031;bgb
146public movsi
147movsi dw dg:command_line_buffer ;off ;an031;bgb
148 dw dg ;seg ;an031;bgb
149 db 0 ;USE PERCENT ZERO ;an031;bgb
150 db Left_Align+Char_Field_ASCIIZ ;type of data ;an031;bgb
151 db 128 ;max width ;an031;bgb
152 db 1 ;min width ;an031;bgb
153 db Blank ;pad char ;an031;bgb
154;--------------------------- ; ;an031;bgb
155; ;an000;bgb
156
157
158
159;
160;*****************************************************************************
161; Message Description Tables
162;*****************************************************************************
163;
164
165;---------------------- ;
166Message_Number = 2 ; AN000;SM
167Handle = STDERR ; AN000;SM
168Sublist = Sublist_Opnerr ; AN000;SM
169Count = N_A ; AN000;SM
170Class = EXT_ERR_CLASS ; AN000;SM
171Function = NO_INPUT ; AN000;SM
172Input = N_A ; AN000;SM
173 Define_Msg opnerr ; AN000;SM File not found - xxxxxx
174;---------------------- ;
175Message_Number = 3 ; AN000;SM
176Handle = STDERR ; AN000;SM
177Sublist = None ; AN000;SM
178Count = N_A ; AN000;SM
179Class = Utility_Msg_Class ; AN000;SM
180Function = NO_INPUT ; AN000;SM
181Input = N_A ; AN000;SM
182 Define_Msg Substerr ; AN000;SM Can not recover SUBST or ASSIGNED drive
183;---------------------- ;
184Message_Number = 4 ; AN000;SM
185Handle = STDERR ; AN000;SM
186Sublist = sublist_baddrv ; AN000;SM
187Count = N_A ; AN000;SM
188Class = UTILITY_MSG_CLASS ; AN000;SM
189Function = NO_INPUT ; AN000;SM
190Input = N_A ; AN000;SM
191 Define_Msg baddrv ; AN000;SM Invalid drive or file name ;AN000;
192;---------------------- ;
193Message_Number = 5 ; AN000;SM
194Handle = STDERR ; AN000;SM
195Sublist = None ; AN000;SM
196Count = N_A ; AN000;SM
197Class = UTILITY_MSG_CLASS ; AN000;SM
198Function = NO_INPUT ; AN000;SM
199Input = N_A ; AN000;SM
200 Define_Msg dirmsg ; AN000;SM Warning - directory full ;AN000;
201;---------------------- ;
202Message_Number = 6 ; AN000;SM
203Handle = STDERR ; AN000;SM
204Sublist = None ; AN000;SM
205Count = N_A ; AN000;SM
206Class = UTILITY_MSG_CLASS ; AN000;SM
207Function = NO_INPUT ; AN000;SM
208Input = N_A ; AN000;SM
209 Define_Msg NotNetM ; AN000;SM Cannot recover a Network drive ;AN000;
210;---------------------- ;
211ifdef fsexec ;an022;bgb
212 Message_Number = 7 ; ;an022;bgb
213 Handle = STDERR ; ;an022;bgb
214 Sublist = Sublist_msg_EXECFailure ; ;an022;bgb
215 Count = 1 ; ;an022;bgb
216 Class = UTILITY_MSG_CLASS ; ;an022;bgb
217 Function = NO_INPUT ; ;an022;bgb
218 Input = N_A ; ;an022;bgb
219 Define_Msg MsgEXECFailure ;RECOVER not avail. on drive %1 ;AN022;bgb
220endif ;an022;bgb
221;---------------------- ;
222Message_Number = 8 ; AN000;SM
223Handle = STDout ; AN007;bgb
224Sublist = Sublist_msg_recmsg ; AN000;SM
225Count = 1 ; AN000;SM
226Class = UTILITY_MSG_CLASS ; AN000;SM
227Function = NO_INPUT ; AN000;SM
228Input = N_A ; AN000;SM
229 Define_Msg recmsg ; AN000;SM %1 file(s) recovered ;AN000;
230;---------------------- ;
231Message_Number = 9 ; AN000;SM
232Handle = STDout ; AN007;bgb
233Sublist = Sublist_msg_ofmsg ; AN000;SM
234Count = 2 ; AN000;SM
235Class = UTILITY_MSG_CLASS ; AN000;SM
236Function = NO_INPUT ; AN000;SM
237Input = N_A ; AN000;SM
238 Define_Msg ofmsg_ptr ; AN000;SM %1 of %2 bytes recovered ;AN000;
239;---------------------- ;
240Message_Number = 10 ; AN000;bgb
241Handle = STDout ; AN007;bgb
242Sublist = drive_sublist ; AN000;bgb
243Count = 1 ; AN000;SM
244Class = UTILITY_MSG_CLASS ; AN000;SM
245Function = NO_INPUT ; AN000;SM
246Input = N_A ; AN000;SM
247 Define_Msg askmsg ; AN000;SM Press any key... ;AN000;
248;---------------------- ;
249Message_Number = 11 ; AN000;SM
250Handle = STDERR ; AN000;SM
251Sublist = None ; AN000;SM
252Count = N_A ; AN000;SM
253Class = Utility_Msg_Class ; AN000;SM
254Function = NO_INPUT ; AN000;SM
255Input = N_A ; AN000;SM
256 Define_Msg FATerrRead ; AN000;SM Can not read File allocation table(s)
257;---------------------- ;
258Message_Number = 12 ; AN000;SM
259Handle = STDERR ; AN000;SM
260Sublist = None ; AN000;SM
261Count = N_A ; AN000;SM
262Class = Utility_Msg_Class ; AN000;SM
263Function = NO_INPUT ; AN000;SM
264Input = N_A ; AN000;SM
265 Define_Msg FATerrWrite ; AN000;SM Can not write file allocation table(s)
266;---------------------- ;
267Message_Number = 13 ; AN000;MT
268Handle = STDout ; AN000;MT
269Sublist = None ; AN000;MT
270Count = N_A ; AN000;MT
271Class = Utility_Msg_Class ; AN000;MT
272Function = NO_INPUT ; AN000;MT
273Input = N_A ; AN000;MT
274 Define_Msg CRLF_Ptr ; AN000;MT CR,LF
275;--------------------------- ;
276Message_Number = 0 ; ;AN000;
277Handle = STDERR ; ;AN000;
278Sublist = None ; ;AN000;
279Count = N_A ; ;AN000;
280Class = Ext_Err_Class ; ;AN000;
281Function = No_Input ; ;AN000;
282Input =N_A ; ;AN000;
283 Define_Msg Extended_Error_Msg ; ;AN000;
284;--------------------------- ;
285;----------------------- ;an000;bgb
286Message_Number = 0 ; ;an000;bgb
287Handle = STDERR ; ;an000;bgb;AN000;
288Sublist = dg:sublist_msg_parserr ; ;an031;bgbbgb000;
289Count = 1 ; ;an031;bgb;AN000;
290Class = Parse_Err_Class ; ;an000;bgb;AN000;
291Function = No_Function ; ;an000;bgb;AN000;
292Input = N_A ; ;an000;bgb;AN000;
293 Define_Msg Parse_Error_Msg ; ;an000;bgb;AN000;
294;---------------------- ;
295Message_Number = 14 ; AN013;bgb
296Handle = STDERR ; AN013;bgb
297Sublist = None ; AN013;bgb
298Count = None ; AN013;bgb
299Class = utility_msg_class ; AN013;bgb
300Function = NO_INPUT ; AN013;bgb
301Input = N_A ; AN013;bgb
302 Define_Msg no_mem_arg ; AN013;bgb insufficient memory
303
304
305Data ends
306; extrn Drive_Letter_Msg:Byte
307; extrn FName_Buffer:Byte
diff --git a/v4.0/src/CMD/RECOVER/RECOVER.ASM b/v4.0/src/CMD/RECOVER/RECOVER.ASM
new file mode 100644
index 0000000..d83a2f5
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECOVER.ASM
@@ -0,0 +1,1615 @@
1page ,132 ;
2TITLE RECOVER.SAL - MS-DOS File/Disk Recovery Utility
3;----------------------------------------------------------
4;
5; Recover - Program to rebuild an ms.dos directory
6;
7; Copyright 1988 by Microsoft Corporation
8;
9;-----------------------------------------------------------
10.xlist
11 include recchng.inc ;an000;bgb
12 include recseg.inc ;AN000;bgb
13 INCLUDE DOSSYM.INC ;AN000;bgb
14 INCLUDE RECEQU.INC ;AN000;bgb
15 INCLUDE RECdata.INC ;AN000;bgb
16 INCLUDE recmacro.inc ;AN000;bgb
17 INCLUDE sysmsg.INC ;AN000;bgb
18 include pathmac.inc
19 msg_utilname<recover>
20; ;AN000;bgb
21;*****************************************************************************
22; Extrn Declarations
23;*****************************************************************************
24data segment public para 'DATA' ;An000;bgb
25 extrn Askmsg:Byte
26 extrn Baddrv:Byte
27 extrn FatErrRead:Byte
28 extrn FATErrWrite:Byte
29 extrn Dirmsg:Byte
30 extrn RecMsg:Byte
31 extrn OpnErr:Byte
32 extrn no_mem_arg:word ;an013;bgb
33data ends ;AN000;bgb
34
35
36;******************************************************************************
37; Public entries
38;******************************************************************************
39code segment public para 'code' ;An000;bgb
40 pathlabl recover
41public GetFat, getSmall, getfat1, getret, SetFat, setsmall, f_exists ;AN000;bgb
42public nofspec, kill_bl, endl, next_char
43Public Main_Routine
44
45IF KANJI
46 public islead
47 PUBLIC notlead
48 PUBLIC dbcsmore
49 PUBLIC TESTKANJ
50ENDIF
51
52
53;PUBLIC stop
54public setfat2, setfat1, setRet, GetKeystroke, Prompt, Load, ReadFt, WrtFat ;AN000;bgb
55public wrtit, wrtok, fEOF, EOFok, printerr, SFFromFCB, Main_Routine ;AN000;bgb
56public slashok, kill_bl, next_char, name_copied, sja, sjb, not_root ;AN000;bgb
57public same_drive, sj1, no_errors, same_dir, noname, drvok, See_If_File ;AN000;bgb
58public step2, step3, step4, direrr, fill_dir, file_spec ;AN000;bgb
59public RecFil, recfil0, rexit1, int_23, rabort, rest_dir, no_fudge ;AN000;bgb
60public int_24, int_24_back, ireti, Read_File, Bad_File_Read, read_fats ;AN000;bgb
61public fill_fat, rexit2, sfsize, stop_read, calc_fat_addr ;an027;bgb
62 EXTRN Write_Disk:NEAR,Read_Disk:NEAR,report:NEAR ; AC000;SM
63 Extrn Main_Init:Near
64 Extrn Change_Blanks:Near ;an012;bgb
65 Extrn Build_String:Near
66 extrn seg_adj:near
67 extrn exitpgm:near ;an026;bgb
68.list
69
70;***************************************************************************** ;an005;bgb
71; calc_fat_addr - calculate the seg/off of the fat cell from the cell number ;an005;bgb
72; ;an005;bgb
73; Inputs: AX the fat cell number ;an005;bgb
74; BX the fat table offset
75; ES the fat table segment (same as program seg) ;an005;bgb
76; Outputs: BX contains the offset of the fat cell ;an005;bgb
77; ES contains the segment of the fat cell ;an005;bgb
78; ;an005;bgb
79; LARGE FAT SUPPORT ;an005;bgb
80;******************* ;an005;bgb
81; the offset into the fat table is cluster number times 2 (2 bytes per fat entry) ;an005;bgb
82; This will result not only in the segment boundary being passed, but also in ;an005;bgb
83; a single-word math overflow. So, we calculate the the address as follows: ;an005;bgb
84; 0. start with cluster number (1-65535) ;an005;bgb
85; 1. divide by 8 to get the number of paragraphs per fat-cell (0-8191) ;an005;bgb
86; remainder = (0-7) ;an005;bgb
87; 2. multiply the remainder by 2 to get offset in bytes (0-15) ;an005;bgb
88; You now have a paragraph-offset number that you can use to calc the addr into ;an005;bgb
89; the fat table. To get the physical addr you must add it to the offset of the ;an005;bgb
90; table in memory. ;an005;bgb
91; 3. add the paras to the segment register ;an005;bgb
92; 4. add the offset to the offset register ;an005;bgb
93;****************************************************************************** ;an005;bgb
94Procedure calc_fat_addr,near ;an005;bgb
95 savereg <ax,dx> ; ax already has cluster number ;an005;bgb
96 lea bx,fattbl ;point to fat table in memory ;an005;bgb
97 call seg_adj ;es:bx = es:00
98 mov bx,0008h ; set up div by para (* 2 bytes per clus) ;an005;bgb
99 xor dx,dx ; zero dx for word divide ;an005;bgb
100 div bx ; do it ;an005;bgb
101 mov bx,es ; get fat table segment ;an005;bgb
102 add bx,ax ; add number of paras to the cluster ;an005;bgb
103 mov es,bx ; move it back ;an005;bgb
104 shl dx,1 ; remainder times 2 ;an005;bgb
105 mov bx,dx ; offset = 00 + remainder ;an005;bgb
106 restorereg <dx,ax> ;an005;bgb
107 return ;an005;bgb
108EndProc calc_fat_addr ;an005;bgb
109
110
111
112 break <GetFat - return the contents of a fat entry>
113;*****************************************************************************
114; GetFat - return the contents of a fat cell
115;
116; Inputs: AX the fat cell number
117; Outputs: BX contains the contents of the fat cell AX
118; CX contains the number of bytes per sector
119; Registers Revised: SI
120;
121; pseudocode:
122; ----------
123; if large-fat, then
124; double fat-number 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
125; fat-table offset = fat-num * 2 2 4 6 8 10 12 14 16 18 20
126; else
127; fat-table offset = fat-num + (fat-num/2)
128;
129; LARGE FAT SUPPORT - if this is a 16-bit fat, use the new calc algorithm
130; *****************
131;******************************************************************************
132Procedure GetFat,NEAR
133 set_data_segment
134 lea bx,fattbl ;point to fat table in memory ;AC000;bgb
135 cmp MaxClus,4086 ; if (MaxClus >= 4086) {
136; $IF AE ;changed to above because max clusters ;an005;bgb
137 JNAE $$IF1
138 ;can now be 'FFFF'hex ;an005;bgb
139 call calc_fat_addr ; ;set up div by para ;an005;bgb
140 mov bx,word ptr es:[bx] ; get contents of fat ;an005;bgb
141; $ELSE ;small fat ;AN000;bgb
142 JMP SHORT $$EN1
143$$IF1:
144getSmall: push ax ;save fat-num ; i = clus + clus/2;
145 mov si,ax ;save fat-num ;
146 sar ax,1 ;div by 2 ;
147 pushf ;save low bit ;
148 add si,ax ;clus + clus/2 ;
149 mov bx,word ptr [bx][si] ; b = b[i];
150 popf ;get low bit ;
151; $IF C ;AN000;bgb
152 JNC $$IF3
153 mov cl,4 ; b >>= 4;
154 shr bx,cl ;
155; $ENDIF ;AN000;bgb
156$$IF3:
157getfat1: and bh,0fh ;even fat-num ; b &= 0xFFF; AC000;bgb
158 pop ax ; }
159; $ENDIF ;AN000;bgb
160$$EN1:
161getret: mov cx,secsiz ; c = SecSize;
162 return
163EndProc GetFat
164
165;
166 break <SetFat - change the contents of a fat element>
167;*****************************************************************************
168; SetFat - given a fat index and a value, change the contents of the fat
169; cell to be the new value.
170;
171; Inputs: AX contains the fat cell to change
172; DX contains the new value to put into the fat cell
173; Outputs: FAT [AX] = DX
174; Registers Revised: CX, SI
175;
176; LARGE FAT SUPPORT - if this is a 16-bit fat, use the new calc algorithm
177; *****************
178;*****************************************************************************
179Procedure SetFat,NEAR
180 set_data_segment
181 lea bx,fattbl ; b = &Table; ;AC000;bgb
182 cmp MaxClus,4086 ;12 bit fat? if (MaxClus >= 4086) {
183; $IF AE ;changed to above because max clusters now 'ffff'hex ;an005;bgb
184 JNAE $$IF6
185 call calc_fat_addr ; calc the fat cell addr ;an005;bgb
186 mov word ptr es:[bx],dx ; get the contents ;an005;bgb
187; $ELSE
188 JMP SHORT $$EN6
189$$IF6:
190setsmall: SaveReg <ax,dx> ;yes, 12 bit fat
191 mov si,ax ; fat cell number i = clus + clus / 2;
192 sar ax,1 ; fat cell num /2
193 pushf ; save result if ax was odd
194 add si,ax ; offset = 1 1/2 bytes * fat cell num
195 mov ax,word ptr [bx][si] ; get contents of fat cell
196 popf ; get results from div ; if ((clus&1) != 0) {
197; $IF C ; was fat cell num odd?
198 JNC $$IF8
199 and ax,000fh ;yes ;keep unchanged part
200 mov cl,4 ; d <<= 4;
201 shl dx,cl
202; $ELSE
203 JMP SHORT $$EN8
204$$IF8:
205setfat2: and ax,0f000h ; no, even ;keep unchanged part
206; $ENDIF
207$$EN8:
208setfat1: or ax,dx ; move new value into ax
209 mov word ptr [bx][si],ax ; b[i] = a;
210 RestoreReg <dx,ax>
211; $ENDIF
212$$EN6:
213setret: return ; return;
214EndProc SetFat
215
216;
217 Break <GetKeystroke - await a single keystroke and flush all remaining>
218;*****************************************************************************
219; GetKeystroke - let the user hit a key and flush the input buffer. Kanji/
220; Taiwanese force this
221;
222; Inputs: None.
223; Outputs: None.
224; Registers Revised: AX
225;*****************************************************************************
226Procedure GetKeystroke,NEAR
227 MOV AX,(Std_CON_Input_Flush SHL 8) + Std_CON_Input_No_Echo
228 INT 21H
229 MOV AX,(Std_CON_Input_Flush SHL 8) + 0
230 INT 21H
231 return
232EndProc GetKeystroke
233
234
235;*****************************************************************************
236;PROMPT
237;*****************************************************************************
238Procedure Prompt,NEAR
239 Cmp Prompted,0
240 retnz
241 MOV Prompted,1
242 push ds
243 push cs
244; move drive letter in message
245 lea dx,askmsg ; AC000;SM ;AC000;bgb
246; display msg
247 call DISPLAY_interface ;AC000;bgb
248 pop ax ; ;AN000;bgb
249 pop ds
250; wait for user
251 call GetKeystroke
252
253 MOV AL,cs:DRIVE ; This is for ibm's single drive sys;AN000;bgb
254 CMP AL,1
255 JA NOSET ; Values other than 0,1 are not appropriate.
256 PUSH DS
257 MOV BX,50H
258 MOV DS,BX
259 MOV DS:(BYTE PTR 4),AL ; Indicate drive changed
260 POP DS
261NOSET:
262
263 return
264EndProc Prompt
265
266
267;
268 Break <Load - set up registers for abs sector read/write>
269;******************************************************************************
270; Load - load up all registers for absolute sector read/write of FAT
271;
272; called by: readft, writeft
273;
274; Inputs: none.
275; Outputs: AL - drive number (a=0)
276; ES:BX - point to FAT table ;an005;bgb
277; CX - number of sectors in FAT
278; DX - sector number of the first FAT sector
279; FatCnt - is set to the number of fats
280; Registers Revised: ax, dx, cx, bx
281;******************************************************************************
282Procedure Load,NEAR
283 set_data_segment ;an005;bgb
284 mov dx,firfat ;sector number of first fat 1-65535
285 mov al,fatnum ;number of fats 2 ;AC000;bgb
286 mov fatcnt,al ;FatCnt = FatNum; 1-65535 ;AC000;bgb
287 mov al,drive ;drive number a=0 b=1 ;AN000;bgb
288 mov cx,fatsiz ;sectors in the fat 1-65535
289 lea bx,fattbl ; es:bx --> fat table ;an005;bgb
290 return
291EndProc Load
292
293 Break <ReadFT - read in the entire fat>
294;******************************************************************************
295; ReadFt - attempt to read in the fat. If there are errors, step to
296; successive fats until no more.
297;
298; Inputs: none.
299; Outputs: Fats are read until one succeeds.
300; Carry set indicates no Fat could be read.
301; Registers Revised: all
302; LOGIC
303; *****
304; DO for each of the fats on the disk:
305; read - all the sectors in the fat
306; increase the starting sector by the number of sectors in each fat
307;
308; LARGE FAT SUPPORT - the big change here is in read disk. since the fat must ;an005;bgb
309; be within the first 32M, then the starting sector number of 65535 is ok, ;an005;bgb
310; as is a larger number of sectors to read/write. ;an005;bgb
311;******************************************************************************
312Procedure ReadFt,NEAR
313 set_data_segment ;an027;bgb;an005;bgb
314 mov dx,firfat ;sector number of first fat 1-65535 ;an027;bgb
315 mov al,fatnum ;number of fats 2 ;an027;bgb ;AC000;bgb
316 mov fatcnt,al ;FatCnt = FatNum; 1-65535 ;an027;bgb ;AC000;bgb
317 mov al,drive ;drive number a=0 b=1 ;an027;bgb;AN000;bgb
318 mov cx,fatsiz ;sectors in the fat 1-65535 ;an027;bgb
319 lea bx,fattbl ; es:bx --> fat table ;an027;bgb;an005;bgb
320 clc ;clear carry flag ;an027;bgb
321 mov Read_Write_Relative.Start_Sector_High,bp ;set hi word to zero ;AN000;
322 call Read_Disk ; read in fat #1 ;AC000;
323; $IF C ; was it a bad read? ;an027;bgb
324 JNC $$IF12
325 add dx,cx ;point to 2nd fat
326 call Read_Disk ; read in 2nd fat ;AC000;
327; $ENDIF ;carry flag set if both fats bad ;AC000;bgb
328$$IF12:
329ret ;an027;bgb
330EndProc ReadFt
331
332
333;
334 Break <WrtFat - write out the fat>
335;*****************************************************************************
336; WrtFat - using the results of a ReadFt, attempt to write out the fat
337; until successful.
338;
339; Inputs: none.
340; Outputs: A write of the fat is attempted in each fat position until
341; one succeeds.
342; Registers Revised: all
343; LOGIC
344; *****
345; DO for each fat on the disk
346; write the fat to disk
347; increase the starting sector number by the number of sectors per fat
348;
349; LARGE FAT SUPPORT - the big change here is in read disk. since the fat must ;an005;bgb
350; be within the first 32M, then the starting sector number of 65535 is ok, ;an005;bgb
351; as is a larger number of sectors to read/write. ;an005;bgb
352;****************************************************************************
353Procedure WrtFat,NEAR
354 call load ; load (); ;an005;bgb
355; $DO ;an005;bgb
356$$DO14:
357wrtit: call Write_Disk ; Write_Disk (); ;an005;bgb
358; $LEAVE C ;an015;bgb
359 JC $$EN14
360wrtok: add dx,cx ; fatStart += fatsize; ;an005;bgb
361 dec byte ptr fatcnt ; } while (--fatcnt); ;an005;bgb
362; $ENDDO Z ;an005;bgb
363 JNZ $$DO14
364$$EN14:
365 return
366EndProc WrtFat
367
368
369;
370 Break <fEOF - check to see if the argument is EOF>
371;*****************************************************************************
372; fEOF - test BX to see if it indicates EOF
373;
374; Inputs: BX - contains cluster
375; Outputs: Carry is set if BX indicates EOF
376; Registers Revised: none
377;*****************************************************************************
378Procedure fEOF,NEAR
379 CMP BX,MaxClus
380 JBE EOFok
381 CMP BL,0F7h ; bad sector indicator
382 JZ EOFok
383 STC
384 return
385EOFok: CLC
386 return
387EndProc fEOF
388
389
390;*****************************************************************************
391;*****************************************************************************
392
393
394;
395 Break <sfFromFCB - take an FCB and convert it to a sf pointer>
396;*****************************************************************************
397; SFFromFCB - index into System File tables for SFN.
398;
399; Input: ES:DI has FCB pointer
400; Output: ES:DI points to Sys-File-table entry
401; Registers Revised: ES:DI, BX only
402;
403;*****************************************************************************
404procedure SFFromFCB,NEAR
405 MOV BL,ES:[DI].FCB_SFN ;fcb+18 = system file table 00
406 XOR BH,BH ; 00
407 SaveReg <AX,BX>
408 MOV AH,Get_IN_Vars ;52h
409 INT 21h ; p = DOSBASE();
410 ; bx = 0026, ax=5200 es=0257
411 LES DI,DWORD PTR ES:[BX].SYSI_FCB ;load es:di w/ ptr to sf table
412 ; es:di = 0b37:0000
413 LEA DI,[DI].sfTable ; di=6 AC000;bgb
414 RestoreReg <BX>
415 SaveReg <DX>
416 MOV AX,SIZE SF_Entry ;42
417 MUL BX ;0
418 ADD DI,AX ;6
419 RestoreReg <DX,AX>
420 return ; return p;
421EndProc SFFromFCB
422
423;*****************************************************************************
424;*****************************************************************************
425Procedure get_dpb_info,Near ;AN000;bgb
426; get dpb for drive indicated
427 push ds ;save ds seg reg
428 mov dl,drive ; get drive number a=0 b=1 c=2 ;AN000;bgb
429 inc dl ; a=1, b=2, c=3
430 mov ah,GET_DPB ; hidden system call (032h)
431 int 21h ; call dos
432; note: ds is now changed !!!!
433 cmp al,0FFH ; -1 = bad return code
434; $IF NZ ;AN000;bgb
435 JZ $$IF17
436; get sector size
437 mov ax,word ptr [bx].dpb_sector_size ; get physical sector size
438 mov es:bytes_per_sector,ax ; save bytes per sector 200 ;AN000;bgb
439; get sectors per cluster
440 xor ch,ch ; zero out high byte ;ac000;bgb
441 mov cl,byte ptr [bx].dpb_cluster_mask ; get sectors/cluster - 1
442 inc cx ;1+1=2 ; get sectors / cluster
443 mov es:secall,cx ;2 ; save sectors per cluster ;AC000;bgb
444; get bytes per cluster
445 mul cx ; ax = bytes per cluster
446 mov eS:secsiz,ax ;400 ; save bytes per cluster ;AC000;bgb
447; first sector record
448 mov ax,[bx].dpb_first_sector ; get record of first sector
449 mov es:firrec,ax ;c ; ;AC000;bgb
450;first dir entry
451 mov dx,[bx].dpb_dir_sector ; get record of first directory entry
452 mov es:firdir,dx ;5 ; ;AC000;bgb
453; first fat record
454 mov si,[bx].dpb_first_fat ; get record of first fat
455 mov es:firfat,si ;1 ; sector number of first fat ;AC000;bgb
456; records in fat
457 mov cX,[bx].dpb_fat_size ; get size of fat (num of rcds) ;AC000;BGB
458 mov es:fatsiz,cX ;2 ;SIZE OF FAT FROM DPB ;AC000;BGB
459; number of cluster
460 mov di,[bx].dpb_max_cluster ; get number of clusters
461 mov es:lastfat,di ;163 ; number of fat entries ;AC000;bgb
462 mov es:MaxClus,di ;163 ; number of fat entries ;AC000;bgb
463; number of fats (1 or 2)
464 mov ch,[bx].dpb_fat_count ; get number of fats on drive
465 mov byte ptr es:fatnum,ch ;2 ; save number of fats on disk ;AC000;bgb
466; max dir entries
467 mov bx,[bx].dpb_root_entries ; get max number of dir entries
468 mov ES:maxent,bx ;70 ; ;AC000;bgb
469 pop ds ; restore ds register to group ;AC000;bgb
470; $ELSE ;AN000;bgb
471 JMP SHORT $$EN17
472$$IF17:
473 pop ds ; restore ds register to group ;AC000;bgb
474 jmp noname ; bad return = display error msg
475; $ENDIF ;AN000;bgb
476$$EN17:
477 ret ; ;AN000;bgb
478endproc get_dpb_info ; ;AN000;bgb
479;
480
481;
482;*****************************************************************************
483; assemble this part if doing japanese version
484;
485;INPUTS: es:di - points to last char in filename
486; ds:dx - point to beginning of filename
487;
488;*****************************************************************************
489Procedure check_kanji,Near ;AN000;bgb
490 IF KANJI
491 lea dx,[fname_buffer] ;point to filename ;AC000;bgb
492 PUSH DX ;save regs
493 PUSH DI ;save regs
494 MOV BX,DI ;bx and di now point to last char in filename
495 MOV DI,DX ;di now points to filename
496
497;do for entrire filename
498delloop: CMP DI,BX ;are we at the beginning of the filename?
499 JAE GOTDELE ;yes, and we are finished
500 MOV AL,[DI] ;get next char in filename
501 INC DI ;point one past it
502 CALL TESTKANJ ;see if it is dbcs
503 JZ NOTKANJ11
504 INC DI ;bump to past 2nd of dbcs pair
505 JMP DELLOOP ;check next char in file name
506notkanj11: cmp al,[dirchar] ;is it '\' ?
507 JNZ DELLOOP ;no, check next char
508 MOV DX,DI ; Point to char after '/'
509 DEC DX
510 DEC DX ; Point to char before '/'
511 JMP DELLOOP
512
513;completed filename
514gotdele: MOV DI,DX ;point to?
515 POP AX ; Initial DI
516 POP DX ;re-point to beginning of filename
517 SUB AX,DI ; Distance moved
518 SUB CX,AX ; Set correct CX
519; CMP DX,DI ;an024;bgb
520;stop: $if b ;an024;bgb
521; pop ax ;an024;bgb;an024;bgb
522; pop cx ;an024;bgb;an024;bgb;an024;bgb
523; jmp sja ;an024;bgb
524;;;;;;;;;;;;;;; JB sja ; Found a pathsep ;an024;bgb
525; $endif ;an024;bgb
526; $if a ;an024;bgb
527; pop ax ;an024;bgb;an024;bgb
528; pop cx ;an024;bgb;an024;bgb;an024;bgb
529; jmp sjb ;an024;bgb
530;;;;;;;;;;;;;;; JA sjb ; Started with a pathsep, root ;an024;bgb
531; $endif ;an024;bgb
532 MOV AX,[DI] ;an024;bgb
533 CALL TESTKANJ ;an024;bgb
534 JNZ same_dirjk ;an024;bgb
535 XCHG AH,AL ;an024;bgb
536; cmp al,[dirchar] ;an024;bgb
537; $if z ;an024;bgb
538; pop ax ;an024;bgb;an024;bgb;an024;bgb
539; pop cx ;an024;bgb;an024;bgb;an024;bgb
540; jmp sja ;an024;bgb
541;;;;;;;;;;;;;;;;jz sja ; One character directory ;an024;bgb
542; $endif ;an024;bgb
543same_dirjk:
544 ret ;AN000;bgb
545 ENDIF
546check_kanji endp ; ;AN000;bgb
547;
548
549;****************************************************************************
550;****************************************************************************
551 break
552 IF KANJI
553TESTKANJ: push ds ;get dbcs vector ;an012;bgb
554 push si
555 push ax
556 mov ax,6300h ;get dbcs vector ;an024;bgb;an012;bgb
557 int 21h ;an012;bgb
558 pop ax ;an024;bgb
559 sub si,2 ;prep for loop ;an012;bgb
560dbcsmore: ;an012;bgb
561 add si,2 ;point to next dbcs vector ;an012;bgb
562 cmp word ptr ds:[SI],bp ;do until 00 found in dbcs vector table ;an012;bgb
563 je notlead ;00 found, quit ;an012;bgb
564 CMP AL,byte ptr ds:[si] ;look at lead byte of dbcs char ;an012;bgb
565 jb dbcsmore ;al < lead byte means not dbcs ;an012;bgb
566 CMP al,byte ptr ds:[si+1] ;look at 2nd byte of dbcs ;an012;bgb
567 JBE ISLEAD ;if it is between the 2 chars, it is dbcs ;an012;bgb
568 jmp dbcsmore ;go get the next dbcs vector ;an012;bgb
569
570NOTLEAD:
571 PUSH AX
572 XOR AX,AX ; Set zero
573 POP AX
574 pop si
575 pop ds
576 RET
577ISLEAD:
578 mov es:dbcs_sw,1 ;an024;bgb
579 PUSH AX
580 XOR AX,AX ; Set zero
581 INC AX ; Reset zero
582 POP AX
583 pop si
584 pop ds
585 RET
586 ENDIF
587
588
589
590
591
592
593;*****************************************************************************;an020;bgb
594; copy the filename from the fcb to the data segment ;an020;bgb
595;*****************************************************************************;an020;bgb
596Procedure copy_fname,Near ;AN000;bgb ;an020;bgb
597;get fcb1 from the psp
598slashok: mov cx,PSP_Segment ;Get addrbility of psp ;AN000;bgb
599 mov ds,cx ; " " " " " " ;AN000;bgb
600 assume ds:dg,es:dg ; " " " " " " ;AN000;bgb
601 call get_fcb
602
603 ;An018;bgb
604
605; remove leading blanks and tabs from filename
606nofspec: mov si,81h ; point to command line ;AC000;bgb
607 lea di,fname_buffer ; point to filename ;ac000;bgb
608 xor cx,cx ; zero pathname length
609; $DO ;get source chars until neither tabs or blanks found
610$$DO20:
611kill_bl: lodsb ; get next char ;AN000;bgb
612 cmp al,tab ; leading tabs? (hex 9) ;AN000;bgb
613; $LEAVE NE,AND ; yes - done ;AN000;bgb
614 JE $$LL21
615 cmp al,' ' ; leading blanks? (hex 20) ;AN000;bgb
616; $LEAVE NE
617 JNE $$EN20
618$$LL21:
619; $ENDDO ; ;AN000;bgb
620 JMP SHORT $$DO20
621$$EN20:
622;
623
624;was any parameter entered at all?
625endl: cmp al,13 ; no name found if the 1st char is CR
626 jne next_char ; file name or drive entered
627 jmp noname ; no parameter entered
628
629
630
631;copy filename from cmd line to fname buffer
632next_char:
633 stosb ; move byte in al to fname_buffer
634 inc cx ;inc fname counter
635 lodsb ; get next byte
636 cmp al,' ' ; terminated by blank?
637 je name_copied ; yes
638 cmp al,9 ;terminated by tab?
639 je name_copied ; yes
640 cmp al,13 ; terminated by CR?
641 jne next_char ; yes
642
643
644;reset ds to data segment
645name_copied: ; got file name
646 push es
647 pop ds ;ds now points to data seg
648 assume ds:dg
649
650 mov byte ptr [di],0 ; nul terminate the pathname
651 dec di ; adjust to the end of the pathname
652 ret ;an020;bgb
653copy_fname endp ; ;an020;bgb
654
655
656
657
658;*****************************************************************************;an020;bgb
659; get a copy of the fcb ;an020;bgb
660;*****************************************************************************;an020;bgb
661Procedure get_fcb,Near ;AN000;bgb ;an020;bgb
662 mov si,fcb ; ds:si point to fcb in the psp ;AN000;bgb
663 lea di,fcb_copy ; es:di point to the copy in the data seg;AC000;bgb
664 mov cx,32 ; move 32 bytes ;AN000;bgb
665 rep movsb ; from ds:si (fcb) to es:di (fcb-copy) ;AN000;bgb
666;check if it is not there (in psp) ;an024;bgb;an020;bgb
667; mov si,fcb ;point to fcb1 ;an024;bgb;AN014;bgb
668; cmp byte ptr ds:[si+1],' ' ;it will be blank if a filespec used ;an024;bgb;AN014;bgb
669; $IF E,AND ;an024;bgb;Ac015;bgb
670; cmp byte ptr ds:[84h],0dh ;this will be CR if drive letter used ;an024;bgb;AN015;bgb
671; $IF NE ;if no drive letter and fcb blank, then filespec! ;an024;bgb;AN015;bgb
672;now get the filename from the command line ;an024;bgb;an020;bgb
673; step 1 - point to end of cmd line ;an024;bgb
674 mov si,081h ;point to beginning of command line ;AN014;bgb
675 mov cl,byte ptr ds:[80h] ;get length of cmd line ;AN014;bgb
676 xor ch,ch ;zero out hi byte for word arith ;AN014;bgb
677 add si,cx ;begin plus length of cmd line = end ;AN014;bgb
678 dec si ;point to last char, not CR ;an020;bgb
679;step 2 - find the first backslash ;an020;bgb
680 mov exit_sw,bp ;false ;an024;bgb
681; $DO ;do until back slash found ;AN014;bgb
682$$DO23:
683 cmp byte ptr ds:[si],'\' ;look for back slash ;AN014;bgb
684; $IF E ;find it? ;an024;bgb;AN014;bgb
685 JNE $$IF24
686 mov al,[si-1] ;get possible leading byte ;an024;bgb
687 IF KANJI
688 call testkanj ;is it a leading byte of DBCS? ;an024;bgb
689 ENDIF
690; $IF Z ;no- then it is subdir delimiter ;an024;bgb
691 JNZ $$IF25
692 mov exit_sw,true ;so exit the search loop ;an024;bgb
693; $ELSE ;yes it is DBCS leading byte ;an024;bgb
694 JMP SHORT $$EN25
695$$IF25:
696 dec si ;so skip the leading byte ;an024;bgb
697; $ENDIF ;check for kanji ;an024;bgb
698$$EN25:
699; $ENDIF ;an024;bgb
700$$IF24:
701 cmp exit_sw,true ;an024;bgb
702; $LEAVE E ;an024;bgb
703 JE $$EN23
704 cmp byte ptr ds:[si],0 ;look for 00 (not a filespec) ;AN018;bgb
705; $IF E ;an020;bgb
706 JNE $$IF30
707 ret ;an020;bgb
708;;;;;;;;;;;;;;;;je nofspec ;filespec not found ;ac020;bgb
709; $ENDIF ;an020;bgb
710$$IF30:
711 dec si ;no , next char ;AN014;bgb
712; $ENDDO ;AN014;bgb
713 JMP SHORT $$DO23
714$$EN23:
715;found backslash, move it into fcb
716 inc si ;point to 1st char of filename ;AN014;bgb
717 lea di,fcb_copy+1 ; move addr of fcb_copy into di ;an024;bgb;AN014;bgb
718; $DO ;do until eol - CR found ;AN014;bgb
719$$DO33:
720 lodsb ;get one byte of filename from cmd line ;AN014;bgb
721 cmp al,0dh ;end of line? ;AN014;bgb
722; $LEAVE E ;if so, we are done ;AN014;bgb
723 JE $$EN33
724 cmp al,'.' ;is it extension indicator? ;AN014;bgb
725; $IF E ;yes ;AN014;bgb
726 JNE $$IF35
727 lea di,fcb_copy ;point to extension in fcb ;AN014;bgb
728 add di,9 ;point to extension in fcb ;AN014;bgb
729; $ELSE ;dont move the period ;AN014;bgb
730 JMP SHORT $$EN35
731$$IF35:
732 stosb ;move char into fcb ;AN014;bgb
733; $ENDIF ;AN014;bgb
734$$EN35:
735; $ENDDO ;AN014;bgb
736 JMP SHORT $$DO33
737$$EN33:
738; $ENDIF ;AN014;bgb
739 ret ;an020;bgb
740get_fcb endp ; ;an020;bgb
741 ;an020;bgb
742 ;an020;bgb
743;
744 Break <Main code of recover - Version check and exit if incorrect>
745;*****************************************************************************
746;Routine name: Main_routine
747;*****************************************************************************
748;
749;description: Main routine for recovering a file from a bad sector
750;
751;Called from: recover_ifs in RECINIT.SAL
752;
753;
754;Called Procedures: prompt
755; readft
756; read_file
757; getfat (sic)
758; feof
759; sffromFCB
760; bad-file-read
761; report
762; wrtfat
763; stdprintf
764; RECPROC.SAL
765;
766;Input: ????
767;
768;Output: FAT is changed if a bad sector is found.
769; The file is complete except for the data in the bad sector.
770;
771;Change History: header created 7-19-87 BGB
772;
773;Psuedocode
774;----------
775;
776;*****************************************************************************
777Main_Routine:
778
779;get system switch character
780 xor bp,bp
781 set_data_segment ; set es,ds to data ;AN000;bgb
782 ;;;;;;; call change_blanks ; get dbcs blanks ;an012;bgb
783 mov ax,(char_oper shl 8) ; get switch character
784 int 21h ; put into dl
785 cmp dl,"/" ; is it / ?
786; $IF nz
787 JZ $$IF39
788 jmp slashok ; if not / , then not PC
789; $ENDIF
790$$IF39:
791 mov [dirchar],"\" ; in PC, dir separator = \
792 mov [userdir],"\"
793
794 call copy_fname
795
796;check for dbcs double byte chars
797 push di ;an019;bgb
798 push cx ;an019;bgb
799 call check_kanji
800same_dirj:
801 pop cx ;an019;bgb
802 pop di ;an019;bgb
803 mov lastchar,di
804
805
806;see if there are any '\' in filename parameter - means filespec ;an024;bgb
807;do until a \ is found or end-of-string ;an024;bgb
808; if a \ is found ;an024;bgb
809; then test for dbcs leading byte ;an024;bgb
810; if it is not dbcs leading byte ;an024;bgb
811; then exit loop ;an024;bgb
812; else continue loop ;an024;bgb
813; $DO ;an024;bgb
814$$DO41:
815 dec cx ;an024;bgb
816 and cx,cx ;compare cx to zero ;an024;bgb
817; $LEAVE E ;an024;bgb
818 JE $$EN41
819 mov al,[dirchar] ;05ch ; get directory separator character ;an024;bgb
820 cmp al,byte ptr [di] ; (cx has the pathname length) ;an024;bgb
821; $IF E ; reset direction, just in case ;an024;bgb
822 JNE $$IF43
823 mov al,[di-1] ;get possible leading byte ;an024;bgb
824 IF KANJI
825 call testkanj ;see if it is leading byte ;an024;bgb
826 ENDIF
827; $IF Z ;not a leading byte? then its a '\' ;an024;bgb
828 JNZ $$IF44
829 mov lastbs,di ;an024;bgb
830 mov di,lastchar ;an024;bgb
831 jmp sja ;zero = not a leading byte ;an024;bgb
832; $ENDIF ;an024;bgb
833$$IF44:
834; $ENDIF ;an024;bgb
835$$IF43:
836 dec di ;an024;bgb
837; $ENDDO ;an024;bgb
838 JMP SHORT $$DO41
839$$EN41:
840;save current disk ;an008;bgb
841 mov ah,19h ;an008;bgb
842 int 21h ;an008;bgb
843 mov old_drive,al ;an008;bgb
844 jmp same_dir ; no dir separator char. found, the
845 ; file is in the current directory
846 ; of the corresponding drive. Ergo,
847 ; the FCB contains the data already.
848
849
850;handle filespec here
851;at least one '\' found in filename
852sja:
853 jcxz sjb ; no more chars left, it refers to root
854 push di ;an024;bgb
855 mov di,lastbs ;an024;bgb
856 cmp byte ptr [di-1],':' ; is the prvious character a disk def?;an024;bgb
857 pop di ;an024;bgb
858 jne not_root
859sjb:
860 mov [the_root],01h ; file is in the root
861not_root:
862 inc di ; point to dir separator char.
863 mov ax,bp ;set to zero
864 stosb ; nul terminate directory name
865; pop ax
866; push di ; save pointer to file name
867 mov [fudge],01h ; remember that the current directory
868 ; has been changed.
869;save current disk ;an008;bgb
870 mov ah,19h ;an008;bgb
871 int 21h ;an008;bgb
872 mov old_drive,al ;an008;bgb
873;----- Save current directory for exit ---------------------------------;
874 mov dl, drive ; get specified drive if any
875;;;;;;; or dl,dl ; default disk? ;an021;bgb
876;;;;;;; jz same_drive ;an021;bgb
877;;;;;;;;dec dl ; adjust to real drive (a=0,b=1,...) ;an021;bgb
878 mov ah,set_default_drive ; change disks
879 int 21h
880; cmp al,-1 ; error?
881; jne same_drive
882;BADDRVSPEC:
883; lea dx,baddrv ; AC000;SM ;AC000;bgb
884; jmp printerr
885
886same_drive:
887 call prompt
888 mov ah,Current_Dir ; userdir = current directory string
889 mov dx,bp ;set to zero
890 lea si,userdir+1 ;AC000;bgb
891 int 21h
892
893;----- Change directories ----------------------------------------------;
894 cmp [the_root],01h
895 lea dx,[dirchar] ; assume the root ;AC000;bgb
896 je sj1
897 lea dx,[fname_buffer] ;AC000;bgb
898sj1:
899 push di ;an024;bgb
900 mov di,lastbs ;an024;bgb
901 mov byte ptr [di],0 ;an024;bgb
902 mov ah,chdir ; change directory
903 int 21h
904 mov byte ptr [di],'\' ;an024;bgb
905 pop di ;an024;bgb
906 mov al,Drive ;Get drive number ;AN000;bgb
907 add al,"A"-1 ;Make it drive letter ;AN000;
908 mov Drive_Letter_Msg,al ;Put in message ;AN000;
909 lea dx,baddrv ;AC000;bgb
910 jnc no_errors
911 call printerr
912 jmp rabort
913
914;
915no_errors:
916
917 Break <Set up exception handlers>
918
919;----- Parse filename to FCB -------------------------------------------;
920; pop si ;an024;bgb
921 mov si,lastbs ;an024;bgb
922 inc si ;an024;bgb
923 lea di,fcb_copy ;AC000;bgb
924 mov ax,(parse_file_descriptor shl 8) or 1
925 int 21h
926;;;;;;;;push ax
927;-----------------------------------------------------------------------;
928same_dir:
929 lea bx,fcb_copy ;point to 1st byte of fcb (drive num) ;AC000;bgb
930 cmp byte ptr [bx+1],' ' ; must specify file name
931 jnz drvok
932 cmp byte ptr [bx],0 ;or drive specifier
933 jnz drvok
934 cmp dbcs_sw,1 ; or dbcs ;an024;bgb
935 jz drvok ;an024;bgb
936noname: ;AC000;bgb
937 push es
938 pop ds
939 lea dx,baddrv ;AC000;bgb
940 call display_interface ; AC000;bgb
941 pop ax ;reset stack ;an024;bgb
942 pop ax ;reset stack ;an024;bgb
943 jmp int_23
944;****************************************************************************
945; we're finished with parsing here, do the main function of recover.
946drvok:
947 CALL Prompt ;wait for user keystroke to begin ;AN000;bgb
948 call get_dpb_info ;get device info ;AN000;bgb
949 call fill_fat ; fill fat table w/ null ;AN000;bgb
950; $IF C ;was there not enuff memory to run? ;an013;bgb
951 JNC $$IF48
952 lea dx,no_mem_arg ; ;an013;bgb
953 call printerr ;an013;bgb
954 jmp rabort ;an013;bgb
955; $ENDIF ;fat could be read from disk ;an013;bgb
956$$IF48:
957
958 call readft ; readft (); ;AN000;bgb
959; $IF C ; could the fat be read from disk? ;AN000;bgb
960 JNC $$IF50
961 lea dx,FATErrRead ; ;AC000;bgb
962 call printerr
963 jmp rabort
964; $ENDIF ;fat could be read from disk ;AN000;bgb
965$$IF50:
966See_If_File: ; ;AN000;
967 lea bx,fname_buffer ; ;AC014;bgb
968 cmp byte ptr [bx+1],':' ;if fname = 'a:' and..... ;ac020;bgb
969; $IF E,AND ; ;an020;bgb
970 JNE $$IF52
971 cmp word ptr [bx+2],bp ;set to zero ;all zeros following that, then ;an020;bgb
972; $IF E ;then drive spec ;AN202;BGB
973 JNE $$IF52
974 call drive_spec ;only drive specified ;AN000;bgb
975; $ELSE ; file name specified ;AN000;bgb
976 JMP SHORT $$EN52
977$$IF52:
978 call file_spec ;file can be 'f' or 'a:,0,file' or 'a:file' or 'file.ext' ;an020;bgb
979; $ENDIF ;AN000;bgb
980$$EN52:
981
982
983int_23: sti ;allow interrupts ;an026;bgb
984 lds dx,cs:dword ptr [int_24_old_off] ;point to old vector ;an026;bgb
985 mov al,24h ;which interrupt to set? ;an026;bgb;AC000;
986 DOS_Call Set_Interrupt_Vector ;set vector to old ;an026;bgb;AC000;
987
988 lds dx,cs:dword ptr [int_23_old_off] ;point to old vector ;an026;bgb
989 mov al,23h ;which interrupt to set? ;an026;bgb;AC000;
990 DOS_Call Set_Interrupt_Vector ;set vector to old ;an026;bgb;AC000;
991
992 PUSH CS ;reset ds ;an026;bgb
993 POP DS ;an026;bgb
994aSSUME DS:DG ;an026;bgb
995 call rest_dir
996 ;an026;bgb
997 mov cs:ExitStatus,0 ; good return ;AC000;
998 jmp [exitpgm] ;an026;bgb
999rabort:
1000 ret ;Return to RECINIT for exit ;AC000;
1001 ; mov ah,exit
1002 ; int 21h
1003
1004
1005;*************************************************************************
1006; DO until either
1007;*************************************************************************
1008procedure file_spec,near ;AN000;bgb
1009; try to open the file
1010recfil: lea dx,fcb_copy ; if (FCBOpen (FCB) == -1) { ;AC000;bgb
1011 mov ah,FCB_OPEN ; function ofh = open
1012 int 21h ;returns -1 in al if bad open
1013 cmp al,0ffh ;was file opened ok? ;AN000;bgb
1014; $IF E ; no ;AN000;bgb
1015 JNE $$IF55
1016; display error msg
1017 lea si,FCB_Copy.fcb_name ;Point at filename in FCB ; ;AC000;bgb
1018 lea di,Fname_Buffer ;Point at buffer ; ;AC000;bgb
1019 mov cx,FCB_Filename_Length ;Length of filename ;AN000;
1020 call Change_Blanks ;Convert DBCS blanks to SBCS ;AN000;
1021 call Build_String ;Build ASCIIZ string ending ;AN000;
1022 lea dx,opnerr ; AC000;SM printf (Can't open); ;AC000;bgb
1023 call display_interface ; AC000;bgb
1024;ecfil0: $ELSE ; LastFat = 1; ;AN000;bgb
1025recfil0:
1026 JMP SHORT $$EN55
1027$$IF55:
1028f_exists: call process_file ;file was opend ok
1029rexit1: mov ah,DISK_RESET
1030 int 21h
1031 call wrtfat ; save the fat
1032; $IF C ;Couldn't write it ;AN000;
1033 JNC $$IF57
1034 lea dx,FATErrWrite ;Just tell user he is in deep! ;AC000;bgb
1035 call display_interface ; ;AN000;bgb
1036; $ELSE
1037 JMP SHORT $$EN57
1038$$IF57:
1039 call report ; report (); ;ac015;bgb
1040; $ENDIF ;AN000;bgb; ;AN000;
1041$$EN57:
1042; $ENDIF ;AN000;bgb
1043$$EN55:
1044 ret ;AN000;bgb
1045endproc file_spec ;AN000;bgb
1046
1047;*************************************************************************
1048; DO until either
1049;*************************************************************************
1050Procedure process_file,Near ; ;AN000;
1051recfile0:
1052 mov lastfat,1 ;set to 1 : means 1st fat read in
1053 lea di,fcb_copy ; d = &FCB ;AC000;bgb
1054 mov ax,[di].FCB_FilSiz ;55 siztmp = filsiz = d->filsiz;
1055 mov filsiz,ax
1056 mov siztmp,ax
1057 mov ax,[di].FCB_FilSiz+2 ;00
1058 mov filsiz+2,ax
1059 mov siztmp+2,ax
1060 SaveReg <ES,DI> ; fatptr =
1061 call sfFromFCB ; sfFromFCB(d)->firclus;
1062 mov ax,ES:[DI].sf_firclus ; es:di +0b = 84
1063 RestoreReg <DI,ES>
1064 mov fatptr,ax
1065 or ax,ax ; if (fatptr == 0)
1066; $IF NZ ;AN000;bgb
1067 JZ $$IF61
1068; read each fat in the file
1069; $DO ;Loop until entire file read in ;AN000;bgb
1070$$DO62:
1071 mov bx,fatptr ;Get current cluster
1072 call fEOF ;Got to the end of the file?
1073; $LEAVE C ;Yes if CY ;AN000;bgb
1074 JC $$EN62
1075STOP_read: call Read_File ;Go read in the cluster
1076; $IF C ;CY indicates an error ;AN000;bgb
1077 JNC $$IF64
1078 call Bad_File_Read ;Go play in the FAT
1079; $ELSE ;Read cluster in okay ;AN000;bgb
1080 JMP SHORT $$EN64
1081$$IF64:
1082 mov ax,secsiz ;Get bytes/cluster
1083 sub siztmp,ax ;Is size left < 1 cluster?
1084 sbb siztmp+2,bp ;zero ;
1085; $IF C ;Yes ;AN000;bgb
1086 JNC $$IF66
1087 xor ax,ax ;Set our running count to 0
1088 mov siztmp,ax
1089 mov siztmp+2,ax
1090; $ENDIF ;AN000; ;AN000;bgb
1091$$IF66:
1092 mov ax,fatptr ;The previous cluster is now
1093 mov lastfat,ax ; the current cluster
1094; $ENDIF ;AX has current cluster ;AN000;bgb
1095$$EN64:
1096 call getfat ;Get the next cluster
1097 mov fatptr,bx ;Save it
1098; $ENDDO ;Keep chasing the chain ;AN000;bgb
1099 JMP SHORT $$DO62
1100$$EN62:
1101; $ENDIF ;All done with data ;AN000;bgb
1102$$IF61:
1103; recover extended attributes ;an032;bgb
1104; SaveReg <ES,DI> ;Save regs ;AN000; ;an032;bgb
1105; call sfFromFCB ;Get sf pointer ;AN000; ;an032;bgb
1106; mov ax,[di].sf_ExtCluster ;Look at extended attrib entry ;AN000; ;an032;bgb
1107; cmp word ptr [di].sf_ExtCluster,bp ;zero ;Is there extended attribs? ;;an032;bgbAN000;
1108; $IF NE ;Yes ;AN000; ;an032;bgb
1109; call Read_File ;Try to read it in ;AN000; ;an032;bgb
1110; $IF C ;CY means we couldn't ;AN000; ;an032;bgb
1111; mov word ptr [di].sf_ExtCluster,bp ;zero ;Off with its head!;an032;bgb;AN000;
1112; and ES:[di].sf_flags,NOT devid_file_clean ; mark file dirty ;AN000; ;an032;bgb
1113; $ENDIF ; ;AN000; ;an032;bgb
1114; $ENDIF ; ;AN000; ;an032;bgb
1115; RestoreReg <DI,ES> ; ;AN000; ;an032;bgb
1116 lea dx,fcb_copy ; close (FCB); ;AC000;bgb
1117 mov ah,FCB_CLOSE
1118 int 21h ;
1119 return ;AN000;bgb
1120endproc process_file ;AN000;bgb
1121
1122;*************************************************************************
1123;***************************************************************************
1124 break
1125;----- Restore INT 24 vector and old current directory -----------------;
1126Procedure Rest_dir,Near ; ;AN000;
1127 cmp cs:[fudge],0
1128; $IF NE
1129 JE $$IF71
1130 mov ax,(set_interrupt_vector shl 8) or 24h
1131 lds dx,cs:[hardch]
1132 int 21h
1133 push cs
1134 pop ds
1135 lea dx,userdir ; restore directory ;AC000;bgb
1136 mov ah,chdir
1137 int 21h
1138; $ENDIF
1139$$IF71:
1140no_fudge:
1141 mov dl,old_drive ; restore old current drive ;an008;bgb
1142 mov ah,set_default_drive
1143 int 21h
1144 ret
1145endproc rest_dir
1146
1147;;----- INT 24 Processing -----------------------------------------------;
1148;*************************************************************************
1149 int_24_retaddr dw int_24_back
1150
1151 int_24 proc far
1152 assume ds:nothing,es:nothing,ss:nothing
1153 pushf ; ** MAKE CHANGES **
1154 push cs
1155 push [int_24_retaddr]
1156 push word ptr [hardch+2]
1157 push word ptr [hardch]
1158 assume ds:dg,es:dg,ss:dg ;AN000;bgb
1159 ret
1160endproc int_24
1161;*************************************************************************
1162int_24_back:
1163 cmp al,2 ; abort?
1164 jnz ireti
1165 push cs
1166 pop ds
1167assume ds:dg,es:dg,ss:dg
1168 call rest_dir
1169 ret ;Ret for common exit ;AC000;
1170ireti:
1171 iret
1172
1173 break < read in a cluster of the file>
1174;****************************************************************************
1175; READ_FILE
1176;Read in cluster of file.
1177;
1178; Input: Secall = sectors/cluster
1179; FatPtr = cluster to read
1180; Firrec = Start of data area - always in first 32mb of partition
1181; dx = offset of fcb_copy ???
1182;
1183; Output: CY set if error on read on ret
1184; DI = pointer to FCB
1185;*****************************************************************************
1186Procedure Read_File,Near ; ;AN000;
1187 mov cx,secall ;2 ;if (aread((fatptr-2)*secall+firrec) == -1) {
1188 mov ax,fatptr ;84 ;cluster number to read
1189 sub ax,2 ;ax=82 ; -1 ;AN000;bgb
1190 mul cx ;ax=104 ; sectors/clus * (clus-2)
1191 add ax,firrec ;ax=110 ; plus beg of data area
1192 adc dx,bp ;0 ;Handle high word of sector ;AN000;
1193 mov Read_Write_Relative.Start_Sector_High,dx ;Start sector ;AN000;
1194 mov dx,ax ;110 ;clus-2
1195 mov es,table ;2b62 ;segment of area past fat table ;an005;bgb
1196 xor bx,bx ;es:bx --> dir/file area ;an005;bgb
1197 mov al,drive ;0 ;drive num ;AN000;bgb
1198 call Read_Disk ; ; ;AC000;
1199 lea di,fcb_copy ; ;AC000;bgb
1200 ret ; ;AN000;
1201endproc Read_File ; ;AN000;
1202
1203
1204 break < found a bad cluster in the file >
1205;*************************************************************************
1206;Play around with the FAT cluster chain, by marking the cluster that failed
1207;to read as bad. Then point the preceding cluster at the one following it.
1208;Special case if there is only one cluster, than file gets set to zero
1209;length with no space allocated.
1210;
1211; Input: FatPtr = Cluster that failed to read
1212; LastFat = Previous cluster, equals 1 if first cluster
1213;
1214; Output: AX = previous cluster
1215; File size = file size - cluster size ( = 0 if cluster size > file)
1216;***************************************************************************
1217Procedure Bad_File_Read,Near
1218 mov ax,fatptr ;Get current cluster
1219 call getfat ;Get the next cluster in BX
1220 cmp lastfat,1 ;Is this the first entry?
1221; $IF E ;Yes ;AC000;
1222 JNE $$IF73
1223 call fEOF ;Is the next the last cluster?
1224; $IF C ;Yes ;AC000;
1225 JNC $$IF74
1226 xor bx,bx ;Need to zero out first cluster
1227; $ENDIF ; because the first one is bad! ;AN000;
1228$$IF74:
1229 SaveReg <ES,DI,BX> ;Save some info
1230 call sfFromFCB ;Get pointer to sf table
1231 RestoreReg <BX> ;Get back clus to point to
1232 mov ES:[DI].sf_firclus,BX ;Skip offending cluster
1233 RestoreReg <DI,ES> ;Get back regs
1234; $ELSE ;Not first entry in chain ;AC000;
1235 JMP SHORT $$EN73
1236$$IF73:
1237 mov dx,bx ;DX = next cluster
1238 mov ax,lastfat ;AX = Previous cluster
1239 call setfat ;prev fat points to next fat
1240 ; offending cluster
1241; $ENDIF ; Ta-Da! ;AN000;
1242$$EN73:
1243 mov ax,fatptr ;Get the offending cluster
1244 mov dx,0fff7h ;Mark it bad
1245 call setfat ;Never use it again!
1246 mov ax,secsiz ;Get bytes/sector
1247 cmp siztmp+2,bp ;Is file < 32mb long?
1248; $IF NE,AND ; and ;AC000;
1249 JE $$IF78
1250 cmp siztmp,ax ;Shorter than cluster size?
1251; $IF BE ;Yes ;AC000;
1252 JNBE $$IF78
1253 mov ax,siztmp ;File size = smaller of the two
1254; $ENDIF ;AN000;
1255$$IF78:
1256 SaveReg <ES,DI> ;Save regs
1257 call sfFromFCB ;Get sf pointer
1258sfsize: sub word ptr ES:[di].sf_size,ax ;Adjust internal file sizes
1259 sbb word ptr ES:[di].sf_size+2,bp ; " " " "
1260 sub siztmp,ax ;Keep track of how much done
1261 sbb siztmp,bp ;
1262 and ES:[di].sf_flags,NOT devid_file_clean ; mark file dirty
1263 RestoreReg <DI,ES> ; sfFromFCB(d)->flags &= ~CLEAN;
1264 lea di,fcb_copy
1265 sub word ptr [di].fcb_filsiz,ax ;And change the FCB
1266 sbb word ptr [di].fcb_filsiz+2,bp ;
1267 and byte ptr [di].fcb_nsl_bits,NOT devid_file_clean ; mark file dirty ;AN000;
1268 mov ax,lastfat ;AX = previous cluster
1269 ret ; ;AN000;
1270endproc Bad_File_Read ; ;AN000;
1271
1272
1273;***************************************************************************** ;an005;bgb
1274; description: fill the fat table in memory with the 'E5' character ;an005;bgb
1275; ;an005;bgb
1276; called from: main-routine ;an005;bgb
1277; ;an005;bgb
1278;Change History: Created 8/7/87 bgb ;an005;bgb
1279; ;an005;bgb
1280;Input: bytes-per-sector ;an005;bgb
1281; fatsiz ;an005;bgb
1282; maxent ;an005;bgb
1283; ;an005;bgb
1284;Output: ram-based fat table ;an005;bgb
1285; ;an005;bgb
1286; LOGIC ;an005;bgb
1287;---------- ;an005;bgb
1288; calc number of para in fat table ;an005;bgb
1289; = bytes-per-sector / 16 * sectors-per-fat ;an005;bgb
1290; calc segment of directory area in memory ;an005;bgb
1291; = fat-table offset + length of fat-table ;an005;bgb
1292; calc number of para in directory ;an005;bgb
1293; = entries-per-directory * bytes-per-entry / 16 ;an005;bgb
1294; do for each para ;an005;bgb
1295; move 16 bytes into memory ;an005;bgb
1296;***************************************************************************** ;an005;bgb
1297 even
1298Procedure fill_fat,Near ;AN000;bgb ;an005;bgb
1299; calc fat table length ;an005;bgb
1300 set_data_segment ;an005;bgb
1301 mov ax,bytes_per_sector ; bytes per sector ;an005;bgb
1302 xor dx,dx ;an005;bgb
1303 mov bx,16 ;an005;bgb
1304 div bx ; paras per sector ;an005;bgb
1305 mov cx,fatsiz ;2 ; get sectors per fat ;an005;bgb
1306 xor dx,dx ;an005;bgb
1307 mul cx ; paras per fat ;an005;bgb
1308 mov paras_per_fat,ax ;length of fat in paragraphs ;an005;bgb
1309; calc dir area addr ;an005;bgb
1310 mov bx,es
1311 add ax,bx ;seg of dir area ;an005;bgb
1312 mov es,ax
1313 lea bx,fattbl ;off ;an005;bgb
1314 call seg_adj ;seg:off = seg:0000 ;an005;bgb
1315 mov table,es ;segment of beginning of fat table ;an005;bgb
1316; calc dir area length ;an005;bgb
1317 mov ax,maxent ;ax= max dir entries ;an005;bgb
1318 mov bx,32 ; 32 bytes per dir entry ;an005;bgb
1319 xor dx,dx ;an005;bgb
1320 mul bx ; bytes per dir ;an005;bgb
1321 xor dx,dx ;zero out for divide ;an005;bgb
1322 mov bx,16 ;divide by bytes per para ;an005;bgb
1323 div bx ;paras per dir ;an005;bgb
1324; calc total length to fill ;an005;bgb
1325 add ax,paras_per_fat ;paras/fat + paras/dir = total paras ;an005;bgb
1326; see if we have enough memory ;an013;bgb
1327 push ax ;an013;bgb
1328 push ds ;save ds reg ;an013;bgb
1329 mov bx,es
1330 add ax,bx ;add in starting seg of fat table ;an013;bgb
1331 inc ax ; one more to go past our area ;an013;bgb
1332 DOS_Call GetCurrentPSP ;Get PSP segment address ;an013;bgb
1333 mov ds,bx ;ds points to the psp ;an013;bgb
1334 Assume DS:Nothing ;point to psp ;an013;bgb
1335 MOV DX,DS:[2] ;get the last para of memory ;an013;bgb
1336 pop ds ;an013;bgb
1337 assume ds:dg
1338 cmp dx,ax ;last-para must be greater or equal ;an013;bgb
1339; $IF AE ;it was, so complete filling the fat ;an013;bgb
1340 JNAE $$IF80
1341 pop ax ;an013;bgb
1342;fill each para ;an005;bgb
1343 push ds
1344 pop es
1345 lea bx,fattbl ; es:di = point to beg of fat table ;an005;bgb
1346 call seg_adj
1347 mov di,bx
1348 mov bx,ax ;total number of paras to do ;an005;bgb
1349 mov ax,0e5e5h ;fill characters Fill (d, 16*dirent, 0xe5e5);;an005;bgb
1350; $DO ;do for each para ;an005;bgb
1351$$DO81:
1352 mov cx,8 ; number of times to repeat ;an005;bgb
1353 xor di,di ;bump addr pointers by 16 bytes -
1354 rep stosw ; mov 2 bytes, 1 ea for 16 * num-of-entries ;an005;bgb
1355 dec bx ;loop counter ;an005;bgb
1356; $LEAVE Z ;until zero ;an005;bgb
1357 JZ $$EN81
1358 mov dx,es ;since we move more than 64k total, we
1359 inc dx ;have to bump es by 1 para, keeping
1360 mov es,dx ;di at zero
1361; $ENDDO ;an005;bgb
1362 JMP SHORT $$DO81
1363$$EN81:
1364; $ELSE ;not enough memory ;an013;bgb
1365 JMP SHORT $$EN80
1366$$IF80:
1367 pop ax ;an013;bgb
1368 stc ;set carry flag indicating badddd!!! ;an013;bgb
1369; $ENDIF ;an013;bgb
1370$$EN80:
1371 return ;AN000;bgb ;an005;bgb
1372endproc fill_fat ;AN000;bgb ;an005;bgb
1373;
1374
1375;
1376
1377;*****************************************************************************
1378;*****************************************************************************
1379Procedure printerr,Near ;AN000;bgb
1380 push cs
1381 pop ds
1382 PUSH DX ; Save message pointer
1383 mov dl,[user_drive] ; restore old current drive
1384 mov ah,set_default_drive
1385 int 21h
1386 POP DX
1387 call display_interface ; AC000;bgb
1388 mov al,0ffh ; erc = 0xFF;
1389 ret ;AN000;bgb
1390endproc printerr ;AN000;bgb ;AN000;
1391
1392
1393;*************************************************************************
1394; CHK_FAT:
1395;
1396; inputs: AX - last fat number for a file
1397; CX - bytes per cluster
1398;*************************************************************************
1399Procedure chk_fat,Near ; ;AN000;bgb
1400 push es
1401step1a: mov filsiz,bp ;start the file size at 0
1402 mov word ptr filsiz+2,bp ;start the file size at 0
1403 mov dx,MaxClus ; dx = MaxClus;
1404 mov target,ax ; target = last fat in this file
1405 mov exit_sw2,bp ;false ; set exit switch to no
1406; $DO COMPLEX ; DO until exit ;AN000;bgb
1407 JMP SHORT $$SD86
1408$$DO86:
1409 mov target,ax ; do this 2+ times around
1410; $STRTDO ; START here 1st time ;AN000;bgb
1411$$SD86:
1412step2: add filsiz,cx ;add in cluster size
1413 adc word ptr filsiz+2,bp ;inc 2nd word if there was a carry
1414 mov ax,2 ;start at first cluster
1415; $DO ;DO until exit ;AN000;bgb
1416$$DO88:
1417Step3: call getfat ; bx= contents of fat cell
1418 cmp bx,target ; reached the end of file yet?
1419; $LEAVE E ; yes - return to outer loop;AN000;bgb
1420 JE $$EN88
1421step4: inc ax ; no - inc target
1422 cmp ax,dx ; target > max-clusters?
1423; $IF NBE ; yes ;AN000;bgb
1424 JBE $$IF90
1425 mov exit_sw2,true ; request exit both loops
1426; $ENDIF ; ;AN000;bgb
1427$$IF90:
1428 cmp exit_sw2,true ; exit requested?
1429; $ENDDO E ; $ENDDO if exit requested ;AN000;bgb
1430 JNE $$DO88
1431$$EN88:
1432endlop2: cmp exit_sw2,true ; outer loop test- exit requested?
1433; $ENDDO E ; ENDDO if exit requested ;AN000;bgb
1434 JNE $$DO86
1435 pop es ; else- go do mov target,ax
1436 ret ;AN000;bgb
1437endproc chk_fat ;AN000;bgb
1438
1439
1440;*****************************************************************************
1441;*****************************************************************************
1442 even
1443Procedure main_loop1,Near ;AN000;bgb
1444; $DO ;AN000;bgb
1445$$DO94:
1446 call read_fats ;inner loop AN000;bgb
1447 cmp exit_sw,true ; 1st way out of loop - fatptr>maxclus
1448; $LEAVE E ; goto step7 AN000;bgb
1449 JE $$EN94
1450 call chk_fat ; ended read_fats on carry from feof
1451; at this point target = head of list, filsiz = file size
1452step4a: inc filcnt ; filcnt++;
1453 mov ax,maxent ; if (filcnt > maxent)
1454 cmp filcnt,ax ; more files than possible dir entries?
1455; $IF A ; yes - this is an error ;AN000;bgb
1456 JNA $$IF96
1457direrr: dec filcnt
1458 lea dx,dirmsg ; ;AC000;bgb
1459 call display_interface ; ;an006;bgb
1460 mov exit_sw,true
1461; $ENDIF ;AN000;bgb
1462$$IF96:
1463nodirerr: cmp exit_sw,true
1464; $LEAVE E ;AN000;bgb
1465 JE $$EN94
1466 call fill_dir
1467 mov ax,fatptr
1468 cmp ax,MaxClus
1469; $LEAVE A ;AN000;bgb
1470 JA $$EN94
1471;ndlop1: $ENDDO ;AN000;bgb
1472endlop1:
1473 JMP SHORT $$DO94
1474$$EN94:
1475 ret ;AN000;bgb
1476endproc main_loop1 ; ;AN000;bgb
1477
1478
1479;*****************************************************************************
1480; purpose: this procedure looks at all the fats for a particular file, until
1481; the end of file marker is reached. then returns
1482; inputs: AX = fat cell number 2
1483; outputs: if any of the
1484;*****************************************************************************
1485Procedure read_fats,Near ;AN000;bgb
1486 push es
1487 mov filsiz,bp ;start the file size at 0 ;an027;bgb
1488 mov word ptr filsiz+2,bp ;start the file size at 0 ;an027;bgb
1489; $DO ;AN000;bgb
1490$$DO101:
1491step1: call getfat ; if (fEOF (GetFat (a)) {
1492 add filsiz,cx ;add in cluster size ;an027;bgb
1493 adc word ptr filsiz+2,bp ;inc 2nd word if there was a carry ;an027;bgb
1494 call fEOF ;
1495; $LEAVE C ; goto step1a AN000;bgb
1496 JC $$EN101
1497step6: inc fatptr ; if (++fatptr <= MaxClus)
1498 mov ax,fatptr
1499 cmp ax,MaxClus
1500; $IF A ;AN000;bgb
1501 JNA $$IF103
1502 mov exit_sw,true
1503; $ENDIF ;AN000;bgb
1504$$IF103:
1505 cmp exit_sw,true ; time to end? ;AN000;bgb
1506; $ENDDO E ; goto step7 ;AN000;bgb
1507 JNE $$DO101
1508$$EN101:
1509 pop es
1510 ret ;AN000;bgb
1511endproc read_fats ; ;AN000;bgb
1512
1513;*****************************************************************************
1514;*****************************************************************************
1515 even
1516Procedure fill_dir,Near ;AN000;bgb
1517 lea si,dirent+7 ; s = &dirent[7]; ;AC000;bgb
1518; $DO ;AN000;bgb
1519$$DO106:
1520nam0: inc byte ptr [si] ; while (++*s > '9')
1521 cmp byte ptr [si],'9'
1522; $LEAVE LE ;AN000;bgb
1523 JLE $$EN106
1524 mov byte ptr [si],'0' ; *s-- = '0';
1525 dec si
1526; $ENDDO ;AN000;bgb
1527 JMP SHORT $$DO106
1528$$EN106:
1529nam1: mov ah,GET_DATE ; dirent.dir_date = GetDate ();
1530 int 21h
1531 sub cx,1980 ; cx = 87
1532 add dh,dh ; dh = 1-12
1533 add dh,dh
1534 add dh,dh
1535 add dh,dh
1536 add dh,dh ; dh = dh * 32 (32-384)
1537 rcl cl,1
1538 or dh,dl
1539 mov byte ptr dirent+24,dh
1540 mov byte ptr dirent+25,cl
1541 mov ah,GET_TIME ; dirent.dir_time = GetTime ();
1542 int 21h
1543 shr dh,1 ;seconds/2
1544 add cl,cl ;minutes
1545 add cl,cl
1546 add cl,cl ;mins * 8
1547 rcl ch,1
1548 add cl,cl
1549 rcl ch,1
1550 add cl,cl
1551 rcl ch,1
1552 or dh,cl
1553 mov byte ptr dirent+22,dh
1554 mov byte ptr dirent+23,ch
1555 mov ax,filsiz ; dirent.dir_fsize = filsiz;
1556 mov word ptr dirent+28,ax
1557 mov ax,word ptr filsiz+2
1558 mov word ptr dirent+30,ax
1559 mov ax,target ; dirent.dir_firclus = target;
1560 mov word ptr dirent+26,ax
1561 lea si,dirent ; di:si --> directory entry ;an005;bgb
1562 mov cx,32 ;move 32 bytes - 1 dir entry ;an005;bgb
1563 rep movsb ;move ds:si to es:di, then ;an005;bgb
1564 ;inc di and inc si ;an005;bgb
1565 inc fatptr ; if (++fatptr <= MaxClus)
1566 ret ;AN000;bgb
1567endproc fill_dir ; ;AN000;bgb
1568;
1569;*****************************************************************************
1570; DRIVE_SPEC - this procedure is executed if the user only specifies a drive
1571; letter to recover.
1572;*****************************************************************************
1573Procedure drive_spec,Near ;AN000;bgb
1574recdsk: xor di,di ;init addr of dir/file area ;an005;bgb
1575 mov es,table ;es:di --> area ;an005;bgb
1576 ;this addr is incremented by the rep movsb in fill_dir ;an005;bgb
1577 mov fatptr,2 ;INIT FATPTR ; a = fatPtr = 2;
1578 mov ax,fatptr ;
1579 MOV exit_sw,bp ; false ; default to continue looping until true
1580 call main_loop1
1581step7: mov al,drive ;AN000;bgb
1582 mov dx,firdir ; write out constructed directory
1583 mov cx,firrec
1584 sub cx,dx
1585 xor bx,bx ;addr of dir area ;an005;bgb
1586 mov es,table ;seg of dir area ;an005;bgb
1587 call Write_Disk
1588; $IF NC ;good write? ;an015;bgb
1589 JC $$IF109
1590 lea dx,recmsg ; ;AC000;bgb
1591 mov si,filcnt
1592 mov rec_num,si
1593 call display_interface ; AC000;bgb
1594; $ENDIF ;an015;bgb
1595$$IF109:
1596rexit2: mov ah,DISK_RESET
1597 int 21h
1598 call wrtfat ; save the fat
1599; $IF C ;Couldn't write it ;AN000;bgb ;AN000;bgb
1600 JNC $$IF111
1601 lea dx,FATErrWrite ;Just tell user he is in deep! ; ;AC000;bgb
1602 call display_interface ; ;AN000;bgb
1603; $ENDIF ; ;AN000;bgb ;AN000;bgb
1604$$IF111:
1605 ret ;AN000;bgb
1606endproc drive_spec ; ;AN000;bgb
1607;
1608 pathlabl recover
1609
1610include msgdcl.inc
1611
1612code ends
1613 end ;recover ;AC000;bgb
1614
1615 \ No newline at end of file
diff --git a/v4.0/src/CMD/RECOVER/RECOVER.LNK b/v4.0/src/CMD/RECOVER/RECOVER.LNK
new file mode 100644
index 0000000..d990fbe
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECOVER.LNK
@@ -0,0 +1,6 @@
1recdisp+
2RECINIT+
3RECproc+
4RECover
5RECOVER.EXE,RECOVER.MAP ;
6 \ No newline at end of file
diff --git a/v4.0/src/CMD/RECOVER/RECOVER.SKL b/v4.0/src/CMD/RECOVER/RECOVER.SKL
new file mode 100644
index 0000000..ee8fcdf
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECOVER.SKL
@@ -0,0 +1,29 @@
1;RECOVER Utility
2;Message Service Routine
3
4:util RECOVER ;BEGIN UTIL
5
6:class A ;EXTENDED ERRORS
7;------- ---------------
8:def 2 CR,LF,"File not found",CR,LF ;File not found
9
10
11 ;COMMON & DEFINED MSGS
12;------- ------------
13:def 3 CR,LF,"Cannot RECOVER an ASSIGNED or SUBST'd drive",CR,LF
14:def 4 CR,LF,"Invalid drive or file name",CR,LF
15:def 5 CR,LF,"Warning - directory full",CR,LF
16
17:def 6 CR,LF,"Cannot RECOVER a Network Drive", CR,LF ;Cannot %1 a Network drive
18;:def 7 CR,LF,"Recover not available on drive %1",CR,LF
19:def 8 CR,LF,"%1 file(s) recovered",CR,LF
20:def 9 CR,LF,"%1 of %2 bytes recovered",CR,LF
21
22;:use COMMON28 ;Press any key... ;AC000;bgb
23:def 10 CR,LF,"Press any key to begin recovery of the",CR,LF,"file(s) on drive %1",CR,LF,CR,LF ;AN000;bgb
24:def 11 CR,LF,"Can not read file allocation table",CR,LF
25:def 12 CR,LF,"Can not write file allocation table",CR,LF
26:def 13 CR,LF
27:use 14 extend8 ;insufficent memory ;an013;bgb
28:end ;END UTIL
29 \ No newline at end of file
diff --git a/v4.0/src/CMD/RECOVER/RECPARSE.INC b/v4.0/src/CMD/RECOVER/RECPARSE.INC
new file mode 100644
index 0000000..dbe4712
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECPARSE.INC
@@ -0,0 +1,177 @@
1
2const segment public para 'const' ;AC000;bgb
3;***************************************************************************
4; Equates
5;***************************************************************************
6;
7;Match Flags
8Numeric_Value equ 8000h ; AN000
9Signed_Numeric_Value equ 4000h ; AN000
10Simple_String equ 2000h ; AN000
11Date_String equ 1000h ; AN000
12Time_String equ 0800h ; AN000
13Complex_List equ 0400h ; AN000
14Filespec equ 0200h ; AN000
15Drive_Only equ 0100h ; AN000
16Quoted_String equ 0080h ; AN000
17Ignore_Colon equ 0010h ; AN000
18Repeats_Allowed equ 0002h ; AN000
19Optional equ 0001h ; AN000
20
21;Function_Flags
22
23File_Table_Capitalize equ 1 ; AN000
24Char_Table_Capitalize equ 2 ; AN000
25Remove_Colon equ 10h ; AN000
26
27;Extra delimeters and EOL
28
29No_Extra_Delimiters equ 00h ; AN000;SM
30Delimiters_Only equ 1 ; AN000
31EOL_Or_Delimiters equ 2 ; AN000
32
33Semi_Colon equ ";" ; AN000
34Tab equ 09h ; AN000
35Colon equ ":" ; AN000
36
37
38;Parse Errors
39
40No_Error equ 0 ; AN000
41Too_Many_Operands equ 1 ; AN000
42Operand_Missing equ 2 ; AN000
43Not_In_Switch_List equ 3 ; AN000
44Not_In_Keyword_List equ 4 ; AN000
45Out_Of_Range equ 6 ; AN000
46Not_In_Value_List equ 7 ; AN000
47Not_In_String_List equ 8 ; AN000
48Syntax_Error equ 9 ; AN000
49End_Of_Parse equ -1 ; AN000
50
51;Return types
52
53Type_Reserved equ 0 ; ;AN000;
54Type_Number equ 1 ; ;AN000;
55Type_List_Index equ 2 ; ;AN000;
56Type_String equ 3 ; ;AN000;
57Type_Complex equ 4 ; ;AN000;
58Type_Filespec equ 5 ; ;AN000;
59Type_Drive equ 6 ; ;AN000;
60Type_Date equ 7 ; ;AN000;
61Type_Time equ 8 ; ;AN000;
62Type_Quoted_String equ 9 ; ;AN000;
63
64
65;Other
66
67None equ 0 ; AN000
68No_Error equ 0 ; AN000
69Switch_Found equ 0FFFFh ; AN000
70Range_Ok equ 1 ; AN000
71Command_Line_Parms equ 81h ; AN000
72const ends ;AC000;bgb
73
74data segment public para 'DATA' ;AC000;bgb
75;***************************************************************************** ;AN000;bgb
76;***************************************************************************** ;AN000;bgb
77; Parse Tables ;AN000;bgb
78;***************************************************************************** ;AN000;bgb
79;***************************************************************************** ;AN000;bgb
80; ;AN000;bgb
81;The following parse control block can be used for any command which ;AN000;bgb
82;needs only one optional file specification an operand. Returns a ;AN000;bgb
83;pointer to the unverified string in PARSE1_OUTPUT. Currently used ;AN000;bgb
84;for the RECOVER command. ;AN000;bgb
85;***************************************************************************** ;AN000;bgb
86;;;;db 'PARSE TABLE AREA' ;AN000;bgb
87 public parms_input_block, parms_ext_block, control_block, value_list_block
88 public results_block, parse_type, parse_code, parse_addr,
89 ;AN000;bgb
90;***************************************************************************** ;AN000;bgb
91; This is the parms input block pointed to by es:di before calling sysparse. ;AN000;bgb
92; it is the top level table. ;AN000;bgb
93parms_input_block LABEL BYTE ;AN000;bgb
94 DW dg:parms_ext_block ; addr of parms extension block ;AN000;bgb
95 DB 0 ; no delimiters or eol chars ;AN000;bgb
96 ;AN000;bgb
97;***************************************************************************** ;AN000;bgb
98; This is the parms extension block pointed to by the parms input block. ;AN000;bgb
99; it defines the number and type of parameters allowed in the command line. ;AN000;bgb
100parms_ext_block LABEL BYTE ;AN000;bgb
101 DB 1,1 ; only one positional parm ;AN000;bgb
102 DW dg:control_block ; addr of positional control block ;AN000;bgb
103 DB 0 ; no switches ;AN000;bgb
104 DB 0 ; no keywords ;AN000;bgb
105; ;AN000;bgb
106;PARSE control block for an optional file specification (upper cased) ;AN000;bgb
107;or drive number ;AN000;bgb
108; ;AN000;bgb
109;***************************************************************************** ;AN000;bgb
110; This is the control block for either drive letter "c:", or filename.ext, or ;AN000;bgb
111; both "c:filename.ext" entered in the command line. it is pointed to by the ;AN000;bgb
112; parms extension block. ;AN000;bgb
113control_block LABEL BYTE ;AN000;bgb
114 Dw $p_file_spc+$p_drv_only ; allowable return values ;AN000;bgb
115 ; 0200 = filespec ;AN000;bgb
116 ; 0100 = drive only ;AN000;bgb
117 DW 1 ; capitalize - file table ;AN000;bgb
118 DW dg:results_block ; points to reults block ;AN000;bgb
119 DW dg:value_list_block ; point to valu list block ;AN000;bgb
120 DB 0 ; no keyword synonyms ;AN000;bgb
121; ;AN000;bgb
122;Indicates no value list for PARSE. ;AN000;bgb
123;***************************************************************************** ;AN000;bgb
124; This is the value list block pointed to by the control block. This table is ;AN000;bgb
125; used to define the type of numeric or string parameters expected. Since no ;AN000;bgb
126; parameters with numerics or strings are used, this block is set to zero. ;AN000;bgb
127value_list_block DW 0 ;AN000; no values ;AN000;bgb
128 ;AN000;bgb
129; ;AN000;bgb
130;Common output blocks for PARSE number, complex, or string values. ;AN000;bgb
131;***************************************************************************** ;AN000;bgb
132; This is the results block pointed to by the control block. ;AN000;bgb
133; both "c:filename.ext" entered in the command line. it is pointed to by the ;AN000;bgb
134; parms extension block. ;AN000;bgb
135results_block LABEL BYTE ;AN000; ;AN000;bgb
136PARSE_TYPE DB 0 ; type of parm returned ;AN000;bgb
137PARSE_CODE DB 0 ; matched item tag / return valu ;AN000;bgb
138PARSE_SYN DW 0 ; es offset of synonym ;AN000;bgb
139PARSE_ADDR DD 0 ; either a numeric value, or ;AN000;bgb
140 dd 0 ;parser puts in too many;the offset of string value ;AN000;bgb
141
142;;;;DB 'PARSE AREA ENDS'
143data ends ;AN000;bgb
144 ;AN000;bgb
145; ;AN000;
146code segment PUBLIC para 'CODE' ;AC000;bgb ;AN000;
147;***************************************************************************** ;AN000;
148; SysParse Routines ;AN000;
149;***************************************************************************** ;AN000;
150FarSW equ Not_Include ; ;AN000;
151DateSW equ Not_Include ; ;AN000;
152TimeSW equ Not_Include ; ;AN000;
153FileSW equ Do_Include ; ;AN000;
154CAPSW equ Not_Include ; ;AN000;
155CmpxSW equ Not_Include ; ;AN000;
156NumSW equ Not_Include ; ;AN000;
157KeySW equ Not_Include ; ;AN000;
158SwSW equ Not_Include ; ;AN000;
159Val1SW equ Not_Include ; ;AN000;
160Val2SW equ Not_Include ; ;AN000;
161Val3SW equ Not_Include ; ;AN000;
162DrvSW equ Do_Include ; ;AN000;
163QusSW equ Not_Include ;
164basesw equ 1 ;use ds as the default register ;an040;bgb
165incsw equ 0 ;include psdata myself ;an040;bgb
166code ends ;an040;bgb
167 ;an040;bgb
168 ;an040;bgb
169data segment PUBLIC para 'DATA' ;an040;bgb
170include psdata.inc ;an040;bgb
171data ends ;an040;bgb
172 ;an040;bgb
173code segment PUBLIC para 'CODE' ;an040;bgb
174pathlabl parser ;an040;bgb
175INCLUDE PARSE.ASM ;AN000; ;an040;bgb
176pathlabl parser ;an040;bgb
177code ends ;an040;bgb
diff --git a/v4.0/src/CMD/RECOVER/RECPROC.ASM b/v4.0/src/CMD/RECOVER/RECPROC.ASM
new file mode 100644
index 0000000..28066bf
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECPROC.ASM
@@ -0,0 +1,531 @@
1page ,132 ;
2TITLE RECPROC.SAL
3;*****************************************************************************
4; Include files
5;*****************************************************************************
6.xlist
7 include recseg.inc ;AN000;bgb
8 include dossym.inc ;AN000;bgb
9 INCLUDE SYSCALL.INC ;AN000;bgb
10 INCLUDE RECMACRO.INC ;AN000;bgb
11 include recequ.inc ;AN000;bgb
12 include pathmac.inc
13.xcref
14BREAK MACRO subtitle
15 SUBTTL subtitle
16 PAGE
17ENDM
18.cref
19;
20;*****************************************************************************
21; Extrn Declarations
22;*****************************************************************************
23data segment PUBLIC para 'DATA' ;AC000;bgb
24 EXTRN secs_per_64k:word
25 EXTRN paras_per_fat:word
26 EXTRN paras_per_64k:word
27 EXTRN bytes_per_sector:word
28 EXTRN sec_count:word
29 EXTRN OFMSG_PTR:WORD
30 EXTRN y_value_lo:WORD ;AN000;bgb
31 EXTRN y_value_hi:WORD ;AN000;bgb ; AC000;SM
32 EXTRN x_value_lo:WORD ;AN000;bgb ; AC000;SM
33 EXTRN x_value_hi:WORD ;AN000;bgb ; AC000;SM
34 EXTRN dbcs_vector:byte ;AN000;bgb ; AC000;SM
35 EXTRN dbcs_vector_off:word ;AN000;bgb ; AC000;SM
36 EXTRN dbcs_vector_seg:word ;AN000;bgb ; AC000;SM
37 EXTRN filsiz:WORD ;AN000;bgb
38 EXTRN read_write_relative:byte ;AN000;bgb
39data ends ;AC000;bgb
40
41;*****************************************************************************
42; recproc procedures
43;*****************************************************************************
44code segment public para 'CODE' ;AC000;bgb
45 pathlabl recproc
46public report ;AN000;bgb
47public Read_Disk ;AN000;bgb
48public Write_Disk ;AN000;bgb
49public Build_String ;AN000;bgb
50public ChANge_BlANks ;AN000;bgb
51public Check_DBCS_CharACter ;AN000;bgb
52.list
53
54;******************************************
55; Prints the XXX of YYY bytes recovered message.
56; The XXX value is a dword at di+16 on entry.
57; The YYY value is a dword (declared as a word) at filsiz.
58;*************************************************************
59Procedure report,near ; ;AN000;bgb
60 lea dx,ofmsg_ptr
61 mov si,[di+16] ;Get the XXX value
62 mov x_value_lo,si
63 mov di,[di+18]
64 mov x_value_hi,di
65 mov si,filsiz ;Get the YYY value
66 mov y_value_lo,si
67 mov di,filsiz+2
68 mov y_value_hi,di
69 call display_interface ; AC000;SM
70 ret
71report endp
72
73;========================================================================= ;an005;bgb
74; READ_DISK : This routine reads the logical sector count requested. ;an005;bgb
75; It will read a maximum of 64k in one read. If more ;an005;bgb
76; than 64k exists it will continue looping until ;an005;bgb
77; all sectors have been read. ;an005;bgb
78; ;an005;bgb
79; Inputs : AL - Drive letter ;an005;bgb
80; ES:BX - Segment:offset of transfer address ;an005;bgb
81; CX - Sector count ;an005;bgb
82; DX - 1st sector ;an005;bgb
83; ;an005;bgb
84; Outputs : Logical sectors read ;an005;bgb
85; LOGIC ;an005;bgb
86; ***** ;an005;bgb
87; adjust es:bx to es:00 ;an005;bgb
88; calcluate sectors-per-64k (how many sectors are there that can fit within a 64k segment?)
89; DO while there are more sectors to read than sectors-per-64k ;an005;bgb
90; set sector-count to sectors-per-64k ;an005;bgb
91; perform the disk read ;an005;bgb
92; bump the seg addr to the new addr ;an005;bgb
93; dec the number of sectors to read by sectors-per-64k ;an005;bgb
94; bump the starting sector number by the sectors-per-64k ;an005;bgb
95; ENDDO ;an005;bgb
96; perform a disk read for less than sectors-per-64k ;an005;bgb
97;========================================================================= ;an005;bgb
98procedure read_disk ;an005;bgb
99 savereg <ax,bx,cx,dx,es>
100 call seg_adj ;an000;calc new seg:off ;an005;bgb
101 call calc_sp64k ;an000;secs/64k ;an005;bgb
102; $DO ; do while more than 64k ;an005;bgb
103$$DO1:
104 cmp cx,secs_per_64k ;an000;exceed 64k ;an005;bgb
105; $LEAVE LE ;an000;yes ;an005;bgb
106 JLE $$EN1
107 mov sec_count,cx ;an000;save cx ;an005;bgb
108 mov cx,secs_per_64k ;an000;get maximum read ;an005;bgb
109 call read_once ;an000;read it ;an005;bgb
110; $LEAVE C ;an005;bgb
111 JC $$EN1
112 mov cx,es ;an005;bgb
113 add cx,paras_per_64k ; adjust transfer area ;an005;bgb
114 mov es,cx ;an005;bgb
115 mov cx,sec_count ; restore sector count ;an005;bgb
116 sub cx,secs_per_64k ;an000;get sectors remaining ;an005;bgb
117 add dx,secs_per_64k ;an000;adjust starting sector ;an005;bgb
118; $ENDDO ;an005;bgb
119 JMP SHORT $$DO1
120$$EN1:
121 call read_once ;an000;read it ;an005;bgb
122 restorereg <es,dx,cx,bx,ax>
123 ret ;an005;bgb
124read_disk endp ;an005;bgb
125 ;an005;bgb
126 ;an005;bgb
127;***************************************************************************** ;an005;bgb
128;Routine name: Read_once ;an005;bgb
129;***************************************************************************** ;an005;bgb
130; ;an005;bgb
131;description: Read in data using Generic IOCtl ;an005;bgb
132; ;an005;bgb
133;Called Procedures: None ;an005;bgb
134; ;an005;bgb
135; ;an005;bgb
136;Change History: Created 5/13/87 MT ;an005;bgb
137; ;an005;bgb
138;Input: AL = Drive number (0=A) ;an005;bgb
139; DS:BX = Transfer address ;an005;bgb
140; CX = Number of sectors ;an005;bgb
141; Read_Write_Relative.Start_Sector_High = Number of sectors high ;an005;bgb
142; DX = logical sector number low ;an005;bgb
143; ;an005;bgb
144;Output: CY if error ;an005;bgb
145; AH = INT 25h error code ;an005;bgb
146; ;an005;bgb
147;Psuedocode ;an005;bgb
148;---------- ;an005;bgb
149; Save registers ;an005;bgb
150; Setup structure for function call ;an005;bgb
151; Read the disk (AX=440Dh, CL = 6Fh) ;an005;bgb
152; Restore registers ;an005;bgb
153; ret ;an005;bgb
154;***************************************************************************** ;an005;bgb
155Procedure Read_once ; ;an005;bgb
156 savereg <ax,bx,cx,dx,si,di,bp,es,ds> ;Change it to Read relative sect;an005;bgb
157 mov Read_Write_Relative.Buffer_Offset,bx ;Get transfer buffer add ;an005;bgb
158 mov bx,es ; ;AN005;bgb
159 mov Read_Write_Relative.Buffer_Segment,bx ;Get segment ;an005;bgb
160 mov Read_Write_Relative.Number_Sectors,cx ;Number of sec to read ;an005;bgb
161 mov Read_Write_Relative.Start_Sector_Low,dx ;Start sector ;an005;bgb
162 mov bx,offset Read_Write_Relative ; ;an005;bgb
163 mov cx,0FFFFh ;Read relative sector ;an005;bgb
164 INT 25h ;Do the read ;an005;bgb
165 pop dx ;Throw away flags on stack ;an005;bgb
166 restorereg <ds,es,bp,di,si,dx,cx,bx,ax> ;an005;bgb
167 return ;an005;bgb
168 Read_once endp ;an005;bgb
169 ;an005;bgb
170 ;an005;bgb
171;========================================================================= ;an005;bgb
172; WRITE-DISK : This routine reads the logical sector count requested. ;an005;bgb
173; It will read a maximum of 64k in one read. If more ;an005;bgb
174; than 64k exists it will continue looping until ;an005;bgb
175; all sectors have been read. ;an005;bgb
176; ;an005;bgb
177; Inputs : AL - Drive letter ;an005;bgb
178; ES:BX - Segment:offset of transfer address ;an005;bgb
179; CX - Sector count ;an005;bgb
180; DX - 1st sector ;an005;bgb
181; ;an005;bgb
182; Outputs : Logical sectors read ;an005;bgb
183; LOGIC ;an005;bgb
184; ***** ;an005;bgb
185; adjust es:bx to es:00 ;an005;bgb
186; calcluate sectors-per-64k (how many sectors are there that can fit within a 64k segment?)
187; DO while there are more sectors to read than sectors-per-64k ;an005;bgb
188; set sector-count to sectors-per-64k ;an005;bgb
189; perform the disk read ;an005;bgb
190; bump the seg addr to the new addr ;an005;bgb
191; dec the number of sectors to read by sectors-per-64k ;an005;bgb
192; bump the starting sector number by the sectors-per-64k ;an005;bgb
193; ENDDO ;an005;bgb
194; perform a disk read for less than sectors-per-64k ;an005;bgb
195;========================================================================= ;an005;bgb
196procedure write_disk ;an005;bgb
197 mov Read_Write_Relative.Start_Sector_High,bp; ;;an027;bgb;an023;bgb
198 call seg_adj ;an000;calc new seg:off ;an005;bgb
199; $DO ; do while more than 64k ;an005;bgb
200$$DO5:
201 cmp cx,secs_per_64k ;an000;exceed 64k ;an005;bgb
202; $LEAVE LE ;an000;yes ;an005;bgb
203 JLE $$EN5
204 mov sec_count,cx ;an000;save cx ;an005;bgb
205 mov cx,secs_per_64k ;an000;get maximum read ;an005;bgb
206 call write_once ;an000;read it ;an005;bgb
207; $LEAVE C ;an005;bgb
208 JC $$EN5
209 mov cx,es ;an005;bgb
210 add cx,paras_per_64k ; adjust transfer area ;an005;bgb
211 mov es,cx ;an005;bgb
212 mov cx,sec_count ; restore sector count ;an005;bgb
213 sub cx,secs_per_64k ;an000;get sectors remaining ;an005;bgb
214 add dx,secs_per_64k ;an000;adjust starting sector ;an005;bgb
215; $ENDDO ;an005;bgb
216 JMP SHORT $$DO5
217$$EN5:
218 call write_once ;an000;read it ;an005;bgb
219 ret ;an005;bgb
220write_disk endp ;an005;bgb
221 ;an005;bgb
222;*****************************************************************************
223;Routine name: Write_Once
224;*****************************************************************************
225;
226;description: Write Data using int 26
227;
228;Called Procedures: None
229;
230;
231;Change History: Created 5/13/87 MT
232;
233;Input: AL = Drive number (0=A)
234; DS:BX = Transfer address
235; CX = Number of sectors
236; Read_Write_Relative.Start_Sector_High = Number of sectors high
237; DX = logical sector number low
238;
239;Output: CY if error
240; AH = INT 26h error code
241;
242;Psuedocode
243;----------
244; Save registers
245; Setup structure for function call
246; Write to disk (AX=440Dh, CL = 4Fh)
247; Restore registers
248; ret
249;*****************************************************************************
250Procedure Write_once ; ;AN000;bgb
251 savereg <ax,bx,cx,dx,di,si,bp,es,ds> ;This is setup for INT 26h right;AN000;bgb
252 mov Read_Write_Relative.Buffer_Offset,bx ;Get transfer buffer add ;AN000;bgb
253 mov bx,es ; ;AN005;bgb
254 mov Read_Write_Relative.Buffer_Segment,bx ;Get segment ;AN000;bgb
255 mov Read_Write_Relative.Number_Sectors,cx ;Number of sec to write ;AN000;bgb
256 mov Read_Write_Relative.Start_Sector_Low,dx ;Start sector ;AN000;bgb
257 mov cx,0FFFFh ;Write relative sector ;AN000;bgb
258 lea bx,read_write_relative ;
259 INT 026h ;Do the write ;AN000;bgb
260 pop dx ;flags is returned on the stack;AN000;bgb
261 restorereg <ds,es,bp,si,di,dx,cx,bx,ax> ; ;AN000;bgb
262 ret ; ;AN000;bgb
263Write_once endp ; ;AN000;bgb
264
265;========================================================================= ;an005;bgb
266; SEG_ADJ : This routine adjusts the segment:offset to prevent ;an005;bgb
267; address wrap. ;an005;bgb
268; ;an005;bgb
269; Inputs : bx - Offset to adjust segment with ;an005;bgb
270; es - Segment to be adjusted ;an005;bgb
271; ;an005;bgb
272; Outputs : bx - New offset ;an005;bgb
273; es - Adjusted segment ;an005;bgb
274;========================================================================= ;an005;bgb
275procedure seg_adj ;an005;bgb
276 savereg <ax,cx,dx> ;an005;bgb
277 mov ax,bx ;an000;get offset ;an005;bgb
278 mov bx,0010h ;divide by 16 ;an005;bgb
279 xor dx,dx ;an000;clear dx ;an005;bgb
280 div bx ;an000;get para count ;an005;bgb
281 mov bx,es ;an000;get seg ;an005;bgb
282 add bx,ax ;an000;adjust for paras ;an005;bgb
283 mov es,bx ;an000;save new seg ;an005;bgb
284 mov bx,dx ;an000;new offset ;an005;bgb
285 restorereg <dx,cx,ax> ;an005;bgb
286 ret ;an005;bgb
287seg_adj endp ;an005;bgb
288 ;an005;bgb
289 ;an005;bgb
290;========================================================================= ;an005;bgb
291; SECS_PER_64K : This routine calculates how many sectors, for this ;an005;bgb
292; particular media, will fit into 64k. ;an005;bgb
293; ;an005;bgb
294; Inputs : DPB_SECTOR_SIZE - bytes/sector ;an005;bgb
295; ;an005;bgb
296; Outputs : SECS_PER_64K - Sectors / 64k ;an005;bgb
297; PARAS_PER_64K - paragraphs per 64k ;an005;bgb
298;========================================================================= ;an005;bgb
299procedure calc_sp64k ;an005;bgb
300 savereg <ax,bx,cx,dx> ;an005;bgb
301 mov ax,0ffffh ;an000;64k ;an005;bgb
302 mov bx,bytes_per_sector ;an000;get bytes/sector ;an005;bgb
303 xor dx,dx ;an000;clear dx ;an005;bgb
304 div bx ;an000;sector count ;an005;bgb
305 mov secs_per_64k,ax ;an000;save sector count ;an005;bgb
306 mov ax,bytes_per_sector ;an000;get bytes/sector ;an005;bgb
307 mov bx,010h ; divide by paras ;an005;bgb
308 xor dx,dx ;an000;clear dx ;an005;bgb
309 div bx ; paras per sector ;an005;bgb
310 mul secs_per_64k ; times sectors ;an005;bgb
311 mov paras_per_64k,ax ; = paras per 64k ;an005;bgb
312 restorereg <dx,cx,bx,ax> ;an000;restore dx ;an005;bgb
313 ret ;an000; ;an005;bgb
314calc_sp64k endp ;an000; ;an005;bgb
315
316
317;*****************************************************************************
318;Routine name: Build_String
319;*****************************************************************************
320;
321;Description: Build AN ASCIIZ string from the FCB filename input.
322;
323;Called Procedures: None
324;
325;ChANge History: Created 6/29/87 MT
326;
327;Input: DS:SI = String containing FCB input
328; ES:DI = Where to build string
329;
330;Output: ES:DI = Input string starting at first non-blANk charACter
331;
332;Psuedocode
333;----------
334;
335; Save regs
336; DO
337; LEAVE Next charACter is 0,OR
338; LEAVE 12th charACter,OR
339; Get charACter
340; LEAVE BlANk
341; Inc counter
342; ENDDO
343; Set next charACter to 0
344; Restore regs
345;
346;*****************************************************************************
347
348Procedure Build_String ; ;AN000;
349 cld ;Set string ops to up ;AN000;
350 push ax ;Save registers ;AN000;
351 push cx ; " " " " ;AN000;
352 push si ;Save pointer reg ;AN000;
353 xor cx,cx ;Init the counter ;AN000;
354; $DO ;Loop until entire string found ;AN000;
355$$DO9:
356 cmp byte ptr [si],ASCIIZ_END ;Is next charACter 0? ;AN000;
357; $LEAVE E,OR ;Yes, end loop ;AN000;
358 JE $$EN9
359 cmp cx,FCB_Filename_Length ;Looked at 11 chars? ;AN000;
360; $LEAVE E,OR ;Yes, end of string ;AN000;
361 JE $$EN9
362 lodsb ;Nope, get charACter ;AN000;
363 cmp al,BlANk ;Find end of filename? ;AN000;
364; $LEAVE E ;Yes, quit looping ;AN000;
365 JE $$EN9
366 stosb ;Move the char
367 inc cx ;No, inc counter ANd try next ;AN000;
368; $ENDDO ; ;AN000;
369 JMP SHORT $$DO9
370$$EN9:
371 mov byte ptr [di],ASCIIZ_END ;Make ASCIIZ string ;AN000;
372 pop si ;Get bACk pointer to string ;AN000;
373 pop cx ;Restore regsisters ;AN000;
374 pop ax ; " " " " ;AN000;
375 ret ; ;AN000;
376Build_String endp ; ;AN000;
377
378;*****************************************************************************
379;Routine name: ChANge_BlANks
380;*****************************************************************************
381;
382;Description: ReplACe all DBCS blANks with SBCS blANks
383;
384;Called Procedures: Check_DBCS_CharACter
385;
386;ChANge History: Created 6/12/87 MT
387;
388;Input: DS:SI = ASCIIZ string containing volume label input
389;
390;Output: DS:SI = ASCIIZ string with all DBCS blANks replACed with 2 SBCS blANks
391;
392;
393;Psuedocode
394;----------
395;
396; Save pointer to string
397; DO
398; LEAVE End of string (0)
399; See if DBCS charACter (Check_DBCS_CharACter)
400; IF CY (DBCS char found)
401; IF first byte DBCS blANk, AND
402; IF second byte DBCS blANk
403; Convert to SBCS blANks
404; ENDIF
405; Point to next byte to compensate for DBCS charACter
406; ENDIF
407; ENDDO
408; Restore pointer to string
409;
410;*****************************************************************************
411Procedure ChANge_BlANks ; ;AN000;
412; $DO ;Do while not CR ;AN000;
413$$DO12:
414 cmp byte ptr [si],Asciiz_End ;Is it end of string? ;AN000;
415; $LEAVE E ;All done if so ;AN000;
416 JE $$EN12
417 call Check_DBCS_CharACter ;Test for dbcs lead byte ;AN000;
418; $IF C ;We have a lead byte ;AN000;
419 JNC $$IF14
420 cmp byte ptr [si],DBCS_Lead ;Is it a lead blANk? ;AN000;
421; $IF E,AND ;If a dbcs char ;AN000;
422 JNE $$IF15
423 cmp byte ptr [si+1],DBCS_BlANk ;Is it AN AsiAN blANk? ;AN000;
424; $IF E ;If AN AsiAN blANk ;AN000;
425 JNE $$IF15
426 mov byte ptr [si+1],BlANk ;set up moves ;AN000;
427 mov byte ptr [si],BlANk ; to replACe ;AN000;
428; $ENDIF ; ;AN000;
429$$IF15:
430 inc si ;Point to dbcs char ;AN000;
431; $ENDIF ;End lead byte test ;AN000;
432$$IF14:
433 inc si ;Point to si+1 ;AN000;
434; $ENDDO ;End do while ;AN000;
435 JMP SHORT $$DO12
436$$EN12:
437 ret ;return to caller ;AN000;
438ChANge_BlANks endp ; ;AN000;
439
440
441;*****************************************************************************
442;Routine name: Check_DBCS_CharACter
443;*****************************************************************************
444;
445;Description: Check if specified byte is in rANges of DBCS vectors
446;
447;Called Procedures: None
448;
449;ChANge History: Created 6/12/87 MT
450;
451;Input: AL = CharACter to check for DBCS lead charACter
452; DBCS_Vector = YES/NO
453;
454;Output: CY set if DBCS charACter
455; DBCS_VECTOR = YES
456;
457;
458;Psuedocode
459;----------
460; Save registers
461; IF DBCS vector not found
462; Get DBCS environmental vector (INT 21h
463; Point at first set of vectors
464; ENDIF
465; SEARCH
466; LEAVE End of DBCS vectors
467; EXITIF CharACter > X1,AND (X1,Y1) are environment vectors
468; EXITIF CharACter < Y1
469; STC (DBCS charACter)
470; ORELSE
471; Inc pointer to next set of vectors
472; ENDLOOP
473; CLC (Not DBCS charACter)
474; ENDSRCH
475; Restore registers
476; ret
477;*****************************************************************************
478Procedure Check_DBCS_CharACter ; ;AN000;
479 push ds ;Save registers ;AN000;
480 push si ; " " " " ;AN000;
481 push ax ; " " " " ;AN000;
482 push ds ; " " " " ;AN000;
483 pop es ;Establish addressability ;AN000;
484 cmp byte ptr es:DBCS_VECTOR,Yes ;Have we set this yet? ;AN000;
485 push ax ;Save input charACter ;AN000;
486; $IF NE ;Nope ;AN000;
487 JE $$IF19
488 mov al,0 ;Get DBCS environment vectors ;AN000;
489 DOS_Call Hongeul ; " " " " ;AN000;
490 mov byte ptr es:DBCS_VECTOR,YES ;Indicate we've got vector ;AN000;
491 mov es:DBCS_Vector_Off,si ;Save the vector ;AN000;
492 mov ax,ds ; ;AN000;
493 mov es:DBCS_Vector_Seg,ax ; ;AN000;
494; $ENDIF ; for next time in ;AN000;
495$$IF19:
496 pop ax ;Restore input charACter ;AN000;
497 mov si,es:DBCS_Vector_Seg ;Get saved vector pointer ;AN000;
498 mov ds,si ; ;AN000;
499 mov si,es:DBCS_Vector_Off ; ;AN000;
500; $SEARCH ;Check all the vectors ;AN000;
501$$DO21:
502 cmp word ptr ds:[si],End_Of_Vector ;End of vector table? ;AN000;
503; $LEAVE E ;Yes, done ;AN000;
504 JE $$EN21
505 cmp al,ds:[si] ;See if char is in vector ;AN000;
506; $EXITIF AE,AND ;If >= to lower, ANd ;AN000;
507 JNAE $$IF21
508 cmp al,ds:[si+1] ; =< thAN higher rANge ;AN000;
509; $EXITIF BE ; then DBCS charACter ;AN000;
510 JNBE $$IF21
511 stc ;Set CY to indicate DBCS ;AN000;
512; $ORELSE ;Not in rANge, check next ;AN000;
513 JMP SHORT $$SR21
514$$IF21:
515 add si,DBCS_Vector_Size ;Get next DBCS vector ;AN000;
516; $ENDLOOP ;We didn't find DBCS char ;AN000;
517 JMP SHORT $$DO21
518$$EN21:
519 clc ;Clear CY for exit ;AN000;
520; $ENDSRCH ; ;AN000;
521$$SR21:
522 pop ax ;Restore registers ;AN000;
523 pop si ; " " " " ;AN000;
524 pop ds ;Restore data segment ;AN000;
525 ret ; ;AN000;
526Check_DBCS_CharACter endp ; ;AN000;
527
528 pathlabl recproc
529code ends
530 end
531 \ No newline at end of file
diff --git a/v4.0/src/CMD/RECOVER/RECPUB.INC b/v4.0/src/CMD/RECOVER/RECPUB.INC
new file mode 100644
index 0000000..79457b5
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECPUB.INC
@@ -0,0 +1,47 @@
1;
2data segment public para 'DATA' ;AC000;bgb
3;******************************************************************************
4; Public Data
5;******************************************************************************
6 public header, prompted, hardch, the_root, fudge, user_drive, drive, dirchar ;AN000;bgb
7 public userdir, fname_buffer, found, done, driveletter, psp_segment, exitstatus ;AN000;bgb
8 public drvlet, bpb_buffer, transrc, data_start_low, data_start_high, ;AN000;bgb
9 public int_23_old_off, int_23_old_seg, int_24_old_off, int_24_old_seg, append ;AN000;bgb
10 public command_line_buffer, command_line_length, fatal_error, command_line, ;AN000;bgb
11 public fs_string_buffer, fs_string_end, len_fs_string_end, fs_not_fat, ;AN000;bgb
12 public fat12_string, fat16_string, len_fs_id_string, media_id_buffer, ;AN000;bgb
13 public dirent, fcb_copy, filcnt, fatcnt, fatnum, fatsiz, firfat, fatptr ;AN000;bgb
14 public secall, target, maxent, firrec, firdir, secsiz, siztmp, filsiz, maxclus ;AN000;bgb
15 public lastfat, table, fattbl, dbcs_vector, dbcs_vector_off, dbcs_vector_seg ;AN000;bgb
16 public read_write_relative, exec_block, exec_path, drive_letter_msg, path_string ;AN000;bgb
17 public len_path_string, search_recover, len_search_recover, search_recover_end ;AN000;bgb
18 public drvlet1, rec_num, x_value_lo, x_value_hi, y_value_lo, y_value_hi
19 public bytes_per_sector, exit_sw, exit_sw2, paras_per_fat
20data ends ;put this 1st so that the recmsg works
21;
22;
23;*****************************************************************************
24; Public Data
25;*****************************************************************************
26; Public drvlet
27; Public rec_num
28; Public x_value_lo
29; Public x_value_hi
30; Public y_value_lo
31; Public y_value_hi
32; Public DrvLet1
33;public drive_sublist ;AN000;bgb
34;public path_si, env_ds
35; Public FS_String_Buffer
36; Public Fatal_Error
37; Public ExitStatus
38; public call_pars
39; PUBLIC INT_23,std_printf, ; AC000;SM
40; Public Read_Write_Relative
41; PUBLIC filsiz
42; PUBLIC FATTbl
43; Public User_Drive
44; Public Fname_Buffer
45; PUBLIC Write_Disk,Read_Disk,report
46; Public Drive_Letter_Msg
47 \ No newline at end of file
diff --git a/v4.0/src/CMD/RECOVER/RECSEG.INC b/v4.0/src/CMD/RECOVER/RECSEG.INC
new file mode 100644
index 0000000..cdcf127
--- /dev/null
+++ b/v4.0/src/CMD/RECOVER/RECSEG.INC
@@ -0,0 +1,21 @@
1; define the segment ordering ;AN000;bgb
2 ;AN000;bgb
3data segment public para 'DATA' ;AN000;bgb
4data ends ;put this 1st so that the recmsg works ;AN000;bgb
5 ;AN000;bgb
6code segment public PARA 'CODE' ;AN000;bgb
7code ends ;AN000;bgb
8 ;AN000;bgb
9const segment public para 'const' ;AN000;bgb
10const ends ;AN000;bgb
11 ;AN000;bgb
12cstack segment stack word 'stack' ;AN000;bgb
13 db (362 - 80h) + 256 dup (?) ; (362 - 80h) == IBM's ROM requirements ;AN000;bgb
14cstack ends ; (New - Old) == size of growth ;AN005;bgb
15 ;AN005;bgb
16lastseg segment public para 'last' ;AN005;bgb
17lastseg ends ;put last because 'table' writes over memory ;AN005;bgb
18 ;AN000;bgb
19dg group data,const,code,cstack,lastseg ;AN000;bgb
20 assume cs:dg,ds:dg,es:dg,ss:CSTACK ;AN000;bgb
21 \ No newline at end of file