
;********************************************************************
;
;	yuvconversion.asm
;
;	1.0 - 28.7.98 (bifat)	written in assembler
;	1.1 - 29.7.98 (bifat)	added yuv2rgbgrey
;	1.2 - 30.7.98 (bifat)	unrolled yuv2rgbgrey and optimized
;							it for superscalarity
;	1.3 - 02.8.98 (copper)  added yuv2pip and yuv2pipgrey
;	1.4 - ? (copper)	added brightness for yuv2pip und yuv2pipgrey
; 	1.5 - 31.9.98 (bifat)   yuv2rgb rewritten, added brightness
;	1.6 - 1.10.98 (bifat)	yuv2rgb now using tables
;
;********************************************************************

OPT_SAVE	EQU	16


		section	bla,BSS

yuv2rgbtable	dcb.l	65536*4


;********************************************************************

		section text,CODE
		
		XREF	_opts

		XDEF	_inityuv2rgb
		XDEF	_yuv2rgb
		XDEF	_yuv2rgbgrey
		XDEF	_yuv2pipgrey
		XDEF	_yuv2pip
		
;********************************************************************

iclip		dcb.w	256
iclp		dcb.w	512

greyclip	dcb.l	256
greyclp		dcb.l	512

greycorrection	dc.w	0

;********************************************************************

_inityuv2rgb:
		movem.l	d2-d7/a2-a6,-(a7)

		lea	iclip(pc),a0

		move.w	#256-1,d0
		moveq	#0,d1
.inilop1	move.w	d1,(a0)+
		dbf	d0,.inilop1

		move.w	#256-1,d0
.inilop2	move.w	d1,(a0)+
		addq.w	#1,d1
		dbf	d0,.inilop2

		move.w	#256-1,d0
		move.w	#255,d1
.inilop3	move.w	d1,(a0)+
		dbf	d0,.inilop3


; - -- -- --- - -- -  -   -    -


	;	create yuv-conversion table
	;	
	;	%	UUUUU VVVVV YYYYYYY
	;		5	5	7


		lea	yuv2rgbtable,a0
		lea	(iclp.w,pc),a1


		moveq	#-128,d0
.ulop
		moveq	#-128,d1
.vlop
		moveq	#0,d2

.ylop		;	t0 = (*py1++ - 16) * 298;

		move.w	d2,d3
		asr.w	#6,d3
		add.w	d2,d3
		sub.w	#16,d3
		muls.w	#298,d3

		;	d4 = ut1 = u * 516;
		
		move.w	d0,d4
		asr.w	#6,d4
		add.w	d0,d4
		muls.w	#516,d4

		;	d5 = vt0 = v * 409;

		move.w	d1,d5
		asr.w	#6,d5
		add.w	d1,d5
		muls.w	#409,d5

		;	d6 = utx = u * -100 + v * -208;
		
		moveq	#-100,d6
		muls.w	d0,d6
		move.w	#-208,d7
		muls.w	d1,d7
		add.l	d7,d6

		;	*rgbp1++ = 	(clipp[(t2 + vt0) >> 8] << 16) +
		;				(clipp[(t2 + utx) >> 8] << 8) +
		;				 clipp[(t2 + ut1) >> 8];
		
		add.l	d3,d5			; y+v
		asr.l	#8,d5
		move.w	(a1,d5.w*2),d7		; 0r
		swap	d7
		
		add.l	d3,d6			; y+utx
		asr.l	#8,d6
		move.w	-1(a1,d6.w*2),d7	; 0rg0
		
		add.l	d3,d4			; y+u
		asr.l	#8,d4
		move.b	1(a1,d4.w*2),d7		; 0rgb
		
		move.l	d7,(a0)+		

		addq.w	#4,d2
		cmp.w	#256,d2
		blt	.ylop

		addq.w	#4,d1
		cmp.w	#128,d1
		blt	.vlop

		addq.w	#4,d0
		cmp.w	#128,d0
		blt	.ulop



		movem.l	(a7)+,d2-d7/a2-a6
		rts


