NEW
  AUTO 3,1
				.LIST OFF
				.OP	65C02
				.OR	$2000
				.TF BIN/PAKME
*--------------------------------------
				.INB INC/MACROS.I
				.INB INC/A2OSX.I
				.INB INC/KERNEL.I
				.INB INC/PAK.I
				.INB INC/LIBPAK.I
				.INB INC/MLI.E.I
*--------------------------------------
CHUNK.MAX		.EQ 32
*--------------------------------------
				.DUMMY
				.OR ZPBIN
ZS.START
ZPPtr1			.BS 2
ZPPtr2			.BS 2
ZPSrcFileSize	.BS 2
ZPDstTableOfs	.BS 2

hSrcFile		.BS 1
hDstFile		.BS 1
ZPChunkIndex	.BS 1
ZPChunkCnt		.BS 1
ZPChunkOfs		.BS 2
ZPChunkLen		.BS 2

ZPChunkPakedLen	.BS 2
ZPChunkNewOfs	.BS 2
hSrcBuf			.BS 1
hDstBuf			.BS 1
ZPSrcBufPtr		.BS 2
ZPDstBufPtr		.BS 2

bPause			.BS 1

ZS.END			.ED
*--------------------------------------
*			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 Size (without Constants)
				.DA DS.END-DS.START		Data SegmentSize
				.DA #64					Stack Size
				.DA #ZS.END-ZS.START	Zero Page Size
				.DA 0
*--------------------------------------
* Relocation Table
*--------------------------------------
.1				.DA CS.INIT
				.DA CS.RUN
				.DA CS.DOEVENT		
				.DA	CS.QUIT
L.LIBPAK		.DA LIBPAK
L.MSG.USAGE		.DA MSG.USAGE
L.MSG.SRCFILE	.DA MSG.SRCFILE
L.MSG.CHUNK		.DA MSG.CHUNK
L.MSG.PAKED		.DA MSG.PAKED
L.MSG.STORE		.DA MSG.STORE
L.MSG.E.IARC	.DA MSG.E.IARC
L.TAG			.DA TAG
				.DA 0
*--------------------------------------
CS.INIT			>LDYA L.LIBPAK
				>SYSCALL LoadLib
				bcs .9
				
				sta hLIB

.9				rts
*--------------------------------------
CS.RUN			ldy #S.PS.ARGC
				lda (pPs),y

				cmp #2
				bne .9

				jsr CS.RUN.CheckSrcFile
				bcs .99

				>PUSHW.G STATBUF+S.STAT.P.AUXTYPE
				>PUSHB.G STATBUF+S.STAT.P.TYPE
				>PUSHBI	O.CREATE+O.WRONLY
				lda #2
				>SYSCALL ArgV

				>SYSCALL FOpen
				bcs .99
				
				sta hDstFile
				
				bra CS.RUN.START
				
.9				>PUSHBI 0
				>LDYA L.MSG.USAGE
				>SYSCALL printf
				lda #E.SYN
				sec
.99				rts
*--------------------------------------
CS.RUN.START	>PUSHW ZPDstTableOfs
				>PUSHB.G PAKME.HEADER+7
				>PUSHW.G PAKME.HEADER+5
				>PUSHW ZPSrcFileSize
				lda #1
				>SYSCALL ArgV
				>PUSHYA
				
				>PUSHBI 9
				>LDYA L.MSG.SRCFILE
				>SYSCALL printf

				>LDYA ZPDstTableOfs
				jsr CS.RUN.GetSrcBufYA
				bcs CS.RUN.RTS

				>PUSHBI SEEK.SET
				>PUSHWZ
				>PUSHWZ
				lda hSrcFile
				>SYSCALL fseek
				bcs CS.RUN.RTS

				>PUSHW ZPDstTableOfs
				>PUSHW ZPSrcBufPtr
				lda hSrcFile
				>SYSCALL fread
				bcs CS.RUN.RTS
				
				>PUSHW ZPDstTableOfs
				>PUSHW ZPSrcBufPtr
				lda hDstFile
				>SYSCALL fwrite
				bcs CS.RUN.RTS

				jsr CS.QUIT.BUF
				
				jsr CS.RUN.WriteTable	Write Fake table

				bcc CS.RUN.LOOP
				
CS.RUN.RTS		rts				
*--------------------------------------
CS.RUN.LOOP		ldy #S.PS.hStdIn
				lda (pPS),y
				>SYSCALL feof
				bcs CS.RUN.RTS
				
				tay
				bne .1
				
				>SYSCALL GetChar
				bcs CS.RUN.RTS
				
				cmp #$03				Ctrl-C
				beq CS.RUN.RTS			Abort....
				
				cmp #$13				Ctrl-S
				bne .1

				lda bPause
				eor	#$ff
				sta bPause
				bne CS.RUN.LOOP
				
.1				lda bPause
				bne CS.RUN.LOOP			Pause...
