;							>>B/S<<
;	FILE I/O
;	OPEN/CLOSE  FILES
;
; 02.10 KRS 06/18/80
; 02.14 krs 07/??/80 atrib
; 02.20 krs 07/??/80 cp/m 2 et al
; 02.33 rlr 11/20/80 flclos rtn code err
; 02.34 krs 12/24/80 remove test in fclosl
; 02.35 DEW 10/15/81 macros added
; 02.36 rlr 12/25/81 special for C3
; 02.37 krs 02/??/82 CLEANUP, C3 CONDITion
; 02.42 sbw 12/08/82 SYS.DIR dir entry number, half flag bug
;
	icl	pdef		;02.39
	icl	df		;02.39
	df.dos			;02.39
	df.cpu			;02.39
	df.sys			;02.39
;
	NAM	FL2242
;
c3ver	equ	0
;
	ENT	FOPN,FCLOS
	ENT	FOPND					;02.01
	ENT	FCLOSL					;02.02
	ENT	FOPNDE					;02.03
	ent	setdcd					;02.20
	ent	sysdir						;02.42
;
	EXT	DIRSIZ,DIRCLS,SETLOG
	EXT	XMTCH,MOVE,FCBDK
	EXT	GETBK,STCLC,SAVAF
;	EXT	RDUCB					;02.35
	ext	DSKIO,LOGDK,CRFIL
	EXT	GTSDT,ASDTE,GETCLS,MUL16
	EXT	CWPIM,ERMSG		;ADUCB		;02.35
	EXT	DIV16,GDIRST
	EXT	DIRRD,DIRWR,DIV32,MUL32 		;02.00
	EXT	DIRCLR					;02.00
	EXT	CDKBK					;02.00
	EXT	NEGHL,ZMOVE				;02.01
	EXT	getdre,getath,getatb,xgetat,getatx	;02.15
	ifc	c3ver					;02.37
	EXT	SDT,ONLVEC,ABIT,DSKBIT			;02.36
	endc
;
EOF	EQU	1AH	; FAKE FILL ON LAST FILE READ
;
    ifc SYSUCB=SINGLE
	EXT	?UFCB,?UBC
    elsec
	EXT	RDUCB,ADUCB
    endc
RECNT	EQU	FCBRC
NXREC	EQU	FCBNR
;
	EJECT
;
; SYSDIR added 02.42
;
; Input:	DE = FCB address
;
; Test for FCB referring to "SYS.DIR".
;
; Output:	Flags zero if SYS.DIR, or non-zero if not.
;		A destroyed
;		All other registers preserved.
;
sysdir:
	push	h
	push	d
	push	b
	lxi	h,..1		; Point to phony FCB
	mvi	b,11		; Length of filename and extension
  .do
	inx	d
	ldax	d
	ani	7fh		; Ignore attributes
	cmp	m		; Compare FCB name and extension to
	inx	h
	brnz	.break		; phony SYS.DIR FCB
	dbrnz	.do
  .until
	pop	b		; Restore and return flags
	pop	d
	pop	h
	ret
;
..1:	db	'SYS     DIR'	; Phony SYS.DIR FCB
;
;  FILE OPEN (15)
;  ENTRY:  @DE=FCB
;  EXIT: A=DIR ENTRY OR -1
;  'SYS.DIR' FAKES DIR ENTRY FOR DIR
;  USER BUFFER USED  / DISK LOGGED-IN (IF NESC.)
;
FOPN:
; TEST IF DISK LOGGED-IN
	CALL	SETLOG	; (*01.02*) SET DISK & A:=0
; SYS.DIR IS FAKED DIRECTORY ENTRY
;
	PUSH	D
	call	sysdir						;02.42
	brne	fopn2	; Jump if not SYS.DIR			;02.42
;
; DO IT ** SETUP FCB AS 'SYS.DIR' *** (02.01)
	XRA	A
