3 ;*****************************************************************************
5 ;*****************************************************************************
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
20 ;*****************************************************************************
22 ;*****************************************************************************
23 data 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
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
41 ;*****************************************************************************
43 ;*****************************************************************************
44 code segment public para
'CODE' ;AC000;bgb
46 public report
;AN000;bgb
47 public Read_Disk
;AN000;bgb
48 public Write_Disk
;AN000;bgb
49 public Build_String
;AN000;bgb
50 public ChANge_BlANks
;AN000;bgb
51 public Check_DBCS_CharACter
;AN000;bgb
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 ;*************************************************************
59 Procedure report
,near ; ;AN000;bgb
61 mov si,[di+16] ;Get the XXX value
65 mov si,filsiz
;Get the YYY value
69 call display_interface
; AC000;SM
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
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
84 ; Outputs : Logical sectors read ;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
96 ; perform a disk read for less than sectors-per-64k ;an005;bgb
97 ;========================================================================= ;an005;bgb
98 procedure 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
104 cmp cx,secs_per_64k
;an000;exceed 64k ;an005;bgb
105 ; $LEAVE LE ;an000;yes ;an005;bgb
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
113 add cx,paras_per_64k
; adjust transfer area ;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
121 call read_once
;an000;read it ;an005;bgb
122 restorereg
<es,dx,cx,bx,ax>
124 read_disk endp
;an005;bgb
127 ;***************************************************************************** ;an005;bgb
128 ;Routine name: Read_once ;an005;bgb
129 ;***************************************************************************** ;an005;bgb
131 ;description: Read in data using Generic IOCtl ;an005;bgb
133 ;Called Procedures: None ;an005;bgb
136 ;Change History: Created 5/13/87 MT ;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
144 ;Output: CY if error ;an005;bgb
145 ; AH = INT 25h error code ;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
154 ;***************************************************************************** ;an005;bgb
155 Procedure 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
168 Read_once endp
;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
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
182 ; Outputs : Logical sectors read ;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
194 ; perform a disk read for less than sectors-per-64k ;an005;bgb
195 ;========================================================================= ;an005;bgb
196 procedure 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
201 cmp cx,secs_per_64k
;an000;exceed 64k ;an005;bgb
202 ; $LEAVE LE ;an000;yes ;an005;bgb
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
210 add cx,paras_per_64k
; adjust transfer area ;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
218 call write_once
;an000;read it ;an005;bgb
220 write_disk endp
;an005;bgb
222 ;*****************************************************************************
223 ;Routine name: Write_Once
224 ;*****************************************************************************
226 ;description: Write Data using int 26
228 ;Called Procedures: None
231 ;Change History: Created 5/13/87 MT
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
240 ; AH = INT 26h error code
245 ; Setup structure for function call
246 ; Write to disk (AX=440Dh, CL = 4Fh)
249 ;*****************************************************************************
250 Procedure 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
263 Write_once endp
; ;AN000;bgb
265 ;========================================================================= ;an005;bgb
266 ; SEG_ADJ : This routine adjusts the segment:offset to prevent ;an005;bgb
267 ; address wrap. ;an005;bgb
269 ; Inputs : bx - Offset to adjust segment with ;an005;bgb
270 ; es - Segment to be adjusted ;an005;bgb
272 ; Outputs : bx - New offset ;an005;bgb
273 ; es - Adjusted segment ;an005;bgb
274 ;========================================================================= ;an005;bgb
275 procedure 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
287 seg_adj endp
;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
294 ; Inputs : DPB_SECTOR_SIZE - bytes/sector ;an005;bgb
296 ; Outputs : SECS_PER_64K - Sectors / 64k ;an005;bgb
297 ; PARAS_PER_64K - paragraphs per 64k ;an005;bgb
298 ;========================================================================= ;an005;bgb
299 procedure 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
314 calc_sp64k endp
;an000; ;an005;bgb
317 ;*****************************************************************************
318 ;Routine name: Build_String
319 ;*****************************************************************************
321 ;Description: Build AN ASCIIZ string from the FCB filename input.
323 ;Called Procedures: None
325 ;ChANge History: Created 6/29/87 MT
327 ;Input: DS:SI = String containing FCB input
328 ; ES:DI = Where to build string
330 ;Output: ES:DI = Input string starting at first non-blANk charACter
337 ; LEAVE Next charACter is 0,OR
338 ; LEAVE 12th charACter,OR
343 ; Set next charACter to 0
346 ;*****************************************************************************
348 Procedure 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;
356 cmp byte ptr [si],ASCIIZ_END
;Is next charACter 0? ;AN000;
357 ; $LEAVE E,OR ;Yes, end loop ;AN000;
359 cmp cx,FCB_Filename_Length
;Looked at 11 chars? ;AN000;
360 ; $LEAVE E,OR ;Yes, end of string ;AN000;
362 lodsb ;Nope, get charACter ;AN000;
363 cmp al,BlANk
;Find end of filename? ;AN000;
364 ; $LEAVE E ;Yes, quit looping ;AN000;
367 inc cx ;No, inc counter ANd try next ;AN000;
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;
376 Build_String endp
; ;AN000;
378 ;*****************************************************************************
379 ;Routine name: ChANge_BlANks
380 ;*****************************************************************************
382 ;Description: ReplACe all DBCS blANks with SBCS blANks
384 ;Called Procedures: Check_DBCS_CharACter
386 ;ChANge History: Created 6/12/87 MT
388 ;Input: DS:SI = ASCIIZ string containing volume label input
390 ;Output: DS:SI = ASCIIZ string with all DBCS blANks replACed with 2 SBCS blANks
396 ; Save pointer to string
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
405 ; Point to next byte to compensate for DBCS charACter
408 ; Restore pointer to string
410 ;*****************************************************************************
411 Procedure ChANge_BlANks
; ;AN000;
412 ; $DO ;Do while not CR ;AN000;
414 cmp byte ptr [si],Asciiz_End
;Is it end of string? ;AN000;
415 ; $LEAVE E ;All done if so ;AN000;
417 call Check_DBCS_CharACter
;Test for dbcs lead byte ;AN000;
418 ; $IF C ;We have a lead byte ;AN000;
420 cmp byte ptr [si],DBCS_Lead
;Is it a lead blANk? ;AN000;
421 ; $IF E,AND ;If a dbcs char ;AN000;
423 cmp byte ptr [si+1],DBCS_BlANk
;Is it AN AsiAN blANk? ;AN000;
424 ; $IF E ;If AN AsiAN blANk ;AN000;
426 mov byte ptr [si+1],BlANk
;set up moves ;AN000;
427 mov byte ptr [si],BlANk
; to replACe ;AN000;
430 inc si ;Point to dbcs char ;AN000;
431 ; $ENDIF ;End lead byte test ;AN000;
433 inc si ;Point to si+1 ;AN000;
434 ; $ENDDO ;End do while ;AN000;
437 ret ;return to caller ;AN000;
438 ChANge_BlANks endp
; ;AN000;
441 ;*****************************************************************************
442 ;Routine name: Check_DBCS_CharACter
443 ;*****************************************************************************
445 ;Description: Check if specified byte is in rANges of DBCS vectors
447 ;Called Procedures: None
449 ;ChANge History: Created 6/12/87 MT
451 ;Input: AL = CharACter to check for DBCS lead charACter
452 ; DBCS_Vector = YES/NO
454 ;Output: CY set if DBCS charACter
461 ; IF DBCS vector not found
462 ; Get DBCS environmental vector (INT 21h
463 ; Point at first set of vectors
466 ; LEAVE End of DBCS vectors
467 ; EXITIF CharACter > X1,AND (X1,Y1) are environment vectors
468 ; EXITIF CharACter < Y1
469 ; STC (DBCS charACter)
471 ; Inc pointer to next set of vectors
473 ; CLC (Not DBCS charACter)
477 ;*****************************************************************************
478 Procedure 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;
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;
493 mov es:DBCS_Vector_Seg
,ax ; ;AN000;
494 ; $ENDIF ; for next time in ;AN000;
496 pop ax ;Restore input charACter ;AN000;
497 mov si,es:DBCS_Vector_Seg
;Get saved vector pointer ;AN000;
499 mov si,es:DBCS_Vector_Off
; ;AN000;
500 ; $SEARCH ;Check all the vectors ;AN000;
502 cmp word ptr ds:[si],End_Of_Vector
;End of vector table? ;AN000;
503 ; $LEAVE E ;Yes, done ;AN000;
505 cmp al,ds:[si] ;See if char is in vector ;AN000;
506 ; $EXITIF AE,AND ;If >= to lower, ANd ;AN000;
508 cmp al,ds:[si+1] ; =< thAN higher rANge ;AN000;
509 ; $EXITIF BE ; then DBCS charACter ;AN000;
511 stc ;Set CY to indicate DBCS ;AN000;
512 ; $ORELSE ;Not in rANge, check next ;AN000;
515 add si,DBCS_Vector_Size
;Get next DBCS vector ;AN000;
516 ; $ENDLOOP ;We didn't find DBCS char ;AN000;
519 clc ;Clear CY for exit ;AN000;
522 pop ax ;Restore registers ;AN000;
523 pop si ; " " " " ;AN000;
524 pop ds ;Restore data segment ;AN000;
526 Check_DBCS_CharACter endp
; ;AN000;