1 // epxb, epxc filter, added by regret
2 // source from Snes9X rerecording (http://code.google.com/p/snes9x151-rerecording/)
3 
4 typedef unsigned char uint8;
5 typedef unsigned short uint16;
6 typedef signed char int8;
7 typedef short int16;
8 typedef int int32;
9 typedef unsigned int uint32;
10 # ifdef __GNUC__  /* long long is not part of ISO C++ */
11 __extension__
12 # endif
13 typedef long long int64;
14 typedef unsigned long long uint64;
15 
16 #define Mask_2	0x07E0	// 00000 111111 00000
17 #define Mask13	0xF81F	// 11111 000000 11111
18 #define Mask_1	0x001F	// 00000 000000 11111
19 #define Mask_3	0xF800	// 11111 000000 00000
20 #define CONVERT_16_TO_32(pixel) \
21         (((((pixel) >> 11)        ) << /*RedShift+3*/  19) | \
22          ((((pixel) >> 6)   & 0x1f) << /*GreenShift+3*/11) | \
23           (((pixel)         & 0x1f) << /*BlueShift+3*/ 3))
24 
25 #define Interp01(c1, c2) \
26 	((((c1) == (c2)) ? (c1) : \
27 	(((((((c1) & Mask_2) *  3) + ((c2) & Mask_2)) >> 2) & Mask_2) + \
28 	 ((((((c1) & Mask13) *  3) + ((c2) & Mask13)) >> 2) & Mask13))))
29 
30 #ifdef LSB_FIRST
31 	#define TWO_PIX(left,right) ((left) | ((right) << 16))
32 	#define THREE_PIX(left,middle,right) uint48((left) | ((middle) << 16), (right))
33 	#define TWO_PIX_32(left,right) (CONVERT_16_TO_32(left) | ((uint64)CONVERT_16_TO_32(right) << 32))
34 	#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))
35 #else
36 	#define TWO_PIX(left,right) ((right) | ((left) << 16))
37 	#define THREE_PIX(left,middle,right) uint48((middle) | ((left) << 16), (right)) // is this right?
38 //	#define THREE_PIX(left,middle,right) uint48((right) | ((middle) << 16), (left)) // or this?
39 #endif
40 
41 // shared EPX-type loop macros
42 // All of these parameters will be constant values,
43 // so I hope the compiler is smart enough to optimize away "if(0) ..."
44 
45 #define DrawRows(scale,diags)            \
46 	{                                    \
47 		h = srcHeight - 1;               \
48 		DoRow(0,1,scale,diags);          \
49 		for (h = srcHeight - 2; h; h--)  \
50 			DoRow(1,1,scale,diags);      \
51 		DoRow(1,0,scale,diags);          \
52 	}
53 
54 #define DoRow(topValid,botValid,scale,diags)              \
55 	{                                                     \
56 		w = srcWidth - 1;                                 \
57 		InitLine(topValid,botValid,scale,diags);          \
58 		DrawPix(0,topValid,0,botValid);                   \
59 		for (w = srcWidth - 2; w; w--)                    \
60 		{                                                 \
61 			NextPixel(topValid,botValid,1,diags);         \
62 			DrawPix(topValid,topValid,botValid,botValid); \
63 		}                                                 \
64 		NextPixel(topValid,botValid,0,diags);             \
65 		DrawPix(topValid,0,botValid,0);                   \
66 		srcPtr += srcPitch;                               \
67 		dstPtr += dstPitch * scale;                       \
68 	}
69 
70 #define InitLine(topValid, botValid, scale, diags)                \
71 	{                                                             \
72 		if(topValid) uP  = (uint16 *) (srcPtr - srcPitch);        \
73 		if(botValid) lP  = (uint16 *) (srcPtr + srcPitch);        \
74 					 sP  = (uint16 *) srcPtr;                     \
75 					 dP1 = (destType *) dstPtr;                   \
76 					 dP2 = (destType *) (dstPtr + dstPitch);      \
77 		if(scale>=3) dP3 = (destType *) (dstPtr + (dstPitch<<1)); \
78 		if(topValid) colorD = *uP++;                              \
79 		if(botValid) colorB = *lP++;                              \
80 					colorX = *sP++;                               \
81 					colorC = *sP;                                 \
82 		if(diags) if(topValid) colorH = *uP;                      \
83 		if(diags) if(botValid) colorG = *lP;                      \
84 	}
85 
86 #define NextPixel(topValid, botValid, rightValid, diags)      \
87 	{                                                         \
88 		colorA = colorX;                                      \
89 		colorX = colorC;                                      \
90 		if(rightValid) colorC = *++sP;                        \
91 		if(diags) {                                           \
92 			if(botValid){                                     \
93 				colorF = colorB;                              \
94 				colorB = colorG;                              \
95 				if(rightValid) colorG = *++lP;                \
96 			}                                                 \
97 			if(topValid){                                     \
98 				colorE = colorD;                              \
99 				colorD = colorH;                              \
100 				if(rightValid) colorH = *++uP;                \
101 			}                                                 \
102 		} else {                                              \
103 			if(botValid) colorB = *lP++;                      \
104 			if(topValid) colorD = *uP++;                      \
105 		}                                                     \
106 	}
107 
108 #define DrawInit(scale,uintDest)                                                            \
109 	uint8 *srcPtr = src, *dstPtr = dst;                                     \
110 	const uint32 srcPitch = srcpitch, dstPitch = dstpitch;                                \
111 	const uint32 srcHeight = nHeight;                              \
112 	const uint32 srcWidth = nWidth;                               \
113 	uint16	colorX, colorA, colorB, colorC, colorD, colorE=0, colorF=0, colorG=0, colorH=0; \
114 	uint16	*sP, *uP, *lP;                                                                  \
115 	typedef uintDest destType;                                                              \
116 	destType *dP1, *dP2, *dP3=0;                                                            \
117 	int		w, h;
118 
119 // code for improved 2X EPX, which tends to do better with diagonal edges than regular EPX
RenderEPXB(unsigned char * src,unsigned int srcpitch,unsigned char * dst,unsigned int dstpitch,int nWidth,int nHeight,int vidDepth)120 void RenderEPXB(unsigned char *src, unsigned int srcpitch, unsigned char *dst, unsigned int dstpitch, int nWidth, int nHeight, int vidDepth)
121 {
122 	// E D H
123 	// A X C
124 	// F B G
125 	#define DrawPix(on00,on01,on10,on11) /* on00 on01 */                                                                                                       \
126 	{                                    /* on10 on11 */                                                                                                       \
127 		if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX))                                                                                     \
128 		&& (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX))                                                                                      \
129 		&& ((!on00||!on01||!on10|!on11) ||                                                                                                                     \
130 			((colorX == colorA) || (colorX == colorB) || (colorX == colorC) || (colorX == colorD) || /* diagonal    */                                         \
131 			 (((colorE != colorG) || (colorX == colorF) || (colorX == colorH)) &&                    /*  edge       */                                         \
132 			  ((colorF != colorH) || (colorX == colorE) || (colorX == colorG))))))                   /*   smoothing */                                         \
133 		{                                                                                                                                                      \
134 			*dP1++ = _TWO_PIX((on00 && colorD == colorA && (colorX != colorE || colorX != colorG || colorD != colorH || colorA != colorF)) ? colorD : colorX,  \
135 							  (on01 && colorC == colorD && (colorX != colorH || colorX != colorF || colorC != colorG || colorD != colorE)) ? colorC : colorX); \
136 			*dP2++ = _TWO_PIX((on10 && colorA == colorB && (colorX != colorF || colorX != colorH || colorA != colorE || colorB != colorG)) ? colorA : colorX,  \
137 							  (on11 && colorB == colorC && (colorX != colorG || colorX != colorE || colorB != colorF || colorC != colorH)) ? colorB : colorX); \
138 		} else {                                                                                                                                               \
139 			*dP1++ = _TWO_PIX(colorX, colorX);                                                                                                                 \
140 			*dP2++ = _TWO_PIX(colorX, colorX);                                                                                                                 \
141 		}                                                                                                                                                      \
142 	}
143 
144 	// again, this supports 32-bit or 16-bit rendering
145 	if(vidDepth == 32)
146 	{
147 #define _TWO_PIX TWO_PIX_32
148 		DrawInit(2,uint64);
149 		DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels
150 #undef _TWO_PIX
151 	}
152 	else
153 	{
154 #define _TWO_PIX TWO_PIX
155 		DrawInit(2,uint32);
156 		DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels
157 #undef _TWO_PIX
158 	}
159 
160 	#undef DrawPix
161 }
162 
163 #define Interp44(c1, c2, c3, c4) \
164 	((((((c1) & Mask_2) * 5 + ((c2) & Mask_2) + ((c3) & Mask_2) + ((c4) & Mask_2)) >> 3) & Mask_2) + \
165 	 (((((c1) & Mask13) * 5 + ((c2) & Mask13) + ((c3) & Mask13) + ((c4) & Mask13)) >> 3) & Mask13))
166 
167 // EPX3 scaled down to 2X
RenderEPXC(unsigned char * src,unsigned int srcpitch,unsigned char * dst,unsigned int dstpitch,int nWidth,int nHeight,int vidDepth)168 void RenderEPXC(unsigned char *src, unsigned int srcpitch, unsigned char *dst, unsigned int dstpitch, int nWidth, int nHeight, int vidDepth)
169 {
170 	// E D H
171 	// A X C
172 	// F B G
173 	#define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \
174 	{                                    /* on10 on11 */ \
175 		if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \
176 		 && (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX))) \
177 		{ \
178 			const bool XnE = colorX != colorE; \
179 			const bool XnF = colorX != colorF; \
180 			const bool XnG = colorX != colorG; \
181 			const bool XnH = colorX != colorH; \
182 			const bool DA = on00 && colorD == colorA && (XnE || XnG || colorD != colorH || colorA != colorF); \
183 			const bool AB = on10 && colorA == colorB && (XnF || XnH || colorA != colorE || colorB != colorG); \
184 			const bool BC = on11 && colorB == colorC && (XnG || XnE || colorB != colorF || colorC != colorH); \
185 			const bool CD = on01 && colorC == colorD && (XnH || XnF || colorC != colorG || colorD != colorE); \
186 			if (!on00||!on01||!on10||!on11 || ((colorA != colorC) && (colorB != colorD) && \
187 				((colorX == colorA) || (colorX==colorB) || (colorX==colorC) || (colorX==colorD) || (colorX==colorE) || (colorX==colorF) || (colorX==colorG) || (colorX==colorH)))) \
188 			{ \
189 				const uint16 colorAA = on00&&on10 && ((DA && XnF) || (AB && XnE)) ? colorA : colorX; \
190 				const uint16 colorBB = on10&&on11 && ((AB && XnG) || (BC && XnF)) ? colorB : colorX; \
191 				const uint16 colorCC = on01&&on11 && ((BC && XnH) || (CD && XnG)) ? colorC : colorX; \
192 				const uint16 colorDD = on00&&on01 && ((CD && XnE) || (DA && XnH)) ? colorD : colorX; \
193 				*dP1++ = _TWO_PIX(Interp44(on00 && DA ? colorA : colorX, colorDD, colorAA, colorX), Interp44(on01 && CD ? colorC : colorX, colorBB, colorCC, colorX)); \
194 				*dP2++ = _TWO_PIX(Interp44(on10 && AB ? colorA : colorX, colorAA, colorBB, colorX), Interp44(on11 && BC ? colorC : colorX, colorCC, colorDD, colorX)); \
195 			} else { \
196 				*dP1++ = _TWO_PIX(Interp01(colorX, on00 && DA && (colorX!=colorB&&colorX!=colorC) ? colorA : colorX), Interp01(colorX, on01 && CD && (colorX!=colorA&&colorX!=colorB) ? colorC : colorX)); \
197 				*dP2++ = _TWO_PIX(Interp01(colorX, on10 && AB && (colorX!=colorC&&colorX!=colorD) ? colorA : colorX), Interp01(colorX, on11 && BC && (colorX!=colorD&&colorX!=colorA) ? colorC : colorX)); \
198 			} \
199 		} else { \
200 			*dP1++ = _TWO_PIX(colorX, colorX); \
201 			*dP2++ = _TWO_PIX(colorX, colorX); \
202 		} \
203 	}
204 
205 	if(vidDepth == 32)
206 	{
207 #define _TWO_PIX TWO_PIX_32
208 		DrawInit(2,uint64);
209 		DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels
210 #undef _TWO_PIX
211 	}
212 	else
213 	{
214 #define _TWO_PIX TWO_PIX
215 		DrawInit(2,uint32);
216 		DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels
217 #undef _TWO_PIX
218 	}
219 
220 	#undef DrawPix
221 }
222