
.CODE             ;Indicates the start of a code segment.


;https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
;The x64 ABI considers the registers RAX, RCX, RDX, R8, R9, R10, R11, and XMM0-XMM5 volatile.


;void RGB_BGR(unsigned char *Data, unsigned PixelCount)
	public	RGB_BGR

RGB_BGR proc \
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	mov	r8,rsi
	mov	rsi,rcx
	mov	rcx,rdx		; Load data ptr.
	sub	rcx,4		; rcx=amount of pixels - 4
	jl	LoopPix1

LoopPix4:
	mov	eax,[rsi]		;[R1, G1, B1, R2]
	mov	edx,[rsi+4]		;[G2, B2, R3, G3]
	mov	[rsi+2],al		;R1
	shr	eax,16			;[B1, R2]
	mov	[rsi],al		;B1
	mov	[rsi+3],dh		;B2
	mov	[rsi+5],ah		;R2
	shr	edx,16			;[R3, G3, 0, 0]
	mov	eax,[rsi+8]		;[B3, R4, G4, B4]
	mov	[rsi+8],dl		;R3
	mov	[rsi+6],al		;B3
	mov	[rsi+11],ah		;B4
	shr	eax,16			;[G4, B4, 0, 0]
	mov	[rsi+9],ah		;B4
	add	rsi,12
	sub	rcx,4
	jae	LoopPix4
	
LoopPix1:add	rcx,4	
	jz	ToEnd		; array has zero size
LoopPix:mov	al,[rsi]
	mov	ah,[rsi+2]
	mov	[rsi],ah
	mov	[rsi+2],al
	add	rsi,3
	loop	LoopPix

ToEnd:	mov	rsi,r8
        ret                     ; _cdecl return
                
RGB_BGR	endp



;void RGBA32_BGRA32(char *Data, int PixelCount)
	public	RGBA32_BGRiA32

RGBA32_BGRiA32 proc \
        uses rsi
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	mov	rsi,rcx		; Load data ptr.
	mov	rcx,rdx		; rcx=amount of pixels
	jrcxz	ToEnd		; array has zero size

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

ToEnd:
        ret                     ; _cdecl return
                
RGBA32_BGRiA32 endp


;void RGBA64_BGRA64(char *Data, int PixelCount)
	public	RGBA64_BGRiA64

RGBA64_BGRiA64 proc \
        uses rsi
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	mov	rsi,rcx		; Load data ptr.
	mov	rcx,rdx		; rcx=amount of pixels
	jrcxz	ToEnd		; array has zero size

LoopPix:mov	ax,[rsi]
	mov	dx,[rsi+4]
	mov	[rsi+4],ax
	mov	[rsi],dx	
	mov	ax,[rsi+6]
	not	ax
	mov	[rsi+6],ax	
		
	add	rsi,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 rsi rdi
;       OutData: ptr byte,RCX
;       InData: ptr byte,RDX
;       PixelCount: QWORD R8

	mov	rsi,rdx
	mov	rdi,rcx

        mov     rcx,R8		; cx=amount of pixels

	sub	rcx,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,[rsi]	; EDX = G3 R3 B2 G2
	add	rsi,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	[rdi],edx	;	G3 B3 R2 G2	shipped out
	add	rdi,4

	stosd			; R4 G4 B4 R3	shipped out
	
	sub	rcx,4
	jae	LoopPix4

			; Simple loop for 0,1,2,3 pixels (works also for more px)
LoopSimple:
	add	rcx,4		; rcx was -4, correct counter
        jz	ToEnd		; array has zero size

LoopPix:lodsw
	mov	[rdi+2],al
	mov	[rdi+1],ah
	lodsb
	mov	[rdi],al
	add	rdi,3
	dec	rcx
	jz	ToEnd
	
	lodsb
	mov	[rdi+2],al
	lodsw
	mov	[rdi+1],al
	mov	[rdi],ah
	add	rdi,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 rsi rdi rbx
;       OutData: ptr byte,RCX
;       InData: ptr byte,RDX
;       PixelCount: QWORD R8

        mov     rsi,rdx			; source data
        mov     rdi,rcx			; destination data

	mov     rcx,R8			; rcx=amount of pixels

        sub	rcx,4
	jl	LoopSimple		; array size < 4

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

	mov	ebx,[rsi]		; EBX = ?? B3 G3 R3
	add	rsi,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	rcx,4
	jae	LoopPx4

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

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