;	call savaf removed					 02.20
	lxi	h,fcbex	; Point to FCB extent requested		;02.42
	dad	d						;02.42
	MOV	M,A	; ZERO NEXT 3 FCB BYTES
	INX	H
	MOV	M,A
	INX	H
	MOV	M,A
	INX	H
	CALL	DIRSIZ	; # OF RECORDS:=DIR SIZE/4
	MVI	C,3FH
	RRC
	RRC
	ANA	C
	MOV	M,A	; SAVE RECORD COUNT
	CALL	DIRCLS	; A:=CLUSTERS IN DIRECTORY
	MOV	B,A	; COUNT WITH B
	INX	H	; MOVE UP TO DM
	MVI	A,1	; STARTING CLUSTER
	MVI	C,16
	MVI	M,-1	; ELSE FAKE WITH -1
	BR	FOPN1D	;  AND JOIN UP...		;02.35
FOPN1A:	INX	H
FOPN1B:	MOV	M,A	; ENTER CLUSTER NO.
	INR	A	; NEXT CLUSTER
FOPN1D:	DCR	C
	DCR	B	; DONE?
	BRNZ	FOPN1A	; NOPE...			;02.35
FOPN1E:	DCR	C
	JM	FOPN1F
	INX	H
	MVI	M,0	; (MOV M,B)
	BR	FOPN1E					;02.35
FOPN1F:
; ALL SET UP
FOPN1G:	POP	D
	XRA	A
	CALL	savaf					;02.37
	lxi	h,4001h	; attributes in h on getat	 02.14
	CALL	CLGTAT	; set up dir entry (fake)	;02.37
;	WILL NOT RETURN HERE -
; 'CALL' IS TO FORCE AN EXTRA PUSH FOR STACK!!!
;
;
	EJECT
FOPN2:	POP	D
;
;	DO ACTUAL OPEN
;
	CALL	FOPND	; OPEN DIRECTORY ENTRY		 02.01
	RC		; IF CY THEN NO FILE		 02.01
	MVI	A,0	;    A=0 AS OK 			 02.01
	RET						;02.10
	EJECT
;
;  OPEN DIRECTORY ENTRY					 02.01
;	 RTNS: BC=USER EXT REQ.,HL=@DIR ENTRY		 02.01
;   FOPND:  SETUP FCB FOR DIR READ			 02.01
;   FOPNDE: DOES SO					 02.01
;   	  AND LEAVES DIR BUFF AVAIL. (@HL)		 02.01
;
FOPND:	
	ifc	c3ver					;02.37
;---------------------02.36 AUTO SEARCH ----------------
; EXPECTS FCB TO HOLD DISK SPECIFIER
; AND WORKS ON SMALL SYSTEM ONLY
	LDAX	D	; WORKS ON SMALL SYSTEM ONLY
	ORA	A
	BRNZ	..1
;AUTO SEARCH - FORCE A .. (SDT-1)
    .DO			; DE==FCB
	XCHG
	LDA	SDT	;CHECK FIRST  (A=1 /BASE 1)
	CMP	M	; AT SDT THEN TRIED ALL
	BRNE	.NEXT
; FAILED - TRUE "NOT FOUND"
	XRA	A
	MOV	M,A	;RESET TO UNIT 0 (AUTO)
	XCHG
	CMA		; RETURN ( A=-1)
	BR	FOPN3X	;FAILED SETS CY
     .NEXT
	PUSH	H
	MOV	B,M	; CHECK FOR DRIVE ON-LINE
	INR	M	; ++ FCB.DISK (BIT TEST IS BASE 0)
	CALL	DSKBIT	;  GET PROPER BIT MASK
	LXI	H,ONLVEC
	CALL	ABIT
	ANA	M
	POP	D	; RESTORE FCB
	BRZ	.DO
	CALL	SETLOG	; MAKE SURE LOGGED IN
	CALL	FOPNDE
	BRC	.DO	;IF SEARCH FAILS THEN TRY NEXT DISK
     .UNTIL
	XRA	A
	RET
..1:			;NORMAL FIXED DISK LOGIC
;---------------------02.36 AUTO SEARCH END ------------
	endc
	CALL	FOPNDE	; OPEN DIR			 02.01
	RC		; ERROR RTN			 02.01
	XRA	A	; OK FLAGS			 02.01
	RET						;02.01
;
FOPNDE:							;02.01
fopn2f:	LXI	H,FCBEX+1	;fix bug in 2.13	 02.13x
	DAD	D	;  AND ASSUME OLD TYPE FCB	 02.01
	MVI	M,0	;  FCB.EXT.HI := 0		 02.01
	INX	H					;02.01
	MVI	M,0	;  FCB.DIR ENTRY :=0		 02.01
