PR#3
PREFIX /A2OSX.SRC
NEW
INC 1
AUTO 6
				.LIST OFF
				.OP	65C02
				.OR	$2000
				.TF /A2OSX.BOOT/BIN/CP
*--------------------------------------
* -R recurse 
* -Y no confirm 
* -C continue on error
*--------------------------------------
				.INB INC/MACROS.I
				.INB INC/A2OSX.I
*--------------------------------------
MAX.RECURSE		.EQ 8
COPY.BUF.SIZE	.EQ 4096
*--------------------------------------
ZPPtr1			.EQ ZPBIN
ZPPtr2			.EQ ZPBIN+2
ZPPtr3			.EQ ZPBIN+4
*--------------------------------------
*			File Header (16 Bytes)
*--------------------------------------
CS.START		cld
				jmp (.1,x)
				.DA #$61				6502,Level 1 (65c02)
				.DA #1					BIN Layout Version 1
				.DA 0
				.DA CS.END-CS.START		Code Length To Relocate
				.DA DS.END-DS.START		Data Segment to Allocate
				.DA 0
				.DA 0
*--------------------------------------
* Relocation Table
*--------------------------------------
.1				.DA CS.INIT
				.DA CS.RUN
				.DA CS.DOEVENT		
				.DA	CS.QUIT
L.MSG.USAGE		.DA MSG.USAGE
L.MSG.CP		.DA MSG.CP
L.MSG.OK		.DA MSG.OK
L.MSG.ERR		.DA MSG.ERR
L.FullSrcPath	.DA FullSrcPath
L.FullDstPath	.DA FullDstPath
L.FINFO			.DA FINFO
				.DA 0
*--------------------------------------
CS.INIT			ldy #hS.LISTDIR.IDX
				tya
				sta (pData),y
				
				ldy #S.PS.hARGS
				lda (pPs),y
				bne .1
				
				>LDYA L.MSG.USAGE
				>SYSCALL SYS.PStrOutYA
				lda #SYSMGR.ERRSYN
				sec
.99				rts
				
.1				>PUSHA
				>PUSHBI $20				Push SEP=' '
				>PUSHBI 0
				>SYSCALL SYS.PStrGetTkn
				bcs .99
				
				sta	hSrcPath
				stx hDstPath

				>SYSCALL SYS.GetMemPtrA
				>STYA ZPPtr1

				stz FullSrcPath
				
				ldy #1
				lda (ZPPtr1),y
				cmp #'/'
				beq .2
				
				jsr CS.INIT.SrcPfx
				
.2				lda (ZPPtr1)
				tay
				clc
				adc FullSrcPath
				sta FullSrcPath
				tax
				
.3				lda (ZPPtr1),y
				sta FullSrcPath,x
				dex
				dey
				bne .3
				
				>LDYA L.FullSrcPath
				jsr NewDirListYA
				bcs .99
				
				lda hDstPath
				bne .4
				jsr CS.INIT.DstPfx
				bra .7
				
.4				>SYSCALL SYS.GetMemPtrA
				>STYA ZPPtr1
				
				stz FullDstPath
				
				ldy #1
				lda (ZPPtr1),y
				cmp #'/'
				beq .5

				jsr CS.INIT.DstPfx
				
.5				lda (ZPPtr1)
				tay
				clc
				adc FullDstPath
				sta FullDstPath
				tax
				
.6				lda (ZPPtr1),y
				sta FullDstPath,x
				dex
				dey
				bne .6
				
.7				>LDYA L.FullDstPath	
				>SYSCALL SYS.MLIGetFileInfoYA
				bcs .71					File not found....must be /path/file
				>STYA ZPPtr3
				ldy #S.FINFO.TYPE
				lda (ZPPtr3),y
				cmp #$f					Directory ?
				bne .71
				
				ldy FullDstPath
				lda FullDstPath,y
				cmp #'/'
				beq .71
				
				inc FullDstPath
				iny
				lda #'/'
				sta FullDstPath,y
				
.71				lda FullDstPath
				sta (pData)
				tay
				
.8				lda FullDstPath,y
				sta (pData),y
				dey
				bne .8
			
				lda (pPs)
				ora #S.PS.F.EVENT		Now accept events
				sta (pPs)
				clc
				rts
*--------------------------------------
CS.INIT.SrcPfx	ldy #S.PS.hPREFIX
				lda (pPs),y
				>SYSCALL SYS.GetMemPtrA
				>STYA ZPPtr2
				
				lda (ZPPtr2)
				sta FullSrcPath
				tay
				
.1				lda (ZPPtr2),y
				sta FullSrcPath,y
				dey
				bne .1
				rts
*--------------------------------------
CS.INIT.DstPfx	ldy #S.PS.hPREFIX
				lda (pPs),y
				>SYSCALL SYS.GetMemPtrA
				>STYA ZPPtr2
				
				lda (ZPPtr2)
				sta FullDstPath
				tay
				
