749 lines
20 KiB
NASM
749 lines
20 KiB
NASM
;
|
||
; system call entry points MSDOS
|
||
;
|
||
|
||
INCLUDE DOSSEG.ASM
|
||
|
||
CODE SEGMENT BYTE PUBLIC 'CODE'
|
||
ASSUME SS:DOSGROUP,CS:DOSGROUP
|
||
|
||
.xlist
|
||
.xcref
|
||
INCLUDE DOSSYM.ASM
|
||
INCLUDE DEVSYM.ASM
|
||
.cref
|
||
.list
|
||
|
||
|
||
i_need YEAR,WORD
|
||
i_need DAY,BYTE
|
||
i_need WeekDay,BYTE
|
||
i_need TimeBuf,6
|
||
i_need BCLOCK,DWORD
|
||
i_need DskErr,BYTE
|
||
i_need Attrib,BYTE
|
||
i_need Name1,BYTE
|
||
i_need Name2,BYTE
|
||
i_need Name3,BYTE
|
||
i_need DelAll,BYTE
|
||
i_need ThisDPB,DWORD
|
||
i_need CurBuf,DWORD
|
||
i_need LastEnt,WORD
|
||
i_need ThisDrv,BYTE
|
||
i_need DirStart,WORD
|
||
i_need DevPt,DWORD
|
||
i_need Creating,BYTE
|
||
i_need VolID,BYTE
|
||
i_need FoundDel,BYTE
|
||
|
||
SUBTTL DATE AND TIME - SYSTEM CALLS 42,43,44,45; S/G DATE,TIME
|
||
PAGE
|
||
procedure $GET_DATE,NEAR ;System call 42
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; None
|
||
; Function:
|
||
; Return current date
|
||
; Returns:
|
||
; Date in CX:DX
|
||
|
||
PUSH SS
|
||
POP DS
|
||
ASSUME DS:DOSGROUP
|
||
invoke READTIME ;Check for rollover to next day
|
||
MOV AX,[YEAR]
|
||
MOV BX,WORD PTR [DAY]
|
||
invoke get_user_stack ;Get pointer to user registers
|
||
ASSUME DS:NOTHING
|
||
MOV [SI.user_DX],BX ;DH=month, DL=day
|
||
ADD AX,1980 ;Put bias back
|
||
MOV [SI.user_CX],AX ;CX=year
|
||
MOV AL,BYTE PTR [WEEKDAY]
|
||
RET
|
||
$GET_DATE ENDP
|
||
|
||
procedure $SET_DATE,NEAR ;System call 43
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; CX:DX valid date
|
||
; Function:
|
||
; Set current date
|
||
; Returns:
|
||
; AL = -1 date bad, = 0 OK
|
||
|
||
MOV AL,-1 ;Be ready to flag error
|
||
SUB CX,1980 ;Fix bias in year
|
||
JC RET24 ;Error if not big enough
|
||
CMP CX,119 ;Year must be less than 2100
|
||
JA RET24
|
||
OR DH,DH
|
||
JZ RET24
|
||
OR DL,DL
|
||
JZ RET24 ;Error if either month or day is 0
|
||
CMP DH,12 ;Check against max. month
|
||
JA RET24
|
||
PUSH SS
|
||
POP DS
|
||
ASSUME DS:DOSGROUP
|
||
invoke DODATE
|
||
RET24: RET
|
||
$SET_DATE ENDP
|
||
|
||
procedure $GET_TIME,NEAR ;System call 44
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; None
|
||
; Function:
|
||
; Get current time
|
||
; Returns:
|
||
; Time in CX:DX
|
||
|
||
PUSH SS
|
||
POP DS
|
||
ASSUME DS:DOSGROUP
|
||
invoke READTIME
|
||
invoke get_user_stack ;Get pointer to user registers
|
||
MOV [SI.user_DX],DX
|
||
MOV [SI.user_CX],CX
|
||
XOR AL,AL
|
||
RET26: RET
|
||
$GET_TIME ENDP
|
||
|
||
procedure $SET_TIME,NEAR ;System call 45
|
||
;Time is in CX:DX in hours, minutes, seconds, 1/100 sec.
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; CX:DX = Time
|
||
; Function:
|
||
; Set time
|
||
; Returns:
|
||
; AL = -1 time bad, = 0 OK
|
||
|
||
MOV AL,-1 ;Flag in case of error
|
||
CMP CH,24 ;Check hours
|
||
JAE RET26
|
||
CMP CL,60 ;Check minutes
|
||
JAE RET26
|
||
CMP DH,60 ;Check seconds
|
||
JAE RET26
|
||
CMP DL,100 ;Check 1/100's
|
||
JAE RET26
|
||
PUSH CX
|
||
PUSH DX
|
||
PUSH SS
|
||
POP DS
|
||
ASSUME DS:DOSGROUP
|
||
MOV BX,OFFSET DOSGROUP:TIMEBUF
|
||
MOV CX,6
|
||
XOR DX,DX
|
||
MOV AX,DX
|
||
PUSH BX
|
||
invoke SETREAD
|
||
ASSUME ES:DOSGROUP
|
||
PUSH DS
|
||
LDS SI,[BCLOCK]
|
||
ASSUME DS:NOTHING
|
||
invoke DEVIOCALL2 ;Get correct day count
|
||
POP DS
|
||
ASSUME DS:DOSGROUP
|
||
POP BX
|
||
invoke SETWRITE
|
||
POP WORD PTR [TIMEBUF+4]
|
||
POP WORD PTR [TIMEBUF+2]
|
||
LDS SI,[BCLOCK]
|
||
ASSUME DS:NOTHING
|
||
invoke DEVIOCALL2 ;Set the time
|
||
XOR AL,AL
|
||
RET
|
||
$SET_TIME ENDP
|
||
|
||
SUBTTL DISK R/W ROUTINES
|
||
PAGE
|
||
procedure $FCB_SEQ_READ,NEAR ; System call 20
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX Points to openned FCB
|
||
; Function:
|
||
; Read next record from file to disk transfer address
|
||
; Returns:
|
||
; AL = 1 EOF record is empty
|
||
; AL = 3 EOF record is partial zero filled
|
||
; AL = 2 No room at disk transfer address
|
||
; AL = 0 All OK
|
||
|
||
invoke GETREC
|
||
invoke LOAD
|
||
JMP SHORT FINSEQ
|
||
|
||
entry $FCB_SEQ_WRITE ; System call 21
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX Points to openned FCB
|
||
; Function:
|
||
; Write next record to file from disk transfer address
|
||
; Returns:
|
||
; AL = 1 Disk full
|
||
; AL = 2 No room in disk transfer segment
|
||
; AL = 0 All OK
|
||
|
||
invoke GETREC
|
||
invoke STORE
|
||
FINSEQ:
|
||
JCXZ SETNREX
|
||
ADD AX,1
|
||
ADC DX,0
|
||
JMP SHORT SETNREX
|
||
|
||
entry $FCB_RANDOM_READ ; System call 33
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX Points to openned FCB
|
||
; Function:
|
||
; Read record addressed by random record field from file to
|
||
; disk transfer address
|
||
; Returns:
|
||
; AL = 1 EOF record is empty
|
||
; AL = 3 EOF record is partial zero filled
|
||
; AL = 2 No room at disk transfer address
|
||
; AL = 0 All OK
|
||
|
||
invoke GETRRPOS1
|
||
invoke LOAD
|
||
JMP SHORT FINRND
|
||
|
||
entry $FCB_RANDOM_WRITE ; System call 34
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX Points to openned FCB
|
||
; Function:
|
||
; Write record addressed by random record field to file from
|
||
; disk transfer address
|
||
; Returns:
|
||
; AL = 1 Disk full
|
||
; AL = 2 No room in disk transfer segment
|
||
; AL = 0 All OK
|
||
|
||
invoke GETRRPOS1
|
||
invoke STORE
|
||
JMP SHORT FINRND
|
||
|
||
entry $FCB_RANDOM_READ_BLOCK ; System call 39
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX Points to openned FCB
|
||
; CX = Record count
|
||
; Function:
|
||
; Read CX records starting at random record field from file
|
||
; to disk transfer address
|
||
; Returns:
|
||
; AL = 1 EOF record is empty
|
||
; AL = 3 EOF record is partial zero filled
|
||
; AL = 2 No room at disk transfer address
|
||
; AL = 0 All OK
|
||
; CX = Actual number of records read
|
||
|
||
invoke GETRRPOS
|
||
invoke LOAD
|
||
JMP SHORT FINBLK
|
||
|
||
entry $FCB_RANDOM_WRITE_BLOCK ; System call 40
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX Points to openned FCB
|
||
; CX = Record count
|
||
; Function:
|
||
; Write CX records starting at random record field to file
|
||
; from disk transfer address
|
||
; If CX = 0 File is set to length determined from random record field
|
||
; Returns:
|
||
; AL = 1 Disk full
|
||
; AL = 2 No room in disk transfer segment
|
||
; AL = 0 All OK
|
||
; CX = Actual number of records written
|
||
|
||
invoke GETRRPOS
|
||
invoke STORE
|
||
FINBLK:
|
||
invoke get_user_stack
|
||
MOV [SI.user_CX],CX
|
||
entry FINNOSAV
|
||
JCXZ FINRND
|
||
ADD AX,1
|
||
ADC DX,0
|
||
FINRND:
|
||
MOV WORD PTR ES:[DI.fcb_RR],AX
|
||
MOV ES:[DI.fcb_RR+2],DL
|
||
OR DH,DH
|
||
JZ SETNREX
|
||
MOV ES:[DI.fcb_RR+3],DH ; Save 4 byte of RECPOS only if significant
|
||
SETNREX:
|
||
MOV CX,AX
|
||
AND AL,7FH
|
||
MOV ES:[DI.fcb_NR],AL
|
||
AND CL,80H
|
||
SHL CX,1
|
||
RCL DX,1
|
||
MOV AL,CH
|
||
MOV AH,DL
|
||
MOV ES:[DI.fcb_EXTENT],AX
|
||
MOV AL,BYTE PTR [DSKERR]
|
||
RET4:
|
||
RET
|
||
$FCB_SEQ_READ ENDP
|
||
|
||
SUBTTL $FCB_DELETE -- SYSTEM CALL 19
|
||
PAGE
|
||
procedure $FCB_DELETE,NEAR ; System call 19
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX point to unopened FCB
|
||
; Function:
|
||
; Delete all matching entries
|
||
; Returns:
|
||
; AL = -1 if no entries matched, otherwise 0
|
||
|
||
invoke MOVNAME
|
||
ASSUME ES:DOSGROUP
|
||
MOV AL,-1
|
||
MOV BYTE PTR [FoundDel],AL
|
||
JC RET4
|
||
MOV AL,BYTE PTR [ATTRIB]
|
||
AND AL,attr_hidden+attr_system+attr_directory+attr_volume_id+attr_read_only
|
||
; Look only at hidden bits
|
||
CMP AL,attr_hidden+attr_system+attr_directory+attr_volume_id+attr_read_only
|
||
; All must be set
|
||
JNZ NOTALL
|
||
MOV CX,11
|
||
MOV AL,"?"
|
||
MOV DI,OFFSET DOSGROUP:NAME1
|
||
REPE SCASB ; See if name is *.*
|
||
JNZ NOTALL
|
||
MOV BYTE PTR [DELALL],0 ; DEL *.* - flag deleting all
|
||
NOTALL:
|
||
invoke FINDNAME
|
||
ASSUME DS:DOSGROUP
|
||
MOV AL,-1
|
||
JC RET4
|
||
OR AH,AH ; Check if device name
|
||
JS RET4 ; Can't delete I/O devices
|
||
DELFILE:
|
||
LES BP,[THISDPB]
|
||
MOV AH,BYTE PTR [DELALL]
|
||
PUSH DS
|
||
LDS DI,[CURBUF]
|
||
ASSUME DS:NOTHING
|
||
TEST [Attrib],attr_read_only ; are we deleting RO files too?
|
||
JNZ DoDelete ; yes
|
||
TEST DS:[BX.dir_attr],attr_read_only
|
||
JZ DoDelete ; not read only
|
||
POP DS
|
||
JMP SHORT DelNxt
|
||
DoDelete:
|
||
MOV BYTE PTR [FoundDel],0
|
||
MOV [DI.BUFDIRTY],1
|
||
MOV BYTE PTR [BX],AH
|
||
MOV BX,[SI]
|
||
POP DS
|
||
ASSUME DS:DOSGROUP
|
||
OR BX,BX
|
||
JZ DELNXT
|
||
CMP BX,ES:[BP.dpb_max_cluster]
|
||
JA DELNXT
|
||
invoke RELEASE
|
||
DELNXT:
|
||
invoke GETENTRY ; Registers need to be reset
|
||
invoke NEXTENT
|
||
JNC DELFILE
|
||
CALL FLUSHRET1
|
||
MOV AL,BYTE PTR [FoundDel]
|
||
RET
|
||
|
||
$FCB_DELETE ENDP
|
||
|
||
SUBTTL $FCB_RENAME -- SYSTEM CALL 23; RENAME FILES
|
||
PAGE
|
||
ERRETJ: JMP ERRET
|
||
|
||
procedure $FCB_RENAME,NEAR ; System call 23
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX point to a modified FCB (DS:DX+11H points to destination
|
||
; name)
|
||
; Function:
|
||
; Rename all matching entries to indicated name
|
||
; Returns:
|
||
; AL = -1 if no entries matched, otherwise 0
|
||
|
||
invoke MOVNAME
|
||
ASSUME ES:DOSGROUP
|
||
JC ERRETJ
|
||
ADD SI,5
|
||
MOV DI,OFFSET DOSGROUP:NAME2
|
||
invoke LODNAME
|
||
JC ERRETJ ; Report error if second name invalid
|
||
invoke FINDNAME
|
||
ASSUME DS:DOSGROUP
|
||
JC ERRETJ
|
||
OR AH,AH ; Check if I/O device name
|
||
JS ERRETJ ; If so, can't rename it
|
||
MOV SI,OFFSET DOSGROUP:NAME1
|
||
MOV DI,OFFSET DOSGROUP:NAME3
|
||
MOV CX,13
|
||
REP MOVSB ; Copy name to search for --include attribute byte
|
||
RENFIL:
|
||
MOV DI,OFFSET DOSGROUP:NAME1
|
||
MOV SI,OFFSET DOSGROUP:NAME2
|
||
MOV CX,11
|
||
NEWNAM:
|
||
LODSB
|
||
CMP AL,"?"
|
||
JNZ NOCHG
|
||
PUSH DS
|
||
MOV DS,WORD PTR [CURBUF+2]
|
||
MOV AL,[BX]
|
||
POP DS
|
||
NOCHG:
|
||
STOSB
|
||
INC BX
|
||
LOOP NEWNAM
|
||
INC DI
|
||
MOV BYTE PTR [DI],attr_all ;Sets ATTRIB
|
||
; Stop duplicates with any attributes
|
||
invoke DEVNAME ; Check if giving it a device name
|
||
JNC RENERR
|
||
XOR AX,AX
|
||
PUSH [LASTENT]
|
||
invoke FINDENTRY ; See if new name already exists
|
||
POP AX
|
||
JNC RENERR ; Error if found
|
||
LES BP,[THISDPB]
|
||
invoke GETENT ; Re-read matching entry
|
||
MOV DI,BX ; Leave BX,DX until call to NEXTENT
|
||
MOV ES,WORD PTR [CURBUF+2]
|
||
MOV SI,OFFSET DOSGROUP:NAME1
|
||
MOV CX,11
|
||
REP MOVSB ; Replace old name with new one
|
||
MOV DI,WORD PTR [CURBUF]
|
||
MOV ES:[DI.BUFDIRTY],1 ; Directory changed
|
||
PUSH SS
|
||
POP ES
|
||
MOV SI,OFFSET DOSGROUP:NAME3
|
||
MOV DI,OFFSET DOSGROUP:NAME1
|
||
MOV CX,13 ; Include attribute byte
|
||
REP MOVSB ; Copy name back into search buffer
|
||
invoke NEXTENT
|
||
JNC RENFIL
|
||
JMP FLUSHRET1
|
||
|
||
RENERR:
|
||
CALL FLUSHRET1
|
||
ERRET:
|
||
MOV AL,-1
|
||
RET
|
||
$FCB_RENAME ENDP
|
||
|
||
SUBTTL $FCB_OPEN -- SYSTEM CALL 15; OPEN A FILE
|
||
PAGE
|
||
procedure $FCB_OPEN,NEAR ; System call 15
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX point to an unopened FCB
|
||
; Function:
|
||
; Open indicated file and fill in FCB
|
||
; Returns:
|
||
; AL = -1 if no entries matched, otherwise 0
|
||
; FOR INTERNAL USE
|
||
; [CURBUF+2]:SI and [CURBUF+2]:BX Preserved
|
||
|
||
invoke GETFILE
|
||
ASSUME DS:DOSGROUP,ES:NOTHING
|
||
|
||
entry DOOPEN
|
||
|
||
; Enter here to perform $FCB_OPEN on file already found
|
||
; in directory. AH=device ID number, DS=CS, BX points to directory
|
||
; entry in [CURBUF], SI points to First Cluster field, and
|
||
; ES:DI point to the FCB to be opened. This entry point
|
||
; is used by $FCB_CREATE.
|
||
JC ERRET
|
||
PUSH SI
|
||
PUSH AX ; Save I/O driver number
|
||
XOR AL,AL
|
||
OR AH,AH
|
||
JS OPENDEV
|
||
MOV AL,[THISDRV]
|
||
MOV DS,WORD PTR [CURBUF+2]
|
||
ASSUME DS:NOTHING
|
||
INC AX
|
||
OPENDEV:
|
||
STOSB
|
||
XOR AX,AX
|
||
IF ZEROEXT
|
||
ADD DI,11
|
||
STOSW ; Zero low byte of extent field if ZERPEXT only
|
||
ELSE
|
||
ADD DI,12 ; Point to high half of CURRENT BLOCK field
|
||
STOSB ; Set it to zero (CP/M programs set low byte)
|
||
ENDIF
|
||
MOV AL,128 ; Default record size
|
||
STOSW ; Set record size
|
||
LODSW ; Get starting cluster
|
||
MOV DX,AX ; Save it for the moment
|
||
MOVSW ; Transfer size to FCB
|
||
MOVSW
|
||
MOV AX,[SI-8] ; Get date
|
||
STOSW ; Save date in FCB
|
||
MOV AX,[SI-10] ; Get time
|
||
STOSW ; Save it in FCB
|
||
POP AX ; Restore I/O driver number
|
||
POP SI
|
||
MOV AL,AH
|
||
OR AL,40H ; Not dirty
|
||
STOSB
|
||
JS SAVDEVPT ; If device, go save pointer to it
|
||
MOV AX,DX ; Restore starting cluster
|
||
STOSW ; first cluster
|
||
PUSH AX ; save cluster
|
||
XOR AX,AX
|
||
STOSW ; clus pos
|
||
POP AX ; last cluster
|
||
STOSB
|
||
MOV AL,AH
|
||
MOV AH,BYTE PTR [DIRSTART]
|
||
PUSH CX
|
||
MOV CL,4
|
||
SHL AH,CL
|
||
OR AL,AH
|
||
STOSB
|
||
MOV AX,[DIRSTART]
|
||
MOV CL,4
|
||
SHL AX,CL
|
||
POP CX
|
||
MOV AL,AH
|
||
STOSB
|
||
OPEN_RET:
|
||
XOR AX,AX
|
||
RET
|
||
|
||
SAVDEVPT:
|
||
ASSUME DS:DOSGROUP
|
||
LDS AX,[DEVPT]
|
||
ASSUME DS:NOTHING
|
||
STOSW
|
||
MOV ES:[DI],DS
|
||
JMP SHORT OPEN_RET
|
||
$FCB_OPEN ENDP
|
||
|
||
SUBTTL $FCB_CLOSE -- SYSTEM CALL 16; CLOSE FILE
|
||
PAGE
|
||
procedure $FCB_CLOSE,NEAR ; System call 16
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX point to an opened FCB
|
||
; Function:
|
||
; Close the indicated file
|
||
; Returns:
|
||
; AL = -1 if disk has been changed, otherwise 0
|
||
|
||
MOV DI,DX
|
||
CMP BYTE PTR [DI],-1 ; Check for extended FCB
|
||
JNZ NORMFCB3
|
||
ADD DI,7
|
||
NORMFCB3:
|
||
TEST [DI.fcb_DEVID],devid_file_clean+devid_device
|
||
; Allow only dirty files
|
||
JNZ OKRET1 ; can't close I/O device or not written
|
||
invoke MOVNAMENOSET
|
||
JC BADCLOSE ; Bad file name
|
||
entry FCB_CLOSE_INNER
|
||
PUSH DX
|
||
PUSH DS
|
||
MOV SI,DX
|
||
MOV BX,[SI.fcb_LSTCLUS+1]
|
||
MOV CL,4
|
||
SHR BX,CL
|
||
PUSH BX
|
||
PUSH SS
|
||
POP DS
|
||
ASSUME DS:DOSGROUP
|
||
invoke FATREAD
|
||
POP BX
|
||
invoke SETDIRSRCH
|
||
invoke FINDENTRY
|
||
POP ES
|
||
POP DI
|
||
JC BADCLOSE
|
||
LDS BX,[CURBUF]
|
||
ASSUME DS:NOTHING
|
||
|
||
; note that SI points to dir_first...
|
||
|
||
OR BYTE PTR [SI-dir_first+dir_attr],attr_archive
|
||
MOV CX,ES:[DI.fcb_FIRCLUS]
|
||
MOV [SI-dir_first+dir_first],CX
|
||
MOV DX,ES:WORD PTR [DI.fcb_FILSIZ]
|
||
MOV [SI-dir_first+dir_size_l],DX
|
||
MOV DX,ES:WORD PTR [DI.fcb_FILSIZ+2]
|
||
MOV [SI-dir_first+dir_size_h],DX
|
||
MOV DX,ES:[DI.fcb_FDATE]
|
||
MOV [SI-dir_first+dir_date],DX
|
||
MOV DX,ES:[DI.fcb_FTIME]
|
||
MOV [SI-dir_first+dir_time],DX
|
||
MOV [BX.BUFDIRTY],1
|
||
PUSH SS
|
||
POP DS
|
||
ASSUME DS:DOSGROUP
|
||
FLUSHRET1:
|
||
LES BP,[THISDPB]
|
||
MOV AL,ES:[BP.dpb_drive]
|
||
invoke FLUSHBUF
|
||
OKRET1:
|
||
XOR AL,AL
|
||
RET
|
||
|
||
BADCLOSE:
|
||
MOV AL,-1
|
||
RET
|
||
$FCB_CLOSE ENDP
|
||
|
||
SUBTTL $FCB_CREATE -- SYSTEM CALL 22; MAKE AND OPEN A NEW FILE
|
||
PAGE
|
||
procedure $FCB_CREATE,NEAR ; System call 22
|
||
ASSUME DS:NOTHING,ES:NOTHING
|
||
|
||
; Inputs:
|
||
; DS:DX point to an unopened FCB
|
||
; Function:
|
||
; If file does not exist, create it and open it
|
||
; If file exists, free up its contents and open the file
|
||
; Returns:
|
||
; AL = -1 if file cannot be created, otherwise 0
|
||
|
||
invoke MOVNAME
|
||
ASSUME ES:DOSGROUP
|
||
JC ERRET3
|
||
MOV DI,OFFSET DOSGROUP:NAME1
|
||
MOV CX,11
|
||
MOV AL,"?"
|
||
REPNE SCASB
|
||
JZ ERRET3
|
||
MOV BYTE PTR [CREATING],-1
|
||
PUSH DX
|
||
PUSH DS
|
||
invoke FINDNAME
|
||
ASSUME DS:DOSGROUP
|
||
NWENTY:
|
||
LES BP,[THISDPB]
|
||
ASSUME ES:NOTHING
|
||
JNC EXISTENT
|
||
invoke BUILDDIR
|
||
JC ERRPOP
|
||
invoke GETENT ; Point at that free entry
|
||
JMP SHORT FREESPOT
|
||
ERRPOP:
|
||
POP DS
|
||
POP DX
|
||
ASSUME DS:NOTHING
|
||
ERRET3:
|
||
JMP SHORT BADCLOSE
|
||
|
||
entry NEWENTRY
|
||
POP DX ; Return address
|
||
POP ES ; ES
|
||
POP CX ; DI
|
||
PUSH DX
|
||
PUSH CX
|
||
PUSH ES
|
||
JMP NWENTY
|
||
|
||
EXISTENT:
|
||
ASSUME DS:DOSGROUP
|
||
JNZ ERRPOP ; Error if attributes don't match
|
||
OR AH,AH ; Check if file is I/O device
|
||
JS OPENJMP ; If so, no action
|
||
PUSH DS
|
||
LDS DI,[CURBUF]
|
||
ASSUME DS:NOTHING
|
||
MOV CX,[SI] ; Get pointer to clusters
|
||
MOV SI,[DI.BUFSECNO]
|
||
POP DS
|
||
ASSUME DS:DOSGROUP
|
||
JCXZ FREESPOT
|
||
CMP CX,ES:[BP.dpb_max_cluster]
|
||
JA FREESPOT
|
||
SUB BX,DI
|
||
PUSH BX
|
||
PUSH SI ; Save sector number
|
||
MOV BX,CX
|
||
invoke RELEASE ; Free any data already allocated
|
||
POP DX
|
||
XOR AL,AL
|
||
invoke GETBUFFR
|
||
POP BX
|
||
ADD BX,WORD PTR [CURBUF]
|
||
FREESPOT:
|
||
TEST BYTE PTR [ATTRIB],attr_volume_id
|
||
JZ NOTVOLID
|
||
CMP BYTE PTR [VOLID],0
|
||
JNZ ERRPOP ; Can't create a second volume ID
|
||
NOTVOLID:
|
||
MOV ES,WORD PTR [CURBUF+2]
|
||
MOV DI,BX
|
||
MOV SI,OFFSET DOSGROUP:NAME1
|
||
MOV CX,5
|
||
MOVSB
|
||
REP MOVSW
|
||
MOV AL,[ATTRIB]
|
||
STOSB
|
||
MOV CL,5
|
||
XOR AX,AX
|
||
REP STOSW
|
||
invoke DATE16
|
||
XCHG AX,DX
|
||
STOSW
|
||
XCHG AX,DX
|
||
STOSW
|
||
XOR AX,AX
|
||
PUSH DI
|
||
STOSW
|
||
STOSW
|
||
STOSW
|
||
MOV SI,WORD PTR [CURBUF]
|
||
MOV ES:[SI.BUFDIRTY],1
|
||
LES BP,[THISDPB]
|
||
MOV AL,ES:[BP.dpb_drive]
|
||
PUSH AX
|
||
PUSH BX
|
||
invoke FLUSHBUF
|
||
POP BX
|
||
POP AX
|
||
POP SI
|
||
MOV AH,AL ; Get I/O driver number back
|
||
OPENJMP:
|
||
CLC ; Clear carry so OPEN won't fail
|
||
POP ES
|
||
POP DI
|
||
ASSUME ES:NOTHING
|
||
JMP DOOPEN
|
||
$FCB_CREATE ENDP
|
||
|
||
do_ext
|
||
|
||
CODE ENDS
|
||
END
|
||
|
||
|