;			WORKS BECAUSE EXTENT 0 MUST BE OPENED
;			VALIDLY BEFORE A HIGH EXTENT SUCH AS
;			100H OR HIGHER CAN BE OPENED!
;			 ELSE SEARCH FOR ENTRY		 02.00
FOPN2A: MVI	A,0
	CALL	XMTCH	; MATCH FILE NAME & EXTENT
;
FOPN3:	CALL	setdcd	;UCB.AF:=DIR ENTRY		 02.20
	CPI	-1
	BRNZ	FOPN3B					;02.00	;02.35
; OPEN FAILURE						 02.01
	LXI	H,FCBEX	; RETURNS BC:=			 02.01
	DAD	D	; USER FCB.EXT			 02.01
	MOV	C,M	; REQUEST			 02.01
	INX	H					;02.01
	MOV	B,M					;02.01
	LXI	H,0	;SAY NO DIR ENTRY AT ALL!	 02.10
;
FOPN3A:	
	STC		; SAY ERROR			 02.01
	RET						;02.00
;
fopn3x:	call	setdcd	; save dir entry #		 02.20
	BR	fopn3a					;02.20	;02.35
;
FOPN3B:							;02.00
	PUSH	D	; SAVE FCB
	PUSH	AF
;
; SAVE USER'S EXTENT REQUEST
	PUSH	H	;DIR				;02.10
	LXI	H,FCBEX					;02.10
	DAD	D					;02.10
	MOV	C,M					;02.10
	INX	H					;02.10
	MOV	B,M					;02.10
	POP	H	;DIR				;02.10
FOPN3E:	PUSH	B	;EXTENT REQ			;02.10
;
;  MOVE @DE(DIR ENTRY)-> @HL(FCB)			;02.10
;	NOT 1ST BYTE (DISK FLAG)			;02.10
	xchg						;02.14
	PUSH	D	; SAVE DIR ENTRY		;02.10
	INX	D					;02.10
	INX	H					;02.10
	LXI	B,31					;02.10
	CALL	MOVE					;02.10
	POP	h	; @DIR ENTRY			 02.14
	POP	b	; EXTENT REQ.			 02.14
	POP	AF	; ENTRY NO.			 02.10
	POP	D	; FCB				 02.10
;
	PUSH	H					;02.10
;		two lines deleted			 02.14
	mov	h,m	;get attributes to h		 02.14
	mov	l,a	;and entry # to l		 02.14
CLGTAT:	PUSH	H		; if not		;02.37
	LHLUCB	BC		; true open, 		;02.37
	MVI	A,15		; then clear 'r'	;02.37
	CMP	L		; and 'w' bits		;02.37
	POP	H		; before calling	 02.37
	BREQ	CLGT2		; DO TRUE		 02.37
..1:	equ	atrr!atrw					;02.42
	MVI	A,^..1		; P--USABF'		;02.37	;02.42
	ANA	H		; CLEAR R + W		 02.36
	MOV	H,A					;02.37
CLGT2:	CALL	xgetat	;go set it up			;02.37
	pop	h					;02.14
	XRA	A	; Z=OK DIR OPEN			 02.10
	RET		;				 02.10
	EJECT
;
setdcd:	push	b					;02.20
	push	psw					;02.20
	cpi	-1	;if -1, error set		 02.20
	BReq	setdc0	;bypass masking			 02.20	;02.35
	mvi	b,3					;02.20
	dcr	a	;make relative to 0		 02.20
	ana	b	;now entry num in dir rec	 02.20
setdc0:;call	savaf					;02.20
	SAFUCB						;02.20	;02.35
	pop	psw					;02.20
	pop	b					;02.20
	ret						;02.20
;
	EJECT
