.486              ;Target processor.  Use instructions for Pentium class machines
.MODEL FLAT, C    ;Use the flat memory model. Use C calling conventions

.CODE             ;Indicates the start of a code segment.


LOCALS @@


;void RGB_BGR(unsigned char *Data, unsigned PixelCount)
	public	RGB_BGR
RGB_BGR proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels        
        jecxz	@@ToEnd			; array has zero size

        mov     esi,[Data]		; Load data ptr.

@@LoopPix:mov	al,[esi]
	mov	ah,[esi+2]
	mov	[esi],ah
	mov	[esi+2],al
	add	esi,3
	loop	@@LoopPix

@@ToEnd:
        ret                     ; _cdecl return
                
RGB_BGR	endp



;void RGBA32_BGRiA32(char *Data, int PixelCount)
	public	RGBA32_BGRiA32
RGBA32_BGRiA32 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels        
        jecxz	@@ToEnd			; array has zero size

        mov     esi,[Data]		; Load data ptr.

@@LoopPix:mov	al,[esi]
	mov	ah,[esi+2]
	mov	[esi],ah
	mov	[esi+2],al
	mov	al,[esi+3]
	not	al
	mov	[esi+3],al
	add	esi,4
	loop	@@LoopPix

@@ToEnd:
        ret                     ; _cdecl return
                
RGBA32_BGRiA32 endp


;void RGBA64_BGRiA64(char *Data, int PixelCount)
	public	RGBA64_BGRiA64
RGBA64_BGRiA64 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

	mov	ecx,[PixelCount]	; cx=amount of pixels
	jecxz	@@ToEnd			; array has zero size

	mov	esi,[Data]		; Load data ptr.

@@LoopPix:mov	ax,[esi]
	mov	dx,[esi+4]
	mov	[esi],dx
	mov	[esi+4],ax
	mov	ax,[esi+6]
	not	ax
	mov	[esi+6],ax
	add	esi,8
	loop	@@LoopPix

@@ToEnd:
        ret                     ; _cdecl return
                
RGBA64_BGRiA64 endp



