NEW
  AUTO 3,1
*/--------------------------------------
* # OpenDir
* ## C
* `short int hDIR opendir (const char * dirpath);`
* ## ASM
* `>LDYA dirpath`
* `>SYSCALL opendir`
* ## RETURN VALUE
*  CC : success
*   A = hDIR
*  CS : error
*   A = EC
*\--------------------------------------
K.OpenDir		jsr PFT.CheckPathYA
				bcs .9

				jmp FS.OPEN.DIR

.9				rts
*/--------------------------------------
* # ReadDir
* ## C
* `int readdir (int hDIR, S.DIRENT * dirent);`
* ## ASM
* `>PUSHW dirent`
* `lda hDIR`
* `>SYSCALL readdir`
* ## RETURN VALUE
*  CC : success
*   X = hDIRENT
*   Y,A = PTR to S.DIRENT
*  CS : error
*   A = EC
*   note : A = 0 means no more entry
*\--------------------------------------
				.DUMMY					ZPTMP,9
				.OR ZPTMP				9 Bytes
K.ReadDir.hBlk	.BS 1
K.ReadDir.ECIB	.BS 1

K.ReadDir.EL	.BS 1
K.ReadDir.EPB	.BS 1
K.ReadDir.EC	.BS 2

K.ReadDir.BufSize	.BS 2
K.ReadDir.hBuf	.BS 1
				.ED
*--------------------------------------
K.ReadDir		jsr PFT.CheckNodeA
				bcs DIRENT.RTS

				ldy #S.FD.REG.REF
				lda (pFD),y
				beq K.ReadDir.ROOT

				bpl .1

				jmp K.ReadDir.DEV

.1				jmp K.ReadDir.DIR

DIRENT.EOF		lda #MLI.E.EOF
				sec
DIRENT.RTS		rts
*--------------------------------------
K.ReadDir.ROOT	ldy #S.FD.DIR.FC		did we already returned something ?
				lda (pFD),y
				bne DIRENT.EOF

				stz K.MLI.PARAMS+1		All Volumes
				>LDYAI K.Buf256
				>STYA K.MLI.PARAMS+2
				>STYA ZPPtr2

				>MLICALL MLIONLINE
				bcs DIRENT.RTS

				>LDYAI 16+S.STAT*18+1	14*(Vols+Stat) + 4*(PFT+Stat) + \0

				jsr K.ReadDir.GetBufYA
				bcs DIRENT.RTS

				lda #16
				sta K.ReadDir.EC

.1				lda (ZPPtr2)
				and #$0F
				beq .4

				tax
				inc
				sta K.MLI.PATH
				lda #'/'
				sta K.MLI.PATH+1
				ldy #1

.2				lda (ZPPtr2),y
				sta K.MLI.PATH+1,y
				jsr K.ReadDir.AddToBuf
				iny
				dex
				bne .2

				txa						Add ending 0 for C String
				jsr K.ReadDir.AddToBuf

				jsr FS.ClrStat

				lda /S.STAT.MODE.BDEV
				sta K.S.STAT+S.STAT.MODE+1

				lda (ZPPtr2)
				asl						DRIVE in Carry
				pha
				lda #0
				rol
				inc
				sta K.S.STAT+S.STAT.P.DRIVE
				pla
				lsr						CC
				lsr
				lsr
				lsr
				lsr
				sta K.S.STAT+S.STAT.P.SLOT

				>LDYAI K.MLI.PATH
				>STYA K.MLI.PARAMS+1
				>MLICALL MLIGETFILEINFO
				sta K.S.STAT+S.STAT.P.DEVSTATUS

				bcs .3

				>LDYA K.MLI.PARAMS+5		AUXTYPE=TOTAL BLOCKS
				>STYA K.S.STAT+S.STAT.P.DEVBLOCKS
				>LDYA K.MLI.PARAMS+8
				>STYA K.S.STAT+S.STAT.BLOCKS

.3				jsr K.ReadDir.AddStat

.4				lda ZPPtr2
				clc
				adc #16
				sta ZPPtr2
				bcc .5
				inc ZPPtr2+1

.5				dec K.ReadDir.EC
				bne .1

				jsr FS.ClrStat

				lda /S.STAT.MODE.DIR
				sta K.S.STAT+S.STAT.MODE+1
				
				ldx #0
	
.6				lda Flt.Table.pftHI,x
				beq .8
				
				sta ZPPtr2+1
				lda Flt.Table.pftLO,x
				sta ZPPtr2
				
				ldy #$ff
				
.7				iny
				lda (ZPPtr2),y
				jsr K.ReadDir.AddToBuf
				eor #0
				bne .7

				jsr K.ReadDir.AddStat
				