;********************************************************************


initgreytab:

		;	d2	rel. brightness

		movem.l	a0/d0-d2,-(a7)

		lea	greycorrection(pc),a0
		cmp.w	(a0),d2
		beq.b	.nochange
		move.w	d2,(a0)

		lea	greyclip(pc),a0
		
		move.w	d2,d1
		bpl.b	.ok1

		moveq	#0,d1

.ok1		move.w	d1,d0
		swap	d1
		move.b	d0,d1
		lsl.w	#8,d1
		move.b	d0,d1

		move.w	#256-1,d0
.inilop1	move.l	d1,(a0)+
		dbf	d0,.inilop1

		move.w	#256-1,d0

.inilop2	move.l	d1,(a0)+

		addq.w	#1,d2
		bmi.b	.skip
		cmp.w	#255,d2
		bgt.b	.skip

		add.l	#$00010101,d1
.skip
		dbf	d0,.inilop2

		move.w	#256-1,d0
.inilop3	move.l	d1,(a0)+
		dbf	d0,.inilop3

.nochange		
		movem.l	(a7)+,a0/d0-d2
		rts


;********************************************************************

		cnop	0,4			

_yuv2rgb:	movem.l	d2-d7/a2-a6,-(a7)

		;	a0	**src
		;	a1	*dest
		;	d0	width
		;	d1	height
		;	d2	brightness


		tst.w	d2
		bne.b	yuv_notable

		tst.w	_opts+4*OPT_SAVE+2		; save? nicht über tabelle
		bne.b	yuv_notable

; - -- -- --- - -- -  -   -    -
;
;		table mapper
;		(brightness not supported)

	
		move.l	(a0)+,a2	; py1
		lea	(a2,d0.w),a3	; py2
		move.l	(a0)+,a4	; pu
		move.l	(a0)+,a5	; pv
		
		lea	yuv2rgbtable,a6	; table

		; a1			; rgbp1
		lea	(a1,d0.w*4),a0	; rgbp2

		move.w	d0,d3
		lsl.w	#2,d3		

.ylop		move.w	d0,d2		; w

.xlop		moveq	#0,d4
		move.b	(a4)+,d4	; u
		lsl.w	#6,d4		; %UUUUUuuu.....
		move.b	(a5)+,d4	; %UUUUUVVVVVvvv
		lsl.l	#6,d4		; %UUUUUVVVVVvvv.....
		move.l	d4,d5
		move.l	d5,d6

		move.b	(a2)+,d4	; %UUUUUVVVVVYYYYYYyy

		move.l	d6,d7

		move.b	(a2)+,d5	; %UUUUUVVVVVYYYYYYyy

		lsr.l	#2,d4

		move.b	(a3)+,d6	; %UUUUUVVVVVYYYYYYyy

		lsr.l	#2,d5

		move.b	(a3)+,d7	; %UUUUUVVVVVYYYYYYyy

		lsr.l	#2,d6

		move.l	(a6,d4.l*4),(a1)+

		lsr.l	#2,d7

		move.l	(a6,d5.l*4),(a1)+
		move.l	(a6,d6.l*4),(a0)+

		move.l	(a6,d7.l*4),(a0)+

		subq.w	#2,d2
		bgt.b	.xlop

		add.w	d0,a2
		add.w	d3,a0
		add.w	d0,a3
		add.w	d3,a1

		subq.w	#2,d1
		bgt.b	.ylop
		
		movem.l	(a7)+,d2-d7/a2-a6

		rts

; - -- -- --- - -- -  -   -    -
;
;		arithmetic mapper
;		(brightness supported)


		cnop	0,4

yuv_notable	move.l	(a0)+,a2	; py1
		lea	(a2,d0.w),a3	; py2
		move.l	(a0)+,a4	; pu
		move.l	(a0)+,a5	; pv
		lea	(iclp.w,pc),a6	; clipp

		; a1			; rgbp1
		lea	(a1,d0.w*4),a0	; rgbp2
		

		sub.w	#16,d2		; br-=16
		swap	d2

		move.w	d1,-(a7)

		move.w	d0,-(a7)	; w
		

