NEW
  AUTO 3,1
*--------------------------------------
XDOS			cld						no decimal.
				sty mliy				save x and y
				stx mlix			 
				
				ply						get processor status
				
				pla						find out the address of the caller
				sta A3L
				clc						preserve the address of the call spec.
				adc #$04
				sta mliretn				last MLI call return address
				pla
				sta A3L+1
				adc #$00
				sta mliretn+1

				phy						pull processor status
				plp						to re-enable interrupts.

				cld						still no decimal
				stz	p8error				clear any previous errors.
				ldy #$01				find out if command is valid.
				lda	(A3L),y				get command #

				lsr						and hash it to a range of 0-$1F
				lsr
				lsr
				lsr
				clc
				adc (A3L),y
				and #$1F
				tax
				lda (A3L),y				check result to see if valid command #
				cmp XDOS.CmdNums,x
				bne scnerr

				iny						index to call spec parm list.
				lda (A3L),y				make A3L point to parameter count byte
				pha						in parameter block.
				iny
				lda (A3L),y
				sta A3L+1
				pla
				sta A3L

				lda	XDOS.ParamCnt,x		make sure parameter list has the correct # of parameters.
				beq goclock				clock has 0 parameters.

				cmp (A3L)
				bne scperr				error if wrong count.

				lda XDOS.CmdNums,x		get call # again
				cmp #MLIQUIT			is it quit?
				beq special				if so, then call quit dispatcher

				asl					 	carry set if bfm or dev mgr
				bpl godevmgr
				bcs gobfmgr

				lsr						shift back down for interrupt manager
				and #$03				valid calls are 0 and 1
				jsr XDOS.intmgr
				bra exitmli

special			jmp jspare				P8 system death vector

goclock			jsr clockv			 	go read clock.
				bra exitmli				no errors possible

godevmgr 		lsr						shift back down for device manager.
				adc #$01				valid commands are 1 and 2.
				sta A4L					save command #.
				jsr XDOS.devmgr			execute read or write request.
				bra exitmli

gobfmgr			lsr						shift back down for block file manager.
				and #$1F				valid commands are 0-$13
				tax
				
				jsr XDOS.bfmgr

exitmli			stz bubit				clear backup bit
				ldy p8error				P8 error code
				cpy #$01				if > 0 then set carry
				tya						and set z flag.
				php						disable interrupts until exit complete.
				sei
				lsr mliact				indicate MLI done.
				plx						save status register until return.
				lda mliretn+1			place last MLI call return address
				pha						on stack. return is done via 'rti'
				lda mliretn				so the status register is restored
				pha						at the same time, so
				phx						place status back on stack
				tya						return error, if any.
				ldx mlix				MLI X register savearea
				ldy mliy				MLI Y register savearea
				pha
				lda bnkbyt1				restore language card status
				jmp GP.MLIEXIT			and return.

nodevice 		lda #MLI.E.NODEV		no device connected.
				jsr GP.P8errv
				
scnerr			lda #MLI.E.BADCALL
				.HS 2C					BIT ABS
scperr			lda #MLI.E.BADCNT
				jsr gosyserr
				bra exitmli
*--------------------------------------
* ProDOS Device Manager
*--------------------------------------
XDOS.devmgr		ldy #$05				the call spec for devices must

.1	  			lda (A3L),y				be passed to drivers in page zero:
				sta A4L,y
				dey
				bne .1

				ldx buf+1				buffer page
				stx usrbuf+1			to user buffer
				inx
				inx
				lda buf					is buffer page aligned (nn00) ?
				beq .2					branch if it is

				inx						else account for 3-page straddle

.2  			jsr vldbuf1				make sure user buffer is not
				bcs gosyserr			conflicting with protected ram.

				jsr XDOS.DevCall		call internal entry for device dispatch
				bcc XDOS.DevCall.RTS

