]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/SYS/SYS2.ASM
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 ; ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ä Ä Ä Ù
21 ; ³ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22 ; ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄ¿
23 ; ÀÄ´Free_ClusterÃÄÄÄÄ´Is_It_EmptyÃÄÄÄÄÄÄÄÄ´Unpack ³
24 ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ÀÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÙ
25 ; ³ÚÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
26 ; ôSearch_FATÃÄÄÄÄÄÄÄÄ´Unpack ³
27 ; ³ÀÄÄÄÄÄÄÄÄÄÄÙ ³À Ä Ä Ä Ù
31 ; ³ ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
32 ; ³ ôFind_Empty_Cluster³ÄÄ´Unpack ³
33 ; ³ ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ù
34 ; ³ ³ÚÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä Ä Ä Ä ¿
35 ; ³ ôXfer_DataÃÄÄÄÄÄÄÄÄÄÄÄ´Direct_Access³
36 ; ³ ³ÀÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ä Ä Ä Ù
38 ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À´Direct_Access³
40 ; ³ÚÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
41 ; À´Search_DIRÃÄÄÄÄ´Search_LoopÃÄÄÄÄÄ´Unpack ³
42 ; ÀÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÙ ³À Ä Ä Ä Ù
44 ; ôPack ³ Direct_Access
46 ; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
47 ; ôFind_Empty_Cluster³ÄÄ´Unpack ³
48 ; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ù
49 ; ³ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä ¿
50 ; ôSub_DIR_Loop³ÄÄ´Unpack ³
51 ; ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ù
52 ; ³ÚÄÄÄÄÄÄÄÄÄ¿ Ú Ä Ä Ä Ä Ä Ä ¿
53 ; ôXfer_DataÃÄÄÄÄÄÄÄÄÄÄÄ´Direct_Access³
54 ; ³ÀÄÄÄÄÄÄÄÄÄÙ À Ä Ä Ä Ä Ä Ä Ù
59 ;******************+ END OF PSEUDOCODE +*****************************************
60 BREAK <SYS2
- Data space
>
62 DATA SEGMENT PARA
PUBLIC
64 extrn TargDrvNum
:BYTE, TargSpec
:WORD, bio_owns_it
:BYTE, DOS_VER
:BYTE
65 extrn packet_sectors
:WORD, packet_buffer
:WORD, packet
:WORD
67 public THIS_DPB
, BUF
, DIR_SECTOR
, first_dir_sector
73 current_dir_sector dw ?
75 entries_per_sector 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
89 cluster_high dw clusters_loaded
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
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
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
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
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
131 ; The following is used as the source/destination for a name trans
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
137 BUF
LABEL BYTE ; beginning of area for file reads
143 CODE SEGMENT PARA
PUBLIC
145 ASSUME
cs:CODE, ds:nothing
, es:nothing
147 BREAK <SYS
- Find_DPB
>
148 ;******************* START OF SPECIFICATIONS ***********************************
149 ;Routine name: Find_DPB
150 ;*******************************************************************************
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.
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.
161 ;Entry: Called by Verify_File_Location
167 ;Input: al = Drive number
169 ;Output: All local variables initalized
170 ; DS:BX = pointer to DPB
172 ;Change History: Created 7/01/87 FG
174 ;******************* END OF SPECIFICATIONS *************************************
175 ;******************+ START OF PSEUDOCODE +**************************************
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
195 ;******************- END OF PSEUDOCODE -**************************************
202 MOV AH,GET_DPB
;Get the DPB ;AN004;
205 mov ax,(disk_reset
shl 8) ; reset the disk to protect all INT 26's
206 INT 21h
; that follow
209 ; initalize current_entry to #3
211 ASSUME
ds:nothing
,es:DATA
213 MOV WORD PTR [THIS_DPB
+2],DS ; ;AN004;
219 mov WORD PTR [THIS_DPB
],bx ; ;AN004;
220 lds bx,[THIS_DPB
] ; ;AN004;
224 mov ax,[bx.dpb_sector_size
] ; ;AN004;
225 mov [SSIZE
],ax ;Sector size in bytes ;AN004;
228 mov al,[bx.dpb_cluster_mask
] ; ;AN004;
230 mov [CSIZE
],ax ;Sectros per cluster ;AN004;
232 mov ax,[BX.dpb_first_FAT
] ;First sector of FAT ;AN004;
233 mov [first_FAT
],ax ; ;AN004;
235 mov al,[BX.dpb_FAT_count
] ;Number of FATs ;AN004;
236 mov [num_of_FATS
],al ; ;AN004;
238 mov ax,[bx.dpb_max_cluster
] ; ;AN004;
239 mov [MCLUS
],ax ;Bound for FAT searching ;AN004;
241 cmp ax,4096-10 ;Big or little FAT? ;AN004;
244 inc [BIGFAT
] ; ;AN004;
245 mov [EOFVAL
],0FFF8h ; ;AN004;
246 mov [BADVAL
],0FFF7h ; ;AN004;
250 mov [DSIZE
],ax ;Total data clusters on disk ;AN004;
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;
260 mov cx,[SSIZE
] ; # of bytes per sector ;AN004;
261 div cx ; = # of root directory sectors ;AN004;
262 cmp dx,0 ; any remainder ? ;AN004;
268 mov [first_dir_sector
],ax ; save for last directory sector calc. ;AN004;
270 mov ax,[bx.dpb_FAT_size
] ;Sectors for one fat ;AN004;
271 cmp DOS_VER
,0 ; running on current version? ;AN019;
273 ; $if ne ; BANG! - we'er running on DOS 3.3 ;AN019;
275 ; dpb_FAT_size is only a BYTE
276 ; so ajust it to a word
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 !
284 mov [FSIZE
],ax ; ;AN004;
286 mov ax,[SSIZE
] ; ;AN004;
287 mov cx,SIZE dir_entry
; ;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;
293 ; $if e ; if not ;AN004;
295 mov ax,[FSIZE
] ; ;AN004;
296 mov [FAT_sectors
],ax ; bring it down to the actual size ;AN004;
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;
307 add ax,[first_dir_sector
] ; # of last directory sector ;AN004;
308 mov [l_sector_offset
],ax ; ;AN004;
310 mov [last_dir_sector
],ax ; save it for later ;AN004;
316 BREAK <SYS
- Move_DIR_Entry
>
317 ;******************* START OF SPECIFICATIONS ***********************************
318 ;Routine name: Move_DIR_Entry
319 ;*******************************************************************************
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.
324 ;Entry: Called by Verify_File_Location
328 ; Find_Empty_Entry - find an available entry
329 ; Direct_Access - do an INT 25 & INT 26
331 ;Input: first_dir_sector
335 ; pointer set to source entry to be moved
337 ;Output: CF = 0 - DIR entry moved to first available entry
338 ; CF = 1 - Error, not able to free up entry
340 ;Change History: Created 7/01/87 FG
342 ;******************* END OF SPECIFICATIONS *************************************
343 ;******************+ START OF PSEUDOCODE +**************************************
345 ; START Move_DIR_Entry
347 ; set dest = entry_buffer
348 ; save source pointer
349 ; copy input entry to buffer
351 ; call Find_Empty_Entry to find hole in directory
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
358 ; call Direct_Access to write it out
360 ; set up for first_dir_sector
362 ; call Direct_Access to read it in
365 ; recover source pointer
366 ; null out entry being processed
368 ; call Direct_Access to update the root
376 ;******************- END OF PSEUDOCODE -**************************************
379 PUBLIC Move_DIR_Entry
381 Move_DIR_Entry PROC
NEAR
383 ASSUME
ds:DATA ; must ensure this is true xxxxxxxxxxxxxxxxx
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;
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;
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;
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;
408 mov ah,-1 ; set up for write ;AN004;
409 call Direct_Access
; write it out ;AN004;
410 ; $if nc ; if no error ;AN004;
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;
421 ; $if nc ; if no error ;AN004;
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;
429 cmp BYTE PTR [si + size DIR_ENTRY
],0 ; is second one a null entry? ;AN010;
430 ; $if e ; if so - ;AN010;
432 mov BYTE PTR [si + size DIR_ENTRY
],deleted
; make it deleted ;AN010;
435 mov ah,-1 ; set up for write ;AN004;
436 call Direct_Access
; write it out ;AN004;
446 BREAK <SYS
- Find_Empty_Entry
>
447 ;******************* START OF SPECIFICATIONS ***********************************
448 ;Routine name: Find_Empty_Entry
449 ;*******************************************************************************
451 ;Description: Find_Empty_Entry scans all root directory sectors looking for
454 ; NOTE; It is assumed that each DIRectory entry is 32 bytes long
458 ; Direct_Acces - do INT 25
460 ;Input: current_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)
466 ;Output: success pointer set to hole
467 ; CF = 0 current_entry updated
468 ; current_dir_sector updated
473 ;Change History: Created 7/01/87 FG
475 ;******************* END OF SPECIFICATIONS *************************************
476 ;******************+ START OF PSEUDOCODE +**************************************
478 ; START Find_Empty_Entry
480 ; search all available sectors
481 ; search for hole (leaves pointer set to the hole)
484 ; advace to next entry
485 ; exitif past end of sector
492 ; exitif hole found (no CF)
493 ; update current_entry
495 ; if not at end (current <= last)
497 ; call Direct_Access to read in next sector
499 ; load error message (no room for system files)
502 ; leave if error (CF)
503 ; update current_DIR_sector
504 ; update current_entry
511 ; END Find_Empty_Entry
513 ;******************- END OF PSEUDOCODE -**************************************
515 PUBLIC Find_Empty_Entry
517 Find_Empty_Entry PROC
NEAR
519 ; $search ; for sectors available ;AN004;
522 ; $search ; for hole - this leaves pointer set at;AN004;
525 cmp BYTE PTR [si],empty
; empty ? ;AN004;
528 cmp BYTE PTR [si],deleted
; deleted ? ;AN004;
531 add ax,size dir_entry
; advace to next entry ;AN004;
533 cmp ax,di ; past end of sector ? ;AN004;
534 ; $exitif ae ; at end ;AN004;
536 stc ; set carry ;AN004;
543 clc ; clear carry ;AN004;
546 ; $exitif nc ; hole is found ;AN004;
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;
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;
562 dec [current_dir_sector
] ; restore curren_dir_sector ;AN004;
565 ; $leave c ; error ;AN004;
567 mov ax,si ; reset pointer to start ;AN004;
568 ; $endloop a ; past last_dir_sector ;AN004;
571 mov ax,(util
shl 8) + no_room
; set message# and class ;AN004;
572 stc ; ensure carry still set ;AN004;
578 Find_Empty_Entry ENDP
582 BREAK <SYS
- Direct_Access
>
583 ;******************* START OF SPECIFICATIONS ***********************************
584 ;Routine name: Direct_Access
585 ;*******************************************************************************
587 ;Description: Direct_Access
594 ;Input: ah = 0 - read
597 ;Output: CF = 0 - Sectors moved
598 ; CF = 1 - Message and class in AX
600 ;Change History: Created 7/01/87 FG
602 ;******************* END OF SPECIFICATIONS *************************************
603 ;******************+ START OF PSEUDOCODE +**************************************
605 ; START Direct_Access
617 ; set message# and class
625 ;******************- END OF PSEUDOCODE -**************************************
629 Direct_Access PROC
NEAR
631 push si ; save registers ;AN004;
632 push bp ; save registers ;AN004;
633 cmp DOS_VER
,0 ; ;AN019;
638 mov cx,-1 ; set up for INT ;AN004;
639 mov bx,offset packet
; ;AN004;
644 ; If running on DOS 3.3 the INT 25
647 ; bx = buffer for read data
650 mov cx,word ptr [packet_sectors
] ; ;AN019;
651 mov dx,[packet
] ; get starting dir sector ;AN019;
652 mov bx,PACKET_BUFFER
[0] ; ;AN019;
657 mov al,TargDrvNum
; set up drive number ;AN004;
660 ; $if e ; if read ;AN004;
662 INT 25h
; INT 25 ;AN004;
663 ; $else ; else ;AN004;
666 xor ah,ah ; zero ah ;AN004;
667 INT 26h
; INT 26 ;AN004;
668 ; $endif ; endif ;AN004;
670 ;; ? ; save return flag ;AN004;
671 pop ax ; clear stack ;AN004;
679 BREAK <SYS
- Free_Cluster
>
680 ;******************* START OF SPECIFICATIONS ***********************************
681 ;Routine name: Free_Cluster processor
682 ;*******************************************************************************
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
690 ;Entry: Called by Verify_File_Location
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
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).
701 ;Input: All local DBP values initalized by Get_DPB
703 ;Ouput: CF = 0 - Cluster available
704 ; CF = 1 - Cluster not available
707 ;Change History: Created 7/01/87 FG
709 ;******************* END OF SPECIFICATIONS *************************************
710 ;******************+ START OF PSEUDOCODE +**************************************
714 ; initialize [cluster_count]
715 ; do until all copies of FAT attempted
716 ; load FAT into memory (INT 25)
717 ; leave if successful
719 ; do until [cluster_count] = 0
735 ;******************- END OF PSEUDOCODE -**************************************
739 Free_Cluster PROC
NEAR
741 mov ax,IBMLOADSIZE
; calculate # of clusters reqd ;AN004;
745 mov cx,[CSIZE
] ; by IBMLOAD (consecutive clusters ;AN004;
746 div cl ; for IBMBIO) ;AN004;
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;
766 ; $do complex ; ;AN004;
769 mov [cluster_count
],cx ; ;AN004;
770 call Is_It_Empty
; ;AN004;
773 cmp al,not_found
; ( -1 ?) ;AN004;
774 ; $if e ; if not found ;AN004;
776 call Search_FAT
; scan FAT to see if cluster chained ;AN004;
785 cmp al,not_found
; if still not found ;AN004;
788 call Search_DIR
; scan DIR to see who starts with #2 ;AN004;
792 clc ; ensure carry is still clear ;AC013;
797 inc [current_cluster
] ; ;AN004;
800 mov cx,[cluster_count
] ; ;AN004;
801 ; $enddo LOOP ; ;AN004;
808 mov ax,(util
shl 8) + no_room
; error message - no room to sys ;AN014;
820 lea bx,[packet
] ; ;AN004;
830 mov al,TargDrvNum
; set up drive number ;AN004;
832 cmp DOS_VER
,0 ; if DOS 3.3 ;AN019;
834 ; $if ne ; load registers for old style INT 25 ;AN019;
836 mov bx,[packet_buffer
] ; ;AN019;
837 mov cx,[packet_sectors
] ; ;AN019;
838 mov dx,[packet
] ; ;AN019;
843 int 25h
;Read in the FAT ;AN004;
844 pop ax ;Flags ;AN004;
846 ; $exitif nc ; error - set up for next fat ;AN004;
848 add sp,8 ;Clean up stack ;AN004;
850 ; mov [packet],ax ; reset to first FAT ;AN004;
858 add [packet
],dx ; point to start of next FAT ;AN004;
859 inc [FAT_2
] ; ;AN004;
860 ; $endloop LOOP ;Try next FAT ;AN004;
862 mov ax,(util
shl 8) + no_room
; set message# and class ;AN004;
871 BREAK <SYS
- Is_It_Empty
>
872 ;******************* START OF SPECIFICATIONS ***********************************
873 ;Routine name: Is_It_Empty
874 ;*******************************************************************************
876 ;Description: Is_It_Empty looks directly into the FAT to see if a specified
877 ; cluster is allocated.
879 ;Entry: Called by Free_Cluster
883 ; Unpack - unpack a FAT cluster number (CF set on error)
885 ;Input: CX = cluster to check
886 ; 12 sectors of FAT in BUF
888 ;Output: CF = 0 AL = 0 - cluster 2 found empty
889 ; AL =-1 - not found & no error
890 ; CF = 1 - critical error
892 ;Change History: Created 7/01/87 FG
894 ;******************* END OF SPECIFICATIONS *************************************
895 ;******************+ START OF PSEUDOCODE +**************************************
899 ; set up for call to Unpack
900 ; set cluster # to [cluster_number]
903 ; if cluster is not empty
907 ; if cluster belongs to IBMBIO
908 ; if next cluster is not contiguous
909 ; reset ownership flag
911 ; set cluster empty (ax = 0)
913 ; save cluster number
914 ; set cluster used (ax = -1)
917 ; set cluster empty (ax = 0)
925 ;******************- END OF PSEUDOCODE -**************************************
929 Is_It_Empty PROC
NEAR
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;
935 ; $if nz ; cluster is not empty ;AN004;
938 cmp al,bad_sector
; ;AN004;
945 cmp [bio_owns_it
],0 ; is it owned by IBMBIO ? ;AN004;
946 ; $if ne ; if it is ;AN004;
949 cmp ax,[current_cluster
] ; ;AN004;
952 dec [bio_owns_it
] ; its not the owner form here on ;AC011;
956 clc ; its IBMBIO's anyway ;AC011;
960 mov [next_cluster
],di ; ;AN004;
961 xor ax,ax ; reset fail flag ;AN004;
962 dec ax ; - its not empty ;AN014;
967 ; $else ; its empty ! ;AN005;
970 xor ax,ax ; its empty - and no error ;AN014;
980 BREAK <SYS
- Search_FAT
>
981 ;******************* START OF SPECIFICATIONS ***********************************
982 ;Routine name: Search_FAT
983 ;*******************************************************************************
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
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
999 ; [cluster_number] of specified cluster
1001 ;Output: CF = 0 - AX = 0 if cluster found
1002 ; = -1 if cluster not found
1003 ; CF = 1 if critical error
1005 ;Change History: Created 7/01/87 FG
1007 ;******************* END OF SPECIFICATIONS *************************************
1008 ;******************+ START OF PSEUDOCODE +**************************************
1012 ; set cluster # to [cluster_number]
1013 ; search till at end of FAT
1015 ; exitif cluster found
1016 ; save [last_cluster]
1019 ; advance to next cluster
1020 ; endloop if past last cluster in fat
1024 ; call Find_Empty_Cluster
1027 ; if empty cluster available and
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
1042 ; do until all FATS written
1043 ; call Direct_Access
1044 ; advace to next FAT (ignore errors)
1050 ; update DPB first cluster and total empty clusters
1057 ;******************- END OF PSEUDOCODE -**************************************
1061 Search_FAT PROC
NEAR
1063 mov si,[current_cluster
] ; set cluster # to [cluster_number] ;AN004;
1064 ; $search ; till at end of FAT ;AN004;
1066 call Unpack
; ;AN004;
1067 ; $leave c ; quit on an error ;AN004;
1069 cmp di,[current_cluster
] ; is it [current_cluster] ? ;AN004;
1070 ; $exitif e ; it is ;AN004;
1072 mov [last_cluster
],si ; save number for later ;AN004;
1074 clc ; clear error flag (found) ;AN004;
1078 inc si ; advance to next cluster ;AN004;
1081 cmp si,[MCLUS
] ; at the end ? ;AN004;
1082 ; $endloop e ; if past last cluster ;AN004;
1086 ; $endsrch ; ;AN004;
1088 ; $if nc ; if cluster found ;AN004;
1090 call Find_Empty_Cluster
; to move data to ;AN004;
1093 ; $if nc,and ; empty cluster available and ;AN004;
1095 call Xfer_Data
; to move data to new cluster ;AN004;
1096 ; $if nc,and ; no errors ;AN004;
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;
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;
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;
1115 call Direct_Access
; write it out - ignore errors ;AN004;
1116 mov ax,[FSIZE
] ; ;AN004;
1117 cmp [FAT_2
],0 ; ;AN004;
1120 add [packet
],ax ; ;AN004;
1121 inc [FAT_2
] ; packet points to FAT #2 ;AC006;
1125 sub [packet
],ax ; ;AN004;
1126 mov [FAT_2
],0 ; reset - packet points to FAT #1 ;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;
1136 lds bx,[THIS_DPB
] ; ;AN004;
1138 ASSUME
ds:nothing
,es:DATA
1140 mov [bx.dpb_next_free
],2 ; ;AN004;
1144 xor ax,ax ; signal success (ax = 0 , cf = 0) ;AN004;
1146 ASSUME
DS:data, es:nothing
1155 clc ; not a critical error - keep trying ;AN004;
1159 stc ; major problem - critical error ;AN004;
1169 BREAK <SYS
- Find_Empty_Cluster
>
1170 ;******************* START OF SPECIFICATIONS ***********************************
1171 ;Routine name: Find_Empty_Cluster
1172 ;*******************************************************************************
1174 ;Description: Find_Empty_Cluster finds the first available empty cluster
1178 ; Unpack - find next cluster number
1182 ;Output: CF = 0 - empty cluster found (# in [empty_cluster])
1183 ; CF = 1 - no empty clusters (ax = message)
1185 ;Change History: Created 7/01/87 FG
1187 ;******************* END OF SPECIFICATIONS *************************************
1188 ;******************+ START OF PSEUDOCODE +**************************************
1190 ; START Find_Empty_Cluster
1192 ; search till at end of FAT
1194 ; exitif cluster is empty (ZF)
1195 ; save empty cluster number
1198 ; advance to next cluster
1199 ; endloop if past last cluster
1200 ; load ax message # - no room for sys files
1206 ; END Find_Empty_Cluster
1208 ;******************- END OF PSEUDOCODE -**************************************
1210 public Find_Empty_Cluster
1212 Find_Empty_Cluster PROC
NEAR
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;
1219 call Unpack
; to convert # to value ;AN004;
1220 ; $exitif z ; cluster is empty ;AN004;
1222 mov [empty_cluster
],si ; save it for later ;AN004;
1223 clc ; clear error flag ;AN004;
1227 inc si ; advance to next cluster ;AN004;
1228 cmp si,[MCLUS
] ; past the end ? ;AN004;
1229 ; $endloop e ; if past last cluster ;AN004;
1231 stc ; set error flag ;AN004;
1232 mov ax,(util
shl 8) + no_room
; error message - no room to sys ;AN014;
1233 ; $endsrch ; ;AN004;
1238 Find_Empty_Cluster ENDP
1240 BREAK <SYS
- Xfer_Data
>
1241 ;******************* START OF SPECIFICATIONS ***********************************
1242 ;Routine name: Xfer_Data
1243 ;*******************************************************************************
1245 ;Description: Xfer_Data moves the data from [cluster_number] into the cluster
1246 ; number passed in ax.
1250 ; Direct_Access - do disk i/o
1252 ;Input: [current_cluster]
1255 ;Output: CF = 0 - data transfered
1256 ; CF = 1 - error - message in AX
1258 ;Change History: Created 7/01/87 FG
1260 ;******************* END OF SPECIFICATIONS *************************************
1261 ;******************+ START OF PSEUDOCODE +**************************************
1265 ; save active FAT starting sector
1266 ; set source to first sector of [current_cluster]
1267 ; set count to # of sectors per cluster
1269 ; call Direct_Access to read data
1271 ; set source to first sector of [empty_cluster]
1273 ; call Direct_Access to write data
1275 ; restore Fat starting sector
1276 ; set count to FAT_sectors
1278 ; call Direct_Access to restore the FAT copy
1286 ;******************- END OF PSEUDOCODE -**************************************
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;
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;
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;
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;
1319 call Direct_Access
; to write data ;AN004;
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;
1332 BREAK <SYS
- cluster_2_sector
>
1333 ;******************* START OF SPECIFICATIONS ***********************************
1334 ;Routine name: cluster_2_sector
1335 ;*******************************************************************************
1337 ;Description: cluster_2_sector
1344 ;Input: AX - cluster number
1346 ;Output: AX - low word of sector
1347 ; DX - high word of sector
1348 ; CX - sectors per cluster
1350 ;Change History: Created 7/01/87 FG
1352 ;******************* END OF SPECIFICATIONS *************************************
1353 ;******************+ START OF PSEUDOCODE +**************************************
1355 ; START cluster_2_sector
1359 ; END cluster_2_sector
1361 ;******************- END OF PSEUDOCODE -**************************************
1363 public cluster_2_sector
1365 cluster_2_sector PROC
NEAR
1367 dec ax ; of [current_cluster] ;AN004;
1369 mov cx,[CSIZE
] ; ;AN004;
1371 add ax,[l_sector_offset
] ; ;AN004;
1375 cluster_2_sector ENDP
1377 BREAK <SYS
- Search_DIR
>
1378 ;******************* START OF SPECIFICATIONS ***********************************
1379 ;Routine name: Search_DIR
1380 ;*******************************************************************************
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
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.
1391 ; FRAME ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
1392 ; ³ present_cluster # ³sector_offset ³ entry_number ³
1393 ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
1396 ; There is space in DIR_BUF for 32 frames (current DOS maximum
1397 ; level of nesting).
1401 ; Search_Loop - scan the directory
1403 ;Input: [current_cluster] - # of cluster to be freed
1405 ;Output: CF = 0 cluster now available
1406 ; CF = 1 error - ax = message #
1409 ;Change History: Created 7/01/87 FG
1411 ;******************* END OF SPECIFICATIONS *************************************
1412 ;******************+ START OF PSEUDOCODE +**************************************
1416 ; set up for first_dir_sector of root DIR
1418 ; call Direct_Access to read first root sector
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)
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)
1433 ; set error flag (CF)
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]
1443 ; set error flag (CF)
1445 ; load error message - no room to sys
1447 ; set error flag (CF) (ax = message)
1449 ; leave if error (ax > 0)
1457 ;******************- END OF PSEUDOCODE -**************************************
1461 Search_DIR PROC
NEAR
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;
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;
1483 call Search_Loop
; ;AN004;
1484 ; $leave nc,long ; cluster found and moved ;AN004;
1488 cmp ax,0ffffh ; ;AN004;
1489 ; $if e ; SubDir ;AN004;
1492 ; Search DIR returned with BX pointing
1493 ; to the current entry - now update
1494 ; current_cluster to this SubDIRs first
1497 mov ax,[bx.dir_first
] ; get starting cluster for where we ;AN007;
1499 mov bx,[present_cluster
] ; get [present_cluster] for frame ;AN004;
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;
1517 mov [FRAME_ptr
],bx ; ;AN004;
1518 clc ; no error ;AN004;
1522 stc ; set error flag (CF) ;AN004;
1525 ; $else long ; ;AN004;
1529 ; $if e,and,long ; end of DIR (CF + 00) and ;AN004;
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;
1540 ; $if be ; as long as there are still FRAMEs ;AC007;
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;
1550 ; Now set up at exactly same point
1551 ; as when SubDIR was entered -
1552 ; advance to next entry
1555 cmp al,[entries_per_sector
] ; ;AN004;
1558 inc [entry_number
] ; ;AN004;
1559 clc ; no error ;AN004;
1560 ; $else ; we've left the sector ;AN004;
1565 mov [entry_number
], al ; shall we start at, say, ENTRY ZERO? Hmmmmm?
1567 mov ax,[present_cluster
] ; ;AN004;
1568 cmp ax,0 ; in the root ? ;AN004;
1569 ; $if ne ; no ;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;
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;
1586 mov [present_cluster
],di ; save it ;AN004;
1588 ; $else ; we are at the end of a Sub DIR chain ;AN004;
1592 ; the following is a best attempt fix
1593 ; to a bad design problem ...... (how
1594 ; to get back a level.....???
1596 ; SEPT 21 - best solution is to check BEFORE putting the entry in the frame
1597 ; (not when taking it off !!! )
1599 jmp next_level_down
; ;AN004;
1603 ; $else ; yes - in the root ;AN004;
1606 mov ax,[sector_offset
] ; ;AC015;
1608 cmp ax,[l_sector_offset
] ; ;AC015;
1611 inc [sector_offset
] ; ;AN004;
1613 clc ; no error, continue with loop
1615 ; $else ; end of the line ;AN004;
1618 stc ; we failed to find it ;AN004;
1628 stc ; set error flag (CF) ;AN004;
1633 ; $if c ; error ;AN004;
1635 mov ax,(util
shl 8) + no_room
; error message - no room to sys ;AN004;
1638 ; $leave c ; if error ;AN004;
1640 ; $enddo long ; ;AN004;
1650 BREAK <SYS
- Search_Loop
>
1651 ;******************* START OF SPECIFICATIONS ***********************************
1652 ;Routine name: Search_Loop
1653 ;*******************************************************************************
1655 ;Description: Search_Loop scans through all entries of all sectors of all
1656 ; clusters of a given Directory for a specified cluster
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
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
1674 ;Change History: Created 7/01/87 FG
1676 ;******************* END OF SPECIFICATIONS *************************************
1677 ;******************+ START OF PSEUDOCODE +**************************************
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]
1686 ; call Find_Empty_Cluster
1691 ; update dir_first_clust
1693 ; call Direct_Access to write out the directory
1696 ; leave if entry is a subdirectory (ah = ffh)
1697 ; advace to next entry
1699 ; endloop if past end of sector
1700 ; set fail flag (CF)
1702 ; exit if [current_cluster] found (NC)
1704 ; leave if subdirectory found (CF + FF)
1705 ; if sectors left to read
1707 ; call Direct_Access to read sector
1709 ; set error flag (CF)
1710 ; zero ax (end of sectors)
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)
1723 ; convert cluster # to logical sector #
1724 ; update [current_sector]
1732 ;******************- END OF PSEUDOCODE -**************************************
1736 Search_Loop PROC
NEAR
1738 mov ax,[present_cluster
] ; initailize for search ;AN004;
1742 call cluster_2_sector
; convert it to a sector ;AN004;
1743 add ax,[sector_offset
] ; ;AC015;
1752 mov ax,[sector_offset
] ;[sector_offset] = current root sector ;AC015;
1756 mov [packet
],ax ; ;AN004;
1757 mov [packet
+2],dx ; ;AN004;
1759 call Direct_Access
; to read the DIR ;AN004;
1760 mov al,SIZE dir_entry
; ;AN004;
1761 mov cl,[entry_number
] ; ;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;
1767 ; - all clusters checked
1768 ; $search ; till at end of sectors ;AN004;
1770 ; - in given cluster
1771 ; $search ; till at end of sector ;AN004;
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;
1778 mov [bx.dir_first
],ax ; zap the starting cluster ;AN019;
1779 mov [bx.dir_attr
],al ; zap the attribute ;AN019;
1782 mov ax,[bx.dir_first
] ; ;AN004;
1783 cmp ax,[current_cluster
] ; ;AN004;
1784 ; $exitif e,and,long ; starting cluster = [current_cluster] ;AN004;
1788 cmp BYTE PTR [bx],deleted
; make sure the entry is valid !!! ;AN007;
1789 ; $exitif ne,and,long ; and entry is not deleted ;AN007;
1793 cmp BYTE PTR [bx],dot
; ;AN007;
1794 ; $exitif ne,long ; and entry is not a . or .. name ;AN007;
1798 test [bx.dir_attr
],attr_directory
; is it a subdir ? ;AN007;
1799 ; $if nz ;if entry is a subdirectory ;AN007;
1801 inc [DIR_cluster
] ; signal special processing ;AN007;
1802 ; Xfere_Data will use this later -
1804 ; 1 = do Sub DIR processing and
1805 ; update [DIR_cluster] to the
1806 ; same value as [empty_cluster]
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;
1823 mov si,[empty_cluster
] ; ;AN004;
1824 mov dx,[next_cluster
] ; ;AN004;
1826 ; $if nc,and ; no errors so far ;AN004;
1828 mov si,[current_cluster
] ; ;AN004;
1829 xor dx,dx ; make it empty ;AN004;
1831 ; $if nc ; no errors so far ;AN004;
1833 cmp [bigfat
],0 ; ;AN004;
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;
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;
1849 call Direct_Access
; write it out - ignore errors ;AN004;
1854 ; $if nc,and ; no error and ;AN004;
1856 call Xfer_Data
; ;AN004;
1857 ; $if nc ; no error ;AN004;
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;
1870 call Direct_Access
; to write out the directory ;AN004;
1871 ; $if nc,and ; ;AN004;
1873 cmp [DIR_cluster
],0 ; is a DIR being processed ? ;AN007;
1876 call Sub_DIR_Loop
; update any children ;AN007;
1879 ; $if nc ; if no errors ;AN007;
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;
1890 mov cl,[num_of_FATS
] ; ;AN004;
1892 call Load_FAT
; restore FAT ;AN004;
1894 push es ; update DPB first cluster ;AN004;
1897 lds bx,[THIS_DPB
] ; ;AN004;
1899 ASSUME
ds:nothing
,es:DATA
1901 mov [bx.dpb_next_free
],2 ; ;AN004;
1906 ASSUME
DS:data, es:nothing
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;
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;
1923 cmp byte ptr [bx],dot
; but not a DOT ;AN007;
1924 ; $leave ne ; ;AN007;
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;
1936 stc ; set fail flag (CF) ;AN004;
1937 ; $endsrch ; ;AN004;
1939 ; $exitif nc ;[current_cluster] found (NC) ;AN004;
1945 ; we have CF = 1 and could have:
1949 ; so - leave if anything other than
1950 ; AX = 0 (out of stuff)
1952 ; $leave c,and ; if not out of stuff ;AN004;
1955 stc ; restore carry flag! ;AN007;
1956 ; $leave nz ; ------ leave ! ;AN009;
1959 mov ax,[sector_offset
] ; ;AC015;
1961 cmp [present_cluster
],0 ; are we in the root? ;AN007;
1962 ; $if e ; if so - ;AN004;
1964 cmp ax,[l_sector_offset
] ; use root sectors ;AC013;
1965 ; $else ; else - ;AN004;
1968 cmp ax,[CSIZE
] ; use sectors per cluster ;AN004;
1971 ; $if b ; sectors left to read ;AN004;
1973 add [packet
],1 ; advance to the next sector ;AN004;
1976 inc [packet
+2] ; adjust high word if needed ;AN004;
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;
1987 xor ax,ax ; zero ax (end of sectors) ;AN004;
1988 stc ; set error flag (CF) ;AN004;
1991 ; $endloop c,long ; if error ;AN004;
1996 ; $endsrch ; ;AN004;
1998 ; $leave nc ; if [current_cluster] found (NC) ;AN004;
2000 ; $leave c,and ;if SubDir found (CF + FF) ;AN004;
2003 stc ; set carry ;AN007;
2004 ; $leave nz ; if Error (CF + messageor FFFFh) ;AN004;
2008 ;--------------------------------------
2009 ; CF = 1 and AX = 0 means - no critical
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;
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;
2029 cmp al,end_cluster
; ;AN007;
2032 ; $exitif z ; no more clusters ;AN004;
2034 xor ax,ax ; zero ax (end of clusters) ;AN004;
2035 stc ; set error flag (CF) ;AN004;
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;
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;
2054 ; $endsrch ; ;AN004;
2061 BREAK <SYS
- Sub_DIR_Loop
>
2063 ;******************* START OF SPECIFICATIONS ***********************************
2064 ;Routine name: Sub_DIR_Loop
2065 ;*******************************************************************************
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
2073 ; Unpack - to find a FAT entry for a Cluster #
2074 ; Direct_Access - absolute disk i/o
2076 ;Input: [empty_cluster] - new parent Sub DIR cluster #
2077 ; [DIR_cluster] - current cluster of DIR being looped
2079 ;Output: CF = 0 at end of directory
2080 ; CF = 1 a read/write error occured
2082 ;Change History: Created 10/07/87 FG
2084 ;******************* END OF SPECIFICATIONS *************************************
2085 ;******************+ START OF PSEUDOCODE +**************************************
2087 ; START Sub_DIR _Loop
2090 ; call cluster_2_sector
2093 ; reset entry pointer
2094 ; reset sector count
2095 ; call Direct_Access
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
2107 ; call cluster_2_sector
2109 ; call Direct_Access
2111 ; update pointer to parent
2113 ; call Direct_Access
2115 ; recover current sector
2116 ; recover current entry
2118 ; call Direct_Access
2122 ; advance to next entry
2123 ; endloop if past end of sector
2127 ; advance to next sector (packet)
2128 ; incriment sector count
2129 ; exitif past end of cluster
2132 ; reset entry pointer
2134 ; call Direct_Access
2139 ; call UNPACK to find next Sub DIR cluster
2140 ; exitif at end of chain
2143 ; update DIR_cluster
2144 ; call cluster_2_sector
2147 ; call Direct_Access
2149 ; reset entry pointer
2150 ; reset sector count
2154 ; reset Sub_DIR_cluster to 0
2160 ;******************- END OF PSEUDOCODE -**************************************
2164 Sub_DIR_Loop PROC
NEAR
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;
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;
2180 ; - all clusters checked ;AN007;
2181 ; $search ; till at end of sectors ;AN007;
2183 ; - in given cluster ;AN007;
2184 ; $search ; till at end of sector ;AN007;
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;
2191 cmp BYTE PTR [bx],deleted
; deleted entry (E5)? ;AN007;
2192 ; $if ne,and ; if entry is not deleted and ;AN007;
2194 test [bx.dir_attr
],attr_directory
; is it a subdir ? ;AN007;
2195 ; $if nz,and ; if this entry is a subdir and ;AN007;
2197 cmp BYTE PTR [bx],dot
; dot entry (2E)? ;AN007;
2198 ; $if ne,and ; this is a true entry and ;AN007;
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;
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;
2217 call Direct_Access
; to write it back ;AN007;
2218 ; $if nc,and ; if no errors and ;AN007;
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;
2226 call Direct_Access
; to continue where we left off ;AN007;
2229 ; $exitif c ; quit if error (CF) ;AN007;
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;
2240 clc ; clear error flag ;AN007;
2241 ; $endsrch ; ;AN007;
2243 ; $leave c ; if error - quit ;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;
2251 clc ; clear error flag ;AN007;
2252 mov [sector_count
],1 ; reset sector count ;AN007;
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;
2266 ; $endsrch ; ;AN007;
2268 ; $leave c ; if error - quit ;AN007;
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;
2281 cmp al,end_cluster
; ;AN007;
2282 ; $exitif e ; at end of chain ;AN007;
2284 clc ; clear error flag ;AN007;
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;
2296 lea bx,DIR_SECTOR
; reset entry pointer ;AN007;
2297 mov [sector_count
],1 ; reset sector count ;AN007;
2298 ; $endloop long ; ;AN007;
2301 ; $endsrch ; ;AN007;
2305 mov [DIR_cluster
],0 ; reset Sub_DIR_cluster to 0 ;AN007;
2311 BREAK <SYS
- Unpack
>
2312 ;******************* START OF SPECIFICATIONS ***********************************
2313 ;Routine name: Unpack
2314 ;*******************************************************************************
2316 ;Description: Read an entry in the FAT
2320 ; Check_FAT - to make sure right part of FAT is loaded (16 bit only)
2322 ;Input: Cluster number in SI
2324 ;Output: Return contents in DI
2326 ; ZF set if cluster is free
2328 ;Change History: Created 7/01/87 FG
2330 ;******************* END OF SPECIFICATIONS *************************************
2331 ;******************+ START OF PSEUDOCODE +**************************************
2343 ; if not word alligned
2346 ; mask off unused portion (set ZF if empty)
2353 ;******************- END OF PSEUDOCODE -**************************************
2359 lea bx,BUF
; ;AN004;
2361 cmp [BIGFAT
],0 ; ;AN004;
2362 ; $if nz ; if 16 bit FAT ;AN004;
2365 call Check_FAT
; make sure right part of FAT loaded ;AN004;
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;
2376 ; $else ; is 12 bit fat ;AN004;
2380 add di,si ; Mult by 1.5 ;AN004;
2381 mov di,WORD PTR [di+bx] ; ;AN004;
2383 ; $if nz ; not allign on cluster ;AN004;
2391 and di,0FFFh ; ;AN004;
2401 ;******************* START OF SPECIFICATIONS ***********************************
2403 ;*******************************************************************************
2405 ;Description: Change an entry in the FAT
2409 ; Check_FAT - to make sure right part of FAT is loaded (16 bit only)
2411 ;Input: si - cluster number to be packed
2412 ; dx - data to be placed in cluster (si)
2414 ;Output: bx,dx destroyed
2416 ;Change History: Created 7/01/87 FG
2418 ;******************* END OF SPECIFICATIONS *************************************
2419 ;******************+ START OF PSEUDOCODE +**************************************
2425 ; convert cluster # to offset
2429 ; convert cluster # to offset
2431 ; recover current entry word
2432 ; if not alligned on word boundary
2434 ; mask off value to be replaced (byte)
2436 ; mask off value to be replaced (word)
2438 ; combine new value and ballace
2445 ;******************- END OF PSEUDOCODE -**************************************
2451 lea bx,BUF
; ;AN004;
2454 cmp [BIGFAT
],0 ; ;AN004;
2455 ; $if nz ; 16 bit FAT ;AN004;
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;
2470 mov di,[si] ; ;AN004;
2471 ; $if c ; no alligned ;AN004;
2477 and di,0Fh ; ;AN004;
2481 and di,0F000h ; ;AN004;
2485 mov [si],di ; ;AN004;
2494 BREAK <SYS
- Check_FAT
>
2495 ;******************* START OF SPECIFICATIONS ***********************************
2496 ;Routine name: Check_FAT
2497 ;*******************************************************************************
2499 ;Description: Check that the protion of the FAT that is referenced in SI
2500 ; is presently in memory.
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
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.
2516 ;Output: appropriate block of FAT in BUF
2517 ; si ajusted to match
2518 ; NB: BX, DX preserved (for UNPACK)
2520 ;Change History: Created 7/01/87 FG
2522 ;******************* END OF SPECIFICATIONS *************************************
2523 ;******************+ START OF PSEUDOCODE +**************************************
2532 ;******************- END OF PSEUDOCODE -**************************************
2539 cmp si,[cluster_low
] ; ;AN004;
2540 ; $if ae,and ; ;AN004;
2542 cmp si,[cluster_high
] ; ;AN004;
2545 sub si,[cluster_low
] ; ;AN004;
2546 ; $else ; the cluster is outside the range
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
2556 cmp [FAT_changed
],0 ; ;AN004;
2561 call Direct_Access
; write it out - ignore errors ;AN004;
2562 mov ax,[FSIZE
] ; ;AN004;
2563 cmp [FAT_2
],0 ; ;AN004;
2566 add [packet
],ax ; ;AN004;
2570 sub [packet
],ax ; ;AN004;
2571 mov [FAT_2
],0 ; packet points to FAT #2 ;AN004;
2576 call Direct_Access
; write it out - ignore errors ;AN004;
2577 mov [FAT_changed
],0 ; FAT now cleared ;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;
2591 call Direct_Access
; ;AN004;
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;
2601 pop ax ; recover starting sector ;AN006;
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;