NEW
  AUTO 3,1
				.LIST OFF
				.OP	65C02
				.OR	$2000
				.TF bin/bmp2pix
*--------------------------------------
				.INB inc/macros.i
				.INB inc/a2osx.i
				.INB inc/io.i
				.INB inc/gfx.i
				.INB inc/libgui.i
*--------------------------------------
S.BMP.SIG		.EQ 0
S.BMP.SIZE		.EQ 2
S.BMP.DATA.OFS	.EQ $A
S.BMP.HDR.SIZE	.EQ $E
S.BMP.W			.EQ $12
S.BMP.H			.EQ $16
S.BMP.PLANES	.EQ $1A
S.BMP.BPP		.EQ $1C
*
S.BMP			.EQ $36
*--------------------------------------
				.DUMMY
				.OR ZPBIN
ZS.START
ZPPtr1			.BS 2
ZPInputBuf		.BS 2
ZPInputBufPtr	.BS 2
ZPInputRowBytes	.BS 2

ZPLineCount		.BS 2
ZPPixelCount	.BS 2
ZPOutputBuf		.BS 2
ZPOutputRowBytes	.BS 2

ZPPixel24		.BS 3
ZPPixelScore	.BS 3
ZPCntX			.BS 1
ZPCntY			.BS 1

ZPPixelBest		.BS 3
ZPPixelIndex16	.BS 1

ZBTmpW1			.BS 2
ZBTmpW2			.BS 2

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					S.PS.F.EVENT
				.DA #0
				.DA CS.END-CS.START		CS
				.DA DS.END-DS.START		DS
				.DA #64					SS
				.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.MSG.USAGE		.DA MSG.USAGE
L.MSG.HEADER.OK	.DA MSG.HEADER.OK
L.MSG.HEADER.KO	.DA MSG.HEADER.KO
L.MSG.DONE		.DA MSG.DONE
				.DA 0
*--------------------------------------
CS.INIT			clc
				rts
*--------------------------------------
CS.RUN
.1				>INC.G ArgCount
				>SYSCALL ArgV
				bcs .7
				>STYA ZPPtr1
				lda (ZPPtr1)
				cmp #'-'
				bne .4
				ldy #1
				lda (ZPPtr1),y

				ldx #OptionVars-OptionList

.2				cmp OptionList-1,x
				beq .3
				dex
				bne .2

.99				>PUSHW L.MSG.USAGE
				>PUSHBI 0
				>SYSCALL PrintF
				lda #E.SYN
				sec
				rts

.3				ldy OptionVars-1,x
				lda #$80
				sta (pData),y
				bra .1

.4				>LDA.G hInputFile
				bne .5

				jsr CS.RUN.OpenInput
				bcc .1					scan for any other args

				rts

.5				>LDA.G hOutputFile
				bne .99

				jsr CS.RUN.CreateOutput
				bcc .1					scan for any other args
.9				rts

.7				>LDA.G hOutputFile
				beq .99

				>LDA.G BMP.Header+S.BMP.BPP
				cmp #1
				beq CS.RUN.1
				jmp CS.RUN.24
*--------------------------------------
CS.RUN.1		lda #S.BM.F.BBP1
				>STA.G PIX.Header+S.BM.F