gosyserr 		jsr GP.P8errv
*--------------------------------------
XDOS.DevCall	php						do not allow interrupts.
				sei						

				lda unitnum				get device # and
				and #$F0				strip misc lower nibble
				sta unitnum				then save it.
				lsr						use as index to device table
				lsr
				lsr
				tax
				jsr XDOS.DevCall.Jmp
				bit CLRC8ROM			RELEASE $C800-$CFFF ROM space
				bcs .9
				
				plp
				clc
				rts
				
.9				plp				
				sec

XDOS.DevCall.RTS
				rts
				
XDOS.DevCall.Jmp
				jmp (DEVPTRS,x)			goto driver (or error if no driver)
*--------------------------------------
* ProDOS interrupt manager
*--------------------------------------
XDOS.intmgr		sta A4L					interrupt command
				lsr						allocate interrupt or deallocate?
				bcs dealcint			branch if deallocate.

				ldx #$03				test for a free interrupt space in tbl.

.1				lda	inttbl-2,x			test high address for 0.
				bne	.2					branch if spot occupied.

				ldy	#$03				get address of routine.
				lda	(A3L),y				must not be zero page.
				beq badint				error if it is.
				sta inttbl-2,x			save high address
				dey
				lda (A3L),y
				sta inttbl-3,x			and low address.
				txa						return interrupt # in range 1-4
				lsr
				dey
				sta (A3L),y				pass back to user.
				clc						no errors.
				rts

.2  			inx
				inx						next lower priority spot
				cpx #$0B				are all 4 already allocated?
				bne	.1					branch if not.

				lda	#MLI.E.IRQFULL		interrupt table full
				.HS 2C					BIT ABS
badint			lda #MLI.E.INVPARAM		invalid parameter.
				jsr GP.P8errv

dealcint		ldy #$01			   	zero out interrupt vector
				lda	(A3L),y				but make sure it is a valid #.
				beq badint				error if < 1

				cmp #$05				or > 4
				bcs badint

				asl
				tax
				
				stz inttbl-2,x
				stz inttbl-1,x
				clc
				rts
*--------------------------------------
XDOS.syserr		sta p8error				P8 error code
				plx
				plx						pop 1 level of return
				sec
				rts
*--------------------------------------
XDOS.SysDeath 	tax						death error code.
				sta CLR80DISP			disable 80 col hardware.
				lda SETTEXT				switch in text.
				lda cortflag			is this a Cortland?
				beq .1					if not, don't use super hires switch.

				stz newvideo			force off super hires.

.1	  			lda CLRPAGE2			switch in text page 1.

				ldy #deathmsg.LEN-1

.2  			lda deathmsg,y
				sta $400,y				'RESTART SYSTEM-$'
				dey
				bpl .2

				txa						x = death error code
				and #$0F				convert to ascii
				ora #$30
				cmp #$3A
				bcc .3					branch if not > 9.

				adc #$06				inc to alpha a-f

.3  			ldy #deathmsg.LEN
				ora #$80
				sta $400,y
				
				lda #" "
				
.4				iny
				sta $400,y
				cpy #39
				bne .4

				bra *
*--------------------------------------
* ProDOS Block File Manager
*--------------------------------------
XDOS.bfmgr		lda XDOS.CmdFlags,x		translate into command address.
				asl						bit 7 indicates pathname to process
				sta cmdtemp
				and #$3F				bit 6  is refnum, 5 is time to process
				tax
				lda cmdtable,x			move address to indirect jump
				sta H3274+1
				lda cmdtable+1,x		high byte
				sta H3274+2

				lda #$20				init backup bit flag
				sta bkbitflg			to say 'file modified'
				bcc nopath

				jsr XDOS.GetPath		process pathname before calling command
				bcs errorsys			branch if bad name.

nopath			asl cmdtemp				test for refnum processing
				bcc nopreref

				jsr XDOS.GetFCB			set pointers to fcb and vcb of file
				bcs errorsys

nopreref 		asl cmdtemp				check for necessity of time stamp
				bcc H3274	

				jsr clockv				date/time