.8				inx
				cpx #K.FLT.MAX
				bne .6

*				lda #0					done by S.MEM.F.INIT0
*				sta (ZPPtr4)			Ending 0

				ldy #S.FD.DIR.FC
				lda #255
				sta (pFD),y				Flag that we returned something for next time
				jmp K.ReadDir.EXIT
*--------------------------------------
K.ReadDir.DEV	jmp DIRENT.EOF			TODO : /dev
*--------------------------------------
K.ReadDir.DIR  	sta K.MLI.PARAMS+1		A=#S.DIR.PRODOS.REF

				>LDYAI 512				Get a 512 bytes buffer for reading dir...
				jsr K.GetMem
				bcs .99

				stx K.ReadDir.hBlk
				>STYA K.MLI.PARAMS+2	For reading
				pha
				tya
*				clc						CC from  K.GetMem
				adc #4					Skip 4 bytes linked list
				sta ZPPtr2				PTR to Buffer for PASS #1
				sta ZPPtr3				PTR to Buffer for PASS #2
				pla
				adc #0
				sta ZPPtr2+1			PTR to Buffer for PASS #1
				sta ZPPtr3+1			PTR to Buffer for PASS #2

				>LDYAI 512
				>STYA K.MLI.PARAMS+4
				>MLICALL MLIREAD		Read A block from directory
				bcs .98

				ldy #S.FD.DIR.EL		Check if first run....
				lda (pFD),y
				bne .2					no, we have all we need....

				ldy #$1f+3
				ldx #3

.1				lda (ZPPtr2),y			Get K.ReadDir.EL....	From Block
				sta K.ReadDir.EL,x
				dey
				dex
				bpl .1

				ldx #8

				ldy #16

.10				lda (ZPPtr2),y
				pha
				iny
				dex
				bne .10

				ldx #8

				ldy #S.FD.DIR.ACL+7

.20				pla
				cpy #S.FD.DIR.MODE+1
				bne .30

				and #$0F

.30				sta (pFD),y
				dey
				dex
				bne .20

				inc K.ReadDir.EC		Add one to EC because we include VOL/DIR Header
				bne .4

				inc K.ReadDir.EC+1		...and ProDOS does NOT include header entry in EC
				bra .4

.98				jmp K.ReadDir.FreeBlk

.99				rts

.2				ldy #S.FD.DIR.EL+3
				ldx #3

.3				lda (pFD),y				get this session parameters from S.DIR
				sta K.ReadDir.EL,x
				dey
				dex
				bpl .3

.4				lda K.ReadDir.EC
				eor #$ff
				tax

				lda K.ReadDir.EC+1
				eor #$ff
				tay

				inx						Any entry remaining ?
				bne .5

				iny
				beq .98					no...exit
* pass #1 compute BufSize...
.5				lda K.ReadDir.EPB
				sta K.ReadDir.ECIB

				lda #1					For Ending 0
				sta K.ReadDir.BufSize
				stz K.ReadDir.BufSize+1

K.ReadDir.DIR1	lda (ZPPtr2)			X = EntryCount In This Block
				beq .7					Free slot....goto next

				and #$F0				get storage_type
				cmp #$F0				Volume header ?
				beq .1

				cmp #$E0				directory header ?
				beq .2

				lda (ZPPtr2)			regular DIR or File, get LEN
				and #$F					compute filename len
				sec						add "#<filename>" + S.STAT
				adc #S.STAT
				.HS 2C					bit abs
.1				lda #2+S.STAT			add "1." string + S.STAT
				.HS 2C					bit abs
.2				lda #2+S.STAT+3+S.STAT	add "1." + S.STAT + "2.." + S.STAT...

				clc
				adc K.ReadDir.BufSize
				sta K.ReadDir.BufSize
				bcc .3

				inc K.ReadDir.BufSize+1

.3				inx
				bne .7

				iny
				bra K.ReadDir.DIR2		we reached last entry in whole DIR

.7				lda ZPPtr2
				clc
				adc K.ReadDir.EL
				sta ZPPtr2
				bcc .8

				inc ZPPtr2+1

.8				dec K.ReadDir.ECIB
				bne K.ReadDir.DIR1
* pass #2 Fill Buffer...(ZPPtr1 & Ptr2 can now be trashed)
K.ReadDir.DIR2	jsr K.ReadDir.GetBuf
				bcs K.ReadDir.FreeBlk

				lda K.ReadDir.EPB
				sta K.ReadDir.ECIB

.1				lda (ZPPtr3)
				beq .7					Empty slot, skip

				and #$F0
				cmp #$F0				Vol Header ?
				bne .2

				jsr K.ReadDir.ADD.
				bra .4

