NEW
  AUTO 3,1
*--------------------------------------
XDOS.DeallocAX	stx bmcnt				high address of block.
*				pha						save low address.
				ldx XDOS.VCBPtr			 	check that bitmap block address is
				ldy XDOS.VCBs+VCB.TBLK+1,x	valid given the total # of blocks
				cpy bmcnt			  	on the volume.
*				pla
				bcc L3C8C			 	branch if invalid

				tax
				and #$07			 	bit to be or'd in
				tay
				lda whichbit,y			(shifting takes 7 bytes, but is slower)
				sta nofree			 	save bit pattern.
				txa		 				low block address.

				ldx #3

.1				lsr bmcnt
				ror
				dex
				bne .1

*				lsr bmcnt
*				ror
*				lsr bmcnt
*				ror

				sta bmptr			  	save pointer.
				lsr bmcnt			  	transfer bit which is page of bitmap
				rol half
				jsr XDOS.GetBM			make sure device is correct one.
				bcs L3C8B			  	error.

				lda XDOS.BM.Idx				current map.
				cmp bmcnt			  	is in-core bitmap the correct one ?
				beq L3C64			  	branch if yes.

				jsr XDOS.FlushBM	 	put current map away.
				bcs L3C8B			  	error.

				lda bmcnt			  	get map #
				ldx XDOS.VCBPtr

				sta XDOS.VCBs+VCB.BMAPIDX,x	and make it current.
				lda XDOS.BM.DevID
				jsr XDOS.ReadBMDevA		read it into buffer
				bcs L3C8B

L3C64  			ldy bmptr			  	index to byte
				lsr half
				lda nofree			 	(get indiviual bit)
				bcc bmbufhi			  	branch if on page 1 of bitmap

				ora XDOS.BMBuf+$100,y
				sta XDOS.BMBuf+$100,y
				bcs L3C7D			  	always.

bmbufhi			ora XDOS.BMBuf,y				this address + 2 is used as an absolute reference to XDOS.BMBuf high byte.
				sta XDOS.BMBuf,y

L3C7D  			sec						mark bitmap as modified
				ror	XDOS.BM.Status

				inc deblock				inc count of blocks deallocated
				bne L3C8A

				inc deblock+1

L3C8A  			clc
L3C8B  			rts

L3C8C  			lda #MLI.E.BADFS	 	bitmap block # impossible.
				sec		 				bitmap disk address wrong
				rts		 				(maybe data masquerading as indx block)
*--------------------------------------
XDOS.GetFreeBlk	jsr XDOS.GetBM			get address of bitmap.
				bcs L3CB8			  	error.

L3C95  			ldy #$00			 	begin search at start of bitmap block.
				sty half			 	which half (page) to search

L3C9A  			lda XDOS.BMBuf,y
				bne L3CB9			  	free blocks indicated by 'on' bits

				iny
				bne L3C9A			  	check all in 1st page.

				inc half			 	now search page 2.
				inc basval			 	base value = base address / 2048.

L3CA8  			lda XDOS.BMBuf+$100,y	search 2nd half for free block
				bne L3CB9

				iny
				bne L3CA8

				inc basval			 	add 2048 offset for next page.
				jsr XDOS.NextBM			get next bitmap (if exists) and
				bcc L3C95			  	update vcb. branch if no error.

L3CB8  			rts		 				return error.

L3CB9  			sty bmptr			  	save index pointer to valid bit group.
				lda basval			 	prep for block address calculation
				sta scrtch+1
				tya		 				address of bit pattern.

				ldx #3

.1				asl			  			multiply this and basval by 8
				rol scrtch+1
				dex
				bne .1

				tax		 				low address within 7 of actual address
				sec
				lda half
				beq L3CDB				branch if allocating from 1st half.

				lda XDOS.BMBuf+$100,y		get pattern from 2nd page.
				bcs L3CDE			  	always.

L3CDB  			lda XDOS.BMBuf,y				get bit pattern from 1st page.
L3CDE  			rol			  			find left most 'on' bit
				bcs L3CE4			  	if found.

				inx		 				adjust low address.
				bne L3CDE			  	always.

