Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

DOS_FIL.ASM

Obsluha souborů

Nedokončeno...


; ============================================================================
;
;                            MicroDOS - Files
;
; ============================================================================

MAXFILES	EQU	20		; total maximum number of open files
NAMELEN		EQU	8		; file name length
EXTLEN		EQU	3		; file extension length
FILENAMELEN	EQU	NAMELEN+EXTLEN	; file name length with extension

DELETED		EQU	0E5h		; flag - deleted file

; ------------- Device handles

DEV_CON		EQU	0		; CON
DEV_AUX		EQU	1		; AUX, COM1
DEV_PRN		EQU	2		; PRN, LPT1
DEV_NUL		EQU	3		; NUL

; ------------- Unopen File Control Block, UFCB

struc		UFCB

UFCB_Disk:	resb	1		; 0: disk number (0=default, 1=A:, ...)
UFCB_Name:	resb	NAMELEN		; 1: blank-padded file name
UFCB_Ext:	resb	EXTLEN		; 9: blank-padded file extension
UFCB_Cluster:	resw	1		; 0ch: current cluster number
UFCB_RecSize:	resw	1		; 0eh: logical record size

endstruc

UFCB_SIZE	EQU	UFCB_size	; 10h = 16 bytes

; ------------- File Control Block, FCB

struc		FCB

FCB_Disk:	resb	1		; 0: disk number (0=default, 1=A:, ...)
FCB_Name:	resb	NAMELEN		; 1: blank-padded file name
FCB_Ext:	resb	EXTLEN		; 9: blank-padded file extension
FCB_Block:	resw	1		; 0Ch: current data block (128 records)
FCB_RecSize:	resw	1		; 0Eh: logical record size
FCB_Size:	resd	1		; 10h: file size
FCB_Date:	resw	1		; 14h: date of last write
					;	bit 0-4: day
					;	bit 5-8: month
					;	bit 9-15: year - 1980
FCB_OpenPar:				; - for devices it contains device ID
					; - for files it contains Root index
FCB_Time:	resw	1		; 16h: time of last write (unused)
					;	bit 0-4: second/2
					;	bit 5-10: minute
					;	bit 11-15: hour
FCB_Start:	resw	1		; 18h: internal,starting cluster number
FCB_Current:	resw	1		; 1Ah: internal,current custer number
FCB_CurRel:	resw	1		; 1Ch: internal, relat. cluster in file
FCB_Modi:	resb	1		; 1Eh: internal, 1=file modified
		resb	1
FCB_RecBlock:	resb	1		; 20h: record within current data block
					;	0 to 127

endstruc

FCB_SIZE	EQU	FCB_size	; 21h = 33 bytes

; ------------- Extended File Control Block, XFCB

struc		XFCB

XFCB_Sign:	resb	1		; 0: 0ffh signature to XFCB
		resb	5		; 1: ...reserved
XFCB_Attr:	resb	1		; 6: file attributes
XFCB_FCB:	resb	FCB_SIZE	; 7: standard FCB

endstruc

XFCB_SIZE	EQU	XFCB_size	; 28h = 40 bytes

; ------------- Open mode

OPEN_MASK	EQU	B0+B1+B2	; access mode mask
OPEN_RO		EQU	0		; read only
OPEN_WO		EQU	1		; write only
OPEN_RW		EQU	2		; read/write

; ------------- DOS Directory Entry, DIR

struc		DIR

DIR_Name:	resb	NAMELEN		; 0: blank-padded file name
					;	first character is set to:
					;	- 0e5h for deleted entry
					;	- 0 for unused entry
DIR_Ext:	resb	EXTLEN		; 8: blank-padded file extension
DIR_Attrib:	resb	1		; 0Bh: attributes (see File attributes)
		resb	10		; 0Ch: ...reserved
DIR_Time:	resw	1		; 16h: time of last write
					;	bit 0-4: second/2
					;	bit 5-10: minute
					;	bit 11-15: hour
DIR_Date:	resw	1		; 18h: date of last write
					;	bit 0-4: day
					;	bit 5-8: month
					;	bit 9-15: year - 1980
DIR_Cluster:	resw	1		; 1Ah: starting cluster number
DIR_Size:	resd	1		; 1Ch: file size

endstruc

DIR_SIZE	EQU	DIR_size	; 20h = 32 bytes

; ------------- File attributes