H3274  			jsr $FFFF				SELF MODIFIED : execute command
				bcc goodop

errorsys 		jsr GP.P8errv
goodop			rts
*--------------------------------------
* entry used by rename for 2nd pathname.
*--------------------------------------
XDOS.GetRenPath	ldy #$03			 	get address to new pathname
				.HS 2C
*--------------------------------------
XDOS.GetPath	ldy #$01				index to pathname pointer
				lda (A3L),y				low pointer address
				sta zpt

				iny
				lda (A3L),y				hi pointer address
				sta zpt+1

				ldx #$00				x = index to pathbuf
				ldy #$00				y = index to input pathname.

				stz prfxflg				assume prefix is in use.
				stz pathbuf				mark pathbuf = nothing processed.

				lda (zpt),y				validate pathname length > 0 and < 65
				beq errsyn

				cmp #$41
				bcs errsyn

				sta pathcnt				this is used to compare for
				inc pathcnt				end of pathname processing.

				iny						now check for full pathname...
				lda (zpt),y				(full name if starts with '/')
				and #$7F
				cmp #'/'
				bne H32AD				branch if prefix appended.

				dec prfxflg				set prefix flag = prefix not used.
				iny						index to 1st character of pathname.

H32AD  			lda #$FF				set current position of pathbuf
				sta pathbuf,x			to indicate end of pathname.

				sta namcnt				$FF = no chars processed in local name.
				stx namptr				pointer to local name length byte.

H32B8  			cpy pathcnt				done with pathname processing?
				bcs endpath

				lda (zpt),y				get character
				and #$7F
				inx						prepare for next char
				iny
				cmp #'/'				is it delimiter '/' ?
				beq endname				yes

				.DO LOWERCASE=0
				cmp #'a'				lowercase?
				bcc .1					no

				and #$5F				shift to uppercase
.1				.FIN

				sta pathbuf,x			store char
				inc namcnt				is it the 1st char of a local name?
				bne .2					no
	
				inc namcnt				increment to 1
				jsr XDOS.IsValidFirstChar
				bcc H32B8

				bra errsyn
				
.2				jsr XDOS.IsValidChar
				bcc H32B8

errsyn			lda #MLI.E.INVPATH
				sec
				rts

endpath			lda #$00			 	end pathname with a 0
				bit namcnt				also make sure count is positive
				bpl H32FD

				sta namcnt
				dex

H32FD  			inx
				sta pathbuf,x
				beq errsyn				error if '/' only.

				stx pathcnt				save length of pathname
				tax

endname  		lda namcnt				validate local name < 16
				cmp #16
				bcs errsyn

				phx						save pointer
				ldx namptr				get index to beginning of local name
				sta pathbuf,x			save local name's length
				plx						restore pointer
				bne H32AD				branch if more names to process

				clc						probably no error, but
				lda prfxflg				make sure all pathnames are prefixed
				bne H3323				or begin with a '/'.

				lda newpfxptr			must be non-zero
				beq errsyn
H3323  			rts
*--------------------------------------
XDOS.SetPrefix	jsr XDOS.GetPath		call is made to detect if a null path.
				bcc H3333				path ok.

				ldy pathbuf				is it a null pathname?
				bne pfxerr				error if not

				sty newpfxptr			fix appletalk PFI bug
				sty preflag	  			prefix flag
				clc						no error
				rts

H3333  			jsr XDOS.FindFileOrVol	go find specified prefix directory.
				bcs pfxerr				branch if error is not root directory.

H333C  			lda d_stor				make sure last local name is dir type
				and #$D0				(either root or sub).
				eor #$D0				directory?
				bne ptyperr				wrong type

				ldy prfxflg				new or appended prefix?
				bne H334D

				lda newpfxptr			append new prefix to old

H334D  			tay
				sec						find new beginning of prefix
				sbc pathcnt
				cmp #$C0				too long?
				bcc errsyn				then error

				tax
				sta newpfxptr
				sta preflag
				lda d_dev				save device #
				sta p_dev
				lda d_frst				and address of 1st block
				sta p_blok
				lda d_frst+1
				sta p_blok+1