;void RGB_BGR2(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB_BGR2
RGB_BGR2 proc \
        uses esi edi, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels

        mov     esi,[InData]	;
        mov     edi,[OutData]	;

	sub	ecx,4
	jl	@@LoopSimple

		; Processing of 4px block with size 3xDWORD	
@@LoopPix4:lodsd			; EAX = R2 B1 G1 R1
	bswap	eax		; EAX = R1 G1 B1 R2
	
	mov	edx,[esi]	; EDX = G3 R3 B2 G2
	add	esi,4
	
	xchg	al,dh		; EAX = R1 G1 B1 B2, EDX=G3 R3 R2 G2
	ror	eax,8		; EAX = B2 R1 G1 B1 
	stosd			;	B2 R1 G1 B1	shipped out
	
	lodsd			; EAX = B4 G4 R4 B3
	bswap	eax		; EAX = B3 R4 G4 B4
	rol	eax,8		; EAX = R4 G4 B4 B3
	
	ror	edx,8		; EDX = G2 G3 R3 R2
	xchg	dh,al		;  B3 <-> R3	    , EAX=R4 G4 B4 R3
	rol	edx,8		; EDX = G3 B3 R2 G2
	
	mov	[edi],edx	;	G3 B3 R2 G2	shipped out
	add	edi,4
	
	stosd			; R4 G4 B4 R3	shipped out
	;mov	[edi],eax	;	(STOSD is slow on AMD, replaced, seems that Intel works reversed)
	;add	edi,4
	
	sub	ecx,4
	jae	@@LoopPix4

			; Simple loop for 0,1,2,3 pixels (works also for more px)
@@LoopSimple:
	add	ecx,4		; ecx was -4, correct counter
        jecxz	@@ToEnd		; array has zero size
@@LoopPix:lodsw
	mov	[edi+2],al
	mov	[edi+1],ah
	lodsb
	mov	[edi],al
	add	edi,3
	dec	ecx
	jz	@@ToEnd
	
	lodsb
	mov	[edi+2],al
	lodsw
	mov	[edi+1],al
	mov	[edi],ah
	add	edi,3
	
	loop	@@LoopPix
@@ToEnd:	ret
	
RGB_BGR2 endp		


;void RGB32_BGR24(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB32_BGR24
RGB32_BGR24 proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; ecx=amount of pixels

        mov     esi,[InData]		; source data
        mov     edi,[OutData]		; destination data
        
        sub	ecx,4
	jl	@@LoopSimple		; array size < 4

@@LoopPx4:mov	ebx,[esi]		; EBX = ?? B1 G1 R1
	add	esi,4
	bswap	ebx			; EBX = R1 G1 B1 ??
		
;	lodsd				; EAX = ?? B2 G2 R2
	mov	eax,[esi]
	add	esi,4
	bswap	eax			; EAX = R2 G2 B2 ??
	
	mov	bl,ah			; BL = B2
	ror	ebx,8			; EBX = B2 R1 G1 B1	
	mov	[edi],ebx		;	shipout B2 R1 G1 B1
	add	edi,4

	mov	ebx,[esi]		; EBX = ?? B3 G3 R3
	add	esi,4
	mov	dl,bl			; DL = R3
	
	mov	ah,bh			; EAX = R2 G2 G3 ??
	bswap	ebx			; EBX = R3 G3 B3 ??
	mov	al,bh			; EAX = R2 G2 G3 B3
	ror	eax,16			; EAX = G3 B3 R2 G2
	stosd				;	shipout G3 B3 R2 G2
	
	lodsd				; EAX = ?? B4 G4 R4
	bswap	eax			; EAX = R4 G4 B4 ??
	mov	al,dl			; EAX = R4 G4 B4 R3

	stosd				;	shipout R4 G4 B4 R3

	sub	ecx,4
	jae	@@LoopPx4

@@LoopSimple:
	add	ecx,4
	jz	@@ToEnd			; remaining size = 0

@@LoopPix:lodsd
	mov	[edi+2],al
	mov	[edi+1],ah
	shr	eax,8
	mov	[edi],ah
	add	edi,3
	loop	@@LoopPix

@@ToEnd:
        ret                     ; _cdecl return
                
RGB32_BGR24 endp



;void RGB_Gray24(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB_Gray24
RGB_Gray24 proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]     ; cx=amount of pixels
        cmp	ecx,1
        jl	@@ToEnd		; array has zero size

        mov     esi,[InData]	;
        mov     edi,[OutData]	;
	
	mov	bh,0	
@@LoopPix:mov	ah,0
	mov	al,[esi]
	mov	bl,[esi+1]
	add	ax,bx
	mov	bl,[esi+2]
	add	ax,bx
	mov	bl,3
	div	bl
	stosb
        stosb
        stosb
	add	esi,3
	loop	@@LoopPix

@@ToEnd:
        ret                     ; _cdecl return
                
RGB_Gray24 endp



;void BGR_Gray24precise(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	BGR_Gray24precise
BGR_Gray24precise proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]     ; cx=amount of pixels
        cmp	ecx,1
        jle	@@ToEnd		; array has zero size

        mov     esi,[InData]	;
        mov     edi,[OutData]	;

@@LoopPix:mov	eax,0
	lodsb
        mov	edx,4731
        mul	edx
	mov	ebx,eax

	mov	eax,0
	lodsb
	mov	edx,46871
        mul	edx
	add	ebx,eax

	mov	eax,0
	lodsb
	mov	edx,13932
        mul	edx
	add	eax,ebx

	shr	eax,16	
	stosb
        stosb
        stosb
	loop	@@LoopPix

@@ToEnd:
        ret                     ; _cdecl return
                
BGR_Gray24precise endp



;void BGR32_Gray24(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	BGR32_Gray24
BGR32_Gray24 proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]     ; cx=amount of pixels
        cmp	ecx,1
        jle	@@ToEnd		; array has zero size

        mov     esi,[InData]	;
        mov     edi,[OutData]	;

@@LoopPix:mov	eax,0
	lodsb
        mov	edx,4731
        mul	edx
	mov	ebx,eax

	mov	eax,0
	lodsb
	mov	edx,46871
        mul	edx
	add	ebx,eax

	mov	eax,0
	lodsb
	mov	edx,13932
        mul	edx
	add	eax,ebx

	shr	eax,16	
	stosb
        stosb
        stosb
	inc	esi
	loop	@@LoopPix

@@ToEnd:
        ret                     ; _cdecl return
                
BGR32_Gray24 endp


;void RGB32_Gray(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB32_Gray
RGB32_Gray proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]     ; cx=amount of pixels
        cmp	ecx,1
        jle	@@ToEnd		; array has zero size

        mov     esi,[InData]	;
        mov     edi,[OutData]	;
	
	mov	bh,0	
@@LoopPix:mov	ah,0
	mov	al,[esi]
	mov	bl,[esi+1]
	add	ax,bx
	mov	bl,[esi+2]
	add	ax,bx
	mov	bl,3
	div	bl
	stosb
	add	esi,4
	loop	@@LoopPix

@@ToEnd:
        ret                     ; _cdecl return
                
RGB32_Gray endp


;void RGB_Gray(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB24_Gray8
RGB24_Gray8 proc \
        uses esi edi ebx, \
	OutData:ptr byte, \
        InData:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]     ; cx=amount of pixels
        cmp	ecx,1
        jle	@@ToEnd		; array has zero size

        mov     esi,[InData]	;
        mov     edi,[OutData]	;
	
	mov	bh,0	
@@LoopPix:mov	ah,0
	mov	al,[esi]
	mov	bl,[esi+1]
	add	ax,bx
	mov	bl,[esi+2]
	add	ax,bx
	mov	bl,3
	div	bl
	stosb
	add	esi,3
	loop	@@LoopPix

@@ToEnd:
        ret                     ; _cdecl return
                
RGB24_Gray8 endp


;void NotR(char *R, unsigned DataSize)	//R1:=not(R1)
	public  NotR
NotR	proc \
        uses edi, \
        R:ptr byte, \
        DataSize:DWORD

        mov     ecx,[DataSize]     ; cx=amount of pixels/bytes
        mov     edi,[R]		; Row byte data

        sub	ecx,4
        jl	@@LoopPx1
        
@@LoopPx4:mov	eax,[edi]	; Invert DWORDs
        not	eax	
        mov	[edi],eax
        add	edi,4
        
        sub	ecx,4        
        jge	@@LoopPx4
        
@@LoopPx1:add	ecx,4        
	jz	@@ToEnd
	
@@LoopPix:mov	al,[edi]	; Invert BYTEs
	not	al
	mov	[edi],al
	inc	edi
	loop	@@LoopPix
@@ToEnd:
        ret                     ; _cdecl return
                
NotR	endp



;void YUV_RGB(unsigned char *OutData, const unsigned char *y, const unsigned char *u, const unsigned char *v, unsigned PixelCount)
	public YUV_RGB
YUV_RGB proc \
        uses edi esi ebx, \
        OutData: ptr BYTE, \
        y: ptr BYTE, \
        u: ptr BYTE, \
	v: ptr BYTE, \
	PixelCount: DWORD
	
	mov	edi,[OutData]
	mov	esi,[y]
	mov	ebx,[u]
	mov	ecx,[PixelCount]
	push	ebp
	mov	ebp,[v]
	
	sub	ecx,2
	jb	@@Exit

@@LoopPx:xor	edx,edx
	mov	dh,[esi]	; 255*Y	

	xor	eax,eax
	mov	al,[ebp]	; V
	sub	eax,128	
	imul	eax,291		; 291*V	
	add	eax,edx
	
	js	@@SmallR1
	test	eax,0FFFF0000h
	jnz	@@BigR1
	mov	[edi],ah	; B1
	jmp	@@LoopX1R
@@BigR1:	mov	byte ptr [edi],255
        jmp	@@LoopX1R
@@SmallR1:mov	byte ptr [edi],0
@@LoopX1R:add	edi,2		; Shift to B

	xor	eax,eax
	mov	al,[ebx]	; U
	sub	eax,128
	imul	eax,521		; 291*V	
	add	eax,edx

	js	@@SmallB1
	test	eax,0FFFF0000h
	jnz	@@BigB1
	mov	[edi],ah	; B1
	jmp	@@LoopX1B
@@BigB1:	mov	byte ptr [edi],255
        jmp	@@LoopX1B
@@SmallB1:mov	byte ptr [edi],0
@@LoopX1B:dec	edi		; Shift back to G1

				;EDX = 255*Y
	xor	eax,eax	
	mov	al,[ebp]	; V
	sub	eax,128	
	imul	eax,148
	sub	edx,eax
	
	xor	eax,eax	
	mov	al,[ebx]	; U
	sub	eax,128
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V

	js	@@SmallG1
	test	edx,0FFFF0000h
	jnz	@@BigG1
	mov	[edi],dh	; R1
	jmp	@@LoopX1G
@@BigG1:	mov	byte ptr [edi],255
        jmp	@@LoopX1G
@@SmallG1:mov	byte ptr [edi],0
@@LoopX1G:add	edi,2		; Shift to R2

	inc	esi	

		; 2nd pixel
	xor	edx,edx
	mov	dh,[esi]	; 255*Y		

	xor	eax,eax
	mov	al,[ebp]	; V
	sub	eax,128	
	imul	eax,291		; 291*V	
	add	eax,edx
	
	js	@@SmallR2
	test	eax,0FFFF0000h
	jnz	@@BigR2
	mov	[edi],ah	; B2
	jmp	@@LoopX2R
@@BigR2:	mov	byte ptr [edi],255
        jmp	@@LoopX2R
@@SmallR2:mov	byte ptr [edi],0
@@LoopX2R:add	edi,2		; Shift to B2

	xor	eax,eax
	mov	al,[ebx]	; U
	sub	eax,128
	imul	eax,521		; 291*V	
	add	eax,edx

	js	@@SmallB2
	test	eax,0FFFF0000h
	jnz	@@BigB2
	mov	[edi],ah	; B1
	jmp	@@LoopX2B
@@BigB2:	mov	byte ptr [edi],255
        jmp	@@LoopX2B
@@SmallB2:mov	byte ptr [edi],0
@@LoopX2B:dec	edi		; Shift back to G

				;EDX = 255*Y
	xor	eax,eax	
	mov	al,[ebp]	; V
	sub	eax,128	
	imul	eax,148
	sub	edx,eax
	
	xor	eax,eax	
	mov	al,[ebx]	; U
	sub	eax,128
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V

	js	@@SmallG2
	test	edx,0FFFF0000h
	jnz	@@BigG2
	mov	[edi],dh	; R1
	jmp	@@LoopX2G
@@BigG2:	mov	byte ptr [edi],255
        jmp	@@LoopX2G
@@SmallG2:mov	byte ptr [edi],0
@@LoopX2G:add	edi,2		; Shift to R3

	inc	ebx		; inc U every 2nd pixel
	inc	ebp		; inc V every 2nd pixel

	inc	esi		; inc Y every pixel
	sub	ecx,2
	jae	@@LoopPx

@@Exit:	
	pop	ebp
	ret
YUV_RGB endp



;void YUYV_RGB(unsigned char *OutData, const unsigned char *yuyv, unsigned PixelCount);
	public YUYV_RGB
YUYV_RGB proc \
        uses edi esi ebx, \
        OutData: ptr BYTE, \
        yuyv: ptr BYTE, \
	PixelCount: DWORD
	
	mov	edi,[OutData]
	mov	esi,[yuyv]
	mov	ecx,[PixelCount]
	push	ebp	
	
	sub	ecx,2
	jb	@@Exit

@@LoopPx:mov	ebx,[esi]
	
	xor	edx,edx
	mov	dh,bl		; 255*Y		

	mov	eax,ebx
	rol	eax,8
	and	eax,0FFh	; V
	sub	eax,128
	mov	ebp,eax		; store V to EBP
	imul	eax,291		; 291*V	
	add	eax,edx
	
	js	@@SmallR1
	test	eax,0FFFF0000h
	jnz	@@BigR1
	mov	[edi],ah	; B1
	jmp	@@LoopX1R
@@BigR1:mov	byte ptr [edi],255
        jmp	@@LoopX1R
@@SmallR1:mov	byte ptr [edi],0
@@LoopX1R:add	edi,2		; Shift to B

	xor	eax,eax
	mov	al,bh		; U
	sub	eax,128
	imul	eax,521		; 291*U	
	add	eax,edx

	js	@@SmallB1
	test	eax,0FFFF0000h
	jnz	@@BigB1
	mov	[edi],ah	; B1
	jmp	@@LoopX1B
@@BigB1:mov	byte ptr [edi],255
        jmp	@@LoopX1B
@@SmallB1:mov	byte ptr [edi],0
@@LoopX1B:dec	edi		; Shift back to G1

				;EDX = 255*Y
	
	imul	eax,ebp,148	; V normalised *148
	sub	edx,eax
	
	xor	eax,eax	
	mov	al,bh		; U
	sub	eax,128
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V

	js	@@SmallG1
	test	edx,0FFFF0000h
	jnz	@@BigG1
	mov	[edi],dh	; R1
	jmp	@@LoopX1G
@@BigG1:	mov	byte ptr [edi],255
        jmp	@@LoopX1G
@@SmallG1:mov	byte ptr [edi],0
@@LoopX1G:add	edi,2		; Shift to R2

		; 2nd pixel
	mov	edx,ebx
	ror	edx,8
	and	edx,0FF00h	; 255*Y2
	
	imul	eax,ebp,291	; 291*V	
	add	eax,edx
	
	js	@@SmallR2
	test	eax,0FFFF0000h
	jnz	@@BigR2
	mov	[edi],ah	; R2
	jmp	@@LoopX2R
@@BigR2:	mov	byte ptr [edi],255
        jmp	@@LoopX2R
@@SmallR2:mov	byte ptr [edi],0
@@LoopX2R:add	edi,2		; Shift to B2

	mov	bl,bh		; U
	and	ebx,0FFh
	sub	ebx,128	
	imul	eax,ebx,521	; 521*U
	add	eax,edx

	js	@@SmallB2
	test	eax,0FFFF0000h
	jnz	@@BigB2
	mov	[edi],ah	; B2
	jmp	@@LoopX2B
@@BigB2:	mov	byte ptr [edi],255
        jmp	@@LoopX2B
@@SmallB2:mov	byte ptr [edi],0
@@LoopX2B:dec	edi		; Shift back to G

				;EDX = 255*Y	
	imul	eax,ebp,148	; V normalised * 148
	sub	edx,eax

	imul	eax,ebx,102	; 102*U normalised
	sub	edx,eax		; 255*Y - 102*U - 148*V

	js	@@SmallG2
	test	edx,0FFFF0000h
	jnz	@@BigG2
	mov	[edi],dh	; G2
	jmp	@@LoopX2G
@@BigG2:mov	byte ptr [edi],255
        jmp	@@LoopX2G
@@SmallG2:mov	byte ptr [edi],0
@@LoopX2G:add	edi,2		; Shift to R3


	add	esi,4		; inc Y per 2 pixels
	sub	ecx,2
	jae	@@LoopPx

@@Exit:	
	pop	ebp
	ret
YUYV_RGB endp


;void swab16(unsigned char *Data, unsigned PixelCount)
	public	swab16
swab16 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels
        jecxz	@@ToEnd			; array has zero size

	mov	esi,[Data]		; Load data ptr.

@@LoopPix:mov	ax,[esi]
	xchg	ah,al
	mov	[esi],ax
	add	esi,2
	loop	@@LoopPix

@@ToEnd:
	ret                     ; _cdecl return
swab16	endp


;void swab32(unsigned char *Data, unsigned PixelCount)
	public	swab32
swab32 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels
        jecxz	@@ToEnd			; array has zero size

	mov	esi,[Data]		; Load data ptr.

@@LoopPix:mov	eax,[esi]
	bswap	eax
	mov	[esi],eax
	add	esi,4
	loop	@@LoopPix

@@ToEnd:
	ret                     ; _cdecl return
swab32	endp


;void swab64(unsigned char *Data, unsigned PixelCount)
	public	swab64
swab64 proc \
        uses esi, \
        Data:ptr byte, \
        PixelCount:DWORD

        mov     ecx,[PixelCount]	; cx=amount of pixels
        jecxz	@@ToEnd			; array has zero size

	mov	esi,[Data]		; Load data ptr.

@@LoopPix:mov	eax,[esi]
	mov	edx,[esi+4]
	bswap	eax
	bswap	edx
	mov	[esi+4],eax
	mov	[esi],edx
	add	esi,8
	loop	@@LoopPix

@@ToEnd:
	ret                     ; _cdecl return
swab64	endp

;void DiffVer1_u32(uint32_t *Out, const uint32_t *In, const uint32_t *In2, int SizeX);
	public	DiffVer1_u32
DiffVer1_u32 proc \
        uses edi ebx esi, \
        OutL: ptr DWORD, \
        InL: ptr DWORD, \
	In2L: ptr DWORD, \
	SizeX: DWORD

	mov	edi,[OutL]
	or	edi,edi
	jz	DiffV1E
	mov	esi,[InL]
	or	esi,esi
	jz	DiffV1E
	mov	edx,[In2L]
	or	edx,edx
	jz	DiffV1E
	mov	ecx,[SizeX]
	jecxz	DiffV1E	
DiffV11:mov	eax,[esi]
	stc
	rcr	eax,1
	add	esi,4
	mov	ebx,[edx]
	shr	ebx,1
	sub	eax,ebx
	add	edx,4
	mov	[edi],eax
	add	edi,4
	loop	DiffV11
DiffV1E:ret
DiffVer1_u32 endp


        end