ATR_RO		EQU	B0		; read-only
ATR_HID		EQU	B1		; hidden
ATR_SYS		EQU	B2		; system
ATR_VOL		EQU	B3		; volume label
;ATR_DIR	EQU	B4		; directory (unused)
;ATR_ARC	EQU	B5		; archive (unused)

; ----------------------------------------------------------------------------
;                             Open FCB file
; ----------------------------------------------------------------------------
; INPUT:	SS:BP = disk DDPB
;		BL = flag, 0=first file, 1=next file
; OUTPUT:	CY = error
;		DS = data segment
;		BX = device file handle, if BH = 0ffh
;			else pointer to Root directory entry
;		DS:SI = file starting cluste number
; ----------------------------------------------------------------------------

; ------------- Push registers

OpenFCB:	push	ax		; push AX
		push	cx		; push CX
		push	di		; push DI
		push	es		; push ES

; ------------- Prepare registers

		push	cs		; push CS
		pop	ds		; DS <- CS
		push	cs		; push CS
		pop	es		; ES <- CS

; ------------- Find next file

		or	bl,bl		; find next file?
		jnz	OpenFCB2	; find next file

; ------------- Check if it is reserved device (-> BX device handle)

		call	CheckDev	; check device
		jnc	OpenFCB8	; it is device

; ------------- Read FAT table from disk

		call	ReadFAT		; read FAT table

; ------------- Prepare first Root entry

		mov	word [RootIndex],-1 ; index of current Root entry
OpenFCB2:	call	GetNextRoot	; get next Root entry
		jc	OpenFCB8	; no Root entry

; ------------- Is this entry deleted?

		cmp	byte [bx],DELETED ; is this entry deleted?
		je	OpenFCB2	; delete entry

; ------------- Compare filename

		mov	si,bx		; SI <- filename in Root entry
		mov	di,CurFilename	; DI <- FCB filename
		mov	cx,FILENAMELEN	; CX <- length of filename
		cld			; direction up
OpenFCB3:	repe	cmpsb		; compare filename
		je	OpenFCB4	; filename equals
		cmp	byte [di-1],"?"	; substitute character?
		je	OpenFCB3	; this character is OK
		jmp	short OpenFCB2	; next Root entry

; ------------- Check file attributes

OpenFCB4:	mov	al,[CurAttrib]	; AL <- required attributes
		not	al		; AL <- attribute mask
		and	al,[si]		; test attribute
		add	si,DIR_Cluster-DIR_Attrib ; skip to cluster number
		and	ah,ATR_HID | ATR_SYS ; system file?
		jz	OpenFCB8	; no system file, ok
		cmp	byte [OpenHidSys],0 ; open HID and SYS files?
		je	OpenFCB2	; no, search next file

; ------------- Pop registers

OpenFCB8:	pop	es		; pop ES
		pop	di		; pop DI
		pop	cx		; pop CX
		pop	ax		; pop AX
		ret

; ----------------------------------------------------------------------------
;                        Parse and open FCB file
; ----------------------------------------------------------------------------
; INPUT:	DS:DX = FCB or XFCB
; OUTPUT:	CY = error
;		SS:BP = DDPB of the disk
;		DS = data segment
;		BX = device file handle, if BH = 0ffh
;			else pointer to Root directory entry
;		DS:SI = starting cluster number
; ----------------------------------------------------------------------------

; ------------- Check and parse FCB

ParseOpenFCB:	call	LoadFCB		; check and parse FCB
		jc	ParseOpenFCB4	; error

; ------------- Read FCB from directory

		mov	bl,0		; flag, open first FCB
		call	OpenFCB		; open FCB file
ParseOpenFCB4:	ret

; ----------------------------------------------------------------------------
;                    Parse and open FCB file with ES:DI
; ----------------------------------------------------------------------------
; INPUT:	DS:DX = FCB or XFCB
; OUTPUT:	CY = error
;		ES:DI = original FCB (not XFCB)
;		SS:BP = DDPB of the disk
;		DS = data segment
;		BX = device file handle, if BH = 0ffh
;			else pointer to Root directory entry
;		DS:SI = starting cluster number
; ----------------------------------------------------------------------------

ParseOpenFCBX:	push	dx		; push DX
		push	ds		; push DS
		call	ParseOpenFCB	; parse and open FCB
		pop	es		; ES <- original DS
		pop	di		; DI <- original DI