.1				lda pathbuf,y
				sta pathbuf,x
				iny
				inx
				bne .1

				clc						good prefix
				rts

ptyperr			lda #MLI.E.UNSUPST		filetype error (not a directory)
pfxerr			sec
				rts
*--------------------------------------
XDOS.GetPrefix	clc						calc how big a buffer is needed.
				ldy #$01				get index to users pathname buffer
				lda (A3L),y
				sta usrbuf				user buffer ptr
				iny
				lda (A3L),y
				sta usrbuf+1

				stz cbytes+1			set buffer length at 64 char max
				lda #$40
				sta cbytes

				jsr valdbuf				go validate prefix buffer address
				bcs pfxerr

				ldy #$00				y = indirect index to user buffer.
				lda newpfxptr			get address of beginning of prefix
				tax
				beq nulprfx				if null prefix.

				eor #$FF				get total length of prefix
				adc #$02				add 2 for leading and trailing slashes.

nulprfx  		sta (usrbuf),y			store length in user's buffer.
				beq gotprfx				branch if null prefix.

sendprfx 		iny						inc to next user buffer location.
				lda pathbuf,x			get next char of prefix.

sndlimit 		sta (usrbuf),y		  	give char to user.
				and #$F0				check for length descriptor.
				bne H33B3				branch if regular character

				lda #'/'				otherwise, substitute a slash.
				bne sndlimit			branch always

H33B3  			inx
				bne sendprfx			branch if more to send.
				iny
				lda #'/'				end with '/'
				sta (usrbuf),y
gotprfx  		clc						no error
				rts
*--------------------------------------
XDOS.GetFCB		ldy #$01				index to ref#
				lda (A3L),y				is it a valid file# ?
				beq badref				must not be 0.

				cmp #FCB.MAX+1
				bcs badref

				pha
				dec 
				lsr
				ror
				ror
				ror						multiply by 32.
				sta fcbptr				used as an index to fcb
				tax
				pla						restore ref# in acc
				cmp FCBs+FCB.ID,x
				bne errnoref
*--------------------------------------
XDOS.GetFCBBufX	lda FCBs+FCB.BUFID,x	get page address of file buffer.
				
				tay						index into global buffer table.
				lda buftbl-1,y
				sta bufaddrh

				beq fcbdead				fcb corrupted

				sta datptr+1			save ptr to data area of buffer
				inc
				inc						index block always 2 pages after data
				sta zpt+1

				lda buftbl-2,y			???? ALWAYS 0

				sta bufaddrl
				sta datptr				index and data buffers always on
				sta zpt					page boundaries.

				jsr XDOS.FCBDevIDSelect

				lda #VCB0

fndfvol			tay						search for associated vcb
				lda VCBs+VCB.DEV,y
				cmp FCBs+FCB.DEVID,x	is this vcb the same device?
				beq tstvopen			if it is, make sure volume is active.

nxtfvol			tya					 	adjust index to next vcb.
				clc
				adc #VCB
				bcc fndfvol				loop until volume found.

				lda #$0A				open file has no volume so
				.HS 2C					BIT ABS

fcbdead			lda #$0B				fcb error so

				jsr GP.SysDeath			kill the system.

tstvopen 		lda VCBs,y				make sure this vcb is open.
				beq nxtfvol				branch if it is not active.

				sty vcbptr				save ptr to good vcb.
				clc						no error
				rts						Y = VCBPtr, X = FCBPtr

errnoref 		stz FCBs,x

badref 			lda #MLI.E.BADREF		requested refnum is
				sec						illegal (out of range)
				rts
