2 ;*****************************************************************************
3 ;*****************************************************************************
4 ;UTILITY NAME: CHKOVER.COM
6 ;MODULE NAME: CHKINIT.SAL
12 ; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
13 ; ôInit_Input_OutputÃÄÄÄÄ´Preload_Messages³
14 ; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
15 ; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
16 ; ³ ôParse_Drive_Letter ³
17 ; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
18 ; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
19 ; ³ ôParse_Command_Line ³
20 ;; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
21 ; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
22 ; ³ À´Interpret_Parse³
24 ; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
25 ; ôValidate_Target_DriveôCheck_Target_Drive³
26 ; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
27 ; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
28 ; ³ ôCheck_For_Network³
29 ; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
30 ; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
31 ; ³ À´Check_Translate_Drive³
32 ; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
39 ; ³ÚÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
40 ; ôCHKDSK_IFSôEXEC_FS_CHKDSK³
41 ; ³ÀÄÄÄÄÄÄÄÄÄÄÙ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
48 ;*****************************************************************************
50 ;*****************************************************************************
53 ;*****************************************************************************
55 ;*****************************************************************************
57 include chkseg
.inc ;an005;bgb ;an000;bgb
58 include pathmac
.inc ;an000;bgb
59 INCLUDE CHKEQU
.INC ; ;an000;bgb;AN000;
60 INCLUDE CHKCHNG
.INC ;List of changes ;an000;bgb
61 include dossym
.inc ;an000;bgb
62 INCLUDE SYSCALL.INC ; ;an000;bgb;AN000;
63 INCLUDE CHKMACRO
.INC ; ;an000;bgb;AN000;
64 INCLUDE CHKPARSE
.INC ; ;an000;bgb;AN000;
65 INCLUDE IOCTL
.INC ;an000;bgb
70 psp
segment public para
'DUMMY' ;an000;bgb
72 FCB1
label byte ;an000;bgb
74 FCB2
label byte ;an000;bgb
78 DATA segment public para
'DATA' ;an000;bgb
79 ;***************************************************************************** ;an000;bgb
80 ; Data Area ;an000;bgb
81 ;***************************************************************************** ;an000;bgb
82 old_drive db 0 ;an000;bgb
90 myramdisk db 'RDV 1.20'
94 myvdisk db 'VDISK' ;an000;bgb
95 bytes_per_sector dw 0 ;an005;bgb ;an000;bgb
96 BPB_Buffer A_DeviceParameters
<> ; ;an000;bgb;AN000;
98 Data_Start_Low dw ?
; ;an000;bgb;AN000;
99 Data_Start_High dw ?
; ;an000;bgb
101 public command_line_buffer
;an046;bgb
102 Command_Line_Buffer db 128 dup(0) ; ;an000;bgb;AN000;
103 Command_Line_Length equ
$ - Command_Line_Buffer
; ;an000;bgb;AN000;
105 Fatal_Error db 0 ; ;an000;bgb;AN000;
107 Command_Line db NO
; ;an000;bgb
108 Append db 0 ; ;an000;bgb
110 ifdef fsexec
;an038;bgb
111 ;These should stay together ; ;an038;bgb
112 ; --------------------------------------- ; ; ;an038;bgb
113 FS_String_Buffer db 13 dup(" ") ; ;an038;bgb
114 FS_String_End db "CHK.EXE",0 ; ;an038;bgb
115 Len_FS_String_End equ
$ - FS_String_End
; ;an038;bgb
116 ;---------------------------------------- ; ;an038;bgb
117 FS_Not_Fat db 0 ; ;an038;bgb
118 FAT12_String db "FAT12 " ; ;an038;bgb
119 FAT16_String db "FAT16 " ; ;an038;bgb
120 Len_FS_ID_String equ
$ - FAT16_String
; ;an038;bgb
121 Media_ID_Buffer Media_ID
<> ; ;an038;bgb
124 ExitStatus db 0 ; ;an000;bgb;AN000;
126 PSP_Segment dw 0 ; ;an000;bgb;AN000;
127 tot_bytes_lo dw 0 ; low word of number of sectors in disk ;an000;bgb;an006;bgb
128 tot_bytes_hi dw 0 ;high word of number of sectors in disk ;an000;bgb;an006;bgb
129 fat_dir_secs dw 0 ;sectors in fat, directory and resvd ;an000;bgb;an006;bgb
131 ;***************************************************************************** ;an000;bgb
132 ; Public Data Declarations ;an000;bgb
133 ;***************************************************************************** ;an000;bgb
134 public bpb_buffer
;an000;bgb;an006;bgb
135 public tot_bytes_lo
;an000;bgb;an006;bgb
136 public tot_bytes_hi
;an000;bgb;an006;bgb
137 public fat_dir_secs
;an000;bgb;an006;bgb
138 public bytes_per_sector
;an000;bgb;an005;bgb
139 Public Data_Start_Low
;an000;bgb
140 Public Data_Start_High
;an000;bgb
141 Public Fatal_Error
;an000;bgb
142 Public ExitStatus
;an000;bgb
143 Public PSP_Segment
;an000;bgb
144 ifdef fsexec
;an038;bgb
145 Public FS_String_Buffer
;an038;bgb
148 ;***************************************************************************** ;an000;bgb
149 ; External Data Declarations ;an000;bgb
150 ;***************************************************************************** ;an000;bgb
151 EXTRN movsi
:word ;move si pointer here for display of invalid parm ;an046;bgb;an000;bgb;an005;bgb
152 EXTRN fatcnt
:Byte ;an000;bgb;an005;bgb
153 EXTRN AllDrv
:Byte ;an000;bgb
154 EXTRN VolNam
:Byte ;an000;bgb
155 EXTRN BadDrvM
:Byte ;an000;bgb
156 EXTRN OrphFCB
:Byte ;an000;bgb
157 EXTRN Arg_Buf
:Byte ;an000;bgb
158 EXTRN Noisy
:Byte ;an000;bgb
159 EXTRN DoFix
:Byte ;an000;bgb
160 EXTRN SubstErr
:Byte ;an000;bgb
161 EXTRN No_Net_Arg
:Byte ;an000;bgb
162 EXTRN UserDev
:Byte ;an000;bgb
163 EXTRN BadDrv_Arg
:Byte ;an000;bgb
164 EXTRN TranSrc
:Byte ;an000;bgb
165 EXTRN ContCh
:Word ;an000;bgb
166 EXTRN HardCh
:Word ;an000;bgb
167 EXTRN Fragment
:Byte ;an000;bgb
168 EXTRN Parse_Error_Msg
:Byte ;an000;bgb
169 EXTRN Chkprmt_End
:Byte ;an000;bgb
170 extrn save_drive
:byte ;an000;bgb
171 EXTRN Read_Write_Relative
:Byte ;an000;bgb
172 EXTRN inval_media
:byte ;an000;bgb;an033;bgb
176 code segment public para
'CODE' ;an000;bgb
177 ;***************************************************************************** ;an000;bgb
178 ; External Routine Declarations ;an000;bgb
179 ;***************************************************************************** ;an000;bgb
180 ifdef fsexec
;an038;bgb
181 EXTRN Exec_FS_CHKDSK
:Near ;an000;bgb
183 EXTRN SysLoadMsg
:Near ;an000;bgb
184 EXTRN SysDispMsg
:Near ;an000;bgb
185 EXTRN Done
:Near ;an000;bgb
186 EXTRN Main_Routine
:Near ;an000;bgb
187 EXTRN INT_23
:Near ;an000;bgb
188 EXTRN INT_24
:Near ;an000;bgb
189 EXTRN Path_Name
:Near ;an000;bgb
190 extrn read_once
:near ;an000;bgb
192 public p97
, multiply_32_bits
;an000;bgb
193 public func60
;an000;bgb
194 public hook_interrupts
;an000;bgb
195 public get_bpb
;an000;bgb
197 pathlabl chkinit
;an000;bgb
198 ;***************************************************************************** ;an000;bgb
199 ;Routine name: Main_Init ;an000;bgb
200 ;***************************************************************************** ;an000;bgb
202 ;Description: Main control routine for init section ;an000;bgb
204 ;Called Procedures: Check_DOS_Version ;an000;bgb
205 ; Init_Input_Output ;an000;bgb
206 ; Validate_Target_Drive ;an000;bgb
207 ; Hook_Interrupts ;an000;bgb
208 ; Clear_Append_X ;an000;bgb
209 ; CHKDSK_IFS ;an000;bgb
210 ; Reset_Append_X ;an000;bgb
212 ;Input: None ;an000;bgb
214 ;Output: None ;an000;bgb
216 ;Change History: Created 5/8/87 MT ;an000;bgb
218 ;Psuedocode ;an000;bgb
219 ;---------- ;an000;bgb
221 ; Set segregs to DATA ;an000;bgb
222 ; Get segment of PSP ;an000;bgb
223 ; Fatal_Error = NO ;an000;bgb
224 ; Flush all buffers (INT 21h AH=0Dh) ;an000;bgb
225 ; Parse input and load messages (CALL Init_Input_Output) ;an000;bgb
226 ; IF !Fatal_Error ;an000;bgb
227 ; Check target drive letter (CALL Validate_Target_Drive) ;an000;bgb
228 ; IF !Fatal_Error ;an000;bgb
229 ; Set up Control Break (CALL Hook_Interrupts) ;an000;bgb
230 ; IF !Fatal_Error ;an000;bgb
231 ; CALL Clear_Append_X ;an000;bgb
232 ; CALL CHKDSK_IFS ;an000;bgb
233 ; CALL Reset_Append_X ;an000;bgb
237 ; Exit program ;an000;bgb
238 ;***************************************************************************** ;an000;bgb
240 Procedure Main_Init
; ;an000;bgb;AN000;
241 Set_Data_Segment
;Setup addressibility ;an000;bgb;AN000;
242 call get_psp
;an000;bgb
243 ;;;;;;;;DOS_Call GetCurrentPSP ;Get PSP segment address ;an000;bgb;ac034;bgb
244 ;;;;;;;;mov PSP_Segment,bx ;Save it for later ;an000;bgb;ac034;bgb
245 mov Fatal_Error
,No
;Init the error flag ;an000;bgb;AN000;
246 Dos_Call Disk_Reset
;Flush all buffers ;an000;bgb
247 call Init_IO
;Setup messages and parse ;an000;bgb;AN000;
248 cmp Fatal_Error
,Yes
;Error occur? ;an000;bgb;AN000;
249 ; $IF NE ;Nope, keep going ;an000;bgb;AN000;
251 call Validate_Target_Drive
;Check drive letter ;an000;bgb;AN000;
252 cmp Fatal_Error
,Yes
;Error occur? ;an000;bgb;AN000;
253 ; $IF NE ;Nope, keep going ;an000;bgb;AN000;
255 ;;;;;;;;;;;;;;call Hook_Interrupts ;Set CNTRL -Break hook ;an000;bgb;AN000;
256 call Clear_Append_X
; ;an000;bgb;AN000;
257 call CHKDSK_IFS
;Chkdsk correct file system ;an000;bgb;AN000;
258 call Reset_Append_X
; ;an000;bgb;AN000;
259 ; $ENDIF ; ;an000;bgb;AN000;
261 ; $ENDIF ; ;an000;bgb;AN000;
263 mov al,ExitStatus
;Get Errorlevel ;an000;bgb;AN000;
264 DOS_Call Exit
;Exit program ;an000;bgb;AN000;
265 int 20h
;If other exit fails ;an000;bgb;AN000;
266 Main_Init endp
; ;an000;bgb;AN000;
268 ;***************************************************************************** ;an000;bgb
269 ;Routine name: get_psp ;an000;bgb
270 ;***************************************************************************** ;an000;bgb
271 ;Description: get info from the psp area ;an000;bgb
273 ;Called Procedures: get_drive ;an000;bgb
275 ;Change History: Created 8/7/87 bgb ;an000;bgb
277 ;Input: none ;an000;bgb
279 ;Output: psp_segment ;an000;bgb
280 ; command_line_buffer ;an000;bgb
282 ;Psuedocode ;an000;bgb
283 ;---------- ;an000;bgb
284 ; get addr of psp ;an000;bgb
285 ; move command line into data seg ;an000;bgb
286 ; get drive number of target ;an000;bgb
287 ; get addr of data seg ;an000;bgb
288 ; call get_drive ;an000;bgb
290 ;***************************************************************************** ;an000;bgb
291 Procedure get_psp
;;AN000; ;an000;bgb
292 ;;;;;;;;DOS_Call GetCurrentPSP ;Get PSP segment address :AN035;b;an000;bgbgb
293 ;;;;;;;;mov PSP_Segment,bx ;Save it for later ;AN035;b;an000;bgbgb
294 ; get command line from psp ;an000;bgb;AN000;bgb
295 mov cx,PSP_Segment
;point ds to data seg ;an000;bgb;AN000;bgb
296 mov ds,cx ; " " " " " ;an000;bgb;AN000;bgb
297 assume
ds:NOTHING
,es:dg
; " " " " " ;an000;bgb;AN000;bgb
298 ; get the drive number of the target from the psp (0=default, a=1, b=2, c=3) ;AN;an000;bgb000;bgb
299 mov bl,ds:[FCB1
] ;Get target drive from FCB -74 ;AN0;an000;bgb00;
300 Set_Data_Segment
;Set DS,ES to Data segment ;AN0;an000;bgb00;bgb
301 call get_drive
;an000;bgb
303 get_psp endp
; ;AN000; ;an000;bgb
306 ;***************************************************************************** ;an000;bgb
307 ;Routine name: get_drive ;an000;bgb
308 ;***************************************************************************** ;an000;bgb
309 ;Description: get drive letter from reg bl ;an000;bgb
311 ;Change History: Created 8/7/87 bgb ;an000;bgb
313 ;Input: bl = drive num (default=0) ;an000;bgb
315 ;Output: driveletter ;an000;bgb
316 ; user_drive ;an000;bgb
318 ;Psuedocode ;an000;bgb
319 ;---------- ;an000;bgb
320 ; IF drive-num = default ;an000;bgb
321 ; get default drive number (a=1) ;an000;bgb
322 ; convert to letter ;an000;bgb
324 ; convert to letter ;an000;bgb
326 ; move letter into data areas ;an000;bgb
328 ;***************************************************************************** ;an000;bgb
329 Procedure get_drive
;;AN000; ;an000;bgb
330 ; convert drive number to drive letter ;an000;bgb
331 cmp bl,0 ;a=1 b=2 c=3 ;Is it default drive? 0=default ;AN000; ;an000;bgb
332 ; $IF E ;Yes, turn it into drive letter ;AN000; ;an000;bgb
334 ; get default drive number ;an000;bgb
335 DOS_Call Get_Default_Drive
;Get default drive num in al ;AN00;an000;bgb0;
336 ;a=0, b=1, c=2 ;an000;bgb
337 ; $ELSE ;Not default, A=1 ;AN000; ;an000;bgb
340 ; bl already contains the correct drive number - save it ;an000;bgb
341 dec bl ;make it zero based ;an000;bgb
343 ; $ENDIF ; 74+40=b4 ;an000;bgb
345 mov BadDrvm
+1,al ; " " " " ;an000;bgb ;AN000;
347 mov byte ptr Buffer
.drnum_stroff
,al ; ;an000;bgb ;
348 mov AllDrv
,al ; ;an000;bgb ;AC000;
349 mov VolNam
,al ; ;an000;bgb ;AC000;
350 mov OrphFCB
,al ; ;an000;bgb ;AC000;
352 add al,"A" ;convert it to letter ;AN000; ;an000;bgb
353 mov arg_buf
,al ;set up prompt msg ;AN0;an000;bgb00;bgb
355 get_drive endp
; ;AN000; ;an000;bgb
357 ;***************************************************************************** ;an000;bgb
358 ;Routine name: Init_Input_Output ;an000;bgb
359 ;***************************************************************************** ;an000;bgb
361 ;description: Initialize messages, Parse command line if FAT file system ;an000;bgb
363 ;Called Procedures: Preload_Messages ;an000;bgb
364 ; Parse_Command_Line ;an000;bgb
366 ;Change History: Created 5/10/87 MT ;an000;bgb
368 ;Input: PSP command line at 81h and length at 80h ;an000;bgb
370 ;Output: FS_Not_FAT = YES/NO ;an000;bgb
372 ;Psuedocode ;an000;bgb
373 ;---------- ;an000;bgb
375 ; FS_Not_FAT = NO ;an000;bgb
376 ; Load messages (CALL Preload_Messages) ;an000;bgb
377 ; IF !Fatal_Error ;an000;bgb
378 ; Get file system type (INT 21h AX=440Dh, CX=084Eh GET MEDIA_ID) ;an000;bgb
379 ; IF CY (Old type diskette),OR ;an000;bgb
380 ; IF "FAT_12 ",OR ;an000;bgb
381 ; IF "FAT_16 " ;an000;bgb
382 ; CALL Parse_Command_Line ;an000;bgb
383 ; IF !Fatal_Error ;an000;bgb
384 ; Interpret_Parse ;an000;bgb
387 ; Get drive letter only (CALL Parse_Drive_Letter) ;an000;bgb
388 ; FS_Not_FAT = YES ;an000;bgb
392 ;***************************************************************************** ;an000;bgb
394 Procedure Init_IO
; ;AN000; ;an000;bgb
396 call Preload_Messages
;Load up message retriever ;an000;bgb;AN000;
397 ifdef fsexec
;an038;bgb
398 mov FS_Not_FAT
,No
;an038;bgb
399 cmp Fatal_Error
,YES
;Quit? ;an038;bgb;AN000;
400 ; $IF NE ;Nope, keep going ;an038;bgb;AN000;
402 mov al,GENERIC_IOCTL
;Generic IOCtl call ;an038;bgb;AN000;
403 push ds ; ;an038;bgb;AN000;
404 mov bx,PSP_Segment
; ;an038;bgb;AN000;
405 mov ds,bx ; ;an038;bgb;AN000;
406 assume
ds:nothing
; ;an038;bgb;AN000;
408 mov bl,ds:FCB1
;Get drive (A=1) ;an038;bgb;AN000;
410 pop ds ; ;an038;bgb;AN000;
411 assume
ds:dg
; ;an038;bgb;AN000;
412 xor bh,bh ;Set bh=0 ;an038;bgb;AN000;
413 mov ch,RawIO
;Get Media ID call ;an038;bgb;AN000;
414 mov cl,GET_MEDIA_ID
; ;an038;bgb;AN000;
415 lea dx,Media_ID_Buffer
;Point at buffer ;an038;bgb;AN000;
416 DOS_Call IOCtl
;Do function call ;an038;bgb;AN000;
417 ; $IF C,OR ;Old style diskette, OR ;an038;bgb;AN000;
419 lea si,FAT12_String
;Check for FAT_12 string ;an038;bgb;AN000;
420 lea di,Media_ID_Buffer
.Media_ID_File_System
; ;AN000;;an038;bgb
421 mov cx,Len_FS_ID_String
;Length of compare ;an038;bgb;AN000;
422 repe cmpsb ;Find it? ;an038;bgb;AN000;
423 ; $IF E,OR ;Nope, keep going ;an038;bgb;AN000;
425 lea si,FAT16_String
;Check for FAT_16 string ;an038;bgb;AN000;
426 lea di,Media_ID_Buffer
.Media_ID_File_System
; ;AN000;;an038;bgb
427 mov cx,Len_FS_ID_String
;Length of compare ;an038;bgb;AN000;
428 repe cmpsb ;Do compare ;an038;bgb;AN000;
429 ; $IF E ;Find it? ;an038;bgb;AN000;
433 call Parse_Command_Line
;Parse in command line input ;an038;bgb;AN000;
434 ifdef fsexec
;an038;bgb
435 ; $ELSE ;We got FS other than FAT ;an038;bgb;AN000;
438 ;;;;;;;;;;;;;;call Parse_Drive_Letter ;Only look for drive letter ;an038;bgb;AN000;
439 mov FS_Not_FAT
,Yes
;Indicate exec file system ;an038;bgb;AN000;
440 mov cx,8 ;an038;bgb;an027;bgb
441 lea si,Media_ID_Buffer
.Media_ID_File_System
;get file system;an038;bgb ;an027;bgb
442 lea di,fs_string_buffer
;put it here ;an038;bgb;an027;bgb
443 rep movsb ;an038;bgb;an027;bgb
444 lea di,fs_string_buffer
;point to beginning again ;an038;bgb;an027;bgb
445 ; $DO COMPLEX ;search th string until eol found ;an038;bgb;an027;bgb
448 inc di ;next char ;an038;bgb;an027;bgb
449 ; $STRTDO ;start loop here ;an038;bgb;an027;bgb
451 cmp byte ptr [di],' ' ;end of string ? ;an038;bgb;an027;bgb
452 ; $ENDDO E ;end loop when eol found ;an038;bgb;an027;bgb
454 lea si,fs_string_end
;get end of string - rec.exe ;an038;bgb;an027;bgb
455 mov cx,8 ; 8 more chars ;an038;bgb;an027;bgb
456 rep movsb ;move it in ;an038;bgb;an027;bgb
457 ; $ENDIF ; ;an038;bgb;AN000;
459 ; $ENDIF ; ;an038;bgb;AN000;
462 ret ; ;an000;bgb;AN000;
464 Init_IO endp
; ;AN000; ;an000;bgb
466 ;***************************************************************************** ;an000;bgb
467 ;Routine name: Preload_Messages ;an000;bgb
468 ;***************************************************************************** ;an000;bgb
470 ;Description: Preload messages using common message retriever routines. ;an000;bgb
472 ;Called Procedures: SysLoadMsg ;an000;bgb
475 ;Change History: Created 5/1/87 MT ;an000;bgb
477 ;Input: Fatal_Error = NO ;an000;bgb
479 ;Output: Fatal_Error = YES/NO ;an000;bgb
481 ;Psuedocode ;an000;bgb
482 ;---------- ;an000;bgb
484 ; Preload All messages (Call SysLoadMsg) ;an000;bgb
485 ; IF error ;an000;bgb
486 ; Display SysLoadMsg error message ;an000;bgb
487 ; Fatal_Error = YES ;an000;bgb
490 ;***************************************************************************** ;an000;bgb
492 Procedure Preload_Messages
; ;an000;bgb;AN000;
494 call SysLoadMsg
;Preload the messages ;an000;bgb;AN000;
495 ; $IF C ;Error? ;an000;bgb;AN000;
497 call SysDispMsg
;Display preload msg ;an000;bgb;AN000;
498 mov Fatal_Error
, YES
;Indicate error exit ;an000;bgb;AN000;
499 ; $ENDIF ; ;an000;bgb;AN000;
501 ret ; ;an000;bgb;AN000;
503 Preload_Messages endp
; ;an000;bgb;AN000;
505 ;***************************************************************************** ;an000;bgb
506 ;Routine name: Parse_Drive_Letter ;an000;bgb
507 ;***************************************************************************** ;an000;bgb
509 ;Description: Copy the command line - then parse looking only for drive ;an000;bgb
510 ; letter. Ignore errors, because this is only called to get ;an000;bgb
511 ; the drive letter for non-FAT chkdsk ;an000;bgb
513 ;Called Procedures: SysParse ;an000;bgb
515 ;Change History: Created 5/12/87 MT ;an000;bgb
517 ;Input: Command line input at 81h ;an000;bgb
519 ;Output: None ;an000;bgb
522 ;Psuedocode ;an000;bgb
523 ;---------- ;an000;bgb
524 ; Copy command line to buffer ;an000;bgb
526 ; Parse buffer line (CALL SysParse) using drive letter only tables ;an000;bgb
527 ; LEAVE end of parse ;an000;bgb
528 ; ENDDO missing operand ;an000;bgb
530 ;***************************************************************************** ;an000;bgb
532 ;Procedure Parse_Drive_Letter ; ;an000;bgb;AN000;
533 ; Set_Data_Segment ;Set DS,ES to Data segment ;an000;bgb;AN000;
534 ; mov cx,PSP_Segment ;Get segment of PSP ;an000;bgb;AN000;
535 ; mov ds,cx ; " " " " ;an000;bgb;AN000;
536 ; assume ds:nothing ; ;an000;bgb;AN000;
537 ; mov si,Command_Line_Parms ;Point to command line ;an000;bgb;AN000;
538 ; lea di,Command_Line_Buffer ;Point to buffer to save to ;an000;bgb;AN000;
539 ; mov cx,Command_Line_Length ;Number of bytes to move ;an000;bgb;AN000;
540 ; rep movsb ;Copy the entire buffer ;an000;bgb;AN000;
541 ; Set_Data_Segment ; ;an000;bgb;AN000;
542 ; lea si,Command_Line_Buffer ;Pointer to parse line ;an000;bgb;AN000;
543 ; lea di,input_table ;Pointer to control table ;an000;bgb;AN000;
544 ; $DO ;Parse for drive letter ;an000;bgb;AN000;
545 ; xor dx,dx ;Parse line @SI ;an000;bgb;AN000;
546 ; xor cx,cx ;Parse table @DI ;an000;bgb;AN000;
547 ; call SysParse ;Go parse ;an000;bgb;AN000;
548 ; cmp ax,End_Of_Parse ;Check for end of parse ;an000;bgb;AN000;
549 ; $LEAVE E ;In other words, no drive letter;an000;bgb;AN000;
550 ; cmp ax,Operand_Missing ; exit if positional missing ;an000;bgb;AN000;
551 ; $ENDDO E ;Ignore errors!!! ;an000;bgb;AN000;
552 ; Set_Data_Segment ; ;an000;bgb;AN000;
553 ; ret ; ;an000;bgb;AN000;
555 ;Parse_Drive_Letter endp ; ;an000;bgb;AN000;
557 ;***************************************************************************** ;an000;bgb
558 ;Routine name: Parse_Command_Line ;an000;bgb
559 ;***************************************************************************** ;an000;bgb
561 ;Description: Parse the command line. Check for errors, and display error and ;an000;bgb
562 ; exit program if found. Use parse error messages except in case ;an000;bgb
563 ; of no parameters, which has its own message ;an000;bgb
565 ;Called Procedures: Message (macro) ;an000;bgb
566 ; SysParse ;an000;bgb
567 ; Interpret_Parse ;an000;bgb
569 ;Change History: Created 5/1/87 MT ;an000;bgb
571 ;Input: Fatal_Error = NO ;an000;bgb
572 ; PSP_Segment ;an000;bgb
574 ;Output: Fatal_Error = YES/NO ;an000;bgb
575 ; Parse output buffers set up ;an000;bgb
578 ;Psuedocode ;an000;bgb
579 ;---------- ;an000;bgb
581 ; Parse command line (CALL SysParse) ;an000;bgb
582 ; EXITIF end of parsing command line ;an000;bgb
583 ; Figure out last thing parsed (Call Interpret_Parse) ;an000;bgb
585 ; See if parse error ;an000;bgb
586 ; ENDLOOP parse error ;an000;bgb
587 ; See what was parsed (Call Interpret_Parse) ;an000;bgb
588 ; Fatal_Error = YES ;an000;bgb
591 ;***************************************************************************** ;an000;bgb
593 Procedure Parse_Command_Line
; ;an000;bgb;AN000;
595 push ds ;Save data segment ;an000;bgb;AN000;
596 Set_Data_Segment
; ;an000;bgb;AN000;
597 mov cx,PSP_Segment
;Get segment of PSP ;an000;bgb;AN000;
598 mov ds,cx ; " " " " ;an000;bgb;AN000;
600 assume
ds:nothing
,es:dg
; ;an000;bgb;AN000;
602 mov si,Command_Line_Parms
;Point at command line ;an000;bgb;AN000;
603 lea di,Command_Line_Buffer
;Where to put a copy of it ;an000;bgb;AN000;
604 mov cx,Command_Line_Length
;How long was input? ;an000;bgb;AN000;
605 repnz movsb ;Copy it ;an000;bgb;AN000;
606 lea Di,Command_Line_Buffer
; ;an046;bgb
607 public nextdi
;an046;bgb
609 mov al,0dh ;search for end of line ;an046;bgb
610 cmp al,ES:[Di] ;zero terminate string ;an046;bgb
614 jmp nextdi
;an046;bgb
618 mov byte ptr ES:[di+1],00 ;an046;bgb
622 Set_Data_Segment
;Set DS,ES to Data segment ;an000;bgb;AN000;
623 xor cx,cx ; ;an000;bgb;AN000;
624 xor dx,dx ;Required for SysParse call ;;an000;bgbAN000;
625 lea si,Command_Line_Buffer
;Pointer to parse line ;an000;bgb ;AN000;
626 lea di,input_table
;Pointer to control table ;an000;bgb ;AN000;
627 ; $SEARCH ;Loop until all parsed ;an000;bgb;AN000;
629 cmp Fatal_Error
,Yes
;Interpret something bad? ;an000;bgb;AN000;
630 ; $EXITIF E,OR ;If so, don't parse any more ;an000;bgb;AN000;
632 call SysParse
;Go parse ;an000;bgb;AN000;
633 cmp ax,End_Of_Parse
;Check for end of parse ;an000;bgb;AN000;
634 ; $EXITIF E ;Is it? ;an000;bgb;AN000;
637 ;All done ;an000;bgb;AN000;
638 ; $ORELSE ;Not end ;an000;bgb;AN000;
641 cmp ax,0 ;Check for parse error ;an000;bgb;AN000;
642 ; $LEAVE NE ;Stop if there was one ;an000;bgb;AN000;
644 call Interpret_Parse
;Go find what we parsed ;an000;bgb;AN000;
645 ; $ENDLOOP ;Parse error, see what it was ;an000;bgb;AN000;
649 dec si ;point to last byte of invalid parm
651 decsi: cmp byte ptr [si],' ' ;are we pointing to a space? ;an046;bgb
652 ; $IF E,OR ;if so, we dont want to do that
654 cmp byte ptr [si],0dh ;are we pointing to CR? ;an046;bgb
655 ; $IF E ;if so, we dont want to do that
658 dec si ;find the last byte of parm
662 mov byte ptr [si+1],00 ;zero terminate display string ;an046;bgb
665 dec si ;look at previous char ;an046;bgb
666 cmp byte ptr [si],' ' ;find parm separator ;an046;bgb
667 jnz nextsi
;loop until begin of parm found
668 mov movsi
,si ;mov si into display parms ;an046;bgb
669 PARSE_MESSAGE
;Display parse error ;an000;bgb;AN000;
670 mov Fatal_Error
,YES
;Indicate death! ;an000;bgb;AN000;
671 ; $ENDSRCH ; ;an000;bgb;AN000;
673 pop ds ; ;an000;bgb;AN000;
674 ret ; ;an000;bgb;AN000;
676 Parse_Command_Line endp
; ;an000;bgb;AN000;
678 ;***************************************************************************** ;an000;bgb
679 ;Routine name: Interpret_Parse ;an000;bgb
680 ;***************************************************************************** ;an000;bgb
682 ;description: Get any switches entered, and dr ;an000;bgb
685 ;Called Procedures: Message (macro) ;an000;bgb
687 ;Change History: Created 5/1/87 MT ;an000;bgb
689 ;Input: DS:DrNum (FCB at 5Ch) ;an000;bgb
691 ;Output: Noisy = ON/OFF ;an000;bgb
692 ; DoFix = ON/OFF ;an000;bgb
693 ; ALLDRV = Target drive, A=1 ;an000;bgb
694 ; VOLNAM = Target drive, A=1 ;an000;bgb
695 ; ORPHFCB = Target drive, A=1 ;an000;bgb
696 ; BADDRVm+1 = Target drive, A=0 ;an000;bgb
697 ; Arg_Buf = Target drive letter ;an000;bgb
698 ; Fragment > 1 if filespec entered ;an000;bgb
700 ;Psuedocode ;an000;bgb
701 ;---------- ;an000;bgb
703 ; Noisy = OFF ;an000;bgb
704 ; DoFix = OFF ;an000;bgb
706 ; Noisy = ON ;an000;bgb
709 ; DoFix = ON ;an000;bgb
711 ; IF file spec entered ;an000;bgb
712 ; Build filename ;an000;bgb
713 ; Fragment = 1 ;an000;bgb
716 ;***************************************************************************** ;an000;bgb
718 Procedure Interpret_Parse
; ;an000;bgb;AN000;
720 push ds ;Save segment ;an000;bgb;AN000;
721 push si ;Restore SI for parser ;an000;bgb;AN000;
722 push cx ; ;an000;bgb;AN000;
724 Set_Data_Segment
; ;an000;bgb
725 cmp byte ptr Buffer
.dfType
,Type_Drive
;Have drive letter? ;AN000; ;an000;bgb
726 ; $IF E ;Yes, save info ;an000;bgb;AN000;
728 and word ptr dfcontrol
,filespec
;dont let another drive letter ;an000;bgb
729 mov al,byte ptr Buffer
.Drnum_stroff
;Get drive entered ;;an000;bgbAN000;
730 mov AllDrv
,al ; ;an000;bgb;AC000;
731 mov VolNam
,al ; ;an000;bgb;AC000;
732 mov OrphFCB
,al ; ;an000;bgb;AC000;
733 dec al ;Make it 0 based ;an000;bgb;AN000;
734 mov BadDrvm
+1,al ; " " " " ;an000;bgb;AN000;
735 add al,'A' ;Make it a drive letter ;an000;bgb;AN000;
736 mov Arg_Buf
,al ;Save it ;an000;bgb;AN000;
737 ; $ENDIF ; ;an000;bgb;AN000;
739 cmp SwBuffer
.Switch_Pointer
,offset Sw_v
;AN020;;an000;bgbbgb
740 ; $IF E ; ;an000;bgb;AN000;
742 mov Noisy
,ON ;Set flag ;an000;bgb;AC000;
743 mov byte ptr sw_v
,blank
;an000;bgb;an020;bgb
744 ; $ENDIF ; ;an000;bgb;AN000;
746 cmp SwBuffer
.Switch_Pointer
,offset sw_f
;AN020;;an000;bgbbgb
747 ; $IF E ; ;an000;bgb;AN000;
749 mov DoFix
,ON ;Set flag ;an000;bgb;AC000;
750 mov byte ptr sw_f
,blank
;;an000;bgban020;bgb
751 ; $ENDIF ; ;an000;bgb;AN000;
753 ;;;;;;; cmp FileSpec_Buffer.FileSpec_Pointer,offset FileSpec_Control.Keyword;an000;bgb ;AN000;
754 cmp buffer
.dftype
, type_filespec
;an000;bgb
755 ; $IF E ; ;an000;bgb;AN000;
757 mov word ptr dfcontrol
,0 ;dont let another drive letter or filesp;an000;bgbec
758 mov si,Buffer
.drnum_StrOff
; ;AN000; ;an000;bgb
759 lea di,Path_Name
;Point to where to build path ;an000;bgb;AN000;
760 cld ;SI-DI dir is up ;an000;bgb;AN000;
761 ; $DO ;Move string one char at a time ;an000;bgb;AN000;
763 cmp byte ptr [si],Asciiz_End
;Is it the end? ;an000;bgb;AN000;
764 ; $LEAVE E ;You got it ;an000;bgb;AN000;
766 movsb ;Nope, move the character ;an000;bgb;AN000;
767 ; $ENDDO ;And keep crusin ;an000;bgb;AN000;
770 inc fragment
;To be compat with old code ;an000;bgb;AN000;
771 ; $ENDIF ; ;an000;bgb;AN000;
773 pop di ;Restore parse regs ;an000;bgb;AN000;
774 pop cx ; ;an000;bgb;AN000;
775 pop si ; ;an000;bgb;AN000;
776 pop ds ; ;an000;bgb;AN000;
777 ret ; ;an000;bgb;AN000;
780 Interpret_Parse endp
; ;an000;bgb;AN000;
784 ;***************************************************************************** ;an000;bgb
785 ;Routine name: Validate_Target_Drive ;an000;bgb
786 ;***************************************************************************** ;an000;bgb
788 ;Description: Control routine for validating the specified format target drive. ;an000;bgb
789 ; If any of the called routines find an error, they will print ;an000;bgb
790 ; message and terminate program, without returning to this routine ;an000;bgb
792 ;Called Procedures: Check_Target_Drive ;an000;bgb
793 ; Check_For_Network ;an000;bgb
794 ; Check_Translate_Drive ;an000;bgb
796 ;Change History: Created 5/1/87 MT ;an000;bgb
798 ;Input: Fatal_Error = NO ;an000;bgb
800 ;Output: Fatal_Error = YES/NO ;an000;bgb
802 ;Psuedocode ;an000;bgb
803 ;---------- ;an000;bgb
805 ; CALL Check_Target_Drive ;an000;bgb
806 ; IF !Fatal_Error ;an000;bgb
807 ; CALL Check_For_Network ;an000;bgb
808 ; IF !Fatal_Error ;an000;bgb
809 ; CALL Check_Translate_Drive ;an000;bgb
813 ;***************************************************************************** ;an000;bgb
815 Procedure Validate_Target_Drive
; ;an000;bgb;AN000;
816 call Check_For_Network
;See if Network drive letter ;an000;;an043;bgbbgb;AN000;
817 cmp Fatal_Error
,YES
;Can we continue? ;an0;an043;bgb00;bgb;AN000;
818 ; $IF NE ;Yep ;an0;an043;bgb00;bgb;AN000;
820 call Check_Target_Drive
;See if valid drive letter ;an000;bgb;AN000;
821 cmp Fatal_Error
,YES
;Can we continue? ;an000;bgb;AN000;
822 ; $IF NE ;Yep ;an000;bgb;AN000;
824 call Check_For_Network
;See if Network drive letter ;an000;bgb;AN000;
825 cmp Fatal_Error
,YES
;Can we continue? ;an000;bgb;AN000;
826 ; $IF NE ;Yep ;an000;bgb;AN000;
828 call Check_Translate_Drive
;See if Subst, Assigned ;an000;bgb;AN000;
829 ; $ENDIF ;- Fatal_Error passed back ;an000;bgb;AN000;
831 ; $ENDIF ; ;an000;bgb;AN000;
835 ret ; ;an000;bgb;AN000;
837 Validate_Target_Drive endp
; ;an000;bgb;AN000;
839 ;***************************************************************************** ;an000;bgb
840 ;Routine name: Check_Target_Drive ;an000;bgb
841 ;***************************************************************************** ;an000;bgb
843 ;Description: Check to see if valid DOS drive by checking if drive is ;an000;bgb
844 ; removable. If error, the drive is invalid. Save default ;an000;bgb
845 ; drive info. Also get target drive BPB information, and compute ;an000;bgb
846 ; the start of the data area ;an000;bgb
848 ;Called Procedures: Message (macro) ;an000;bgb
850 ;Change History: Created 5/1/87 MT ;an000;bgb
852 ;Input: Fatal_Error = NO ;an000;bgb
854 ;Output: BIOSFile = default drive letter ;an000;bgb
855 ; DOSFile = default drive letter ;an000;bgb
856 ; CommandFile = default drive letter ;an000;bgb
857 ; Fatal_Error = YES/NO ;an000;bgb
859 ;Psuedocode ;an000;bgb
860 ;---------- ;an000;bgb
862 ; Get default drive (INT 21h, AH = 19h) ;an000;bgb
863 ; Convert it to drive letter ;an000;bgb
864 ; Save into BIOSFile,DOSFile,CommandFile ;an000;bgb
865 ; See if drive removable (INT 21h, AX=4409h IOCtl) ;an000;bgb
866 ; IF error - drive invalid ;an000;bgb
867 ; Display Invalid drive message ;an000;bgb
868 ; Fatal_Error= YES ;an000;bgb
870 ; Get BPB of target drive (Generic IOCtl Get Device parameters) ;an000;bgb
871 ; Compute start of data area ;an000;bgb
873 ;***************************************************************************** ;an000;bgb
874 Procedure Check_Target_Drive
; ;an000;bgb;AN000;
875 call func60
; ;an000;bgb
876 mov al,save_drive
;an000;bgb
877 cmp al,0ffh ;save drive spec ;an000;bgb
880 Message BadDrv_Arg
;Print message ;an000;bgb;AC000;
881 mov Fatal_Error
,Yes
;Indicate error ;an000;bgb;AN000;
882 jmp Exit_Baddrv
;dont do rest of proc ;an000;bgb;an021;bgb;an099;
885 DOS_Call Get_Default_Drive
;Find the current drive 19 ;an000;bgb;AC000;
886 mov UserDev
,al ;Save it ;an000;bgb; ;
887 cmp AllDrv
,0 ;Was drive entered? ;an000;bgb;AN002;
888 ; $IF E ;No ;an000;bgb;AN002;
890 mov BadDrvm
+1,al ;Save 0 based number ;an000;bgb;AN002;
891 inc al ;Make 1 based ;an000;bgb;AN002;
892 mov byte ptr Buffer
.Drnum_stroff
,al ; ;an000;bgb ;
893 mov AllDrv
,al ;Use default drive for ;an000;bgb;AN002;
894 mov VolNam
,al ;entries for drive fields ;an000;bgb;AN002;
895 mov OrphFCB
,al ; ;an000;bgb;AN002;
896 add al,'A'-1 ;Make it a drive letter ;an000;bgb;AN002;
897 mov Arg_Buf
,al ;Save it ;an000;bgb;AN002;
898 ; $ENDIF ; ;an000;bgb;AN002;
900 mov bl,alldrv
;Get drive number (A=1) ;AN00;an044;bgb;an000;bgb0;
901 mov al,09h ;See if drive is local ;an000;bgb;AC000;
902 DOS_Call IOCtl
;-this will fail if bad drive ;an000;bgb;AC000;
903 ; $IF C ;CY means invalid drive ;an000;bgb;AC000;
905 Message BadDrv_Arg
;Print message ;an000;bgb;AC015;bgb
906 mov Fatal_Error
,Yes
;Indicate error ;an000;bgb;AN015;bgb
907 ; $ENDIF ; ;an000;bgb;AN000;
909 cmp fatal_error
,no
;an000;bgb
912 get_bpb: mov al,GENERIC_IOCTL
;Get BPB information ;an000;bgb ;AN000;
913 mov ch,RawIO
; " " " " ;an000;bgb ;AN000;
914 mov cl,GET_DEVICE_PARAMETERS
; ;an000;bgb ;AN000;
915 mov bl,AllDrv
; " " " " ;an000;bgb ;AN000;
916 lea dx,BPB_Buffer
; dx points to bpb area ;an000;bgb ;AN000;
917 mov byte ptr bpb_buffer
, 0ffh ;turn bit 0 on to get bpb inf;an000;bgbo of disk ;an008;bgb
918 DOS_Call IOCtl
; " " " " ;an000;bgb ;AN000;
919 mov bx,dx ;use bx as the pointer to bpb;an000;bgb ;an015;bgb
920 ; $IF C ;is ioct not supported or bad? ;an000;bgb ;an015;bgb
922 mov al,BadDrvm
+1 ; drive number a=0 ;an000;bgb ;AN015;bgb
923 lea bx,chkprmt_end
; transfer address es:bx ;an000;bgb ;an015;bgb
924 ;warning! this label must be the last in the code segment ;an000;bgb
925 mov cx,1 ; 1 sector - boot record ;an000;bgb ;an015;bgb
926 mov dx,0 ; logical sector 0 ;an000;bgb ;an015;bgb
927 mov Read_Write_Relative
.Start_Sector_High
,0 ; ;an000;bgb ;an015;bgb
928 call read_once
;an000;bgb ;an015;bgb
929 ; $IF C ;couldnt read the boot? ;an000;bgb ;an015;bgb
931 Message BadDrv_Arg
;Print message ;an000;bgb ;AC015;bgb
932 mov Fatal_Error
,Yes
;Indicate error ;an000;bgb ;AN015;bgb
933 ; $ELSE ;ioct not supported - is it vdisk ;an000;bgb ;an015;bgb
936 ; mov di,bx ;an000;bgb;an022;bgb
937 ; add di,3 ;es:di --> to vdisk area in boot rcd ;an000;bgb;an022;bgb
938 ; lea si,myvdisk ;ds:si --> proper vdisk string ;an000;bgb;an022;bgb
939 ; mov cx,5 ; compare 5 bytes ;an000;bgb;an022;bgb
940 ; repe cmpsb ;compare both strings ;an000;bgb;an022;bgb
942 ; $IF NE ;an000;bgb;an022;bgb
943 ; jmp baddrv ;an000;bgb
944 ; $ENDIF ;an000;bgb;an022;bgb
960 ; $ENDIF ;an000;bgb;an022;bgb
962 add bx,4 ;boot-record-offset - device-paramete;an000;bgbr offset ;an015;bgb
963 ; $ENDIF ;an000;bgb ;an015;bgb
967 cmp fatal_error
,no
;an000;bgb
970 call get_boot_info
;an053;bgb
971 call calc_space
;an000;bgb
974 cmp bytes_per_sector
,0 ;an000;bgb;an033;bgb
975 ; $IF E ;an000;bgb;an033;bgb
977 baddrv: mov fatal_error
,yes
;an000;bgb;an033;bgb
978 mov dx,offset dg
:inval_media
;an000;bgb;an033;bgb
979 invoke printf_crlf
;an000;bgb;an033;bgb
980 ; $ENDIF ;an000;bgb;an033;bgb
983 ret ;And we're outa here ;an000;bgb;AN000;
984 Check_Target_Drive endp
; ;an000;bgb;AN000;
988 ;****************************************************************************** ;an053;bgb;an000;bgb
989 ; get_boot_info ;an053;bgb
991 ; ;an053;bgb;an000;bgb
992 ; Inputs : none ;an053;bgb;an000;bgb
993 ; ;an053;bgb;an000;bgb
994 ; Outputs : ;an053;bgb
995 ;****************************************************************************** ;an053;bgb;an000;bgb
996 Procedure get_boot_info
; ;an053;bgb;an000;bgb
997 mov cx,[bx].BytePerSector
; usually 512 ;an053;bgb;an000;bgb ;an015;bgb
998 cmp cx,512 ;vdisk sizes ;an053;bgb
999 ; $IF NE,AND ;vdisk sizes ;an053;bgb
1001 cmp cx,256 ;vdisk sizes ;an053;bgb
1002 ; $IF NE,AND ;vdisk sizes ;an053;bgb
1004 cmp cx,128 ;vdisk sizes ;an053;bgb
1005 ; $IF NE ;vdisk sizes ;an053;bgb
1007 jmp baddrv
;an053;bgb
1010 mov bytes_per_sector
,cx ; ; ;an053;bgb;an000;bgb ;an005;bgb
1012 xor cx,cx ;Find # sectors used by FA;an053;bgb;an000;bgbT's ;AN000;
1013 mov cl,[bx].NumberOfFats
; " " " " ;an053;bgb;an000;bgb ;an015;bgb
1014 cmp cx,2 ;make sure it is ok ;an053;bgb;an032;bgb
1015 ; $IF NE,AND ;an053;bgb
1017 cmp cx,1 ;make sure it is ok ;an053;bgb;an032;bgb
1020 jmp baddrv
;must be 2 fats ;an053;bgb ;an032;bgb
1023 mov fatcnt
,cl ;an053;bgb;an000;bgb ;an005;bgb
1026 xor ax,ax ;an053;bgb
1027 mov al,[bx].SectorsPerCluster
;get total sectors ;an053;bgb ;an000;bgb;an015;bgb
1028 cmp ax,1 ;make sure it is ok ;an053;bgb;an032;bgb
1029 ; $IF NE,AND ;an053;bgb
1031 cmp ax,2 ;make sure it is ok ;an053;bgb;an032;bgb
1032 ; $IF NE,AND ;an053;bgb
1034 cmp ax,4 ;make sure it is ok ;an053;bgb;an032;bgb
1035 ; $IF NE,AND ;an053;bgb
1037 cmp ax,8 ;make sure it is ok ;an053;bgb;an032;bgb
1038 ; $IF NE,AND ;an053;bgb
1040 cmp ax,16 ;make sure it is ok ;an053;bgb;an032;bgb
1041 ; $IF NE,AND ;an053;bgb
1043 cmp ax,32 ;make sure it is ok ;an053;bgb;an032;bgb
1044 ; $IF NE,AND ;an053;bgb
1046 cmp ax,64 ;make sure it is ok ;an053;bgb;an032;bgb
1047 ; $IF NE,AND ;an053;bgb
1049 cmp ax,128 ;make sure it is ok ;an053;bgb;an032;bgb
1052 jmp baddrv
;this is not! ;an053;bgb ;an032;bgb
1056 mov ax,[bx].SectorsPerFAT
; " " " " ;an053;bgb;an000;bgb ;an015;bgb
1057 cmp ax,0 ;make sure it is ok ;an053;bgb;an032;bgb
1058 jz baddrv
;this is not! ;an053;bgb;an032;bgb
1059 mul cx ; " " " " ;an053;bgb;an000;bgb ;AN000;
1060 push bx ;save bpb pointer ;an053;bgb;an000;bgb ;an015;bgb
1061 push dx ;Save results ;an053;bgb;an000;bgb ;AN000;
1062 push ax ; " " ;an053;bgb;an000;bgb ;AN000;
1064 mov ax,[bx].RootEntries
;Find number of sectors in root ;an053;bgb;an000;bgb ;an015;bgb
1065 cmp ax,2 ;make sure it is ok ;an053;bgb;an032;bgb
1066 ; $IF B,OR ;this is not! ;an053;bgb;an032;bgb
1068 cmp ax,512 ;make sure it is ok ;an053;bgb;an032;bgb
1069 ; $IF A ;this is not! ;an053;bgb;an032;bgb
1072 jmp baddrv
;an053;bgb
1076 mov cl,Dir_Entries_Per_Sector
; by dividing RootEntries ;an053;bgb;an000;bgb ;AN000;
1077 cmp cl,0 ;an053;bgb;an000;bgb;an022;bgb
1078 ; $IF NE ;an053;bgb;an000;bgb;an022;bgb
1080 div cl ; by (512/32) ;an053;bgb;an000;bgb;an022;bgb;AN000;
1081 ; $ENDIF ;an053;bgb;an000;bgb;an022;bgb
1083 pop bx ;Get low sectors per FAT b;an053;bgb;an000;bgback ;AN000;
1084 pop dx ;Get high part ;an053;bgb;an000;bgb ;AN000;
1085 add ax,bx ;Add to get FAT+Dir sector;an053;bgb;an000;bgbs ;AN000;
1086 adc dx,0 ;High part ;an053;bgb;an000;bgb ;AN000;
1087 mov fat_dir_secs
,ax ;save it ;an053;bgb;an000;bgb ;an006;bgb
1088 inc fat_dir_secs
; 1 for reserved sector ;an053;bgb;an000;bgb ;an006;bgb
1089 pop bx ;restore bpb pointer ;an053;bgb;an000;bgb ;an015;bgb
1090 add ax,[bx].ReservedSectors
;Add in Boot record sectors ;an053;bgb;an000;bgb ;an015;bgb
1091 adc dx,0 ;to get start of data (DX:;an053;bgb;an000;bgbAX) ;AN000;
1092 mov Data_Start_Low
,ax ;Save it ;an053;bgb;an000;bgb ;AN000;
1093 mov Data_Start_High
,dx ; ;an053;bgb;an000;bgb ;AN000;
1094 ret ; ;an053;bgb;an000;bgb
1095 get_boot_info endp
; ;an053;bgb;an000;bgb
1103 ;****************************************************************************** ;an000;bgb
1104 ; Calc_Space : Calculate the total space that is ;an000;bgb
1105 ; addressible on the the disk by DOS. ;an000;bgb
1107 ; Inputs : none ;an000;bgb
1109 ; Outputs : Fdsksiz - Size in bytes of the disk ;an000;bgb
1110 ;****************************************************************************** ;an000;bgb
1111 Procedure Calc_Space
; ;an000;bgb
1112 ; get the total number of clusters on the disk ;an000;bgb ;an006;bgb
1113 p97: xor ax,ax ;clear ax ;an000;bgb
1114 mov ah,36h
;Get disk free space ;an000;bgb
1115 mov dl,alldrv
; 1 based drive number ;an000;bgb
1116 push bx ;save bpb pointer ;an000;bgb;an015;bgb
1117 int 21h
;bx = total space avail ;an000;bgb
1118 ;multiply by sectors per cluster ;an000;bgb
1119 gtsecs: mov ax,dx ;get total clusters ;an000;bgb
1120 xor cx,cx ;clear cx ;an000;bgb
1121 pop bx ;restore bpb pointer ;an000;bgb;an015;bgb
1122 mov cl,[bx].SectorsPerCluster
;get total sectors ;an000;bgb;an015;bgb
1123 push bx ;save bpb pointer ;an000;bgb;an015;bgb
1124 xor bx,bx ;clear bx ;an000;bgb
1125 call Multiply_32_Bits
;multiply ;an000;bgb
1126 ;multiply by bytes per sector ;an000;bgb
1127 mov dx,bx ;save bx ;an000;bgb;an015;bgb
1128 pop bx ;get bpb addr ;an000;bgb;an015;bgb
1129 mov cx,[bx].BytePerSector
;get total bytes ;an000;bgb;an015;bgb
1130 mov bx,dx ;restore bx ;an000;bgb;an015;bgb
1131 call Multiply_32_Bits
; multiply ;an000;bgb
1132 ;result is bytes on disk ;an000;bgb
1133 mov tot_bytes_lo
,ax ;save high word ;an000;bgb
1134 mov tot_bytes_hi
,bx ;save low word ;an000;bgb
1136 Calc_Space endp
; ;an000;bgb
1139 ;***************************************************************************** ;an000;bgb
1140 ;Routine name: Check_For_Network ;an000;bgb
1141 ;***************************************************************************** ;an000;bgb
1143 ;Description: See if target drive isn't local, or if it is a shared drive. If ;an000;bgb
1144 ; so, exit with error message. The IOCtl call is not checked for ;an000;bgb
1145 ; an error because it is called previously in another routine, and ;an000;bgb
1146 ; invalid drive is the only error it can generate. That condition ;an000;bgb
1147 ; would not get this far ;an000;bgb
1149 ;Called Procedures: Message (macro) ;an000;bgb
1151 ;Change History: Created 5/1/87 MT ;an000;bgb
1153 ;Input: Drive_Letter_Buffer.Drive_Number ;an000;bgb
1154 ; Fatal_Error = NO ;an000;bgb
1156 ;Output: Fatal_Error = YES/NO ;an000;bgb
1158 ;Psuedocode ;an000;bgb
1159 ;---------- ;an000;bgb
1160 ; See if drive is local (INT 21h, AX=4409 IOCtl) ;an000;bgb
1161 ; IF not local ;an000;bgb
1162 ; Display network message ;an000;bgb
1163 ; Fatal_ERROR = YES ;an000;bgb
1165 ; IF 8000h bit set on return ;an000;bgb
1166 ; Display assign message ;an000;bgb
1167 ; Fatal_Error = YES ;an000;bgb
1171 ;***************************************************************************** ;an000;bgb
1173 Procedure Check_For_Network
; ;an000;bgb;AN000;
1175 mov bl,alldrv
;Drive is 1=A, 2=B ;an000;bgb; ;
1176 mov al,09h ;See if drive is local or remote;an000;bgb;AC000;
1177 DOS_CALL IOCtl
;We will not check for error ;an000;bgb;AC000;
1178 test dx,Net_Check
;if (x & 1200H)(redir or shared);an000;bgb; ;
1179 ; $IF NZ ;Found a net drive ;an000;bgb;AC000;
1181 Message No_Net_Arg
;Tell 'em ;an000;bgb;AC000;
1182 mov Fatal_Error
,Yes
;Indicate bad stuff ;an000;bgb;AN000;
1183 ; $ELSE ;Local drive, now check assign ;an000;bgb;AN000;
1186 test dx,Assign_Check
;8000h bit is bad news ;an000;bgb; ;
1187 ; $IF NZ ;Found it ;an000;bgb;AC000;
1189 Message SubstErr
;Tell error ;an000;bgb;AC000;
1190 mov Fatal_Error
,Yes
;Indicate bad stuff ;an000;bgb;AN000;
1191 ; $ENDIF ; ;an000;bgb;AN000;
1193 ; $ENDIF ; ;an000;bgb;AN000;
1195 ret ; ;an000;bgb;AN000;
1197 Check_For_Network endp
; ;an000;bgb;AN000;
1199 ;***************************************************************************** ;an000;bgb
1200 ;Routine name: Check_Translate_Drive ;an000;bgb
1201 ;***************************************************************************** ;an000;bgb
1203 ;Description: Do a name translate call on the drive letter to see if it is ;an000;bgb
1204 ; assigned by SUBST or ASSIGN ;an000;bgb
1206 ;Called Procedures: Message (macro) ;an000;bgb
1208 ;Change History: Created 5/1/87 MT ;an000;bgb
1210 ;Input: Drive_Letter_Buffer.Drive_Number ;an000;bgb
1211 ; Fatal_Error = NO ;an000;bgb
1213 ;Output: Fatal_Error = YES/NO ;an000;bgb
1215 ;Psuedocode ;an000;bgb
1216 ;---------- ;an000;bgb
1217 ; Put drive letter in ASCIIZ string "d:\",0 ;an000;bgb
1218 ; Do name translate call (INT 21) ;an000;bgb
1219 ; IF drive not same ;an000;bgb
1220 ; Display assigned message ;an000;bgb
1221 ; Fatal_Error = YES ;an000;bgb
1224 ;***************************************************************************** ;an000;bgb
1225 Procedure Check_Translate_Drive
; ;an000;bgb;AN000;
1226 call func60
; ;an000;bgb
1227 mov bl,byte ptr [TranSrc
] ;Get drive letter from path ;an000;bgb; ;
1228 cmp bl,byte ptr [Chkprmt_End
] ;Did drive letter change? ;an000;bgb; ;
1229 ; $IF NE ;If not the same, it be bad ;an000;bgb;AC000;
1231 Message SubstErr
;Tell user ;an000;bgb;AC000;
1232 mov Fatal_Error
,Yes
;Setup error flag ;an000;bgb;AN000;
1233 ; $ENDIF ; ;an000;bgb;AN000;
1235 ret ; ;an000;bgb;AN000;
1236 Check_Translate_Drive endp
; ;an000;bgb;AN000;
1239 Procedure func60
; ;an000;bgb;AN000;
1240 ; PUSH DS ;ICE ;an000;bgb
1241 ; push bx ;ICE ;an000;bgb
1242 ; push ax ;ICE ;an000;bgb
1244 ; mov bx,0140H ;ICE ;an000;bgb
1245 ; xor ax,ax ;ICE ;an000;bgb
1246 ; mov ds,ax ;ICE ;an000;bgb
1247 ; mov ax,word ptr ds:[bx] ;ICE ;an000;bgb
1248 ; mov word ptr ds:[bx],ax ;ICE ;an000;bgb
1250 ; pop ax ;ICE ;an000;bgb
1251 ; pop bx ;ICE ;an000;bgb
1252 ; POP DS ;ICE ;an000;bgb
1254 mov byte ptr [transrc
],'A' ;an000;bgb
1255 mov bl,alldrv
;Get drive ; ;an000;bgb ;
1256 dec bl ;Make it 0 based ;an000;bgb;AN001;
1257 add byte ptr [TranSrc
],bl ;Make string "d:\" ;an000;bgb; ;
1258 lea si,TranSrc
;Point to translate string ;an000;bgb; ;
1259 push ds ;Set ES=DS (Data segment) ;an000;bgb; ;
1260 pop es ; " " " " ;an000;bgb; ;
1261 lea di,Chkprmt_End
;Point at output buffer ;an000;bgb; ;
1262 DOS_Call xNameTrans
;Get real path ;an000;bgb;AC000;
1263 ret ; ;an000;bgb;AN000;
1264 func60 endp
; ;AN000; ;an000;bgb
1267 ;***************************************************************************** ;an000;bgb
1268 ;Routine name: Hook_Interrupts ;an000;bgb
1269 ;***************************************************************************** ;an000;bgb
1271 ;Description: Change the interrupt handler for INT 13h to point to the ;an000;bgb
1272 ; ControlC_Handler routine ;an000;bgb
1274 ;Called Procedures: None ;an000;bgb
1276 ;Change History: Created 4/21/87 MT ;an000;bgb
1278 ;Input: None ;an000;bgb
1280 ;Output: None ;an000;bgb
1282 ;Psuedocode ;an000;bgb
1283 ;---------- ;an000;bgb
1285 ; Point at ControlC_Handler routine ;an000;bgb
1286 ; Set interrupt handler (INT 21h, AX=2523h) ;an000;bgb
1288 ;***************************************************************************** ;an000;bgb
1290 procedure Hook_Interrupts
; ;an000;bgb;AN000;
1292 mov al,23h
;an000;bgb
1293 DOS_Call Get_Interrupt_Vector
;Get the INT 23h handler ;an000;bgb;AC000;
1294 mov word ptr [CONTCH
],bx ; ;an000;bgb
1295 mov bx,es ; ;an000;bgb;AN000;
1296 mov word ptr [CONTCH
+2],bx ; ;an000;bgb
1297 mov al,23h
;Specify CNTRL handler ;an000;bgb; ;
1298 lea dx, INT_23
;Point at it ;an000;bgb; ;
1299 push ds ;Save data seg ;an000;bgb; ;
1300 push cs ;Point to code segment ;an000;bgb; ;
1301 pop ds ; ;an000;bgb; ;
1302 DOS_Call Set_Interrupt_Vector
;Set the INT 23h handler ;an000;bgb;AC000;
1303 pop ds ;Get Data degment back ;an000;bgb; ;
1304 mov al,24h
; ;an000;bgb
1305 DOS_Call Get_Interrupt_Vector
;Get the INT 24h handler ;an000;bgb;AC000;
1306 mov word ptr [HardCh
],bx ;Save it ;an000;bgb
1307 mov bx,es ; ;an000;bgb
1308 mov word ptr [HardCh
+2],bx ; ;an000;bgb
1309 mov al,24h
;Specify handler ;an000;bgb ; ;
1310 lea dx, INT_24
;Point at it ;an000;bgb; ;
1311 push ds ;Save data seg ;an000;bgb; ;
1312 push cs ;Point to code segment ;an000;bgb; ;
1313 pop ds ; ;an000;bgb; ;
1314 DOS_Call Set_Interrupt_Vector
;Set the INT 23h handler ;an000;bgb;AC000;
1315 pop ds ;Get Data degment back ;an000;bgb; ;
1316 ret ; ;an000;bgb;AN000;
1318 hook_Interrupts endp
; ;an000;bgb;AN000;
1320 ;***************************************************************************** ;an000;bgb
1321 ;Routine name: Clear_Append_X ;an000;bgb
1322 ;***************************************************************************** ;an000;bgb
1324 ;Description: Determine if Append /XA is turned on thru INT 2Fh, and shut ;an000;bgb
1325 ; off for life of CHKDSK if it is. ;an000;bgb
1327 ;Called Procedures: None ;an000;bgb
1330 ;Change History: Created 5/13/87 MT ;an000;bgb
1332 ;Input: None ;an000;bgb
1334 ;Output: APPEND = YES/NO ;an000;bgb
1336 ;Psuedocode ;an000;bgb
1337 ;---------- ;an000;bgb
1339 ; Append = NO ;an000;bgb
1340 ; See if APPEND /X is present (INT 2Fh, AX=0B706h) ;an000;bgb
1341 ; IF present ;an000;bgb
1342 ; Turn append /X off (INT 2Fh, AX=B707h, BX = 0) ;an000;bgb
1343 ; Append = YES ;an000;bgb
1346 ;***************************************************************************** ;an000;bgb
1348 Procedure Clear_Append_X
; ;an000;bgb ;AN000;
1350 mov Append
,NO
;Init the Append /X flag ;an000;bgb;AN000;
1351 mov ax,Append_X
;Is Append /X there? ;an000;bgb;AN000;
1352 int Multiplex
; " " " " ;an000;bgb;AN000;
1353 cmp bx,Append_X_Set
;Was it turned on? ;an000;bgb;AN000;
1354 ; $IF E ;Yep ;an000;bgb;AN000;
1356 mov Append
,YES
;Indicate that it was on ;an000;bgb;AN000;
1357 mov ax,Set_Append_X
;Turn Append /X off ;an000;bgb;AN000;
1358 mov bx,Append_Off
; " " " " ;an000;bgb;AN000;
1359 int Multiplex
; " " " " ;an000;bgb;AN000;
1360 ; $ENDIF ; ;an000;bgb;AN000;
1362 ret ; ;an000;bgb;AN000;
1364 Clear_Append_X endp
; ;an000;bgb;AN000;
1367 ;***************************************************************************** ;an000;bgb
1368 ;Routine name: CHKDSK_IFS ;an000;bgb
1369 ;***************************************************************************** ;an000;bgb
1371 ;Description: ;an000;bgb
1373 ;Called Procedures: Main_Routine ;an000;bgb
1374 ; EXEC_FS_CHKDSK ;an000;bgb
1377 ;Change History: Created 5/8/87 MT ;an000;bgb
1379 ;Input: FS_Not_FAT = Yes/No ;an000;bgb
1381 ;Output: None ;an000;bgb
1383 ;Psuedocode ;an000;bgb
1384 ;---------- ;an000;bgb
1386 ; IF File system other than FAT ;an000;bgb
1387 ; Go call file system specific CHKDSK (CALL Exec_FS_CHKDSK) ;an000;bgb
1389 ; Do FAT based CHKDSK (CALL Main_Routine) ;an000;bgb
1391 ; Restore current drive (CALL Done) ;an000;bgb
1393 ;***************************************************************************** ;an000;bgb
1396 Procedure CHKDSK_IFS
; ;an000;bgb;AN000;
1398 ifdef fsexec
;an038;bgb
1399 cmp FS_Not_Fat
,YES
;Is the target FS a FAT? ;an038;bgb;AN000;
1400 ; $IF E ;No, so need to exec the ;an038;bgb;AN000;
1402 call EXEC_FS_CHKDSK
; file system specific prog. ;an038;bgb;AN000;
1403 ; $ELSE ;It's a FAT ;an038;bgb;AN000;
1407 call Main_Routine
;Use canned code! ;an038;bgb;AN000;
1408 ifdef fsexec
;an038;bgb
1409 ; $ENDIF ; ;an038;bgb;AN000;
1412 call Done
;Restore current drive ;an000;bgb;AN000;
1413 ret ; ;an000;bgb;AN000;
1415 CHKDSK_IFS endp
; ;an000;bgb;AN000;
1417 ;***************************************************************************** ;an000;bgb
1418 ;Routine name: Reset_Append_X ;an000;bgb
1419 ;***************************************************************************** ;an000;bgb
1421 ;description: If APPEND /XA was on originally, turn it back on ;an000;bgb
1423 ;Called Procedures: None ;an000;bgb
1426 ;Change History: Created 5/13/87 MT ;an000;bgb
1428 ;Input: None ;an000;bgb
1430 ;Output: APPEND = YES/NO ;an000;bgb
1432 ;Psuedocode ;an000;bgb
1433 ;---------- ;an000;bgb
1435 ; IF APPEND = YES ;an000;bgb
1436 ; Turn append /X on (INT 2Fh, AX=B707h, BX = 1) ;an000;bgb
1439 ;***************************************************************************** ;an000;bgb
1441 Procedure Reset_Append_X
; ;an000;bgb;AN000;
1443 cmp Append
,Yes
;Was Append /X on to start with?;an000;bgb;AN000;
1444 ; $IF E ;Yep ;an000;bgb;AN000;
1446 mov ax,Set_Append_X
;Turn Append /X off ;an000;bgb;AN000;
1447 mov bx,Append_On
; " " " " ;an000;bgb;AN000;
1448 int Multiplex
; " " " " ;an000;bgb;AN000;
1449 ; $ENDIF ; ;an000;bgb;AN000;
1451 ret ; ;an000;bgb;AN000;
1453 Reset_Append_X endp
; ;an000;bgb;AN000;
1455 ;***************************************************************************** ;an000;bgb
1456 ;Routine name: Multiply_32_Bits ;an000;bgb
1457 ;***************************************************************************** ;an000;bgb
1459 ;Description: A real sleazy 32 bit x 16 bit multiply routine. Works by adding ;an000;bgb
1460 ; the 32 bit number to itself for each power of 2 contained in the ;an000;bgb
1461 ; 16 bit number. Whenever a bit that is set in the multiplier (CX) ;an000;bgb
1462 ; gets shifted to the bit 0 spot, it means that that amount has ;an000;bgb
1463 ; been multiplied so far, and it should be added into the total ;an000;bgb
1464 ; value. Take the example CX = 12 (1100). Using the associative ;an000;bgb
1465 ; rule, this is the same as CX = 8+4 (1000 + 0100). The ;an000;bgb
1466 ; multiply is done on this principle - whenever a bit that is set ;an000;bgb
1467 ; is shifted down to the bit 0 location, the value in BX:AX is ;an000;bgb
1468 ; added to the running total in DI:SI. The multiply is continued ;an000;bgb
1469 ; until CX = 0. The routine will exit with CY set if overflow ;an000;bgb
1470 ; occurs. ;an000;bgb
1473 ;Called Procedures: None ;an000;bgb
1475 ;Change History: Created 7/23/87 MT ;an000;bgb
1477 ;Input: BX:AX = 32 bit number to be multiplied ;an000;bgb
1478 ; CX = 16 bit number to be multiplied. (Must be even number) ;an000;bgb
1480 ;Output: BX:AX = output. ;an000;bgb
1481 ; CY set if overflow ;an000;bgb
1483 ;Psuedocode ;an000;bgb
1484 ;---------- ;an000;bgb
1486 ; Point at ControlC_Handler routine ;an000;bgb
1487 ; Set interrupt handler (INT 21h, AX=2523h) ;an000;bgb
1489 ;***************************************************************************** ;an000;bgb
1491 Public Multiply_32_Bits
;an000;bgb
1492 Multiply_32_Bits proc
; ;an000;bgb;AN000;
1494 push di ; ;an000;bgb;AN000;
1495 push si ; ;an000;bgb;AN000;
1496 xor di,di ;Init result to zero ;an000;bgb
1497 xor si,si ; ;an000;bgb
1498 cmp cx,0 ;Multiply by 0? ;an000;bgb;AN000;
1499 ; $IF NE ;Keep going if not ;an000;bgb;AN000;
1501 ; $DO ;This works by adding the result;an000;bgb;AN000;
1503 test cx,1 ;Need to add in sum of this bit?;an000;bgb;AN000;
1504 ; $IF NZ ;Yes ;an000;bgb;AN000;
1506 add si,ax ;Add in the total so far for ;an000;bgb;AN000;
1507 adc di,bx ; this bit multiplier (CY oflow);an000;bgb;AN000;
1508 ; $ELSE ;Don't split multiplier ;an000;bgb;AN000;
1511 clc ;Force non exit ;an000;bgb;AN000;
1512 ; $ENDIF ; ;an000;bgb;AN000;
1514 ; $LEAVE C ;Leave on overflow ;an000;bgb;AN000;
1516 shr cx,1 ;See if need to multiply value ;an000;bgb;AN000;
1517 cmp cx,0 ;by 2 ;an000;bgb;AN000;
1518 ; $LEAVE E ;Done if cx shifted down to zero;an000;bgb;AN000;
1520 add ax,ax ;Each time cx is shifted, add ;an000;bgb;AN000;
1521 adc bx,bx ;value to itself (Multiply * 2) ;an000;bgb;AN000;
1522 ; $ENDDO C ;CY set on overflow ;an000;bgb;AN000;
1525 ; $IF NC ;If no overflow, add in DI:SI ;an000;bgb;AN000;
1527 mov ax,si ; which contains the original ;an000;bgb;AN000;
1528 mov bx,di ; value if odd, 0 if even. This ;an000;bgb;AN000;
1529 clc ;Set no overflow flag ;an000;bgb;AN000;
1530 ; $ENDIF ; ;an000;bgb;AN000;
1532 ; $ELSE ; ;an000;bgb
1535 xor ax,ax ; ;an000;bgb
1536 xor bx,bx ; ;an000;bgb
1537 ; $ENDIF ;Multiply by 0 ;an000;bgb;AN000;
1539 pop si ; ;an000;bgb;AN000;
1540 pop di ; ;an000;bgb;AN000;
1541 ret ; ;an000;bgb;AN000;
1543 Multiply_32_Bits endp
;an000;bgb
1544 pathlabl chkinit
;an000;bgb
1545 code ends
;an000;bgb