L3CE4  			lsr			  			restore pos'n of all but left most bit.
				bcc L3CE4			  	loop until mark moves into carry.

				stx scrtch			 	save low address.
				ldx half			 	which half of bitmap ?
				bne L3CF4			  	if page 2.

				sta XDOS.BMBuf,y
				beq L3CF7			  	always.

L3CF4  			sta XDOS.BMBuf+$100,y		update to show allocated block in use.

L3CF7  			sec					 	indicate map is modified.
				ror XDOS.BM.Status

				ldx XDOS.VCBPtr			 	subtract 1 from total free vcb blocks
				lda XDOS.VCBs+VCB.FBLK,x			to account for newly allocated block.
				bne .7

				dec	XDOS.VCBs+VCB.FBLK+1,x

.7				dec	XDOS.VCBs+VCB.FBLK,x

				lda scrtch			 	return address in y,a of newly
				ldy scrtch+1			allocated block.

				clc		 				no errors.
				rts
*--------------------------------------
XDOS.NextBM		ldx XDOS.VCBPtr			 	inc to next bitmap, but 1st make sure there is another one.
				lda XDOS.VCBs+VCB.TBLK+1,x
				lsr
				lsr
				lsr
				lsr
				cmp XDOS.VCBs+VCB.BMAPIDX,x	are there more maps ?
				beq L3D60			  	if no more to look at.

				inc XDOS.VCBs+VCB.BMAPIDX,x	add 1 to current map
				jsr XDOS.FlushBM

XDOS.GetBM		ldy XDOS.VCBPtr
				lda XDOS.VCBs+VCB.DEV,y	get device #.
				cmp XDOS.BM.DevID				does this map match this device ?
				beq L3D4A			  	yes.

				jsr XDOS.FlushBM	 	otherwise, save other volume's bitmap
				bcs L3D5F

				ldy XDOS.VCBPtr
				lda XDOS.VCBs+VCB.DEV,y
				sta XDOS.BM.DevID			 	and read in fresh bitmap for this dev.

L3D4A  			bit XDOS.BM.Status				is it already modified ?
				bmi L3D54			  	yes, return pointer

				jsr XDOS.ReadBMDevA	 	otherwise read in fresh bitmap.
				bcs L3D5F			  	if error.

L3D54  			ldy XDOS.VCBPtr			get relative block # of bitmap.
				lda XDOS.VCBs+VCB.BMAPIDX,y
				asl			  			2 pages per block
				sta basval

				clc		 				no errors.
L3D5F  			rts

L3D60  			lda #MLI.E.VOLFULL	 	request can't be filled
				sec		 				error
				rts
*--------------------------------------
XDOS.FlushBM	clc
				bit XDOS.BM.Status				is current map modified ?
				bpl .9				  	no.

				jsr XDOS.WriteBM		update device.
				bcs .9				  	if error on writing.

				stz XDOS.BM.Status				mark bitmap buffer as free
			lda #0						MUST EXIT WITH A=0
.9				rts
*--------------------------------------
XDOS.ReadBMDevA	sta XDOS.BM.DevID			 	read bitmap specified by dev and vcb.

				ldy XDOS.VCBPtr			get lowest map # with free blocks in it
				lda XDOS.VCBs+VCB.BMAPIDX,y
				sta XDOS.BM.Idx				associate offset with bitmap ctrl block.
				clc						add this # to the base address of
				adc XDOS.VCBs+VCB.BMAP,y	1st bitmap and save in bmadadr which
				sta XDOS.BM.BlkNum				is address of bitmap to be used.

				lda XDOS.VCBs+VCB.BMAP+1,y
				adc #$00
				sta XDOS.BM.BlkNum+1

				lda #$01			 	read device command
				.HS 2C					BIT ABS
