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 DIRENT.RTS

				jsr FS.OPEN.DIR
				bcs DIRENT.RTS
				
				jmp K.FOpen.REGDIR
*/--------------------------------------
* # ReadDir
* ## C
* `struct dirent *readdir (short int hDIR);`
* ## ASM
* `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.ECIB	.BS 1

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

K.ReadDir.BufS	.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 MLI.ONLINE
				bcs DIRENT.RTS

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

				jsr K.ReadDir.GetBuf
				bcs DIRENT.RTS

.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.Add2B
				iny
				dex
				bne .2

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

				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 MLI.GFINFO
				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
				bne .1

				jsr FS.ClrStat

				lda /S.STAT.MODE.DIR
				sta K.S.STAT+S.STAT.MODE+1
				
				ldx #0
	
.6				lda PFTs.pHI,x
				beq .8
				
				sta ZPPtr2+1
				lda PFTs.pLO,x
				sta ZPPtr2
				
				ldy #$ff
				
.7				iny
				lda (ZPPtr2),y
				jsr K.ReadDir.Add2B
				eor #0
				bne .7

				jsr K.ReadDir.AddStat
				
.8				inx
				cpx #K.PFT.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

				stz K.MLI.PARAMS+2
				lda /K.Buf256			read in Buf256+IOBuf
				sta K.MLI.PARAMS+3

				stz K.MLI.PARAMS+4
				lda /512
				sta K.MLI.PARAMS+5
				
K.ReadDir.DIR0	>MLICALL MLI.READ		Read A block from directory
				bcs .99

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

				ldx #3

.1				lda K.Buf256+$23,x		Get K.ReadDir.EL....	From Block
				sta K.ReadDir.EL,x
				dex
				bpl .1

				ldx #7

				ldy #S.FD.DIR.ACL+7

.20				lda K.Buf256+$14,x
				cpy #S.FD.DIR.MODE+1
				bne .30

				and #$0F

.30				sta (pFD),y
				dey
				dex
				bpl .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

.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 K.ReadDir.DIR1

				iny
				bne K.ReadDir.DIR1
				
				lda #MLI.E.EOF
				sec
				rts
*--------------------------------------
* pass #1 compute BufS...
*--------------------------------------
K.ReadDir.DIR1	lda K.ReadDir.EPB
				sta K.ReadDir.ECIB

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

				jsr K.ReadDir.P3Init
				
				stz .8+1

.10				lda (ZPPtr3)
				beq .7					Free slot....goto next

				inc .8+1

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

				cmp #$E0				directory header ?
				beq .2

				lda (ZPPtr3)			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.BufS
				sta K.ReadDir.BufS
				bcc .3

				inc K.ReadDir.BufS+1

.3				inx						X,Y = !Total entry Count
				bne .7

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

.7				jsr K.ReadDir.P3Next
				bne .10
				
.8				lda #$FF
				bne K.ReadDir.DIR2
				
				jmp K.ReadDir.DIR0
*--------------------------------------
* pass #2 Fill Buffer...(ZPPtr1 & Ptr2 can now be trashed)
*--------------------------------------
K.ReadDir.DIR2	lda K.ReadDir.EPB
				sta K.ReadDir.ECIB

				>LDYA K.ReadDir.BufS	Get a BufS bytes buffer for storing results
				jsr K.ReadDir.GetBuf
				bcc .10

				rts
				
.10				jsr K.ReadDir.P3Init
				
.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.SA2B

				jsr K.ReadDir.ADD..
				bra .4

.3				jsr K.ReadDir.FN2B

.4				jsr K.ReadDir.SA2B

				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				jsr K.ReadDir.P3Next
				bne .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

K.ReadDir.EXIT	ldx K.ReadDir.hBuf
				txa
				jmp K.GetMemPtr
*--------------------------------------
K.ReadDir.P3Init
				ldy #4					Skip 4 bytes linked list
				sty ZPPtr3

				lda /K.Buf256
				sta ZPPtr3+1
				rts
*--------------------------------------
K.ReadDir.P3Next
				lda ZPPtr3
				clc
				adc K.ReadDir.EL
				sta ZPPtr3
				bcc .8

				inc ZPPtr3+1

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

				rts
*--------------------------------------
K.ReadDir.GetBuf
				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.Add2B		Add X dot(s)
				dex
				bne .1

				txa
				jmp K.ReadDir.Add2B		Add Ending 0
*--------------------------------------
K.ReadDir.FN2B	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.Add2B
				iny
				dex
				bne .8

				txa
*				jsr K.ReadDir.Add2B

*				rts
*--------------------------------------
K.ReadDir.Add2B	sta (ZPPtr4)
				inc ZPPtr4
				bne .8

				inc ZPPtr4+1

.8				rts
*--------------------------------------
K.ReadDir.SA2B	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.Add2B
				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
