; Palette handling, Copr. 1994 Matthias K”ppe

		LOCALS	@@

	.286

TRGBTRIPLE	STRUC
  rgbtBlue	DB	?
  rgbtGreen	DB	?
  rgbtRed	DB	?
TRGBTRIPLE	ENDS

DATA		SEGMENT WORD PUBLIC

		ASSUME	DS: DATA

		EXTRN	GetDevPalProc: WORD, \
			ColorWeights: TRGBTRIPLE, \
                        DevicePalette: UNKNOWN, \
			sDevicePalette: WORD, \
			LookUpTable: DWORD

DATA		ENDS

CODE		SEGMENT BYTE PUBLIC

		ASSUME	CS: CODE

		PUBLIC	GetDevPal_16, GetDevPal_256, GetDevicePalette, \
			DoCalcPalette, LookUpPalette

	; Translate color value
	;
	; In:	Val	0..63
	; Out:	AL      0..255

Trans		MACRO	val
		mov	al, val
		mov	ah, al
		shl	al, 2
		shr	ah, 4
		or	al, ah
		ENDM

	; GetDevPal
	;
	; In:	es:dx	buffer
	; Out:	ax	color count

GetDevPal_256	PROC NEAR
		mov	ax, 1017h
		mov	bx, 0
		mov	cx, 256
		int	10h
		mov	di, dx
@@1:		Trans	<BYTE PTR es:[di]>
		xchg	al, es:[di+2]
		Trans	<al>
		mov	es:[di], al
		Trans	<BYTE PTR es:[di+1]>
		mov	es:[di+1], al
		add	di, 3
		loop	@@1
		mov	ax, 256
		ret
GetDevPal_256	ENDP

GetDevPal_16	PROC NEAR
		LOCAL	Pal: BYTE: 17 = LocalSize
		enter	LocalSize, 0
		push	es dx
		lea	dx, Pal
		mov	ax, ss
		mov	es, ax
		mov	ax, 1009h
		int	10h		; read all palette regs and overscan
		pop	di es
		cld
		push	bp
		lea	bp, Pal
		mov	dl, 16
@@1:		mov	bl, [bp]
		mov	ax, 1015h
		int	10h		; read individual dac register
		Trans	<cl>
		stosb
		Trans	<ch>
		stosb
		Trans	<dh>
		stosb
		inc	bp
		dec	dl
		jnz	@@1
		pop	bp
		leave
		mov	ax, 16
		retn
GetDevPal_16	ENDP

	;
	; Get Device Palette
	;

GetDevicePalette PROC NEAR
		ARG	Palette: DWORD = ArgSize
		push	bp
		mov	bp, sp
		les	dx, Palette
		call	GetDevPalProc
		pop	bp
		ret	ArgSize
GetDevicePalette ENDP

	;
	; Calc Palette
	;

DoCalcPalette	PROC NEAR
		ARG	PalBuf: DWORD, EntrySize: WORD, \
			Count: WORD, BmpPal: DWORD = ArgSize
		LOCAL	DevPal: BYTE: 256*3, Weights: TRGBTRIPLE, \
			DevCount: WORD, Diff: DWORD, MinOffs: WORD, \
			CalcProc: WORD = LocalSize
		enter	LocalSize, 0
		lea	dx, DevPal
		mov	ax, ss
		mov	es, ax
	;	call	GetDevPalProc
		;
		mov	si, OFFSET DevicePalette
		mov	di, dx
		cld
		mov	ax, sDevicePalette
		imul	cx, ax, 3
		shr	cx, 1
		rep	movsw
		;
		mov	DevCount, ax
		mov	ax, WORD PTR ColorWeights[0]
		mov	WORD PTR Weights[0], ax
		mov	bl, BYTE PTR ColorWeights[2]
		mov	BYTE PTR Weights[2], bl
		cmp	bl, al
		mov	bx, OFFSET CalcDiffWeighted
		jnz	@@0
		cmp	ah, al
		jnz	@@0
		mov	bx, OFFSET CalcDifference
@@0:		mov	CalcProc, bx
		push	ds
		lea	bx, DevPal		; ss:bx Device Palette
		lds	si, BmpPal		; ds:si Bitmap Palette
		les	di, PalBuf		; es:di Translation Table
		cld

