;This file contains alternate versions of functions used in DOSLFN.
;Whilst not currently being used, they could still have a future.
;==============
;FASTOPEN CACHE
;==============
;A version of the fastopen cache using a double-linked list.
;TDirCache should start with "next" and "prev" words.
; mov si,ofs (name|path)_cache
;head: mov bx,[cachesi.next]
;tail: mov bx,[cachesi.prev]
proc cache_unlink
;FU: Remove a cache entry from the queue.
;PE: SI=cache
; BX=entry
;PA: SI=entry
; DI=cache
push si
mov si,[cachebx.next]
mov di,[cachebx.prev]
mov [cachesi.prev],di
mov [cachedi.next],si
pop di
mov si,bx
ret
endp
proc to_front
;FU: Move a cache entry to the front of the queue.
;PE: SI=cache
; BX=entry
;VR: SI,DI
call cache_unlink
xchg [cachedi.next],si
mov [cachebx.next],si
mov di,[cachesi.prev]
mov [cachebx.prev],di
mov [cachesi.prev],bx
ret
endp
proc to_back
;FU: Move a cache entry to the back of the queue.
;PE: SI=cache
; BX=entry
;VR: SI,DI
call cache_unlink
xchg [cachedi.prev],si
mov [cachebx.prev],si
mov di,[cachesi.next]
mov [cachebx.next],di
mov [cachesi.next],bx
ret
endp
name_cache dw ?,? ;head (next) and tail (prev) pointers
path_cache dw ?,?
cache_dirs TDirCache CACHE_ENTRIES dup (<>)
cache_names TDirCache CACHE_ENTRIES dup (<>)
proc cache_link
;Make all the cache entries point to each other.
;PE: SI=cache
; BX=first entry
push si bx
mov [cachesi.next],bx
mov cx,CACHE_ENTRIES
@@link: lea si,[bx+SIZE TDirCache]
lea di,[bx-SIZE TDirCache]
mov [cachebx.next],si
mov [cachebx.prev],di
mov bx,si
loop @@link
add di,SIZE TDirCache
pop bx si
mov [cachedi.next],si
mov [cachebx.prev],si
mov [cachesi.prev],di
ret
endp
mov si,ofs path_cache
mov bx,ofs cache_dirs
call cache_link
mov si,ofs name_cache
mov bx,ofs cache_names
call cache_link
;=================
;Calc_Next_Cluster
;=================
; Cache the next cluster to save re-reading the sector.
; However, don't cache the last cluster, since it's not known when it can grow.
; Not complete, as it has to be reset on drive change and directory removal.
; Whilst it did save a bit, overall it's not really worth it (not with a
; disk cache, anyway).
; Not really a good implementation, since it could overwrite a recently used
; cluster. It might be feasible to modify the fastopen cache to allow this,
; as well. (Place the size of each entry at the head of the cache.)
CLUST_NUM equ 16
clust_buf dd CLUST_NUM*2 dup (0)
clust_ptr dw clust_buf
proc Calc_Next_Cluster pascal
;Berechnung für Next_Sektor, liest die FAT ein
;PE: EAX=(vorhergehender) Sektor (gerechnet ab UsrSec)
; CL=Shift
;PA: EAX=nächster Sektor (erster Sektor des nächsten Clusters, ab UsrSec)
; CY=1: Ende der Cluster-Kette, EAX=Cluster-Nr.
;VR: alle, [Sektor]-Inhalt zerstört
shr eax,cl
add eax,2 ;EAX ist nun CLUSTER
mov di,ofs clust_buf
push cx
mov cx,CLUST_NUM
repne scasd
pop cx
jne @@0
mov edx,[di-4+CLUST_NUM*4]
cmp eax,edx
je @@1
xchg eax,edx
jmp @@ce
@@0: mov di,[clust_ptr]
cmp di,ofs clust_buf+CLUST_NUM*4
jne @@00
mov di,ofs clust_buf
@@00: mov [di],eax
mov [di+CLUST_NUM*4],eax
add di,4
mov [clust_ptr],di
@@1: push di
call Cluster2FAT
pop di
jc @@e
;...
@@3b: cmc
jc @@e ;Ende der Clusterkette
mov [di-4+CLUST_NUM*4],eax
@@ce: sub eax,2
jc @@e ;momentaner Cluster ist frei (falsch!)
shl eax,cl
_nde_ret:
@@e: ret
endp
;==========
;LocalAlloc
;==========
;Search for a free block that is the (almost) exact fit. If there are none,
;use first fit.
proc LocalAlloc pascal
;PE: AX=geforderte Speichermenge in Bytes
;PA: CY=1: kein Speicher mehr frei!
; CY=0 und DI=Zeiger auf Speicherblock (fertig für STOSx)
;VR: CX,DX,DI,AX(=tatsächliche Alloc-Größe inkl. Größen-WORD)
uses bx,si
inc ax ;an additional two bytes are required
inc ax ; to store the size
mov si,[LocalHeap]
xor cx,cx
@@l2: mov di,si
mov si,[si] ;si=erster (oder weiterer) Freispeicher
or si,si ;Ende erreicht?
jz @@r
mov dx,[si+2]
sub dx,ax ;Block hat genug Platz?
jc @@l2 ;nein, nächsten Freispeicher suchen
je @@ganz
cmp dx,4
jb @@fit
inc cx
loop @@l2
mov bx,di ;Kandidat gefunden: BX=Vorheriger Freispeicher
mov cx,si ;Kandidat gefunden: CX=Jetziger Freispeicher
jmp @@l2
@@r:
jcxz @@nomem
mov si,cx
mov cx,[si+2]
sub cx,ax
mov di,si
add di,ax ;auf neue Position
mov [bx],di
mov [di+2],cx ;neue (kleinere) Größe
db 0b9h
@@fit: add ax,dx ;increase allocation to fit free block
@@ganz: movsw ;Next-Pointer
lea di,[si-2]
@@1: stosw ;Größe allozierter Block eintragen
@@e: ret
@@nomem:mov [LastError],4 ;"not enough memory"
stc
jmp @@e
endp
Detected encoding: OEM (CP437) | 1
|
|