ParseOpenKorig:	pushf			; push flags
		cmp	byte [es:di],0ffh ; is it extended FCB?
		jne	ParseOpenFCBX2	; it is not extended FCB
		add	di,byte 7	; DI <- normal FCB
ParseOpenFCBX2:	popf			; pop flags
		ret

; ----------------------------------------------------------------------------
;               Int 21h, function 0Fh - open file using FCB
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 0Fh (function code)
;		DS:DX = unopened FCB
; INT21 OUTPUT:	AL = status
;			00h: successful
;			0ffh: file not found
; ----------------------------------------------------------------------------

; ------------- Find file FCB

Int210F:	call	ParseOpenFCBX	; parse and open FCB file
		jc	Int210F9	; error, file not found

; ------------- Check if it is a device

Int210FNew:	cmp	bh,0ffh		; is it a device?
		jne	Int210F2	; it is not device
		mov	[es:di+FCB_OpenPar],bx ; store device ID
		mov	al,0		; AL <- 0, status OK
		ret

; ------------- Filling up file informations

Int210F2:	cld			; direction up
		mov	al,[bp+DDPB_disk] ; AL <- disk drive
		stosb			; store disk drive
		add	di,FILENAMELEN	; skip filename
		xor	ax,ax		; AX <- 0
		stosw			; clear current cluster number
		mov	al,80h		; AX <- 80h, default record size
		stosw			; set default record size
		lodsw			; AX <- starting cluster number
		push	ax		; push starting cluster number
		movsw			; file size LOW
		movsw			; file size HIGH
		mov	ax,[si-8]	; AX <- date of last write
		stosw			; set date of last write
		mov	ax,[RootIndex]	; AX <- index of Root entry
		stosw			; set index of Root entry
		pop	ax		; AX <- starting cluster number
		stosw			; set starting cluster number
		stosw			; set current cluster number
		xor	ax,ax		; AX <- 0
		stosw			; set current cluster in file
		stosb			; flag, file not modified
		ret

Int210F9:	mov	al,0ffh		; error flag
		ret

; ----------------------------------------------------------------------------
;               Int 21h, function 10h - close file using FCB
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 10h (function code)
;		DS:DX = opened FCB
; INT21 OUTPUT:	AL = status
;			00h: successful
;			0ffh: failed
; ----------------------------------------------------------------------------

; ------------- Skip extended header

Int2110:	mov	di,dx		; DI <- FCB
		cmp	byte [di],0ffh	; is it extended FCB?
		jne	Int21102	; it is not extended FCB
		add	di,byte 7	; skip extended header

; ------------- Check if it is device

Int21102:	cmp	byte [di+FCB_OpenPar+1],0ffh ; is it device?
		je	Int21107	; it is device

; ------------- Check if the file is modified

		cmp	byte [di+FCB_Modi],0 ; is file modified?
		je	Int21107	; it is not modified

; ------------- Get DDPB disk table (-> SS:BP)

		mov	al,[di+FCB_Disk]; AL <- disk number
		call	GetDDPB		; get DDPB disk table
		jc	Int21109	; error, invalid disk drive

; ------------- Check if data buffer is modified

		mov	al,[bp+DDPB_disk] ; AL <- disk
		mov	ah,1		; flag - buffer is modified
		cmp	ax,[cs:DataDiskModi] ; is buffer modified?
		jne	Int21104	; buffer is not modified

; ------------- Write data buffer to disk

		call	WriteData	; write data buffer to disk

; ------------- Open file Root entry

Int21104:	call	ParseOpenFCBX	; open file Root entry
                jc	Int21108	; error

; ------------- Check Root index (if file is property opened)

		mov	ax,[es:di+FCB_OpenPar] ; Root index
		cmp	ax,[cs:RootIndex] ; check Root index
		jne	Int21108	; invalid Root index
	
; ------------- Transfer new parameters

		mov	ax,[es:di+FCB_Start] ; AX <- starting cluster number
		mov	[si],ax		; store starting cluster number
		mov	ax,[es:di+FCB_Size] ; AX <- file size LOW
		mov	[si+2],ax	; store file size LOW
		mov	ax,[es:di+FCB_Size+2] ; AX <- file size HIGH
		mov	[si+4],ax	; store file size LOW
		mov	ax,[es:di+FCB_Date] ; AX <- date of last write
		mov	[si-2],ax	; store date of last write

; ------------- Write Root buffer to disk

		call	ModiWriteRoot	; modify and write Root to disk