.ylop		move.w	(a7),d2

.xlop		swap	d2		; br

		moveq	#0,d0

		moveq	#-128,d7

		move.b	(a4)+,d0	

		moveq	#0,d1

		add.w	d7,d0		; u

		move.b	(a5)+,d1	

		moveq	#-100,d3

		add.w	d7,d1		; v

		move.w	#-208,d5

		muls.w	d0,d3

		muls.w	d1,d5

		moveq	#0,d4

		move.w	#298,d7

		move.b	(a2)+,d4

		muls.w	#516,d0		; ut1

		add.l	d5,d3		; utx

		add.w	d2,d4

		muls.w	#409,d1		; vt0

		muls.w	d7,d4			; t0

		move.l	d1,d5
		add.l	d4,d5
		asr.l	#8,d5
		move.w	(a6,d5.w*2),d6		; 0r
		move.l	d4,d5

		swap	d6

		add.l	d3,d5

		add.l	d0,d4

		asr.l	#8,d5
		move.w	-1(a6,d5.w*2),d6	; 0rg0

		asr.l	#8,d4
		move.b	1(a6,d4.w*2),d6		; 0rgb

		moveq	#0,d4
		move.b	(a2)+,d4
		add.w	d2,d4
		muls.w	d7,d4			; t1

		move.l	d1,d5
		add.l	d4,d5
		asr.l	#8,d5
		move.w	(a6,d5.w*2),d7		; 0r
		move.l	d4,d5

		swap	d7

		add.l	d3,d5

		add.l	d0,d4

		asr.l	#8,d5
		move.w	-1(a6,d5.w*2),d7	; 0rg0

		asr.l	#8,d4
		move.b	1(a6,d4.w*2),d7		; 0rgb
		
	
		move.l	d6,(a1)+
		move.l	d7,(a1)+



		move.w	#298,d7

		moveq	#0,d4
		move.b	(a3)+,d4
		add.w	d2,d4
		muls.w	d7,d4			; t2

		move.l	d1,d5
		add.l	d4,d5
		asr.l	#8,d5
		move.w	(a6,d5.w*2),d6		; 0r
		move.l	d4,d5

		swap	d6

		add.l	d3,d5

		add.l	d0,d4

		asr.l	#8,d5
		move.w	-1(a6,d5.w*2),d6	; 0rg0

		asr.l	#8,d4
		move.b	1(a6,d4.w*2),d6		; 0rgb


		moveq	#0,d4
		move.b	(a3)+,d4
		add.w	d2,d4
		muls.w	d7,d4			; t3

		move.l	d1,d5
		add.l	d4,d5
		asr.l	#8,d5
		move.w	(a6,d5.w*2),d7		; 0r
		move.l	d4,d5

		swap	d7

		add.l	d3,d5

		add.l	d0,d4

		asr.l	#8,d5
		move.w	-1(a6,d5.w*2),d7	; 0rg0

		asr.l	#8,d4
		move.b	1(a6,d4.w*2),d7		; 0rgb
		
		
		move.l	d6,(a0)+
		swap	d2		; x
		move.l	d7,(a0)+

		subq.w	#2,d2
		bgt.w	.xlop


		move.w	(a7),d0
		add.w	d0,a2
		add.w	d0,a3
		lsl.w	#2,d0
		add.w	d0,a0
		add.w	d0,a1

		subq.w	#2,2(a7)
		bgt.w	.ylop
		
		addq.w	#4,a7

		movem.l	(a7)+,d2-d7/a2-a6

		rts


;********************************************************************

		cnop	0,4			

_yuv2rgbgrey:
		;	a0	**src
		;	a1	*dest
		;	d0	w
		;	d1	h
		;	d2	greycorrection

		movem.l	d2-d7/a2-a6,-(a7)
		
		tst.w	d2
		beq.b	nogreycorrection

		bsr	initgreytab
		
		lea	greyclp(pc),a3


		move.l	(a0),a0		; *src

		move.w	d1,d6

		moveq	#3,d7
		and.w	d0,d7
		lsr.w	#2,d0
		move.w	d0,d7			; 1er:4er