*--------------------------------------
				jsr CS.RUN.GetChunk
				bcs CS.RUN.RTS
				
				>PUSHW ZPChunkLen
				>PUSHW ZPChunkOfs
				lda ZPChunkIndex
				inc
				>PUSHA
				>PUSHBI 5
				>LDYA L.MSG.CHUNK
				>SYSCALL printf
				bcs .9

				jsr CS.RUN.Pak
				bcs .2

				jsr CS.RUN.WritePak
				bcc .7
				rts
				
.2				jsr CS.RUN.WriteStore
				bcs .9

.7				jsr CS.QUIT.BUF
				
				jsr CS.RUN.UpdateTable
				inc ZPChunkIndex
				dec ZPChunkCnt
				beq .8
				
				jmp CS.RUN.LOOP
				
.8				jsr CS.RUN.RewriteTable	Write modified Table
				bcs .9
				
				lda #0
				sec
.9				rts
*--------------------------------------
CS.RUN.CheckSrcFile
				>PUSHWZ					Aux type
				>PUSHBI 0				Type
				>PUSHBI	O.RDONLY
				lda #1
				>SYSCALL ArgV
				
				>SYSCALL FOpen
				bcs .99
				
				sta hSrcFile
				
				>PUSHEA.G STATBUF
				lda hSrcFile
				>SYSCALL fstat
.99				bcs .9
				
				>LDA.G STATBUF+S.STAT.SIZE+3
				dey
				ora (pData),y
				bne .90

				dey
				lda (pData),y
				sta ZPSrcFileSize+1
				dey
				lda (pData),y
				sta ZPSrcFileSize
								
				jsr CS.RUN.CheckTAG
				bcs .9
				
				jsr CS.RUN.GetTable
				bcs .9
				
				
				clc
				rts
				
.90				lda #MLI.E.INCFF
				sec
.9				
CS.RUN.CheckSrcFile.RTS
				rts				
*--------------------------------------
CS.RUN.CheckTAG	>PUSHBI SEEK.SET
				>PUSHWZ

				lda ZPSrcFileSize
				sec
				sbc #10
				tay
				lda ZPSrcFileSize+1
				sbc #0
				>PUSHYA
				
				lda hSrcFile
				>SYSCALL fseek
				bcs CS.RUN.CheckSrcFile.RTS
				
				>PUSHWI 10
				>PUSHEA.G PAKME.HEADER
				lda hSrcFile
				>SYSCALL fread
				bcs CS.RUN.CheckSrcFile.RTS
				
				ldx #4
				
				ldy #PAKME.HEADER+4

.1				lda TAG,x
				cmp (pData),y
				bne .90
				dey
				dex
				bpl .1
				
				clc
				rts
				
.90				lda #MLI.E.INCFF
				sec
.9				rts
*--------------------------------------
CS.RUN.GetTable	>LDA.G PAKME.HEADER+8
				sec
				>SBC.G PAKME.HEADER+5
				sta ZPDstTableOfs

				>LDA.G PAKME.HEADER+9
				>SBC.G PAKME.HEADER+6
				sta ZPDstTableOfs+1

				>PUSHBI SEEK.SET
				>PUSHWZ
				>PUSHW ZPDstTableOfs
				lda hSrcFile
				>SYSCALL fseek
				bcs .9
				
				>LDA.G PAKME.HEADER+7
				sta ZPChunkCnt

				asl
				tay
				lda #0
				>PUSHYA
				
				>PUSHEA.G PAKME.TABLE
				lda hSrcFile
				>SYSCALL fread

.9				rts
*--------------------------------------
CS.RUN.GetChunk	lda ZPChunkIndex
				
				asl
				clc
				adc #PAKME.TABLE+1
				tay
				lda (pData),y
				pha
				dey
				lda (pData),y
				sec
				ldy #PAKME.HEADER+5
				sbc (pData),y
				sta ZPChunkOfs
				
				iny
				pla
				sbc (pData),y
				sta ZPChunkOfs+1

				>PUSHBI SEEK.SET
				>PUSHWZ
				>PUSHW ZPChunkOfs
				lda hSrcFile
				>SYSCALL fseek
				bcs .9
				
				>PUSHWI 3
				>PUSHEA.G CHUNK.HEADER
				lda hSrcFile
				>SYSCALL fread
				bcs .9
				
				>LDA.G CHUNK.HEADER
				bne .90

				>LDA.G CHUNK.HEADER+1
				sta ZPChunkLen
				pha
				iny
				lda (pData),y
				sta ZPChunkLen+1
				ply
				
				jsr CS.RUN.GetSrcBufYA
				bcs .9
				
				>PUSHW ZPChunkLen
				>PUSHW ZPSrcBufPtr
				lda hSrcFile
				>SYSCALL fread
				bcs .9
				
*				clc
				rts

.90				lda #MLI.E.INCFF
				sec
				
.9				rts				
*--------------------------------------
CS.RUN.GetSrcBufYA
				>SYSCALL getmem
				bcs .9
				stx hSrcBuf
				>STYA ZPSrcBufPtr