; ------------- Write FAT table to disk

		call	WriteFAT	; write FAT table to disk

; ------------- Result OK

Int21107:	mov	al,0		; status OK
		ret

; ------------- Error, clear FAT modified flag

Int21108:	mov	byte [bp+DDPB_modi],0 ; clear FAT buffer modified flag
Int21109:	mov	al,0ffh		; error flag
		ret

; ----------------------------------------------------------------------------
;               Int 21h, function 13h - delete file using FCB
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 13h (function code)
;		DS:DX = unopened FCB ('?' wildcards allowed)
; INT21 OUTPUT:	AL = status
;			00h: one or more files successfully deleted
;			0ffh: no matching files or all were read-only
; ----------------------------------------------------------------------------

; ------------- Find file FCB

Int2113:	call	ParseOpenFCB	; parse and open FCB file
		mov	al,0ffh		; AL <- 0ffh error flag
		jc	Int21138	; error

; ------------- Check if it is device file (CON, AUX, ...)

		cmp	al,bh		; is it device file?
		je	Int21138	; it is device file

; ------------- Delete directory entry

Int21132:	mov	byte [bx],DELETED ; delete directory entry

; ------------- Prepare first cluster number

		mov	bx,[si]		; BX <- first cluster number
		or	bx,bx		; is it free cluster?
		jz	Int21136	; it is free cluster
		cmp	bx,[bp+DDPB_maxclust] ; check cluster number
		ja	Int21136	; invalid cluster, end of chain

; ------------- Free cluster chain

		call	FreeChain	; free cluster chain

; ------------- Find next FCB file

Int21136:       mov	bl,1		; flag, open next FCB
		call	OpenFCB		; open next FCB file
		jnc	Int21132	; next file OK

; ------------- Write FAT to disk

		call	WriteFAT	; write FAT to disk

; ------------- Modify and write Root to disk

		call	ModiWriteRoot	; modify and write Root to disk
		mov	al,0		; AL <- 0 status, operation OK
Int21138:	ret

; ----------------------------------------------------------------------------
;                     Get record number from opened FCB
; ----------------------------------------------------------------------------
; INPUT:	DS:DX = opened FCB
; OUTPUT:	CX = 1 (number of records)
;		DX:AX = record number
;		DS:DI = normal FCB (not extended)
; ----------------------------------------------------------------------------

; ------------- Skip extended FCB header

GetRecord:	mov	di,dx		; DI <- FCB
		cmp	byte [di],0ffh	; is it extended FCB?
		jne	GetRecord2	; it is not extended FCB
		add	di,7		; skip to normal FCB

; ------------- Prepare record number

GetRecord2:	mov	al,[di+FCB_RecBlock] ; AL <- record within data block
		mov	dx,[di+FCB_Block]; DX <- current data block
		shl	al,1		; AL << 1 (prerotate, *2)
		shr	dx,1		; DX / 2, low bit -> CF
		rcr	al,1		; transfer low bit from DX >> AL
		mov	ah,dl		; AH <- DL
		mov	dl,dh		; DL <- DH
		mov	dh,0		; DH <- 0
		ret

; ----------------------------------------------------------------------------
;                        Prepare for file read/write
; ----------------------------------------------------------------------------
; INPUT:	CX = number of records
;		DX:AX = record number
;		DS:DI = normal FCB (not extended)
; OUTPUT:	CY = error
;		SS:BP = DDPB of the disk
;		DS = data segment
;		ES:DI = normal FCB (not extended)
;		CX = number of bytes
; DESTROYS:	AX, BX, DX, SI
; ----------------------------------------------------------------------------

; ------------- Prepare record size (-> BX)

PrepRW:		mov	bx,[di+FCB_RecSize] ; BX <- record size
		or	bx,bx		; use default record size?
		jnz	PrepRW1		; record size known
		mov	bl,80h		; BX <- 80h default record size
		mov	[di+FCB_RecSize],bx ; set default record size

; ------------- Prepare segment registers

PrepRW1:        push	ax		; push AX (record LOW)
		mov	al,[di+FCB_Disk] ; AL <- disk number
		push	ds		; push DS
		pop	es		; ES <- FCB segment
		push	cs		; push CS
		pop	ds		; DS <- CS

; ------------- Prepare DDPB disk table

		call	GetDDPB		; get DDPB disk table
		pop	ax		; pop AX
		jnc	PrepRW3		; disk is OK