XDOS.WriteBM	lda #$02			 	write command.

				sta ZP.CMDNUM

				lda GP.DEVNUM			save current dev #
				pha
				lda XDOS.BM.DevID			 	get bitmap's dev #
				sta GP.DEVNUM
				lda XDOS.BM.BlkNum				and disk address
				sta ZP.BLKNUM
				lda XDOS.BM.BlkNum+1
				sta ZP.BLKNUM+1

				lda /XDOS.BMBuf
*				lda bmbufhi+2			address of the buffer (low = 0)
				jsr XDOS.RWBlock

				plx						keep A=error code if CS
				stx GP.DEVNUM

				rts
*--------------------------------------
				.DO LOWERCASE=1
XDOS.WriteGBufDir
				jsr XDOS.PackGBuf
				bra XDOS.WriteGBuf
				.FIN
*--------------------------------------
XDOS.ReadGBufDEKeyPtr
				lda XDOS.DE.KeyPtr			 	read 1st block of directory into XDOS.GBuf
				ldx XDOS.DE.KeyPtr+1
				.DO LOWERCASE=1
XDOS.ReadGBufAXDir
				jsr XDOS.ReadGBufAX
				bcc XDOS.UnpackGBuf
				rts
				.FIN
XDOS.ReadGBufAX	sta ZP.BLKNUM
				stx ZP.BLKNUM+1

XDOS.ReadGBuf	lda #$01			 	read command.
				.HS 2C					BIT ABS

XDOS.WriteGBuf	lda #$02				write command

				sta ZP.CMDNUM		  	pass to device handler.
				lda /XDOS.GBuf			general buffer.

XDOS.RWBlock	sta ZP.BUFPTR+1			buffer high.
				stz ZP.BUFPTR			buffer low (always on page boundary)

				jmp XDOS.FileIO2
*--------------------------------------
				.DO LOWERCASE=1

XDOS.CheckAndUnpackGBuf
				lda XDOS.GBuf+35
				sta XDOS.DH.EL
				ldy XDOS.GBuf+36
				sty XDOS.DH.EPB
				cmp #$27
				bne .9

				cpy #$0D
				beq XDOS.UnpackGBuf

.9				lda	#MLI.E.NOTPRODOS
				sec
				rts

XDOS.UnpackGBuf	jsr XDOS.ZPT.InitGBuf

				ldx XDOS.DH.EPB

.1				jsr XDOS.ZPT.Unpack

				dex
				beq .8

				jsr XDOS.ZPT.Next
				bra .1

.8				clc						make sure CC
				rts
*--------------------------------------
*XDOS.PackGBuf.Bitmap .BS 2
XDOS.PackGBuf.Bitmap .EQ sos
*--------------------------------------
XDOS.PackGBuf	jsr XDOS.ZPT.InitGBuf

				ldx XDOS.DH.EPB

.1				lda (zpt)
				and #$0F
				beq .6

				stz XDOS.PackGBuf.Bitmap
				stz XDOS.PackGBuf.Bitmap+1

				tay

.2				lda (zpt),y

				cmp #'a'
				bcc .5

				cmp #'z'+1
				bcs .5

				eor #$20				to uppercase
				sta (zpt),y

				cpy #8					CS if MIN_VERSION to use
				bcs .3

				lda whichbit,y
				tsb XDOS.PackGBuf.Bitmap+1
				bra .4

.3				lda whichbit-8,y
				tsb XDOS.PackGBuf.Bitmap

.4				lda #$80
				tsb XDOS.PackGBuf.Bitmap+1

.5				dey
				bne .2

				ldy #$1C				VERSION
				lda XDOS.PackGBuf.Bitmap
				sta (zpt),y

				iny 					MIN_VERSION
				lda XDOS.PackGBuf.Bitmap+1
				sta (zpt),y

.6				jsr XDOS.ZPT.Next
				dex
				bne .1

				rts

				.FIN
*--------------------------------------
XDOS.GetMark	ldx XDOS.FCBPtr				index to open fcb.

				ldy #$02				index to user's mark parameter.