.2				cmp #$E0				Dir Header ?
				bne .3

				jsr K.ReadDir.ADD.
				jsr K.ReadDir.AddStatACL

				jsr K.ReadDir.ADD..
				bra .4

.3				jsr K.ReadDir.AddFNToBuf

.4				jsr K.ReadDir.AddStatACL

				lda K.ReadDir.EC			decrease global counter...
				sec
				sbc #1
				sta K.ReadDir.EC
				lda K.ReadDir.EC+1
				sbc #0
				sta K.ReadDir.EC+1
				ora K.ReadDir.EC
				beq .8						0! no more files in DIR

.7				dec K.ReadDir.ECIB			0! no more file in block
				beq .8

				lda ZPPtr3
				clc
				adc K.ReadDir.EL
				sta ZPPtr3
				bcc .1

				inc ZPPtr3+1
				bra .1

.8				ldx #3
				ldy #S.FD.DIR.EL+3

.81				lda K.ReadDir.EL,x		Store back this session parameters to S.DIR
				sta (pFD),y
				dey
				dex
				bpl .81

				jsr K.ReadDir.FreeBlk

K.ReadDir.EXIT	ldx K.ReadDir.hBuf
				txa
				jmp K.GetMemPtr
*--------------------------------------
K.ReadDir.FreeBlk
				pha
				lda K.ReadDir.hBlk
				jsr K.FreeMem
				pla
				sec
				rts
*--------------------------------------
K.ReadDir.GetBuf
				>LDYA K.ReadDir.BufSize			Get a BufSize bytes buffer for storing results
K.ReadDir.GetBufYA
				jsr K.GetMem0			make sure 0 filled
				bcs .9
				stx K.ReadDir.hBuf
				>STYA ZPPtr4
.9				rts
*--------------------------------------
K.ReadDir.ADD.  ldx #1					filename="1."
				.HS 2C					bit abs
K.ReadDir.ADD..
				ldx #2					filename="2.."
				lda #'.'

.1				jsr K.ReadDir.AddToBuf		Add X dot(s)
				dex
				bne .1

				txa
				jmp K.ReadDir.AddToBuf		Add Ending 0
*--------------------------------------
K.ReadDir.AddFNToBuf
				ldy #$1D				version/min_version for lowercase bitmap
				lda (ZPPtr3),y			check bxxxxxxx.xxxxxxxx...
				bpl	.7					not set, no lowercase bitmap present

				pha
				dey
				lda (ZPPtr3),y
				pha

				lda #$1
				sta .2+1

				ldy #15

.1				pla
.2				bit #$ff
				pha
				beq .3

				lda (ZPPtr3),y
				ora #$20				convert a-z to A-Z adding from $4x to $6x
				sta (ZPPtr3),y

.3				asl .2+1
				bne .4

				rol .2+1
				pla

.4				dey
				bne .1

				pla
.7				lda (ZPPtr3)
				and #$0F				get filename len
				tax
				ldy #1

.8				lda (ZPPtr3),y
				jsr K.ReadDir.AddToBuf
				iny
				dex
				bne .8

				txa
*				jsr K.ReadDir.AddToBuf

*				rts
*--------------------------------------
K.ReadDir.AddToBuf
				sta (ZPPtr4)
				inc ZPPtr4
				bne .8
				inc ZPPtr4+1
.8				rts
*--------------------------------------
K.ReadDir.AddStatACL
				jsr FS.DirEnt2Stat

				ldy #S.FD.DIR.UID
				ldx #S.STAT.UID

.1				lda (pFD),y
				sta K.S.STAT,x
				iny
				inx
				cpx #S.STAT.GID+2
				bne .1

				ldy #S.FD.DIR.MODE+1
				ldx #1

.2				lda (pFD),y
				ora K.S.STAT+S.STAT.MODE,x
				sta K.S.STAT+S.STAT.MODE,x
				dey
				dex
				bpl .2

K.ReadDir.AddStat
				ldy #0

.1				lda K.S.STAT,y
				jsr K.ReadDir.AddToBuf
				iny
				cpy #S.STAT
				bne .1

				rts
*/-------------------------------------
* # CloseDir
* ## C
* `void closedir(hDIR);`
* ## ASM
* `lda hDIR`
* `>SYSCALL closedir`
* ## RETURN VALUE
*  none, always succeed.
*\-------------------------------------
*K.CloseDir		.EQ K.FClose
*--------------------------------------
MAN
SAVE usr/src/sys/kernel.s.dirent
LOAD usr/src/sys/kernel.s
ASM