.ylop		swap	d7
		move.w	d7,d2
		beq.b	.no1

		moveq	#0,d3
.loop1		move.b	(a0)+,d3
		move.l	(a3,d3.w*4),(a1)+
		subq.w	#1,d2
		bne.b	.loop1

.no1		swap	d7
		move.w	d7,d5
		beq.b	.no4
		
.loop2
		moveq	#0,d4
		move.l	(a0)+,d0
		moveq	#0,d3
		move.b	d0,d4
		moveq	#0,d2
		lsr.w	#8,d0
		moveq	#0,d1
		move.b	d0,d3
		move.l	(a3,d4.w*4),d4
		swap	d0
		move.b	d0,d2
		move.l	(a3,d3.w*4),d3
		lsr.w	#8,d0
		move.l	(a3,d2.w*4),d2
		move.b	d0,d1
		move.l	(a3,d1.w*4),d1
			
		movem.l	d1-d4,(a1)
		add.w	#16,a1

		subq.w	#1,d5
		bne.b	.loop2

.no4		subq.w	#1,d6
		bne.b	.ylop


		bra	raus
		




nogreycorrection
		
		move.l	(a0),a0		; *src

		move.w	d1,a6

		moveq	#3,d2
		and.w	d0,d2
		move.w	d2,a3		; 1er
		
		lsr.w	#2,d0
		move.w	d0,a4		; 4er

		moveq	#0,d1
		moveq	#0,d4
		moveq	#0,d5
		moveq	#0,d6
		moveq	#0,d7

.ylop
		move.w	a3,d2
		beq.b	.no1

		moveq	#0,d3
.loop1		move.b	(a0)+,d3
		move.l	d3,d4
		swap	d4
		move.b	d3,d4
		lsl.w	#8,d4
		move.b	d3,d4
		move.l	d4,(a1)+

		subq.w	#1,d2
		bne.b	.loop1

.no1		move.w	a4,d0
		beq.b	.no4
		move.w	a4,a5
		
		moveq	#0,d0
		moveq	#0,d2
		moveq	#0,d3

.loop2
		move.b	(a0)+,d0	; $11		
		move.l	d0,d4
		move.b	(a0)+,d1	; $22
		swap	d4
		move.b	(a0)+,d2	; $33
		move.l	d1,d5
		move.b	(a0)+,d3	; $44
		move.l	d2,d6
		move.b	d0,d4
		swap	d6
		lsl.w	#8,d4
		swap	d5
		move.b	d0,d4
		move.b	d2,d6
		move.l	d4,(a1)+
		move.b	d1,d5
		lsl.w	#8,d6
		lsl.w	#8,d5
		move.l	d3,d7
		move.b	d1,d5
		swap	d7
		move.l	d5,(a1)+
		move.b	d3,d7
		move.b	d2,d6
		lsl.w	#8,d7
		move.l	d6,(a1)+
		move.b	d3,d7
		subq.w	#1,a5
		move.l	d7,(a1)+
		move.w	a5,d0
		bne.b	.loop2

.no4

		subq.w	#1,a6
		move.w	a6,d0
		bne.b	.ylop

raus
		movem.l	(a7)+,d2-d7/a2-a6

		
		rts


;********************************************************************

		cnop	0,4			

_yuv2pipgrey:
		;	a0	*address
		;	a1	**srcbuffer
		;	d0	y
		;	d4  	br
		movem.l	d0-d4/a0/a1,-(a7)

		move.l	#$ff00ff00,d2
		move.l	#$00800080,d3
		move.l	d0,d7
		subq.w	#1,d7
		move.l	(a1),a1

.next:
		moveq	#0,d0
		move.w	(a1)+,d0	;00yy
		move.l	d0,d1
		and.w	#$00ff,d1
		add.l	d4,d1
		tst.w	d1
		bpl.b	.ok
		moveq	#0,d1
		bra.b	.p