@@1:            push	bx
		mov     WORD PTR Diff[0], 0FFFFh
		mov	WORD PTR Diff[2], 0FFFFh
		mov	cx, DevCount

@@2:		push	cx
		call	CalcProc
		cmp	dx, WORD PTR Diff[2]
		ja	SHORT @@4
		jb	SHORT @@3
		cmp	ax, WORD PTR Diff[0]
		jae	SHORT @@4
@@3:		mov	WORD PTR Diff[2], dx
		mov	WORD PTR Diff[0], ax
		mov	MinOffs, bx
@@4:		add	bx, 3
		pop	cx
		loop	@@2

		pop	bx
		mov	ax, MinOffs
		sub	ax, bx
		mov	cl, 3
		div	cl
		stosb
		add	si, EntrySize
		dec	Count
		jnz	@@1

		pop	ds
		leave
		ret
DoCalcPalette	ENDP

	;
	; LookupPalette
	;

	.386

LookupPalette	PROC NEAR
		ARG	PalBuf: DWORD, EntrySize: WORD, \
			Count: WORD, BmpPal: DWORD = ArgSize
		push	bp
		mov	bp, sp
		push	ds
		push	fs
		lfs	bx, LookUpTable		; fs:bx 4:4:4 Lookup Table
		lds	si, BmpPal		; ds:si Bitmap Palette
		les	di, PalBuf		; es:di Translation Table
		mov	cx, Count
		cld
@@1:
		mov	al, [si].TRGBTriple.rgbtRed
		and	ax, 11110000b
		shl	ax, 4

		mov	dl, [si].TRGBTriple.rgbtGreen
		and	dx, 11110000b
		add	ax, dx

		mov	dl, [si].TRGBTriple.rgbtBlue
		shr	dl, 4
		or	al, dl
		add	ax, bx
		mov	bp, ax
		mov	al, fs:[bp]
		stosb

		add	si, 3			; EntrySize
		dec	cx
		jnz	@@1

		pop	fs
		pop	ds
		pop	bp
		ret
LookupPalette	ENDP

	.286

	; Calculate the difference of two 24-bit colours.
	;
	; In:	DS:SI	reference color
	;	SS:BX	test color
	;
	; Out:	DX:AX	Difference measure
	;	CX	destroyed

	; Non-weighted version

CalcDifference	PROC NEAR
		mov	al, [si].TRGBTRIPLE.rgbtBlue
		sub	al, ss:[bx].TRGBTRIPLE.rgbtBlue
		jnb	SHORT @@1
		neg	al
@@1:		mul	al
		mov	cx, ax
		xor	dx, dx
		mov	al, [si].TRGBTRIPLE.rgbtGreen
		sub	al, ss:[bx].TRGBTRIPLE.rgbtGreen
		jnb	SHORT @@2
		neg	al
@@2:		mul	al
		add	cx, ax
		adc	dx, 0
		mov	al, [si].TRGBTRIPLE.rgbtRed
		sub	al, ss:[bx].TRGBTRIPLE.rgbtRed
		jnb	SHORT @@3
		neg	al
@@3:		mul	al
		add	ax, cx
		adc	dx, 0
		retn
CalcDifference	ENDP

	; Weighted version

CalcDiffWeighted PROC NEAR
		mov	al, [si].TRGBTRIPLE.rgbtBlue
		sub	al, ss:[bx].TRGBTRIPLE.rgbtBlue
		jnb	SHORT @@1
		neg	al
@@1:		mul	Weights.rgbtBlue
		mul	ax
		push	dx ax
		mov	al, [si].TRGBTRIPLE.rgbtGreen
		sub	al, ss:[bx].TRGBTRIPLE.rgbtGreen
		jnb	SHORT @@2
		neg	al
@@2:		mul	Weights.rgbtGreen
		mul	ax
		pop	cx
		add	ax, cx
		pop	cx
		adc	dx, cx
		push	dx ax
		mov	al, [si].TRGBTRIPLE.rgbtRed
		sub	al, ss:[bx].TRGBTRIPLE.rgbtRed
		jnb	SHORT @@3
		neg	al
@@3:		mul	Weights.rgbtRed
		mul	ax
		pop	cx
		add	ax, cx
		pop	cx
		adc	dx, cx
		retn
CalcDiffWeighted ENDP

CODE		ENDS

		END