.1				lda XDOS.FCBs+FCB.MARK,x		transfer current position
				sta (ZP.A3L),y				to user's parameter list
				inx
				iny
				cpy #$05				transfer 3 bytes
				bne .1

				clc
				rts

L3DFD  			lda #MLI.E.BEYEOF		invalid position
				sec
				rts
*--------------------------------------
XDOS.SetMark	ldy #$04				index to user's desired position.
				ldx XDOS.FCBPtr			file's control block index.
				inx						inc by 2 for index to hi eof
				inx
				sec						indicate comparisons are necessary.

.1				lda (ZP.A3L),y			move it to 'tpos'
				sta XDOS.TmpPos-2,y
				bcc .2					branch if mark < eof

				cmp XDOS.FCBs+FCB.EOF,x
				bcc .2					branch if mark qualifies.

				bne L3DFD				branch if mark > eof (invalid position)

				dex

.2				dey		 				move/compare next lower byte of mark.
				tya						test for all bytes moved/tested.
				eor #$01				preserves carry status.
				bne .1					branch if more.
*--------------------------------------
rdposn			ldy XDOS.FCBPtr			test to see if new position is
				lda XDOS.FCBs+FCB.MARK+1,y	within the same (current) data block.
				and #$FE
				sta scrtch

				lda XDOS.TmpPos+1		middle byte of new position
				sec
				sbc scrtch
				sta scrtch
				bcc L3E44				branch if < current position.

				cmp #$02				must be within 512 bytes of beginning
				bcs L3E44				of current position.

				lda XDOS.TmpPos+2		make sure within the same 64k.
				cmp XDOS.FCBs+FCB.MARK+2,y
				bne L3E44				branch if not.

				jmp	svmark				if so, adj fcb, position ptr and return.

L3E44			lda XDOS.FCBs+FCB.STYPE,y	determine file type for positioning.
				beq L3E50				0 = invalid file type.

				cmp #$04				tree class file?
				bcc L3E59				yes, go position.

				jmp dirmark				no, test for dir type.

L3E50  			
*				ldy #$A4				??????? clear illegal filetype entry in fcb
*				sta XDOS.FCBs,y			??????? WILL TRASH anther FCB
				lda #MLI.E.BADREF	 	and report error
				sec
				rts

L3E59  			lda XDOS.FCBs+FCB.STYPE,y	use storage type as # of index levels
				sta levels			 	since 1=seed, 2=sapling, 3=tree.
				lda XDOS.FCBs+FCB.F,y
				and #FCB.F.DBLKMOD	 	if previous data was modified then
				beq L3E6B			  	disk must be updated.

				jsr XDOS.WriteDBLK

				bcs L3ED4				if error.

L3E6B  			ldy XDOS.FCBPtr				test to see if current index block
				lda XDOS.FCBs+FCB.MARK+2,y	is usable by checking if new
				and #$FE			 	position is within 128k of the
				sta scrtch			 	beginning of current sapling level
				lda XDOS.TmpPos+2			 	chunk.
				sec
				sbc scrtch
				bcc L3E9D				branch if a new index block is needed.

				cmp #$02				is new position within 128k of old ?
				bcs L3E9D				branch if not.

				ldx levels				is it a seed file ?
				dex
				bne datlevel1			no, use current indexes.

L3E89  			lda XDOS.TmpPos+1				is new position < 512 ?
				lsr
				ora XDOS.TmpPos+2
				bne L3EEF				no, mark both data and index block as

				lda XDOS.FCBs+FCB.1stBLK,y	unallocated. 1st block is only block
				sta ZP.BLKNUM			and it's data.
				lda XDOS.FCBs+FCB.1stBLK+1,y	high block address.
				jmp rnewpos				go read in block and set statuses.

L3E9D  			lda XDOS.FCBs+FCB.F,y		check to see if previous index block
				and #FCB.F.IBLKMOD		was modified.
				beq L3EA9				read in over it if current up to date.

				jsr XDOS.WriteIBLK		go update index on disk (fcb block addr)
				bcs L3ED4