; ------------- Error, invalid disk

		mov	byte [RWResult],4 ; error, invalid disk
PrepRW2:	xor	cx,cx		; CX <- 0 no data transfered
		stc			; set error flag
		ret

; ------------- Ignore highest byte of record number if record size >= 64

PrepRW3:	cmp	bx,byte 64	; is small record size?
		jb	PrepRW4		; small record size
		mov	dh,0		; else ignore highest byte of record

; ------------- Store parameters for operation

PrepRW4:	mov	byte [RWResult],0 ; set operation result OK
		mov	[RWRecords],cx	; store number of records
		mov	[RWRecord],ax	; store record number LOW
		mov	[RWRecord+2],dx	; store record number HIGH
		mov	[RWFCB],di	; store address of FCB
		mov	si,[DTA]	; offset of DTA
		mov	[RWAddr],si 	; store offset of DTA address
		mov	byte [RWDataOn],0 ; flag, don't transfer data

; ------------- Recalc record number to offset in file

		mov	si,dx		; SI <- record number HIGH
		mul	bx		; offset in file LOW
		mov	[RWFileOff],ax	; store offset in file LOW
		push	dx		; push offet in file HIGH
		xchg	ax,si		; AX <- record number HIGH
		mul	bx		; offset in file HIGH
		pop	si		; SI <- carry from offset LOW
		add	ax,si		; add carry from offset LOW
		mov	[RWFileOff+2],ax	; offset in file HIGH
		adc	dx,byte 0	; carry HIGH
		jz	PrepRW7		; data OK

; ------------- Error, no data

PrepRW5:	mov	byte [RWResult],1 ; error, no data
PrepRW6:	jmp	short PrepRW2	

; ------------- Recalc offset in file to sector in file

PrepRW7:	xchg	ax,dx		; DX <- offset in file HIGH
		mov	ax,[RWFileOff]	; AX <- offset in file LOW
		mov	si,[bp+DDPB_sector] ; SI <- sector size
		cmp	dx,si		; would be overflow?
		jae	PrepRW5		; error, overflow
		div	si		; recalc to sector number
		mov	[RWFileSect],ax	; store sector in file
		mov	[RWSectOff],dx	; store offset in sector

; ------------- Recalc sector in file to cluster in file

		mov	si,ax		; SI <- sector in file
		and	al,[bp+DDPB_maxsect] ; mask sector in cluster
		mov	[RWClustSect],al ; sector in cluster
		mov	ax,cx		; AX <- number of records
		mov	cl,[bp+DDPB_shifts] ; CL <- shift count
		shr	si,cl		; SI <- cluster in file
		mov	[RWFileClust],si ; store cluster in file

; ------------- Check DTA address

		mul	bx		; recalc records to bytes
		mov	cx,ax		; CX <- store lenght of data
		mov	si,[DTA]	; SI <- offset in DTA buffer
		add	ax,si		; add offset in DTA buffer
		adc	dx,byte 0	; overflow
		jz	PrepRW9		; no overflow over segment boundary
		mov	byte [RWResult],2 ; error, segment overflow

; ------------- Limit data to segment boundary

		xchg	ax,si		; AX <- offset in DTA buffer
		neg	ax		; rest to 64 KB
		jnz	PrepRW8		; no overflow
		dec	ax		; limit data to 0ffffh
PrepRW8:	xor	dx,dx		; DX <- 0
		div	bx		; recalc data to records
		mov	[RWRecords],ax	; new number of records
		mul	bx		; recalc back to data size
		xchg	ax,cx		; CX <- number of bytes
		jcxz	PrepRW6		; error, no data remains

PrepRW9:	clc			; operation OK
		ret

; ----------------------------------------------------------------------------
;                            Read from file
; ----------------------------------------------------------------------------
; INPUT:	CX = number of records
;		DX:AX = record number
;		DS:DI = normal FCB (not extended)
; OUTPUT:
; ----------------------------------------------------------------------------

; ------------- Prepare for operation

ReadFile:	call	PrepRW		; prepare for operation
		jnc	ReadFile1	; ok
		ret			; error

; ------------- Check if it is a device

ReadFile1:	mov	bx,[es:di+FCB_OpenPar] ; BX <- device ID
		cmp	bh,0ffh		; is it device?
		jne	ReadFile2	; it is not device
		jmp	ReadDev		; read from device