*				>LDA.G PIX.Header+S.BM.W
*				sta ZPBMPRowBytes
*				sta ZPPIXRowBytes
*				iny
*				lda (pData),y
*				sta ZPBMPRowBytes+1
*				sta ZPPIXRowBytes+1
*				lda ZPBMPRowBytes
*				and #%00011111
*				beq .1
*				lda ZPBMPRowBytes
*				and #%11100000
*				clc
*				adc #%00100000
*				bcc .1
*				inc ZPBMPRowBytes+1
*.1				lsr ZPBMPRowBytes+1
*				ror
*				lsr ZPBMPRowBytes+1
*				ror
*				lsr ZPBMPRowBytes+1
*				ror
*				sta ZPBMPRowBytes
*				lda ZPPIXRowBytes
*				and #%00000111
*				beq .2
*				lda ZPPIXRowBytes
*				and #%11111000
*				clc
*				adc #%00001000
*				bcc .2
*				inc ZPPIXRowBytes+1
*.2				lsr ZPPIXRowBytes+1
*				ror
*				lsr ZPPIXRowBytes+1
*				ror
*				lsr ZPPIXRowBytes+1
*				ror
*				sta ZPPIXRowBytes
*				>STA.G PIX.Header+S.BM.RowBytes
*				lda ZPInputBufPtr
*				clc
*				adc	ZPInputBufLen
*				sta ZPInputDataPtr
*				lda ZPInputBufPtr+1
*				adc	ZPInputBufLen+1
*				sta ZPInputDataPtr+1
*				jsr CS.RUN.WRITE.HDR
*				bcs CS.RUN.RTS
*CS.RUN.1.LOOP	inc ZPLineCount
*				bne .1
*				inc ZPLineCount+1
*				beq .8
*.1				lda ZPInputDataPtr
*				sec
*				sbc ZPBMPRowBytes
*				sta ZPInputDataPtr
*				lda ZPInputDataPtr+1
*				sbc ZPBMPRowBytes+1
*				sta ZPInputDataPtr+1
*				>LDYA ZPBufPtr
*				>STYA ZPPtr1
*				ldy #0
*.2				lda (ZPInputDataPtr),y
*				tax
*				lda TWIST,x
*				sta (ZPPtr1)
*				inc ZPPtr1
*				bne .3
*				inc ZPPtr1+1
*.3				iny
*				cpy ZPPIXRowBytes
*				bne .2
*				>PUSHW ZPPIXRowBytes
*				>PUSHW ZPOutputBufPtr
*				>LDA.G hOutputFile
*				>SYSCALL FWrite
*				bcs CS.RUN.RTS
*				bra CS.RUN.1.LOOP
*.8				>LDYA L.MSG.DONE
*				>SYSCALL PutS
*				lda #0
*				sec
CS.RUN.RTS		rts
*--------------------------------------
CS.RUN.24		lda #S.BM.F.BBP4
				>STA.G PIX.Header+S.BM.F

				>LDA.G BMP.Header+S.BMP.W
				asl
				sta ZPInputRowBytes
				>LDA.G BMP.Header+S.BMP.W+1
				rol
				sta ZPInputRowBytes+1
				lda ZPInputRowBytes
				clc
				>ADC.G BMP.Header+S.BMP.W
				pha
				lda ZPInputRowBytes+1
				>ADC.G BMP.Header+S.BMP.W+1
				tax
				pla
				bit #%00000011
				beq .1
				and #%11111100
				clc
				adc #4
				bcc .1

				inx

.1				sta ZPInputRowBytes
				stx ZPInputRowBytes+1

				>LDYA ZPInputRowBytes
				>SYSCALL GetMem
				bcs CS.RUN.RTS

				>STYA ZPInputBuf
				txa
				>STA.G hInputBuf
				>LDA.G PIX.Header+S.BM.W+1
				lsr
				tax
				>LDA.G PIX.Header+S.BM.W
				ror
				bcc .2
				inc
				bne .2
				inx

.2				sta ZPOutputRowBytes
				stx ZPOutputRowBytes+1
				>STA.G PIX.Header+S.BM.RowBytes
*				txa
*				>STA.G PIX.Header+S.BM.RowBytes+1
				jsr CS.RUN.GetOutputBuf
				bcs CS.RUN.RTS
				jsr DEBUG.ClrScr
				lda #$ff
				sta ZPCntY

CS.RUN.24.LOOP	inc ZPLineCount
				bne .1

				inc ZPLineCount+1
				beq .8

.1				inc ZPCntY
				lda #$ff
				sta ZPCntX
				jsr CS.RUN.ReadInput
				bcs .9

				lda ZPOutputBuf
				sec
				sbc ZPOutputRowBytes
				sta ZPOutputBuf
				lda ZPOutputBuf+1
				sbc ZPOutputRowBytes+1
				sta ZPOutputBuf+1

.2				inc ZPPixelCount
				bne .3
				inc ZPPixelCount+1
				beq CS.RUN.24.LOOP
.3				inc ZPCntX
				ldx #2
				ldy #0
.4				lda (ZPInputBufPtr),y
				sta ZPPixel24,x
				iny
				dex
				bpl .4
				lda ZPInputBufPtr
				clc
				adc #3
				sta ZPInputBufPtr
				bcc .5
				inc ZPInputBufPtr+1
.5				jsr CS.RUN.GetNearestColor

				pha

				jsr DEBUG.PLOT

				lda ZPCntX
				lsr
				tay
				pla
				bcs .6

				sta (ZPOutputBuf),y
				bra .2