L3EA9  			ldx levels				be sure there is a top index
				cpx #$03			 	before reading it...
				beq posindex			branch if file is a tree.

				lda XDOS.TmpPos+2			 	is new position within range of a
				lsr			  			sapling file (less than 128k) ?
				php		 				save results
				lda #$07			 	(no level is allocated for new pos'n)
				plp		 				restore z-flag.
				bne L3F18			  	go mark all as dummy.

				jsr XDOS.ClrFCBStatus	clr status bits 0,1,2 (index/data/alloc)

				dex						check for seed
				beq L3E89			  	if seed, check for position < 512.

				jsr rfcbfst				go get only index block.
				bcs L3ED4			  	if error.

				jsr XDOS.UpdateFCBIBlk	save newly loaded index block's address.

datlevel1		bra datlevel			branch always

L3ED4  			rts

posindex 		jsr XDOS.ClrFCBStatus	clr all alloc requirements for previous
				jsr rfcbfst				position. get highest level index block
				bcs L3ED4

				lda XDOS.TmpPos+2			 	then test for a sap level index block
				lsr
				tay
				lda (zpt),y
				inc zpt+1
				cmp (zpt),y				(both high and low = 0 if no index exists)
				bne saplevel

				tax		 				are both bytes 0 ?
				bne saplevel

				dec zpt+1

L3EEF  			lda #$03				show neither index or data block alloc'd
				bra L3F18

saplevel 		sta ZP.BLKNUM			read in next lower index block.
				lda (zpt),y				(high address)
				sta ZP.BLKNUM+1
				dec zpt+1

*				jsr rfcbidx				read in sapling level

				lda #$01			 	prepare to read index block : read command
				sta ZP.CMDNUM

				ldx #zpt			 	address of current index buffer.
				jsr XDOS.FileIOPtrX		go read index block.
				bcs L3ED4			 	error

				jsr XDOS.UpdateFCBIBlk save block address of this index in fcb

datlevel 		jsr XDOS.Tpos2Y			get block address of data block

				lda (zpt),y				data block address low
				inc zpt+1
				cmp (zpt),y
				bne L3F51

				tax
				bne L3F51

				lda #$01				show data block as never been allocated
				dec zpt+1

L3F18  			jsr XDOS.SetFCBStatus	set status to show what's missing

				lsr			  			discard bit that says data block
				lsr			  			unallocated because carry indicates if
				jsr XDOS.ZeroData		index block is invalid and needs to be zeroed.
				bcc svmark			  	branch if it doesn't need zeroed

				jsr XDOS.ZeroIndex		zero index block in user's i/o buffer
				bra svmark
*--------------------------------------
XDOS.ZeroData	lda #$00
				tay

				inc ZP.DataPtr+1

				jsr .1

				dec ZP.DataPtr+1

.1  			sta (ZP.DataPtr),y
				iny
				bne .1

				rts
*--------------------------------------
L3F51  			sta ZP.BLKNUM			get data block of new position
				lda (zpt),y				(high address)
				dec zpt+1

rnewpos			sta ZP.BLKNUM+1
				jsr XDOS.ReadFCB.DBLK
				bcs L3F86				if error.

				jsr XDOS.ClrFCBStatus	show whole chain is allocated.
*--------------------------------------
svmark			ldy XDOS.FCBPtr			update position in fcb
				iny
				iny
				ldx #$02

L3F68  			lda XDOS.FCBs+FCB.MARK,y	save old mark in case calling routine
				sta oldmark,x			fails later.
				lda XDOS.TmpPos,x
				sta XDOS.FCBs+FCB.MARK,y
				dey
				dex		 				move 3 byte position marker
				bpl L3F68

				clc		 				set up indirect address to buffer
				lda ZP.DataPtr			page pointed to by the current
				sta sos			  		position marker.
				lda XDOS.TmpPos+1
				and #$01
				adc ZP.DataPtr+1
				sta sos+1