ReadFile2:

ReadFileDevRet:

		ret


; ------------- Prepare to read from device

ReadDev:	push	es		; push ES (FCB segment)
		les	di,[DTA]	; ES:DI <- DTA address
		and	bx,byte 7fh	; is it console?
		jnz	ReadDev3	; it is not console

; ------------- Check if there are next data to read from console buffer

		mov	si,[RWConAddr]	; SI <- console buffer
		or	si,si		; there are next data?
		jnz	ReadDev25	; there are next data to read

; ------------- Initialize console input buffer

		cmp	byte [ConBuff],80h ; is console buffer initialized?
		je	ReadDev22	; buffer is initialized
		mov	word [ConBuff],0ff80h ; initialize buffer

; ------------- Read next line from console to buffer

ReadDev22:	push	cx		; push CX (number of bytes)
		push	di		; push DI (offset of buffer)
		push	es		; push ES (segment of buffer)
		mov	dx,ConBuff	; DX <- console input buffer
		call	Int210A		; read from console
		pop	es		; pop ES
		pop	di		; pop DI
		pop	cx		; pop CX

; ------------- Check if there any data in console buffer

		mov	si,ConBuff	; SI <- console buffer
		mov	al,EOF  	; AL <- EOF
		cmp	[si],al		; any valid data in buffer?
		jne	ReadDev25	; read data from console buffer

; ------------- Mark end of text

		cld			; direction up
		stosb			; store EOF character
		mov	al,LF		; AL <- LF character
		call	ConOutChar	; display character on console
		xor	si,si		; SI <- 0, no other data
		jmp	short ReadDev28

; ------------- Read next data from console buffer (ending with CR/LF)

ReadDev25:	cld			; direction up
ReadDev26:	lodsb			; AL <- load next character
		stosb			; store this character
		cmp	al,CR		; is it CR character?
		jne	ReadDev27	; it is not CR character
		mov	byte [si],LF	; next character will be LF
ReadDev27:	cmp	al,LF		; is it end of line?
		loopne	ReadDev26	; next character
		jnz	ReadDev28	; any data remain

; ------------- Prepare next data from konzole

		call	ConOutChar	; display character on console
		xor	si,si		; SI <- 0 no data left
		or	cx,cx		; any other data required?
		jnz	ReadDev22	; read next line from console
		inc	ax		; clear ZF
ReadDev28:	mov	[RWConAddr],si	; store new address of buffer
		jmp	short ReadDev4

; ------------- Read from AUX (COM1) port

ReadDev3:	dec	bx		; is it AUX device?
		jnz	ReadDev4	; it is not AUX device
ReadDev32:	call	Int2103		; read character from AUX/COM1
		cld			; direction up
		stosb			; store character
		cmp	al,EOF		; end of file?
		loopne	ReadDev32	; next character

; ------------- Read data from PRN and NUL (=no data to read)

ReadDev4:	mov	[RWAddr],di 	; next store address
		pop	es		; pop ES (FCB segment)
		jnz	ReadDev42	; there left any data
		mov	di,[RWFCB]	; DI <- FCB offset
		or	byte [es:di+FCB_OpenPar],80h ; change to NUL device
ReadDev42:	jmp	ReadFileDevRet

; ----------------------------------------------------------------------------
;             Int 21h, function 14h - sequential read from FCB file
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 14h (function code)
;		DS:DX = opened FCB
; INT21 OUTPUT:	AL = status
;			00h: successful
;			01h: end of file, no data
;			02h: segment wrap in DTA
;			03h: end of file, partial record read
;			04h: invalid disk
;		DTA (Disk Transfer Area) filled with record read from file
; ----------------------------------------------------------------------------
; NOTES:	- If a partial record was read, it is zero-padded to full size
; ----------------------------------------------------------------------------

; ------------- Get current record number

Int2114:	call	GetRecord	; get current record number

; ------------- Read from file

		call	ReadFile	; read from file


; ----------------------------------------------------------------------------
;             Int 21h, function 15h - sequential write to FCB file
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 15h (function code)
;		DS:DX = opened FCB
;		DTA (Disk Transfer Area) contains record to be written
; INT21 OUTPUT:	AL = status
;			00h: successful
;			01h: disk full
;			02h: segment wrap in DTA
;			04h: invalid disk
; ----------------------------------------------------------------------------

; ------------- Get current record number

Int2115:	call	GetRecord	; get current record number