.1				lda (ZPPtr2),y
				sta FullDstPath,y
				dey
				bne .1
				rts
*--------------------------------------
CS.RUN			ldy #bCANCEL
				lda (pData),y
				beq .98

				sec
				rts
				
.98				ldy #bSTOP
				lda (pData),y
				beq .1
				clc
.99				rts
				
.1				jsr GetDirList
				bcs .99
				>SYSCALL SYS.ListDirNextA
				bcc .15
				
				jsr CloseDirList
				rts						if not back to first level, CC, if CS, quit!
				
.15				pha
				>SYSCALL SYS.GetMemPtrA
				>STYA ZPPtr1
				
				lda (ZPPtr1)			get File type/len

				and #$E0
				cmp #$E0				Volume ($F) or Dir ($E) HEADER ?
				bne .10
				jmp .8
				
.10				lda (ZPPtr1)
				and #$0F
				sta (ZPPtr1)			Adjust Filename len
				
				jsr GetDirList
				>SYSCALL SYS.GetMemPtrA
				>STYA ZPPtr2
				
				ldy #S.LISTDIR.hPATH	get Src path	
				lda (ZPPtr2),y
				>SYSCALL SYS.GetMemPtrA
				>STYA ZPPtr2
				
				lda (ZPPtr2)
				tay
				tax
				
.11				lda (ZPPtr2),y
				sta FullSrcPath,y
				dey
				bne .11

				ldy #0
				
.12				inx						append filename
				iny
				lda (ZPPtr1),y
				sta FullSrcPath,x
				tya
				cmp (ZPPtr1)
				bne .12
				
				stx FullSrcPath

				lda (pData)
				tay
				tax
				
.2				lda (pData),y			copy dest path
				sta FullDstPath,y
				dey
				bne .2
				
				ldy #0
				
.3				inx						append filename
				iny
				lda (ZPPtr1),y
				sta FullDstPath,x
				tya
				cmp (ZPPtr1)
				bne .3
				
				stx FullDstPath
				
				>PUSHW L.FullDstPath
				>PUSHW L.FullSrcPath
				
				>LDYA L.MSG.CP
				>SYSCALL SYS.PStrOutYA
				
				jsr CS.RUN.COPY
				bcs .5
				>LDYA L.MSG.OK
				bra .7
				
.5				>PUSHA
				>LDYA L.MSG.ERR
				
.7				>SYSCALL SYS.PStrOutYA
				
.8				pla
				>SYSCALL SYS.FreeMemA
				clc
				rts
*--------------------------------------
CS.RUN.COPY		>LDYA L.FullSrcPath	
				>SYSCALL SYS.MLIGetFileInfoYA
				bcs .9
				>STYA ZPPtr1
				
				ldy #S.FINFO-1			Save File info for applying to new file later
.1				lda (ZPPtr1),y
				sta FINFO,y
				dey
				bpl .1
				
				lda FINFO+S.FINFO.TYPE
				cmp #$f					dir ?
				bne .2
				jsr CS.RUN.COPY.DIR
				bcc .3
				rts
				
.2				jsr CS.RUN.COPY.FILE
				bcc .3
				rts
				
.3				>PUSHW L.FullDstPath
				>PUSHW L.FINFO
				>SYSCALL SYS.MLISetFileInfo
.9				rts
*--------------------------------------
CS.RUN.COPY.DIR	>LDYA L.FullDstPath	
				>SYSCALL SYS.MLICreateDirYA
				bcc .10
				cmp #$47
				bne CS.RUN.COPY.ERR		CS
				
.10				ldx FullSrcPath
				inx
				lda #'/'
				sta FullSrcPath,x
				stx FullSrcPath
				
				>LDYA L.FullSrcPath
				jsr NewDirListYA
				bcs .9
				
				lda FullDstPath
				inc
				sta (Pdata)
				tay
				lda #'/'
				sta (Pdata),y
				dey
				
.1				lda FullDstPath,y
				sta (Pdata),y
				dey
				bne .1
				
				clc
.9				rts

CS.RUN.COPY.ERR	sec
CS.RUN.COPY.RTS	rts
*--------------------------------------
CS.RUN.COPY.FILE
				>PUSHW FINFO+S.FINFO.AUXTYPE
				>PUSHB FINFO+S.FINFO.TYPE
				>PUSHBI $C3					R/W, we will setup attrs later
				>PUSHW L.FullDstPath
				>SYSCALL SYS.MLICreateFile
				bcc .10
				cmp #$47
				bne CS.RUN.COPY.ERR
	
.10				>LDYA L.FullSrcPath
				>SYSCALL SYS.MLIOpenYA
				bcs CS.RUN.COPY.RTS
				sta hSrcFile
				stx hSrcBuf
				
				>LDYA L.FullDstPath
				>SYSCALL SYS.MLIOpenYA
				bcs .19
				sta hDstFile
				stx hDstBuf
				
				>PUSHWI COPY.BUF.SIZE 
				>PUSHBI 0
				>SYSCALL SYS.GetMem
