; Figure 5-16
;
;	OPENF
;	Open File
;
;	Given a pointer to a 00H-byte terminated file name,
;	and an area that can be used for a File Control Block,
;	this subroutine builds a valid File Control Block, and
;	attempts to open the File.
;
;	If the file is opened, it returns with Carry Flag clear.
;	If the file cannot be opened, this subroutine returns 
;	with the Carry Flag set.
;
;	Entry Parameters
;
;		DE -> 36-byte area for File Control Block
;		HL -> 00H-byte terminated file name of the form
;			{disk:} Name {.typ}
;			(That is, the disk and typ are optional)
;
;	Exit Parameters
;
;		Carry Clear : File opened correctly.
;		Carry Set   : File not opened.
;
;	Calling Sequence
;
;		LXI	D,FCB
;		LXI	H,FNAME
;		CALL	OPENF
;		JC	ERROR
;
;		where
;
;	FCB:	DS	36	;Space for File Control Block
;	FNAME:	DB	'A:TESTFILE.DAT',0
;
;
B$OPEN		EQU	15	;File Open Function Code
BDOS		EQU	5	;BDOS Entry Point
;
;
OPENF:
	PUSH	D		;Preserve pointer to FCB
	CALL	BF		;Build File Control Block (FCB)
	MVI	C,B$OPEN
	POP	D		;Recover Pointer to FCB
	CALL	BDOS
	RAL			;If A=0FFH, Carry set
				;otherwise Carry Clear
	RET
;
;	BF
;	Build File Control Block
;	This subroutine formats a 00H-byte terminated string
;	(presumed to be a File Name) into an FCB, setting the
;	Disk, File name and Type and clearing the remainder of the
;	FCB to 0's.
;
;	Entry Parameters
;
;		DE -> File Control Block (36 Bytes)
;		HL -> File Name String (00H-byte terminated)
;
;	Exit Parameters
;
;		The built File Control block.
;
;	Calling Sequence
;
;		LXI	D,FCB
;		LXI	H,FILENAME
;		CALL	BF
;
;
BF:
	INX	H		;Check if 2nd char. is ":"
	MOV	A,M		;Get character from file name
	DCX	H		;HL -> now back at 1st char
	CPI	':'		;If ":", then Disk specified
	JNZ	BF$ND		;No disk
	MOV	A,M		;Get disk letter
	ANI	0001$1111B	;A (41H) -> 1, B (42H) -> 2 ...
	INX	H		;Bypass disk letter
	INX	H		;Bypass ":"
	JMP	BF$SD		;Store disk in FCB
BF$ND:				;No disk present
	XRA	A		;Indicate default disk
BF$SD:
	STAX	D		;Store disk in FCB
	INX	D		;DE -> 1st char. of name in FCB
	MVI	C,8		;File name length
	CALL	BF$GT		;Get token
				;Note - at this point, BF$GT will
				;have advanced the string pointer to
				;either a '.' or 00H byte
	CPI	'.'		;Check terminating character
	JNZ	BF$NT		;No file type specified
	INX	H		;Bypass '.' in file name
BF$NT:
	MVI	C,3		;File Type Length
	CALL	BF$GT		;Get Token
				;Note - if no file type is present
				;BF$GT will merely spacefill the FCB
	MVI	B,0		;0-fill the remainder of the FCB
	MVI	C,24		;36 - 12 (Disk, Name, Type = 12 chars.)
	CALL	BF$FT		;Re-use Fill Token S/R
	RET
;
;	BF$GT
;	Build FCB - Get Token
;
;	This subroutine scans a file name string,
;	placing characters into a File Control Block.
;	On encountering a terminator character ("." or 00H),
;	the remainder of the token is space filled. 
;	If an "*" is encountered, the remainder of the token
;	is filled with "?".
;
;	Entry Parameters
;
;		DE -> Into File Control Block
;		HL -> Into File Name String
;		C = Maximum no. of characters in token
;
;	Exit Parameters
;
;		File Control Block contains next token.
;		A = Terminating Character.
BF$GT:
	MOV	A,M		;Get next string character
	ORA	A		;Check if end of string
	JZ	BF$SFT		;Yes, space fill token
	CPI	'*'		;Check if ?-fill required
	JZ	BF$QFT		;Yes, fill with ?
	CPI	'.'		;Assume current token is Filename
				;check if file type coming up
				;(If current token is File type this
				;check is benignly redundant)
	JZ	BF$SFT		;Yes, space fill token
	STAX	D		;None of the above, so store in FCB
	INX	D		;Update FCB Pointer
	INX	H		;Update String Pointer
	DCR	C		;Countdown on token length
	JNZ	BF$GT		;Still more characters to go
BF$SKIP:			;Skip chars. until '.' or 00H
	MOV	A,M		;Get next string character
	ORA	A		;Check if 00H
	RZ			;Yes
	CPI	'.'		;Check if '.'
	RZ			;Yes
	INX	H		;Update string pointer (only)
	JMP	BF$SKIP	;Try next character

BF$SFT:			;Space fill token
	MVI	B,' '
	JMP	BF$FT		;Common Fill Token code
				;BF$FT returns to caller

BF$QFT:			;Question Mark Fill Token
	MVI	B,'?'
	CALL	BF$FT		;Common Fill Token Code
	JMP	BF$SKIP	;Bypass multiple '*' etc.

BF$FT:				;Fill Token
	PUSH	PSW		;Save terminating character
	MOV	A,B		;Get fill characer
BF$FTL:			;Inner loop
	STAX	D		;Store in FCB
	INX	D		;Update FCB Pointer
	DCR	C		;Downdate residual count
	JNZ	BF$FTL		;Keep going
	POP	PSW		;Recover terminating character
	RET