*--------------------------------------
XDOS.Online		jsr mvdbufr				figure out how big buffer has to be.

				stz cbytes				set this for valdbuf routine.
				stz cbytes+1
				ldy #$01
				lda (A3L),y				if 0 then cbytes=$100 else $010 for one
				and #$F0				device. mask out unused nibble.
				sta devnum				last device used.
				beq H343C				branch if all devices.

				lda #$10				cbytes = $010
				sta cbytes
				bne H343F				always taken

H343C  			inc cbytes+1			cbytes = $100

H343F  			jsr valdbuf				go validate buffer range against
				bcs onlinerr			allocated memory.

				lda #$00				zero out user buffer space
				ldy cbytes

H3449  			dey
				sta (usrbuf),y
				bne H3449

				sta namptr				used as pointer to user buffer.
				lda devnum				get device # again.
				bne online1				branch if only 1 device to process.

				jsr mvdevnums			get list of currently recognized dev's.

H3459  			phx						save index to last item on list
				lda loklst,x
				sta devnum				save desired device to look at.
				jsr online1				log this volume and return it's name.
				lda namptr				inc pointer for next device
				clc
				adc #$10
				sta namptr
				plx						get index to device list.
				dex						next device.
				bpl H3459				branch if there is another device.

				lda #$00				no errors for multiple on-line
				clc
onlinerr 		rts
*--------------------------------------
online1			jsr XDOS.FindVCBForDevNum	see if it has already been logged in.
				bcs olinerr1			branch if vcb is full.

				lda #$02
				ldx #$00				read in root (volume) directory
				jsr XDOS.ReadGBufAX		read ROOT VOL into general purpose buffer.
				bcc volfound			branch if read was ok.

				ldx vcbptr
				ldy VCBs+VCB.OFCNT,x	don't take the vcb offline if
				bne olinerr1			there are active files present.

				stz VCBs,x				now take the volume offline
				stz VCBs+VCB.DEV,x

				bra olinerr1			branch if unable to read.

volfound 		.DO LOWERCASE=1
				jsr XDOS.CheckAndUnpackGBuf
				bcs olinerr1
				.FIN

				ldx vcbptr
				lda VCBs,x				has it been logged in before?
				beq H349E				if not.

				lda VCBs+VCB.OFCNT,x	it has, are there active files?
				bne H34AA				branch if volume is currently busy.

H349E  			jsr XDOS.VCBMountAtX
				bcs olinerr1			branch if there is a problem.

				lda #MLI.E.DUPVOL		anticipate a duplicate active volume
				bit duplflag			exits.
				bmi olinerr1			branch if so.

H34AA  			ldx vcbptr
				jsr XDOS.VCBCmpGBUF		does vol read compare with logged vol?
				lda #MLI.E.DSKSWIT		anticipate wrong volume mounted.
				bcc H34D0				branch if ok.

olinerr1 		pha						save error code.
				jsr svdevn				report what device has problem.
				pla						error code.
				iny						tell what error was encountered.
				sta (usrbuf),y
				cmp #MLI.E.DUPVOL		duplicate volume error?
				bne H34CE				no.

				iny						report which other device has same name
				ldx vcbentry
				lda VCBs+VCB.DEV,x
				sta (usrbuf),y
				stz duplflag			clear duplicate flag.

				lda #MLI.E.DUPVOL		duplicate volume error code.

H34CE  			sec						flag error
				rts

H34D0  			lda VCBs,x				get volume name count
				sta namcnt
				ldy namptr				index to user's buffer.

H34D9  			lda VCBs,x				move name to user's buffer
				sta (usrbuf),y
				inx
				iny
				dec namcnt
				bpl H34D9

svdevn			ldy namptr				index to 1st byte of this entry.
				lda devnum				upper nibble = device# and
				ora (usrbuf),y			lower nibble = name length.
				sta (usrbuf),y
		
				clc						no errors
				rts						end of block file manager
*--------------------------------------
XDOS.Create		jsr XDOS.CheckPath		check for duplicate, get free entry
				bcc	duperr				error code may be 'file not found'