;
;  FILE CLOSE (16)
;  ENTRY @DE=FCB
;  EXIT:  A=DIR ENTRY OR -1
;	USER BUFFER USED
;
FCLOS:	CALL	FCLOSL	; FILE CLOSE			 02.02
;	call	savaf	;02.33 save user rtn code
	SAFUCB		;02.33 save user rtn code	;02.35
	PUSH	AF					;02.02
	PUSH	D					;02.02
	PUSH	B					;02.07
	CALL	FCBDK					;02.07
	CALL	DIRCLR	; CLEAR DIRECTORY		 02.02
	POP	B					;02.07
	POP	D					;02.02
	POP	AF					;02.02
	RET						;02.02
;
; LOCAL CLOSE - DOES IT BUT NO DIR CLR			 02.02
;	=== 11 LINES OF CODE DELETED BELOW - MOVED HERE	 02.20	X
; TEST IF FCB WAS MODIFIED				 02.01	X
;
;	SIX LINES OF CODE DELETED in FCLOSL-
;	REMOVE TEST FOR VALID DIRECTORY ENTRY            02.34
;								 
FCLOSL:	INX	D	; SIX LINES OF CODE DELETED	 02.34
	LDAX	D	; CHECK IF MODIFIED		 02.01	X
	RAL		;  CY:=MSB			 02.01	X
	PUSH	AF	;	SAVE CY STATE		 02.01	X
	ORA	A	; CY:=0				 02.01	X
	RAR		;  MSB:=0			 02.01	X
	STAX	D	; RESTORE CHAR WITH MSB CLEARED	 02.01	X
	DCX	D					;02.01	X
	POP	AF	; IF NO CY			 02.01	X
	MVI	A,0	;  THEN OK,NEVER MODIFIED	 02.01	X
	JNC	FOPN3A	;   ... DONE			 02.16	X
;	=== END OF MOVED CODE				 02.20	X
; MOVE FCB CLOSING TO UCB.FCB				;02.01
	PUSH	D					;02.01
	ADRUCB	FCB	; HL=@UCB.FCB			;02.01	;02.35
	PUSH	H					;02.01
	LXI	B,33	; MOVE WHOLE FCB		 02.02
	CALL	MOVE					;02.01
	POP	D	; DE=@UCB.FCB			 02.01
	CALL	FOPNDE	; RTN: HL=@DIR ENTRY		 02.01
	POP	D	; RECOVER ORIG FCB		 02.01
	JC	FOPN3x	; ERROR				 02.17
;	=== 11 LINES OF CODE MOVED FROM HERE UP ABOVE	 02.20
;
;  HL=@DIR ENTRY					 02.01
; MOVE FCB.DM TO PROPER PLACE				 02.01
; ALSO UPDATE DIR.EXT AND DIR.RC			 02.01
	PUSH	D	; SAVE ORIG FCB			 02.01
; IF SMALL DIR THEN					 02.01
	INX	D					;02.01
	push	h	; save dir rec pointer		 02.20
	INX	H	;02.01 SKIP DISK FLAG
	mvi	b,11	; move name minus high bits	;02.37
nmmov:	ldax	d					;02.37
	ani	7fh					;02.37
	mov	m,a					;02.37
	inx	h					;02.37
	inx	d					;02.37
	dbrnz	nmmov					;02.37	;02.42
	ifc	c3ver					;02.37
;-------02.36 MOVE CODE W/O WREAKING OWNER NUMBER -------
	ldax	d	; extent
	mov	m,a
	inxL	h
	INX	D
	INX	H	; SKIP OWNER NUMBER
	INX	D
	INX	H	; SKIP DIRECTORY ENTRY NUMBER
	LXI	B,17
; ------------- END 02.36 -------------
	elsec
	lxi	b,20					;02.37
	endc
	CALL	MOVE	; MOVE FCB -> ENTRY [15..31]
	pop	h	; dir entry pointer		 02.20
;
	mov	a,m	; Clear archive bit			;02.42
	ani	^ARCHIVE					;02.42
	mov	m,a	;	in directory entry		;02.42
;
	lxi	d,fcbde	; dir entry number spot		 02.20
	dad	d					;02.20
	mvi	m,0	; clear it!			 02.20
	CALL	DIRWR	; UPDATE DIR BLOCK		 02.01
	BR	FCL3	;	AND DONE		 02.01	;02.35
	EJECT
FCL3:							;02.02
	POP	D	; RESTORE ORIG FCB		 02.02
	XRA	A	;	FLAG AS OK
	RET
	EJECT
	END
