summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/SYS/SYS2.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/CMD/SYS/SYS2.ASM')
-rw-r--r--v4.0/src/CMD/SYS/SYS2.ASM2622
1 files changed, 2622 insertions, 0 deletions
diff --git a/v4.0/src/CMD/SYS/SYS2.ASM b/v4.0/src/CMD/SYS/SYS2.ASM
new file mode 100644
index 0000000..6c96070
--- /dev/null
+++ b/v4.0/src/CMD/SYS/SYS2.ASM
@@ -0,0 +1,2622 @@
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
72first_dir_sector dw ?
73current_dir_sector dw ?
74last_dir_sector dw ?
75entries_per_sector db ?
76current_entry db 3
77source_ptr dw ?
78ibmbio_status db ?
79ibmdos_status db ?
80FAT_sectors dw FAT_sect_size ; initailize it to 12 sectors
81FAT_changed db 0 ; FAT must be written - its packed
82FAT_2 db 0 ; if non zero, [packet] points at FAT 2
83cluster_count dw ? ; number of clusters that must be free
84last_cluster dw 0 ; cluster pointing to [current_cluster]
85current_cluster dw 2 ; start at cluster 2
86next_cluster dw 0 ; cluster [current_cluster] points at
87empty_cluster dw 0 ; newly aquired cluster
88cluster_low dw 0
89cluster_high dw clusters_loaded
90
91l_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
95DIR_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)
101present_cluster dw ? ; current cluster for DIR search
102sector_offset dw ? ; current sector in present_cluster
103entry_number db ? ; DIR entry in current sector
104FRAME_ptr dw ?
105dir_sector_low dw ?
106dir_sector_hi dw ?
107DIR_offset dw ?
108sector_count db 1
109
110FRAME STRUC
111
112p_cluster dw ? ; current cluster for DIR search
113s_offset dw ? ; current sector in present_cluster
114e_number db ? ; DIR entry in current sector
115
116FRAME ENDS
117
118BIGFAT DB 0 ;0=12 bit FAT, NZ=16bit FAT
119EOFVAL DW 0FF8H ;0FF8 for 12 bit FAT,0FFF8 for 16 bit
120BADVAL DW 0FF7H ;0FF7 for 12 bit FAT,0FFF7 for 16 bit
121
122THIS_DPB DD ? ;Pointer to drive DPB
123CSIZE DW ? ;Sectors per cluster
124SSIZE DW ? ;bytes per sector
125DSIZE DW ? ;# alloc units on disk
126FSIZE DW ? ;# sectors in 1 FAT
127first_FAT DW ? ; first cluster of first FAT
128num_of_FATS db ? ; number of FATS
129MCLUS DW ? ;DSIZE + 1
130;
131; The following is used as the source/destination for a name trans
132;
133ENTRY_BUF DB size dir_entry DUP (?)
134DIR_BUF DB ( 34 * size frame) DUP (?) ; space for DIR frames - see Search_DIR
135DIR_SECTOR DB 512 DUP (?) ; space for 1 DIR sector
136
137BUF 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:
1533next_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:
1563if not ibmcopyright
1564 xor al, al
1565 mov [entry_number], al ; shall we start at, say, ENTRY ZERO? Hmmmmm?
1566endif
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;
1612if not ibmcopyright
1613 clc ; no error, continue with loop
1614endif
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 \ No newline at end of file