.6				asl
				asl
				asl
				asl
				ora (ZPOutputBuf),y
				sta (ZPOutputBuf),y
				bra .2

.8				jsr CS.RUN.WriteOutput
				bcs .9
				lda #0
				sec
.9				rts
*--------------------------------------
CS.RUN.GetNearestColor
				stz ZPPixelIndex16

				lda #$ff
				sta ZPPixelBest
				sta ZPPixelBest+1
				sta ZPPixelBest+2

				ldy #63

.30				stz ZPPixelScore
				stz ZPPixelScore+1
				stz ZPPixelScore+2

				ldx #2

.40				phx						A = |c - C|

				dey
				lda PALETTE.RGB,y
				sec
				sbc ZPPixel24,x
				bcs .5

				eor #$ff
				inc

.5				sta ZBTmpW1
				stz ZBTmpW1+1

				stz ZBTmpW2
				stz ZBTmpW2+1

				ldx #8					compute A²

.1				lsr
				bcc .2

				pha

				lda ZBTmpW1
				clc
				adc ZBTmpW2
				sta ZBTmpW2

				lda ZBTmpW1+1
				adc ZBTmpW2+1
				sta ZBTmpW2+1

				pla

.2				asl	ZBTmpW1
				rol ZBTmpW1+1
				dex
				bne .1

				lda ZPPixelScore			compute A²+b+c²
				clc
				adc ZBTmpW2
				sta ZPPixelScore

				lda ZPPixelScore+1
				adc ZBTmpW2+1
				sta ZPPixelScore+1

				bcc .3
				inc ZPPixelScore+2

.3				plx

				dex
				bpl .40

				lda ZPPixelBest
				cmp ZPPixelScore

				lda ZPPixelBest+1
				sbc ZPPixelScore+1

				lda ZPPixelBest+2
				sbc ZPPixelScore+2
				bcc .8

				lda ZPPixelScore
				sta ZPPixelBest

				lda ZPPixelScore+1
				sta ZPPixelBest+1

				lda ZPPixelScore+2
				sta ZPPixelBest+2

				tya
				lsr
				lsr
				sta ZPPixelIndex16

.8				dey
				bpl .30

				lda ZPPixelIndex16
CS.RUN.GetIndexInPalette.RTS
				rts
*--------------------------------------
CS.RUN.OpenInput
				>PUSHW ZPPtr1
				>PUSHBI	O.RDONLY
				>PUSHBI 0				Type
				>PUSHWZ				Aux type
				>SYSCALL FOpen
				bcs CS.RUN.GetIndexInPalette.RTS

				>STA.G hInputFile

				>PUSHWI S.BMP
				>PUSHEA.G BMP.Header
				>LDA.G hInputFile
				>SYSCALL FRead
				bcs CS.RUN.GetIndexInPalette.RTS

				>LDA.G BMP.Header+S.BMP.SIG
				cmp #'B'
				bne .99
				iny
				lda (pData),y
				cmp #'M'
				bne .99
				>LDA.G BMP.Header+S.BMP.BPP+1
				bne .99
				dey
				lda (pData),y
				cmp #1
				beq .1
				cmp #24
				bne .99

.1				>PUSHW L.MSG.HEADER.OK

				>LDA.G BMP.Header+S.BMP.W
				>STA.G PIX.Header+S.BM.W
				pha
				>LDA.G BMP.Header+S.BMP.W+1
				>STA.G PIX.Header+S.BM.W+1
				>PUSHA
				pla
				>PUSHA

				>LDA.G BMP.Header+S.BMP.H
				>STA.G PIX.Header+S.BM.H
				pha
				eor #$ff
				sta ZPLineCount

				>LDA.G BMP.Header+S.BMP.H+1
				>STA.G PIX.Header+S.BM.H+1
				>PUSHA
				eor #$ff
				sta ZPLineCount+1
				pla
				>PUSHA

				>PUSHB.G BMP.Header+S.BMP.BPP

				>PUSHBI 5
				>SYSCALL PrintF
.9				rts

.99				>LDYA L.MSG.HEADER.KO
				>SYSCALL PutS
				lda #E.IBIN
				sec
				rts