.19				bcs .98
				>STYA ZPPtr2
				stx hCopyBuf
				
.2				>PUSHWI COPY.BUF.SIZE
				>PUSHW ZPPtr2
				>PUSHB hSrcFile
				>SYSCALL SYS.MLIRead
				bcs .97
				>STYA ZPPtr3		Bytes Read
				
				>PUSHYA			
				>PUSHW ZPPtr2
				>PUSHB hDstFile
				>SYSCALL SYS.MLIWrite
				
				lda ZPPtr3
				cmp #COPY.BUF.SIZE
				lda ZPPtr3+1
				sbc /COPY.BUF.SIZE
				bcs .2
				
				jsr .97
				clc
				rts
				
.97				pha
				lda hCopyBuf
				>SYSCALL SYS.FreeMemA
				pla
				
.98				pha
				lda hSrcFile
				>SYSCALL SYS.MLICloseA
				lda hSrcBuf
				>SYSCALL SYS.FreeMemA
				pla
				
.99				pha
				lda hDstFile
				>SYSCALL SYS.MLICloseA
				lda hDstBuf
				>SYSCALL SYS.FreeMemA
				pla
				sec
				rts
*--------------------------------------
CS.DOEVENT		ldy #S.EVT.hDEV		is Event from active IN device?
				lda (pEvent),y
				ldy #S.PS.hINDEV
				cmp (pPs),y
				bne .9

				lda (pEvent)
				and #S.EVT.F.KEY		is it a KEY event?
				beq .9

				ldy #S.EVT.DATAHI		is it an O or SAPPLE key ?
				lda (pEvent),y
				bne	.9

				ldy #S.EVT.DATALO	
				lda (pEvent),y
				cmp #$03				Ctrl-C
				bne .1

				lda #$FF
				ldy #bCANCEL
				sta (pData),y
				bra .8
				
.1				cmp #$13				Ctrl-S
				bne .8
				
				ldy #bSTOP
				lda (pData),y
				eor #$FF
				sta (pData),y

.8				clc
				rts
				
.9				sec
				rts
*--------------------------------------
CS.QUIT			jsr CloseDirList
				bcc CS.QUIT
				
				lda hSrcPath
				beq .1
				>SYSCALL SYS.FreeMemA
				
.1				lda hDstPath
				beq .8
				>SYSCALL SYS.FreeMemA
				
.8				clc
				rts
*--------------------------------------
*				PRIVATE
*--------------------------------------
NewDirListYA	>SYSCALL SYS.ListDirInitYA
				bcs .9
				tax
				ldy #hS.LISTDIR.IDX
				lda (pData),y
				inc
				cmp #hS.LISTDIR.IDX+MAX.RECURSE+1
				beq .9					CS
				sta (pData),y
				tay
				txa
				sta (pData),y
			
				clc
.9				rts				
*--------------------------------------
CloseDirList	jsr GetDirList
				bcs .9
				
				>SYSCALL SYS.ListDirCloseA
				ldy #hS.LISTDIR.IDX
				lda (pData),y
				tay
				lda #0
				sta (pData),y
				tya
				ldy #hS.LISTDIR.IDX
				dec
				sta (pData),y
				cmp #hS.LISTDIR.IDX
				beq .9					CS
				
				lda (pData)
				tay
				
.1				dey
				lda (pData),y
				cmp #'/'
				bne .1
				
				tya
				sta (pData)				cut DIR2/ from /dir1/DIR2/
				
				clc
.9				rts
*--------------------------------------
GetDirList		ldy #hS.LISTDIR.IDX
				lda (pData),y
				cmp #hS.LISTDIR.IDX
				beq .9					CS
				tay
				lda (pData),y
				clc
.9				rts
*--------------------------------------
CS.END
MSG.USAGE		>PSTRING "Usage : CP [-R -C] <Src file/Dir, *,? wildcards allowed> [Dest Dir]\n -R recurse subdirs\n -C resume on error\n"
MSG.CP			>PSTRING "cp: %S to %S "
MSG.OK			>PSTRING "[Ok]\n"
MSG.ERR			>PSTRING "[%h]\n"
hSrcPath		.BS 1
hDstPath		.BS 1
FullSrcPath		.BS 64
FullDstPath		.BS 64
FINFO			.BS S.FINFO
hSrcFile		.BS 1
hSrcBuf			.BS 1
hDstFile		.BS 1
hDstBuf			.BS 1
hCopyBuf		.BS 1
*--------------------------------------
				.DUMMY
				.OR 0
DS.START
DstPath			.BS 64					(pData)
hS.LISTDIR.IDX	.BS 1
hS.LISTDIRS		.BS MAX.RECURSE
bSTOP			.BS 1
bCANCEL			.BS 1
bRECURSE		.BS 1
bCONTINUEONERR	.BS 1
DS.END
				.ED
*--------------------------------------
MAN
SAVE BIN/CP.S
ASM