.9				rts				
*--------------------------------------
CS.RUN.Pak		>LDYA ZPChunkLen
				>SYSCALL getmem
				bcs .9
				stx hDstBuf
				>STYA ZPDstBufPtr

				>PUSHEA.G PAKSTAT
				>PUSHW ZPDstBufPtr
				>PUSHW ZPChunkLen
				>PUSHW ZPSrcBufPtr
				>LIBCALL hLIB,LIBPAK.Pak
				bcs .9
				>STYA ZPChunkPakedLen
.9				rts
*--------------------------------------
CS.RUN.RewriteTable
				>PUSHBI SEEK.SET
				>PUSHWZ
				>PUSHW ZPDstTableOfs
				lda hDstFile
				>SYSCALL fseek
				bcs CS.RUN.WriteTable.RTS
*--------------------------------------
CS.RUN.WriteTable
				>LDA.G PAKME.HEADER+7
				asl
				tay
				lda #0
				>PUSHYA
				>PUSHEA.G PAKME.TABLE
				lda hDstFile
				>SYSCALL fwrite
CS.RUN.WriteTable.RTS				
				rts
*--------------------------------------
CS.RUN.WritePak	lda hDstFile
				>SYSCALL ftell
				bcs .9
				
				>PULLW ZPChunkNewOfs
				inc pStack
				inc pStack
				
				>PUSHW ZPChunkPakedLen
				>PUSHW ZPDstBufPtr
				lda hDstFile
				>SYSCALL fwrite
				bcs .9
				
				>PUSHW ZPChunkNewOfs
				>PUSHW ZPChunkPakedLen
				>PUSHBI 4
				>LDYA L.MSG.PAKED
				>SYSCALL printf				
				
.9
CS.RUN.WritePak.RTS
				rts
*--------------------------------------
CS.RUN.WriteStore
				lda hDstFile
				>SYSCALL ftell
				bcs CS.RUN.WritePak.RTS
				
				>PULLW ZPChunkNewOfs
				inc pStack
				inc pStack
				
				>PUSHWI 3
				>PUSHEA.G CHUNK.HEADER
				lda hDstFile
				>SYSCALL fwrite
				bcs .9
	
				>PUSHW ZPChunkLen
				>PUSHW ZPSrcBufPtr
				lda hDstFile
				>SYSCALL fwrite
				bcs .9
				
				>PUSHW ZPChunkNewOfs
				>PUSHW ZPChunkLen
				>PUSHBI 4
				>LDYA L.MSG.STORE
				>SYSCALL printf				
				
.9				rts
*--------------------------------------
CS.RUN.UpdateTable
				ldy #PAKME.HEADER+6
				lda (pData),y
				pha
				
				dey
				lda (pData),y
				pha

				lda ZPChunkIndex
				
				asl
				clc
				adc #PAKME.TABLE
				tay

				pla
				clc
				adc ZPChunkNewOfs
				sta (pData),y
				
				iny
				
				pla
				adc ZPChunkNewOfs+1
				sta (pData),y
				rts
*--------------------------------------
CS.DOEVENT		sec
				rts
*--------------------------------------
CS.QUIT			lda hDstFile
				beq .2
				>SYSCALL fclose
				
.2				lda hSrcFile
				beq .3
				>SYSCALL fclose
				
.3				jsr CS.QUIT.BUF

				lda hLIB
				beq .8
				
				>SYSCALL UnloadLib
				
.8				clc
				rts
*--------------------------------------
CS.QUIT.BUF		lda hDstBuf
				beq .1
				stz hDstBuf
				>SYSCALL FreeMem

.1				lda hSrcBuf
				beq .8
				stz hSrcBuf
				>SYSCALL FreeMem
				
.8				rts				
*--------------------------------------
CS.END
*--------------------------------------
MSG.USAGE		.AZ "Usage : PAKME SourceBIN PackedBIN\r\n"
MSG.SRCFILE		.AZ "Source File : %s, Size=%5D, Org=$%H, %d Chunks at $%H.\r\n"
MSG.CHUNK		.AZ "  Chunk #%02d : Ofs=$%H, Len=%5D ... "
MSG.PAKED		.AZ "PAKed : %5D Bytes, New Ofs=$%H\r\n"
MSG.STORE		.AZ "Store : %5D Bytes, New Ofs=$%H\r\n"
MSG.E.IARC		.AZ "Invalid/corrupt archive"
TAG				.AZ "PAKME"
*--------------------------------------
LIBPAK			.AZ "libpak"
hLIB			.BS 1
*--------------------------------------
				.DUMMY
				.OR 0
DS.START
STATBUF			.BS S.STAT
PAKME.HEADER	.BS 10
PAKME.TABLE		.BS CHUNK.MAX*2
CHUNK.HEADER	.BS 3
PAKSTAT			.BS S.PAKSTAT
DS.END			.ED
*--------------------------------------
MAN
SAVE USR/SRC/BIN/PAKME.S
ASM