*--------------------------------------
CS.RUN.ReadInput
				>PUSHB.G hInputFile
				>PUSHW ZPInputBuf
				>PUSHW ZPInputRowBytes
				>SYSCALL FRead
				bcs .9

				>LDYA ZPInputBuf
				>STYA ZPInputBufPtr
				>LDA.G BMP.Header+S.BMP.W
				eor #$ff
				sta ZPPixelCount
				>LDA.G BMP.Header+S.BMP.W+1
				eor #$ff
				sta ZPPixelCount+1
.9				rts
*--------------------------------------
CS.RUN.CreateOutput
				>PUSHW ZPPtr1
				>PUSHBI	O.WRONLY+O.CREATE
				>PUSHBI $CB				PIX Type
				>PUSHWZ					Aux type
				>SYSCALL FOpen
				bcs .9
				>STA.G hOutputFile
.9				rts
*--------------------------------------
CS.RUN.GetOutputBuf
				stz ZPPtr1
				stz ZPPtr1+1
				ldy ZPLineCount
				ldx ZPLineCount+1
.1				iny
				bne .2
				inx
				beq .8
.2				lda ZPPtr1
				clc
				adc ZPOutputRowBytes
				sta ZPPtr1
				lda ZPPtr1+1
				adc ZPOutputRowBytes+1
				sta ZPPtr1+1
				bra .1
.8				>LDYA ZPPtr1
				>SYSCALL GetMem
				bcs .9

				>STYA ZPOutputBuf
				txa
				>STA.G hOutputBuf

				lda ZPPtr1
				>STA.G OutputDataLen
				clc
				adc ZPOutputBuf
				sta ZPOutputBuf
				lda ZPPtr1+1
				>STA.G OutputDataLen+1
				adc ZPOutputBuf+1
				sta ZPOutputBuf+1

				clc
.9				rts
*--------------------------------------
CS.RUN.WriteOutput
				>LDA.G bNoHeader
				bmi .1
				
				>PUSHB.G hOutputFile
				>PUSHEA.G PIX.Header
				>PUSHWI S.BM
				>SYSCALL FWrite
				bcs .9

.1				>PUSHB.G hOutputFile
				>PUSHW ZPOutputBuf
				>PUSHW.G OutputDataLen
				>SYSCALL FWrite
.9				rts
*--------------------------------------
CS.DOEVENT		sec
				rts
*--------------------------------------
CS.QUIT			>LDA.G hOutputBuf
				beq .1
				>SYSCALL FreeMem

.1				>LDA.G hInputBuf
				beq .2
				>SYSCALL FreeMem
.2				>LDA.G hOutputFile
				beq .3

				>SYSCALL FClose
.3				>LDA.G hInputFile
				beq .8

				>SYSCALL FClose
.8				clc
				rts
*--------------------------------------
DEBUG.ClrScr	sta SETMIXED
				sta CLRTEXT
				ldx #19
.1				lda SCR.BASEL,x
				sta ZPPtr1
				lda SCR.BASEH,x
				sta ZPPtr1+1

				lda #0
				ldy #39

.2				sta SETPAGE2
				sta (ZPPtr1),y
				sta CLRPAGE2
				sta (ZPPtr1),y

				dey
				bpl .2
				dex
				bpl .1
				rts
*--------------------------------------
DEBUG.PLOT		php
				sei

				pha
				tax

				lda ZPCntY
				cmp #40
				bcs .9

				lda ZPCntX
				cmp #80
				bcs .9

				lsr
				tay

				bcs .1					CS = main

				sta SETPAGE2
				lda PALETTE.AUX,x
				bra .2

.1				sta CLRPAGE2
				lda PALETTE.MAIN,x

.2				pha

				lda #39
				sec
				sbc ZPCntY
				lsr
				tax
				lda SCR.BASEL,x
				sta ZPPtr1
				lda SCR.BASEH,x
				sta ZPPtr1+1
				pla
				bcc .3

				asl
				asl
				asl
				asl

.3				ora (ZPPtr1),y
				sta (ZPPtr1),y
				sta CLRPAGE2

.9				pla
				plp
				rts
*--------------------------------------
SCR.BASEL		.HS	00.80.00.80.00.80.00.80.28.A8.28.A8.28.A8.28.A8.50.D0.50.D0.50.D0.50.D0
SCR.BASEH		.HS	04.04.05.05.06.06.07.07.04.04.05.05.06.06.07.07.04.04.05.05.06.06.07.07
*--------------------------------------
CS.END
*--------------------------------------
				.INB usr/src/shared/x.twist.g
