added hq2x filtering feature!

- 3 'versions' of filter with varying effects (like on windows)
This commit is contained in:
michniewski 2009-01-30 07:25:30 +00:00
parent 38a1c406d3
commit 3a3385da4b
8 changed files with 722 additions and 18 deletions

541
source/ngc/filter.cpp Normal file
View File

@ -0,0 +1,541 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Michniewski 2008
*
* HQ2x, HQ3x, HQ4x filters
* (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
*
* filter.cpp
*
* Adapted from Snes9x Win32/MacOSX ports
* Video Filter Code (hq2x)
****************************************************************************/
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ogcsys.h>
#include <unistd.h>
#include <malloc.h>
#include "filter.h"
#include "video.h"
#include "snes9xGX.h"
#include "memmap.h"
#include "menudraw.h"
#define NUMBITS (16)
static int RGBtoYUV[1<<NUMBITS];
static uint16 RGBtoBright[1<<NUMBITS];
TFilterMethod FilterMethod = RenderPlain;
//TFilterMethod FilterMethodHiRes = RenderPlain;
//
// Functions:
//
bool
GetFilterHiResSupport (RenderFilter filterID)
{
switch(filterID)
{
case FILTER_NONE:
return true;
default:
return false;
}
}
const char*
GetFilterName (RenderFilter filterID)
{
switch(filterID)
{
default: return "Unknown";
case FILTER_NONE: return "None";
case FILTER_HQ2X: return "hq2x";
case FILTER_HQ2XS: return "hq2x Soft";
case FILTER_HQ2XBOLD: return "hq2x Bold";
}
}
// Return pointer to appropriate function
TFilterMethod
FilterToMethod (RenderFilter filterID)
{
switch(filterID)
{
default:
case FILTER_NONE: return RenderPlain;
case FILTER_HQ2X: return RenderHQ2X<FILTER_HQ2X>;
case FILTER_HQ2XS: return RenderHQ2X<FILTER_HQ2XS>;
case FILTER_HQ2XBOLD: return RenderHQ2X<FILTER_HQ2XBOLD>;
}
}
int GetFilterScale(RenderFilter filterID)
{
switch(filterID)
{
case FILTER_NONE:
return 1;
default:
case FILTER_HQ2X:
case FILTER_HQ2XS:
case FILTER_HQ2XBOLD:
return 2;
}
}
void
SelectFilterMethod ()
{
//WaitPrompt ((char*)"Select Filter Method."); // debug
FilterMethod = FilterToMethod((RenderFilter)GCSettings.FilterMethod);
//FilterMethodHiRes = FilterToMethod((RenderFilter)GCSettings.FilterMethodHiRes);
// check whether or not we need filter memory (alloc or free it)
}
//
// Filter Codes:
//
// No enlargement, just render to the screen
void
RenderPlain (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
{
if (dstPtr == NULL)
{
WaitPrompt((char*)"dstPtr is NULL. exiting!");
exit(1);
}
//memcpy (dstPtr, srcPtr, width*height*srcPitch);
return;
}
//
// HQ2X Filter Code:
//
#define Mask_2 0x07E0 // 00000 111111 00000
#define Mask13 0xF81F // 11111 000000 11111
#define Ymask 0xFF0000
#define Umask 0x00FF00
#define Vmask 0x0000FF
#define trY 0x300000
#define trU 0x000700
#define trV 0x000006
#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 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 InitLUTs(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 (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
{
// If Snes9x is rendering anything in HiRes, then just copy, don't interpolate
if (height > SNES_HEIGHT_EXTENDED || width == 512)
{
//RenderSimple2X (Src, Dst, rect);
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:
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);
}
}

62
source/ngc/filter.h Normal file
View File

@ -0,0 +1,62 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Michniewski 2008
*
* filter.h
*
* Filters Header File
****************************************************************************/
#ifndef _FILTER_H_
#define _FILTER_H_
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "snes9x.h"
enum RenderFilter{
FILTER_NONE = 0,
FILTER_HQ2X,
FILTER_HQ2XS,
FILTER_HQ2XBOLD,
NUM_FILTERS
};
#define EXT_WIDTH (MAX_SNES_WIDTH + 4)
#define EXT_PITCH (EXT_WIDTH * 2)
#define EXT_HEIGHT (MAX_SNES_HEIGHT + 4)
// Offset into buffer to allow a two pixel border around the whole rendered
// SNES image. This is a speed up hack to allow some of the image processing
// routines to access black pixel data outside the normal bounds of the buffer.
#define EXT_OFFSET (EXT_PITCH * 2 + 2 * 2)
typedef void (*TFilterMethod)(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
extern TFilterMethod FilterMethod;
extern TFilterMethod FilterMethodHiRes;
extern unsigned char filtermem[];
//
// Prototypes
//
void SelectFilterMethod ();
void RenderPlain (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
void SelectFilterMethod ();
TFilterMethod FilterToMethod (RenderFilter filterID);
const char* GetFilterName (RenderFilter filterID);
bool GetFilterHiResSupport (RenderFilter filterID);
int GetFilterScale(RenderFilter filterID);
template<int GuiScale> void RenderHQ2X (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);
void InitLUTs();
#endif

View File

@ -55,6 +55,7 @@ extern "C" {
#include "cheatmgr.h" #include "cheatmgr.h"
#include "input.h" #include "input.h"
#include "patch.h" #include "patch.h"
#include "filter.h"
extern int menu; extern int menu;
@ -511,12 +512,13 @@ FileOptions ()
/**************************************************************************** /****************************************************************************
* Video Options * Video Options
***************************************************************************/ ***************************************************************************/
static int videomenuCount = 10; static int videomenuCount = 11;
static char videomenu[][50] = { static char videomenu[][50] = {
"Enable Zooming", "Enable Zooming",
"Video Rendering", "Video Rendering",
"Video Scaling", "Video Scaling",
"Video Filtering",
"Shift Video Up", "Shift Video Up",
"Shift Video Down", "Shift Video Down",
@ -555,7 +557,9 @@ VideoOptions ()
sprintf (videomenu[2], "Video Scaling %s", sprintf (videomenu[2], "Video Scaling %s",
GCSettings.widescreen == true ? "16:9 Correction" : "Default"); GCSettings.widescreen == true ? "16:9 Correction" : "Default");
sprintf (videomenu[7], "Video Shift: %d, %d", GCSettings.xshift, GCSettings.yshift); sprintf (videomenu[3], "Video Filtering %s", GetFilterName((RenderFilter)GCSettings.FilterMethod));
sprintf (videomenu[8], "Video Shift: %d, %d", GCSettings.xshift, GCSettings.yshift);
ret = RunMenu (videomenu, videomenuCount, "Video Options"); ret = RunMenu (videomenu, videomenuCount, "Video Options");
@ -567,7 +571,7 @@ VideoOptions ()
case 1: case 1:
GCSettings.render++; GCSettings.render++;
if (GCSettings.render > 2 ) if (GCSettings.render > 2 || GCSettings.FilterMethod != FILTER_NONE)
GCSettings.render = 0; GCSettings.render = 0;
// reset zoom // reset zoom
zoom_reset (); zoom_reset ();
@ -578,33 +582,40 @@ VideoOptions ()
break; break;
case 3: case 3:
GCSettings.FilterMethod++;
if (GCSettings.FilterMethod >= NUM_FILTERS)
GCSettings.FilterMethod = 0;
SelectFilterMethod();
break;
case 4:
// Move up // Move up
GCSettings.yshift--; GCSettings.yshift--;
break; break;
case 4: case 5:
// Move down // Move down
GCSettings.yshift++; GCSettings.yshift++;
break; break;
case 5: case 6:
// Move left // Move left
GCSettings.xshift--; GCSettings.xshift--;
break; break;
case 6: case 7:
// Move right // Move right
GCSettings.xshift++; GCSettings.xshift++;
break; break;
case 7: case 8:
break; break;
case 8: case 9:
// reset video shifts // reset video shifts
GCSettings.xshift = GCSettings.yshift = 0; GCSettings.xshift = GCSettings.yshift = 0;
WaitPrompt("Video Shift Reset"); WaitPrompt("Video Shift Reset");
break; break;
case -1: // Button B case -1: // Button B
case 9: case 10:
quit = 1; quit = 1;
break; break;
@ -1088,4 +1099,6 @@ MainMenu (int selectedMenu)
VIDEO_WaitVSync(); VIDEO_WaitVSync();
count++; count++;
} }
SelectFilterMethod();
} }

View File

@ -157,6 +157,7 @@ preparePrefsData (int method)
createXMLSetting("ZoomLevel", "Zoom Level", FtoStr(GCSettings.ZoomLevel)); createXMLSetting("ZoomLevel", "Zoom Level", FtoStr(GCSettings.ZoomLevel));
createXMLSetting("render", "Video Filtering", toStr(GCSettings.render)); createXMLSetting("render", "Video Filtering", toStr(GCSettings.render));
createXMLSetting("widescreen", "Aspect Ratio Correction", toStr(GCSettings.widescreen)); createXMLSetting("widescreen", "Aspect Ratio Correction", toStr(GCSettings.widescreen));
createXMLSetting("FilterMethod", "Filter Method", toStr(GCSettings.FilterMethod));
createXMLSetting("xshift", "Horizontal Video Shift", toStr(GCSettings.xshift)); createXMLSetting("xshift", "Horizontal Video Shift", toStr(GCSettings.xshift));
createXMLSetting("yshift", "Vertical Video Shift", toStr(GCSettings.yshift)); createXMLSetting("yshift", "Vertical Video Shift", toStr(GCSettings.yshift));
@ -315,6 +316,7 @@ decodePrefsData (int method)
loadXMLSetting(&GCSettings.ZoomLevel, "ZoomLevel"); loadXMLSetting(&GCSettings.ZoomLevel, "ZoomLevel");
loadXMLSetting(&GCSettings.render, "render"); loadXMLSetting(&GCSettings.render, "render");
loadXMLSetting(&GCSettings.widescreen, "widescreen"); loadXMLSetting(&GCSettings.widescreen, "widescreen");
loadXMLSetting(&GCSettings.FilterMethod, "FilterMethod");
loadXMLSetting(&GCSettings.xshift, "xshift"); loadXMLSetting(&GCSettings.xshift, "xshift");
loadXMLSetting(&GCSettings.yshift, "yshift"); loadXMLSetting(&GCSettings.yshift, "yshift");

View File

@ -17,6 +17,7 @@
#include "snes9x.h" #include "snes9x.h"
#include "snes9xGX.h" #include "snes9xGX.h"
#include "input.h" #include "input.h"
#include "filter.h"
struct SGCSettings GCSettings; struct SGCSettings GCSettings;
@ -55,6 +56,7 @@ DefaultSettings ()
GCSettings.ZoomLevel = 1.0; // zoom level GCSettings.ZoomLevel = 1.0; // zoom level
GCSettings.render = 2; // Unfiltered GCSettings.render = 2; // Unfiltered
GCSettings.widescreen = 0; // no aspect ratio correction GCSettings.widescreen = 0; // no aspect ratio correction
GCSettings.FilterMethod = FILTER_NONE; // no hq2x
GCSettings.xshift = 0; // video shift GCSettings.xshift = 0; // video shift
GCSettings.yshift = 0; GCSettings.yshift = 0;

View File

@ -341,7 +341,7 @@ main(int argc, char *argv[])
#ifdef DEBUG_WII #ifdef DEBUG_WII
DEBUG_Init(GDBSTUB_DEVICE_USB, 1); // init debugging DEBUG_Init(GDBSTUB_DEVICE_USB, 1); // init debugging
_break(); //_break();
#endif #endif
InitDeviceThread(); InitDeviceThread();

View File

@ -15,6 +15,7 @@
#define _SNES9XGX_H_ #define _SNES9XGX_H_
#include "snes9x.h" #include "snes9x.h"
#include "filter.h"
#define APPNAME "Snes9x GX" #define APPNAME "Snes9x GX"
#define APPVERSION "009" #define APPVERSION "009"
@ -62,6 +63,7 @@ struct SGCSettings{
float ZoomLevel; // zoom amount float ZoomLevel; // zoom amount
int VerifySaves; int VerifySaves;
int render; // 0 - original, 1 - filtered, 2 - unfiltered int render; // 0 - original, 1 - filtered, 2 - unfiltered
int FilterMethod; // convert to RenderFilter
int Superscope; int Superscope;
int Mouse; int Mouse;
int Justifier; int Justifier;

View File

@ -24,10 +24,12 @@
#include "aram.h" #include "aram.h"
#include "snes9xGX.h" #include "snes9xGX.h"
#include "filter.h"
#include "gui.h" #include "gui.h"
/*** Snes9x GFX Buffer ***/ /*** Snes9x GFX Buffer ***/
static unsigned char snes9xgfx[1024 * 512 * 2]; static unsigned char snes9xgfx[EXT_PITCH * EXT_HEIGHT]; // changed.
unsigned char filtermem[512 * MAX_SNES_HEIGHT * 4]; // only want ((512*2) X (239*2))
/*** 2D Video ***/ /*** 2D Video ***/
unsigned int *xfb[2] = { NULL, NULL }; // Double buffered unsigned int *xfb[2] = { NULL, NULL }; // Double buffered
@ -39,10 +41,10 @@ extern u32* backdrop;
/*** GX ***/ /*** GX ***/
#define TEX_WIDTH 512 #define TEX_WIDTH 512
#define TEX_HEIGHT 512 #define TEX_HEIGHT 512
static unsigned char texturemem[TEX_WIDTH * (TEX_HEIGHT + 8) * 2] ATTRIBUTE_ALIGN (32);
#define DEFAULT_FIFO_SIZE 256 * 1024 #define DEFAULT_FIFO_SIZE 256 * 1024
unsigned int copynow = GX_FALSE; unsigned int copynow = GX_FALSE;
static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32); static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] ATTRIBUTE_ALIGN (32);
static unsigned char texturemem[TEX_WIDTH * (TEX_HEIGHT + 8)] ATTRIBUTE_ALIGN (32);
GXTexObj texobj; GXTexObj texobj;
Mtx view; Mtx view;
static int vwidth, vheight, oldvwidth, oldvheight; static int vwidth, vheight, oldvwidth, oldvheight;
@ -237,6 +239,8 @@ static GXRModeObj TV_448i =
} }
}; };
static GXRModeObj TV_Custom;
/* TV Modes table */ /* TV Modes table */
static GXRModeObj *tvmodes[4] = { static GXRModeObj *tvmodes[4] = {
&TV_239p, &TV_478i, /* Snes PAL video modes */ &TV_239p, &TV_478i, /* Snes PAL video modes */
@ -427,6 +431,51 @@ UpdatePadsCB ()
PAD_ScanPads(); PAD_ScanPads();
} }
/****************************************************************************
* MakeTexture
*
* - modified for a buffer with an offset (border)
****************************************************************************/
static void
MakeTexture (const void *src, void *dst, s32 width, s32 height)
{
register u32 tmp0 = 0, tmp1 = 0, tmp2 = 0, tmp3 = 0;
__asm__ __volatile__ (" srwi %6,%6,2\n"
" srwi %7,%7,2\n"
" subi %3,%4,4\n"
" mr %4,%3\n"
" subi %4,%4,4\n"
"2: mtctr %6\n"
" mr %0,%5\n"
//
"1: lwz %1,0(%5)\n" //1
" stwu %1,8(%4)\n"
" lwz %2,4(%5)\n" //1
" stwu %2,8(%3)\n"
" lwz %1,1032(%5)\n" //2
" stwu %1,8(%4)\n"
" lwz %2,1036(%5)\n" //2
" stwu %2,8(%3)\n"
" lwz %1,2064(%5)\n" //3
" stwu %1,8(%4)\n"
" lwz %2,2068(%5)\n" //3
" stwu %2,8(%3)\n"
" lwz %1,3096(%5)\n" //4
" stwu %1,8(%4)\n"
" lwz %2,3100(%5)\n" //4
" stwu %2,8(%3)\n"
" addi %5,%5,8\n"
" bdnz 1b\n"
" addi %5,%0,4128\n" //5
" subic. %7,%7,1\n"
" bne 2b"
// regs 0-7
:"=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2),
"=&r" (tmp3), "+r" (dst):"r" (src), "r" (width),
"r" (height));
}
/**************************************************************************** /****************************************************************************
* InitGCVideo * InitGCVideo
* *
@ -549,6 +598,8 @@ InitGCVideo ()
draw_init (); draw_init ();
InitLUTs(); // init LUTs for hq2x
InitVideoThread (); InitVideoThread ();
// Finally, the video is up and ready for use :) // Finally, the video is up and ready for use :)
@ -566,7 +617,7 @@ ResetVideo_Emu ()
Mtx44 p; Mtx44 p;
int i = -1; int i = -1;
if (GCSettings.render == 0) // original render mode if (GCSettings.render == 0 || GCSettings.FilterMethod != FILTER_NONE) // original render mode or hq2x
{ {
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
@ -574,6 +625,19 @@ ResetVideo_Emu ()
break; break;
} }
rmode = tvmodes[i]; rmode = tvmodes[i];
// hack to fix video output for hq2x
if (GCSettings.FilterMethod != FILTER_NONE)
{
memcpy(&TV_Custom, tvmodes[i], sizeof(TV_Custom));
rmode = &TV_Custom;
rmode->fbWidth = 512;
rmode->efbHeight *= 2;
rmode->xfbHeight *= 2;
rmode->xfbMode = VI_XFBMODE_DF;
rmode->viTVMode |= VI_INTERLACE;
}
} }
else else
{ {
@ -652,6 +716,7 @@ ResetVideo_Menu ()
***************************************************************************/ ***************************************************************************/
uint32 prevRenderedFrameCount = 0; uint32 prevRenderedFrameCount = 0;
extern bool CheckVideo; extern bool CheckVideo;
int fscale;
void void
update_video (int width, int height) update_video (int width, int height)
@ -675,10 +740,17 @@ update_video (int width, int height)
{ {
int xscale, yscale; int xscale, yscale;
fscale = GetFilterScale((RenderFilter)GCSettings.FilterMethod);
ResetVideo_Emu (); // reset video to emulator rendering settings ResetVideo_Emu (); // reset video to emulator rendering settings
/** Update scaling **/ /** Update scaling **/
if (GCSettings.render == 0) // original render mode if (GCSettings.FilterMethod != FILTER_NONE) // hq2x filters
{
xscale = vwidth;
yscale = vheight;
}
else if (GCSettings.render == 0) // original render mode
{ {
xscale = 256; xscale = 256;
yscale = vheight / 2; yscale = vheight / 2;
@ -704,7 +776,8 @@ update_video (int width, int height)
DCFlushRange (square, 32); // update memory BEFORE the GPU accesses it! DCFlushRange (square, 32); // update memory BEFORE the GPU accesses it!
draw_init (); draw_init ();
GX_InitTexObj (&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE); // initialize the texture obj we are going to use // initialize the texture obj we are going to use
GX_InitTexObj (&texobj, texturemem, vwidth*fscale, vheight*fscale, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
if (GCSettings.render == 0 || GCSettings.render == 2) if (GCSettings.render == 0 || GCSettings.render == 2)
GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF GX_InitTexObjLOD(&texobj,GX_NEAR,GX_NEAR_MIP_NEAR,2.5,9.0,0.0,GX_FALSE,GX_FALSE,GX_ANISO_1); // original/unfiltered video mode: force texture filtering OFF
@ -721,7 +794,14 @@ update_video (int width, int height)
CheckVideo = 0; CheckVideo = 0;
} }
MakeTexture565((char *) GFX.Screen, (char *) texturemem, vwidth, vheight); // convert image to texture // convert image to texture
if (GCSettings.FilterMethod != FILTER_NONE)
{
FilterMethod ((uint8*) GFX.Screen, EXT_PITCH, (uint8*) filtermem, vwidth*fscale*2, vwidth, vheight);
MakeTexture565((char *) filtermem, (char *) texturemem, vwidth*fscale, vheight*fscale);
} else {
MakeTexture((char *) GFX.Screen, (char *) texturemem, vwidth, vheight);
}
DCFlushRange (texturemem, TEX_WIDTH * TEX_HEIGHT * 2); // update the texture memory DCFlushRange (texturemem, TEX_WIDTH * TEX_HEIGHT * 2); // update the texture memory
GX_InvalidateTexAll (); GX_InvalidateTexAll ();
@ -797,6 +877,8 @@ showscreen ()
void void
setGFX () setGFX ()
{ {
GFX.Screen = (unsigned short *) snes9xgfx; GFX.Pitch = EXT_PITCH;
GFX.Pitch = 1024; GFX.Screen = (uint16*)(snes9xgfx + EXT_OFFSET);
memset (snes9xgfx, 0, sizeof(snes9xgfx));
} }