L3F86  			rts						carry set if error
*--------------------------------------
dirmark			cmp #$0D				is it a directory ?
				beq L3F9C			  	yes...

				lda #MLI.E.INCFF	 	no, so compatability problem.
				jsr GP.SYSERR		 	should not have been opened !!!

L3F9C  			lda scrtch			 	recover results of previous subtraction.
				lsr						use difference as counter for how many
				sta cntent			 	blocks must be read to get to new pos'n.

				lda XDOS.FCBs+FCB.MARK+1,y	test for positive direction
				cmp XDOS.TmpPos+1			 	indicated by carry.

				lda XDOS.FCBs+FCB.MARK+2,y
				sbc XDOS.TmpPos+2

				bcc L3FB9			  	if set, position forward. otherwise,

L3FAB  			ldy #$00			 	read directory file in reverse order.
				jsr XDOS.DirSeek		read previous block.
				bcs L3FD6			  	if error.

				inc cntent				count up to 128.
				bpl L3FAB			  	loop if more blocks to pass over.

				bmi svmark			  	always.

L3FB9  			ldy #$02			 	position is forward from current.
				jsr XDOS.DirSeek		read next directory block
				bcs L3FD6			  	if error.

				dec cntent
				bne L3FB9			  	loop if position not found in this block

				beq svmark			  	branch always.
*--------------------------------------
XDOS.DirSeek	lda (ZP.DataPtr),y		get link address of previous or next
				sta ZP.BLKNUM			directory block.
				iny		 				
				lda (ZP.DataPtr),y		get the rest of the link.
				sta ZP.BLKNUM+1
				ora ZP.BLKNUM			but first be sure there is a link.
				bne XDOS.ReadFCB.DBLK  	branch if certain link exists.

				lda #MLI.E.EOF		 	something is wrong with directory file!
				sec						error.
L3FD6  			rts
*--------------------------------------
XDOS.ReadFCB.DBLK
				lda #$01				read command
				sta ZP.CMDNUM

				ldx #ZP.DataPtr			points at address  of data buffer.
				jsr XDOS.FileIOPtrX		go do file input.
				bcs .9				  	error.

				ldy XDOS.FCBPtr
				lda ZP.BLKNUM
				sta XDOS.FCBs+FCB.DBLK,y		save block # just read in fcb.
				lda ZP.BLKNUM+1
				sta XDOS.FCBs+FCB.DBLK+1,y

*				clc

.9  			rts
*--------------------------------------
wfcbfst			jsr XDOS.FlushBM		update the bitmap and write file's 1st block.

				ldx #$02				write command
				.HS 2C					BIT ABS

rfcbfst			ldx	#$01				read command.

				lda #FCB.1stBLK
				ora XDOS.FCBPtr			add offset to XDOS.FCBPtr
				tay
				txa						get back command

				ldx #zpt			 	rd block into index portion of file buf
*--------------------------------------
XDOS.FileIOPtrXCmdABlkY
				sta ZP.CMDNUM	  		command

				lda XDOS.FCBs,y			get disk block address from fcb.
				sta ZP.BLKNUM			block 0 not legal
				bne .1

				lda XDOS.FCBs+1,y		high address of disk block
				bne .2

				lda #$0C			 	Block = $0000, allocation error.
				jsr GP.SYSDEATH			doesn't return...

.1  			lda XDOS.FCBs+1,y
.2				sta ZP.BLKNUM+1
*--------------------------------------
XDOS.FileIOPtrX	lda $00,x			  	get memory address of buffer from
				sta ZP.BUFPTR			page zero pointed to by x register
				lda $01,x
				sta ZP.BUFPTR+1			and pass address to device handler

				jsr XDOS.FCBDevIDSelect

XDOS.FileIO2	sec					 	also, set to indicate reg call made to
				ror ioaccess			device handler.
				lda GP.DEVNUM			transfer device # for dispatcher
				sta ZP.UNITNUM			to convert to unit #.
				stz GP.ERROR			clear global error code.
				jmp XDOS.DevCall	 	call the driver.