.ok:		cmp.w	#$ff,d1
		ble.b	.p
		move.l	#$ff,d1
.p:
		lsl.w	#8,d1
		lsr.w	#8,d0
		add.l	d4,d0
		tst.w	d0
		bpl.b	.ok1
		moveq	#0,d0
		bra.b	.p1
.ok1:		cmp.w	#$ff,d0
		ble.b	.p1
		move.l	#$ff,d0
.p1:
		lsl.w	#8,d0
		swap	d0		;yy00
		or.l	d1,d0		;yyy0
		and.l	d2,d0		;y0y0
		or.l	d3,d0		;y8y8
		move.l	d0,(a0)+
		dbra	d7,.next

		movem.l	(a7)+,d0-d4/a0/a1

		rts

		cnop	0,4			

;********************************************************************

_yuv2pip:
		;	a0	*address
		;	a1	**scrbuffer
		;	d5	x-1
		;	d7	y-1
		;	d4	br
		movem.l	d0-a6,-(a7)

		move.l	(a1)+,a2		;y
		move.l	(a1)+,a3		;u
		move.l	(a1)+,a4		;v
;		move.l	#$ff00ff00,d4

.loop1:
		movem.l	a3/a4,-(a7)

		move.l	d5,d6
.loop2:
		moveq	#0,d2
		move.w	(a2)+,d2
		move.l	d2,d3

		and.w	#$00ff,d3
		add.l	d4,d3
		tst.w	d3
		bpl.b	.ok
		moveq	#0,d3
		bra.b	.p
.ok:		cmp.w	#$ff,d3
		ble.b	.p
		move.l	#$ff,d3
.p:
		lsl.w	#8,d3
		lsr.w	#8,d2
		add.l	d4,d2
		tst.w	d2
		bpl.b	.ok1
		moveq	#0,d2
		bra.b	.p1
.ok1:		cmp.w	#$ff,d2
		ble.b	.p1
		move.l	#$ff,d2
.p1:
		lsl.w	#8,d2
		swap	d2			;yy00
		or.l	d3,d2		;yyy0
;		and.l	d4,d2		;y0y0
		and.l	#$ff00ff00,d2		;y0y0
		moveq	#0,d0
		move.b	(a3)+,d0	;u
		swap	d0
		move.b	(a4)+,d1	;v	
		or.l	d0,d2
		or.b	d1,d2		;yuyv
		move.l	d2,(a0)+
		dbra	d6,.loop2

		movem.l	(a7)+,a3/a4

		move.l	d5,d6
.loop3:
		moveq	#0,d2
		move.w	(a2)+,d2
		move.l	d2,d3

		and.w	#$00ff,d3
		add.l	d4,d3
		tst.w	d3
		bpl.b	.ok2
		moveq	#0,d3
		bra.b	.p2
.ok2:		cmp.w	#$ff,d3
		ble.b	.p2
		move.l	#$ff,d3
.p2:
		lsl.w	#8,d3
		lsr.w	#8,d2
		add.l	d4,d2
		tst.w	d2
		bpl.b	.ok3
		moveq	#0,d2
		bra.b	.p3
.ok3:		cmp.w	#$ff,d2
		ble.b	.p3
		move.l	#$ff,d2
.p3:
		lsl.w	#8,d2

		swap	d2			;yy00
		or.l	d3,d2		;yyy0
;		and.l	d4,d2		;y0y0
		and.l	#$ff00ff00,d2		;y0y0
		moveq	#0,d0
		move.b	(a3)+,d0	;u
		swap	d0
		move.b	(a4)+,d1	;v	
		or.l	d0,d2
		or.b	d1,d2		;yuyv
		move.l	d2,(a0)+
		dbra	d6,.loop3

		dbra	d7,.loop1

		movem.l	(a7)+,d0-a6

		rts

;********************************************************************

	
	
		END
	
					


	