tstfnf			cmp #MLI.E.FNOTFND		'file not found' is ok
				bne crerr1				otherwise exit with error.

				ldy #$07				test for tree or directory file,
				lda (A3L),y				no other kinds are legal.
				cmp #$04				is it seed, sapling or tree?
				bcc tstdspc				branch if it is

				cmp #$0D
				bne ctyperr				report type error if not directory.

tstdspc			lda devnum				make sure destination device
				jsr twrprot1			is not write protected.
				bcs H351D

				lda nofree				is there space in directory to
				beq xtndir				add this file? branch if not
				jmp creat1				otherwise, go create file.

xtndir			lda own_blk				before extending directory,
				ora own_blk+1			make sure it's a subdirectory.
				bne H352A

				lda #MLI.E.DIRFULL		otherwise, directory full error
				.HS 2C					BIT ABS
ctyperr			lda #MLI.E.UNSUPST		filetype error
				.HS 2C					BIT ABS
duperr			lda #MLI.E.DUPFILE		name already exists
crerr1			sec
H351D  			rts
	
H352A  			lda bloknml				preserve disk address of current (last)
				pha						directory link, before allocating an
				lda bloknml+1			extended block.
				pha
				jsr alc1blk				allocate a block for extending directory
				plx
				stx bloknml+1			restore block addr of dir info in gbuf
				plx
				stx bloknml
				bcs H351D				unable to allocate.

				sta gbuf+2				save block address in y,a to
				sty gbuf+3				current directory.
				.DO LOWERCASE=1
				jsr XDOS.WriteGBufDir
				.ELSE
				jsr XDOS.WriteGBuf		update directory block with new link.
				.FIN
				bcs H351D				if error

				ldx #$01

swpbloks 		lda bloknml,x			prepare new directory block
				sta gbuf,x				using current block as back link
				lda gbuf+2,x
				sta bloknml,x			and save new block as next to be written
				dex
				bpl swpbloks

				inx						x = 0

clrdir 			stz gbuf+2,x
				stz gbuf+$100,x
				inx
				bne clrdir

				.DO LOWERCASE=1
				jsr XDOS.WriteGBufDir
				.ELSE
				jsr XDOS.WriteGBuf		write prepared directory extension.
				.FIN
				bcs H351D				if error

				lda own_blk
				ldx own_blk+1

				.DO LOWERCASE=1
				jsr XDOS.ReadGBufAXDir
				.ELSE
				jsr XDOS.ReadGBufAX		read in parent directory block
				.FIN

				ldx own_ent				and calc entry address.
				lda /gbuf
				sta zpt+1
				lda #$04

ocalc  			clc
				dex						has entry address been calculated?
				beq H3584				if yes.

				adc own_len				next entry address
				bcc ocalc

				inc zpt+1				entry must be in 2nd 256 bytes of block
				bcs ocalc				always taken.

H3584  			sta zpt
				ldy #$13				index to block count
H3588  			lda (zpt),y
				adc dinctbl-$13,y		add 1 to block count and
				sta (zpt),y
				iny
				tya						$200 to the directory's eof.
				eor #$18				done with usage/eof update?
				bne H3588				branch if not.

				.DO LOWERCASE=1
				jsr XDOS.WriteGBufDir
				.ELSE
				jsr XDOS.WriteGBuf		go update parent.
				.FIN
				bcs crerr2

				jmp XDOS.Create
crerr2 			rts						return and report errors
*--------------------------------------
creat1			ldx #$00				zero out gbuf

H35A0  			stz gbuf,x
				stz gbuf+$100,x			and data block of file.
				inx
				bne H35A0

				ldy #$0B				move user specified date/time

cmvtime			lda (A3L),y				to directory.
				sta d_filid,y
				txa		 				if all 4 bytes of date/time = 0
				ora (A3L),y				then use built-in date/time.
				tax
				dey
				cpy #$07
				bne cmvtime

				txa						does user want default time?
				bne cmvname				if not.

				ldx #$03

