📄 funcs.fdo
字号:
; On Exit:
; None
lodsw ; get sector size in bytes
mov es:DDSC_SECSIZE[di],ax
lodsb ; get sectors/allocation unit
dec ax ; get cluster mask
mov es:DDSC_CLMSK[di],al ; store cluster mask
lodsw ; get FAT address
mov es:DDSC_FATADDR[di],ax
lodsb ; get # of fats
mov es:DDSC_NFATS[di],al
cbw ; make it a word value
xchg ax,dx ; and keep in DX
lodsw ; get # of directory entries
mov es:DDSC_DIRENT[di],ax
lodsw ; get # of sectors total in image
push ax ; save disk size for later
lodsb ; get FAT id byte
mov es:DDSC_MEDIA[di],al ; set media byte
lodsw ; get # of sectors in a fat
if DOS5
mov es:DDSC_NFATRECS[di],ax ; set FAT size
else
mov es:DDSC_NFATRECS[di],al ; set FAT size
endif
mul dx ; AX = FAT size
add ax,es:DDSC_FATADDR[di] ; AX = 1st directory sector
mov es:DDSC_DIRADDR[di],ax ; set root directory address
add si,word+word+dword ; skip SPT, NHEADS, BIGHIDDEN
mov cx,es:DDSC_SECSIZE[di]
mov ax,32 ; size of single directory entry
mul es:DDSC_DIRENT[di] ; AX/DX = root directory bytes
add ax,cx ; round up sector size
dec ax ; in case of odd number
div cx ; convert to whole sectors
add ax,es:DDSC_DIRADDR[di] ; add in base of root directory
mov es:DDSC_DATADDR[di],ax ; set this as first cluster address
pop ax ; recover total disk size
xor dx,dx ; assume 16 bit number
test ax,ax ; test for big drive
jnz bpb2ddsc10 ; skip if not large drive
lodsw ; get low word of size
mov dx,[si] ; get high word of size
bpb2ddsc10: ; AX/DX = disk size in sectors
sub ax,es:DDSC_DATADDR[di] ; subtract non-data portion
sbb dx,0
xor cx,cx ; CL = cluster shift
mov ch,es:DDSC_CLMSK[di] ; CH = cluster mask
bpb2ddsc20: ; count # of 1 bits
shr ch,1 ; shift right mask
jnc bpb2ddsc30 ; skip if all 1 bits shifted out
inc cx ; count another 1 bit
shr dx,1
rcr ax,1 ; div by two
jmps bpb2ddsc20 ; repeat until all 1's counted
bpb2ddsc30: ; CL = log2 (CH)
mov es:DDSC_CLSHF[di],cl ; set cluster shift
inc ax ; clusters 0/1 reserved (+2), and we
mov es:DDSC_NCLSTRS[di],ax ; want max (-1), so +1
xor ax,ax
mov es:DDSC_BLOCK[di],ax ; next block = 0
dec ax
mov es:DDSC_FREE[di],ax ; free space = -1 (unknown)
ret
eject
; DIRECT DISK IO
; +----+----+----+----+----+----+
; | 54 |drv | op |nsectors |
; +----+----+----+----+----+----+----+----+
; | startsec | dma address |
; +----+----+----+----+----+----+----+----+
; entry:
; ------
; param block set up for direct disk IO
; exit:
; -----
; AX = 0, or error code
;
DIO_25_READ_OP equ 1
DIO_26_WRITE_OP equ 2
fdos_ddio:
;---------
; Used by emulator for Int 25H/26H disk calls to BIOS
;
; entry: dio = offset of parameter block in user data segment
;
; exit: AX = return code from BIOS
call local_disk ; get the MX
mov ax,fdos_pb+WORD ; AX = logical drive
call logical2physical ; AX = physical drive
call get_ddsc ; make sure this drive is valid
jc fdos_ddio30 ; bail if not
mov adrive,al ; remember this unit
mov ax,CMD_INPUT+0*256 ; disk read operation of system area
cmp byte ptr fdos_pb+3,DIO_26_WRITE_OP
jne fdos_ddio10
mov ax,0FFFFh
mov es:DDSC_FREE[bx],ax ; free space = -1 (unknown)
call hshdscrd ; discard hashing info for all drives (AL=FF)
mov ax,CMD_OUTPUT+1*256 ; disk write operation of system area
fdos_ddio10:
mov rwmode,ah ; save read/write of system area
mov req_hdr+5,ah ; (so driver can get the hint)
mov bx,offset req_hdr ; we will build request here
mov RH_CMD[bx],al ; save the command
mov ax,fdos_pb+4 ; AX = # sectors
mov RH4_COUNT[bx],ax ; set requested sector count
les ax,dword ptr fdos_pb+6 ; pick up 32-bit record address
mov word ptr pblock,ax
mov word ptr pblock+WORD,es
les ax,dword ptr fdos_pb+10 ; ES:AX -> DMA seg
mov RH4_BUFOFF[bx],ax
mov RH4_BUFSEG[bx],es
call ddioif ; go do it
jns fdos_ddio20 ; did we have a problem ?
cbw ; AX = base error
add ax,ED_PROTECT ; "add" in BIOS error code
mov fdos_ret,ax ; save return code
fdos_ddio20:
ret
fdos_ddio30:
jmp fdos_ED_DRIVE ; return bad drive error
eject
; EXPAND FILE NAME
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; | 55 | relative name | | absolute name |
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; relative name: segmented address of ASCIIZ name
; absolute name: segmented address of ASCIIZ name
; exit:
; -----
; AX = BX: 0000 or error code ( < 0)
fdos_expand:
;-----------
call redir_asciiz_dev_offer ; is it a networked device ?
call asciiz_dev_offer ; see it we are expanding a device name
call local_disk ; get MXdisk, switch stack
push ds
les si,dword ptr fdos_pb+2 ; get relative name buffer
mov ax,es:[si] ; get 1st two chars of path
call check_dslash ; is it a '\\' form ?
je fdos_expand10
mov bx,ED_FILE
test al,al
jz fdos_expand60
call toupper ; work on premise we have drive
sub al,'A' ; specified in relative name
sub ah,':' ; did we have ?
je fdos_expand20 ; if so use it
fdos_expand10:
mov al,current_dsk ; use current drive
fdos_expand20:
cmp al,last_drv ; is it a legal drive
jae fdos_expand50
; we should check for a media change so select_logical_drv seems to be
; a better solution
; call get_ldt ; ES:BX -> LDT_ for drive
; jc fdos_expand40 ; no LDT at init - copy relative path
; mov word ptr current_ldt,bx
; mov word ptr current_ldt+WORD,es
call select_logical_drv
les bx,current_ldt
test es:LDT_FLAGS[bx],LFLG_PHYSICAL
jz fdos_expand50 ; make sure it's a valid drive
push ss ! pop es
mov di,offset pri_pathname ; build name in pathname buffer
lds si,dword ptr fdos_pb+2
; we must trick redir_build_path to find the correct function number -
; otherwise we could not get correct (critical) error reporting to work
push bp
mov bp,offset fdos_pb+6
mov 2[bp],bp
mov byte ptr [bp],FD_EXPAND
call redir_build_path ; build name from LDT
pop bp
jc fdos_expand60 ; bail out if bad name
lds di,ss:current_ldt ; we need to append a '\' if
mov bx,ds:LDT_ROOTLEN[di] ; we are at the root
test ds:LDT_FLAGS[di],LFLG_SUBST
jz fdos_expand30 ; if drive is SUBST'd then
mov bx,2 ; only append if real root
fdos_expand30:
mov si,offset pri_pathname ; SS:SI -> full path
push ss ! pop ds ; leave current ldt -> buffer as LAN
mov word ptr current_ldt,si ; MAN 2.1 extended edition expects it
mov word ptr current_ldt+WORD,ds
mov ax,'\' ; get pathchar in AX for checks
cmp ds:byte ptr [si+bx],ah ; are we at the root ?
jne fdos_expand40 ; if so append a '\'
mov ds:word ptr [si+bx],ax
fdos_expand40:
les di,ss:dword ptr fdos_pb+10; ES:DI -> destination buffer
call copy_asciiz ; copy the full pathname
pop ds
ret
fdos_expand50:
mov bx,ED_DRIVE ; return bad drive error
fdos_expand60:
mov ax,bx
pop ds
jmp fdos_error
expand_dev:
;----------
les si,dword ptr fdos_pb+2 ; this is the original source
lods es:ax ; get the source
les di,dword ptr fdos_pb+10 ; data will end up here
cmp ah,':' ; is a drive specified ?
je expand_dev10
mov al,'A'
add al,ss:current_dsk
expand_dev10:
call toupper ; make sure drive letter is upper case
stosb ; plant an 'd'
mov ax,':'+256*'/'
stosw ; make that 'd:/'
mov bx,offset name_buf ; DS:BX -> name buffer
jmp unparse ; unparse the device name
eject
; RENAME FILE
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; | 56 | old name | | new name |
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; old name: segmented address of ASCIIZ name
; new name: segmented address of ASCIIZ name
; exit:
; -----
; AX: 0000 or error code ( < 0)
; Note: R/O files can be renamed.
; ---
fdos_move:
;---------
call redir_move_offer
call local_disk ; get MXdisk, switch stack
call path_prep ; parse the path, go to bottom level
call chk_no_dev
cmp ss:remote_call,0 ; wildcards allowed if server/FCB
jnz move10
call chk_no_wild ; make sure not a wild card
move10:
call finddfcbf ; else try to locate directory entry
jz fdos_ED_FILE ; error if no match occurred
move20:
call close_if_same_psp ; make sure not open by other PDs
if PASSWORD
call check_pwd_any ; check if password protected
endif
mov si,dirp ; get matching directory entry
mov di,offset save_area ; get a temporary save area
mov cx,32/WORD ; save it all
rep movsw ; so we can move it to new entry
mov si,offset fdos_hds
mov di,offset saved_hds
mov cl,HDS_LEN
rep movsb ; copy current HDS to safe place
mov ax,dcnt ; also save directory index
mov saved_dcnt,ax ; so we can release entry later
les di,dword ptr fdos_pb+10 ; es:di -> path name
call path_prep_ptr ; find the destination path
call chk_no_dev ; no devices allowed here
cmp ss:remote_call,0 ; wildcards allowed if server/FCB
jnz move25
call chk_no_wild ; make sure not a wild card
move25:
mov al,fdos_hds_drv ; get the work drive
cmp al,saved_hds_drv ; make sure same drive for
je move30 ; source and destination
mov ax,ED_DEVICE ; "not same device" error
jmps fdos_moverr ; return the error
fdos_ED_FILE:
mov ax,ED_FILE ; get error code
fdos_moverr:
jmp fdos_error ; return the error
move30: ; same drive for source & destination
mov al,byte ptr fdos_pb+8 ; check attributes
if PASSWORD
cmp save_area+DPWD,0
je move31
or al,DA_HIDDEN
move31:
endif
not al
and al,DA_HIDDEN+DA_SYSTEM+DA_DIR+DA_VOLUME
test save_area+DATTS,al
jnz move80
mov si,offset info_fcb+1 ; SI->new name (possible wildcards)
mov di,si ; DI->new name
mov bx,offset save_area ; current name on disk
cmp byte ptr DNAME[bx],'.'
je move80
mov cx,11
move40: ; fill in the wild card characters
lodsb ; get next character from new name
if KANJI
call dbcs_lead ; is it the 1st of a kanji pair
jne move45
dec cx ; copied this one
jcxz move55 ; discard if no room for kanji char
stosb ; copy 1st byte of Kanji pair
inc bx
lodsb ; copy 2nd byte
jmps move50
move45:
endif
call toupper ; make it upper case
cmp al,'?' ; is it just a wild card?
jne move50 ; no, put in destination as is
mov al,[bx] ; else leave original character
move50: ; AL = next char for destination
stosb ; store next char in destination
inc bx ; increment all pointers
loop move40 ; repeat for all 11 characters
move55:
call finddfcbf ; find first non-volume entry
jnz move_access ; file already exists, return error
call move_comp ; source & destination in same dir?
jne move60 ; skip if moving to different directory
call move_seek ; else find old entry again
jmps move70 ; replace name in old entry
move60: ; moving to different directory
test save_area+DATTS,DA_DIR ; can't move directory to new path
jnz move_access ; so return error if new path
call allocdir ; allocate a directory entry
move70:
mov si,offset info_fcb+1 ; get pointer to new name
mov di,dirp ; get pointer to directory entry
mov cx,11 ; copy new name into buffer
rep movsb
mov si,offset save_area+11 ; copy remaining info
mov cx,32-11
rep movsb
call update_dir ; update the disk
call move_comp ; did we rename across directories?
je move80 ; skip if in same directory
mov si,offset saved_hds
mov di,offset fdos_hds ; else need to copy HDS back
mov cx,HDS_LEN ; so we can get old entry again
rep movsb ; (time to get rid of it)
call move_seek ; seek the original entry
mov bx,dirp
mov DNAME[bx],0E5h ; and bye, bye! it goes...
call update_dir ; update the old directory entry
move80:
cmp ss:remote_call,0 ; wildcards allowed if server/FCB
jz move90 ; so check for multiple files
call path_prep ; parse the path, go to bottom level
mov ax,saved_dcnt ; restore dcnt for remote call
mov dcnt,ax ; to function properly
and chdblk,0
call finddfcb ; try to locate another directory entry
jz move90 ; no, return now
jmp move20 ; round again if we do
move_access:
jmp fdos_ED_ACCESS ; "access denied" if file
; already exists
move90:
; in order to update the current directory in case part of it has been
; renamed we call fdos_chdir which does all the work for rebuilding
; the LDT_ for the given drive
push ss
pop ds
mov bx,offset sec_pathname
mov ax,path_drive
add ax,'A'+(':'*100h)
mov [bx],ax
mov word ptr 2[bx],'.'
mov fdos_pb+4,ds
mov fdos_pb+2,bx
mov byte ptr remote_call,0
jmp fdos_move_chdir
move_seek: ; re-seek the old directory entry
mov ax,saved_dcnt ; get saved directory count
dec ax ; move back one for GETDIR
mov dcnt,ax ; set search offset
and chdblk,0 ; follow the chains, not sequential
mov cl,0 ; return next entry
jmp getdir ; in current directory
move_comp:
mov ax,fdos_hds_blk
cmp ax,saved_hds_blk
ret
eject
; GET/SET FILE DATE/TIME
; +----+----+----+----+----+----+----+----+----+----+
; | 57 | handle | mode | date | time |
; +----+----+----+----+----+----+----+----+----+----+
; entry:
; ------
; handle: open file handle
; mode: 0 = get date/time, 1 = set date/time
; date: date as in directory FCB
; time: time as in directory FCB
; exit:
; -----
; AX: 0000 or error code ( < 0)
; date: date of last modification if mode = 0
; time: date of last modification if mode = 0
fdos_dattim:
;-----------
call vfy_dhndl_ptr ; check file handle #
call redir_dhndl_offer
call local_disk ; get
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -