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
ZPPixelBest		.BS 3

ZPPixelIndex16	.BS 1
ZBTmpB1			.BS 1
ZBTmpW			.BS 2

ZPCntX			.BS 1
ZPCntY			.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					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 OptionList
				
.2				cmp OptionList,x
				beq .3
				dex
				bne .2
				
.99				>PUSHBI 0
				>LDYA L.MSG.USAGE
				>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				lda PALETTE.RGB-1,y
				sec
				sbc ZPPixel24,x
				bcs .5
				
				eor #$ff
				inc
				
.5				phx
  
				sta ZBTmpB1
				sta ZBTmpW
				stz ZBTmpW+1

				lda #0
				ldx #8

.1				lsr ZBTmpW
				bcc .2
				clc
				adc ZBTmpB1
				
.2				ror
				ror ZBTmpW
				dex
				bne .1
				
				sta ZBTmpW+1
				
				lda ZPPixelScore
				clc
				adc ZBTmpW
				sta ZPPixelScore
				
				lda ZPPixelScore+1
				adc ZBTmpW+1
				sta ZPPixelScore+1
				bcc .3
				inc ZPPixelScore+2
				
.3				plx

				dey
				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
				>PUSHWZ				Aux type
				>PUSHBI 0				Type
				>PUSHBI	O.RDONLY	
				>LDYA ZPPtr1
				>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				>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
								
				>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
				
				>PUSHBI 5
				>LDYA L.MSG.HEADER.OK
				>SYSCALL printf
.9				rts
				
.99				>LDYA L.MSG.HEADER.KO
				>SYSCALL puts
				lda #E.IBIN
				sec
				rts				
*--------------------------------------
CS.RUN.ReadInput
				>PUSHW ZPInputRowBytes
				>PUSHW ZPInputBuf
				>LDA.G hInputFile
				>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
				>PUSHWZ				Aux type
				>PUSHBI $CB				PIX Type
				>PUSHBI	O.WRONLY+O.CREATE	
				>LDYA ZPPtr1
				>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
				>PUSHWI S.BM
				>PUSHEA.G PIX.Header
				>LDA.G hOutputFile
				>SYSCALL FWrite
				bcs .9
				
				>PUSHW.G OutputDataLen
				>PUSHW ZPOutputBuf
				>LDA.G hOutputFile
				>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
				
				lda ZPCntX
				cmp #80
				bcs .9
				
				lsr
				tay

				sta CLRPAGE2
				bcs .1					CS = main
				sta SETPAGE2
				plx
				lda PALETTE.AUX,x
				pha
				
.1				lda ZPCntY
				cmp #40
				bcs .9
				
				lda #39
				sec
				sbc ZPCntY
				lsr
				tax
				lda SCR.BASEL,x
				sta ZPPTR1
				lda SCR.BASEH,x
				sta ZPPTR1+1
				
				pla
				bcc .2
				
				asl
				asl
				asl
				asl
				
.2				ora (ZPPTR1),y
				sta (ZPPTR1),y
				sta CLRPAGE2
				plp
				rts
				
.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		>PSTR "Vv"
OptionVars		.DA #bVerbose,#bVerbose
MSG.USAGE		.AS "Usage : BMP2PIX BMP-File \r\n"
				.AZ "   -V : Verbose Mode\r\n"
MSG.HEADER.OK	.AZ "BMP Size : %D x %D pixels, %d bit(s)/pixel\r\n"		
MSG.HEADER.KO	.AZ "Invalid Input File Format"		
MSG.DONE		.AZ "All Done!!!"		
*--------------------------------------
* LOWRES Patette : https://comp.sys.apple2.narkive.com/lTSrj2ZI/apple-ii-colour-rgb
*--------------------------------------
*PALETTE.RGB	.HS 00000000			BLACK
*				.HS e31e6000			RED
*				.HS 604ebd00			DARK.BLUE
*				.HS ff44fd00			PURPLE
*				.HS 00a36000			DARK.GREEN
*				.HS 9c9c9c00			DARK.GRAY
*				.HS 14cffd00			BLUE
*				.HS d0c3ff00			LIGHT.BLUE
*				.HS 60720300			BROWN
*				.HS ff6a3c00			ORANGE
*				.HS 9c9c9c00			DARK.GRAY
*				.HS ffa0d000			PINK
*				.HS 14f53c00			LIGHT.GREEN
*				.HS d0dd8d00			YELLOW
*				.HS 72ffd000			AQUA
*				.HS ffffff00			WHITE
*--------------------------------------
PALETTE.RGB		.HS 00000000			BLACK
				.HS 930B7c00			RED
				.HS 1f35D300			DARK.BLUE
				.HS bb36ff00			PURPLE
				.HS 00760c00			DARK.GREEN
				.HS 7e7e7e00			DARK.GRAY
				.HS 07a8e000			BLUE
				.HS b5afff00			LIGHT.BLUE
				.HS 624c0000			BROWN
				.HS f9561d00			ORANGE
				.HS 9c9c9c00			LIGHT.GRAY
				.HS ff81ec00			PINK
				.HS 43c80000			LIGHT.GREEN
				.HS dccd1600			YELLOW
				.HS 5df78400			AQUA
				.HS ffffff00			WHITE
*--------------------------------------
PALETTE.AUX		.HS 00080109020A030B040C050D060E070F
*--------------------------------------
				.DUMMY
				.OR 0
DS.START
ArgCount		.BS 1
bVerbose		.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