; ----------------------------------------------------------------------------
;         Int 21h, function 16h - create or truncate file using FCB
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 16h (function code)
;		DS:DX = unopened FCB
; INT21 OUTPUT:	AL = status
;			00h: successful
;			0ffh: directory full or existing file is read-only
; ----------------------------------------------------------------------------

; ------------- Check and parse FCB

Int2116:	call	LoadFCB		; check and parse FCB
		jc	Int21165	; error

; ------------- Check if filename contains wildcars

		push	cs		; push CS
		pop	es		; ES <- CS
		mov	al,"?"		; search wildcard character
		mov	di,CurFilename	; DI <- current filename
		mov	cx,FILENAMELEN	; CX <- length of filename
		repne	scasb		; find wildcard character
		je	Int21165	; error, no wildcards allowed

; ------------- Push original FCB

		push	dx		; push DX (FCB offset)
		push	ds		; push DS (FCB segment)

; ------------- Open existing file

		mov	byte [cs:OpenHidSys],1 ; open HID and SYS files
		mov	bl,0		; flag, open first FCB
		call	OpenFCB		; open FCB file
		jnc	Int21166	; file found, truncate it

; ------------- Read FAT table from disk

		call	ReadFAT		; read FAT table

; ------------- Find free Root entry

		mov	word [RootIndex],-1 ; index of current Root entry
Int21162:	call	GetNextRoot	; get next Root entry
		jc	Int21164	; error, no next entry
		cmp	byte [bx],0	; unused entry?
		je	Int21167	; found unused directory entry
		cmp	byte [bx],DELETED ; find free directory entry?
		jne	Int21162	; no free entry
		jmp	short Int21167

; ------------- Error

Int21164:	pop	ds		; pop DS
		pop	dx		; pop DX
Int21165:	mov	al,0ffh		; error flag
		ret

; ------------- Check if existing file is valid

Int21166:	cmp	bh,0ffh		; is it device?
                je	Int21168	; it is device, reopen it
                test	byte [bx+DIR_Attrib],ATR_RO ; is it read-only?
		jnz	Int21164	; file is read-only
		
; ------------- Truncate existing file

		mov	ax,[si]		; AX <- starting cluster
		or	ax,ax		; is any clulster?
		jz	Int21167	; file has no data
		cmp	ax,[bp+DDPB_maxclust] ; is it valid cluster?
		ja	Int21167	; end of file
		push	bx		; push BX
		xchg	ax,bx		; BX <- starting cluster
		call	FreeChain	; free cluster chain
		call	WriteFAT	; write FAT table to disk
		pop	bx		; pop BX

; ------------- Fill directory entry

Int21167:	mov	di,bx		; DI <- directory entry
		mov	si,CurFilename	; SI <- current filename
		mov	cx,FILENAMELEN	; CX <- length of filename
		rep	movsb		; copy filename
		mov	al,[CurAttrib]	; AL <- attributes
		stosb			; set attributes
		mov	al,0		; AL <- 0
		mov	cl,12		; CX <- 12 unused data
		rep	stosb		; clear unused data + time
		mov	ax,[FileDate]	; AX <- current date
		stosw			; set current date
		mov	al,0		; AL <- 0
		mov	cl,6		; CX <- 6
		rep	stosb		; clear cluster and file size

; ------------- Modify and write Root to disk

		call	ModiWriteRoot	; modify and write Root to disk

; ------------- Result OK - open file

Int21168:	pop	es		; pop ES (FCB segment)
		pop	di		; pop DI (FCB offset)
		call	ParseOpenKorig	; korig ED:DI (skip XFCB header)
		jmp	Int210FNew	; reopen new file

; ----------------------------------------------------------------------------
;               Int 21h, function 17h - rename file using FCB
; ----------------------------------------------------------------------------
; INT21 INPUT:	AH = 17h (function code)
;		DS:DX = modified FCB ('?' wildcards allowed)
;			- old filename is in the standard location
;			- new filename is on the 11h offset
; INT21 OUTPUT:	AL = status
;			00h: successfully renamed
;			0ffh: no matching files, read-only or already exists
; ----------------------------------------------------------------------------

; ------------- Check and parse FCB

Int2117:	call	LoadFCB		; check and parse FCB
		jc	Int21176	; error