mvdftime 		lda p8date,x			move current default date/time
				sta d_credt,x
				dex
				bpl mvdftime

cmvname			lda (A3L),y				y = index to file kind.
				cmp #$04
				lda #$10				assume tree type
				bcc csvfkind

				lda #$D0			 	it's directory.

csvfkind 		ldx namptr			 	index to local name of pathname.
				ora pathbuf,x			combine file kind with name length.
				sta d_stor			 	sos calls this 'storage type'.
				and #$0F			 	strip back to name length
				tay		 				and use as counter for move.
				clc
				adc namptr			 	calc end of name
				tax

crname			lda pathbuf,x			move local name as filename
				sta d_stor,y

				dex
				dey
				bne crname

				ldy #$03				index to 'access' parameter
				lda (A3L),y
				sta d_attr
				iny						also move 'file identification'
				lda (A3L),y
				sta d_filid

cmvauxid 		iny						move auxillary identification bytes
				lda (A3L),y
				sta d_auxid-5,y
				cpy #$06
				bne cmvauxid

				.DO LOWERCASE=0
				lda xdosver				save current xdos version #
				sta d_sosver

				lda compat			 	and backward compatibility #
				sta d_comp
				.FIN
				
				lda #$01			 	usage is always 1 block
				sta d_usage
				lda d_head				place back pointer to header block
				sta d_dhdr

				lda d_head+1
				sta d_dhdr+1

				lda d_stor				storage type.
				and #$E0			 	is it a directory?
				beq cralcblk			branch if seed file.

* Create Dir First Block

				ldx #$1E			 	move header to data block

cmvheadr 		lda d_stor,x
				sta gbuf+4,x
				dex
				bpl cmvheadr

				eor #$30
				sta gbuf+4				make it a directory header mark.

				.DO LOWERCASE=0
				
				ldx #$07			 	overwrite password area and other

cmvpass			lda pass,x				header info.
				sta gbuf+20,x

				lda xdosver,x
				sta gbuf+32,x
				dex
				bpl cmvpass
				
				.ELSE
				lda #$75
				sta gbuf+20
				
				ldx #XDOS.VolHdrDef.Cnt-1
				
.1				lda XDOS.VolHdrDef,x
				sta gbuf+34,x
				dex
				bpl .1
				
				.FIN

				ldx #$02				and include info about parent directory
				stx d_eof+1				set file size = 512

cmvparnt 		lda d_entblk,x
				sta gbuf+39,x
				dex
				bpl cmvparnt

				lda h_entln				lastly, the length of parent's
				sta gbuf+42				directory entries.

				.DO LOWERCASE=1
				jsr XDOS.PackGBuf
				.FIN

cralcblk 		jsr alc1blk				get address of file's data block
				bcs crerr3

				sta d_frst
				sty d_frst+1
				sta bloknml
				sty bloknml+1
				jsr XDOS.WriteGBuf		go write data block of file
				bcs crerr3

				inc h_fcnt			 	add 1 to total # of files in this dir
				bne credone

				inc h_fcnt+1

credone			jsr drevise				go revise directories with new file
				bcs crerr3

				jmp upbmap			 	lastly, update volume bitmap
*--------------------------------------
entcalc			lda /gbuf				set high address of dir entry
				sta zpt+1			  	index pointer.
				lda #$04			 	calc address of entry based
				ldx d_entnum			on the entry #.

H3689  			clc

H368A  			dex		 				addr = gbuf + ((d_entnum-1) * h_entln)
				beq H3696			  	branch with carry clear = no errors.

				adc h_entln
				bcc H368A

				inc zpt+1			  	inc hi address.
				bcs H3689				always.

H3696  			sta zpt			  		newly calculated low address.
crerr3 			rts		 				carry set if error.
*--------------------------------------
drevise			lda p8date
				beq drevise1		  	if no clock, then don't mod date/time.

				ldx #$03

modtime			lda p8date,x			move last modification date/time
				sta d_moddt,x			to entry being updated.
				dex
				bpl modtime

