snes9x/win32/render.cpp

2769 lines
140 KiB
C++
Raw Normal View History

/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
2010-09-25 17:46:12 +02:00
/* Render.CPP
* ----------
* Video output filters for the Windows port.
*/
2015-01-29 21:42:32 +01:00
#include <algorithm>
2010-09-25 17:46:12 +02:00
#include "../port.h"
#include "wsnes9x.h"
#include "../snes9x.h"
#include <memory.h>
#include "render.h"
#include "../ppu.h"
#include "../gfx.h"
#include <math.h>
#include "../gfx.h"
#include "../filter/2xsai.h"
#include "../filter/hq2x.h"
#include "snes_ntsc.h"
2014-06-24 21:53:00 +02:00
#include "../filter/xbrz.h"
#include <vector>
#include <intrin.h>
2010-09-25 17:46:12 +02:00
// Private Prototypes, should not be called directly
void RenderPlain (SSurface Src, SSurface Dst, RECT *);
void RenderForced1X (SSurface Src, SSurface Dst, RECT *);
void RenderSimple2X (SSurface Src, SSurface Dst, RECT *);
void RenderFakeTV (SSurface Src, SSurface Dst, RECT *);
void RenderSuperEagle (SSurface Src, SSurface Dst, RECT *);
void Render2xSaI (SSurface Src, SSurface Dst, RECT *);
void RenderSuper2xSaI (SSurface Src, SSurface Dst, RECT *);
void RenderTVMode (SSurface Src, SSurface Dst, RECT *);
template<int T> void RenderHQ2X (SSurface Src, SSurface Dst, RECT *rect);
template<int T> void RenderHQ3X (SSurface Src, SSurface Dst, RECT *rect);
void RenderLQ3XB (SSurface Src, SSurface Dst, RECT *rect);
void RenderHQ4X (SSurface Src, SSurface Dst, RECT *rect);
2014-06-25 23:16:52 +02:00
void Render2xBRZ(SSurface Src, SSurface Dst, RECT* rect);
void Render3xBRZ(SSurface Src, SSurface Dst, RECT* rect);
2014-06-24 21:53:00 +02:00
void Render4xBRZ(SSurface Src, SSurface Dst, RECT* rect);
2016-10-07 21:39:32 +02:00
void Render5xBRZ(SSurface Src, SSurface Dst, RECT* rect);
void Render6xBRZ(SSurface Src, SSurface Dst, RECT* rect);
2010-09-25 17:46:12 +02:00
void RenderEPXA (SSurface Src, SSurface Dst, RECT *);
void RenderEPXB (SSurface Src, SSurface Dst, RECT *);
void RenderEPXC (SSurface Src, SSurface Dst, RECT *);
void RenderEPX3 (SSurface Src, SSurface Dst, RECT *);
void RenderSimple3X (SSurface Src, SSurface Dst, RECT *);
void RenderSimple4X (SSurface Src, SSurface Dst, RECT *);
void RenderTVMode3X (SSurface Src, SSurface Dst, RECT *);
void RenderDotMatrix3X (SSurface Src, SSurface Dst, RECT *);
void RenderBlarggNTSCComposite(SSurface Src, SSurface Dst, RECT *);
void RenderBlarggNTSCSvideo(SSurface Src, SSurface Dst, RECT *);
void RenderBlarggNTSCRgb(SSurface Src, SSurface Dst, RECT *);
void RenderBlarggNTSC(SSurface Src, SSurface Dst, RECT *);
void RenderMergeHires(void *src, int srcPitch , void* dst, int dstPitch, unsigned int width, unsigned int height);
void InitLUTsWin32(void);
2014-06-25 23:16:52 +02:00
void RenderxBRZ(SSurface Src, SSurface Dst, RECT* rect, int scalingFactor);
2010-09-25 17:46:12 +02:00
// Contains the pointer to the now active render method
typedef void (*TRenderMethod)( SSurface Src, SSurface Dst, RECT *);
TRenderMethod _RenderMethod = RenderPlain;
TRenderMethod _RenderMethodHiRes = RenderPlain;
2010-09-25 17:46:12 +02:00
// Used as change log
static uint8 ChangeLog1 [EXT_PITCH * MAX_SNES_HEIGHT];
static uint8 ChangeLog2 [EXT_PITCH * MAX_SNES_HEIGHT];
static uint8 ChangeLog3 [EXT_PITCH * MAX_SNES_HEIGHT];
BYTE *BlendBuf = NULL;
BYTE *BlendBuffer = NULL;
2010-09-25 17:46:12 +02:00
uint8 *ChangeLog [3] = {
ChangeLog1, ChangeLog2, ChangeLog3
};
START_EXTERN_C
uint8 snes9x_clear_change_log = 0;
END_EXTERN_C
enum BlarggMode { UNINITIALIZED,BLARGGCOMPOSITE,BLARGGSVIDEO,BLARGGRGB };
snes_ntsc_t *ntsc = NULL;
BlarggMode blarggMode = UNINITIALIZED;
2014-06-24 21:53:00 +02:00
int num_xbrz_threads = 4;
struct xbrz_thread_data {
HANDLE xbrz_start_event;
HANDLE xbrz_sync_event;
HANDLE thread_handle;
static int scalingFactor;
static SSurface *src;
static SSurface *dst;
static uint8* dstPtr;
int yFirst;
int yLast;
};
xbrz_thread_data *xbrz_thread_sync_data;
int xbrz_thread_data::scalingFactor = 4;
SSurface *xbrz_thread_data::src = NULL;
SSurface *xbrz_thread_data::dst = NULL;
uint8 *xbrz_thread_data::dstPtr = NULL;
HANDLE *xbrz_sync_handles;
DWORD WINAPI ThreadProc_XBRZ(VOID * pParam);
2010-09-25 17:46:12 +02:00
TRenderMethod FilterToMethod(RenderFilter filterID)
{
switch(filterID)
{
default:
case FILTER_NONE: return RenderPlain;
case FILTER_SIMPLE1X: return RenderForced1X;
case FILTER_SIMPLE2X: return RenderSimple2X;
case FILTER_SCANLINES: return RenderFakeTV;
case FILTER_TVMODE: return RenderTVMode;
case FILTER_SUPEREAGLE: return RenderSuperEagle;
case FILTER_SUPER2XSAI: return RenderSuper2xSaI;
case FILTER_2XSAI: return Render2xSaI;
case FILTER_HQ2X: return RenderHQ2X<FILTER_HQ2X>;
case FILTER_HQ2XS: return RenderHQ2X<FILTER_HQ2XS>;
case FILTER_HQ2XBOLD: return RenderHQ2X<FILTER_HQ2XBOLD>;
case FILTER_EPXA: return RenderEPXA;
case FILTER_EPXB: return RenderEPXB;
case FILTER_EPXC: return RenderEPXC;
2014-06-25 23:16:52 +02:00
case FILTER_2XBRZ: return Render2xBRZ;
2010-09-25 17:46:12 +02:00
case FILTER_SIMPLE3X: return RenderSimple3X;
case FILTER_TVMODE3X: return RenderTVMode3X;
case FILTER_DOTMATRIX3X:return RenderDotMatrix3X;
case FILTER_HQ3X: return RenderHQ3X<FILTER_HQ3X>;
case FILTER_HQ3XS: return RenderHQ3X<FILTER_HQ3XS>;
case FILTER_HQ3XBOLD: return RenderHQ3X<FILTER_HQ3XBOLD>;
case FILTER_LQ3XBOLD: return RenderLQ3XB;
case FILTER_EPX3: return RenderEPX3;
2014-06-25 23:16:52 +02:00
case FILTER_3XBRZ: return Render3xBRZ;
2010-09-25 17:46:12 +02:00
case FILTER_BLARGGCOMP: return RenderBlarggNTSCComposite;
case FILTER_BLARGGSVID: return RenderBlarggNTSCSvideo;
case FILTER_BLARGGRGB: return RenderBlarggNTSCRgb;
case FILTER_SIMPLE4X: return RenderSimple4X;
case FILTER_HQ4X: return RenderHQ4X;
2014-06-24 21:53:00 +02:00
case FILTER_4XBRZ: return Render4xBRZ;
2016-10-07 21:39:32 +02:00
case FILTER_5XBRZ: return Render5xBRZ;
case FILTER_6XBRZ: return Render6xBRZ;
2010-09-25 17:46:12 +02:00
}
}
const char* GetFilterName(RenderFilter filterID)
{
switch(filterID)
{
default: return "Unknown";
case FILTER_NONE: return "None";
case FILTER_SIMPLE1X: return "Forced 1X";
case FILTER_SIMPLE2X: return "Simple 2X";
case FILTER_SCANLINES: return "Scanlines";
case FILTER_TVMODE: return "TV Mode";
case FILTER_BLARGGCOMP: return "Blargg's NTSC (Composite)";
case FILTER_BLARGGSVID: return "Blargg's NTSC (S-Video)";
case FILTER_BLARGGRGB: return "Blargg's NTSC (RGB)";
case FILTER_SUPEREAGLE: return "SuperEagle";
case FILTER_SUPER2XSAI: return "Super2xSaI";
case FILTER_2XSAI: return "2xSaI";
case FILTER_HQ2X: return "hq2x";
case FILTER_HQ2XS: return "hq2xS";
case FILTER_HQ2XBOLD: return "hq2xBold";
case FILTER_EPXA: return "EPX A";
case FILTER_EPXB: return "EPX B";
case FILTER_EPXC: return "EPX C";
2014-06-25 23:16:52 +02:00
case FILTER_2XBRZ: return "2xBRZ";
2010-09-25 17:46:12 +02:00
case FILTER_SIMPLE3X: return "Simple 3X";
case FILTER_TVMODE3X: return "TV Mode 3X";
case FILTER_DOTMATRIX3X: return "Dot Matrix 3X";
case FILTER_HQ3X: return "hq3x";
case FILTER_HQ3XS: return "hq3xS";
case FILTER_HQ3XBOLD: return "hq3xBold";
case FILTER_LQ3XBOLD: return "lq3xBold";
case FILTER_EPX3: return "EPX3";
2014-06-25 23:16:52 +02:00
case FILTER_3XBRZ: return "3xBRZ";
2010-09-25 17:46:12 +02:00
case FILTER_SIMPLE4X: return "Simple 4X";
case FILTER_HQ4X: return "hq4x";
2014-06-24 21:53:00 +02:00
case FILTER_4XBRZ: return "4xBRZ";
2016-10-07 21:39:32 +02:00
case FILTER_5XBRZ: return "5xBRZ";
case FILTER_6XBRZ: return "6xBRZ";
2010-09-25 17:46:12 +02:00
}
}
int GetFilterScale(RenderFilter filterID)
{
switch(filterID)
{
case FILTER_NONE:
case FILTER_SIMPLE1X:
return 1;
default:
return 2;
case FILTER_SIMPLE3X:
case FILTER_TVMODE3X:
case FILTER_DOTMATRIX3X:
case FILTER_HQ3X:
case FILTER_HQ3XS:
case FILTER_HQ3XBOLD:
case FILTER_LQ3XBOLD:
case FILTER_EPX3:
case FILTER_BLARGGCOMP:
case FILTER_BLARGGSVID:
case FILTER_BLARGGRGB:
2014-06-25 23:16:52 +02:00
case FILTER_3XBRZ:
2010-09-25 17:46:12 +02:00
return 3;
case FILTER_SIMPLE4X:
case FILTER_HQ4X:
2014-06-24 21:53:00 +02:00
case FILTER_4XBRZ:
2010-09-25 17:46:12 +02:00
return 4;
2016-10-07 21:39:32 +02:00
case FILTER_5XBRZ:
return 5;
case FILTER_6XBRZ:
return 6;
2010-09-25 17:46:12 +02:00
}
}
bool GetFilterHiResSupport(RenderFilter filterID)
{
switch(filterID)
{
case FILTER_NONE:
case FILTER_SIMPLE1X:
case FILTER_SIMPLE2X:
case FILTER_SCANLINES:
case FILTER_BLARGGCOMP:
case FILTER_BLARGGSVID:
case FILTER_BLARGGRGB:
case FILTER_TVMODE:
case FILTER_SIMPLE3X:
case FILTER_SIMPLE4X:
case FILTER_HQ4X:
2014-06-25 23:16:52 +02:00
case FILTER_2XBRZ:
case FILTER_3XBRZ:
2014-06-24 21:53:00 +02:00
case FILTER_4XBRZ:
2016-10-07 21:39:32 +02:00
case FILTER_5XBRZ:
case FILTER_6XBRZ:
2010-09-25 17:46:12 +02:00
return true;
default:
return false;
}
}
inline static bool GetFilter32BitSupport(RenderFilter filterID)
{
switch(filterID)
{
case FILTER_NONE:
case FILTER_SIMPLE1X:
case FILTER_SIMPLE2X:
case FILTER_SIMPLE3X:
case FILTER_EPXA:
case FILTER_EPXB:
case FILTER_EPXC:
case FILTER_EPX3:
case FILTER_SCANLINES:
case FILTER_TVMODE3X:
case FILTER_DOTMATRIX3X:
2010-09-25 17:52:32 +02:00
case FILTER_SIMPLE4X:
2010-09-25 17:46:12 +02:00
return true;
default:
return false;
}
}
inline static bool GetFilterBlendSupport(RenderFilter filterID)
{
switch(filterID)
{
case FILTER_SIMPLE1X:
case FILTER_BLARGGCOMP:
case FILTER_BLARGGSVID:
case FILTER_BLARGGRGB:
return true;
default:
return false;
}
}
void AdjustHeightExtend(unsigned int &height)
{
if(GUI.HeightExtend)
{
if(height == SNES_HEIGHT)
height = SNES_HEIGHT_EXTENDED;
else if(height == SNES_HEIGHT * 2)
height = SNES_HEIGHT_EXTENDED * 2;
}
else
{
if(height == SNES_HEIGHT_EXTENDED)
height = SNES_HEIGHT;
else if(height == SNES_HEIGHT_EXTENDED * 2)
height = SNES_HEIGHT * 2;
}
}
inline void SetRect(RECT* rect, unsigned int width, unsigned int height, int scale)
{
AdjustHeightExtend(height);
rect->left = 0;
rect->right = width * scale;
rect->top = 0;
rect->bottom = height * scale;
}
RECT GetFilterOutputSize(SSurface Src)
{
RECT rect;
RenderFilter filterID = GUI.Scale;
if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) {
filterID = GUI.ScaleHiRes;
}
// default to fixed factor
SetRect(&rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, GetFilterScale(filterID));
// handle special cases
switch (filterID)
{
case FILTER_NONE:
SetRect(&rect, Src.Width, Src.Height, 1);
break;
case FILTER_BLARGGCOMP:
case FILTER_BLARGGSVID:
case FILTER_BLARGGRGB:
SetRect(&rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 2);
rect.right = SNES_NTSC_OUT_WIDTH(256);
break;
default:
break;
}
return rect;
}
2010-09-25 17:46:12 +02:00
void SelectRenderMethod()
{
TRenderMethod OldRenderMethod = _RenderMethod;
TRenderMethod OldRenderMethodHiRes = _RenderMethodHiRes;
2010-09-25 17:46:12 +02:00
_RenderMethod = FilterToMethod(GUI.Scale);
_RenderMethodHiRes = FilterToMethod(GUI.ScaleHiRes);
2010-09-25 17:46:12 +02:00
if (OldRenderMethod != _RenderMethod || OldRenderMethodHiRes != _RenderMethodHiRes)
2010-09-25 17:46:12 +02:00
snes9x_clear_change_log = GUI.NumFlipFrames;
GUI.DepthConverted = !GUI.NeedDepthConvert;
if(GUI.ScreenDepth == 32 &&
((GetFilter32BitSupport(GUI.Scale) && (IPPU.RenderedScreenHeight <= SNES_HEIGHT_EXTENDED && IPPU.RenderedScreenWidth < 512)) ||
(GetFilter32BitSupport(GUI.ScaleHiRes) && (IPPU.RenderedScreenHeight > SNES_HEIGHT_EXTENDED || IPPU.RenderedScreenWidth == 512))))
{
// filter supports converting
GUI.DepthConverted = true;
}
}
void RenderMethod(SSurface Src, SSurface Dst, RECT * rect)
{
AdjustHeightExtend(Src.Height);
if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) {
if(GUI.BlendHiRes && Src.Width == 512 && !GetFilterBlendSupport(GUI.ScaleHiRes)) {
RenderMergeHires(Src.Surface,Src.Pitch,BlendBuffer,EXT_PITCH,Src.Width,Src.Height);
Src.Surface = BlendBuffer;
}
_RenderMethodHiRes(Src,Dst,rect);
} else {
_RenderMethod(Src,Dst,rect);
}
}
void InitRenderFilters(void)
{
InitLUTsWin32();
if(!ntsc) {
ntsc = new snes_ntsc_t;
}
if(!BlendBuf) {
BlendBuf = new BYTE [EXT_PITCH * EXT_HEIGHT];
BlendBuffer = BlendBuf + EXT_OFFSET;
memset(BlendBuf, 0, EXT_PITCH * EXT_HEIGHT);
}
2014-06-24 21:53:00 +02:00
SYSTEM_INFO sysinfo;
GetSystemInfo( &sysinfo );
2014-06-25 23:16:52 +02:00
num_xbrz_threads = sysinfo.dwNumberOfProcessors;
2014-06-24 21:53:00 +02:00
if(!xbrz_thread_sync_data) {
xbrz_thread_sync_data = new xbrz_thread_data[num_xbrz_threads];
xbrz_sync_handles = new HANDLE[num_xbrz_threads];
for(int i = 0; i < num_xbrz_threads; i++) {
xbrz_thread_sync_data[i].xbrz_start_event = CreateEvent(NULL, FALSE, FALSE, NULL);
xbrz_thread_sync_data[i].xbrz_sync_event = CreateEvent(NULL, FALSE, FALSE, NULL);
xbrz_thread_sync_data[i].thread_handle = CreateThread(NULL, 0, ThreadProc_XBRZ, &xbrz_thread_sync_data[i], 0, NULL);
xbrz_sync_handles[i] = xbrz_thread_sync_data[i].xbrz_sync_event;
}
}
}
2017-10-13 22:24:30 +02:00
void DeInitRenderFilters()
{
if (ntsc) {
delete ntsc;
}
if (BlendBuf) {
delete[] BlendBuf;
}
if (xbrz_thread_sync_data) {
delete[] xbrz_thread_sync_data;
delete[] xbrz_sync_handles;
}
S9xBlit2xSaIFilterDeinit();
S9xBlitHQ2xFilterDeinit();
}
2010-09-25 17:46:12 +02:00
#define R5G6B5 // windows port uses RGB565
#ifdef R5G6B5
#define Mask_2 0x07E0 // 00000 111111 00000
#define Mask13 0xF81F // 11111 000000 11111
#define Mask_1 0x001F // 00000 000000 11111
#define Mask_3 0xF800 // 11111 000000 00000
#define CONVERT_16_TO_32(pixel) \
(((((pixel) >> 11) ) << /*RedShift+3*/ 19) | \
((((pixel) >> 5) & 0x3f) << /*GreenShift+2*/10) | \
2010-09-25 17:46:12 +02:00
(((pixel) & 0x1f) << /*BlueShift+3*/ 3))
#define NUMBITS (16)
2014-06-24 21:53:00 +02:00
#define CONVERT_32_TO_16(pixel) \
(((((pixel) & 0xf80000) >> 8) | \
(((pixel) & 0xfc00) >> 5) | \
(((pixel) & 0xf8) >> 3)) & 0xffff)
2010-09-25 17:46:12 +02:00
#else
#define Mask_2 0x03E0 // 00000 11111 00000
#define Mask13 0x7C1F // 11111 00000 11111
#define Mask_1 0x001F // 00000 00000 11111
#define Mask_3 0x7C00 // 11111 00000 00000
#define CONVERT_16_TO_32(pixel) \
(((((pixel) >> 10) ) << /*RedShift+3*/ 19) | \
((((pixel) >> 5) & 0x1f) << /*GreenShift+3*/11) | \
(((pixel) & 0x1f) << /*BlueShift+3*/ 3))
#define NUMBITS (15)
2014-06-24 21:53:00 +02:00
#define CONVERT_32_TO_16(pixel) \
(((((pixel) & 0xf80000) >> 9) | \
(((pixel) & 0xf800) >> 6) | \
(((pixel) & 0xf8) >> 3)) & 0xffff)
2010-09-25 17:46:12 +02:00
#endif
static int RGBtoYUV[1<<NUMBITS];
static uint16 RGBtoBright[1<<NUMBITS];
#define Interp05(c1, c2) \
(((c1) == (c2)) ? (c1) : \
((((((c1) & Mask_2) + ((c2) & Mask_2)) >> 1) & Mask_2) + \
(((((c1) & Mask13) + ((c2) & Mask13)) >> 1) & Mask13)))
#define Interp01(c1, c2) \
((((c1) == (c2)) ? (c1) : \
(((((((c1) & Mask_2) * 3) + ((c2) & Mask_2)) >> 2) & Mask_2) + \
((((((c1) & Mask13) * 3) + ((c2) & Mask13)) >> 2) & Mask13))))
#define Halve(c1) \
((((((c1) & Mask_2)) >> 1) & Mask_2) + \
(((((c1) & Mask13)) >> 1) & Mask13))
#define ThreeQuarters(c1) \
((((((c1) & Mask_2)*3) >> 2) & Mask_2) + \
(((((c1) & Mask13)*3) >> 2) & Mask13))
#ifdef LSB_FIRST
#define TWO_PIX(left,right) ((left) | ((right) << 16))
#define THREE_PIX(left,middle,right) uint48((left) | ((middle) << 16), (right))
#define TWO_PIX_32(left,right) (CONVERT_16_TO_32(left) | ((uint64)CONVERT_16_TO_32(right) << 32))
#define THREE_PIX_32(left,middle,right) uint96(CONVERT_16_TO_32(left) | ((uint64)CONVERT_16_TO_32(middle) << 32), CONVERT_16_TO_32(right))
#else
#define TWO_PIX(left,right) ((right) | ((left) << 16))
#define THREE_PIX(left,middle,right) uint48((middle) | ((left) << 16), (right)) // is this right?
// #define THREE_PIX(left,middle,right) uint48((right) | ((middle) << 16), (left)) // or this?
#endif
// stretches a single line
inline void DoubleLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = *lpSrc;
*lpDst++ = *lpSrc++;
}
}
inline void TripleLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = *lpSrc;
*lpDst++ = *lpSrc;
*lpDst++ = *lpSrc++;
}
}
inline void QuadrupleLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = *lpSrc;
*lpDst++ = *lpSrc;
*lpDst++ = *lpSrc;
*lpDst++ = *lpSrc++;
}
}
inline void ThreeHalfLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width-=2){
*lpDst++ = *lpSrc;
*lpDst++ = Interp05(*lpSrc, *(lpSrc+1));
*lpDst++ = *(lpSrc+1);
lpSrc+=2;
}
}
inline void HalfLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = Interp05(*lpSrc, *(lpSrc+1));
lpSrc+=2;
}
}
inline void DoubleLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
lpSrc++;
}
}
inline void QuadrupleLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
lpSrc++;
}
}
inline void SingleLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
lpSrc++;
}
}
inline void HalfLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
const uint16 color = Interp05(*lpSrc, *(lpSrc+1));
*lpDst++ = CONVERT_16_TO_32(color);
lpSrc+=2;
}
}
inline void TripleLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width--){
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
lpSrc++;
}
}
inline void ThreeHalfLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){
while(Width-=2){
*lpDst++ = CONVERT_16_TO_32(*lpSrc);
const uint16 color = Interp05(*lpSrc, *(lpSrc+1));
*lpDst++ = CONVERT_16_TO_32(color);
*lpDst++ = CONVERT_16_TO_32(*(lpSrc+1));
lpSrc+=2;
}
}
#define AVERAGE_565(el0, el1) (((el0) & (el1)) + ((((el0) ^ (el1)) & 0xF7DE) >> 1))
void RenderMergeHires(void *src, int srcPitch , void* dst, int dstPitch, unsigned int width, unsigned int height)
{
for (register int y = 0; y < height; y++)
{
register uint16 *input = (uint16 *) ((uint8 *) src + y * srcPitch);
register uint16 *output = (uint16 *) ((uint8 *) dst + y * dstPitch);
register uint16 l, r;
l = 0;
for (register int x = 0; x < (width >> 1); x++)
{
r = *input++;
*output++ = AVERAGE_565 (l, r);
l = r;
r = *input++;
*output++ = AVERAGE_565 (l, r);
l = r;
}
}
return;
}
2010-09-25 17:46:12 +02:00
// No enlargement, just render to the screen
void RenderPlain (SSurface Src, SSurface Dst, RECT *rect)
{
SetRect(rect, Src.Width, Src.Height, 1);
const uint32 srcHeight = (rect->bottom - rect->top);
uint16 *lpSrc = reinterpret_cast<uint16 *>(Src.Surface);
const unsigned int srcPitch = Src.Pitch >> 1;
if(GUI.ScreenDepth == 16)
{
const unsigned int dstPitch = Dst.Pitch >> 1;
uint16 *lpDst = reinterpret_cast<uint16 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
for (unsigned int H = 0; H != srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch)
memcpy (lpDst, lpSrc, Src.Width << 1);
}
else if(GUI.ScreenDepth == 32)
{
const unsigned int dstPitch = Dst.Pitch >> 2;
uint32 *lpDst = reinterpret_cast<uint32 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
for (unsigned int H = 0; H != srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch)
SingleLine32(lpDst, lpSrc, Src.Width);
}
}
void RenderForced1X( SSurface Src, SSurface Dst, RECT *rect)
{
uint16 *lpSrc;
unsigned int H;
SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 1);
const uint32 srcHeight = (rect->bottom - rect->top);
const unsigned int srcPitch = Src.Pitch >> 1;
lpSrc = reinterpret_cast<uint16 *>(Src.Surface);
if(GUI.ScreenDepth == 16)
{
const unsigned int dstPitch = Dst.Pitch >> 1;
uint16 *lpDst = reinterpret_cast<uint16 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if (Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H != srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch)
memcpy (lpDst, lpSrc, Src.Width << 1);
else
for (H = 0; H < srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch)
HalfLine16 (lpDst, lpSrc, Src.Width >> 1);
2010-09-25 17:46:12 +02:00
else
if(Src.Width != 512)
for (H = 0; H != Src.Height; H+=2, lpDst += dstPitch, lpSrc += srcPitch<<1)
memcpy (lpDst, lpSrc, Src.Width << 1);
else
for (H = 0; H < Src.Height >> 1; H++, lpDst += dstPitch, lpSrc += srcPitch<<1)
HalfLine16 (lpDst, lpSrc, Src.Width >> 1);
2010-09-25 17:46:12 +02:00
}
else if(GUI.ScreenDepth == 32)
{
const unsigned int dstPitch = Dst.Pitch >> 2;
uint32 *lpDst = reinterpret_cast<uint32 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if (Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H != srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch)
SingleLine32 (lpDst, lpSrc, Src.Width);
else
for (H = 0; H < srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch)
HalfLine32 (lpDst, lpSrc, Src.Width >> 1);
2010-09-25 17:46:12 +02:00
else
if(Src.Width != 512)
for (H = 0; H != Src.Height; H+=2, lpDst += dstPitch, lpSrc += srcPitch<<1)
SingleLine32 (lpDst, lpSrc, Src.Width);
else
for (H = 0; H < Src.Height >> 1; H++, lpDst += dstPitch, lpSrc += srcPitch<<1)
HalfLine32 (lpDst, lpSrc, Src.Width >> 1);
2010-09-25 17:46:12 +02:00
}
}
// Enlarge 2x using Fake TV mode when the Snes9x is not rendering in HiRes
// FakeTV mode = a black line between each other line (scanlines)
void RenderFakeTV( SSurface Src, SSurface Dst, RECT *rect)
{
uint16 *lpSrc;
unsigned int H;
SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 2);
const uint32 srcHeight = (rect->bottom - rect->top)/2;
const unsigned int srcPitch = Src.Pitch >> 1;
lpSrc = reinterpret_cast<uint16 *>(Src.Surface);
if(GUI.ScreenDepth == 16)
{
const unsigned int dstPitch = Dst.Pitch >> 1;
uint16 *lpDst = reinterpret_cast<uint16 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if(Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
memset (lpDst, 0, 512*2), lpDst += dstPitch;
else
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
memcpy (lpDst, lpSrc, Src.Width << 1), lpDst += dstPitch,
memset (lpDst, 0, 512*2), lpDst += dstPitch;
else
if(Src.Width != 512)
for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch << 1)
DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
memset (lpDst, 0, 512*2), lpDst += dstPitch;
else
for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch << 1)
memcpy (lpDst, lpSrc, Src.Width << 1), lpDst += dstPitch,
memset (lpDst, 0, 512*2), lpDst += dstPitch;
}
else if(GUI.ScreenDepth == 32)
{
const unsigned int dstPitch = Dst.Pitch >> 2;
uint32 *lpDst = reinterpret_cast<uint32 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if(Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
memset (lpDst, 0, 512*4), lpDst += dstPitch;
else
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
SingleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
memset (lpDst, 0, 512*4), lpDst += dstPitch;
else
if(Src.Width != 512)
for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch << 1)
DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
memset (lpDst, 0, 512*4), lpDst += dstPitch;
else
for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch << 1)
SingleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
memset (lpDst, 0, 512*4), lpDst += dstPitch;
}
}
void RenderSimple2X( SSurface Src, SSurface Dst, RECT *rect)
{
// just copy if it's high res in both dimensions
if(Src.Height > SNES_HEIGHT_EXTENDED && Src.Width == 512)
{RenderPlain (Src, Dst, rect); return;}
uint16 *lpSrc;
unsigned int H;
SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 2);
const uint32 srcHeight = (rect->bottom - rect->top)/2;
const unsigned int srcPitch = Src.Pitch >> 1;
lpSrc = reinterpret_cast<uint16 *>(Src.Surface);
if(GUI.ScreenDepth == 16)
{
const unsigned int dstPitch = Dst.Pitch >> 1;
uint16 *lpDst = reinterpret_cast<uint16 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if (Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
memcpy (lpDst, lpSrc, Src.Width << 1), lpDst += dstPitch,
memcpy (lpDst, lpSrc, Src.Width << 1), lpDst += dstPitch;
else
for (H = 0; H < Src.Height; H++, lpSrc += srcPitch)
DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
}
else if(GUI.ScreenDepth == 32)
{
const unsigned int dstPitch = Dst.Pitch >> 2;
uint32 *lpDst = reinterpret_cast<uint32 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if (Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
SingleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
SingleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < Src.Height; H++, lpSrc += srcPitch)
DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
}
}
void RenderSuperEagle (SSurface Src, SSurface Dst, RECT *rect)
{
if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{RenderSimple2X (Src, Dst, rect); return;}
unsigned char *lpSrc, *lpDst;
SetRect(rect, Src.Width, Src.Height, 2);
lpSrc = Src.Surface;
lpDst = Dst.Surface;
lpDst += rect->top * Dst.Pitch + rect->left * 2;
SuperEagle (lpSrc, Src.Pitch,
lpDst, Dst.Pitch, Src.Width, Src.Height);
if (snes9x_clear_change_log)
snes9x_clear_change_log--;
}
void Render2xSaI (SSurface Src, SSurface Dst, RECT *rect)
{
unsigned char *lpSrc, *lpDst;
// If Snes9x is rendering anything in HiRes, then just copy, don't interpolate
if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{
RenderSimple2X (Src, Dst, rect);
return;
}
SetRect(rect, Src.Width, Src.Height, 2);
lpSrc = Src.Surface;
lpDst = Dst.Surface;
lpDst += rect->top * Dst.Pitch + rect->left * 2;
_2xSaI (lpSrc, Src.Pitch,
lpDst, Dst.Pitch, Src.Width, Src.Height);
if (snes9x_clear_change_log)
snes9x_clear_change_log--;
}
void RenderSuper2xSaI (SSurface Src, SSurface Dst, RECT *rect)
{
if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{RenderSimple2X (Src, Dst, rect); return;}
unsigned char *lpSrc, *lpDst;
SetRect(rect, Src.Width, Src.Height, 2);
lpSrc = Src.Surface;
lpDst = Dst.Surface;
lpDst += rect->top * Dst.Pitch + rect->left * 2;
Super2xSaI (lpSrc, Src.Pitch,
lpDst, Dst.Pitch, Src.Width, Src.Height);
if (snes9x_clear_change_log)
snes9x_clear_change_log--;
}
void RenderTVMode ( SSurface Src, SSurface Dst, RECT *rect)
{
// XXX: this filter's hi-res support for double-height modes is NYI
if (Src.Height > SNES_HEIGHT_EXTENDED)
{
snes9x_clear_change_log = GUI.NumFlipFrames;
RenderSimple2X (Src, Dst, rect);
return;
}
uint8 *nextLine, *finish;
uint32 colorMask = ~(RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 16));
uint32 lowPixelMask = RGB_LOW_BITS_MASK;
uint8 *srcPtr = Src.Surface;
uint8 *dstPtr = Dst.Surface;
uint32 srcPitch = Src.Pitch;
uint32 dstPitch = Dst.Pitch;
int width = Src.Width;
int height = Src.Height;
uint8 *deltaPtr = ChangeLog [GUI.FlipCounter % GUI.NumFlipFrames];
SetRect(rect, 256, height, 2);
dstPtr += rect->top * Dst.Pitch + rect->left * 2;
nextLine = dstPtr + dstPitch;
if (width == 256)
{
do
{
uint32 *bP = (uint32 *) srcPtr;
uint32 *xP = (uint32 *) deltaPtr;
uint32 *dP = (uint32 *) dstPtr;
uint32 *nL = (uint32 *) nextLine;
uint32 currentPixel;
uint32 nextPixel;
uint32 currentDelta;
uint32 nextDelta;
finish = (uint8 *) bP + ((width + 2) << 1);
nextPixel = *bP++;
nextDelta = *xP++;
do
{
currentPixel = nextPixel;
currentDelta = nextDelta;
nextPixel = *bP++;
nextDelta = *xP++;
if (snes9x_clear_change_log ||
nextPixel != nextDelta || currentPixel != currentDelta)
{
uint32 colorA, colorB, product, darkened;
*(xP - 2) = currentPixel;
#ifdef LSB_FIRST
colorA = currentPixel & 0xffff;
colorB = (currentPixel & 0xffff0000) >> 16;
#else
colorA = (currentPixel & 0xffff0000) >> 16;
colorB = currentPixel & 0xffff;
#endif
*(dP) = product = TWO_PIX(colorA, (((colorA & colorMask) >> 1) +
((colorB & colorMask) >> 1) +
(colorA & colorB & lowPixelMask)));
darkened = (product = ((product & colorMask) >> 1));
darkened += (product = ((product & colorMask) >> 1));
darkened += (product & colorMask) >> 1;
*(nL) = darkened;
#ifdef LSB_FIRST
colorA = nextPixel & 0xffff;
#else
colorA = (nextPixel & 0xffff0000) >> 16;
#endif
*(dP + 1) = product = TWO_PIX(colorB, (((colorA & colorMask) >> 1) +
((colorB & colorMask) >> 1) +
(colorA & colorB & lowPixelMask)));
darkened = (product = ((product & colorMask) >> 1));
darkened += (product = ((product & colorMask) >> 1));
darkened += (product & colorMask) >> 1;
*(nL + 1) = darkened;
}
dP += 2;
nL += 2;
} while ((uint8 *) bP < finish);
deltaPtr += srcPitch;
srcPtr += srcPitch;
dstPtr += dstPitch * 2;
nextLine += dstPitch * 2;
}
while (--height);
if (snes9x_clear_change_log)
snes9x_clear_change_log--;
}
else
{
snes9x_clear_change_log = GUI.NumFlipFrames;
do
{
uint32 *bP = (uint32 *) srcPtr;
uint32 *xP = (uint32 *) deltaPtr;
uint32 *dP = (uint32 *) dstPtr;
uint32 *nL = (uint32 *) nextLine;
uint32 currentPixel;
uint32 nextPixel;
uint32 currentDelta;
uint32 nextDelta;
finish = (uint8 *) bP + ((width + 2) << 1);
nextPixel = *bP++;
nextDelta = *xP++;
do
{
currentPixel = nextPixel;
currentDelta = nextDelta;
nextPixel = *bP++;
nextDelta = *xP++;
if (snes9x_clear_change_log ||
nextPixel != nextDelta || currentPixel != currentDelta)
{
uint32 colorA, colorB, product, darkened;
*(xP - 1) = currentPixel;
#ifdef LSB_FIRST
colorA = currentPixel & 0xffff;
colorB = (currentPixel & 0xffff0000) >> 16;
#else
colorA = (currentPixel & 0xffff0000) >> 16;
colorB = currentPixel & 0xffff;
#endif
product = TWO_PIX(colorA, (((colorA & colorMask) >> 1) +
((colorB & colorMask) >> 1) +
(colorA & colorB & lowPixelMask)));
*(dP) = currentPixel;
darkened = (product = ((product & colorMask) >> 1));
darkened += (product = ((product & colorMask) >> 1));
darkened += (product & colorMask) >> 1;
*(nL) = darkened;
}
dP += 1;
nL += 1;
} while ((uint8 *) bP < finish);
deltaPtr += srcPitch;
srcPtr += srcPitch;
dstPtr += dstPitch * 2;
nextLine += dstPitch * 2;
}
while (--height);
}
}
void RenderSimple3X( SSurface Src, SSurface Dst, RECT *rect)
{
uint16 *lpSrc;
unsigned int H;
SetRect(rect, 256, 239, 3);
const uint32 srcHeight = (rect->bottom - rect->top)/3;
const unsigned int srcPitch = Src.Pitch >> 1;
lpSrc = reinterpret_cast<uint16 *>(Src.Surface);
if(GUI.ScreenDepth == 16)
{
const unsigned int dstPitch = Dst.Pitch >> 1;
uint16 *lpDst = reinterpret_cast<uint16 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if (Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
if(Src.Width != 512)
for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch)
TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, lpSrc += srcPitch,
TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch)
ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, lpSrc += srcPitch,
ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
}
else if(GUI.ScreenDepth == 32)
{
const unsigned int dstPitch = Dst.Pitch >> 2;
uint32 *lpDst = reinterpret_cast<uint32 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if (Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
if(Src.Width != 512)
for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch)
TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, lpSrc += srcPitch,
TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch)
ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, lpSrc += srcPitch,
ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
}
}
#ifdef LSB_FIRST
#pragma pack(push, 1)
struct uint48
{
uint32 L;
uint16 R;
inline uint48(uint32 left, uint16 right)
{
L = left;
R = right;
}
};
struct uint96
{
uint64 L;
uint32 R;
inline uint96(uint64 left, uint32 right)
{
L = left;
R = right;
}
};
#pragma pack(pop)
#else
#error NYI for !LSB_FIRST
#endif
// assert that sizeof(uint48) == 6 bytes
//static int compiler_error_sizeof_uint48_notequal_6 [(sizeof(uint48)== 6)?1:0] = {0};
//static int compiler_error_sizeof_uint96_notequal_12 [(sizeof(uint96)==12)?1:0] = {0};
// shared EPX-type loop macros
// All of these parameters will be constant values,
// so I hope the compiler is smart enough to optimize away "if(0) ..."
#define DrawRows(scale,diags) \
{ \
h = srcHeight - 1; \
DoRow(0,1,scale,diags); \
for (h = srcHeight - 2; h; h--) \
DoRow(1,1,scale,diags); \
DoRow(1,0,scale,diags); \
}
#define DoRow(topValid,botValid,scale,diags) \
{ \
w = srcWidth - 1; \
InitLine(topValid,botValid,scale,diags); \
DrawPix(0,topValid,0,botValid); \
for (w = srcWidth - 2; w; w--) \
{ \
NextPixel(topValid,botValid,1,diags); \
DrawPix(topValid,topValid,botValid,botValid); \
} \
NextPixel(topValid,botValid,0,diags); \
DrawPix(topValid,0,botValid,0); \
srcPtr += srcPitch; \
dstPtr += dstPitch * scale; \
}
#define InitLine(topValid, botValid, scale, diags) \
{ \
if(topValid) uP = (uint16 *) (srcPtr - srcPitch); \
if(botValid) lP = (uint16 *) (srcPtr + srcPitch); \
sP = (uint16 *) srcPtr; \
dP1 = (destType *) dstPtr; \
dP2 = (destType *) (dstPtr + dstPitch); \
if(scale>=3) dP3 = (destType *) (dstPtr + (dstPitch<<1)); \
if(topValid) colorD = *uP++; \
if(botValid) colorB = *lP++; \
colorX = *sP++; \
colorC = *sP; \
if(diags) if(topValid) colorH = *uP; \
if(diags) if(botValid) colorG = *lP; \
}
#define NextPixel(topValid, botValid, rightValid, diags) \
{ \
colorA = colorX; \
colorX = colorC; \
if(rightValid) colorC = *++sP; \
if(diags) { \
if(botValid){ \
colorF = colorB; \
colorB = colorG; \
if(rightValid) colorG = *++lP; \
} \
if(topValid){ \
colorE = colorD; \
colorD = colorH; \
if(rightValid) colorH = *++uP; \
} \
} else { \
if(botValid) colorB = *lP++; \
if(topValid) colorD = *uP++; \
} \
}
#define DrawInit(scale,uintDest) \
uint8 *srcPtr = Src.Surface, *dstPtr = Dst.Surface; \
const uint32 srcPitch = Src.Pitch, dstPitch = Dst.Pitch; \
SetRect(rect, 256, Src.Height, scale); \
dstPtr += rect->top * Dst.Pitch + rect->left * 2; \
const uint32 srcHeight = (rect->bottom - rect->top)/scale; \
const uint32 srcWidth = (rect->right - rect->left)/scale; \
uint16 colorX, colorA, colorB, colorC, colorD, colorE=0, colorF=0, colorG=0, colorH=0; \
uint16 *sP, *uP, *lP; \
typedef uintDest destType; \
destType *dP1, *dP2, *dP3=0; \
int w, h;
// code for rendering the image enlarged 2X with EPX
void RenderEPXA (SSurface Src, SSurface Dst, RECT *rect)
{
if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{RenderSimple2X (Src, Dst, rect); return;}
// all we have to do now is define what to do at each pixel
// (it's a 2x filter, so for each pixel we draw 2x2 = 4 pixels)
// based on the current pixel and the surrounding 4 pixels
// D
// A X C
// B
#define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \
{ /* on10 on11 */ \
if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \
&& (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX))) \
{ \
*dP1++ = _TWO_PIX((on00 && colorD == colorA) ? colorD : colorX, /* we set 2 pixels at a time (the pointer size is the size of (scale=2) pixels)*/\
(on01 && colorC == colorD) ? colorC : colorX); \
*dP2++ = _TWO_PIX((on10 && colorA == colorB) ? colorA : colorX, /* also set the 2 pixels below those*/\
(on11 && colorB == colorC) ? colorB : colorX); \
} else { \
*dP1++ = _TWO_PIX(colorX, colorX); \
*dP2++ = _TWO_PIX(colorX, colorX); \
} \
}
// this renderer supports 32-bit or 16-bit rendering (see GetFilter32BitSupport())
// so we must switch based on depth to handle both modes.
// we could choose to only support 16-bit, but that would impose a performance penalty
// for color conversion from the increasingly-commonly-used 32-bit depth
if(GUI.ScreenDepth == 32)
{
#define _TWO_PIX TWO_PIX_32 // define _TWO_PIX to combine two 32-bit pixels at a time
DrawInit(2,uint64); // initialize with the scale and an int as big as 2 pixels
DrawRows(2,0); // scale is 2x, and diags (8 surrounding pixels) is off since we only need 4 surrounding
#undef _TWO_PIX
}
else // 16-bit, same deal but with smaller pointer size and different 2-pixel combiner
{
#define _TWO_PIX TWO_PIX // define _TWO_PIX to combine two 16-bit pixels at a time
DrawInit(2,uint32); // initialize with the scale and an int as big as 2 pixels
DrawRows(2,0); // scale is 2x, and diags (8 surrounding pixels) is off since we only need 4 surrounding
#undef _TWO_PIX
}
#undef DrawPix
}
// code for improved 2X EPX, which tends to do better with diagonal edges than regular EPX
void RenderEPXB (SSurface Src, SSurface Dst, RECT *rect)
{
if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{RenderSimple2X (Src, Dst, rect); return;}
// E D H
// A X C
// F B G
#define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \
{ /* on10 on11 */ \
if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \
&& (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX)) \
&& ((!on00||!on01||!on10|!on11) || \
((colorX == colorA) || (colorX == colorB) || (colorX == colorC) || (colorX == colorD) || /* diagonal */ \
(((colorE != colorG) || (colorX == colorF) || (colorX == colorH)) && /* edge */ \
((colorF != colorH) || (colorX == colorE) || (colorX == colorG)))))) /* smoothing */ \
{ \
*dP1++ = _TWO_PIX((on00 && colorD == colorA && (colorX != colorE || colorX != colorG || colorD != colorH || colorA != colorF)) ? colorD : colorX, \
(on01 && colorC == colorD && (colorX != colorH || colorX != colorF || colorC != colorG || colorD != colorE)) ? colorC : colorX); \
*dP2++ = _TWO_PIX((on10 && colorA == colorB && (colorX != colorF || colorX != colorH || colorA != colorE || colorB != colorG)) ? colorA : colorX, \
(on11 && colorB == colorC && (colorX != colorG || colorX != colorE || colorB != colorF || colorC != colorH)) ? colorB : colorX); \
} else { \
*dP1++ = _TWO_PIX(colorX, colorX); \
*dP2++ = _TWO_PIX(colorX, colorX); \
} \
}
// again, this supports 32-bit or 16-bit rendering
if(GUI.ScreenDepth == 32)
{
#define _TWO_PIX TWO_PIX_32
DrawInit(2,uint64);
DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels
#undef _TWO_PIX
}
else
{
#define _TWO_PIX TWO_PIX
DrawInit(2,uint32);
DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels
#undef _TWO_PIX
}
#undef DrawPix
}
void RenderEPX3 (SSurface Src, SSurface Dst, RECT *rect)
{
if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{RenderSimple3X (Src, Dst, rect); return;}
// E D H
// A X C
// F B G
#define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \
{ /* on10 on11 */ \
if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \
&& (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX))) \
{ \
const bool XnE = colorX != colorE; \
const bool XnF = colorX != colorF; \
const bool XnG = colorX != colorG; \
const bool XnH = colorX != colorH; \
const bool DA = on00 && colorD == colorA && (XnE || XnG || colorD != colorH || colorA != colorF); \
const bool AB = on10 && colorA == colorB && (XnF || XnH || colorA != colorE || colorB != colorG); \
const bool BC = on11 && colorB == colorC && (XnG || XnE || colorB != colorF || colorC != colorH); \
const bool CD = on01 && colorC == colorD && (XnH || XnF || colorC != colorG || colorD != colorE); \
if (!on00||!on01||!on10||!on11 || ((colorA != colorC) && (colorB != colorD) && \
((colorX == colorA) || (colorX==colorB) || (colorX==colorC) || (colorX==colorD) || (colorX==colorE) || (colorX==colorF) || (colorX==colorG) || (colorX==colorH)))) \
{ \
*dP1++ = _THREE_PIX(on00 && DA ? colorA : colorX, on00&&on01 && ((CD && XnE) || (DA && XnH)) ? colorD : colorX, on01 && CD ? colorC : colorX); \
*dP2++ = _THREE_PIX(on00&&on10 && ((DA && XnF) || (AB && XnE)) ? colorA : colorX, colorX, on01&&on11 && ((BC && XnH) || (CD && XnG)) ? colorC : colorX); \
*dP3++ = _THREE_PIX(on10 && AB ? colorA : colorX, on10&&on11 && ((AB && XnG) || (BC && XnF)) ? colorB : colorX, on11 && BC ? colorC : colorX); \
} else { \
*dP1++ = _THREE_PIX(on00 && DA && (colorX!=colorB&&colorX!=colorC) ? colorA : colorX, colorX, on01 && CD && (colorX!=colorA&&colorX!=colorB) ? colorC : colorX); \
*dP2++ = _THREE_PIX(colorX,colorX,colorX); \
*dP3++ = _THREE_PIX(on10 && AB && (colorX!=colorC&&colorX!=colorD) ? colorA : colorX, colorX, on11 && BC && (colorX!=colorD&&colorX!=colorA) ? colorC : colorX); \
} \
} else { \
*dP1++ = _THREE_PIX(colorX, colorX, colorX); \
*dP2++ = _THREE_PIX(colorX, colorX, colorX); \
*dP3++ = _THREE_PIX(colorX, colorX, colorX); \
} \
}
if(GUI.ScreenDepth == 32)
{
#define _THREE_PIX THREE_PIX_32
DrawInit(3,uint96); // initialize with the scale and an int as big as 3 pixels
DrawRows(3,1);
#undef _THREE_PIX
}
else
{
#define _THREE_PIX THREE_PIX
DrawInit(3,uint48);
DrawRows(3,1);
#undef _THREE_PIX
}
#undef DrawPix
}
#define Interp44(c1, c2, c3, c4) \
((((((c1) & Mask_2) * 5 + ((c2) & Mask_2) + ((c3) & Mask_2) + ((c4) & Mask_2)) >> 3) & Mask_2) + \
(((((c1) & Mask13) * 5 + ((c2) & Mask13) + ((c3) & Mask13) + ((c4) & Mask13)) >> 3) & Mask13))
#define Interp11(c1, c2) \
((((c1) == (c2)) ? (c1) : \
(((((((c1) & Mask_2) * 3) + ((c2) & Mask_2) * 5) >> 3) & Mask_2) + \
((((((c1) & Mask13) * 3) + ((c2) & Mask13) * 5) >> 3) & Mask13))))
// EPX3 scaled down to 2X
void RenderEPXC (SSurface Src, SSurface Dst, RECT *rect)
{
if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{RenderSimple2X (Src, Dst, rect); return;}
// E D H
// A X C
// F B G
#define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \
{ /* on10 on11 */ \
if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \
&& (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX))) \
{ \
const bool XnE = colorX != colorE; \
const bool XnF = colorX != colorF; \
const bool XnG = colorX != colorG; \
const bool XnH = colorX != colorH; \
const bool DA = on00 && colorD == colorA && (XnE || XnG || colorD != colorH || colorA != colorF); \
const bool AB = on10 && colorA == colorB && (XnF || XnH || colorA != colorE || colorB != colorG); \
const bool BC = on11 && colorB == colorC && (XnG || XnE || colorB != colorF || colorC != colorH); \
const bool CD = on01 && colorC == colorD && (XnH || XnF || colorC != colorG || colorD != colorE); \
if (!on00||!on01||!on10||!on11 || ((colorA != colorC) && (colorB != colorD) && \
((colorX == colorA) || (colorX==colorB) || (colorX==colorC) || (colorX==colorD) || (colorX==colorE) || (colorX==colorF) || (colorX==colorG) || (colorX==colorH)))) \
{ \
const uint16 colorAA = on00&&on10 && ((DA && XnF) || (AB && XnE)) ? colorA : colorX; \
const uint16 colorBB = on10&&on11 && ((AB && XnG) || (BC && XnF)) ? colorB : colorX; \
const uint16 colorCC = on01&&on11 && ((BC && XnH) || (CD && XnG)) ? colorC : colorX; \
const uint16 colorDD = on00&&on01 && ((CD && XnE) || (DA && XnH)) ? colorD : colorX; \
*dP1++ = _TWO_PIX(Interp44(on00 && DA ? colorA : colorX, colorDD, colorAA, colorX), Interp44(on01 && CD ? colorC : colorX, colorBB, colorCC, colorX)); \
*dP2++ = _TWO_PIX(Interp44(on10 && AB ? colorA : colorX, colorAA, colorBB, colorX), Interp44(on11 && BC ? colorC : colorX, colorCC, colorDD, colorX)); \
} else { \
*dP1++ = _TWO_PIX(Interp01(colorX, on00 && DA && (colorX!=colorB&&colorX!=colorC) ? colorA : colorX), Interp01(colorX, on01 && CD && (colorX!=colorA&&colorX!=colorB) ? colorC : colorX)); \
*dP2++ = _TWO_PIX(Interp01(colorX, on10 && AB && (colorX!=colorC&&colorX!=colorD) ? colorA : colorX), Interp01(colorX, on11 && BC && (colorX!=colorD&&colorX!=colorA) ? colorC : colorX)); \
} \
} else { \
*dP1++ = _TWO_PIX(colorX, colorX); \
*dP2++ = _TWO_PIX(colorX, colorX); \
} \
}
if(GUI.ScreenDepth == 32)
{
#define _TWO_PIX TWO_PIX_32
DrawInit(2,uint64);
DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels
#undef _TWO_PIX
}
else
{
#define _TWO_PIX TWO_PIX
DrawInit(2,uint32);
DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels
#undef _TWO_PIX
}
#undef DrawPix
}
void RenderTVMode3X (SSurface Src, SSurface Dst, RECT *rect)
{
if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{RenderSimple3X (Src, Dst, rect); return;}
// E D H
// A X C
// F B G
#define Interp05TQ(c1,c2) ThreeQuarters(Interp05(c1,c2))
#define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \
{ /* on10 on11 */ \
if(!on00) {colorE = 0; if(!on01) {colorD = 0; colorX = Halve(colorX); }} \
if(!on01) {colorH = 0; if(!on11) {colorC = 0; colorX = Halve(colorX); }} \
if(!on10) {colorF = 0; if(!on00) {colorA = 0; colorX = Halve(colorX); }} \
if(!on11) {colorG = 0; if(!on10) {colorB = 0; colorX = Halve(colorX); }} \
if ((colorA == colorC) && (colorB == colorD) && (colorX == colorA) && (colorF == colorG) && (colorE == colorH) && (colorX == colorF) && (colorF == colorE)) \
{ \
const uint16 colorX2 = ThreeQuarters(colorX); \
*dP1++ = _THREE_PIX(colorX, colorX, colorX); \
*dP2++ = _THREE_PIX(colorX, colorX, colorX); \
*dP3++ = _THREE_PIX(colorX2, colorX2, colorX2); \
} \
else \
{ \
*dP1++ = _THREE_PIX(Interp05((colorE&Mask_1)|(colorD&(Mask_3|Mask_2)), (colorA&Mask_1)|(colorX&(Mask_3|Mask_2))), \
Interp05(colorD,colorX), \
Interp05((colorD&(Mask_2|Mask_1))|(colorH&Mask_3), (colorX&(Mask_2|Mask_1))|(colorC&Mask_3))); \
*dP2++ = _THREE_PIX(((colorA&Mask_1)|(colorX&(Mask_3|Mask_2))), \
colorX, \
((colorX&(Mask_2|Mask_1))|(colorC&Mask_3))); \
*dP3++ = _THREE_PIX(Interp05TQ((colorA&Mask_1)|(colorX&(Mask_3|Mask_2)), (colorF&Mask_1)|(colorB&(Mask_3|Mask_2))), \
Interp05TQ(colorB,colorX), \
Interp05TQ((colorX&(Mask_2|Mask_1))|(colorC&Mask_3), (colorB&(Mask_2|Mask_1))|(colorG&Mask_3))); \
} \
}
if(GUI.ScreenDepth == 32)
{
#define _THREE_PIX THREE_PIX_32
DrawInit(3,uint96);
DrawRows(3,1);
#undef _THREE_PIX
}
else
{
#define _THREE_PIX THREE_PIX
DrawInit(3,uint48);
DrawRows(3,1);
#undef _THREE_PIX
}
#undef DrawPix
}
void RenderDotMatrix3X (SSurface Src, SSurface Dst, RECT *rect)
{
if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{RenderSimple3X (Src, Dst, rect); return;}
#define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \
{ /* on10 on11 */ \
const uint16 colorXA = COLOR_ADD(colorX,colorX); \
const uint16 colorXS = COLOR_SUB(colorXA,colorX); \
const uint16 colorX2 = COLOR_SUB(colorX,colorXS); \
*dP1++ = _THREE_PIX(colorX2, colorX, colorX2); \
*dP2++ = _THREE_PIX(colorX, colorXA, colorX); \
*dP3++ = _THREE_PIX(colorX2, colorX, colorX2); \
}
if(GUI.ScreenDepth == 32)
{
#define _THREE_PIX THREE_PIX_32
DrawInit(3,uint96);
DrawRows(3,0);
#undef _THREE_PIX
}
else
{
#define _THREE_PIX THREE_PIX
DrawInit(3,uint48);
DrawRows(3,0);
#undef _THREE_PIX
}
#undef DrawPix
}
#undef DoRow
#undef InitLine
#undef NextPixel
#undef DrawRows
#undef DrawInit
////////////////////////////////////////////////////////////////////////////////
// HQ2X stuff follows)
////////////////////////////////////////////////////////////////////////////////
#define Ymask 0xFF0000
#define Umask 0x00FF00
#define Vmask 0x0000FF
#define trY 0x300000
#define trU 0x000700
#define trV 0x000006
#define Interp02(c1, c2, c3) \
((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 2) & Mask_2) + \
(((((c1) & Mask13) * 2 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 2) & Mask13))
#define Interp06(c1, c2, c3) \
((((((c1) & Mask_2) * 5 + ((c2) & Mask_2) * 2 + ((c3) & Mask_2) ) >> 3) & Mask_2) + \
(((((c1) & Mask13) * 5 + ((c2) & Mask13) * 2 + ((c3) & Mask13) ) >> 3) & Mask13))
#define Interp07(c1, c2, c3) \
((((((c1) & Mask_2) * 6 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 3) & Mask_2) + \
(((((c1) & Mask13) * 6 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 3) & Mask13))
#define Interp09(c1, c2, c3) \
((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) * 3 + ((c3) & Mask_2) * 3) >> 3) & Mask_2) + \
(((((c1) & Mask13) * 2 + ((c2) & Mask13) * 3 + ((c3) & Mask13) * 3) >> 3) & Mask13))
#define Interp10(c1, c2, c3) \
((((((c1) & Mask_2) * 14 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 4) & Mask_2) + \
(((((c1) & Mask13) * 14 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 4) & Mask13))
#define PIXEL00_0 *(dp) = w5
#define PIXEL00_10 *(dp) = Interp01(w5, w1)
#define PIXEL00_11 *(dp) = Interp01(w5, w4)
#define PIXEL00_12 *(dp) = Interp01(w5, w2)
#define PIXEL00_20 *(dp) = Interp02(w5, w4, w2)
#define PIXEL00_21 *(dp) = Interp02(w5, w1, w2)
#define PIXEL00_22 *(dp) = Interp02(w5, w1, w4)
#define PIXEL00_60 *(dp) = Interp06(w5, w2, w4)
#define PIXEL00_61 *(dp) = Interp06(w5, w4, w2)
#define PIXEL00_70 *(dp) = Interp07(w5, w4, w2)
#define PIXEL00_90 *(dp) = Interp09(w5, w4, w2)
#define PIXEL00_100 *(dp) = Interp10(w5, w4, w2)
#define PIXEL01_0 *(dp + 1) = w5
#define PIXEL01_10 *(dp + 1) = Interp01(w5, w3)
#define PIXEL01_11 *(dp + 1) = Interp01(w5, w2)
#define PIXEL01_12 *(dp + 1) = Interp01(w5, w6)
#define PIXEL01_20 *(dp + 1) = Interp02(w5, w2, w6)
#define PIXEL01_21 *(dp + 1) = Interp02(w5, w3, w6)
#define PIXEL01_22 *(dp + 1) = Interp02(w5, w3, w2)
#define PIXEL01_60 *(dp + 1) = Interp06(w5, w6, w2)
#define PIXEL01_61 *(dp + 1) = Interp06(w5, w2, w6)
#define PIXEL01_70 *(dp + 1) = Interp07(w5, w2, w6)
#define PIXEL01_90 *(dp + 1) = Interp09(w5, w2, w6)
#define PIXEL01_100 *(dp + 1) = Interp10(w5, w2, w6)
#define PIXEL10_0 *(dp + dst1line) = w5
#define PIXEL10_10 *(dp + dst1line) = Interp01(w5, w7)
#define PIXEL10_11 *(dp + dst1line) = Interp01(w5, w8)
#define PIXEL10_12 *(dp + dst1line) = Interp01(w5, w4)
#define PIXEL10_20 *(dp + dst1line) = Interp02(w5, w8, w4)
#define PIXEL10_21 *(dp + dst1line) = Interp02(w5, w7, w4)
#define PIXEL10_22 *(dp + dst1line) = Interp02(w5, w7, w8)
#define PIXEL10_60 *(dp + dst1line) = Interp06(w5, w4, w8)
#define PIXEL10_61 *(dp + dst1line) = Interp06(w5, w8, w4)
#define PIXEL10_70 *(dp + dst1line) = Interp07(w5, w8, w4)
#define PIXEL10_90 *(dp + dst1line) = Interp09(w5, w8, w4)
#define PIXEL10_100 *(dp + dst1line) = Interp10(w5, w8, w4)
#define PIXEL11_0 *(dp + dst1line + 1) = w5
#define PIXEL11_10 *(dp + dst1line + 1) = Interp01(w5, w9)
#define PIXEL11_11 *(dp + dst1line + 1) = Interp01(w5, w6)
#define PIXEL11_12 *(dp + dst1line + 1) = Interp01(w5, w8)
#define PIXEL11_20 *(dp + dst1line + 1) = Interp02(w5, w6, w8)
#define PIXEL11_21 *(dp + dst1line + 1) = Interp02(w5, w9, w8)
#define PIXEL11_22 *(dp + dst1line + 1) = Interp02(w5, w9, w6)
#define PIXEL11_60 *(dp + dst1line + 1) = Interp06(w5, w8, w6)
#define PIXEL11_61 *(dp + dst1line + 1) = Interp06(w5, w6, w8)
#define PIXEL11_70 *(dp + dst1line + 1) = Interp07(w5, w6, w8)
#define PIXEL11_90 *(dp + dst1line + 1) = Interp09(w5, w6, w8)
#define PIXEL11_100 *(dp + dst1line + 1) = Interp10(w5, w6, w8)
#define Absolute(c) \
(!(c & (1 << 31)) ? c : (~c + 1))
static inline bool Diff(int c1, int c2)
{
int c1y = (c1 & Ymask) - (c2 & Ymask);
if (Absolute(c1y) > trY) return true;
int c1u = (c1 & Umask) - (c2 & Umask);
if (Absolute(c1u) > trU) return true;
int c1v = (c1 & Vmask) - (c2 & Vmask);
if (Absolute(c1v) > trV) return true;
return false;
}
void InitLUTsWin32(void)
{
int c, r, g, b, y, u, v;
for (c = 0 ; c < (1<<NUMBITS) ; c++)
{
#ifdef R5G6B5
b = (int)((c & 0x1F)) << 3;
g = (int)((c & 0x7E0)) >> 3;
r = (int)((c & 0xF800)) >> 8;
#else
b = (int)((c & 0x1F)) << 3;
g = (int)((c & 0x3E0)) >> 2;
r = (int)((c & 0x7C00)) >> 7;
#endif
RGBtoBright[c] = r+r+r + g+g+g + b+b;
y = (int)( 0.256788f*r + 0.504129f*g + 0.097906f*b + 0.5f) + 16;
u = (int)(-0.148223f*r - 0.290993f*g + 0.439216f*b + 0.5f) + 128;
v = (int)( 0.439216f*r - 0.367788f*g - 0.071427f*b + 0.5f) + 128;
RGBtoYUV[c] = (y << 16) + (u << 8) + v;
}
}
#define HQ2XCASES \
case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: PIXEL00_20; PIXEL01_20; PIXEL10_20; PIXEL11_20; break; \
case 2: case 34: case 130: case 162: PIXEL00_22; PIXEL01_21; PIXEL10_20; PIXEL11_20; break; \
case 16: case 17: case 48: case 49: PIXEL00_20; PIXEL01_22; PIXEL10_20; PIXEL11_21; break; \
case 64: case 65: case 68: case 69: PIXEL00_20; PIXEL01_20; PIXEL10_21; PIXEL11_22; break; \
case 8: case 12: case 136: case 140: PIXEL00_21; PIXEL01_20; PIXEL10_22; PIXEL11_20; break; \
case 3: case 35: case 131: case 163: PIXEL00_11; PIXEL01_21; PIXEL10_20; PIXEL11_20; break; \
case 6: case 38: case 134: case 166: PIXEL00_22; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \
case 20: case 21: case 52: case 53: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_21; break; \
case 144: case 145: case 176: case 177: PIXEL00_20; PIXEL01_22; PIXEL10_20; PIXEL11_12; break; \
case 192: case 193: case 196: case 197: PIXEL00_20; PIXEL01_20; PIXEL10_21; PIXEL11_11; break; \
case 96: case 97: case 100: case 101: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_22; break; \
case 40: case 44: case 168: case 172: PIXEL00_21; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \
case 9: case 13: case 137: case 141: PIXEL00_12; PIXEL01_20; PIXEL10_22; PIXEL11_20; break; \
case 18: case 50: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_20; PIXEL10_20; PIXEL11_21; break; \
case 80: case 81: PIXEL00_20; PIXEL01_22; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_20; break; \
case 72: case 76: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_20; PIXEL11_22; break; \
case 10: case 138: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_20; PIXEL01_21; PIXEL10_22; PIXEL11_20; break; \
case 66: PIXEL00_22; PIXEL01_21; PIXEL10_21; PIXEL11_22; break; \
case 24: PIXEL00_21; PIXEL01_22; PIXEL10_22; PIXEL11_21; break; \
case 7: case 39: case 135: PIXEL00_11; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \
case 148: case 149: case 180: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_12; break; \
case 224: case 228: case 225: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_11; break; \
case 41: case 169: case 45: PIXEL00_12; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \
case 22: case 54: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_20; PIXEL11_21; break; \
case 208: case 209: PIXEL00_20; PIXEL01_22; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 104: case 108: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \
case 11: case 139: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_22; PIXEL11_20; break; \
case 19: case 51: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_10; else PIXEL00_60, PIXEL01_90; PIXEL10_20; PIXEL11_21; break; \
case 146: case 178: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_20; break; \
case 84: case 85: PIXEL00_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_10; else PIXEL01_60, PIXEL11_90; PIXEL10_21; break; \
case 112: case 113: PIXEL00_20; PIXEL01_22; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_10; else PIXEL10_61, PIXEL11_90; break; \
case 200: case 204: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \
case 73: case 77: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_10; else PIXEL00_61, PIXEL10_90; PIXEL01_20; PIXEL11_22; break; \
case 42: case 170: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_21; PIXEL11_20; break; \
case 14: case 142: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_22; PIXEL11_20; break; \
case 67: PIXEL00_11; PIXEL01_21; PIXEL10_21; PIXEL11_22; break; \
case 70: PIXEL00_22; PIXEL01_12; PIXEL10_21; PIXEL11_22; break; \
case 28: PIXEL00_21; PIXEL01_11; PIXEL10_22; PIXEL11_21; break; \
case 152: PIXEL00_21; PIXEL01_22; PIXEL10_22; PIXEL11_12; break; \
case 194: PIXEL00_22; PIXEL01_21; PIXEL10_21; PIXEL11_11; break; \
case 98: PIXEL00_22; PIXEL01_21; PIXEL10_12; PIXEL11_22; break; \
case 56: PIXEL00_21; PIXEL01_22; PIXEL10_11; PIXEL11_21; break; \
case 25: PIXEL00_12; PIXEL01_22; PIXEL10_22; PIXEL11_21; break; \
case 26: case 31: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_21; break; \
case 82: case 214: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 88: case 248: PIXEL00_21; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 74: case 107: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \
case 27: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_22; PIXEL11_21; break; \
case 86: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; PIXEL11_10; break; \
case 216: PIXEL00_21; PIXEL01_22; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 106: PIXEL00_10; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \
case 30: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_21; break; \
case 210: PIXEL00_22; PIXEL01_10; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 120: PIXEL00_21; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \
case 75: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_10; PIXEL11_22; break; \
case 29: PIXEL00_12; PIXEL01_11; PIXEL10_22; PIXEL11_21; break; \
case 198: PIXEL00_22; PIXEL01_12; PIXEL10_21; PIXEL11_11; break; \
case 184: PIXEL00_21; PIXEL01_22; PIXEL10_11; PIXEL11_12; break; \
case 99: PIXEL00_11; PIXEL01_21; PIXEL10_12; PIXEL11_22; break; \
case 57: PIXEL00_12; PIXEL01_22; PIXEL10_11; PIXEL11_21; break; \
case 71: PIXEL00_11; PIXEL01_12; PIXEL10_21; PIXEL11_22; break; \
case 156: PIXEL00_21; PIXEL01_11; PIXEL10_22; PIXEL11_12; break; \
case 226: PIXEL00_22; PIXEL01_21; PIXEL10_12; PIXEL11_11; break; \
case 60: PIXEL00_21; PIXEL01_11; PIXEL10_11; PIXEL11_21; break; \
case 195: PIXEL00_11; PIXEL01_21; PIXEL10_21; PIXEL11_11; break; \
case 102: PIXEL00_22; PIXEL01_12; PIXEL10_12; PIXEL11_22; break; \
case 153: PIXEL00_12; PIXEL01_22; PIXEL10_22; PIXEL11_12; break; \
case 58: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_21; break; \
case 83: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 92: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 202: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \
case 78: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_22; break; \
case 154: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_22; PIXEL11_12; break; \
case 114: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 89: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 90: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 55: case 23: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_0; else PIXEL00_60, PIXEL01_90; PIXEL10_20; PIXEL11_21; break; \
case 182: case 150: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_20; break; \
case 213: case 212: PIXEL00_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_0; else PIXEL01_60, PIXEL11_90; PIXEL10_21; break; \
case 241: case 240: PIXEL00_20; PIXEL01_22; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_0; else PIXEL10_61, PIXEL11_90; break; \
case 236: case 232: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \
case 109: case 105: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_0; else PIXEL00_61, PIXEL10_90; PIXEL01_20; PIXEL11_22; break; \
case 171: case 43: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_21; PIXEL11_20; break; \
case 143: case 15: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_22; PIXEL11_20; break; \
case 124: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \
case 203: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_10; PIXEL11_11; break; \
case 62: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_11; PIXEL11_21; break; \
case 211: PIXEL00_11; PIXEL01_10; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 118: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_12; PIXEL11_10; break; \
case 217: PIXEL00_12; PIXEL01_22; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 110: PIXEL00_10; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \
case 155: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_22; PIXEL11_12; break; \
case 188: PIXEL00_21; PIXEL01_11; PIXEL10_11; PIXEL11_12; break; \
case 185: PIXEL00_12; PIXEL01_22; PIXEL10_11; PIXEL11_12; break; \
case 61: PIXEL00_12; PIXEL01_11; PIXEL10_11; PIXEL11_21; break; \
case 157: PIXEL00_12; PIXEL01_11; PIXEL10_22; PIXEL11_12; break; \
case 103: PIXEL00_11; PIXEL01_12; PIXEL10_12; PIXEL11_22; break; \
case 227: PIXEL00_11; PIXEL01_21; PIXEL10_12; PIXEL11_11; break; \
case 230: PIXEL00_22; PIXEL01_12; PIXEL10_12; PIXEL11_11; break; \
case 199: PIXEL00_11; PIXEL01_12; PIXEL10_21; PIXEL11_11; break; \
case 220: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 158: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_12; break; \
case 234: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_11; break; \
case 242: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 59: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_21; break; \
case 121: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 87: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 79: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_22; break; \
case 122: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 94: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 218: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 91: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 229: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_11; break; \
case 167: PIXEL00_11; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \
case 173: PIXEL00_12; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \
case 181: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_12; break; \
case 186: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_12; break; \
case 115: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 93: PIXEL00_12; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 206: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \
case 205: case 201: PIXEL00_12; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \
case 174: case 46: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; PIXEL10_11; PIXEL11_20; break; \
case 179: case 147: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_20; PIXEL11_12; break; \
case 117: case 116: PIXEL00_20; PIXEL01_11; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \
case 189: PIXEL00_12; PIXEL01_11; PIXEL10_11; PIXEL11_12; break; \
case 231: PIXEL00_11; PIXEL01_12; PIXEL10_12; PIXEL11_11; break; \
case 126: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \
case 219: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 125: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_0; else PIXEL00_61, PIXEL10_90; PIXEL01_11; PIXEL11_10; break; \
case 221: PIXEL00_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_0; else PIXEL01_60, PIXEL11_90; PIXEL10_10; break; \
case 207: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_10; PIXEL11_11; break; \
case 238: PIXEL00_10; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \
case 190: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_11; break; \
case 187: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_10; PIXEL11_12; break; \
case 243: PIXEL00_11; PIXEL01_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_0; else PIXEL10_61, PIXEL11_90; break; \
case 119: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_0; else PIXEL00_60, PIXEL01_90; PIXEL10_12; PIXEL11_10; break; \
case 237: case 233: PIXEL00_12; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \
case 175: case 47: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; PIXEL10_11; PIXEL11_20; break; \
case 183: case 151: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_20; PIXEL11_12; break; \
case 245: case 244: PIXEL00_20; PIXEL01_11; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \
case 250: PIXEL00_10; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 123: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \
case 95: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_10; PIXEL11_10; break; \
case 222: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 252: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \
case 249: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 235: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \
case 111: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \
case 63: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_11; PIXEL11_21; break; \
case 159: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_22; PIXEL11_12; break; \
case 215: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 246: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \
case 254: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \
case 253: PIXEL00_12; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \
case 251: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 239: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \
case 127: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \
case 191: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_11; PIXEL11_12; break; \
case 223: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \
case 247: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \
case 255: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break;
template<int GuiScale>
void RenderHQ2X (SSurface Src, SSurface Dst, RECT *rect)
{
// If Snes9x is rendering anything in HiRes, then just copy, don't interpolate
if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{
RenderSimple2X (Src, Dst, rect);
return;
}
uint8 *srcPtr = Src.Surface;
uint8 *dstPtr = Dst.Surface;
uint32 srcPitch = Src.Pitch;
uint32 dstPitch = Dst.Pitch;
int width = Src.Width;
int height = Src.Height;
SetRect(rect, 256, height, 2);
dstPtr += rect->top * Dst.Pitch + rect->left * 2;
if(GuiScale==FILTER_HQ2X) {
HQ2X_16(Src.Surface,Src.Pitch,dstPtr,Dst.Pitch,Src.Width,Src.Height);
return;
}
int w1, w2, w3, w4, w5, w6, w7, w8, w9;
uint32 src1line = srcPitch >> 1;
uint32 dst1line = dstPitch >> 1;
uint16 *sp = (uint16 *) srcPtr;
uint16 *dp = (uint16 *) dstPtr;
const int* RGBtoYUVtable = RGBtoYUV;
uint32 pattern;
int l, y;
while (height--)
{
sp--;
w1 = *(sp - src1line);
w4 = *(sp);
w7 = *(sp + src1line);
sp++;
w2 = *(sp - src1line);
w5 = *(sp);
w8 = *(sp + src1line);
for (l = width; l; l--)
{
sp++;
w3 = *(sp - src1line);
w6 = *(sp);
w9 = *(sp + src1line);
pattern = 0;
switch(GuiScale)
{
case FILTER_HQ2XBOLD: {
const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9;
const bool diff5 = RGBtoBright[w5] > avg;
if ((w1 != w5) && ((RGBtoBright[w1] > avg) != diff5)) pattern |= (1 << 0);
if ((w2 != w5) && ((RGBtoBright[w2] > avg) != diff5)) pattern |= (1 << 1);
if ((w3 != w5) && ((RGBtoBright[w3] > avg) != diff5)) pattern |= (1 << 2);
if ((w4 != w5) && ((RGBtoBright[w4] > avg) != diff5)) pattern |= (1 << 3);
if ((w6 != w5) && ((RGBtoBright[w6] > avg) != diff5)) pattern |= (1 << 4);
if ((w7 != w5) && ((RGBtoBright[w7] > avg) != diff5)) pattern |= (1 << 5);
if ((w8 != w5) && ((RGBtoBright[w8] > avg) != diff5)) pattern |= (1 << 6);
if ((w9 != w5) && ((RGBtoBright[w9] > avg) != diff5)) pattern |= (1 << 7);
} break;
case FILTER_HQ2XS: {
bool nosame = true;
if(w1 == w5 || w3 == w5 || w7 == w5 || w9 == w5)
nosame = false;
if(nosame)
{
const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9;
const bool diff5 = RGBtoBright[w5] > avg;
if((RGBtoBright[w1] > avg) != diff5) pattern |= (1 << 0);
if((RGBtoBright[w2] > avg) != diff5) pattern |= (1 << 1);
if((RGBtoBright[w3] > avg) != diff5) pattern |= (1 << 2);
if((RGBtoBright[w4] > avg) != diff5) pattern |= (1 << 3);
if((RGBtoBright[w6] > avg) != diff5) pattern |= (1 << 4);
if((RGBtoBright[w7] > avg) != diff5) pattern |= (1 << 5);
if((RGBtoBright[w8] > avg) != diff5) pattern |= (1 << 6);
if((RGBtoBright[w9] > avg) != diff5) pattern |= (1 << 7);
}
else
{
y = RGBtoYUV[w5];
if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0);
if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1);
if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2);
if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3);
if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4);
if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5);
if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6);
if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7);
}
} break;
default:
case FILTER_HQ2X: // never reached, normal hq is handled by the core hq files
y = RGBtoYUVtable[w5];
if ((w1 != w5) && (Diff(y, RGBtoYUVtable[w1]))) pattern |= (1 << 0);
if ((w2 != w5) && (Diff(y, RGBtoYUVtable[w2]))) pattern |= (1 << 1);
if ((w3 != w5) && (Diff(y, RGBtoYUVtable[w3]))) pattern |= (1 << 2);
if ((w4 != w5) && (Diff(y, RGBtoYUVtable[w4]))) pattern |= (1 << 3);
if ((w6 != w5) && (Diff(y, RGBtoYUVtable[w6]))) pattern |= (1 << 4);
if ((w7 != w5) && (Diff(y, RGBtoYUVtable[w7]))) pattern |= (1 << 5);
if ((w8 != w5) && (Diff(y, RGBtoYUVtable[w8]))) pattern |= (1 << 6);
if ((w9 != w5) && (Diff(y, RGBtoYUVtable[w9]))) pattern |= (1 << 7);
break;
}
switch (pattern)
{
HQ2XCASES
}
w1 = w2; w4 = w5; w7 = w8;
w2 = w3; w5 = w6; w8 = w9;
dp += 2;
}
dp += ((dst1line - width) << 1);
sp += (src1line - width);
}
}
#define PIXEL00_1M *(dp) = Interp01(w5, w1);
#define PIXEL00_1U *(dp) = Interp01(w5, w2);
#define PIXEL00_1L *(dp) = Interp01(w5, w4);
#define PIXEL00_2 *(dp) = Interp02(w5, w4, w2);
#define PIXEL00_4 *(dp) = Interp04(w5, w4, w2);
#define PIXEL00_5 *(dp) = Interp05(w4, w2);
#define PIXEL00_C *(dp) = w5;
#define PIXEL01_1 *(dp + 1) = Interp01(w5, w2);
#define PIXEL01_3 *(dp + 1) = Interp03(w5, w2);
#define PIXEL01_6 *(dp + 1) = Interp01(w2, w5);
#define PIXEL01_C *(dp + 1) = w5;
#define PIXEL02_1M *(dp + 2) = Interp01(w5, w3);
#define PIXEL02_1U *(dp + 2) = Interp01(w5, w2);
#define PIXEL02_1R *(dp + 2) = Interp01(w5, w6);
#define PIXEL02_2 *(dp + 2) = Interp02(w5, w2, w6);
#define PIXEL02_4 *(dp + 2) = Interp04(w5, w2, w6);
#define PIXEL02_5 *(dp + 2) = Interp05(w2, w6);
#define PIXEL02_C *(dp + 2) = w5;
#define PIXEL10_1 *(dp + dst1line) = Interp01(w5, w4);
#define PIXEL10_3 *(dp + dst1line) = Interp03(w5, w4);
#define PIXEL10_6 *(dp + dst1line) = Interp01(w4, w5);
#define PIXEL10_C *(dp + dst1line) = w5;
#define PIXEL11 *(dp + dst1line + 1) = w5;
#define PIXEL12_1 *(dp + dst1line + 2) = Interp01(w5, w6);
#define PIXEL12_3 *(dp + dst1line + 2) = Interp03(w5, w6);
#define PIXEL12_6 *(dp + dst1line + 2) = Interp01(w6, w5);
#define PIXEL12_C *(dp + dst1line + 2) = w5;
#define PIXEL20_1M *(dp + dst1line + dst1line) = Interp01(w5, w7);
#define PIXEL20_1D *(dp + dst1line + dst1line) = Interp01(w5, w8);
#define PIXEL20_1L *(dp + dst1line + dst1line) = Interp01(w5, w4);
#define PIXEL20_2 *(dp + dst1line + dst1line) = Interp02(w5, w8, w4);
#define PIXEL20_4 *(dp + dst1line + dst1line) = Interp04(w5, w8, w4);
#define PIXEL20_5 *(dp + dst1line + dst1line) = Interp05(w8, w4);
#define PIXEL20_C *(dp + dst1line + dst1line) = w5;
#define PIXEL21_1 *(dp + dst1line + dst1line + 1) = Interp01(w5, w8);
#define PIXEL21_3 *(dp + dst1line + dst1line + 1) = Interp03(w5, w8);
#define PIXEL21_6 *(dp + dst1line + dst1line + 1) = Interp01(w8, w5);
#define PIXEL21_C *(dp + dst1line + dst1line + 1) = w5;
#define PIXEL22_1M *(dp + dst1line + dst1line + 2) = Interp01(w5, w9);
#define PIXEL22_1D *(dp + dst1line + dst1line + 2) = Interp01(w5, w8);
#define PIXEL22_1R *(dp + dst1line + dst1line + 2) = Interp01(w5, w6);
#define PIXEL22_2 *(dp + dst1line + dst1line + 2) = Interp02(w5, w6, w8);
#define PIXEL22_4 *(dp + dst1line + dst1line + 2) = Interp04(w5, w6, w8);
#define PIXEL22_5 *(dp + dst1line + dst1line + 2) = Interp05(w6, w8);
#define PIXEL22_C *(dp + dst1line + dst1line + 2) = w5;
#define Interp03(c1, c2) \
(((c1 == c2) ? c1 : \
((((((c1) & Mask_2) * 7 + ((c2) & Mask_2)) >> 3) & Mask_2) + \
(((((c1) & Mask13) * 7 + ((c2) & Mask13)) >> 3) & Mask13))))
#define Interp04(c1, c2, c3) \
((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) * 7 + ((c3) & Mask_2) * 7) >> 4) & Mask_2) + \
(((((c1) & Mask13) * 2 + ((c2) & Mask13) * 7 + ((c3) & Mask13) * 7) >> 4) & Mask13))
#define HQ3XCASES \
case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\
case 2: case 34: case 130: case 162: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\
case 16: case 17: case 48: case 49: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\
case 64: case 65: case 68: case 69: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\
case 8: case 12: case 136: case 140: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\
case 3: case 35: case 131: case 163: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\
case 6: case 38: case 134: case 166: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\
case 20: case 21: case 52: case 53: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\
case 144: case 145: case 176: case 177: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\
case 192: case 193: case 196: case 197: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\
case 96: case 97: case 100: case 101: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\
case 40: case 44: case 168: case 172: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\
case 9: case 13: case 137: case 141: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\
case 18: case 50: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_1M PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\
case 80: case 81: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_1M } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 72: case 76: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_1M PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 10: case 138: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\
case 66: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\
case 24: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\
case 7: case 39: case 135: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\
case 148: case 149: case 180: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\
case 224: case 228: case 225: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\
case 41: case 169: case 45: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\
case 22: case 54: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\
case 208: case 209: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 104: case 108: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 11: case 139: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\
case 19: case 51: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL12_C } else { PIXEL00_2 PIXEL01_6 PIXEL02_5 PIXEL12_1 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\
case 146: case 178: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_1M PIXEL12_C PIXEL22_1D } else { PIXEL01_1 PIXEL02_5 PIXEL12_6 PIXEL22_2 } PIXEL00_1M PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 break; }\
case 84: case 85: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL02_1U PIXEL12_C PIXEL21_C PIXEL22_1M } else { PIXEL02_2 PIXEL12_6 PIXEL21_1 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL10_1 PIXEL11 PIXEL20_1M break; }\
case 112: case 113: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL20_1L PIXEL21_C PIXEL22_1M } else { PIXEL12_1 PIXEL20_2 PIXEL21_6 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 break; }\
case 200: case 204: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_1M PIXEL21_C PIXEL22_1R } else { PIXEL10_1 PIXEL20_5 PIXEL21_6 PIXEL22_2 } PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 break; }\
case 73: case 77: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL00_1U PIXEL10_C PIXEL20_1M PIXEL21_C } else { PIXEL00_2 PIXEL10_6 PIXEL20_5 PIXEL21_1 } PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 PIXEL22_1M break; }\
case 42: case 170: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M PIXEL01_C PIXEL10_C PIXEL20_1D } else { PIXEL00_5 PIXEL01_1 PIXEL10_6 PIXEL20_2 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL21_1 PIXEL22_2 break; }\
case 14: case 142: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_C } else { PIXEL00_5 PIXEL01_6 PIXEL02_2 PIXEL10_1 } PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\
case 67: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\
case 70: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\
case 28: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\
case 152: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\
case 194: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\
case 98: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\
case 56: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\
case 25: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\
case 26: case 31: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL11 PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\
case 82: case 214: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\
case 88: case 248: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\
case 74: case 107: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 27: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\
case 86: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\
case 216: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 106: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 30: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\
case 210: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 120: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 75: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\
case 29: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\
case 198: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\
case 184: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\
case 99: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\
case 57: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\
case 71: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\
case 156: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\
case 226: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\
case 60: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\
case 195: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\
case 102: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\
case 153: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\
case 58: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\
case 83: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 92: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 202: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\
case 78: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1M break; }\
case 154: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\
case 114: { PIXEL00_1M PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 89: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 90: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 55: case 23: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL00_1L PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL00_2 PIXEL01_6 PIXEL02_5 PIXEL12_1 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\
case 182: case 150: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C PIXEL22_1D } else { PIXEL01_1 PIXEL02_5 PIXEL12_6 PIXEL22_2 } PIXEL00_1M PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 break; }\
case 213: case 212: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL02_1U PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL02_2 PIXEL12_6 PIXEL21_1 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL10_1 PIXEL11 PIXEL20_1M break; }\
case 241: case 240: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL20_1L PIXEL21_C PIXEL22_C } else { PIXEL12_1 PIXEL20_2 PIXEL21_6 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 break; }\
case 236: case 232: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C PIXEL22_1R } else { PIXEL10_1 PIXEL20_5 PIXEL21_6 PIXEL22_2 } PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 break; }\
case 109: case 105: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL00_1U PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL00_2 PIXEL10_6 PIXEL20_5 PIXEL21_1 } PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 PIXEL22_1M break; }\
case 171: case 43: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C PIXEL20_1D } else { PIXEL00_5 PIXEL01_1 PIXEL10_6 PIXEL20_2 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL21_1 PIXEL22_2 break; }\
case 143: case 15: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL02_1R PIXEL10_C } else { PIXEL00_5 PIXEL01_6 PIXEL02_2 PIXEL10_1 } PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\
case 124: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 203: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\
case 62: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\
case 211: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 118: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\
case 217: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 110: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 155: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\
case 188: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\
case 185: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\
case 61: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\
case 157: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\
case 103: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\
case 227: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\
case 230: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\
case 199: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\
case 220: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 158: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\
case 234: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1M PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1R break; }\
case 242: { PIXEL00_1M PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL20_1L if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 59: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\
case 121: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 87: { PIXEL00_1L if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_1M PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 79: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1R PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1M break; }\
case 122: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 94: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 218: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 91: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 229: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\
case 167: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\
case 173: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\
case 181: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\
case 186: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\
case 115: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 93: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 206: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\
case 205: case 201: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\
case 174: case 46: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\
case 179: case 147: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\
case 117: case 116: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\
case 189: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\
case 231: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\
case 126: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 219: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\
case 125: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL00_1U PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL00_2 PIXEL10_6 PIXEL20_5 PIXEL21_1 } PIXEL01_1 PIXEL02_1U PIXEL11 PIXEL12_C PIXEL22_1M break; }\
case 221: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL02_1U PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL02_2 PIXEL12_6 PIXEL21_1 PIXEL22_5 } PIXEL00_1U PIXEL01_1 PIXEL10_C PIXEL11 PIXEL20_1M break; }\
case 207: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL02_1R PIXEL10_C } else { PIXEL00_5 PIXEL01_6 PIXEL02_2 PIXEL10_1 } PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\
case 238: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C PIXEL22_1R } else { PIXEL10_1 PIXEL20_5 PIXEL21_6 PIXEL22_2 } PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL11 PIXEL12_1 break; }\
case 190: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C PIXEL22_1D } else { PIXEL01_1 PIXEL02_5 PIXEL12_6 PIXEL22_2 } PIXEL00_1M PIXEL10_C PIXEL11 PIXEL20_1D PIXEL21_1 break; }\
case 187: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C PIXEL20_1D } else { PIXEL00_5 PIXEL01_1 PIXEL10_6 PIXEL20_2 } PIXEL02_1M PIXEL11 PIXEL12_C PIXEL21_1 PIXEL22_1D break; }\
case 243: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL20_1L PIXEL21_C PIXEL22_C } else { PIXEL12_1 PIXEL20_2 PIXEL21_6 PIXEL22_5 } PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 break; }\
case 119: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL00_1L PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL00_2 PIXEL01_6 PIXEL02_5 PIXEL12_1 } PIXEL10_1 PIXEL11 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\
case 237: case 233: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\
case 175: case 47: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\
case 183: case 151: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\
case 245: case 244: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\
case 250: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\
case 123: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 95: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL11 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\
case 222: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\
case 252: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\
case 249: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\
case 235: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\
case 111: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 63: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\
case 159: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\
case 215: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\
case 246: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\
case 254: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_2 } break; }\
case 253: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\
case 251: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_2 PIXEL21_3 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\
case 239: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\
case 127: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_2 PIXEL01_3 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\
case 191: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\
case 223: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_2 PIXEL12_3 } PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\
case 247: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\
case 255: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }
template<int GuiScale>
void RenderHQ3X (SSurface Src, SSurface Dst, RECT *rect)
{
// If Snes9x is rendering anything in HiRes, then just copy, don't interpolate
if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{
RenderSimple3X (Src, Dst, rect);
return;
}
uint8 *srcPtr = Src.Surface;
uint8 *dstPtr = Dst.Surface;
uint32 srcPitch = Src.Pitch;
uint32 dstPitch = Dst.Pitch;
int width = Src.Width;
int height = Src.Height;
SetRect(rect, 256, height, 3);
dstPtr += rect->top * Dst.Pitch + rect->left * 2;
if(GuiScale==FILTER_HQ2X) {
HQ3X_16(Src.Surface,Src.Pitch,dstPtr,Dst.Pitch,Src.Width,Src.Height);
return;
}
int w1, w2, w3, w4, w5, w6, w7, w8, w9;
uint32 src1line = srcPitch >> 1;
uint32 dst1line = dstPitch >> 1;
uint16 *sp = (uint16 *) srcPtr;
uint16 *dp = (uint16 *) dstPtr;
const int* RGBtoYUVtable = RGBtoYUV;
uint32 pattern;
int l, y;
while (height--)
{
sp--;
w1 = *(sp - src1line);
w4 = *(sp);
w7 = *(sp + src1line);
sp++;
w2 = *(sp - src1line);
w5 = *(sp);
w8 = *(sp + src1line);
for (l = width; l; l--)
{
sp++;
w3 = *(sp - src1line);
w6 = *(sp);
w9 = *(sp + src1line);
pattern = 0;
switch(GuiScale)
{
case FILTER_HQ3XBOLD: {
const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9;
const bool diff5 = RGBtoBright[w5] > avg;
if ((w1 != w5) && ((RGBtoBright[w1] > avg) != diff5)) pattern |= (1 << 0);
if ((w2 != w5) && ((RGBtoBright[w2] > avg) != diff5)) pattern |= (1 << 1);
if ((w3 != w5) && ((RGBtoBright[w3] > avg) != diff5)) pattern |= (1 << 2);
if ((w4 != w5) && ((RGBtoBright[w4] > avg) != diff5)) pattern |= (1 << 3);
if ((w6 != w5) && ((RGBtoBright[w6] > avg) != diff5)) pattern |= (1 << 4);
if ((w7 != w5) && ((RGBtoBright[w7] > avg) != diff5)) pattern |= (1 << 5);
if ((w8 != w5) && ((RGBtoBright[w8] > avg) != diff5)) pattern |= (1 << 6);
if ((w9 != w5) && ((RGBtoBright[w9] > avg) != diff5)) pattern |= (1 << 7);
} break;
case FILTER_HQ3XS: {
bool nosame = true;
if(w1 == w5 || w3 == w5 || w7 == w5 || w9 == w5)
nosame = false;
if(nosame)
{
const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9;
const bool diff5 = RGBtoBright[w5] > avg;
if((RGBtoBright[w1] > avg) != diff5) pattern |= (1 << 0);
if((RGBtoBright[w2] > avg) != diff5) pattern |= (1 << 1);
if((RGBtoBright[w3] > avg) != diff5) pattern |= (1 << 2);
if((RGBtoBright[w4] > avg) != diff5) pattern |= (1 << 3);
if((RGBtoBright[w6] > avg) != diff5) pattern |= (1 << 4);
if((RGBtoBright[w7] > avg) != diff5) pattern |= (1 << 5);
if((RGBtoBright[w8] > avg) != diff5) pattern |= (1 << 6);
if((RGBtoBright[w9] > avg) != diff5) pattern |= (1 << 7);
}
else
{
y = RGBtoYUV[w5];
if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0);
if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1);
if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2);
if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3);
if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4);
if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5);
if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6);
if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7);
}
} break;
default:
case FILTER_HQ3X: // never reached, normal hq is handled by the core hq files
y = RGBtoYUVtable[w5];
if ((w1 != w5) && (Diff(y, RGBtoYUVtable[w1]))) pattern |= (1 << 0);
if ((w2 != w5) && (Diff(y, RGBtoYUVtable[w2]))) pattern |= (1 << 1);
if ((w3 != w5) && (Diff(y, RGBtoYUVtable[w3]))) pattern |= (1 << 2);
if ((w4 != w5) && (Diff(y, RGBtoYUVtable[w4]))) pattern |= (1 << 3);
if ((w6 != w5) && (Diff(y, RGBtoYUVtable[w6]))) pattern |= (1 << 4);
if ((w7 != w5) && (Diff(y, RGBtoYUVtable[w7]))) pattern |= (1 << 5);
if ((w8 != w5) && (Diff(y, RGBtoYUVtable[w8]))) pattern |= (1 << 6);
if ((w9 != w5) && (Diff(y, RGBtoYUVtable[w9]))) pattern |= (1 << 7);
break;
}
switch (pattern)
{
HQ3XCASES
}
w1 = w2; w4 = w5; w7 = w8;
w2 = w3; w5 = w6; w8 = w9;
dp += 3;
}
dp += ((dst1line - width) * 3);
sp += (src1line - width);
}
}
#undef Interp02
#undef Interp06
#undef Interp07
#undef Interp10
#undef Interp03
#undef Interp01
#undef Interp09
#undef Interp04
#define Interp02(c1, c2, c3) (c1) // choose majority
#define Interp06(c1, c2, c3) (c1)
#define Interp07(c1, c2, c3) (c1)
#define Interp10(c1, c2, c3) (c1)
#define Interp03(c1, c2) (c1)
#define Interp01(c1, c2) (c1)
#define Interp09(c1, c2, c3) Interp05(c2,c3) // 50/50 split of majority
#define Interp04(c1, c2, c3) Interp05(c2,c3)
// same as RenderHQ3XB except mostly choosing colors instead of blending them
void RenderLQ3XB (SSurface Src, SSurface Dst, RECT *rect)
{
// If Snes9x is rendering anything in HiRes, then just copy, don't interpolate
if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{
RenderSimple3X (Src, Dst, rect);
return;
}
uint8 *srcPtr = Src.Surface;
uint8 *dstPtr = Dst.Surface;
uint32 srcPitch = Src.Pitch;
uint32 dstPitch = Dst.Pitch;
int width = Src.Width;
int height = Src.Height;
SetRect(rect, 256, height, 3);
dstPtr += rect->top * Dst.Pitch + rect->left * 2;
int w1, w2, w3, w4, w5, w6, w7, w8, w9;
uint32 src1line = srcPitch >> 1;
uint32 dst1line = dstPitch >> 1;
uint16 *sp = (uint16 *) srcPtr;
uint16 *dp = (uint16 *) dstPtr;
const int* RGBtoYUVtable = RGBtoYUV;
uint32 pattern;
int l;//, y;
while (height--)
{
sp--;
w1 = *(sp - src1line);
w4 = *(sp);
w7 = *(sp + src1line);
sp++;
w2 = *(sp - src1line);
w5 = *(sp);
w8 = *(sp + src1line);
for (l = width; l; l--)
{
sp++;
w3 = *(sp - src1line);
w6 = *(sp);
w9 = *(sp + src1line);
pattern = 0;
{
const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9;
const bool diff5 = RGBtoBright[w5] > avg;
if ((w1 != w5) && ((RGBtoBright[w1] > avg) != diff5)) pattern |= (1 << 0);
if ((w2 != w5) && ((RGBtoBright[w2] > avg) != diff5)) pattern |= (1 << 1);
if ((w3 != w5) && ((RGBtoBright[w3] > avg) != diff5)) pattern |= (1 << 2);
if ((w4 != w5) && ((RGBtoBright[w4] > avg) != diff5)) pattern |= (1 << 3);
if ((w6 != w5) && ((RGBtoBright[w6] > avg) != diff5)) pattern |= (1 << 4);
if ((w7 != w5) && ((RGBtoBright[w7] > avg) != diff5)) pattern |= (1 << 5);
if ((w8 != w5) && ((RGBtoBright[w8] > avg) != diff5)) pattern |= (1 << 6);
if ((w9 != w5) && ((RGBtoBright[w9] > avg) != diff5)) pattern |= (1 << 7);
}
switch (pattern)
{
HQ3XCASES
}
w1 = w2; w4 = w5; w7 = w8;
w2 = w3; w5 = w6; w8 = w9;
dp += 3;
}
dp += ((dst1line - width) * 3);
sp += (src1line - width);
}
}
#undef Interp02
#undef Interp06
#undef Interp07
#undef Interp10
#undef Interp03
#undef Interp01
#undef Interp09
#undef Interp04
static void DoubleHeightInPlace ( uint16 *lpSurface, unsigned int surfaceRowPixels, unsigned int width, unsigned int height)
{
unsigned int targetHeight=height*2;
uint16 *lpSrc=lpSurface+surfaceRowPixels*height;
uint16 *lpDst=lpSurface+surfaceRowPixels*targetHeight;
for(int i=targetHeight;i;i-=2) {
memcpy(lpDst,lpSrc,width*2),lpDst-=surfaceRowPixels,
memcpy(lpDst,lpSrc,width*2),lpDst-=surfaceRowPixels;
lpSrc-=surfaceRowPixels;
}
}
static void DoubleWidthInPlace ( uint16 *lpSurface, unsigned int surfaceRowPixels, unsigned int width, unsigned int height)
{
unsigned int targetWidth=width*2;
uint16 *lpSrc=lpSurface+width+height*surfaceRowPixels;
uint16 *lpDst=lpSurface+targetWidth+height*surfaceRowPixels;
for(int i=height;i;i--) {
for(int j=width;j;j--) {
*lpDst-- = *lpSrc;
*lpDst-- = *lpSrc;
lpSrc--;
}
lpSrc-=(surfaceRowPixels - width);
lpDst-=(surfaceRowPixels - targetWidth);
}
}
void RenderHQ4X (SSurface Src, SSurface Dst, RECT *rect)
{
uint8 *dstPtr = Dst.Surface;
SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 4);
dstPtr += rect->top * Dst.Pitch + rect->left * 2;
if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512)
{
HQ2X_16(Src.Surface,Src.Pitch,dstPtr,Dst.Pitch,Src.Width,Src.Height);
if(Src.Height<=SNES_HEIGHT_EXTENDED)
DoubleHeightInPlace((uint16 *)dstPtr,Dst.Pitch>>1,Src.Width*2,Src.Height*2);
else if(Src.Width==SNES_WIDTH)
DoubleWidthInPlace((uint16 *)dstPtr,Dst.Pitch>>1,Src.Width*2,Src.Height*2);
return;
}
HQ4X_16(Src.Surface,Src.Pitch,dstPtr,Dst.Pitch,Src.Width,Src.Height);
}
void RenderSimple4X( SSurface Src, SSurface Dst, RECT *rect)
{
uint16 *lpSrc;
unsigned int H;
SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 4);
const uint32 srcHeight = (rect->bottom - rect->top)/4;
const unsigned int srcPitch = Src.Pitch >> 1;
lpSrc = reinterpret_cast<uint16 *>(Src.Surface);
if(GUI.ScreenDepth == 16)
{
const unsigned int dstPitch = Dst.Pitch >> 1;
uint16 *lpDst = reinterpret_cast<uint16 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if (Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
if(Src.Width != 512)
for (H = 0; H < Src.Height; H++, lpSrc += srcPitch)
QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < Src.Height; H++, lpSrc += srcPitch)
DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch;
}
else if(GUI.ScreenDepth == 32)
{
const unsigned int dstPitch = Dst.Pitch >> 2;
uint32 *lpDst = reinterpret_cast<uint32 *>(Dst.Surface) + rect->top * dstPitch + rect->left;
if (Src.Height <= SNES_HEIGHT_EXTENDED)
if(Src.Width != 512)
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < srcHeight; H++, lpSrc += srcPitch)
DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
if(Src.Width != 512)
for (H = 0; H < Src.Height; H++, lpSrc += srcPitch)
QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch,
QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch;
else
for (H = 0; H < Src.Height; H++, lpSrc += srcPitch)
DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch,
DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch;
}
}
2014-06-24 21:53:00 +02:00
/*#################### XBRZ support ####################*/
//copy image and convert from RGB565/555 to ARGB
inline
void copyImage16To32(const uint16_t* src, int width, int height, int srcPitch,
uint32_t* trg, int yFirst, int yLast)
{
yFirst = std::max(yFirst, 0);
yLast = std::min(yLast, height);
if (yFirst >= yLast || height <= 0 || width <= 0) return;
for (int y = yFirst; y < yLast; ++y)
{
uint32_t* trgLine = trg + y * width;
const uint16_t* srcLine = reinterpret_cast<const uint16_t*>(reinterpret_cast<const char*>(src) + y * srcPitch);
for (int x = 0; x < width; ++x)
trgLine[x] = CONVERT_16_TO_32(srcLine[x]);
}
}
//stretch image and convert from ARGB to RGB565/555
inline
void stretchImage32To16(const uint32_t* src, int srcWidth, int srcHeight,
uint16_t* trg, int trgWidth, int trgHeight, int trgPitch,
int yFirst, int yLast)
{
yFirst = std::max(yFirst, 0);
yLast = std::min(yLast, trgHeight);
if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) return;
for (int y = yFirst; y < yLast; ++y)
{
uint16_t* trgLine = reinterpret_cast<uint16_t*>(reinterpret_cast<char*>(trg) + y * trgPitch);
const int ySrc = srcHeight * y / trgHeight;
const uint32_t* srcLine = src + ySrc * srcWidth;
for (int x = 0; x < trgWidth; ++x)
{
const int xSrc = srcWidth * x / trgWidth;
trgLine[x] = CONVERT_32_TO_16(srcLine[xSrc]);
}
}
}
std::vector<uint32_t> renderBuffer; //raw image
std::vector<uint32_t> xbrzBuffer; //scaled image
DWORD WINAPI ThreadProc_XBRZ(VOID * pParam)
{
xbrz_thread_data *thread_data = (xbrz_thread_data *)pParam;
while(true) {
WaitForSingleObject(thread_data->xbrz_start_event, INFINITE);
int trgWidth = xbrz_thread_data::src->Width * xbrz_thread_data::scalingFactor;
int trgHeight = xbrz_thread_data::src->Height * xbrz_thread_data::scalingFactor;
copyImage16To32(reinterpret_cast<const uint16_t*>(thread_data->src->Surface), xbrz_thread_data::src->Width, xbrz_thread_data::src->Height, xbrz_thread_data::src->Pitch,
&renderBuffer[0], thread_data->yFirst, thread_data->yLast);
SetEvent(thread_data->xbrz_sync_event);
WaitForSingleObject(thread_data->xbrz_start_event, INFINITE);
2015-01-29 21:42:32 +01:00
xbrz::scale(thread_data->scalingFactor, &renderBuffer[0], &xbrzBuffer[0], xbrz_thread_data::src->Width, xbrz_thread_data::src->Height, xbrz::ColorFormat::RGB, xbrz::ScalerCfg(), thread_data->yFirst, thread_data->yLast);
2014-06-24 21:53:00 +02:00
SetEvent(thread_data->xbrz_sync_event);
WaitForSingleObject(thread_data->xbrz_start_event, INFINITE);
2014-06-25 23:16:52 +02:00
trgHeight = SNES_HEIGHT_EXTENDED * xbrz_thread_data::scalingFactor;
if (xbrz_thread_data::src->Height % SNES_HEIGHT == 0)
trgHeight = SNES_HEIGHT * xbrz_thread_data::scalingFactor;
trgWidth = SNES_WIDTH * xbrz_thread_data::scalingFactor;
2014-06-24 21:53:00 +02:00
stretchImage32To16(&xbrzBuffer[0], xbrz_thread_data::src->Width * xbrz_thread_data::scalingFactor, xbrz_thread_data::src->Height * xbrz_thread_data::scalingFactor,
reinterpret_cast<uint16_t*>(xbrz_thread_data::dstPtr), trgWidth, trgHeight, xbrz_thread_data::dst->Pitch, thread_data->yFirst * xbrz_thread_data::scalingFactor, thread_data->yLast * xbrz_thread_data::scalingFactor);
SetEvent(thread_data->xbrz_sync_event);
}
return 0;
}
2014-06-25 23:16:52 +02:00
void Render2xBRZ(SSurface Src, SSurface Dst, RECT* rect)
{
RenderxBRZ(Src, Dst, rect, 2);
}
void Render3xBRZ(SSurface Src, SSurface Dst, RECT* rect)
{
RenderxBRZ(Src, Dst, rect, 3);
}
2014-06-24 21:53:00 +02:00
void Render4xBRZ(SSurface Src, SSurface Dst, RECT* rect)
{
2014-06-25 23:16:52 +02:00
RenderxBRZ(Src, Dst, rect, 4);
}
2016-10-07 21:39:32 +02:00
void Render5xBRZ(SSurface Src, SSurface Dst, RECT* rect)
{
RenderxBRZ(Src, Dst, rect, 5);
}
void Render6xBRZ(SSurface Src, SSurface Dst, RECT* rect)
{
RenderxBRZ(Src, Dst, rect, 6);
}
2014-06-25 23:16:52 +02:00
void RenderxBRZ(SSurface Src, SSurface Dst, RECT* rect, int scalingFactor)
{
xbrz_thread_data::scalingFactor = scalingFactor;
2014-06-24 21:53:00 +02:00
xbrz_thread_data::dstPtr = Dst.Surface;
SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, xbrz_thread_data::scalingFactor);
xbrz_thread_data::dstPtr += rect->top * Dst.Pitch + rect->left * sizeof(uint16_t);
if (Src.Width <= 0 || Src.Height <= 0)
return;
renderBuffer.resize(Src.Width * Src.Height);
xbrzBuffer.resize(renderBuffer.size() * xbrz_thread_data::scalingFactor * xbrz_thread_data::scalingFactor);
xbrz_thread_data::src = &Src;
xbrz_thread_data::dst = &Dst;
// init + convert run
int ySlice = Src.Height / num_xbrz_threads;
for(int i = 0; i < num_xbrz_threads; i++) {
xbrz_thread_sync_data[i].yFirst = ySlice * i;
xbrz_thread_sync_data[i].yLast = (i == num_xbrz_threads - 1) ? Src.Height : ySlice * i + ySlice;
SetEvent(xbrz_thread_sync_data[i].xbrz_start_event);
}
WaitForMultipleObjects(num_xbrz_threads, xbrz_sync_handles, TRUE, INFINITE);
// xbrz run
for(int i = 0; i < num_xbrz_threads; i++) {
SetEvent(xbrz_thread_sync_data[i].xbrz_start_event);
}
WaitForMultipleObjects(num_xbrz_threads, xbrz_sync_handles, TRUE, INFINITE);
// convert run
for(int i = 0; i < num_xbrz_threads; i++) {
SetEvent(xbrz_thread_sync_data[i].xbrz_start_event);
}
WaitForMultipleObjects(num_xbrz_threads, xbrz_sync_handles, TRUE, INFINITE);
}
/*#################### /XBRZ support ####################*/
2010-09-25 17:46:12 +02:00
void RenderBlarggNTSCComposite( SSurface Src, SSurface Dst, RECT *rect)
{
if(blarggMode!=BLARGGCOMPOSITE) {
snes_ntsc_setup_t setup = snes_ntsc_composite;
setup.merge_fields = 1;
snes_ntsc_init( ntsc, &setup );
blarggMode=BLARGGCOMPOSITE;
}
RenderBlarggNTSC(Src,Dst,rect);
}
void RenderBlarggNTSCSvideo( SSurface Src, SSurface Dst, RECT *rect)
{
if(blarggMode!=BLARGGSVIDEO) {
snes_ntsc_setup_t setup = snes_ntsc_svideo;
setup.merge_fields = 1;
snes_ntsc_init( ntsc, &setup );
blarggMode=BLARGGSVIDEO;
}
RenderBlarggNTSC(Src,Dst,rect);
}
void RenderBlarggNTSCRgb( SSurface Src, SSurface Dst, RECT *rect)
{
if(blarggMode!=BLARGGRGB) {
snes_ntsc_setup_t setup = snes_ntsc_rgb;
setup.merge_fields = 1;
snes_ntsc_init( ntsc, &setup );
blarggMode=BLARGGRGB;
}
RenderBlarggNTSC(Src,Dst,rect);
}
void RenderBlarggNTSC( SSurface Src, SSurface Dst, RECT *rect)
{
SetRect(rect, 256, 239, 2);
rect->right = SNES_NTSC_OUT_WIDTH(256);
2010-09-25 17:46:12 +02:00
const unsigned int srcRowPixels = Src.Pitch/2;
2010-09-25 17:46:12 +02:00
if(Src.Width == 512)
snes_ntsc_blit_hires( ntsc, (unsigned short *)Src.Surface, srcRowPixels, 0,Src.Width, Src.Height, Dst.Surface, Dst.Pitch );
else
snes_ntsc_blit( ntsc, (unsigned short *)Src.Surface, srcRowPixels, 0,Src.Width, Src.Height, Dst.Surface, Dst.Pitch );
2010-09-25 17:46:12 +02:00
//Blargg's filter produces half-height output, so we have to double the height again (unless we have double height hi-res)
if(Src.Height <= SNES_HEIGHT_EXTENDED)
{
int mask = 0;
if (GUI.NTSCScanlines)
mask = 0x18E3;
int last_blargg_line = rect->bottom / 2;
memset(Dst.Surface + last_blargg_line * Dst.Pitch, 0, Dst.Pitch);
for(int y = last_blargg_line; --y >= 0; )
{
unsigned char const* in = Dst.Surface + y * Dst.Pitch;
unsigned char* out = Dst.Surface + y * 2 * Dst.Pitch;
for(int n = rect->right; n; --n)
{
unsigned prev = *(unsigned short*)in;
unsigned next = *(unsigned short*)(in + Dst.Pitch);
/* mix 16-bit rgb without losing low bits */
unsigned mixed = prev + next + ((prev ^ next) & 0x0821);
/* darken by 12% */
*(unsigned short*)out = prev;
*(unsigned short*)(out + Dst.Pitch) = (mixed >> 1) - (mixed >> 4 & mask);
in += 2;
out += 2;
}
}
}
2010-09-25 17:46:12 +02:00
}