*--------------------------------------
OptionList		.AS "VvHh"
OptionVars		.DA #bVerbose,#bVerbose,#bNoHeader,#bNoHeader
MSG.USAGE		.CS "Usage : BMP2PIX BMP-File\r\n"
				.CZ "   -V : Verbose Mode\r\n"
MSG.HEADER.OK	.CZ "BMP Size : %D x %D pixels, %d bit(s)/pixel\r\n"
MSG.HEADER.KO	.CZ "Invalid Input File Format"
MSG.DONE		.CZ "All Done!!!"
*--------------------------------------
* LOWRES Patette : https://comp.sys.apple2.narkive.com/lTSrj2ZI/apple-ii-colour-rgb
*--------------------------------------
*PALETTE.RGB	.HS 00000000			BLACK
*				.HS 604ebd00			DARK.BLUE
*				.HS 00a36000			DARK.GREEN
*				.HS 14cffd00			BLUE
*				.HS 60720300			BROWN
*				.HS 7e7e7e00			DARK.GRAY
*				.HS 14f53c00			LIGHT.GREEN
*				.HS 72ffd000			AQUA
*				.HS e31e6000			RED
*				.HS ff44fd00			PURPLE
*				.HS 9c9c9c00			LIGHT.GRAY
*				.HS d0c3ff00			LIGHT.BLUE
*				.HS ff6a3c00			ORANGE
*				.HS ffa0d000			PINK
*				.HS d0dd8d00			YELLOW
*				.HS ffffff00			WHITE
*--------------------------------------
*PALETTE.RGB		.DA #0,#0,#0,#0			0  Black
*				.DA #255,#255,#255,#0	15 White
*				.DA #126,#126,#126,#0	5  Grey1
*				.DA #156,#156,#156,#0	10 Grey2
*				.DA #96,#78,#189,#0		8  Dark Blue
*				.DA #20,#207,#253,#0	12 Medium Blue
*				.DA #208,#195,#255,#0	13 Light Blue
*				.DA #0,#163,#96,#0		4  Dark Green
*				.DA #20,#245,#60,#0		6  Green
*				.DA #114,#255,#208,#0	14 Aqua
*				.DA #255,#68,#253,#0	9  Violet
*				.DA #255,#160,#208,#0	11 Pink
*				.DA #227,#30,#96,#0		1  Magenta
*				.DA #96,#114,#3,#0		2  Brown
*				.DA #255,#106,#60,#0	3  Orange
*				.DA #208,#221,#141,#0	7  Yellow
*--------------------------------------
PALETTE.RGB		.HS 00000000			BLACK
				.HS 1f35D300			DARK.BLUE
				.HS 00760c00			DARK.GREEN
				.HS 07a8e000			BLUE
				.HS 624c0000			BROWN
				.HS 7e7e7e00			DARK.GRAY
				.HS 43c80000			LIGHT.GREEN
				.HS 5df78400			AQUA
				.HS 930B7c00			RED
				.HS bb36ff00			PURPLE
				.HS 9c9c9c00			LIGHT.GRAY
				.HS b5afff00			LIGHT.BLUE
				.HS f9561d00			ORANGE
				.HS ff81ec00			PINK
				.HS dccd1600			YELLOW
				.HS ffffff00			WHITE
*--------------------------------------
PALETTE.MAIN	.HS 00.02.04.06.08.0A.0C.0E
				.HS 01.03.05.07.09.0B.0D.0F

PALETTE.AUX		.HS 00.01.02.03.04.05.06.07
				.HS 08.09.0A.0B.0C.0D.0E.0F

*PALETTE.AUX	.HS 00.08.01.09.02.0A.03.0B
*				.HS	04.0C.05.0D.06.0E.07.0F
*--------------------------------------
				.DUMMY
				.OR 0
DS.START
ArgCount		.BS 1
bVerbose		.BS 1
bNoHeader		.BS 1
hInputFile		.BS 1
hInputBuf		.BS 1
hOutputFile		.BS 1
hOutputBuf		.BS 1
OutputDataLen	.BS 2
BMP.Header		.BS	S.BMP
PIX.Header		.BS	S.BM
DS.END
				.ED
*--------------------------------------
MAN
SAVE usr/src/bin/bmp2pix.s
ASM