drevise1 		lda bkbitflg			(bit 5 = backup needed)
				tsb d_attr				mark entry as backupable
				
				lda d_dev			  	get device # of directory
				sta devnum			 	to be revised

				lda d_entblk			and address of directory block.
				ldx d_entblk+1

				.DO LOWERCASE=1
				jsr XDOS.ReadGBufAXDir
				.ELSE
				jsr XDOS.ReadGBufAX		read block into general purpose buffer
				.FIN
				bcs crerr3

				jsr entcalc				fix up ptr to entry location within gbuf.

				ldy h_entln				now move 'd.' info to directory.
				dey
				
.1  			lda d_stor,y
				sta (zpt),y
				dey
				bpl .1

				lda d_head				is the entry block same as
				cmp bloknml				the entry's header block?
				bne H36E0			  	if no, go save entry block

				lda d_head+1			then maybe, so test high addresses.
				cmp bloknml+1
				beq uphead			 	branch if they are the same block.

H36E0  			.DO LOWERCASE=1
				jsr XDOS.WriteGBufDir
				.ELSE
				jsr XDOS.WriteGBuf		go write updated directory block.
				.FIN
				bcs crerr3

				lda d_head			 	get address of header block and
				ldx d_head+1

				.DO LOWERCASE=1
				jsr XDOS.ReadGBufAXDir
				.ELSE
				jsr XDOS.ReadGBufAX		go read in header block to modify.
				.FIN
				bcs crerr3

uphead			ldy #$01				update current # of files in this dir.

H36F2  			lda h_fcnt,y
				sta gbuf+37,y			(current entry count)
				dey
				bpl H36F2

				lda h_attr			 	also update header's attributes.
				sta gbuf+34

				.DO LOWERCASE=1
				jsr XDOS.WriteGBufDir
				.ELSE
				jsr XDOS.WriteGBuf		go write updated header
				.FIN
				bcs H375A
*--------------------------------------
ripple			lda gbuf+4				test for 'root' directory because
				and #$F0			 	if it is, then directory revision
				eor #$F0			 	is complete (leaves carry clear).
				beq H3770			  	branch if done.

				lda gbuf+41				get entry #
				sta d_entnum
				lda gbuf+42				and the length of entries in that dir
				sta h_entln

				lda gbuf+39				get addr of parent entry's dir block
				ldx gbuf+40
	
				.DO LOWERCASE=1
				jsr XDOS.ReadGBufAX		no need to pak/unpak....will disturb zpt
				.ELSE
				jsr XDOS.ReadGBufAX		read it
				.FIN
				bcs H375A

				jsr entcalc				get indirect ptr to parent entry in gbuf

				lda p8date				don't touch mod
				beq H373B			  	if no clock...

				ldx #$03			 	update the modification date & time
				ldy #$24			 	for this entry too

H3732  			lda p8date,x
				sta (zpt),y
				dey
				dex
				bpl H3732

H373B  			.DO LOWERCASE=1
				jsr XDOS.WriteGBuf		
				.ELSE
				jsr XDOS.WriteGBuf		write updated entry back to disk.
				.FIN
				bcs H375A			  	if error.

				ldy #$26			 	compare current block # to this
				lda (zpt),y				entry's header block.
				tax
				dey
				lda (zpt),y				block as header.
				cmp bloknml				are low addresses the same?
				bne H3751			 	branch if entry doesn't reside in same

				cpx bloknml+1			are high address the same?
				beq ripple			 	they are the same, continue to root dir.

H3751  			.DO LOWERCASE=1
				jsr XDOS.ReadGBufAX		
				.ELSE
				jsr XDOS.ReadGBufAX
				.FIN
				bcc ripple				continue if read was good

H375A  			rts

H3770  			clc		 				no error
				rts
*--------------------------------------
MAN
SAVE usr/src/prodos.fx/prodos.s.xdos.a
LOAD usr/src/prodos.fx/prodos.s
ASM