*--------------------------------------
XDOS.WriteDBLK	ldx #ZP.DataPtr			point at memory address with x and
				lda #FCB.DBLK		 	disk address with y.
				ora XDOS.FCBPtr			 	add offset to XDOS.FCBPtr
				tay		 				and put in y.
				lda #$02			 	write data block.
				jsr XDOS.FileIOPtrXCmdABlkY
				bcs L4096			  	if errors.

				lda #$BF			 	mark data status as current.
				bra XDOS.ResetFCBStatus

XDOS.WriteIBLK	jsr XDOS.FlushBM	 	update bitmap.

				ldx #zpt			 	point to address of index buffer
				lda #FCB.IBLK		 	and block address of that index block.
				ora XDOS.FCBPtr
				tay
				lda #$02
				jsr XDOS.FileIOPtrXCmdABlkY
				bcs L4096			  	if errors.

				lda #$7F			 	mark index status as current.
*--------------------------------------
XDOS.ResetFCBStatus
				ldx XDOS.FCBPtr
				and XDOS.FCBs+FCB.F,x
				sta XDOS.FCBs+FCB.F,x

L4096  			rts
*--------------------------------------
XDOS.Open		jsr XDOS.FindFileOrVol	look up the file.
				bcs L4096			  	if not, then error.

L40A0  			jsr XDOS.IsOpened		are any other files writing to this
				bcc L40AD			  	same file ? branch if not.

L40A5  			lda #MLI.E.OPEN		 	file is busy, shared access not allowed.
				.HS 2C
L40A9  			lda #MLI.E.UNSUPST		file is wrong storage type.
				.HS 2C
L40AB			lda #MLI.E.FCBFULL	 	fcb full error.
				sec
				rts

L40AD  			lda fcbflg				if this byte <> 0 then free fcb found
				beq L40AB			 	and available for use.

				ldx XDOS.FCBPtr				get address of 1st free fcb found.

L40B9  			ldy #FCB

L40BD  			stz XDOS.FCBs,x		 		but clean it first.
				inx
				dey
				bne L40BD

				ldy #0

				ldx XDOS.FCBPtr

L40CB  			lda XDOS.DE.DevID,y				move ownership info.
				sta XDOS.FCBs+FCB.DEVID,x	note: this code depends upon the defined
				inx						order of both the fcb and directory entry buffer.
				iny
				cpy #6
				bne L40CB

				lda XDOS.DE.Filename			 	get storage type and
				jsr XDOS.SetFCBSType
				tax		 				save in x for later comparison

				lda XDOS.DE.Access			 	get file's attributes and use it
				and #$03				as a default access request.
				cpx #$0D			 	if directory, don't allow write enable.
				bne L40EB

				and #$01			 	read enabled bit

L40EB  			sta XDOS.FCBs+FCB.ACCESS,y
				and #$02			 	check for write enabled request.
				beq L40F7			  	branch for open as read-only

				lda totent			 	otherwise, be sure no one else is
				bne L40A5			  	reading the same file. branch if busy.

L40F7  			cpx #$04			 	is it a tree file type ?
				bcc L40FF			  	yes.

				cpx #$0D			 	is it a directory type ?
				bne L40A9			  	if not, wrong storage type.

L40FF  			ldx #$06				move address of 1st block of file, end

L4101  			sta ZP.BLKNUM+1			of file and current usage count.
				lda XDOS.FCBPtr
				ora XDOS.DE2FCB,x		this is done via a translation table
				tay		 				between directory info and fcb.
				lda XDOS.DE.KeyPtr,x
				sta XDOS.FCBs,y
				dex
				bpl L4101				last loop stores hi address of 1st block

				sta ZP.BLKNUM			and this is the low one.
				ldx XDOS.FCBPtr
				lda cntent			 	this was set up by 'tstopen'.
				sta XDOS.FCBs,x			claim fcb for this file.
				jsr alcbuffr			go allocate buffer in memory tables.
				bcs L4147			  	if errors.

				ldx XDOS.FCBPtr
				jsr XDOS.GetFCBBufX		rtn addr of bufs in data & index ptrs.
				lda GP.FLEVEL		 	mark level at which
				sta XDOS.FCBs+FCB.FLEVEL,x	file was opened.

				lda XDOS.FCBs+FCB.STYPE,x	file must be positioned at beginning.
				cmp #$04			 	is it a tree file ?
				bcs L415E			  	no, assume a directory.

				lda #$FF			 	fool the position routine into giving
				sta XDOS.FCBs+FCB.MARK+2,x	a valid position with preloaded data,

				ldy #$02			 	etc. set desired position to 0.
				lda #$00