ToEnd:
        ret                     ; _cdecl return
                
RGB32_BGR24 endp



;void RGB_Gray(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB24_Gray8
RGB24_Gray8 proc \
        uses rsi rdi rbx
;	OutData:ptr byte, \
;       InData:ptr byte, \
;       PixelCount:DWORD

        mov     rsi,rdx			; source data
        mov     rdi,rcx			; destination data

        mov     rcx,R8			; rcx=amount of pixels
        
	mov	ebx,3

	sub	rcx,2
	jl	LoopPix1

LoopPix2:
	lodsw
	add	al,ah
	mov	ah,0
	rcl	ah,1
	mov	dx,[rsi]
	add	rsi,2
	add	al,dl
	adc	ah,0
	div	bl
	stosb

	lodsw
	add	al,ah
	mov	ah,0
	rcl	ah,1
	add	al,dh
	adc	ah,0
	div	bl
	stosb

	sub	rcx,2
	jae	LoopPix2
	
LoopPix1:
	add	rcx,2
        cmp	rcx,1
        jl	ToEnd			; array has zero size

	mov	dh,0
	
LoopPix:mov	ah,0
	mov	al,[rsi]
	mov	bl,[rsi+1]
	add	ax,bx
	mov	bl,[rsi+2]
	add	ax,bx
	mov	bl,3
	div	bl
	stosb
	add	rsi,3
	loop	LoopPix

ToEnd:
	ret                     ; _cdecl return

RGB24_Gray8 endp


;void RGB_Gray24(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB_Gray24
RGB_Gray24 proc \
        uses rsi rdi rbx
;	OutData:ptr byte, \
;       InData:ptr byte, \
;       PixelCount:DWORD

        mov     rsi,rdx			; source data
        mov     rdi,rcx			; destination data

        mov     rcx,R8			; rcx=amount of pixels
        
	mov	ebx,3

	sub	rcx,2
	jl	LoopPix1

LoopPix2:
	lodsw
	add	al,ah
	mov	ah,0
	rcl	ah,1
	mov	dx,[rsi]
	add	rsi,2
	add	al,dl
	adc	ah,0
	div	bl
	stosb
	stosb
	stosb

	lodsw
	add	al,ah
	mov	ah,0
	rcl	ah,1
	add	al,dh
	adc	ah,0
	div	bl
	stosb
	stosb
	stosb

	sub	rcx,2
	jae	LoopPix2
	
LoopPix1:
	add	rcx,2
        cmp	rcx,1
        jl	ToEnd			; array has zero size

	mov	dh,0
	
LoopPix:mov	ah,0
	mov	al,[rsi]
	mov	bl,[rsi+1]
	add	ax,bx
	mov	bl,[rsi+2]
	add	ax,bx
	mov	bl,3
	div	bl
	stosb
	stosb
	stosb	
	add	rsi,3
	loop	LoopPix

ToEnd:
	ret                     ; _cdecl return

RGB_Gray24 endp


;void RGB32_Gray(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	RGB32_Gray
RGB32_Gray proc \
        uses rsi rdi rbx
;	OutData:ptr byte, \
;        InData:ptr byte, \
;        PixelCount:DWORD

	mov	rsi,rdx			; source data
	mov	rdi,rcx			; destination data

	mov	rcx,R8			; rcx=amount of pixels
	jrcxz	ToEnd			; array has zero size

	mov	bh,0	
LoopPix:mov	ah,0
	mov	al,[rsi]
	mov	bl,[rsi+1]
	add	ax,bx
	mov	bl,[rsi+2]
	add	ax,bx
	mov	bl,3
	div	bl
	stosb
	add	rsi,4
	loop	LoopPix

ToEnd:
	ret                     ; _cdecl return
                
RGB32_Gray endp


;void BGR_Gray24precise(unsigned char *OutData, const unsigned char *InData, unsigned PixelCount)
	public	BGR_Gray24precise
BGR_Gray24precise proc \
        uses rsi rdi rbx
;	OutData:ptr byte, \
;        InData:ptr byte, \
;        PixelCount:DWORD

	mov	rsi,rdx			; source data
	mov	rdi,rcx			; destination data

	mov	rcx,R8			; rcx=amount of pixels
	jrcxz	ToEnd			; array has zero size

	cld
LoopPix:movzx	eax,byte ptr[rsi]
	imul	edx,eax,4731

	movzx	eax,byte ptr[rsi+1]
	imul	eax,eax,46871
	add	edx,eax

	movzx	eax,byte ptr[rsi+2]
	imul	eax,eax,13932
	add	eax,edx

	shr	eax,16
	add	rsi,3
	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 rdi
;	OutData:ptr byte, \
;       InData:ptr byte, \
;       PixelCount:DWORD
	
	mov	rdi,rcx			; destination data
	mov	rcx,R8			; rcx=amount of pixels
	mov	r8,rdx			; source data
	jrcxz	ToEnd			; array has zero size

LoopPix:movzx	eax,byte ptr[r8]
	imul	edx,eax,4731

	movzx	eax,byte ptr[r8+1]
	imul	eax,eax,46871
	add	edx,eax

	movzx	eax,byte ptr[r8+2]
	imul	eax,eax,13932
	add	eax,edx			; return value to eax
	
	add	r8,4
	shr	eax,16	
	stosb
	stosb
	stosb
	loop	LoopPix

ToEnd:
	ret                     ; _cdecl return

BGR32_Gray24 endp


;void NotR(char *R, unsigned DataSize)	//R1:=not(R1)
	public  NotR
NotR	proc \
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	xchg	rcx,rdx		; rcx=amount of pixels/bytes

        sub	rcx,8
        jl	LoopPx1
        
LoopPx8:;mov	rax,[rdx]	;moving through register is slower on x64. On x32 it works better.
        ;not	rax
        ;mov	[rdx],rax
        not	qword ptr [rdx]	; Invert QWORDs
        add	rdx,8
        
        sub	rcx,8
        jge	LoopPx8

LoopPx1:add	rcx,8
	jz	ToEnd

LoopPix:not	byte ptr [rdx]	; Invert BYTE
	inc	rdx
	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
IF (@Version LT 1200) OR (@Version GE 1300)
YUV_RGB proc \
        uses rdi rsi rbx,
        OutData: ptr BYTE,
        y: ptr BYTE,
        u: ptr BYTE,
	v: ptr BYTE,
	PixelCount: DWORD	; on stack
ELSE
; The ASM from MSVC2013 seems to be much more worse than previous one.
YUV_RGB proc \
        uses rdi rsi rbx
ENDIF
	
	mov	rdi,rcx		; [OutData]
	mov	rsi,rdx		; [y]
IF (@Version LT 1200) OR (@Version GE 1300)
	mov	ecx,PixelCount
ELSE
	mov	ecx,[rsp+28h+3*8]	;28h stays for 5th arg; 3 registers rdi,rsi,rbx are now on the stack
ENDIF

	sub	ecx,2
	jb	exit

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

	xor	eax,eax
	mov	al,[R9]		; V
	sub	eax,128
	mov	R10,rax	
	imul	eax,291		; 291*V	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR1:	mov	[rdi],ah	; R1

	movzx	eax,byte ptr [R8]	; U
	sub	eax,128
	mov	R11d,eax
	imul	eax,521		; 291*V	
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormB1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax	
NormB1:	mov	[rdi+2],ah	; B1
				;EDX = 255*Y
	mov	rax,R10		; V	
	imul	eax,148
	sub	edx,eax
	
	mov	eax,R11d	; U
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG1
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx	
NormG1:	mov	[rdi+1],dh	; G1	

	inc	rsi	

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

	mov	rax,R10		; V	
	imul	eax,291		; 291*V	
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR2:	mov	[rdi+3],ah	; R2

	mov	eax,R11d	; U
	imul	eax,521		; 521*U	
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormB2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormB2:	mov	[rdi+5],ah	; B2

				;EDX = 255*Y
	mov	rax,R10		; V	
	imul	eax,148
	sub	edx,eax
	
	mov	eax,R11d	; U
	imul	eax,102		; 102*U
	sub	edx,eax		; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG2
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx
NormG2:	mov	[rdi+4],dh	; G2

	inc	R8		; inc U every 2nd pixel
	inc	R9		; inc V every 2nd pixel
	add	rdi,6		; Shift to R3

	inc	rsi		; inc Y every pixel
	sub	ecx,2
	jae	LoopPx

Exit:	
	ret
YUV_RGB endp


;void YUYV_RGB(unsigned char *OutData, const unsigned char *yuyv, unsigned PixelCount);
	public YUYV_RGB
YUYV_RGB proc \
        uses rdi rsi rbx
;        OutData: ptr BYTE, \
;        yuyv: ptr BYTE, \
;	PixelCount: DWORD

	mov	rsi,rdx			; source data
	mov	rdi,rcx			; destination data
	mov	rcx,R8			; rcx=amount of pixels
	
	sub	ecx,2
	jb	Exit

LoopPx:	mov	ebx,[rsi]	; V_Y2_U_Y1
	mov	eax,ebx
	
	xor	edx,edx
	mov	dh,bl		; 255*Y
	
	rol	eax,8
	and	eax,0FFh	; V
	sub	eax,128
	mov	r8d,eax		; store V  ---> to R8D
	imul	eax,291		; 291*V
	mov	r9d,eax		; store 291*V to r9d
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR1:	mov	[rdi],ah	; R1

	movzx	eax,bh		; U
	sub	eax,128
	mov	r11d,eax
	imul	eax,521		; 521*U
	mov	r10d,eax
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormB1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax	
NormB1:	mov	[rdi+2],ah	; B1

				;EDX = 255*Y	
	imul	r8d,r8d,148	; V normalised *148 ---> R8D
	sub	edx,r8d
	
	imul	r11d,r11d,102	; 102*U
	sub	edx,r11d	; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG1
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx	
NormG1:	mov	[rdi+1],dh	; G1

		; 2nd pixel
	ror	ebx,8
	mov	eax,r9d		; 291*V
	and	ebx,0FF00h	; 255*Y2	
	add	eax,ebx

	test	eax,0FFFF0000h
	jz	NormR2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR2:	mov	[rdi+3],ah	; R2

	mov	eax,r10d	; 521*U
	add	eax,ebx

	test	eax,0FFFF0000h
	jz	NormB2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormB2:	mov	[rdi+5],ah	; B2

				;EDX = 255*Y
	sub	ebx,r8d		; V normalised * 148
				; r11d - 102*U normalised
	sub	ebx,r11d	; 255*Y - 102*U - 148*V
	test	ebx,0FFFF0000h
	jz	NormG2
	sar	ebx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	ebx
NormG2:	mov	[rdi+4],bh	; **** G2 ****

	add	rsi,4		; inc Y per 2 pixels
	add	rdi,6		; Shift to R3
	sub	ecx,2
	jae	LoopPx

Exit:	
	ret
YUYV_RGB endp


;void UYVY_RGB(unsigned char *OutData, const unsigned char *yuyv, unsigned PixelCount);
	public UYVY_RGB
UYVY_RGB proc \
        uses rdi rsi rbx
;        OutData: ptr BYTE, \
;        yuyv: ptr BYTE, \
;	PixelCount: DWORD

	mov	rsi,rdx			; source data
	mov	rdi,rcx			; destination data
	mov	rcx,R8			; rcx=amount of pixels
	
	sub	ecx,2
	jb	Exit

LoopPx:	mov	ebx,[rsi]	; Y2_V_Y1_U
	mov	eax,ebx
	
	xor	edx,edx
	mov	dh,bh		; 255*Y
	
	ror	eax,8
	movzx	eax,ah		; V
	sub	eax,128
	mov	r8d,eax		; store V  ---> to R8D
	imul	eax,291		; 291*V
	mov	r9d,eax		; store 291*V to r9d
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR1:	mov	[rdi],ah	; R1

	movzx	eax,bl		; U
	sub	eax,128
	mov	r11d,eax
	imul	eax,521		; 521*U
	mov	r10d,eax
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormB1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax	
NormB1:	mov	[rdi+2],ah	; B1

				;EDX = 255*Y	
	imul	r8d,r8d,148	; V normalised *148 ---> R8D
	sub	edx,r8d
	
	imul	r11d,r11d,102	; 102*U
	sub	edx,r11d	; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG1
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx	
NormG1:	mov	[rdi+1],dh	; G1

		; 2nd pixel
	ror	ebx,16
	mov	eax,r9d		; 291*V
	and	ebx,0FF00h	; 255*Y2	
	add	eax,ebx

	test	eax,0FFFF0000h
	jz	NormR2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR2:	mov	[rdi+3],ah	; R2

	mov	eax,r10d	; 521*U
	add	eax,ebx

	test	eax,0FFFF0000h
	jz	NormB2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormB2:	mov	[rdi+5],ah	; B2

				;EDX = 255*Y
	sub	ebx,r8d		; V normalised * 148
				; r11d - 102*U normalised
	sub	ebx,r11d	; 255*Y - 102*U - 148*V

	test	ebx,0FFFF0000h
	jz	NormG2
	sar	ebx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	ebx
NormG2:	mov	[rdi+4],bh	; G2

	add	rsi,4		; inc Y per 2 pixels
	add	rdi,6		; Shift to R3
	sub	ecx,2
	jae	LoopPx

Exit:	
	ret
UYVY_RGB endp



;void YVYU_RGB(unsigned char *OutData, const unsigned char *YVYU, unsigned PixelCount);
	public YVYU_RGB
YVYU_RGB proc \
        uses rdi rsi rbx
;        OutData: ptr BYTE, \
;        YVYU: ptr BYTE, \
;	PixelCount: DWORD

	mov	rsi,rdx			; source data
	mov	rdi,rcx			; destination data
	mov	rcx,R8			; rcx=amount of pixels
	
	sub	ecx,2
	jb	Exit

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

	movzx	eax,bh		; V
	sub	eax,128
	mov	r8d,eax		; store V to R8D
	imul	eax,291		; 291*V
	mov	r9d,eax		; store 291*V to r9d
	add	eax,edx
	
	test	eax,0FFFF0000h
	jz	NormR1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR1:	mov	[rdi],ah	; R1

	mov	eax,ebx
	rol	eax,8
	and	eax,0FFh	; U
	sub	eax,128
	mov	r11d,eax
	imul	eax,521		; 521*U
	mov	r10d,eax
	add	eax,edx

	test	eax,0FFFF0000h
	jz	NormB1
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax	
NormB1:	mov	[rdi+2],ah	; B1

				;EDX = 255*Y	
	imul	r8d,r8d,148	; V normalised *148 ---> R8D
	sub	edx,r8d
	
	imul	r11d,r11d,102	; 102*U
	sub	edx,r11d	; 255*Y - 102*U - 148*V

	test	edx,0FFFF0000h
	jz	NormG1
	sar	edx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	edx	
NormG1:	mov	[rdi+1],dh	; G1

		; 2nd pixel		
	ror	ebx,8
	mov	eax,r9d		; 291*V
	and	ebx,0FF00h	; 255*Y2	
	add	eax,ebx
	
	test	eax,0FFFF0000h
	jz	NormR2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormR2:	mov	[rdi+3],ah	; R2

	mov	eax,r10d	; 521*U
	add	eax,ebx

	test	eax,0FFFF0000h
	jz	NormB2
	sar	eax,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	eax
NormB2:	mov	[rdi+5],ah	; B2

				;EDX = 255*Y
	sub	ebx,r8d		; V normalised * 148
				; r11d - 102*U normalised
	sub	ebx,r11d	; 255*Y - 102*U - 148*V

	test	ebx,0FFFF0000h
	jz	NormG2
	sar	ebx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	ebx
NormG2:	mov	[rdi+4],bh	; G2

	add	rsi,4		; inc Y per 2 pixels
	add	rdi,6		; Shift to R3
	sub	ecx,2
	jae	LoopPx

Exit:	
	ret
YVYU_RGB endp


;void AYUV_BGR24(void *pDst, const void *pSrc, unsigned Pixels);
        public  AYUV_BGR24
AYUV_BGR24 proc \
        uses rdi rbx
;        pDst:ptr byte, \	RCX
;        pSrc:ptr byte, \	RDX
;        Pixels:DWORD		R8

	or	rdx,rdx
	jz	toend
	mov	R11,rdx
	mov	rdi,rcx
	or	rdi,rdi
	jz	toend
	or	R8,R8
	jz	toend

LoopPx: mov	ebx,[R11]
	xor	edx,edx
	mov	dh,bh			; Y
	shr	ebx,16

	movzx	ecx,bh			; V
	movzx	R9d,bl			; U
	sub	ecx,128		
	imul	eax,ecx,291		; 291*V	
	sub	R9d,128			; U-128

	add	eax,edx
	mov	ebx,eax
	sar	ebx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	ebx

	test	eax,0FFFF0000h
	cmovnz	ax,bx
	mov	[rdi+2],ah		;  ****** STORE R ******

	imul	eax,R9d,521		; 521*V	
	add	eax,edx

	mov	ebx,eax
	sar	ebx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	ebx
	test	eax,0FFFF0000h
	cmovnz	ax,bx	
	imul	ebx,R9d,102		; 102*U		
	mov	[rdi],ah		; ****** STORE B ******

	imul	eax,ecx,148		; 148*V
	sub	edx,ebx			; 255*Y - 102*U - 148*V
	sub	edx,eax	
					;EDX = 255*Y	
	mov	ebx,edx
	sar	ebx,24			; signed DWORD <0 AH=1; >0 AH=0;
	not	ebx		

	test	edx,0FFFF0000h
	cmovnz	dx,bx
	mov	[rdi+1],dh		; ****** STORE  G  ******
	add	rdi,3
	add	R11,4	
	dec	R8
	jnz	LoopPx

toend:
        ret                     ; _cdecl return

AYUV_BGR24 endp


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


;void swab16(unsigned char *Data, unsigned PixelCount)
	public	swab16

swab16 proc \
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

        xchg	rcx,rdx
        
        sub	rcx,2
	jl	LoopPx1

LoopPx2:mov	eax,[rdx]
	bswap	eax
	rol	eax,16
	mov	[rdx],eax
	add	rdx,4
        sub	rcx,2
	jae	LoopPx2

LoopPx1:add	rcx,2
	jz	ToEnd		; array has zero size

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

ToEnd:
        ret                     ; _cdecl return
                
swab16	endp



;void swab32(unsigned char *Data, unsigned PixelCount)
	public	swab32

swab32 proc
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	xchg	rcx,rdx        

	sub	rcx,2
	jl	LoopPx1

LoopPx2:mov	rax,[rdx]
	bswap	rax
	rol	rax,32
	mov	[rdx],rax
	add	rdx,8
        sub	rcx,2
	jae	LoopPx2

LoopPx1:add	rcx,2
	jz	ToEnd		; array has zero size

LoopPix:mov	eax,[rdx]
	bswap	eax
	mov	[rdx],eax
	add	rdx,4
	loop	LoopPix

ToEnd:
        ret                     ; _cdecl return
                
swab32	endp



;void swab64(unsigned char *Data, unsigned PixelCount)
	public	swab64

swab64 proc
;       Dest:ptr byte,	RCX
;       count:DWORD	RDX

	xchg	rdx,rcx
        jrcxz	ToEnd		; array has zero size

LoopPix:mov	rax,[rdx]
	bswap	rax
	mov	[rdx],rax
	add	rdx,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 rdi rbx rsi
;	OutL: ptr DWORD, \
;	InL: ptr DWORD, \
;	In2L: ptr DWORD, \
;	SizeX: DWORD

	mov	rdi,rcx		; [Out]
	or	rdi,rdi
	jz	DiffV1E
	mov	rsi,rdx		; [In]
	or	rsi,rsi
	jz	DiffV1E
	mov	rdx,R8		; [In2]
	or	rdx,rdx
	jz	DiffV1E
	mov	rcx,R9
	jrcxz	DiffV1E	
DiffV11:mov	eax,[rsi]
	stc
	rcr	eax,1
	add	rsi,4
	mov	ebx,[rdx]
	shr	ebx,1
	sub	eax,ebx
	add	rdx,4
	mov	[rdi],eax
	add	rdi,4
	loop	DiffV11
DiffV1E:ret
DiffVer1_u32 endp


        end