void yuv2rgb(unsigned char **srcbuffer, ULONG *rgbp, int w, int h)
{
	int x, y, i;
	unsigned char *py, *pu, *pv, *puu, *pvv;
	int tmp, tmp1, tmp2, tmp3;
	int u, v, vt0, ut1, utx;
	
	py = srcbuffer[0];
	pu = srcbuffer[1];
	pv = srcbuffer[2];
	
	for(y = 0; y < h/2; y++)
	{
		for(i = 0; i < 2; i++)
		{
			puu = pu;
			pvv = pv;

			for(x = 0; x < w/2; x++)
			{
				tmp = (*py++ - 16) * 298;
				
				u = *puu++ - 128;
				v = *pvv++ - 128;
	
				vt0 = v * 409;
				ut1 = u * 516;
				utx = u * -100 + v * -208;
	
				tmp1 = (tmp + vt0) >> 8;
				tmp2 = (tmp + utx) >> 8;
				tmp3 = (tmp + ut1) >> 8;
		
				*rgbp++ = (clipp[tmp1]) << 16 | (clipp[tmp2]) << 8 | (clipp[tmp3]);


				tmp = (*py++ - 16) * 298;		

				tmp1 = (tmp + vt0) >> 8;
				tmp2 = (tmp + utx) >> 8;
				tmp3 = (tmp + ut1) >> 8;

				*rgbp++ = (clipp[tmp1]) << 16 | (clipp[tmp2]) << 8 | (clipp[tmp3]);
			}
		}
		pu = puu;
		pv = pvv;
	}

}




	END
	
	

#include "yuvconversion.h"
#include <exec/types.h>


static unsigned short cliptab[256*3];
static unsigned short *clipp;

void inityuv2rgb(void)
{
	int i;
	unsigned short *cp = cliptab;

	clipp = &cliptab[256];
	
	for (i = -256; i < 512; ++i)
	{
		*cp++ = i < 0 ? 0 : (i > 255 ? 255 : i);
	}
}


void yuv2rgb(unsigned char **srcbuffer, ULONG *rgbp, int w, int h)
{
	int x, y, i;
	unsigned char *py, *pu, *pv, *puu, *pvv;
	int tmp, tmp1, tmp2, tmp3;
	int u, v, vt0, ut1, utx;
	
	py = srcbuffer[0];
	pu = srcbuffer[1];
	pv = srcbuffer[2];
	
	for(y = 0; y < h/2; y++)
	{
		for(i = 0; i < 2; i++)
		{
			puu = pu;
			pvv = pv;

			for(x = 0; x < w/2; x++)
			{
				tmp = (*py++ - 16) * 298;
				
				u = *puu++ - 128;
				v = *pvv++ - 128;
	
				vt0 = v * 409;
				ut1 = u * 516;
				utx = u * -100 + v * -208;
	
				tmp1 = (tmp + vt0) >> 8;
				tmp2 = (tmp + utx) >> 8;
				tmp3 = (tmp + ut1) >> 8;
		
				*rgbp++ = (clipp[tmp1]) << 16 | (clipp[tmp2]) << 8 | (clipp[tmp3]);


				tmp = (*py++ - 16) * 298;		

				tmp1 = (tmp + vt0) >> 8;
				tmp2 = (tmp + utx) >> 8;
				tmp3 = (tmp + ut1) >> 8;

				*rgbp++ = (clipp[tmp1]) << 16 | (clipp[tmp2]) << 8 | (clipp[tmp3]);
			}
		}
		pu = puu;
		pv = pvv;
	}

}


void yuv2rgbgrey(unsigned char **srcbuffer, ULONG *rgbp, int w, int h)
{
	int i;
	unsigned char *source;
	unsigned char *dest;
	unsigned char p;
	
	source = srcbuffer[0];
	dest = (char *) rgbp;

	for (i=0; i < w*h; ++i)
	{
		p = *source++;
		*dest++= 0;
		*dest++= p;
		*dest++= p;
		*dest++= p;
	}

}
