mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-26 09:54:20 +00:00
666 lines
27 KiB
Plaintext
666 lines
27 KiB
Plaintext
;***************** BDOS file system part 2 *****************
|
||
;
|
||
scndm:
|
||
;scan the disk map addressed by dptr for non-zero
|
||
;entries, the allocation vector entry corresponding
|
||
;to a non-zero entry is set to the value of CL (0,1)
|
||
;BX addresses the beginning of the directory entry
|
||
;
|
||
CALL getdptra ;BX = buffa + dptr
|
||
ADD BX,dskmap ;BX = diskmap address
|
||
PUSH CX ;save the 0/1 bit to set
|
||
MOV CL,fcblen-dskmap+1 ;size of single byte diskmap+1
|
||
scndm0:
|
||
;loop for each diskmap entry
|
||
POP DX ;recall bit parity
|
||
DEC CL
|
||
JNZ L_41
|
||
RET
|
||
L_41: ;all done scanning?
|
||
;no, get next entry for scan
|
||
PUSH DX ;replace bit parity
|
||
cmp single,0
|
||
JZ scndm1
|
||
;single byte scan operation
|
||
PUSH CX ;save counter
|
||
PUSH BX ;save map address
|
||
MOV CL,[bx]
|
||
MOV CH,0 ;CX=block#
|
||
jmps scndm2
|
||
scndm1:
|
||
;double byte scan operation
|
||
DEC CL ;count for double byte
|
||
PUSH CX ;save counter
|
||
MOV cx,[bx] ;CX=block
|
||
INC BX
|
||
PUSH BX ;save map address
|
||
scndm2:
|
||
;arrive here with CX=block#,
|
||
;DL= 0/1
|
||
OR cx,cx ;skip if = 0000
|
||
JZ scan3
|
||
MOV BX,maxall ;check invalid index
|
||
cmp bx,cx
|
||
JNAE L_42
|
||
CALL setallocbit
|
||
L_42: ;
|
||
;bit set to 0/1
|
||
scan3: ;
|
||
POP BX
|
||
INC BX ;to next bit position
|
||
POP CX ;recall counter
|
||
jmps scndm0 ;for another item
|
||
;
|
||
initialize:
|
||
;initialize the current disk
|
||
;lret = false ;set to true if $ file exists
|
||
;compute the length of the allocation vector - 2
|
||
MOV BX,maxall
|
||
MOV CL,3 ;perform maxall/8
|
||
shr bx,cl
|
||
INC BX
|
||
mov cx,bx
|
||
MOV BX,alloca ;base of allocation vector
|
||
;fill the allocation vector
|
||
;with zeros
|
||
init0:
|
||
MOV b[bx],0
|
||
INC BX ;alloc(i)=0
|
||
loop init0
|
||
;set the reserved space for
|
||
;the directory
|
||
MOV DX,dirblk
|
||
MOV BX,alloca ;BX=.alloc()
|
||
MOV [bx],dx ;sets reserved directory blks
|
||
;allocation vector initialized
|
||
CALL home ;home disk
|
||
;cdrmax = 3 (scans at least
|
||
;one directory record)
|
||
MOV BX,cdrmaxa
|
||
mov w[bx],3
|
||
;cdrmax = 0000
|
||
CALL setenddir ;dcnt = enddir
|
||
;read directory entries and
|
||
;check for allocated storage
|
||
init2:
|
||
MOV CL,true
|
||
CALL rddir
|
||
CALL endofdir
|
||
jz ret8b ;rz
|
||
;not end of directory,
|
||
;valid entry ?
|
||
CALL getdptra ;BX = buffa + dptr
|
||
cmp b[bx],empty
|
||
JZ init2 ;go get another item
|
||
;not empty,user code the same?
|
||
MOV AL,usrcode
|
||
CMP AL,[bx]
|
||
JNZ pdollar
|
||
;same user code,
|
||
;check for '$' submit
|
||
INC BX
|
||
MOV AL,[bx] ;first character
|
||
SUB AL,'$' ;dollar file?
|
||
JNZ pdollar
|
||
;$ file found, mark in lret
|
||
DEC AL
|
||
MOV lret,al ;lret = 255
|
||
pdollar:
|
||
;now scan the disk map for
|
||
;allocated blocks
|
||
MOV CL,1 ;set to allocated
|
||
CALL scndm
|
||
CALL setcdr ;set cdrmax to dcnt
|
||
jmps init2 ;for another entry
|
||
;
|
||
cpydirloc:
|
||
;copy directory location to lret following
|
||
;delete, rename, ... ops
|
||
MOV AL,dirloc
|
||
JMP staret
|
||
; ret
|
||
;
|
||
compext:
|
||
;compare extent# in AL with that in CL, return nonzero
|
||
;if they do not match
|
||
PUSH CX ;save CL's original value
|
||
MOV ch,extmsk
|
||
NOT ch
|
||
;CH has negated form of
|
||
;extent mask
|
||
and cl,ch ;low bits removed from CL
|
||
AND AL,CH ;low bits removed from AL
|
||
SUB AL,CL
|
||
AND AL,maxext ;set flags
|
||
POP CX ;restore original values
|
||
ret8b: RET
|
||
;
|
||
srch:
|
||
;search for directory element
|
||
;of lenght
|
||
MOV dirloc,0ffh ;changed if actually found
|
||
MOV srchl,cl ;searchl = CL
|
||
MOV BX,info
|
||
MOV srcha,BX ;searcha = info
|
||
CALL setenddir ;dcnt = enddir
|
||
CALL home ;to start at the beginning
|
||
;(drop through to searchn) ;
|
||
;
|
||
srchn:
|
||
;search for the next directory element, assuming
|
||
;a previous call on search which sets searcha and searchhl
|
||
MOV CL,false
|
||
CALL rddir ;read next dir element
|
||
CALL endofdir
|
||
jz srchfin
|
||
;skip to end if so
|
||
;not end of directory,
|
||
;scan for match
|
||
MOV dx,srcha ;DX=beginning of user fcb
|
||
MOV SI,DX
|
||
LODS al ;first character
|
||
CMP AL,empty ;keep scanning if empty
|
||
JZ srchnext
|
||
;not empty, may be end of
|
||
;logical directory
|
||
PUSH DX ;save search address
|
||
CALL compcdr ;past logical end?
|
||
POP DX ;recall address
|
||
jnb srchfin
|
||
;artificial stop
|
||
srchnext:
|
||
CALL getdptra ;BX = buffa+dptr
|
||
MOV AL,srchl
|
||
MOV CL,AL ;length of search to CL
|
||
MOV CH,0 ;CH counts up, CL counts down
|
||
srchloop:
|
||
or cl,cl
|
||
JZ endsearch
|
||
MOV SI,DX
|
||
LODS al
|
||
CMP AL,'?'
|
||
JZ srchok ;? matches all
|
||
;scan next character if not
|
||
;ubytes
|
||
CMP ch,ubytes
|
||
JZ srchok
|
||
;not the ubytes field,
|
||
;extent field
|
||
CMP ch,extnum ;may be extent field
|
||
MOV SI,DX
|
||
LODS al ;fcb character
|
||
JZ srchext ;skip to search extent
|
||
SUB AL,[bx]
|
||
AND AL,7fh ;mask-out flags/extent modulus
|
||
jnz srchn
|
||
jmps srchok ;matched character
|
||
srchext:
|
||
;A has fcb character
|
||
;attempt an extent # match
|
||
PUSH CX ;save counters
|
||
MOV CL,[bx] ;directory character to c
|
||
CALL compext ;compare user/dir char
|
||
POP CX ;recall counters
|
||
jnz srchn ;skip if no match
|
||
srchok:
|
||
;current character matches
|
||
INC DX
|
||
INC BX
|
||
INC CH
|
||
DEC CL
|
||
jmps srchloop
|
||
endsearch:
|
||
;entire name matches, return dir position
|
||
MOV AL,ldcnt
|
||
AND AL,dskmsk
|
||
MOV lret,al
|
||
;lret = low(dcnt) and 11b
|
||
LEA BX,dirloc
|
||
MOV AL,[bx]
|
||
RCL AL,1
|
||
jae ret9 ;rnc
|
||
;yes, change it to 0 to
|
||
;mark as found
|
||
XOR AL,AL
|
||
MOV [bx],al ;dirloc=0
|
||
ret9: RET
|
||
srchfin:
|
||
;end of directory, or empty name
|
||
CALL setenddir ;may be artifical end
|
||
MOV AL,255
|
||
JMP staret
|
||
;
|
||
;
|
||
delet:
|
||
;delete the currently addressed file
|
||
CALL checkwrite ;write protected?
|
||
MOV CL,extnum
|
||
CALL srch ;search through file type
|
||
delet0:
|
||
;loop while directory matches
|
||
CALL endofdir
|
||
jz ret9
|
||
;set each non zero disk map
|
||
;entry to 0
|
||
;in the allocation vector
|
||
;may be r/o file
|
||
CALL ckrodir ;ro disk error if found
|
||
CALL getdptra ;BX=.buff(dptr)
|
||
MOV b[bx],empty
|
||
MOV CL,0
|
||
CALL scndm ;alloc elts set to 0
|
||
CALL wrdir ;write the directory
|
||
CALL srchn ;to next element
|
||
jmps delet0 ;for another record
|
||
;
|
||
getblock:
|
||
;given allocation vector position CX, find the zero bit
|
||
;closest to this position by searching left and right.
|
||
;if found, set the bit to 1 and return the bit position
|
||
;in BX. if not found (i.e., we pass 0 on the left, or
|
||
;maxall on the right), return 0000 in BX
|
||
;
|
||
MOV dx,cx ;copy start pos. to DX
|
||
lefttst:
|
||
or cx,cx
|
||
JZ righttst ;skip if left=0000
|
||
;left not at position zero,
|
||
;bit zero ?
|
||
DEC CX
|
||
PUSH DX
|
||
PUSH CX ;left,right pushed
|
||
CALL getallocbit
|
||
RCR AL,1
|
||
JAE rblok ;return block number if zero
|
||
;bit is one, so try the right
|
||
POP CX
|
||
POP DX ;left, right restored
|
||
righttst:
|
||
cmp dx,maxall ;value of maximum allocation#
|
||
JAE rblok0 ;return block 0000 if so
|
||
INC DX
|
||
PUSH CX
|
||
PUSH DX ;left, right pushed
|
||
MOV cx,dx ;ready right for call
|
||
CALL getallocbit
|
||
RCR AL,1
|
||
JAE rblok ;return block number if zero
|
||
POP DX
|
||
POP CX ;restore left and right ptr
|
||
jmps lefttst ;for another attempt
|
||
rblok:
|
||
RCL AL,1
|
||
INC AL ;bit back into position
|
||
;and set to 1
|
||
;DL contains the number of
|
||
;shifts required to reposition
|
||
CALL rotr ;move bit back to position
|
||
;and store
|
||
POP BX
|
||
POP DX ;BX returned value,
|
||
;DX discarded
|
||
RET
|
||
rblok0:
|
||
;cannot find an available
|
||
;bit, return 0000
|
||
or cx,cx
|
||
jnz lefttst
|
||
MOV BX,0000h
|
||
RET
|
||
;
|
||
copyfcb:
|
||
;copy the entire FCB
|
||
MOV CL,0
|
||
MOV DL,fcblen ;start at 0, to fcblen-1
|
||
; jmp copydir ;
|
||
;
|
||
copydir:
|
||
;copy fcb information starting
|
||
;into the currently addressed directory entry
|
||
PUSH DX ;save length for later
|
||
MOV CH,0 ;double index to CX
|
||
MOV dx,info ;BX = source for data
|
||
ADD dx,CX ;DX=.fcb(CL), source for copy
|
||
CALL getdptra ;BX=.buff(dptr), destination
|
||
POP CX ;DX=source, BX=dest, C=length
|
||
CALL move ;data moved
|
||
seekcopy:
|
||
;enter from close to seek and copy current element
|
||
CALL seekdir ;to the directory element
|
||
JMP wrdir ;write the directory element
|
||
;ret
|
||
;
|
||
;
|
||
rename:
|
||
;rename the file described by the first half of
|
||
;the currently addressed file control block. the
|
||
;new name is contained in the last half of the
|
||
;currently addressed file conrol block. the file
|
||
;name and type are changed, but the reel number
|
||
;is ignored. the user number is identical.
|
||
;
|
||
CALL checkwrite ;may be write protected
|
||
;search up to the extent field
|
||
MOV CL,extnum
|
||
CALL srch
|
||
;copy position 0
|
||
MOV BX,info
|
||
MOV AL,[bx] ;BX=.fcb(0), A=fcb(0)
|
||
ADD BX,dskmap ;bx=.fcb(diskmap)
|
||
MOV [bx],al ;fcb(dskmap)=fcb(0)
|
||
;assume the same disk
|
||
;for new named file
|
||
renam0:
|
||
CALL endofdir
|
||
JNZ L_51
|
||
ret10: RET
|
||
L_51: ;stop at end of dir
|
||
;not end of directory,
|
||
;rename next element
|
||
CALL ckrodir ;may be read-only file
|
||
MOV CL,dskmap
|
||
MOV DL,extnum
|
||
CALL copydir
|
||
;element renamed, move to next
|
||
CALL srchn
|
||
jmps renam0
|
||
;
|
||
indicators:
|
||
;set file indicators for current fcb
|
||
MOV CL,extnum
|
||
CALL srch ;through file type
|
||
indic0:
|
||
CALL endofdir
|
||
jz ret10 ;stop at end of dir
|
||
;not end of directory,
|
||
;continue to change
|
||
MOV CL,0
|
||
MOV DL,extnum ;copy name
|
||
CALL copydir
|
||
CALL srchn
|
||
jmps indic0
|
||
;
|
||
open:
|
||
;search for the directory entry, copy to FCB
|
||
MOV CL,namlen
|
||
CALL srch
|
||
CALL endofdir
|
||
jz ret10 ;return with lret=255 if end
|
||
;not end of directory,copy fcb
|
||
opencopy:
|
||
;(referenced below to copy fcb
|
||
CALL getexta
|
||
|
||
PUSH AX
|
||
PUSH BX ;save extent#
|
||
CALL getdptra
|
||
XCHG BX,DX ;DX = .buff(dptr)
|
||
MOV BX,info ;BX=.fcb(0)
|
||
MOV CL,nxtrec ;length of move operation
|
||
PUSH DX ;save .buff(dptr)
|
||
CALL move ;from .buff(dptr) to .fcb(0)
|
||
;note that entire fcb is
|
||
;copied, including indicators
|
||
CALL setfwf ;sets file write flag
|
||
POP DX
|
||
MOV BX,extnum
|
||
ADD BX,DX ;bx=.buff(dptr+extnum)
|
||
mov cl,[bx]
|
||
|
||
MOV BX,reccnt
|
||
ADD BX,DX
|
||
mov ch,[bx]
|
||
|
||
POP BX
|
||
POP AX
|
||
MOV [bx],al ;restore extent number
|
||
;
|
||
;BX = .user extent#, CH = dir rec cnt, CL = dir extent#
|
||
;if user ext < dir ext then user := 128 records
|
||
;if user ext = dir ext then user := dir records
|
||
;if user ext > dir ext then user := 0 records
|
||
;
|
||
CMP cl,[bx]
|
||
MOV AL,CH ;ready dir reccnt
|
||
JZ openrcnt ;if same, user gets dir reccnt
|
||
MOV AL,0
|
||
JB openrcnt ;user is larger
|
||
MOV AL,128 ;directory is larger
|
||
openrcnt: ;A has record count to fill
|
||
MOV BX,info
|
||
MOV DX,reccnt
|
||
ADD BX,DX
|
||
MOV [bx],al
|
||
ret11: RET
|
||
;
|
||
mergezero:
|
||
;BX = .fcb1(i), DX = .fcb2(i),
|
||
;if fcb1(i) = 0
|
||
;then fcb1(i) := fcb2(i)
|
||
cmp w[bx],0
|
||
jnz ret11 ;rnz
|
||
MOV SI,DX
|
||
LODS ax
|
||
mov [bx],ax
|
||
ret12: RET
|
||
;
|
||
close:
|
||
;locate the directory element and re-write it
|
||
XOR AX,AX
|
||
MOV lret,al
|
||
MOV dcnt,ax
|
||
CALL nowrite
|
||
jnz ret12 ;skip close if r/o disk
|
||
;check file write flag -
|
||
;0 indicates written
|
||
CALL getmodnum ;fcb(modnum) in A
|
||
AND AL,fwfmsk
|
||
jnz ret12 ;return if bit remains set
|
||
MOV CL,namlen
|
||
CALL srch ;locate file
|
||
CALL endofdir
|
||
jz ret12 ;return if not found
|
||
;merge the disk map at info
|
||
MOV CX,dskmap
|
||
CALL getdptra
|
||
ADD BX,CX
|
||
XCHG BX,DX ;DX is .buff(dptr+16)
|
||
MOV BX,info
|
||
ADD BX,CX ;dx=.buff(dptr+16),
|
||
;bx=.fcb(16)
|
||
MOV CL,(fcblen-dskmap) ;length of single byte dm
|
||
merge0:
|
||
cmp single,0
|
||
JZ merged ;skip to double
|
||
;
|
||
;this is a single byte map
|
||
;if fcb(i) = 0 then fcb(i) = buff(i)
|
||
;if buff(i) = 0 then buff(i) = fcb(i)
|
||
;if fcb(i) <> buff(i) then error
|
||
;
|
||
MOV AL,[bx]
|
||
OR AL,AL
|
||
MOV SI,DX
|
||
LODS al
|
||
JNZ fcbnzero
|
||
;fcb(i) = 0
|
||
MOV [bx],al ;fcb(i) = buff(i)
|
||
fcbnzero:
|
||
OR AL,AL
|
||
JNZ buffnzero
|
||
;buff(i) = 0
|
||
MOV AL,[bx]
|
||
MOV DI,DX
|
||
stos al ;buff(i)=fcb(i)
|
||
buffnzero:
|
||
CMP AL,[bx]
|
||
jnz mergerr ;fcb(i) = buff(i)?
|
||
jmps dmset ;if merge ok
|
||
merged:
|
||
;this is a double byte merge
|
||
CALL mergezero ;buff = fcb if buff 0000
|
||
XCHG BX,DX
|
||
CALL mergezero
|
||
XCHG BX,DX ;fcb = buff if fcb 0000
|
||
;they should be identical
|
||
;at this point
|
||
MOV SI,DX
|
||
mov ax,[si]
|
||
cmp ax,[bx]
|
||
jnz mergerr
|
||
inc dx
|
||
inc bx
|
||
;merge ok for this pair
|
||
DEC CL ;extra count for double byte
|
||
dmset:
|
||
INC DX
|
||
INC BX
|
||
DEC CL
|
||
JNZ merge0 ;for more
|
||
;end of disk map merge,
|
||
;check record count
|
||
;DX = .buff(dptr)+32,
|
||
;BX = .fcb(32)
|
||
MOV CX,-(fcblen-extnum)
|
||
ADD BX,CX
|
||
XCHG BX,DX
|
||
ADD BX,CX
|
||
;DX = .fcb(extnum),
|
||
;BX = .buff(dptr+extnum)
|
||
MOV SI,DX
|
||
LODS al ;current user extent number
|
||
;if fcb(ext) >= buff(fcb) then
|
||
;buff(ext) := fcb(ext),
|
||
;buff(rec) := fcb(rec)
|
||
CMP AL,[bx]
|
||
JB endmerge
|
||
;fcb extent number >=
|
||
;dir extent number
|
||
MOV [bx],al ;buff(ext) = fcb(ext)
|
||
;update dir. rec count field
|
||
MOV CX,(reccnt-extnum)
|
||
ADD BX,CX
|
||
XCHG BX,DX
|
||
ADD BX,CX
|
||
;DX=.buff(reccnt),
|
||
;BX=.fcb(reccnt)
|
||
MOV AL,[bx]
|
||
MOV DI,DX
|
||
stos al ;buff(reccnt)=fcb(reccnt)
|
||
endmerge:
|
||
MOV fcbcopied,true ;mark as copied
|
||
JMP seekcopy ;ok to "wrdir" here -
|
||
;1.4 compatible
|
||
; ret
|
||
mergerr:
|
||
;elements did not merge ok
|
||
dec lret ;=255 non zero flag set
|
||
ret13: RET
|
||
;
|
||
make:
|
||
;create a new file by creating a directory entry
|
||
;then opening the file
|
||
CALL checkwrite ;may be write protected
|
||
push info
|
||
MOV info,offset efcb ;info = .empty
|
||
MOV CL,1
|
||
CALL srch ;length 1 match on empty entry
|
||
CALL endofdir ;zero flag set if no space
|
||
pop info ;recall word ptr info address
|
||
jz ret13 ;return with error condition
|
||
;255 if not found
|
||
XCHG BX,DX ;DX = word ptr info address
|
||
;clear the remainder of fcb
|
||
MOV BX,namlen
|
||
ADD BX,DX ;bx=.fcb(namlen)
|
||
MOV CL,fcblen-namlen ;number of bytes to fill
|
||
XOR AL,AL ;clear AL for fill
|
||
make0:
|
||
MOV [bx],al
|
||
INC BX
|
||
DEC CL
|
||
JNZ make0
|
||
MOV BX,ubytes
|
||
ADD BX,DX ;bx=.fcb(ubytes)
|
||
MOV [bx],al ;fcb(ubytes) = 0
|
||
CALL setcdr ;may have extended dir
|
||
;now copy entry to dir
|
||
CALL copyfcb
|
||
;set file write flag to "1"
|
||
JMP setfwf
|
||
;ret
|
||
;
|
||
openreel:
|
||
;close the current extent, and open the next one
|
||
;if possible. RMF is true if in read mode.
|
||
XOR AL,AL
|
||
MOV fcbcopied,AL ;set true if actually copied
|
||
CALL close ;close current extent
|
||
;lret remains at enddir
|
||
;if we cannot open next ext
|
||
CALL endofdir
|
||
jz ret13 ;return if end
|
||
;increment extent number
|
||
MOV BX,info
|
||
ADD BX,extnum ;BX=.fcb(extnum)
|
||
MOV AL,[bx]
|
||
INC AL
|
||
AND AL,maxext
|
||
MOV [bx],al ;fcb(extnum)=++1
|
||
JZ openmod ;move to next module if 0
|
||
;may be in same extent group
|
||
MOV CH,AL
|
||
MOV AL,extmsk
|
||
AND AL,CH
|
||
;if 0, then not in same group
|
||
and al,fcbcopied ;true if fcb was copied to dir
|
||
;puts 0 in AL if not written
|
||
JZ openr0 ;go to next physical extent
|
||
;result is non zero,
|
||
;so we must be in same extent
|
||
jmps openr1 ;to copy fcb info
|
||
openmod:
|
||
;extent number overflow, go to next module
|
||
ADD BX,(modnum-extnum) ;bx=.fcb(modnum)
|
||
INC b[bx] ;fcb(modnum)=++1
|
||
;module number incremented,
|
||
;check for overflow
|
||
MOV AL,[bx]
|
||
AND AL,maxmod ;mask high order bits
|
||
JZ openerr ;cannot overflow to 0
|
||
;otherwise, ok to continue
|
||
;with new module
|
||
openr0:
|
||
MOV CL,namlen
|
||
CALL srch ;next extent found?
|
||
CALL endofdir
|
||
JNZ openr1
|
||
;end of file encountered
|
||
MOV AL,rmf
|
||
INC AL ;0ffh becomes 00 if read
|
||
JZ openerr ;sets lret = 1
|
||
;try to extend current file
|
||
CALL make
|
||
;cannot be end of directory
|
||
CALL endofdir
|
||
JZ openerr ;with lret = 1
|
||
jmps openr2
|
||
openr1:
|
||
;not end of file, open
|
||
CALL opencopy
|
||
openr2:
|
||
CALL getfcb ;set parameters
|
||
XOR AL,AL
|
||
JMP staret ;lret = 0
|
||
; ret
|
||
openerr:
|
||
;cannot move to next extent
|
||
;of this file
|
||
CALL setlret1 ;lret = 1
|
||
JMP setfwf ;ensure that it will not
|
||
;be closed
|
||
;ret
|
||
;
|
||
;*************** end BDOS file system part 2 ***************
|
||
end
|
||
|