L413C  			sta XDOS.TmpPos,y
				dey
				bpl L413C

				jsr rdposn			 	let tree position routine do the rest.
				bcc L4163			  	if successful.

L4147  			pha		 				save error code.

				ldx XDOS.FCBPtr			 	free buffer space.
				stz XDOS.FCBs,x				necessary to release fcb also.
				lda XDOS.FCBs+FCB.BUFID,x
				beq L4156			  	if no bufnum, ok because never alloc'd.

				jsr relbuffr			go release buffer.

L4156  			pla		 				error code.
				sec
				rts

L415E  			jsr XDOS.ReadFCB.DBLK	read in 1st block of directory file.
				bcs L4147			  	return error after freeing buffer & fcb.

L4163  			ldx XDOS.VCBPtr				index to vcb.
				inc XDOS.VCBs+VCB.OFCNT,x	add 1 to # of files currently open

				ldx XDOS.FCBPtr			 	index to fcb.
				lda XDOS.FCBs+FCB.ID,x		return ref # to user.
				ldy #$05
				sta (ZP.A3L),y
*				clc		 				open is successful
				rts
*--------------------------------------
XDOS.IsOpened	stz cntent				returns the ref # of a free fcb.
				stz totent			 	flag to indicate file already open.
				stz fcbflg			 	flag indicates a free fcb is available.

				lda #$00

L4188  			tay						index to next fcb.
				ldx fcbflg			 	test for free fcb found.
				bne L4191			  	if already found.

				inc cntent

L4191  			lda XDOS.FCBs,y				is this fcb in use ?
				bne L41A3			  	yes.

				txa		 				if not, should we claim it ?
				bne L41C1			  	branch if free fcb already found.

				sty XDOS.FCBPtr			 	save index to new free fcb.
				lda #$FF			 	set fcb flag to indicate
				sta fcbflg			 	free fcb found.
				bne L41C1			  	branch always to test next fcb.

L41A3  			tya		 				add offset to index to ownership info
				ora #$06
				tay		 				and put it back in y.
				ldx #$06			 	index to directory entry owner info.

L41A9  			lda XDOS.FCBs,y			all bytes must match to say that it's
				cmp XDOS.DE.DevID-1,x	the same file again.
				bne L41C1			  	if not, then next fcb.

				dey		 				index to next lower bytes.
				dex
				bne L41A9				loop to check all owner info.

				inc totent			 	file is already open, now see
				lda XDOS.FCBs+FCB.ACCESS,y	if it's already opened for write.				and #$02			 if so report file busy (with carry set).
				and #$02			 	if so report file busy (with carry set).
				beq L41C1				branch if this file is read access only.

				sec
				rts

L41C1  			tya						calc position of next fcb.
				and #$E0			 	first strip any possible index offsets.
				clc
				adc #FCB			 	inc to next fcb.
				bcc L4188			  	branch if more to compare.

				clc		 				report no conflicts.
				rts
*--------------------------------------
XDOS.UpdateFCBIBlk
				ldy XDOS.FCBPtr
				lda ZP.BLKNUM
				sta XDOS.FCBs+FCB.IBLK,y		save block address of this index in fcb
				lda ZP.BLKNUM+1
				sta XDOS.FCBs+FCB.IBLK+1,y
				rts
*--------------------------------------
MAN
SAVE usr/src/prodos.fx/prodos.s.xdos.c
LOAD usr/src/prodos.fx/prodos.s
ASM
