]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/SYS/SYS2.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / CMD / SYS / SYS2.ASM
1 TITLE SYS-2- Program
2 include version.inc
3 INCLUDE SYSHDR.INC
4
5 page 80,132
6 BREAK <SYS2 - Program Organization>
7 ;******************+ START OF PSEUDOCODE +**************************************
8 ; Ä Ä Ä Ä Ä Ä Ä Ä¿ ÚÄÄÄÄÄÄÄÄÄ¿
9 ; Read_Directory ÃÄÄÄÄÄÄ´Find_DPB ³
10 ; Ä Ä Ä Ä Ä Ä Ä ÄÙ ÀÄÄÄÄÄÄÄÄÄÙ
11 ; Ä Ä Ä Ä Ä Ä Ä Ä Ä ÄÄ¿
12 ; Verify_File_LocationÃÄ¿
13 ; Ä Ä Ä Ä Ä Ä Ä Ä Ä ÄÄÙ ³
14 ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
15 ; ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä Ä Ä Ä ¿
16 ; ÃÄ´Move_DIR_EntryÃÄÄ´Find_Empty_Entry ÃÄÄ´Direct_Access³
17 ; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ä Ä Ä Ù
18 ; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
19 ; ³ À´Direct_Access³
20 ; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
21 ; ³ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22 ; ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄ¿
23 ; ÀÄ´Free_ClusterÃÄÄÄÄ´Is_It_EmptyÃÄÄÄÄÄÄÄÄ´Unpack ³
24 ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÙ
25 ; ³ÚÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
26 ; ôSearch_FATÃÄÄÄÄÄÄÄÄ´Unpack ³
27 ; ³ÀÄÄÄÄÄÄÄÄÄÄÙ ³À Ä Ä Ä Ù
28 ; ³ ³ÚÄÄÄÄÄÄ¿
29 ; ³ ôPack ³
30 ; ³ ³ÀÄÄÄÄÄÄÙ
31 ; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
32 ; ³ ôFind_Empty_Cluster³ÄÄ´Unpack ³
33 ; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ù
34 ; ³ ³ÚÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä Ä Ä Ä ¿
35 ; ³ ôXfer_DataÃÄÄÄÄÄÄÄÄÄÄÄ´Direct_Access³
36 ; ³ ³ÀÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ä Ä Ä Ù
37 ; ³ ³Ú Ä Ä Ä Ä Ä Ä ¿
38 ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À´Direct_Access³
39 ; ³ À Ä Ä Ä Ä Ä Ä Ù
40 ; ³ÚÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
41 ; À´Search_DIRÃÄÄÄÄ´Search_LoopÃÄÄÄÄÄ´Unpack ³
42 ; ÀÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÙ ³À Ä Ä Ä Ù
43 ; ³ÚÄÄÄÄÄÄ¿
44 ; ôPack ³ Direct_Access
45 ; ³ÀÄÄÄÄÄÄÙ
46 ; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
47 ; ôFind_Empty_Cluster³ÄÄ´Unpack ³
48 ; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ù
49 ; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
50 ; ôSub_DIR_Loop³ÄÄ´Unpack ³
51 ; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ù
52 ; ³ÚÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä Ä Ä Ä ¿
53 ; ôXfer_DataÃÄÄÄÄÄÄÄÄÄÄÄ´Direct_Access³
54 ; ³ÀÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ä Ä Ä Ù
55 ; ³Ú Ä Ä Ä Ä Ä Ä ¿
56 ; À´Direct_Access³
57 ; À Ä Ä Ä Ä Ä Ä Ù
58 ;
59 ;******************+ END OF PSEUDOCODE +*****************************************
60 BREAK <SYS2 - Data space>
61
62 DATA SEGMENT PARA PUBLIC
63
64 extrn TargDrvNum:BYTE, TargSpec:WORD, bio_owns_it:BYTE, DOS_VER:BYTE
65 extrn packet_sectors:WORD, packet_buffer:WORD, packet:WORD
66
67 public THIS_DPB, BUF, DIR_SECTOR, first_dir_sector
68
69
70 ; $SALUT (4,25,30,41)
71
72 first_dir_sector dw ?
73 current_dir_sector dw ?
74 last_dir_sector dw ?
75 entries_per_sector db ?
76 current_entry db 3
77 source_ptr dw ?
78 ibmbio_status db ?
79 ibmdos_status db ?
80 FAT_sectors dw FAT_sect_size ; initailize it to 12 sectors
81 FAT_changed db 0 ; FAT must be written - its packed
82 FAT_2 db 0 ; if non zero, [packet] points at FAT 2
83 cluster_count dw ? ; number of clusters that must be free
84 last_cluster dw 0 ; cluster pointing to [current_cluster]
85 current_cluster dw 2 ; start at cluster 2
86 next_cluster dw 0 ; cluster [current_cluster] points at
87 empty_cluster dw 0 ; newly aquired cluster
88 cluster_low dw 0
89 cluster_high dw clusters_loaded
90
91 l_sector_offset dw ? ; this is the value required to convert
92 ; a sector from a cluster # to a
93 ; logical sector # for INT 25 & 26
94
95 DIR_cluster dw 0 ; Sub DIR cluster being processed
96 ; = 0 - not processing s Sub DIR
97 ; = 1 - starting to process
98 ; (set by Search_Loop)
99 ; = n - Sub DIR cluster now being
100 ; processed. (set by Xfer_Data)
101 present_cluster dw ? ; current cluster for DIR search
102 sector_offset dw ? ; current sector in present_cluster
103 entry_number db ? ; DIR entry in current sector
104 FRAME_ptr dw ?
105 dir_sector_low dw ?
106 dir_sector_hi dw ?
107 DIR_offset dw ?
108 sector_count db 1
109
110 FRAME STRUC
111
112 p_cluster dw ? ; current cluster for DIR search
113 s_offset dw ? ; current sector in present_cluster
114 e_number db ? ; DIR entry in current sector
115
116 FRAME ENDS
117
118 BIGFAT DB 0 ;0=12 bit FAT, NZ=16bit FAT
119 EOFVAL DW 0FF8H ;0FF8 for 12 bit FAT,0FFF8 for 16 bit
120 BADVAL DW 0FF7H ;0FF7 for 12 bit FAT,0FFF7 for 16 bit
121
122 THIS_DPB DD ? ;Pointer to drive DPB
123 CSIZE DW ? ;Sectors per cluster
124 SSIZE DW ? ;bytes per sector
125 DSIZE DW ? ;# alloc units on disk
126 FSIZE DW ? ;# sectors in 1 FAT
127 first_FAT DW ? ; first cluster of first FAT
128 num_of_FATS db ? ; number of FATS
129 MCLUS DW ? ;DSIZE + 1
130 ;
131 ; The following is used as the source/destination for a name trans
132 ;
133 ENTRY_BUF DB size dir_entry DUP (?)
134 DIR_BUF DB ( 34 * size frame) DUP (?) ; space for DIR frames - see Search_DIR
135 DIR_SECTOR DB 512 DUP (?) ; space for 1 DIR sector
136
137 BUF LABEL BYTE ; beginning of area for file reads
138
139 DATA ENDS
140
141 ; $SALUT (4,4,9,41)
142
143 CODE SEGMENT PARA PUBLIC
144
145 ASSUME cs:CODE, ds:nothing, es:nothing
146
147 BREAK <SYS - Find_DPB >
148 ;******************* START OF SPECIFICATIONS ***********************************
149 ;Routine name: Find_DPB
150 ;*******************************************************************************
151 ;
152 ;Description: Find_DPB gets the pointer to the Target DPB and initializes all
153 ; local valiables required by Move_DIR_Entry and Free_Cluster.
154 ;
155 ;NOTE: This routine contains code that is specific for DOS 3.3. It
156 ; must be removed for subsequent releases. In and before
157 ; DOS 3.3 the DPB was one byte smaller. The field dpb_FAT_size
158 ; was changed from a byte to a word in DOS 4.00.
159 ;
160 ;
161 ;Entry: Called by Verify_File_Location
162 ;
163 ;Called Procedures:
164 ;
165 ; INT 21 - 32h
166 ;
167 ;Input: al = Drive number
168 ;
169 ;Output: All local variables initalized
170 ; DS:BX = pointer to DPB
171 ;
172 ;Change History: Created 7/01/87 FG
173 ;
174 ;******************* END OF SPECIFICATIONS *************************************
175 ;******************+ START OF PSEUDOCODE +**************************************
176 ;
177 ; START Find_DPB
178 ;
179 ; get DPB pointer (INT 21 - 32h)
180 ; initalize first_dir_sector
181 ; initalize current_dir_sector
182 ; initalize current_cluster (0 for root)
183 ; calculate # of clusters required by IBMBIO
184 ; initalize [cluster_count]
185 ; calculate # of dir sectors
186 ; initalize [dir_sectors]
187 ; initalize [current_entry] to #3
188 ; allocate memory for FAT + 32 DIR frames
189 ; allocate memory for data sectors
190 ;
191 ; ret
192 ;
193 ; END Find_DPB
194 ;
195 ;******************- END OF PSEUDOCODE -**************************************
196
197
198 PUBLIC Find_DPB
199
200 Find_DPB PROC NEAR
201
202 MOV AH,GET_DPB ;Get the DPB ;AN004;
203 INT 21H
204
205 mov ax,(disk_reset shl 8) ; reset the disk to protect all INT 26's
206 INT 21h ; that follow
207
208
209 ; initalize current_entry to #3
210
211 ASSUME ds:nothing,es:DATA
212
213 MOV WORD PTR [THIS_DPB+2],DS ; ;AN004;
214 push es ; ;AN004;
215 pop ds ; ;AN004;
216
217 ASSUME ds:DATA
218
219 mov WORD PTR [THIS_DPB],bx ; ;AN004;
220 lds bx,[THIS_DPB] ; ;AN004;
221
222 ASSUME ds:nothing
223
224 mov ax,[bx.dpb_sector_size] ; ;AN004;
225 mov [SSIZE],ax ;Sector size in bytes ;AN004;
226
227 xor ax,ax ; ;AN004;
228 mov al,[bx.dpb_cluster_mask] ; ;AN004;
229 inc al ; ;AN004;
230 mov [CSIZE],ax ;Sectros per cluster ;AN004;
231
232 mov ax,[BX.dpb_first_FAT] ;First sector of FAT ;AN004;
233 mov [first_FAT],ax ; ;AN004;
234
235 mov al,[BX.dpb_FAT_count] ;Number of FATs ;AN004;
236 mov [num_of_FATS],al ; ;AN004;
237
238 mov ax,[bx.dpb_max_cluster] ; ;AN004;
239 mov [MCLUS],ax ;Bound for FAT searching ;AN004;
240
241 cmp ax,4096-10 ;Big or little FAT? ;AN004;
242 ; $if ae ; ;AN004;
243 JNAE $$IF1
244 inc [BIGFAT] ; ;AN004;
245 mov [EOFVAL],0FFF8h ; ;AN004;
246 mov [BADVAL],0FFF7h ; ;AN004;
247 ; $endif ; ;AN004;
248 $$IF1:
249 dec ax ; ;AN004;
250 mov [DSIZE],ax ;Total data clusters on disk ;AN004;
251
252 ;--------------------------------------
253 ; calculate # of dir sectors and
254 ; initalize last_dir_sector
255 ;--------------------------------------
256 mov ax,[bx.dpb_root_entries] ; max # of entries in the root ;AN004;
257 mov cx,size dir_entry ; size of each entry ;AN004;
258 mul cx ; size of root directory in bytes ;AN004;
259 ; in AX:DX ;AN004;
260 mov cx,[SSIZE] ; # of bytes per sector ;AN004;
261 div cx ; = # of root directory sectors ;AN004;
262 cmp dx,0 ; any remainder ? ;AN004;
263 ; $if nz ; ;AN004;
264 JZ $$IF3
265 inc ax ; ;AN004;
266 ; $endif ; ;AN004;
267 $$IF3:
268 mov [first_dir_sector],ax ; save for last directory sector calc. ;AN004;
269
270 mov ax,[bx.dpb_FAT_size] ;Sectors for one fat ;AN004;
271 cmp DOS_VER,0 ; running on current version? ;AN019;
272
273 ; $if ne ; BANG! - we'er running on DOS 3.3 ;AN019;
274 JE $$IF5
275 ; dpb_FAT_size is only a BYTE
276 ; so ajust it to a word
277 xor ah,ah ;AN019;
278 dec bx ; BACK UP the index into the DPB ;AN019;
279 mov WORD PTR [THIS_DPB],bx ; save it for later (dpb_next_free) ;AN021;
280 ; Now everything else lines up !
281 ; $endif
282 $$IF5:
283
284 mov [FSIZE],ax ; ;AN004;
285
286 mov ax,[SSIZE] ; ;AN004;
287 mov cx,SIZE dir_entry ; ;AN004;
288 div cx ; ;AN004;
289 dec ax ; first entry number is zero ;AN004;
290 mov [entries_per_sector],al ; ;AN004;
291 cmp [BIGFAT],0 ; is it a big fat ? ;AN004;
292
293 ; $if e ; if not ;AN004;
294 JNE $$IF7
295 mov ax,[FSIZE] ; ;AN004;
296 mov [FAT_sectors],ax ; bring it down to the actual size ;AN004;
297 ; $endif ; ;AN004;
298 $$IF7:
299 ;--------------------------------------
300 ; initalize first_dir_sector
301 ; and current_dir_sector
302 ;--------------------------------------
303 mov ax,[bx.dpb_dir_sector] ; first dir sector ;AN004;
304 mov [current_dir_sector],ax ; save it for later ;AN004;
305 xchg [first_dir_sector],ax ; save it and recover # of dir sectors ;AN004;
306
307 add ax,[first_dir_sector] ; # of last directory sector ;AN004;
308 mov [l_sector_offset],ax ; ;AN004;
309 dec ax ; ;AN004;
310 mov [last_dir_sector],ax ; save it for later ;AN004;
311
312 ret ; ;AN004;
313
314 Find_DPB ENDP
315
316 BREAK <SYS - Move_DIR_Entry >
317 ;******************* START OF SPECIFICATIONS ***********************************
318 ;Routine name: Move_DIR_Entry
319 ;*******************************************************************************
320 ;
321 ;Description: Move_DIR_Entry will move the entry pointed to by the caller into
322 ; the first available location in the root, if one exists.
323 ;
324 ;Entry: Called by Verify_File_Location
325 ;
326 ;Called Procedures:
327 ;
328 ; Find_Empty_Entry - find an available entry
329 ; Direct_Access - do an INT 25 & INT 26
330 ;
331 ;Input: first_dir_sector
332 ; current_dir_sector
333 ; last_dir_sector
334 ; current_entry
335 ; pointer set to source entry to be moved
336 ;
337 ;Output: CF = 0 - DIR entry moved to first available entry
338 ; CF = 1 - Error, not able to free up entry
339 ;
340 ;Change History: Created 7/01/87 FG
341 ;
342 ;******************* END OF SPECIFICATIONS *************************************
343 ;******************+ START OF PSEUDOCODE +**************************************
344 ;
345 ; START Move_DIR_Entry
346 ;
347 ; set dest = entry_buffer
348 ; save source pointer
349 ; copy input entry to buffer
350 ; if no error and
351 ; call Find_Empty_Entry to find hole in directory
352 ; if no error
353 ; set source to entry_buffer
354 ; set dest to hole pointer
355 ; copy buffer to enpty entry
356 ; if first_dir_sector != current_dir_sector
357 ; set up for write
358 ; call Direct_Access to write it out
359 ; if no error
360 ; set up for first_dir_sector
361 ; set up for read
362 ; call Direct_Access to read it in
363 ; endif
364 ; if no error
365 ; recover source pointer
366 ; null out entry being processed
367 ; set up for write
368 ; call Direct_Access to update the root
369 ; endif
370 ; endif
371 ;
372 ; ret
373 ;
374 ; END Move_DIR_Entry
375 ;
376 ;******************- END OF PSEUDOCODE -**************************************
377
378
379 PUBLIC Move_DIR_Entry
380
381 Move_DIR_Entry PROC NEAR
382
383 ASSUME ds:DATA ; must ensure this is true xxxxxxxxxxxxxxxxx
384
385 ; source = source entry (#1 or #2) DS:SI
386 lea di,ENTRY_BUF ; dest = entry_buffer ;AN004;
387 mov [source_ptr],si ; save source pointer ;AN004;
388 mov ax,size dir_entry ; ;AN004;
389 mov cx,ax ; ;AN004;
390 rep movsb ; copy directory entry into entry buffer;AN004;
391 lea si,DIR_SECTOR ; start at beginning of directory ;AN004;
392 mov di,si ; save start for end calculation ;AN004;
393 shl ax,1 ; set pointer for current entry to #3 ;AN004;
394 add ax,si ; ;AN004;
395 mov si,ax ; ;AN004;
396 add di,[SSIZE] ; calculate end of directory ;AN004;
397 call Find_Empty_Entry ; find hole in directory ;AN004;
398 ; $if nc ; if no error and ;AN004;
399 JC $$IF9
400 mov di,si ; dest = hole pointer ;AN004;
401 lea si,ENTRY_BUF ; source = entry_buffer ;AN004;
402 mov cx,size dir_entry ; ;AN004;
403 rep movsb ; copy buffer to DTA ;AN004;
404 mov ax,[first_dir_sector] ; ;AN004;
405 cmp ax,[current_dir_sector] ; ;AN004;
406 ; $if ne ; if first_dir_sector != current_dir_sector;AN004;
407 JE $$IF10
408 mov ah,-1 ; set up for write ;AN004;
409 call Direct_Access ; write it out ;AN004;
410 ; $if nc ; if no error ;AN004;
411 JC $$IF11
412 mov ax,[first_dir_sector] ; set up for first_dir_sector ;AN004;
413 mov [current_dir_sector],ax ; update current_dir_sector ;AN004;
414 mov [packet],ax ; ;AN004;
415 xor ah,ah ; set up for read ;AN004;
416 call Direct_Access ; read it in ;AN004;
417 ; $endif ; ;AN004;
418 $$IF11:
419 ; $endif ; ;AN004;
420 $$IF10:
421 ; $if nc ; if no error ;AN004;
422 JC $$IF14
423 mov si,[source_ptr] ; recover source pointer ;AN004;
424 mov BYTE PTR [si],deleted ; delete entry being processed ;AN004;
425 mov BYTE PTR [si.dir_first],0 ; null out cluster # ;AN004;
426 cmp si,offset DIR_SECTOR ; are we at the first entry ? ;AN010;
427 ; $if e,and ; if so - ;AN010;
428 JNE $$IF15
429 cmp BYTE PTR [si + size DIR_ENTRY],0 ; is second one a null entry? ;AN010;
430 ; $if e ; if so - ;AN010;
431 JNE $$IF15
432 mov BYTE PTR [si + size DIR_ENTRY],deleted ; make it deleted ;AN010;
433 ; $endif ; ;AN010;
434 $$IF15:
435 mov ah,-1 ; set up for write ;AN004;
436 call Direct_Access ; write it out ;AN004;
437 ; $endif ; ;AN004;
438 $$IF14:
439 ; $endif ; ;AN004;
440 $$IF9:
441
442 ret ; ;AN004;
443
444 Move_DIR_Entry ENDP
445
446 BREAK <SYS - Find_Empty_Entry >
447 ;******************* START OF SPECIFICATIONS ***********************************
448 ;Routine name: Find_Empty_Entry
449 ;*******************************************************************************
450 ;
451 ;Description: Find_Empty_Entry scans all root directory sectors looking for
452 ; an empty entry.
453 ;
454 ; NOTE; It is assumed that each DIRectory entry is 32 bytes long
455 ;
456 ;Called Procedures:
457 ;
458 ; Direct_Acces - do INT 25
459 ;
460 ;Input: current_dir_sector
461 ; last_dir_sector
462 ; first_dir_sector in DTA buffer
463 ; DS:SI set for first entry to check
464 ; DS:DI set to end of directory (sector)
465 ;
466 ;Output: success pointer set to hole
467 ; CF = 0 current_entry updated
468 ; current_dir_sector updated
469 ;
470 ; fail message # set
471 ; CF = 1
472 ;
473 ;Change History: Created 7/01/87 FG
474 ;
475 ;******************* END OF SPECIFICATIONS *************************************
476 ;******************+ START OF PSEUDOCODE +**************************************
477 ;
478 ; START Find_Empty_Entry
479 ;
480 ; search all available sectors
481 ; search for hole (leaves pointer set to the hole)
482 ; leave if empty
483 ; leave if deleted
484 ; advace to next entry
485 ; exitif past end of sector
486 ; set carry
487 ; orelse
488 ; endloop
489 ; clear carry
490 ; save current_entry
491 ; endsrch
492 ; exitif hole found (no CF)
493 ; update current_entry
494 ; orelse
495 ; if not at end (current <= last)
496 ; set for read
497 ; call Direct_Access to read in next sector
498 ; else
499 ; load error message (no room for system files)
500 ; set error (CF)
501 ; endif
502 ; leave if error (CF)
503 ; update current_DIR_sector
504 ; update current_entry
505 ; endif
506 ; endloop
507 ; endsrch
508 ;
509 ; ret
510 ;
511 ; END Find_Empty_Entry
512 ;
513 ;******************- END OF PSEUDOCODE -**************************************
514
515 PUBLIC Find_Empty_Entry
516
517 Find_Empty_Entry PROC NEAR
518
519 ; $search ; for sectors available ;AN004;
520 $$DO19:
521 ; ;AN004;
522 ; $search ; for hole - this leaves pointer set at;AN004;
523 $$DO20:
524 ; the hole ;AN004;
525 cmp BYTE PTR [si],empty ; empty ? ;AN004;
526 ; $leave e ; ;AN004;
527 JE $$EN20
528 cmp BYTE PTR [si],deleted ; deleted ? ;AN004;
529 ; $leave e ; ;AN004;
530 JE $$EN20
531 add ax,size dir_entry ; advace to next entry ;AN004;
532 mov si,ax ; ;AN004;
533 cmp ax,di ; past end of sector ? ;AN004;
534 ; $exitif ae ; at end ;AN004;
535 JNAE $$IF20
536 stc ; set carry ;AN004;
537 ; $orelse ; ;AN004;
538 JMP SHORT $$SR20
539 $$IF20:
540 ; $endloop ; ;AN004;
541 JMP SHORT $$DO20
542 $$EN20:
543 clc ; clear carry ;AN004;
544 ; $endsrch ; ;AN004;
545 $$SR20:
546 ; $exitif nc ; hole is found ;AN004;
547 JC $$IF19
548 ; $orelse ; ;AN004;
549 JMP SHORT $$SR19
550 $$IF19:
551 inc [current_dir_sector] ; advance to next sector ;AN004;
552 mov ax,[current_dir_sector] ; ;AN004;
553 cmp ax,[last_dir_sector] ; past last_dir_sector ? ;AN004;
554 ; $leave a ; if at end (current <= last) ;AN004;
555 JA $$EN19
556 lea si,DIR_SECTOR ; start at start of next sector ;AN004;
557 mov [packet],ax ; ;AN004;
558 xor ah,ah ; set for read ;AN004;
559 call Direct_Access ; read in next sector ;AN004;
560 ; $if c ; if error ;AN004;
561 JNC $$IF30
562 dec [current_dir_sector] ; restore curren_dir_sector ;AN004;
563 ; $endif ; ;AN004;
564 $$IF30:
565 ; $leave c ; error ;AN004;
566 JC $$EN19
567 mov ax,si ; reset pointer to start ;AN004;
568 ; $endloop a ; past last_dir_sector ;AN004;
569 JNA $$DO19
570 $$EN19:
571 mov ax,(util shl 8) + no_room ; set message# and class ;AN004;
572 stc ; ensure carry still set ;AN004;
573 ; $endsrch ; ;AN004;
574 $$SR19:
575
576 ret ; ;AN004;
577
578 Find_Empty_Entry ENDP
579
580
581
582 BREAK <SYS - Direct_Access >
583 ;******************* START OF SPECIFICATIONS ***********************************
584 ;Routine name: Direct_Access
585 ;*******************************************************************************
586 ;
587 ;Description: Direct_Access
588 ;
589 ;Called Procedures:
590 ;
591 ; INT 25
592 ; INT 26
593 ;
594 ;Input: ah = 0 - read
595 ; ah = -1 - write
596 ;
597 ;Output: CF = 0 - Sectors moved
598 ; CF = 1 - Message and class in AX
599 ;
600 ;Change History: Created 7/01/87 FG
601 ;
602 ;******************* END OF SPECIFICATIONS *************************************
603 ;******************+ START OF PSEUDOCODE +**************************************
604 ;
605 ; START Direct_Access
606 ;
607 ; save registers
608 ; if read
609 ; INT 25
610 ; else
611 ; zero ah
612 ; INT 26
613 ; endif
614 ; save return flag
615 ; clear stack
616 ; if error
617 ; set message# and class
618 ; endif
619 ; restore registers
620 ;
621 ; ret
622 ;
623 ; END Direct_Access
624 ;
625 ;******************- END OF PSEUDOCODE -**************************************
626
627 public Direct_Access
628
629 Direct_Access PROC NEAR
630
631 push si ; save registers ;AN004;
632 push bp ; save registers ;AN004;
633 cmp DOS_VER,0 ; ;AN019;
634
635 ; $if e ; ;AN019;
636 JNE $$IF35
637
638 mov cx,-1 ; set up for INT ;AN004;
639 mov bx,offset packet ; ;AN004;
640
641 ; $else ; ;AN019;
642 JMP SHORT $$EN35
643 $$IF35:
644 ; If running on DOS 3.3 the INT 25
645 ; interface is:
646 ; al = drive number
647 ; bx = buffer for read data
648 ; cx = # of sectors
649 ; dx = start sector
650 mov cx,word ptr [packet_sectors] ; ;AN019;
651 mov dx,[packet] ; get starting dir sector ;AN019;
652 mov bx,PACKET_BUFFER[0] ; ;AN019;
653
654 ; $endif ; ;AN019;
655 $$EN35:
656
657 mov al,TargDrvNum ; set up drive number ;AN004;
658 dec al ; ;AN004;
659 cmp ah,0 ; ;AN004;
660 ; $if e ; if read ;AN004;
661 JNE $$IF38
662 INT 25h ; INT 25 ;AN004;
663 ; $else ; else ;AN004;
664 JMP SHORT $$EN38
665 $$IF38:
666 xor ah,ah ; zero ah ;AN004;
667 INT 26h ; INT 26 ;AN004;
668 ; $endif ; endif ;AN004;
669 $$EN38:
670 ;; ? ; save return flag ;AN004;
671 pop ax ; clear stack ;AN004;
672 pop bp ; ;AN004;
673 pop si ; ;AN004;
674
675 ret ; ;AN004;
676
677 Direct_Access ENDP
678
679 BREAK <SYS - Free_Cluster >
680 ;******************* START OF SPECIFICATIONS ***********************************
681 ;Routine name: Free_Cluster processor
682 ;*******************************************************************************
683 ;
684 ;Description: IBMBIO MUST have at lease cluster 2 as its first cluster. This
685 ; routine ensures that cluster 2 and any additional clusters (if
686 ; needed) ARE available. If they are chained, their data is copied
687 ; into the first available cluster, and the needed cluster is
688 ; is replaced by this cluster in the FAT
689 ;
690 ;Entry: Called by Verify_File_Location
691 ;
692 ;Called Procedures:
693 ;
694 ; Is_It_Empty - see if Cluster is empty
695 ; Search_FAT - scan FAT to see if the cluster is chained
696 ; Search_DIR - use FAT to walk directories looking for the cluster
697 ;
698 ; NOTES: Check_FAT and Check_DIR will do the processing requred to move
699 ; data out of the cluster and fix up the FAT and the Dir (if needed).
700 ;
701 ;Input: All local DBP values initalized by Get_DPB
702 ;
703 ;Ouput: CF = 0 - Cluster available
704 ; CF = 1 - Cluster not available
705 ;
706 ;
707 ;Change History: Created 7/01/87 FG
708 ;
709 ;******************* END OF SPECIFICATIONS *************************************
710 ;******************+ START OF PSEUDOCODE +**************************************
711 ;
712 ; START Free_Cluster
713 ;
714 ; initialize [cluster_count]
715 ; do until all copies of FAT attempted
716 ; load FAT into memory (INT 25)
717 ; leave if successful
718 ; enddo
719 ; do until [cluster_count] = 0
720 ; call Is_It_Empty
721 ; if not found and
722 ; if no errors and
723 ; call Search_FAT
724 ; if not found and
725 ; if no errors
726 ; call Search_DIR
727 ; endif
728 ; leave if error
729 ; enddo
730 ;
731 ; ret
732 ;
733 ; END Free_Cluster
734 ;
735 ;******************- END OF PSEUDOCODE -**************************************
736
737 public Free_Cluster
738
739 Free_Cluster PROC NEAR
740
741 mov ax,IBMLOADSIZE ; calculate # of clusters reqd ;AN004;
742 xor cx,cx ; ;AN004;
743 mov di,cx ; ;AN004;
744 dec di ; ;AN004;
745 mov cx,[CSIZE] ; by IBMLOAD (consecutive clusters ;AN004;
746 div cl ; for IBMBIO) ;AN004;
747 cmp ah,0 ; ;AN004;
748 ; $if ne ; ;AN004;
749 JE $$IF41
750 inc al ; ;AN004;
751 xor ah,ah ; ;AN004;
752 ; $endif ; ;AN004;
753 $$IF41:
754 inc ax ; will be decrimenter immediately upon ;AN004;
755 ; entering complex do below
756 mov [cluster_count],ax ; save for later ;AN004;
757 mov ax,[FAT_sectors] ;only read needed sectors ;AN004;
758 mov [packet_sectors],ax ; ;AN004;
759 mov cl,[num_of_FATS] ;Number of FATs ;AN004;
760 mov ax,[first_FAT] ;First sector of FAT ;AN004;
761 mov [packet],ax ; ;AN004;
762 mov [packet_buffer],OFFSET BUF ; point to FAT buffer ;AN004;
763 call Load_FAT ; ;AN004;
764 ; $if nc ; no error so far....... ;AN004;
765 JC $$IF43
766 ; $do complex ; ;AN004;
767 JMP SHORT $$SD44
768 $$DO44:
769 mov [cluster_count],cx ; ;AN004;
770 call Is_It_Empty ; ;AN004;
771 ; $leave c ; ;AN014;
772 JC $$EN44
773 cmp al,not_found ; ( -1 ?) ;AN004;
774 ; $if e ; if not found ;AN004;
775 JNE $$IF46
776 call Search_FAT ; scan FAT to see if cluster chained ;AN004;
777 ; $else ; ;AN004;
778 JMP SHORT $$EN46
779 $$IF46:
780 clc ; ;AN004;
781 ; $endif ; ;AN004;
782 $$EN46:
783 ; $leave c ; ;AN004;
784 JC $$EN44
785 cmp al,not_found ; if still not found ;AN004;
786 ; $if e ; ;AN004;
787 JNE $$IF50
788 call Search_DIR ; scan DIR to see who starts with #2 ;AN004;
789 ; $else ; ;AC013;
790 JMP SHORT $$EN50
791 $$IF50:
792 clc ; ensure carry is still clear ;AC013;
793 ; $endif ; ;AN004;
794 $$EN50:
795 ; $leave c ; ;AN004;
796 JC $$EN44
797 inc [current_cluster] ; ;AN004;
798 ; $strtdo ; ;AN004;
799 $$SD44:
800 mov cx,[cluster_count] ; ;AN004;
801 ; $enddo LOOP ; ;AN004;
802 LOOP $$DO44
803 $$EN44:
804 ; $endif ; ;AN004;
805 $$IF43:
806 ; $if c ; ;AN004;
807 JNC $$IF57
808 mov ax,(util shl 8) + no_room ; error message - no room to sys ;AN014;
809 ; $endif ; ;AN004;
810 $$IF57:
811
812 ret ; ;AN004;
813
814 Free_Cluster ENDP
815
816 public Load_FAT
817
818 Load_FAT PROC NEAR
819
820 lea bx,[packet] ; ;AN004;
821
822 ; $search ; ;AN004;
823 $$DO59:
824 xchg cx,di ; ;AN004;
825 push cx ; ;AN004;
826 push di ; ;AN004;
827 push dx ; ;AN004;
828 push bx ; ;AN004;
829 xor ah,ah ; ;AN004;
830 mov al,TargDrvNum ; set up drive number ;AN004;
831 dec al ; ;AN004;
832 cmp DOS_VER,0 ; if DOS 3.3 ;AN019;
833
834 ; $if ne ; load registers for old style INT 25 ;AN019;
835 JE $$IF60
836 mov bx,[packet_buffer] ; ;AN019;
837 mov cx,[packet_sectors] ; ;AN019;
838 mov dx,[packet] ; ;AN019;
839 ; $endif ; ;AN019;
840 $$IF60:
841
842 push bp ; ;AN019;
843 int 25h ;Read in the FAT ;AN004;
844 pop ax ;Flags ;AN004;
845 pop bp ; ;AN019;
846 ; $exitif nc ; error - set up for next fat ;AN004;
847 JC $$IF59
848 add sp,8 ;Clean up stack ;AN004;
849 mov ax,1 ; ;AN004;
850 ; mov [packet],ax ; reset to first FAT ;AN004;
851 ; $orelse ; ;AN004;
852 JMP SHORT $$SR59
853 $$IF59:
854 pop bx ; ;AN004;
855 pop dx ; ;AN004;
856 pop cx ; ;AN004;
857 pop di ; ;AN004;
858 add [packet],dx ; point to start of next FAT ;AN004;
859 inc [FAT_2] ; ;AN004;
860 ; $endloop LOOP ;Try next FAT ;AN004;
861 LOOP $$DO59
862 mov ax,(util shl 8) + no_room ; set message# and class ;AN004;
863 ; $endsrch ; ;AN004;
864 $$SR59:
865
866 ret
867
868 Load_FAT ENDP
869
870
871 BREAK <SYS - Is_It_Empty >
872 ;******************* START OF SPECIFICATIONS ***********************************
873 ;Routine name: Is_It_Empty
874 ;*******************************************************************************
875 ;
876 ;Description: Is_It_Empty looks directly into the FAT to see if a specified
877 ; cluster is allocated.
878 ;
879 ;Entry: Called by Free_Cluster
880 ;
881 ;Called Procedures:
882 ;
883 ; Unpack - unpack a FAT cluster number (CF set on error)
884 ;
885 ;Input: CX = cluster to check
886 ; 12 sectors of FAT in BUF
887 ;
888 ;Output: CF = 0 AL = 0 - cluster 2 found empty
889 ; AL =-1 - not found & no error
890 ; CF = 1 - critical error
891 ;
892 ;Change History: Created 7/01/87 FG
893 ;
894 ;******************* END OF SPECIFICATIONS *************************************
895 ;******************+ START OF PSEUDOCODE +**************************************
896 ;
897 ; START Is_It_Empty
898 ;
899 ; set up for call to Unpack
900 ; set cluster # to [cluster_number]
901 ; call Unpack
902 ; if no error
903 ; if cluster is not empty
904 ; if bad cluster
905 ; set error flag
906 ; else
907 ; if cluster belongs to IBMBIO
908 ; if next cluster is not contiguous
909 ; reset ownership flag
910 ; endif
911 ; set cluster empty (ax = 0)
912 ; else
913 ; save cluster number
914 ; set cluster used (ax = -1)
915 ; endif
916 ; else
917 ; set cluster empty (ax = 0)
918 ; endif
919 ; endif
920 ;
921 ; ret
922 ;
923 ; END Is_It_Empty
924 ;
925 ;******************- END OF PSEUDOCODE -**************************************
926
927 public Is_It_Empty
928
929 Is_It_Empty PROC NEAR
930
931 mov si,[current_cluster] ; set up for call to Unpack ;AN004;
932 call Unpack ; to find the value ;AN004;
933 ; $if nc ; if no error ;AN004;
934 JC $$IF66
935 ; $if nz ; cluster is not empty ;AN004;
936 JZ $$IF67
937 mov ax,di ; ;AN004;
938 cmp al,bad_sector ; ;AN004;
939 ; $if e ; ;AN004;
940 JNE $$IF68
941 stc ; ;AN004;
942 ; $else ; ;AN004;
943 JMP SHORT $$EN68
944 $$IF68:
945 cmp [bio_owns_it],0 ; is it owned by IBMBIO ? ;AN004;
946 ; $if ne ; if it is ;AN004;
947 JE $$IF70
948 dec ax ; ;AN004;
949 cmp ax,[current_cluster] ; ;AN004;
950 ; $if ne ; ;AC011;
951 JE $$IF71
952 dec [bio_owns_it] ; its not the owner form here on ;AC011;
953 ; $endif ; ;AC011;
954 $$IF71:
955 xor ax,ax ; ;AN004;
956 clc ; its IBMBIO's anyway ;AC011;
957 ; $else ; ;AN004;
958 JMP SHORT $$EN70
959 $$IF70:
960 mov [next_cluster],di ; ;AN004;
961 xor ax,ax ; reset fail flag ;AN004;
962 dec ax ; - its not empty ;AN014;
963 ; $endif ; ;AN004;
964 $$EN70:
965 ; $endif ; ;AN004;
966 $$EN68:
967 ; $else ; its empty ! ;AN005;
968 JMP SHORT $$EN67
969 $$IF67:
970 xor ax,ax ; its empty - and no error ;AN014;
971 ; $endif ; ;AN014;
972 $$EN67:
973 ; $endif ; ;AN004;
974 $$IF66:
975
976 ret ; ;AN004;
977
978 Is_It_Empty ENDP
979
980 BREAK <SYS - Search_FAT >
981 ;******************* START OF SPECIFICATIONS ***********************************
982 ;Routine name: Search_FAT
983 ;*******************************************************************************
984 ;
985 ;Description: Search_FAT for a [cluster_number]. If it is listed in the FAT,
986 ; then its chained into a file. The data in the [cluster_number] is
987 ; then buffered, and copied into an empty cluster, and the FAT is
988 ; updated
989 ;
990 ;Called Procedures:
991 ;
992 ; Unpack - to find a FAT entry for a Cluster #
993 ; Pack - to set a FAT entry for a Cluster #
994 ; Find_Empty_Cluster - find an unused cluster
995 ; Xfer_Data - transfere data from one cluster to another
996 ; Direct_Access - absolute disk i/o
997 ;
998 ;Input: FAT in BUF
999 ; [cluster_number] of specified cluster
1000 ;
1001 ;Output: CF = 0 - AX = 0 if cluster found
1002 ; = -1 if cluster not found
1003 ; CF = 1 if critical error
1004 ;
1005 ;Change History: Created 7/01/87 FG
1006 ;
1007 ;******************* END OF SPECIFICATIONS *************************************
1008 ;******************+ START OF PSEUDOCODE +**************************************
1009 ;
1010 ; START Search_FAT
1011 ;
1012 ; set cluster # to [cluster_number]
1013 ; search till at end of FAT
1014 ; call Unpack
1015 ; exitif cluster found
1016 ; save [last_cluster]
1017 ; clear CF
1018 ; orelse
1019 ; advance to next cluster
1020 ; endloop if past last cluster in fat
1021 ; set CF
1022 ; endsrch
1023 ; if cluster found
1024 ; call Find_Empty_Cluster
1025 ; endif
1026 ;
1027 ; if empty cluster available and
1028 ;
1029 ; call Xfer_Data
1030 ;
1031 ; if no errors
1032 ;
1033 ; set taget cluster as one pointing to [cluster_number]
1034 ; set value to that of empty cluster
1035 ; call Pack to update FAT
1036 ; set target cluster as [cluster_number]
1037 ; set cluster value to empty
1038 ; call Pack to update FAT
1039 ; set destination to first sector of first FAT
1040 ; set count to # of fat sectors
1041 ; set up for write
1042 ; do until all FATS written
1043 ; call Direct_Access
1044 ; advace to next FAT (ignore errors)
1045 ; enddo
1046 ;
1047 ; endif
1048 ;
1049 ; if no errors
1050 ; update DPB first cluster and total empty clusters
1051 ; endif
1052 ;
1053 ; ret
1054 ;
1055 ; END Search_FAT
1056 ;
1057 ;******************- END OF PSEUDOCODE -**************************************
1058
1059 public Search_FAT
1060
1061 Search_FAT PROC NEAR
1062
1063 mov si,[current_cluster] ; set cluster # to [cluster_number] ;AN004;
1064 ; $search ; till at end of FAT ;AN004;
1065 $$DO79:
1066 call Unpack ; ;AN004;
1067 ; $leave c ; quit on an error ;AN004;
1068 JC $$EN79
1069 cmp di,[current_cluster] ; is it [current_cluster] ? ;AN004;
1070 ; $exitif e ; it is ;AN004;
1071 JNE $$IF79
1072 mov [last_cluster],si ; save number for later ;AN004;
1073 xor ax,ax ; ;AN004;
1074 clc ; clear error flag (found) ;AN004;
1075 ; $orelse ; ;AN004;
1076 JMP SHORT $$SR79
1077 $$IF79:
1078 inc si ; advance to next cluster ;AN004;
1079 xor ax,ax ; ;AN004;
1080 dec ax ; ;AN004;
1081 cmp si,[MCLUS] ; at the end ? ;AN004;
1082 ; $endloop e ; if past last cluster ;AN004;
1083 JNE $$DO79
1084 $$EN79:
1085 stc ; ;AN014;
1086 ; $endsrch ; ;AN004;
1087 $$SR79:
1088 ; $if nc ; if cluster found ;AN004;
1089 JC $$IF85
1090 call Find_Empty_Cluster ; to move data to ;AN004;
1091 ; $endif ; ;AN004;
1092 $$IF85:
1093 ; $if nc,and ; empty cluster available and ;AN004;
1094 JC $$IF87
1095 call Xfer_Data ; to move data to new cluster ;AN004;
1096 ; $if nc,and ; no errors ;AN004;
1097 JC $$IF87
1098 mov si,[last_cluster] ; set target [last_cluster] ;AN004;
1099 mov dx,[empty_cluster] ; set value to [empty_cluster] ;AN004;
1100 call Pack ; to update FAT ;AN004;
1101 ; $if nc,and ; no errors ;AN004;
1102 JC $$IF87
1103 mov si,[empty_cluster] ; set target [empty_cluster] ;AN004;
1104 mov dx,[next_cluster] ; set value to [next_cluster] ;AN004;
1105 call Pack ; to update FAT ;AN004;
1106 ; $if nc,and ; no errors ;AN004;
1107 JC $$IF87
1108 mov si,[current_cluster] ; set target [current_cluster] ;AN004;
1109 xor dx,dx ; set cluster value to empty ;AN004;
1110 call Pack ; to update FAT ;AN004;
1111 ; $if nc ; no errors ;AN004;
1112 JC $$IF87
1113 xor ah,ah ; ;AN004;
1114 dec ah ; ;AN004;
1115 call Direct_Access ; write it out - ignore errors ;AN004;
1116 mov ax,[FSIZE] ; ;AN004;
1117 cmp [FAT_2],0 ; ;AN004;
1118 ; $if e ; ;AN004;
1119 JNE $$IF88
1120 add [packet],ax ; ;AN004;
1121 inc [FAT_2] ; packet points to FAT #2 ;AC006;
1122 ; $else ; ;AN004;
1123 JMP SHORT $$EN88
1124 $$IF88:
1125 sub [packet],ax ; ;AN004;
1126 mov [FAT_2],0 ; reset - packet points to FAT #1 ;AN004;
1127 ; $endif ; ;AN004;
1128 $$EN88:
1129 xor ah,ah ; ;AN004;
1130 dec ah ; ;AN004;
1131 call Direct_Access ; write it out - ignore errors ;AN004;
1132 mov [FAT_changed],0 ; FAT now cleared ;AN004;
1133 push es ; update DPB first cluster ;AN004;
1134 mov bx,ds ; ;AN004;
1135 mov es,bx ; ;AN004;
1136 lds bx,[THIS_DPB] ; ;AN004;
1137
1138 ASSUME ds:nothing,es:DATA
1139
1140 mov [bx.dpb_next_free],2 ; ;AN004;
1141 mov ax,es ; ;AN004;
1142 mov ds,ax ; ;AN004;
1143 pop es ; ;AN004;
1144 xor ax,ax ; signal success (ax = 0 , cf = 0) ;AN004;
1145
1146 ASSUME DS:data, es:nothing
1147
1148 ; $endif ; ;AN004;
1149 $$IF87:
1150 ; $if c ; ;AN004;
1151 JNC $$IF92
1152 cmp ax,-1 ; ;AN004;
1153 ; $if e ; ;AN004;
1154 JNE $$IF93
1155 clc ; not a critical error - keep trying ;AN004;
1156 ; $else ; ;AN004;
1157 JMP SHORT $$EN93
1158 $$IF93:
1159 stc ; major problem - critical error ;AN004;
1160 ; $endif ; ;AN004;
1161 $$EN93:
1162 ; $endif ; ;AN004;
1163 $$IF92:
1164
1165 ret ; ;AN000;
1166
1167 Search_FAT ENDP
1168
1169 BREAK <SYS - Find_Empty_Cluster >
1170 ;******************* START OF SPECIFICATIONS ***********************************
1171 ;Routine name: Find_Empty_Cluster
1172 ;*******************************************************************************
1173 ;
1174 ;Description: Find_Empty_Cluster finds the first available empty cluster
1175 ;
1176 ;Called Procedures:
1177 ;
1178 ; Unpack - find next cluster number
1179 ;
1180 ;Input: none
1181 ;
1182 ;Output: CF = 0 - empty cluster found (# in [empty_cluster])
1183 ; CF = 1 - no empty clusters (ax = message)
1184 ;
1185 ;Change History: Created 7/01/87 FG
1186 ;
1187 ;******************* END OF SPECIFICATIONS *************************************
1188 ;******************+ START OF PSEUDOCODE +**************************************
1189 ;
1190 ; START Find_Empty_Cluster
1191 ;
1192 ; search till at end of FAT
1193 ; call Unpack
1194 ; exitif cluster is empty (ZF)
1195 ; save empty cluster number
1196 ; clear CF
1197 ; orelse
1198 ; advance to next cluster
1199 ; endloop if past last cluster
1200 ; load ax message # - no room for sys files
1201 ; set CF
1202 ; endsrch
1203 ;
1204 ; ret
1205 ;
1206 ; END Find_Empty_Cluster
1207 ;
1208 ;******************- END OF PSEUDOCODE -**************************************
1209
1210 public Find_Empty_Cluster
1211
1212 Find_Empty_Cluster PROC NEAR
1213
1214 mov si,[current_cluster] ; ;AN004;
1215 mov ax,[cluster_count] ; ;AN004;
1216 add si,ax ; look past required space ;AN004;
1217 ; $search ; till at end of FAT ;AN004;
1218 $$DO97:
1219 call Unpack ; to convert # to value ;AN004;
1220 ; $exitif z ; cluster is empty ;AN004;
1221 JNZ $$IF97
1222 mov [empty_cluster],si ; save it for later ;AN004;
1223 clc ; clear error flag ;AN004;
1224 ; $orelse ; ;AN004;
1225 JMP SHORT $$SR97
1226 $$IF97:
1227 inc si ; advance to next cluster ;AN004;
1228 cmp si,[MCLUS] ; past the end ? ;AN004;
1229 ; $endloop e ; if past last cluster ;AN004;
1230 JNE $$DO97
1231 stc ; set error flag ;AN004;
1232 mov ax,(util shl 8) + no_room ; error message - no room to sys ;AN014;
1233 ; $endsrch ; ;AN004;
1234 $$SR97:
1235
1236 ret ; ;AN004;
1237
1238 Find_Empty_Cluster ENDP
1239
1240 BREAK <SYS - Xfer_Data >
1241 ;******************* START OF SPECIFICATIONS ***********************************
1242 ;Routine name: Xfer_Data
1243 ;*******************************************************************************
1244 ;
1245 ;Description: Xfer_Data moves the data from [cluster_number] into the cluster
1246 ; number passed in ax.
1247 ;
1248 ;Called Procedures:
1249 ;
1250 ; Direct_Access - do disk i/o
1251 ;
1252 ;Input: [current_cluster]
1253 ; [empty_cluster]
1254 ;
1255 ;Output: CF = 0 - data transfered
1256 ; CF = 1 - error - message in AX
1257 ;
1258 ;Change History: Created 7/01/87 FG
1259 ;
1260 ;******************* END OF SPECIFICATIONS *************************************
1261 ;******************+ START OF PSEUDOCODE +**************************************
1262 ;
1263 ; START Xfer_Data
1264 ;
1265 ; save active FAT starting sector
1266 ; set source to first sector of [current_cluster]
1267 ; set count to # of sectors per cluster
1268 ; set up for read
1269 ; call Direct_Access to read data
1270 ; if no errors
1271 ; set source to first sector of [empty_cluster]
1272 ; set up for write
1273 ; call Direct_Access to write data
1274 ; endif
1275 ; restore Fat starting sector
1276 ; set count to FAT_sectors
1277 ; set up for read
1278 ; call Direct_Access to restore the FAT copy
1279 ;
1280 ; endif
1281 ;
1282 ; ret
1283 ;
1284 ; END Xfer_Data
1285 ;
1286 ;******************- END OF PSEUDOCODE -**************************************
1287
1288 public Xfer_Data
1289
1290 Xfer_Data PROC NEAR
1291
1292 push [packet] ; save active FAT starting sector ;AN004;
1293 push [packet+2] ; ;AN004;
1294 push [packet_sectors] ; ;AN004;
1295 mov ax,[CSIZE] ; ;AN004;
1296 mov [packet_sectors],ax ; ;AN004;
1297 mov ax,[current_cluster] ; set source to [current_cluster] ;AN004;
1298 call cluster_2_sector ; convert Cluster to sector # ;AN004;
1299 mov [packet],ax ; low sector word ;AN004;
1300 mov [packet+2],dx ; high sector word ;AN004;
1301 xor ah,ah ; set up for read ;AN004;
1302 call Direct_Access ; to read data ;AN004;
1303 ; $if nc ; no errors ;AN004;
1304 JC $$IF102
1305 mov ax,[empty_cluster] ; set destination to [empty_cluster] ;AN004;
1306 cmp [DIR_cluster],0 ; have we just loaded a directory? ;AN007;
1307 ; $if ne ; if so - ;AN007;
1308 JE $$IF103
1309 mov [DIR_cluster],ax ; save the new cluster ;AN007;
1310 lea bx,BUF ; ;AN007;
1311 mov [bx.dir_first],ax ; update the '.' entry start cluster ;AN007;
1312 ; $endif ; ;AN007;
1313 $$IF103:
1314 call cluster_2_sector ; conver to logical sector ;AN004;
1315 mov [packet],ax ; low word ;AN004;
1316 mov [packet+2],dx ; high word ;AN004;
1317 xor ah,ah ; set up for write ;AN004;
1318 dec ah ; ;AN004;
1319 call Direct_Access ; to write data ;AN004;
1320 ; $endif ; ;AN004;
1321 $$IF102:
1322 pop [packet_sectors] ; ;AN004;
1323 pop [packet+2] ; restore starting sector ;AN004;
1324 pop [packet] ; ;AN004;
1325 xor ah,ah ; set up for read ;AN004;
1326 call Direct_Access ; to restore the FAT copy ;AN004;
1327
1328 ret ; ;AN004;
1329
1330 Xfer_Data ENDP
1331
1332 BREAK <SYS - cluster_2_sector >
1333 ;******************* START OF SPECIFICATIONS ***********************************
1334 ;Routine name: cluster_2_sector
1335 ;*******************************************************************************
1336 ;
1337 ;Description: cluster_2_sector
1338 ;
1339 ;
1340 ;Called Procedures:
1341 ;
1342 ; none
1343 ;
1344 ;Input: AX - cluster number
1345 ;
1346 ;Output: AX - low word of sector
1347 ; DX - high word of sector
1348 ; CX - sectors per cluster
1349 ;
1350 ;Change History: Created 7/01/87 FG
1351 ;
1352 ;******************* END OF SPECIFICATIONS *************************************
1353 ;******************+ START OF PSEUDOCODE +**************************************
1354 ;
1355 ; START cluster_2_sector
1356 ;
1357 ; ret
1358 ;
1359 ; END cluster_2_sector
1360 ;
1361 ;******************- END OF PSEUDOCODE -**************************************
1362
1363 public cluster_2_sector
1364
1365 cluster_2_sector PROC NEAR
1366
1367 dec ax ; of [current_cluster] ;AN004;
1368 dec ax ; ;AN004;
1369 mov cx,[CSIZE] ; ;AN004;
1370 mul cx ; ;AN004;
1371 add ax,[l_sector_offset] ; ;AN004;
1372
1373 ret ; ;AN004;
1374
1375 cluster_2_sector ENDP
1376
1377 BREAK <SYS - Search_DIR >
1378 ;******************* START OF SPECIFICATIONS ***********************************
1379 ;Routine name: Search_DIR
1380 ;*******************************************************************************
1381 ;
1382 ;Description: Search_DIR walks the directory tree looking for the file that
1383 ; starts with [cluster_number]. If found, the data is moved to the
1384 ; first empty cluster (if available), and the directory entry is
1385 ; updated.
1386 ;
1387 ; This routine walks the DIR tree by creating a 'FRAME' for each
1388 ; Sub DIR it encounters. It saves all the data needed to continue
1389 ; the search once the Sub DIR has been checked.
1390 ;
1391 ; FRAME ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
1392 ; ³ present_cluster # ³sector_offset ³ entry_number ³
1393 ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
1394 ; byte 1 2 3 4
1395 ;
1396 ; There is space in DIR_BUF for 32 frames (current DOS maximum
1397 ; level of nesting).
1398 ;
1399 ;Called Procedures:
1400 ;
1401 ; Search_Loop - scan the directory
1402 ;
1403 ;Input: [current_cluster] - # of cluster to be freed
1404 ;
1405 ;Output: CF = 0 cluster now available
1406 ; CF = 1 error - ax = message #
1407 ;
1408 ;
1409 ;Change History: Created 7/01/87 FG
1410 ;
1411 ;******************* END OF SPECIFICATIONS *************************************
1412 ;******************+ START OF PSEUDOCODE +**************************************
1413 ;
1414 ; START Search_DIR
1415 ;
1416 ; set up for first_dir_sector of root DIR
1417 ; set up for read
1418 ; call Direct_Access to read first root sector
1419 ; if no error
1420 ; set [current_sector]
1421 ; set [sector_count] = #_dir_sectors
1422 ; set [current_entry] = 1
1423 ; set [sub_dir_level] = 0
1424 ; do until cluster free (NC)
1425 ; call Search_Loop
1426 ; if SubDir
1427 ; save [current_cluster] in frame
1428 ; save [current_sector]in frame
1429 ; save [current_entry] in frame
1430 ; save [sector_count] in frame
1431 ; incriment [sub_dir_level] (frame)
1432 ; zero ax
1433 ; set error flag (CF)
1434 ; else
1435 ; if end of DIR (CF + 00) and
1436 ; if [dir_count] > 0
1437 ; recover [current_cluster] from frame
1438 ; recover [current_sector] from frame
1439 ; recover [current_entry] from frame
1440 ; recover [sector_count] from frame
1441 ; decriment [sub_dir_level]
1442 ; zero ax
1443 ; set error flag (CF)
1444 ; else
1445 ; load error message - no room to sys
1446 ; endif
1447 ; set error flag (CF) (ax = message)
1448 ; endif
1449 ; leave if error (ax > 0)
1450 ; enddo
1451 ; endif
1452 ;
1453 ; ret
1454 ;
1455 ; END Search_DIR
1456 ;
1457 ;******************- END OF PSEUDOCODE -**************************************
1458
1459 public Search_DIR
1460
1461 Search_DIR PROC NEAR
1462
1463 mov ax,[first_dir_sector] ; set up for first_dir_sector of root ;AN004;
1464 mov [packet],ax ; ;AN004;
1465 mov [packet+2],0 ; zero out high word ;AN004;
1466 mov [packet_sectors],1 ; only process 1 sector at a time ;AN004;
1467 mov [packet_buffer],OFFSET DIR_SECTOR ; ;AN004;
1468 xor ah,ah ; set up for read ;AN004;
1469 call Direct_Access ; to read first root sector ;AN004;
1470 ; $if nc,long ; no error ;AN004;
1471 JNC $$XL1
1472 JMP $$IF106
1473 $$XL1:
1474 xor ax,ax ; ;AN004;
1475 mov [present_cluster],ax ; set [present_cluster] = 0 (root) ;AN004;
1476 mov [entry_number],al ; set [entry_number] = 0 (first) ;AN004;
1477 mov ax,[first_dir_sector] ; ;AN013;
1478 mov [sector_offset],ax ; set [sector_offset] = [first_dir_sec];AC015;
1479 lea bx,DIR_BUF ; set [FRAME_ptr] = DIR_BUF ;AN004;
1480 mov [FRAME_ptr],bx ; ;AN004;
1481 ; $do ; until cluster free (NC) ;AN004;
1482 $$DO107:
1483 call Search_Loop ; ;AN004;
1484 ; $leave nc,long ; cluster found and moved ;AN004;
1485 JC $$XL2
1486 JMP $$EN107
1487 $$XL2:
1488 cmp ax,0ffffh ; ;AN004;
1489 ; $if e ; SubDir ;AN004;
1490 JNE $$IF109
1491
1492 ; Search DIR returned with BX pointing
1493 ; to the current entry - now update
1494 ; current_cluster to this SubDIRs first
1495 ; cluster
1496
1497 mov ax,[bx.dir_first] ; get starting cluster for where we ;AN007;
1498 ; want to go
1499 mov bx,[present_cluster] ; get [present_cluster] for frame ;AN004;
1500 ; (where we were)
1501 mov [present_cluster],ax ; [present_cluster] for next pass ;AN007;
1502 xchg ax,bx ; recover old [present_cluster] ;AN007;
1503 mov bx,[FRAME_ptr] ; get FRAME pointer ;AN004;
1504 mov [bx.p_cluster],ax ; save [present_cluster] in frame ;AN004;
1505 mov ax,[sector_offset] ; save [sector_offset]in frame ;AC015;
1506 mov [bx.s_offset],ax ; ;AC015;
1507 mov al,[entry_number] ; save [entry_number] in frame ;AN004;
1508 mov [bx.e_number],al ; ;AN004;
1509 xor ax,ax ; reset - ;AN007;
1510 mov [sector_offset],ax ; [sector_offset] ;AC015;
1511 mov [entry_number],al ; [entry_number] ;AN007;
1512 add bx,SIZE FRAME ; incriment FRAME pointer ;AN004;
1513 lea ax,DIR_SECTOR ; ;AN004;
1514 cmp ax,bx ; ;AN004;
1515 ; $if a ; ;AC007;
1516 JNA $$IF110
1517 mov [FRAME_ptr],bx ; ;AN004;
1518 clc ; no error ;AN004;
1519 ; $else ; ;AN004;
1520 JMP SHORT $$EN110
1521 $$IF110:
1522 stc ; set error flag (CF) ;AN004;
1523 ; $endif ; ;AN004;
1524 $$EN110:
1525 ; $else long ; ;AN004;
1526 JMP $$EN109
1527 $$IF109:
1528 cmp ax,0 ; ;AN004;
1529 ; $if e,and,long ; end of DIR (CF + 00) and ;AN004;
1530 JE $$XL3
1531 JMP $$IF114
1532 $$XL3:
1533 next_level_down: ; ;AN004;
1534 mov bx,[FRAME_ptr] ; recover FRAME_ptr - but remember ** ;AC007;
1535 ; it points to the next available
1536 ; frame - not the last one - so
1537 sub bx,SIZE FRAME ; move back! ;AN007;
1538 lea ax,DIR_BUF ; ;AN004;
1539 cmp ax,bx ; ;AN004;
1540 ; $if be ; as long as there are still FRAMEs ;AC007;
1541 JNBE $$IF114
1542 mov ax,[bx.p_cluster] ; get [present_cluster] from frame ;AN004;
1543 mov [present_cluster],ax ; ;AN004;
1544 mov ax,[bx.s_offset] ; recover [sector_offset] from frame ;AC015;
1545 mov [sector_offset],ax ; ;AC015;
1546 mov al,[bx.e_number] ; recover [entry_number] from frame ;AN004;
1547 mov [entry_number],al ; ;AN004;
1548 mov [FRAME_ptr],bx ; ;AN004;
1549
1550 ; Now set up at exactly same point
1551 ; as when SubDIR was entered -
1552 ; advance to next entry
1553
1554 inc al ; ;AN004;
1555 cmp al,[entries_per_sector] ; ;AN004;
1556 ; $if b ; ;AN004;
1557 JNB $$IF115
1558 inc [entry_number] ; ;AN004;
1559 clc ; no error ;AN004;
1560 ; $else ; we've left the sector ;AN004;
1561 JMP SHORT $$EN115
1562 $$IF115:
1563 if not ibmcopyright
1564 xor al, al
1565 mov [entry_number], al ; shall we start at, say, ENTRY ZERO? Hmmmmm?
1566 endif
1567 mov ax,[present_cluster] ; ;AN004;
1568 cmp ax,0 ; in the root ? ;AN004;
1569 ; $if ne ; no ;AN004;
1570 JE $$IF117
1571 mov si,ax ; ;AN004;
1572 mov [cluster_high],1 ; force Upack to load FAT ;AN004;
1573 mov ax,[FAT_sectors] ; get the size right ;AN004;
1574 mov [packet_sectors],ax ; ;AN004;
1575 mov [packet_buffer],OFFSET BUF ; ;AN004;
1576 call Unpack ; to get next cluster # ;AN004;
1577 mov [packet_buffer],OFFSET DIR_SECTOR ; ;AN004;
1578 mov [packet_sectors],1 ; set size back ;AN004;
1579 mov [cluster_high],1 ; ensure that FAT will be ;AN004;
1580 ; re-loaded
1581
1582 mov ax,di ; check if at end ;AN007;
1583 cmp al,end_cluster ; at the end? ;AN007;
1584 ; $if nz ; not at end of line ;AN004;
1585 JZ $$IF118
1586 mov [present_cluster],di ; save it ;AN004;
1587 clc ; ;AN004;
1588 ; $else ; we are at the end of a Sub DIR chain ;AN004;
1589 JMP SHORT $$EN118
1590 $$IF118:
1591
1592 ; the following is a best attempt fix
1593 ; to a bad design problem ...... (how
1594 ; to get back a level.....???
1595
1596 ; SEPT 21 - best solution is to check BEFORE putting the entry in the frame
1597 ; (not when taking it off !!! )
1598
1599 jmp next_level_down ; ;AN004;
1600
1601 ; $endif ; ;AN004;
1602 $$EN118:
1603 ; $else ; yes - in the root ;AN004;
1604 JMP SHORT $$EN117
1605 $$IF117:
1606 mov ax,[sector_offset] ; ;AC015;
1607 inc ax ; ;AN004;
1608 cmp ax,[l_sector_offset] ; ;AC015;
1609 ; $if b ; ;AN004;
1610 JNB $$IF122
1611 inc [sector_offset] ; ;AN004;
1612 if not ibmcopyright
1613 clc ; no error, continue with loop
1614 endif
1615 ; $else ; end of the line ;AN004;
1616 JMP SHORT $$EN122
1617 $$IF122:
1618 stc ; we failed to find it ;AN004;
1619 ; $endif ; ;AN004;
1620 $$EN122:
1621 ; $endif ; ;AN004;
1622 $$EN117:
1623 ; $endif ; ;AN004;
1624 $$EN115:
1625 ; $else ; ;AN004;
1626 JMP SHORT $$EN114
1627 $$IF114:
1628 stc ; set error flag (CF) ;AN004;
1629 ; $endif ; ;AN004;
1630 $$EN114:
1631 ; $endif ; ;AN004;
1632 $$EN109:
1633 ; $if c ; error ;AN004;
1634 JNC $$IF130
1635 mov ax,(util shl 8) + no_room ; error message - no room to sys ;AN004;
1636 ; $endif ; ;AN004;
1637 $$IF130:
1638 ; $leave c ; if error ;AN004;
1639 JC $$EN107
1640 ; $enddo long ; ;AN004;
1641 JMP $$DO107
1642 $$EN107:
1643 ; $endif ; ;AN004;
1644 $$IF106:
1645
1646 ret ; ;AN004;
1647
1648 Search_DIR ENDP
1649
1650 BREAK <SYS - Search_Loop >
1651 ;******************* START OF SPECIFICATIONS ***********************************
1652 ;Routine name: Search_Loop
1653 ;*******************************************************************************
1654 ;
1655 ;Description: Search_Loop scans through all entries of all sectors of all
1656 ; clusters of a given Directory for a specified cluster
1657 ;
1658 ;Called Procedures:
1659 ;
1660 ; Unpack - to find a FAT entry for a Cluster #
1661 ; Pack - to set a FAT entry for a Cluster #
1662 ; Find_Empty_Cluster - find an unused cluster
1663 ; Xfer_Data - transfere data from one cluster to another
1664 ; Direct_Access - absolute disk i/o
1665 ;
1666 ;Input:
1667 ;
1668 ;Output: CF = 0 found and freed [cluster_number]
1669 ; CF = 1 - ax = 0 - at end of directory
1670 ; ax = (message + class) - error occured
1671 ; ax = -1 - SubDir found
1672 ; bx = pointer to current entry
1673 ;
1674 ;Change History: Created 7/01/87 FG
1675 ;
1676 ;******************* END OF SPECIFICATIONS *************************************
1677 ;******************+ START OF PSEUDOCODE +**************************************
1678 ;
1679 ; START Search_Loop
1680 ;
1681 ; search till at end of directory - all clusters checked
1682 ; search till at end of sectors - in given cluster
1683 ; search till at end of sector - all entries checked
1684 ; exitif starting cluster = [cluster_number]
1685 ; set up for FAT
1686 ; call Find_Empty_Cluster
1687 ; if no error and
1688 ; call Xfer_Data
1689 ; reset for DIR
1690 ; if no error
1691 ; update dir_first_clust
1692 ; set up for write
1693 ; call Direct_Access to write out the directory
1694 ; endif
1695 ; orelse
1696 ; leave if entry is a subdirectory (ah = ffh)
1697 ; advace to next entry
1698 ; zero ax
1699 ; endloop if past end of sector
1700 ; set fail flag (CF)
1701 ; endsrch
1702 ; exit if [current_cluster] found (NC)
1703 ; orelse
1704 ; leave if subdirectory found (CF + FF)
1705 ; if sectors left to read
1706 ; set up to read
1707 ; call Direct_Access to read sector
1708 ; else
1709 ; set error flag (CF)
1710 ; zero ax (end of sectors)
1711 ; endif
1712 ; endloop if error
1713 ; endsrch
1714 ; leave if [current_cluster] found (NC)
1715 ; leave if SubDir found (CF + FF)
1716 ; leave if Error (CF + message)
1717 ; get [current_cluster] #
1718 ; call Unpack to get next cluster #
1719 ; exitif no more clusters
1720 ; zero ax (end of clusters)
1721 ; set error flag (CF)
1722 ; orelse
1723 ; convert cluster # to logical sector #
1724 ; update [current_sector]
1725 ; endloop
1726 ; endsrch
1727 ;
1728 ; ret
1729 ;
1730 ; END Search_Loop
1731 ;
1732 ;******************- END OF PSEUDOCODE -**************************************
1733
1734 public Search_Loop
1735
1736 Search_Loop PROC NEAR
1737
1738 mov ax,[present_cluster] ; initailize for search ;AN004;
1739 cmp ax,0 ; ;AN004;
1740 ; $if ne ; ;AN004;
1741 JE $$IF135
1742 call cluster_2_sector ; convert it to a sector ;AN004;
1743 add ax,[sector_offset] ; ;AC015;
1744 ; $if c ; ;AN004;
1745 JNC $$IF136
1746 inc dx ; ;AN004;
1747 ; $endif ; ;AN004;
1748 $$IF136:
1749 ; $else ; ;AN004;
1750 JMP SHORT $$EN135
1751 $$IF135:
1752 mov ax,[sector_offset] ;[sector_offset] = current root sector ;AC015;
1753 xor dx,dx ; ;AN004;
1754 ; $endif ; ;AN004;
1755 $$EN135:
1756 mov [packet],ax ; ;AN004;
1757 mov [packet+2],dx ; ;AN004;
1758 xor ah,ah ; ;AN004;
1759 call Direct_Access ; to read the DIR ;AN004;
1760 mov al,SIZE dir_entry ; ;AN004;
1761 mov cl,[entry_number] ; ;AN004;
1762 mul cl ; ;AN004;
1763 lea bx,DIR_SECTOR ; ;AN004;
1764 add bx,ax ; BX now points to the DIR entry ;AN004;
1765 ; $search ; till at end of directory ;AN004;
1766 $$DO140:
1767 ; - all clusters checked
1768 ; $search ; till at end of sectors ;AN004;
1769 $$DO141:
1770 ; - in given cluster
1771 ; $search ; till at end of sector ;AN004;
1772 $$DO142:
1773 ; - all entries checked
1774 cmp BYTE PTR [bx],deleted ; make sure the entry is valid !!! ;AN019;
1775 ; $if e ; if it is not - ;AN019;
1776 JNE $$IF143
1777 xor ax,ax ; ;AN019:
1778 mov [bx.dir_first],ax ; zap the starting cluster ;AN019;
1779 mov [bx.dir_attr],al ; zap the attribute ;AN019;
1780 ; $endif ; ;AN019;
1781 $$IF143:
1782 mov ax,[bx.dir_first] ; ;AN004;
1783 cmp ax,[current_cluster] ; ;AN004;
1784 ; $exitif e,and,long ; starting cluster = [current_cluster] ;AN004;
1785 JE $$XL4
1786 JMP $$IF142
1787 $$XL4:
1788 cmp BYTE PTR [bx],deleted ; make sure the entry is valid !!! ;AN007;
1789 ; $exitif ne,and,long ; and entry is not deleted ;AN007;
1790 JNE $$XL5
1791 JMP $$IF142
1792 $$XL5:
1793 cmp BYTE PTR [bx],dot ; ;AN007;
1794 ; $exitif ne,long ; and entry is not a . or .. name ;AN007;
1795 JNE $$XL6
1796 JMP $$IF142
1797 $$XL6:
1798 test [bx.dir_attr],attr_directory ; is it a subdir ? ;AN007;
1799 ; $if nz ;if entry is a subdirectory ;AN007;
1800 JZ $$IF146
1801 inc [DIR_cluster] ; signal special processing ;AN007;
1802 ; Xfere_Data will use this later -
1803 ; 0 = not a sub DIR
1804 ; 1 = do Sub DIR processing and
1805 ; update [DIR_cluster] to the
1806 ; same value as [empty_cluster]
1807 ; $endif ; ;AN007;
1808 $$IF146:
1809 mov ax,[packet] ; save pointer to this DIR ;AN007;
1810 mov [dir_sector_low],ax ; ;AN007;
1811 mov ax,[packet+2] ; ;AN007;
1812 mov [dir_sector_hi],ax ; ;AN007;
1813 mov [source_ptr],bx ; save pointer ;AN004;
1814 mov [cluster_high],1 ; force Upack to load FAT ;AN004;
1815 mov ax,[FAT_sectors] ; get the size right ;AN004;
1816 mov [packet_sectors],ax ; ;AN004;
1817 mov [packet],1 ; ;AN004;
1818 mov [packet+2],0 ; ;AN004;
1819 mov [packet_buffer],OFFSET BUF ; ;AN004;
1820 call Find_Empty_Cluster ; ;AN004;
1821 ; $if nc,and ; no errors so far ;AN004;
1822 JC $$IF148
1823 mov si,[empty_cluster] ; ;AN004;
1824 mov dx,[next_cluster] ; ;AN004;
1825 call PACK ; ;AN004;
1826 ; $if nc,and ; no errors so far ;AN004;
1827 JC $$IF148
1828 mov si,[current_cluster] ; ;AN004;
1829 xor dx,dx ; make it empty ;AN004;
1830 call PACK ; ;AN004;
1831 ; $if nc ; no errors so far ;AN004;
1832 JC $$IF148
1833 cmp [bigfat],0 ; ;AN004;
1834 ; $if ne ; ;AN004;
1835 JE $$IF149
1836 mov [cluster_high],1 ; ensure that FAT will be updated ;AN004;
1837 call Unpack ; ;AN004;
1838 ; $else ; must manualy write out 12 bit FATS ;AN004;
1839 JMP SHORT $$EN149
1840 $$IF149:
1841 xor ah,ah ; ;AN004;
1842 dec ah ; ;AN004;
1843 mov [packet],1 ; start with the first FAT ;AN004;
1844 call Direct_Access ; write it out - ignore errors ;AN004;
1845 mov ax,[FSIZE] ; ;AN004;
1846 add [packet],ax ; advance to second FAT ;AN004;
1847 xor ah,ah ; ;AN004;
1848 dec ah ; ;AN004;
1849 call Direct_Access ; write it out - ignore errors ;AN004;
1850 ; $endif ; ;AN004;
1851 $$EN149:
1852 ; $endif ; ;AN004;
1853 $$IF148:
1854 ; $if nc,and ; no error and ;AN004;
1855 JC $$IF153
1856 call Xfer_Data ; ;AN004;
1857 ; $if nc ; no error ;AN004;
1858 JC $$IF153
1859 mov ax,[empty_cluster] ; update dir_first_clust ;AN004;
1860 mov bx,[source_ptr] ; recover pointer ;AN004;
1861 mov [bx.dir_first],ax ; ;AN004;
1862 mov [packet_sectors],1 ; set size back ;AN004;
1863 mov [packet_buffer],OFFSET DIR_SECTOR ; ;AN004;
1864 mov ax,[dir_sector_low] ; reset DIR sector ;AN007;
1865 mov [packet],ax ; ;AN007;
1866 mov ax,[dir_sector_hi] ; ;AN007;
1867 mov [packet+2],ax ; ;AN007;
1868 xor ah,ah ; set up for write ;AN004;
1869 dec ah ; ;AN004;
1870 call Direct_Access ; to write out the directory ;AN004;
1871 ; $if nc,and ; ;AN004;
1872 JC $$IF154
1873 cmp [DIR_cluster],0 ; is a DIR being processed ? ;AN007;
1874 ; $if ne ; ;AN007;
1875 JE $$IF154
1876 call Sub_DIR_Loop ; update any children ;AN007;
1877 ; $endif ; ;AN007;
1878 $$IF154:
1879 ; $if nc ; if no errors ;AN007;
1880 JC $$IF156
1881 mov ax,[FAT_sectors] ;only read needed sectors ;AN004;
1882 mov [packet_sectors],ax ; ;AN004;
1883 mov [packet],1 ; ;AN004;
1884 mov [packet_buffer],OFFSET BUF ; point to FAT buffer ;AN004;
1885 mov [cluster_high],clusters_loaded ; ;AN004;
1886 mov [cluster_low],0 ; ;AN004;
1887 xor cx,cx ; ;AN004;
1888 mov di,cx ; ;AN004;
1889 dec di ; ;AN004;
1890 mov cl,[num_of_FATS] ; ;AN004;
1891 ; ;AN004;
1892 call Load_FAT ; restore FAT ;AN004;
1893 ; ;AN004;
1894 push es ; update DPB first cluster ;AN004;
1895 mov bx,ds ; ;AN004;
1896 mov es,bx ; ;AN004;
1897 lds bx,[THIS_DPB] ; ;AN004;
1898
1899 ASSUME ds:nothing,es:DATA
1900
1901 mov [bx.dpb_next_free],2 ; ;AN004;
1902 mov ax,es ; ;AN004;
1903 mov ds,ax ; ;AN004;
1904 pop es ; ;AN004;
1905
1906 ASSUME DS:data, es:nothing
1907
1908 ; $endif ; ;AN004;
1909 $$IF156:
1910 ; $endif ; ;AN004;
1911 $$IF153:
1912 ; $orelse ; ;AN004;
1913 JMP SHORT $$SR142
1914 $$IF142:
1915 xor ax,ax ; get ready in case ----- ;AN007;
1916 cmp BYTE PTR [bx],0 ; at the end of the dir? ;AN007;
1917 ; $leave e ; then no point in continuing ;AN007;
1918 JE $$EN142
1919 dec ax ; get ready in case we fail ;AN004;
1920 test [bx.dir_attr],attr_directory ; is it a subdir ? ;AN004;
1921 ; $leave nz, and ;if entry is a subdirectory (ah = ffh) ;AN004;
1922 JZ $$LL161
1923 cmp byte ptr [bx],dot ; but not a DOT ;AN007;
1924 ; $leave ne ; ;AN007;
1925 JNE $$EN142
1926 $$LL161:
1927 xor ax,ax ; zero ax ;AN004;
1928 add bx,SIZE dir_entry ; advace to next entry ;AN004;
1929 inc [entry_number] ; ;AN004;
1930 cmp bx,OFFSET BUF ; are we out of sector ? ;AN004;
1931 ; $endloop ae,long ;if past end of sector ;AN004;
1932 JAE $$XL7
1933 JMP $$DO142
1934 $$XL7:
1935 $$EN142:
1936 stc ; set fail flag (CF) ;AN004;
1937 ; $endsrch ; ;AN004;
1938 $$SR142:
1939 ; $exitif nc ;[current_cluster] found (NC) ;AN004;
1940 JC $$IF141
1941 ; $orelse ; ;AN004;
1942 JMP SHORT $$SR141
1943 $$IF141:
1944
1945 ; we have CF = 1 and could have:
1946 ; AX = 0 -
1947 ; AX = 1 to fffe
1948 ; AX = ffff
1949 ; so - leave if anything other than
1950 ; AX = 0 (out of stuff)
1951
1952 ; $leave c,and ; if not out of stuff ;AN004;
1953 JNC $$LL166
1954 cmp ax,0 ; ;AN009;
1955 stc ; restore carry flag! ;AN007;
1956 ; $leave nz ; ------ leave ! ;AN009;
1957 JNZ $$EN141
1958 $$LL166:
1959 mov ax,[sector_offset] ; ;AC015;
1960 inc ax ; ;AN004;
1961 cmp [present_cluster],0 ; are we in the root? ;AN007;
1962 ; $if e ; if so - ;AN004;
1963 JNE $$IF167
1964 cmp ax,[l_sector_offset] ; use root sectors ;AC013;
1965 ; $else ; else - ;AN004;
1966 JMP SHORT $$EN167
1967 $$IF167:
1968 cmp ax,[CSIZE] ; use sectors per cluster ;AN004;
1969 ; $endif ; ;AN004;
1970 $$EN167:
1971 ; $if b ; sectors left to read ;AN004;
1972 JNB $$IF170
1973 add [packet],1 ; advance to the next sector ;AN004;
1974 ; $if c ; ;AN004;
1975 JNC $$IF171
1976 inc [packet+2] ; adjust high word if needed ;AN004;
1977 ; $endif ; ;AN004;
1978 $$IF171:
1979 xor ah,ah ; set up to read ;AN004;
1980 mov [entry_number],ah ; ;AN004;
1981 inc [sector_offset] ; ;AN004;
1982 call Direct_Access ; to read sector ;AN004;
1983 lea bx,DIR_SECTOR ; set index to start of sector ;AN004;
1984 ; $else ; ;AN004;
1985 JMP SHORT $$EN170
1986 $$IF170:
1987 xor ax,ax ; zero ax (end of sectors) ;AN004;
1988 stc ; set error flag (CF) ;AN004;
1989 ; $endif ; ;AN004;
1990 $$EN170:
1991 ; $endloop c,long ; if error ;AN004;
1992 JC $$XL8
1993 JMP $$DO141
1994 $$XL8:
1995 $$EN141:
1996 ; $endsrch ; ;AN004;
1997 $$SR141:
1998 ; $leave nc ; if [current_cluster] found (NC) ;AN004;
1999 JNC $$EN140
2000 ; $leave c,and ;if SubDir found (CF + FF) ;AN004;
2001 JNC $$LL178
2002 cmp ax,0 ; ;AN004;
2003 stc ; set carry ;AN007;
2004 ; $leave nz ; if Error (CF + messageor FFFFh) ;AN004;
2005 JNZ $$EN140
2006 $$LL178:
2007
2008 ;--------------------------------------
2009 ; CF = 1 and AX = 0 means - no critical
2010 ; errors
2011 ; - no Sub DIR
2012 ; found
2013 ; inner SEARCH is out of sectors
2014 ; - so advance to the next cluster
2015 ;--------------------------------------
2016 mov si,[present_cluster] ; get [present_cluster] # ;AN004;
2017 cmp si,0 ; end of the root ? ;AN004;
2018 ; $if nz ; ;AN004;
2019 JZ $$IF179
2020 mov [cluster_high],1 ; force Upack to load FAT ;AN004;
2021 mov ax,FAT_sectors ; get the size right ;AN004;
2022 mov [packet_sectors],ax ; ;AN004;
2023 mov [packet_buffer],OFFSET BUF ; ;AN004;
2024 call Unpack ; to get next cluster # ;AN004;
2025 mov [packet_sectors],1 ; set size back ;AN004;
2026 mov [cluster_high],1 ; ensure that FAT will be re-loaded ;AN004;
2027 mov [packet_buffer],OFFSET DIR_SECTOR ; ;AN004;
2028 mov ax,di ; ;AN007;
2029 cmp al,end_cluster ; ;AN007;
2030 ; $endif ; ;AN004;
2031 $$IF179:
2032 ; $exitif z ; no more clusters ;AN004;
2033 JNZ $$IF140
2034 xor ax,ax ; zero ax (end of clusters) ;AN004;
2035 stc ; set error flag (CF) ;AN004;
2036 ; $orelse ; ;AN004;
2037 JMP SHORT $$SR140
2038 $$IF140:
2039 mov [present_cluster],di ; ;AN004;
2040 mov ax,di ; set up for cluster_2_sector ;AN004;
2041 call cluster_2_sector ; convert cluster # to logical sector #;AN004;
2042 mov [packet],ax ; ;AN004;
2043 mov [packet+2],dx ; ;AN004;
2044 xor ax,ax ; ;AN004;
2045 mov [sector_offset],ax ; reset [sector_offset] ;AC015;
2046 mov [entry_number],ah ; reset [entry_number] ;AN004;
2047 call Direct_Access ; to read sector ;AN004;
2048 lea bx,DIR_SECTOR ; set pointer ;AN004;
2049 ; $endloop c,long ; end loop if read fails ;AN004;
2050 JC $$XL9
2051 JMP $$DO140
2052 $$XL9:
2053 $$EN140:
2054 ; $endsrch ; ;AN004;
2055 $$SR140:
2056
2057 ret ; ;AN004;
2058
2059 Search_Loop ENDP
2060
2061 BREAK <SYS - Sub_DIR_Loop >
2062
2063 ;******************* START OF SPECIFICATIONS ***********************************
2064 ;Routine name: Sub_DIR_Loop
2065 ;*******************************************************************************
2066 ;
2067 ;Description: Sub_DIR_Loop scans through all entries of a subdirectory looking
2068 ; child subdirectories. If found, their parent [dir_first] entries
2069 ; (the .. entry) are updated to point to the correct cluster
2070 ;
2071 ;Called Procedures:
2072 ;
2073 ; Unpack - to find a FAT entry for a Cluster #
2074 ; Direct_Access - absolute disk i/o
2075 ;
2076 ;Input: [empty_cluster] - new parent Sub DIR cluster #
2077 ; [DIR_cluster] - current cluster of DIR being looped
2078 ;
2079 ;Output: CF = 0 at end of directory
2080 ; CF = 1 a read/write error occured
2081 ;
2082 ;Change History: Created 10/07/87 FG
2083 ;
2084 ;******************* END OF SPECIFICATIONS *************************************
2085 ;******************+ START OF PSEUDOCODE +**************************************
2086 ;
2087 ; START Sub_DIR _Loop
2088 ;
2089 ; get DIR_cluster
2090 ; call cluster_2_sector
2091 ; update packet
2092 ; set for read
2093 ; reset entry pointer
2094 ; reset sector count
2095 ; call Direct_Access
2096 ; if no error
2097 ; search till at end of directory - all clusters checked
2098 ; search till at end of sectors - in given cluster
2099 ; search till at end of sector - all entries checked
2100 ; leave if null entry
2101 ; if entry is not deleted and
2102 ; if this entry is a subdir and
2103 ; if this is a true entry and
2104 ; save current sector
2105 ; save current entry
2106 ; get start cluster
2107 ; call cluster_2_sector
2108 ; set for read
2109 ; call Direct_Access
2110 ; if no errors and
2111 ; update pointer to parent
2112 ; set for write
2113 ; call Direct_Access
2114 ; if no errors and
2115 ; recover current sector
2116 ; recover current entry
2117 ; if no errors
2118 ; call Direct_Access
2119 ; endif
2120 ; exitif error (CF)
2121 ; orelse
2122 ; advance to next entry
2123 ; endloop if past end of sector
2124 ; clear error flag
2125 ; endsrch
2126 ; leave if error
2127 ; advance to next sector (packet)
2128 ; incriment sector count
2129 ; exitif past end of cluster
2130 ; clear error flag
2131 ; orelse
2132 ; reset entry pointer
2133 ; set for read
2134 ; call Direct_Access
2135 ; endloop if error
2136 ; endsrch
2137 ; leave if error
2138 ; get DIR_cluster
2139 ; call UNPACK to find next Sub DIR cluster
2140 ; exitif at end of chain
2141 ; clear error flag
2142 ; orelse
2143 ; update DIR_cluster
2144 ; call cluster_2_sector
2145 ; update packet
2146 ; set for read
2147 ; call Direct_Access
2148 ; leave if error
2149 ; reset entry pointer
2150 ; reset sector count
2151 ; endloop
2152 ; endsrch
2153 ; endif
2154 ; reset Sub_DIR_cluster to 0
2155 ;
2156 ; ret
2157 ;
2158 ; END Sub_DIR_Loop
2159 ;
2160 ;******************- END OF PSEUDOCODE -**************************************
2161
2162 public Sub_DIR_Loop
2163
2164 Sub_DIR_Loop PROC NEAR
2165
2166 mov ax,[DIR_cluster] ; get DIR_cluster ;AN007;
2167 call cluster_2_sector ; to convert to a logical sector ;AN007;
2168 mov [packet],ax ; update packet ;AN007;
2169 mov [packet+2],dx ; ;AN007;
2170 xor ax,ax ; set for read ;AN007;
2171 call Direct_Access ; to read the first sector of the DIR ;AN007;
2172 ; $if nc,long ; if no error ;AN007;
2173 JNC $$XL10
2174 JMP $$IF185
2175 $$XL10:
2176 mov [sector_count],1 ; reset sector count ;AN007;
2177 lea bx,DIR_SECTOR ; reset entry pointer ;AN007;
2178 ; $search ; till at end of directory ;AN007;
2179 $$DO186:
2180 ; - all clusters checked ;AN007;
2181 ; $search ; till at end of sectors ;AN007;
2182 $$DO187:
2183 ; - in given cluster ;AN007;
2184 ; $search ; till at end of sector ;AN007;
2185 $$DO188:
2186 ; - all entries checked ;AN007;
2187 mov [dir_offset],bx ; reset entry pointer ;AN007;
2188 cmp BYTE PTR [bx],0 ; null entry (00)? ;AN007;
2189 ; $leave z ; if null entry ;AN007;
2190 JZ $$EN188
2191 cmp BYTE PTR [bx],deleted ; deleted entry (E5)? ;AN007;
2192 ; $if ne,and ; if entry is not deleted and ;AN007;
2193 JE $$IF190
2194 test [bx.dir_attr],attr_directory ; is it a subdir ? ;AN007;
2195 ; $if nz,and ; if this entry is a subdir and ;AN007;
2196 JZ $$IF190
2197 cmp BYTE PTR [bx],dot ; dot entry (2E)? ;AN007;
2198 ; $if ne,and ; this is a true entry and ;AN007;
2199 JE $$IF190
2200 mov ax,[packet] ; save current sector ;AN007;
2201 mov [dir_sector_low],ax ; ;AN007;
2202 mov ax,[packet+2] ; ;AN007;
2203 mov [dir_sector_hi],ax ; ;AN007;
2204 mov ax,[bx.dir_first] ; get start cluster ;AN007;
2205 call cluster_2_sector ; convert to sector ;AN007;
2206 mov [packet],ax ; update packet ;AN007;
2207 mov [packet+2],dx ; ;AN007;
2208 xor ax,ax ; set for read ;AN007;
2209 call Direct_Access ; to read it in ;AN007;
2210 ; $if nc,and ; no errors and ;AN007;
2211 JC $$IF190
2212 mov ax,[empty_cluster] ; update pointer to parent ;AN007;
2213 lea bx,DIR_SECTOR ; ;AN007;
2214 mov [bx + dir_first + size dir_entry],ax ; ;AN007;
2215 xor ax,ax ; set for write ;AN007;
2216 dec ax ; ;AN007;
2217 call Direct_Access ; to write it back ;AN007;
2218 ; $if nc,and ; if no errors and ;AN007;
2219 JC $$IF190
2220 mov ax,[dir_sector_low] ; ;AN007;
2221 mov [packet],ax ; recover current sector ;AN007;
2222 mov ax,[dir_sector_hi] ; ;AN007;
2223 mov [packet+2],ax ; ;AN007;
2224 ; $if nc ; if no errors ;AN007;
2225 JC $$IF190
2226 call Direct_Access ; to continue where we left off ;AN007;
2227 ; $endif ; ;AN007;
2228 $$IF190:
2229 ; $exitif c ; quit if error (CF) ;AN007;
2230 JNC $$IF188
2231 ; $orelse ; ;AN007;
2232 JMP SHORT $$SR188
2233 $$IF188:
2234 mov bx,[dir_offset] ; recover current entry ;AN007;
2235 add bx,SIZE dir_entry ; advance to next entry ;AN007;
2236 cmp bx,OFFSET BUF ; ;AN007;
2237 ; $endloop a ; if past end of sector ;AN007;
2238 JNA $$DO188
2239 $$EN188:
2240 clc ; clear error flag ;AN007;
2241 ; $endsrch ; ;AN007;
2242 $$SR188:
2243 ; $leave c ; if error - quit ;AN007;
2244 JC $$EN187
2245 xor ax,ax ; ;AN007;
2246 mov ax,[CSIZE] ; incriment sector count ;AN007;
2247 inc [sector_count] ; ;AN007;
2248 cmp [sector_count],al ; ;AN007;
2249 ; $exitif a ; past end of cluster ;AN007;
2250 JNA $$IF187
2251 clc ; clear error flag ;AN007;
2252 mov [sector_count],1 ; reset sector count ;AN007;
2253 ; $orelse ; ;AN007;
2254 JMP SHORT $$SR187
2255 $$IF187:
2256 xor ax,ax ; set for read ;AN007;
2257 add WORD PTR [packet],1 ; advance to next sector (packet) ;AN007;
2258 adc [packet+2],ax ; look after carry ;AN007;
2259 call Direct_Access ; to read in next sector ;AN007;
2260 lea bx,DIR_SECTOR ; reset entry pointer ;AN007;
2261 ; $endloop c,long ; if error - quit ;AN007;
2262 JC $$XL11
2263 JMP $$DO187
2264 $$XL11:
2265 $$EN187:
2266 ; $endsrch ; ;AN007;
2267 $$SR187:
2268 ; $leave c ; if error - quit ;AN007;
2269 JC $$EN186
2270 mov si,[DIR_cluster] ; get DIR_cluster ;AN007;
2271 push [packet_sectors] ; save current packet stuff ;AN007;
2272 push [packet_buffer] ; ;AN007;
2273 mov ax,[FAT_sectors] ; update packet to FAT ;AN007;
2274 mov [packet_sectors],ax ; ;AN007;
2275 mov [packet_buffer],OFFSET BUF ; ;AN007;
2276 mov [cluster_high],1 ; force FAT to be reloaded - if needed ;AN007;
2277 call UNPACK ; to find next Sub DIR cluster ;AN007;
2278 pop [packet_buffer] ; recover packet to DIR ;AN007;
2279 pop [packet_sectors] ; ;AN007;
2280 mov ax,di ; ;AN007;
2281 cmp al,end_cluster ; ;AN007;
2282 ; $exitif e ; at end of chain ;AN007;
2283 JNE $$IF186
2284 clc ; clear error flag ;AN007;
2285 ; $orelse ; ;AN007;
2286 JMP SHORT $$SR186
2287 $$IF186:
2288 mov [DIR_cluster],ax ; ;AN007;
2289 call cluster_2_sector ; to convert to sector ;AN007;
2290 mov [packet],ax ; update packet ;AN007;
2291 mov [packet+2],dx ; ;AN007;
2292 xor ax,ax ; set for read ;AN007;
2293 call Direct_Access ; to read first sector of next cluster ;AN007;
2294 ; $leave c ; if error ;AN007;
2295 JC $$EN186
2296 lea bx,DIR_SECTOR ; reset entry pointer ;AN007;
2297 mov [sector_count],1 ; reset sector count ;AN007;
2298 ; $endloop long ; ;AN007;
2299 JMP $$DO186
2300 $$EN186:
2301 ; $endsrch ; ;AN007;
2302 $$SR186:
2303 ; $endif ; ;AN007;
2304 $$IF185:
2305 mov [DIR_cluster],0 ; reset Sub_DIR_cluster to 0 ;AN007;
2306
2307 ret ; ;AN007;
2308
2309 Sub_DIR_Loop ENDP
2310
2311 BREAK <SYS - Unpack >
2312 ;******************* START OF SPECIFICATIONS ***********************************
2313 ;Routine name: Unpack
2314 ;*******************************************************************************
2315 ;
2316 ;Description: Read an entry in the FAT
2317 ;
2318 ;Called Procedures:
2319 ;
2320 ; Check_FAT - to make sure right part of FAT is loaded (16 bit only)
2321 ;
2322 ;Input: Cluster number in SI
2323 ;
2324 ;Output: Return contents in DI
2325 ; xX destroyed
2326 ; ZF set if cluster is free
2327 ;
2328 ;Change History: Created 7/01/87 FG
2329 ;
2330 ;******************* END OF SPECIFICATIONS *************************************
2331 ;******************+ START OF PSEUDOCODE +**************************************
2332 ;
2333 ; START Unpack
2334 ;
2335 ; if 16 bit FAT
2336 ; call Check_FAT
2337 ; multiply # by 2
2338 ; read value
2339 ; check if empty
2340 ; else
2341 ; multiply # by 2
2342 ; read value
2343 ; if not word alligned
2344 ; shift to allign
2345 ; endif
2346 ; mask off unused portion (set ZF if empty)
2347 ; endif
2348 ;
2349 ; ret
2350 ;
2351 ; END Unpack
2352 ;
2353 ;******************- END OF PSEUDOCODE -**************************************
2354
2355 public Unpack
2356
2357 Unpack PROC NEAR
2358
2359 lea bx,BUF ; ;AN004;
2360 mov di,si ; ;AN004;
2361 cmp [BIGFAT],0 ; ;AN004;
2362 ; $if nz ; if 16 bit FAT ;AN004;
2363 JZ $$IF208
2364 push si ; ;AN004;
2365 call Check_FAT ; make sure right part of FAT loaded ;AN004;
2366 ; $if nc ; ;AN004;
2367 JC $$IF209
2368 mov di,si ; Check_FAT ajusts si ;AN004;
2369 shl di,1 ; Mult by 2 ;AN004;
2370 mov di,WORD PTR [di+bx] ; ;AN004;
2371 or di,di ; Set zero ;AN004;
2372 clc ; ;AN004;
2373 ; $endif ; ;AN004;
2374 $$IF209:
2375 pop si ; ;AN004;
2376 ; $else ; is 12 bit fat ;AN004;
2377 JMP SHORT $$EN208
2378 $$IF208:
2379 shr di,1 ; ;AN004;
2380 add di,si ; Mult by 1.5 ;AN004;
2381 mov di,WORD PTR [di+bx] ; ;AN004;
2382 test si,1 ; ;AN004;
2383 ; $if nz ; not allign on cluster ;AN004;
2384 JZ $$IF212
2385 shr di,1 ; ;AN004;
2386 shr di,1 ; ;AN004;
2387 shr di,1 ; ;AN004;
2388 shr di,1 ; ;AN004;
2389 ; $endif ; ;AN004;
2390 $$IF212:
2391 and di,0FFFh ; ;AN004;
2392 ; $endif ; ;AN004;
2393 $$EN208:
2394
2395
2396 ret ; ;AN004;
2397
2398 Unpack ENDP
2399
2400 BREAK <SYS - Pack >
2401 ;******************* START OF SPECIFICATIONS ***********************************
2402 ;Routine name: Pack
2403 ;*******************************************************************************
2404 ;
2405 ;Description: Change an entry in the FAT
2406 ;
2407 ;Called Procedures:
2408 ;
2409 ; Check_FAT - to make sure right part of FAT is loaded (16 bit only)
2410 ;
2411 ;Input: si - cluster number to be packed
2412 ; dx - data to be placed in cluster (si)
2413 ;
2414 ;Output: bx,dx destroyed
2415 ;
2416 ;Change History: Created 7/01/87 FG
2417 ;
2418 ;******************* END OF SPECIFICATIONS *************************************
2419 ;******************+ START OF PSEUDOCODE +**************************************
2420 ;
2421 ; START Pack
2422 ;
2423 ; if 16 bit FAT
2424 ; call Check_FAT
2425 ; convert cluster # to offset
2426 ; add offset of FAT
2427 ; store value
2428 ; else
2429 ; convert cluster # to offset
2430 ; add offset of FAT
2431 ; recover current entry word
2432 ; if not alligned on word boundary
2433 ; shift to allign
2434 ; mask off value to be replaced (byte)
2435 ; else
2436 ; mask off value to be replaced (word)
2437 ; endif
2438 ; combine new value and ballace
2439 ; store the entry
2440 ;
2441 ; ret
2442 ;
2443 ; END Pack
2444 ;
2445 ;******************- END OF PSEUDOCODE -**************************************
2446
2447 public Pack
2448
2449 Pack PROC NEAR
2450
2451 lea bx,BUF ; ;AN004;
2452 push si ; ;AN004;
2453 mov di,si ; ;AN004;
2454 cmp [BIGFAT],0 ; ;AN004;
2455 ; $if nz ; 16 bit FAT ;AN004;
2456 JZ $$IF215
2457 call Check_FAT ; make sure the part of the FAT we want;AN004;
2458 ; is loaded & ajust offset to match ;AN004;
2459 shl si,1 ; convert cluster # to offset ;AN004;
2460 add si,bx ; add offset of FAT ;AN004;
2461 mov [si],dx ; store value ;AN004;
2462 mov [FAT_changed],1 ; the fat has been changed ;AN004;
2463 ; $else ; its 12 bit FAT ;AN004;
2464 JMP SHORT $$EN215
2465 $$IF215:
2466 shr si,1 ; ;AN004;
2467 add si,bx ; ;AN004;
2468 add si,di ; ;AN004;
2469 shr di,1 ; ;AN004;
2470 mov di,[si] ; ;AN004;
2471 ; $if c ; no alligned ;AN004;
2472 JNC $$IF217
2473 shl dx,1 ; ;AN004;
2474 shl dx,1 ; ;AN004;
2475 shl dx,1 ; ;AN004;
2476 shl dx,1 ; ;AN004;
2477 and di,0Fh ; ;AN004;
2478 ; $else ; ;AN004;
2479 JMP SHORT $$EN217
2480 $$IF217:
2481 and di,0F000h ; ;AN004;
2482 ; $endif ; ;AN004;
2483 $$EN217:
2484 or di,dx ; ;AN004;
2485 mov [si],di ; ;AN004;
2486 ; $endif ; ;AN004;
2487 $$EN215:
2488 pop si ; ;AN004;
2489
2490 ret ; ;AN004;
2491
2492 Pack ENDP
2493
2494 BREAK <SYS - Check_FAT >
2495 ;******************* START OF SPECIFICATIONS ***********************************
2496 ;Routine name: Check_FAT
2497 ;*******************************************************************************
2498 ;
2499 ;Description: Check that the protion of the FAT that is referenced in SI
2500 ; is presently in memory.
2501 ;
2502 ; Only 12 sectors of the FAT are kept in memory. If the requested
2503 ; cluster does not fall within that range, 12 sectors of the FAT
2504 ; are read into memory - the first cluster will contain the entry
2505 ; of interest.
2506 ;
2507 ;Called Procedures:
2508 ;
2509 ; none
2510 ;
2511 ;Input: si - cluster number to be checked
2512 ; [FAT_changed] = 0 - no need to write out FAT before changing
2513 ; = x - must write before reading.
2514 ;
2515 ;
2516 ;Output: appropriate block of FAT in BUF
2517 ; si ajusted to match
2518 ; NB: BX, DX preserved (for UNPACK)
2519 ;
2520 ;Change History: Created 7/01/87 FG
2521 ;
2522 ;******************* END OF SPECIFICATIONS *************************************
2523 ;******************+ START OF PSEUDOCODE +**************************************
2524 ;
2525 ; START Check_FAT
2526 ;
2527 ;
2528 ; ret
2529 ;
2530 ; END Check_FAT
2531 ;
2532 ;******************- END OF PSEUDOCODE -**************************************
2533
2534 public Check_FAT
2535
2536 Check_FAT PROC NEAR
2537
2538 push bx
2539 cmp si,[cluster_low] ; ;AN004;
2540 ; $if ae,and ; ;AN004;
2541 JNAE $$IF221
2542 cmp si,[cluster_high] ; ;AN004;
2543 ; $if be ; ;AN004;
2544 JNBE $$IF221
2545 sub si,[cluster_low] ; ;AN004;
2546 ; $else ; the cluster is outside the range
2547 JMP SHORT $$EN221
2548 $$IF221:
2549 ; of the part of the FAT presently loaded.
2550 ; convert cluster # into sector + offset
2551 ; by dividing the cluster # by # of entries
2552 ; per sector IE: sector = 512 bytes
2553 ; cluster entry = 2 bytes
2554 ; then # of entries/sector = 256
2555
2556 cmp [FAT_changed],0 ; ;AN004;
2557 ; $if ne ; ;AN004;
2558 JE $$IF223
2559 xor ah,ah ; ;AN004;
2560 dec ah ; ;AN004;
2561 call Direct_Access ; write it out - ignore errors ;AN004;
2562 mov ax,[FSIZE] ; ;AN004;
2563 cmp [FAT_2],0 ; ;AN004;
2564 ; $if e ; ;AN004;
2565 JNE $$IF224
2566 add [packet],ax ; ;AN004;
2567 ; $else ; ;AN004;
2568 JMP SHORT $$EN224
2569 $$IF224:
2570 sub [packet],ax ; ;AN004;
2571 mov [FAT_2],0 ; packet points to FAT #2 ;AN004;
2572 ; $endif ; ;AN004;
2573 $$EN224:
2574 xor ah,ah ; ;AN004;
2575 dec ah ; ;AN004;
2576 call Direct_Access ; write it out - ignore errors ;AN004;
2577 mov [FAT_changed],0 ; FAT now cleared ;AN004;
2578 ; $endif ; ;AN004;
2579 $$IF223:
2580 mov ax,si ; ;AN004;
2581 xor cx,cx ; ;AN004;
2582 mov cl,al ; this is a cheap and ;AN004;
2583 mov al,ah ; dirty divide by 256 ;AN004;
2584 xor ah,ah ; ax = result ;AN004;
2585 push ax ; save starting sector ;AN006;
2586 mov si,cx ; cx = remainder ;AN004;
2587 inc ax ; leave room for boot sector ;AN004;
2588 mov [packet],ax ; ;AN004;
2589 mov [packet+2],0 ; ;AN004;
2590 push dx ; ;AN004;
2591 call Direct_Access ; ;AN004;
2592 ; $if c ; ;AN004;
2593 JNC $$IF228
2594 mov ax,[FSIZE] ; ;AN004;
2595 add [packet],ax ; ;AN004;
2596 mov [FAT_2],1 ; packet points to FAT #2 ;AN004;
2597 call Direct_Access ; ;AN004;
2598 ; $endif ; ;AN004;
2599 $$IF228:
2600 pop dx ; ;AN004;
2601 pop ax ; recover starting sector ;AN006;
2602 ; $if nc ; ;AN004;
2603 JC $$IF230
2604 xchg al,ah ; convert sector back to cluster ;AN004;
2605 mov [cluster_low],ax ; new bottom of FAT ;AN004;
2606 mov [cluster_high],ax ; ;AN004;
2607 add [cluster_high],clusters_loaded ; new top of FAT ;AN004;
2608 ; $endif ; ;AN004;
2609 $$IF230:
2610 ; $endif ; ;AN004;
2611 $$EN221:
2612 pop bx
2613
2614
2615 ret ; ;AN004;
2616
2617 Check_FAT ENDP
2618
2619 CODE ENDS
2620
2621 END
2622 \1a