; ------------- Parse second FCB

		add	si,5		; SI <- second filename in FCB
		mov	di,SecFilename	; DI <- buffer of second filename
		call	Load2FCB	; parse second FCB
		jc	Int21176	; error, invalid filename

; ------------- Find first FCB

		mov	bl,0		; flag, open first FCB
		call	OpenFCB		; open FCB file
		jc	Int21176	; error, file not found
		cmp	bh,0ffh		; is it device?
		je	Int21176	; error, it is device

; ------------- Push filename into temporary buffer

		push	cs		; push CS
		pop	es		; ES <- CS
		mov	cx,FILENAMELEN	; CX <- length of filename
		mov	si,CurFilename	; SI <- current filename
		mov	di,PushFilename	; DI <- push filename
		cld			; direction up
		rep	movsb		; store filename

; ------------- Assemble new filename

Int21172:	mov	cx,FILENAMELEN	; CX <- length of filename
		mov	di,CurFilename	; DI <- current filename
		mov	si,SecFilename	; SI <- second filename
Int21174:	lodsb			; load character
		cmp	al,"?"		; is it wildcard?
		jne	Int21175	; it is not wildcard
		mov	al,[bx]		; AL <- character of found filename
Int21175:	inc	bx		; increase filename pointer
		stosb			; store new character
		loop	Int21174	; next character

; ------------- Check, if it is now device name

		call	CheckDev	; check reserved device name
		jnc	Int21176	; error, it is device name

; ------------- Check, if such filename already exists

		push	word [RootIndex] ; push current Root index
		mov	word [RootIndex],-1 ; index of current Root entry
		mov	bl,1		; flag, open next FCB
		call	OpenFCB		; open FCB file
		pop	ax		; AX <- old Root index
		jc	Int21178	; ok, file not found

; ------------- Error

Int21176:	mov	al,0ffh		; AL <- 0ffh, error flag
		jmp	short Int21179

; ------------- Return old root entry

Int21178:	dec	ax		; previous Root index
		mov	[RootIndex],ax	; return old index
		call	GetNextRoot	; return old root entry

; ------------- Store new filename into entry

		mov	cx,FILENAMELEN	; CX <- length of filename
		mov	si,CurFilename	; SI <- new filename
		mov	di,bx		; DI <- directory entry
		rep	movsb		; store new filename
		call	SetRootModi	; set Root modified flag

; ------------- Restore filename from temporary buffer

		mov	cx,FILENAMELEN	; CX <- length of filename
		mov	si,PushFilename	; SI <- pushed filename
		mov	di,CurFilename	; DI <- current filename
		rep	movsb		; restore filename
 
; ------------- Find next FCB file

		mov	bl,1		; flag, open next FCB
		call	OpenFCB		; open next FCB file
		jnc	Int21172	; next file OK

; ------------- OK

		mov	al,0		; AL <- 0, OK flag
Int21179:	call	WriteRoot	; write Root sector
		ret

; ----------------------------------------------------------------------------
;                                    Data
; ----------------------------------------------------------------------------

RootIndex:	dw	0		; index of current Root entry

RootSectDisk:
RootSect:	db	-1		; current Root sector in Root buffer
RootDisk:	db	-1		; current disk in Root buffer

RootModi:	db	0		; flag, 0ffh=Root buffer modified, 0=no

; ------------- Read/write file operation

RWResult:	db	0		; result of file operation
RWRecords:	dw	0		; number of required records
RWRecord:	dd	0		; record number
RWFCB:		dw	0		; offset of original FCB
RWAddr:		dw	0		; address of buffer (offset in DTA)
RWDataOn:	db	0		; 1=transfer data, 0=don't transfer
RWFileOff:	dd	0		; offset in file
RWFileSect:	dw	0		; sector in file
RWSectOff:	dw	0		; offset in sector
RWFileClust:	dw	0		; cluster in file
RWDiskClust:	dw	0		; cluster in disk
RWClustSect:	dw	0		; sector in cluster
RWConAddr:	dw	0		; address for reading from console

; ------------- Current file

CurFilename:	times FILENAMELEN db SPACE ; current filename
SecFilename:	times FILENAMELEN db SPACE ; second filename
PushFilename:	times FILENAMELEN db SPACE ; push filename
CurExtFlag:	db	0		; flag, 0ffh = use extended FCB
CurAttrib:	db	0		; current attributes
OpenHidSys:	db	0		; flag, 0ffh = open HID and SYS files

Zpět na stránku systému MICRODOS