📄 disk.a86
字号:
mov FD_PATHSEG,es
xchg ax,dx ; drive in AL
cbw ; make that AX
mov FD_DRIVE,ax
jmp fdos_ax_crit ; return garbage in AH (SPJ bug)
; *****************************
; *** DOS Function 53 ***
; *** Build DPB from BPB ***
; *****************************
;
; This function takes the BPB at DS:SI and builds a DDSC at ES:BP
;
Public func53
func53:
call set_retry_RF ; Valid to RETRY or FAIL
mov FD_BPBOFF,si ; Segment and Offset of BPB
mov FD_BPBSEG,es
mov FD_DDSCOFF,bp ; Segment and Offset of DDSC
call reload_ES
mov FD_DDSCSEG,es
jmp fdos_nocrit
;
; *****************************
; *** DOS Function 56 ***
; *** Rename/Move a File ***
; *****************************
;
Public func56
func56:
call set_retry_RF ; Valid to RETRY or FAIL
mov FD_NNAMEOFF,di ; New FileName
push es
call reload_ES ; callers ES:DI
mov FD_NNAMESEG,es ; point to new filename
pop es
mov FD_ONAMEOFF,dx ; Old FileName
mov FD_ONAMESEG,es
cmp ss:remote_call,0
jne func56_10
mov cl,17h
func56_10:
mov FD_ATTRIB,cx
jmp fdos_crit
; *****************************
; *** DOS Function 57 ***
; *** Get/Set File Time ***
; *****************************
;
Public func57
func57:
call set_retry_RF ; Valid to RETRY or FAIL
mov FD_DATE,dx
mov FD_TIME,cx
mov FD_SFLAG,ax
cmp al,1 ; allow get/set only
mov ax,ED_FUNCTION ; all else fails horribly
ja f57_error
call fdos_handle
jc f57_error
call reload_registers
test al,al
jnz f57_exit
mov cx,FD_TIME
call return_CX ; return TIME in CX
mov dx,FD_DATE
jmp return_DX ; and DATE in DX
f57_exit:
ret
f57_error:
jmp error_exit
; *****************************
; *** DOS Function 5A ***
; *** Create Unique File ***
; *****************************
;
Public func5A
func5A:
mov ax,ED_ACCESS ; assume we will have an error
test cx,DA_FIXED ; because of silly attributes
jnz func5A_40 ; did we ?
mov si,dx ; find end of pathname
xor ax,ax ; no previous char
func5A_10:
xchg ax,bx ; BL = previous char
lods es:al ; get next char
test al,al ; is it the end of the string?
jz func5A_20
call dbcs_lead ; is it a KANJI char?
jnz func5A_10
inc si ; skip 2nd char of pair
jmps func5A_10
func5A_20:
dec si ; SI -> NUL
cmp bl,'\' ; was last char a '\' ?
je func5A_30
cmp bl,'/' ; (or a '/' for unix freaks)
je func5A_30
mov es:byte ptr [si],'\' ; append a '\' to name
inc si
func5A_30:
; Here ES:DX -> start of name, ES:SI -> position to append <unique name>,0
; CX = attribute for file.
; We generate a unique name based upon the time and date - if this already
; exists we keep retrying knowing the number of files is finite and we must
; succeed eventually
push cx ! push dx ! push si ; append a unique'ish name
call func5A_append_unique_name
pop si ! pop dx ! pop cx
mov ah,MS_X_MKNEW ; try to create unique file
call dos_entry
jnc func5A_50 ; exit if we succeeded
mov es:byte ptr [si],0 ; else forget extention
cmp ax,ED_EXISTS ; we only retry if it already exists
je func5A_30
func5A_40:
jmp error_exit ; return error to caller
func5A_50:
jmp return_AX_CLC ; return handle to caller
func5A_append_unique_name:
;-------------------------
; On Entry:
; ES:DX -> start of name
; ES:SI -> position to append <unique name>,0
; CX = attribute for file.
; On Exit:
; None
;
; We append a unique 8 character filename to this based upon the current
; date/time.
push si
mov ax,120dh
int 2fh ; get date/time in AX & DX
pop di
add ax,unique_name_seed ; randomise the date otherwise we would
inc unique_name_seed ; have one second wait between names
call func5A_app_AX ; store 4 ascii bytes
xchg ax,dx ; was DX = time
call func5A_app_AX ; store 4 ascii bytes
xor ax,ax
stosb ; and a terminating NUL
ret
func5A_app_AX:
; On Entry AX = word, ES:DI -> string
; Store 4 ASCII chars at ES:DI, based upon value in AX
call func5A_app_AL ; do low byte, falling thru to do high
func5A_app_AL:
call func5A_app_NIB ; low nibble, falling thru for high
func5A_app_NIB:
push ax
and al,0fh ; mask out a nibble
add al,'A' ; make it ASCII character
stosb ; plant the string
pop ax
mov cl,4
shr ax,cl ; shift nibble
ret
; *****************************
; *** DOS Function 60 ***
; ***Perform Name Processing***
; *****************************
;
; DS:SI point to a source string which contains a relative path
; specification ES:DI points to a buffer which is at least 80
; bytes longer than the source string.
;
; The carry flag is set and AX contains an error code if the
; source string is mal formed. This function is used by the
; Ryan-McFarland COBOL compiler.
;
Public func60
func60:
call set_retry_RF ; Valid to RETRY or FAIL
mov FD_FUNC,FD_EXPAND ; Expand a relative Path
mov FD_ONAMEOFF,si ; Initialise Source Pointer
mov FD_ONAMESEG,es
mov FD_NNAMEOFF,di ; Initialise Destination
call reload_ES ; pointer
mov FD_NNAMESEG,es
jmp fdos_crit
; *****************************
; *** DOS Function 67 ***
; *** Set/Handle Count ***
; *****************************
;
; We impose a minimum of 20 handles regardless of what the caller
; requests. If the request is <=20 we use the default handle table in
; the PSP, else we allocate a memory block for the new table.
; If the old handle table was in a memory block (ie. zero offset) we
; will free that block up afterwards.
; When shrinking the handle count the error ED_HANDLE will be given if
; open files would have been lost.
;
Public func67
func67:
push ds
mov ds,current_psp ; DS -> current PSP blk
cmp bx,20 ; force to minimum value of 20
jae f67_10
mov bx,20 ; never have less than 20 handles
f67_10:
mov cx,ds:PSP_XFNMAX ; we have this many handles
sub cx,bx ; are we growing ?
jbe f67_20 ; if shrinking make sure none open
les di,ds:PSP_XFTPTR ; point to existing handle table
lea di,[di+bx] ; point to 1st handle we will lose
mov al,0FFh ; they must all be closed
repe scasb ; or we fail
mov ax,ED_HANDLE ; fail if we are in danger of losing
jne f67_error ; open handles
f67_20:
push bx ; save # of handles wanted
push ds ! pop es
mov di,offset PSP_XFT ; ES:DI -> new handle table
cmp bx,20 ; if we are setting to the
je f67_30 ; default size
add bx,15 ; calculate memory required
mov cl,4 ! shr bx,cl ; num of paragraphs required
xor di,di ; offset will be zero
mov ah,MS_M_ALLOC ; allocate the memory
call dos_entry
mov es,ax ; ES:DI -> new handle table
f67_30:
pop bx ; BX = # handles wanted
jc f67_error ; ES:DI -> new handle table
mov cx,bx ; CX = new # handles
xchg cx,ds:PSP_XFNMAX ; Update the Handle Count
mov si,di ; Update the Table Offset
xchg si,ds:PSP_XFTOFF
mov ax,es
xchg ax,ds:PSP_XFTSEG ; Update the Table Segment
mov ds,ax ; DS:SI -> old handle table
; ES:DI -> new handle table
; CX = # old handles to copy
; BX = # new handles desired
sub bx,cx ; BX = # extra "closed" handles
jae f67_40 ; negative if we are shrinking
add cx,bx ; CX = # handles we inherit
xor bx,bx ; BX = no extra "closed" handles
f67_40:
push si ; save offset old handle table
rep movsb ; Copy the existing Handles
pop si ; SI = offset old handle table
mov al,0FFh ; AL = unused handle
mov cx,bx ; mark extra handles as unused
rep stosb ; mark as unused
test si,si ; do we have memory to free ?
jnz f67_50
mov ah,MS_M_FREE
call dos_entry ; free up old handle table DMD
f67_50:
pop ds
jmp return_AX_CLC ; clear carry on return
f67_error:
pop ds ; restore DS
jmp error_exit ; and return error AX to caller
; *****************************
; *** DOS Function 68 ***
; *** Commit File ***
; *****************************
;
Public func68
func68:
call set_retry_RF ; Valid to RETRY or FAIL
mov FD_FUNC,FD_COMMIT ; Close a File Handle
jmp fdos_handle
; *****************************
; *** DOS Function 6C ***
; *** Extended Open ***
; *****************************
;
Public func6C
func6C:
mov al,OK_RF ; Valid to RETRY or FAIL
test bh,20h ; should we allow critical errors ?
jz f6C10
or al,NO_CRIT_ERRORS ; no, so remember that
f6C10:
call set_retry
mov ax,ED_FUNCTION ; assume an illegal action code
test dx,not 0113h ; now check for sensible bits
jnz f6C_error
inc dx
test dl,4 ; also reject bits 0-3 = 3
jnz f6C_error
dec dx
xchg ax,si ; ES:AX -> name
xchg ax,dx ; AX = action, ES:DX -> name
xchg ax,bx ; AX = open mode, BX = action
test bl,010h ; should we create if not there ?
jz f6C_open ; no, skip the attempt at make new
and ah,(DHM_COMMIT+DHM_NOCRIT)/100h
mov FD_FUNC,FD_NEW ; create only if not there
call funcExtendedOpenCreate ; try to open/create the file
mov cx,2 ; CX = file created
jnc f6C_exit ; return this if we succeeded
f6C_open:
call reload_registers ; all registers as per entry
xchg ax,si ; ES:AX -> name
xchg ax,dx ; AX = action, ES:DX -> name
xchg ax,bx ; AX = open mode, BX = action
push bx ; save action
and ah,(DHM_COMMIT+DHM_NOCRIT)/100h
mov FD_FUNC,MS_X_OPEN ; try an open an existing file
call funcExtendedOpenCreate
pop bx ; recover action
jc f6C_error ; return error if we can't open file
mov cx,1 ; CX = file opened
test bl,001h ; should we open if it exists ?
jnz f6C_exit ; yes, return the handle
xchg ax,bx ; BX = handle, AX = action
test al,002h ; should we replace the file ?
mov ax,ED_EXISTS ; if not close and return error
jz f6C_close_on_error
mov ah,MS_X_WRITE
xor cx,cx ; write zero bytes to truncate file
call dos_entry
jc f6C_close_on_error ; on error AX = error code, return it
xchg ax,bx ; AX = handle
mov cx,3 ; CX = file replaced
f6C_exit:
jmp return_CX ; return CX to caller
f6C_close_on_error:
; File exits, but open should be failed (error code in AX)
push ax
mov ah,MS_X_CLOSE
call dos_entry ; close that file
pop ax
f6C_error:
jmp error_exit ; generate critical error
PCMODE_DATA DSEG WORD
extrn current_psp:word
extrn current_dsk:byte
extrn dma_offset:word
extrn dma_segment:word
extrn int21regs_ptr:dword
extrn last_drv:byte
extrn remote_call:word
if DELWATCH
extrn fdos_stub:dword
endif
GLOBAL_DATA dseg word
; When creating unique files we use the date/time to make the name.
; We add this seed value to "randomise" things, INCing on failure so the next
; attempt usually succeeds.
unique_name_seed dw 0 ; so we don't have to wait 1 second
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -