1 | /*****************************************************************************\ |
2 | Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. |
3 | This file is licensed under the Snes9x License. |
4 | For further information, consult the LICENSE file in the root directory. |
5 | \*****************************************************************************/ |
6 | |
7 | #include "snes9x.h" |
8 | #include "2xsai.h" |
9 | |
10 | #define ALL_COLOR_MASK (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) |
11 | |
12 | #define colorMask (((~RGB_LOW_BITS_MASK & ALL_COLOR_MASK) << 16) | (~RGB_LOW_BITS_MASK & ALL_COLOR_MASK)) |
13 | #define qcolorMask (((~TWO_LOW_BITS_MASK & ALL_COLOR_MASK) << 16) | (~TWO_LOW_BITS_MASK & ALL_COLOR_MASK)) |
14 | #define lowPixelMask ((RGB_LOW_BITS_MASK << 16) | RGB_LOW_BITS_MASK) |
15 | #define qlowpixelMask ((TWO_LOW_BITS_MASK << 16) | TWO_LOW_BITS_MASK) |
16 | |
17 | static inline int GetResult (uint32, uint32, uint32, uint32); |
18 | static inline int GetResult1 (uint32, uint32, uint32, uint32, uint32); |
19 | static inline int GetResult2 (uint32, uint32, uint32, uint32, uint32); |
20 | static inline uint32 INTERPOLATE (uint32, uint32); |
21 | static inline uint32 Q_INTERPOLATE (uint32, uint32, uint32, uint32); |
22 | |
23 | |
24 | static inline int GetResult (uint32 A, uint32 B, uint32 C, uint32 D) |
25 | { |
26 | int x = 0, y = 0, r = 0; |
27 | |
28 | if (A == C) x += 1; else if (B == C) y += 1; |
29 | if (A == D) x += 1; else if (B == D) y += 1; |
30 | if (x <= 1) r += 1; |
31 | if (y <= 1) r -= 1; |
32 | |
33 | return (r); |
34 | } |
35 | |
36 | static inline int GetResult1 (uint32 A, uint32 B, uint32 C, uint32 D, uint32 E) |
37 | { |
38 | int x = 0, y = 0, r = 0; |
39 | |
40 | if (A == C) x += 1; else if (B == C) y += 1; |
41 | if (A == D) x += 1; else if (B == D) y += 1; |
42 | if (x <= 1) r += 1; |
43 | if (y <= 1) r -= 1; |
44 | |
45 | return (r); |
46 | } |
47 | |
48 | static inline int GetResult2 (uint32 A, uint32 B, uint32 C, uint32 D, uint32 E) |
49 | { |
50 | int x = 0, y = 0, r = 0; |
51 | |
52 | if (A == C) x += 1; else if (B == C) y += 1; |
53 | if (A == D) x += 1; else if (B == D) y += 1; |
54 | if (x <= 1) r -= 1; |
55 | if (y <= 1) r += 1; |
56 | |
57 | return (r); |
58 | } |
59 | |
60 | static inline uint32 INTERPOLATE (uint32 A, uint32 B) |
61 | { |
62 | return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask)); |
63 | } |
64 | |
65 | static inline uint32 Q_INTERPOLATE (uint32 A, uint32 B, uint32 C, uint32 D) |
66 | { |
67 | uint32 x = ((A & qcolorMask) >> 2) + ((B & qcolorMask) >> 2) + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2); |
68 | uint32 y = (A & qlowpixelMask) + (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask); |
69 | |
70 | y = (y >> 2) & qlowpixelMask; |
71 | |
72 | return (x + y); |
73 | } |
74 | |
75 | bool8 S9xBlit2xSaIFilterInit (void) |
76 | { |
77 | return (TRUE); |
78 | } |
79 | |
80 | void S9xBlit2xSaIFilterDeinit (void) |
81 | { |
82 | return; |
83 | } |
84 | |
85 | void SuperEagle (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) |
86 | { |
87 | uint16 *bP; |
88 | uint32 *dP; |
89 | uint32 nextline = srcRowBytes >> 1; |
90 | |
91 | for (; height; height--) |
92 | { |
93 | bP = (uint16 *) srcPtr; |
94 | dP = (uint32 *) dstPtr; |
95 | |
96 | for (int i = 0; i < width; i++) |
97 | { |
98 | uint32 color1, color2, color3, color4, color5, color6; |
99 | uint32 colorA1, colorA2, colorB1, colorB2, colorS1, colorS2; |
100 | uint32 product1a, product1b, product2a, product2b; |
101 | |
102 | colorB1 = *(bP - nextline ); |
103 | colorB2 = *(bP - nextline + 1); |
104 | |
105 | color4 = *(bP - 1); |
106 | color5 = *(bP ); |
107 | color6 = *(bP + 1); |
108 | colorS2 = *(bP + 2); |
109 | |
110 | color1 = *(bP + nextline - 1); |
111 | color2 = *(bP + nextline ); |
112 | color3 = *(bP + nextline + 1); |
113 | colorS1 = *(bP + nextline + 2); |
114 | |
115 | colorA1 = *(bP + nextline + nextline ); |
116 | colorA2 = *(bP + nextline + nextline + 1); |
117 | |
118 | if (color2 == color6 && color5 != color3) |
119 | { |
120 | product1b = product2a = color2; |
121 | if ((color1 == color2 && color6 == colorS2) || (color2 == colorA1 && color6 == colorB2)) |
122 | { |
123 | product1a = INTERPOLATE(color2, color5); |
124 | product1a = INTERPOLATE(color2, product1a); |
125 | product2b = INTERPOLATE(color2, color3); |
126 | product2b = INTERPOLATE(color2, product2b); |
127 | } |
128 | else |
129 | { |
130 | product1a = INTERPOLATE(color5, color6); |
131 | product2b = INTERPOLATE(color2, color3); |
132 | } |
133 | } |
134 | else |
135 | if (color5 == color3 && color2 != color6) |
136 | { |
137 | product2b = product1a = color5; |
138 | if ((colorB1 == color5 && color3 == colorA2) || (color4 == color5 && color3 == colorS1)) |
139 | { |
140 | product1b = INTERPOLATE(color5, color6); |
141 | product1b = INTERPOLATE(color5, product1b); |
142 | product2a = INTERPOLATE(color5, color2); |
143 | product2a = INTERPOLATE(color5, product2a); |
144 | } |
145 | else |
146 | { |
147 | product1b = INTERPOLATE(color5, color6); |
148 | product2a = INTERPOLATE(color2, color3); |
149 | } |
150 | } |
151 | else |
152 | if (color5 == color3 && color2 == color6 && color5 != color6) |
153 | { |
154 | int r = 0; |
155 | |
156 | r += GetResult(color6, color5, color1, colorA1); |
157 | r += GetResult(color6, color5, color4, colorB1); |
158 | r += GetResult(color6, color5, colorA2, colorS1); |
159 | r += GetResult(color6, color5, colorB2, colorS2); |
160 | |
161 | if (r > 0) |
162 | { |
163 | product1b = product2a = color2; |
164 | product1a = product2b = INTERPOLATE(color5, color6); |
165 | } |
166 | else |
167 | if (r < 0) |
168 | { |
169 | product2b = product1a = color5; |
170 | product1b = product2a = INTERPOLATE(color5, color6); |
171 | } |
172 | else |
173 | { |
174 | product2b = product1a = color5; |
175 | product1b = product2a = color2; |
176 | } |
177 | } |
178 | else |
179 | { |
180 | if ((color2 == color5) || (color3 == color6)) |
181 | { |
182 | product1a = color5; |
183 | product2a = color2; |
184 | product1b = color6; |
185 | product2b = color3; |
186 | } |
187 | else |
188 | { |
189 | product1b = product1a = INTERPOLATE(color5, color6); |
190 | product1a = INTERPOLATE(color5, product1a); |
191 | product1b = INTERPOLATE(color6, product1b); |
192 | |
193 | product2a = product2b = INTERPOLATE(color2, color3); |
194 | product2a = INTERPOLATE(color2, product2a); |
195 | product2b = INTERPOLATE(color3, product2b); |
196 | } |
197 | } |
198 | |
199 | #ifdef MSB_FIRST |
200 | product1a = (product1a << 16) | product1b; |
201 | product2a = (product2a << 16) | product2b; |
202 | #else |
203 | product1a = product1a | (product1b << 16); |
204 | product2a = product2a | (product2b << 16); |
205 | #endif |
206 | |
207 | *(dP) = product1a; |
208 | *(dP + (dstRowBytes >> 2)) = product2a; |
209 | |
210 | bP++; |
211 | dP++; |
212 | } |
213 | |
214 | dstPtr += dstRowBytes << 1; |
215 | srcPtr += srcRowBytes; |
216 | } |
217 | } |
218 | |
219 | void _2xSaI (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) |
220 | { |
221 | uint16 *bP; |
222 | uint32 *dP; |
223 | uint32 nextline = srcRowBytes >> 1; |
224 | |
225 | for (; height; height--) |
226 | { |
227 | bP = (uint16 *) srcPtr; |
228 | dP = (uint32 *) dstPtr; |
229 | |
230 | for (int i = 0; i < width; i++) |
231 | { |
232 | uint32 colorA, colorB, colorC, colorD, colorE, colorF, colorG, colorH, colorI, colorJ, colorK, colorL, colorM, colorN, colorO, colorP; |
233 | uint32 product, product1, product2; |
234 | |
235 | colorI = *(bP - nextline - 1); |
236 | colorE = *(bP - nextline ); |
237 | colorF = *(bP - nextline + 1); |
238 | colorJ = *(bP - nextline + 2); |
239 | |
240 | colorG = *(bP - 1); |
241 | colorA = *(bP ); |
242 | colorB = *(bP + 1); |
243 | colorK = *(bP + 2); |
244 | |
245 | colorH = *(bP + nextline - 1); |
246 | colorC = *(bP + nextline ); |
247 | colorD = *(bP + nextline + 1); |
248 | colorL = *(bP + nextline + 2); |
249 | |
250 | colorM = *(bP + nextline + nextline - 1); |
251 | colorN = *(bP + nextline + nextline ); |
252 | colorO = *(bP + nextline + nextline + 1); |
253 | colorP = *(bP + nextline + nextline + 2); |
254 | |
255 | if ((colorA == colorD) && (colorB != colorC)) |
256 | { |
257 | if (((colorA == colorE) && (colorB == colorL)) || ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ))) |
258 | product = colorA; |
259 | else |
260 | product = INTERPOLATE(colorA, colorB); |
261 | |
262 | if (((colorA == colorG) && (colorC == colorO)) || ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM))) |
263 | product1 = colorA; |
264 | else |
265 | product1 = INTERPOLATE(colorA, colorC); |
266 | |
267 | product2 = colorA; |
268 | } |
269 | else |
270 | if ((colorB == colorC) && (colorA != colorD)) |
271 | { |
272 | if (((colorB == colorF) && (colorA == colorH)) || ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI))) |
273 | product = colorB; |
274 | else |
275 | product = INTERPOLATE(colorA, colorB); |
276 | |
277 | if (((colorC == colorH) && (colorA == colorF)) || ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI))) |
278 | product1 = colorC; |
279 | else |
280 | product1 = INTERPOLATE(colorA, colorC); |
281 | |
282 | product2 = colorB; |
283 | } |
284 | else |
285 | if ((colorA == colorD) && (colorB == colorC)) |
286 | { |
287 | if (colorA == colorB) |
288 | { |
289 | product = colorA; |
290 | product1 = colorA; |
291 | product2 = colorA; |
292 | } |
293 | else |
294 | { |
295 | int r = 0; |
296 | |
297 | product1 = INTERPOLATE(colorA, colorC); |
298 | product = INTERPOLATE(colorA, colorB); |
299 | |
300 | r += GetResult1(colorA, colorB, colorG, colorE, colorI); |
301 | r += GetResult2(colorB, colorA, colorK, colorF, colorJ); |
302 | r += GetResult2(colorB, colorA, colorH, colorN, colorM); |
303 | r += GetResult1(colorA, colorB, colorL, colorO, colorP); |
304 | |
305 | if (r > 0) |
306 | product2 = colorA; |
307 | else |
308 | if (r < 0) |
309 | product2 = colorB; |
310 | else |
311 | product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD); |
312 | } |
313 | } |
314 | else |
315 | { |
316 | product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD); |
317 | |
318 | if ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ)) |
319 | product = colorA; |
320 | else |
321 | if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) |
322 | product = colorB; |
323 | else |
324 | product = INTERPOLATE(colorA, colorB); |
325 | |
326 | if ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM)) |
327 | product1 = colorA; |
328 | else |
329 | if ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI)) |
330 | product1 = colorC; |
331 | else |
332 | product1 = INTERPOLATE(colorA, colorC); |
333 | } |
334 | |
335 | #ifdef MSB_FIRST |
336 | product = (colorA << 16) | product; |
337 | product1 = (product1 << 16) | product2; |
338 | #else |
339 | product = colorA | (product << 16); |
340 | product1 = product1 | (product2 << 16); |
341 | #endif |
342 | |
343 | *(dP) = product; |
344 | *(dP + (dstRowBytes >> 2)) = product1; |
345 | |
346 | bP++; |
347 | dP++; |
348 | } |
349 | |
350 | dstPtr += dstRowBytes << 1; |
351 | srcPtr += srcRowBytes; |
352 | } |
353 | } |
354 | |
355 | void Super2xSaI (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) |
356 | { |
357 | uint16 *bP; |
358 | uint32 *dP; |
359 | uint32 nextline = srcRowBytes >> 1; |
360 | |
361 | for (; height; height--) |
362 | { |
363 | bP = (uint16 *) srcPtr; |
364 | dP = (uint32 *) dstPtr; |
365 | |
366 | for (int i = 0; i < width; i++) |
367 | { |
368 | uint32 color1, color2, color3, color4, color5, color6; |
369 | uint32 colorA0, colorA1, colorA2, colorA3, colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; |
370 | uint32 product1a, product1b, product2a, product2b; |
371 | |
372 | colorB0 = *(bP - nextline - 1); |
373 | colorB1 = *(bP - nextline ); |
374 | colorB2 = *(bP - nextline + 1); |
375 | colorB3 = *(bP - nextline + 2); |
376 | |
377 | color4 = *(bP - 1); |
378 | color5 = *(bP ); |
379 | color6 = *(bP + 1); |
380 | colorS2 = *(bP + 2); |
381 | |
382 | color1 = *(bP + nextline - 1); |
383 | color2 = *(bP + nextline ); |
384 | color3 = *(bP + nextline + 1); |
385 | colorS1 = *(bP + nextline + 2); |
386 | |
387 | colorA0 = *(bP + nextline + nextline - 1); |
388 | colorA1 = *(bP + nextline + nextline ); |
389 | colorA2 = *(bP + nextline + nextline + 1); |
390 | colorA3 = *(bP + nextline + nextline + 2); |
391 | |
392 | if (color2 == color6 && color5 != color3) |
393 | product2b = product1b = color2; |
394 | else |
395 | if (color5 == color3 && color2 != color6) |
396 | product2b = product1b = color5; |
397 | else |
398 | if (color5 == color3 && color2 == color6 && color5 != color6) |
399 | { |
400 | int r = 0; |
401 | |
402 | r += GetResult(color6, color5, color1, colorA1); |
403 | r += GetResult(color6, color5, color4, colorB1); |
404 | r += GetResult(color6, color5, colorA2, colorS1); |
405 | r += GetResult(color6, color5, colorB2, colorS2); |
406 | |
407 | if (r > 0) |
408 | product2b = product1b = color6; |
409 | else |
410 | if (r < 0) |
411 | product2b = product1b = color5; |
412 | else |
413 | product2b = product1b = INTERPOLATE(color5, color6); |
414 | } |
415 | else |
416 | { |
417 | if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) |
418 | product2b = Q_INTERPOLATE(color3, color3, color3, color2); |
419 | else |
420 | if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) |
421 | product2b = Q_INTERPOLATE(color2, color2, color2, color3); |
422 | else |
423 | product2b = INTERPOLATE(color2, color3); |
424 | |
425 | if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) |
426 | product1b = Q_INTERPOLATE(color6, color6, color6, color5); |
427 | else |
428 | if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) |
429 | product1b = Q_INTERPOLATE(color6, color5, color5, color5); |
430 | else |
431 | product1b = INTERPOLATE (color5, color6); |
432 | } |
433 | |
434 | if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) |
435 | product2a = INTERPOLATE(color2, color5); |
436 | else |
437 | if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) |
438 | product2a = INTERPOLATE(color2, color5); |
439 | else |
440 | product2a = color2; |
441 | |
442 | if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) |
443 | product1a = INTERPOLATE(color2, color5); |
444 | else |
445 | if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) |
446 | product1a = INTERPOLATE(color2, color5); |
447 | else |
448 | product1a = color5; |
449 | |
450 | #ifdef MSB_FIRST |
451 | product1a = (product1a << 16) | product1b; |
452 | product2a = (product2a << 16) | product2b; |
453 | #else |
454 | product1a = product1a | (product1b << 16); |
455 | product2a = product2a | (product2b << 16); |
456 | #endif |
457 | |
458 | *(dP) = product1a; |
459 | *(dP +(dstRowBytes >> 2)) = product2a; |
460 | |
461 | bP++; |
462 | dP++; |
463 | } |
464 | |
465 | dstPtr += dstRowBytes << 1; |
466 | srcPtr += srcRowBytes; |
467 | } |
468 | } |
469 | |