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 "blit.h"
9
10#define ALL_COLOR_MASK (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK)
11
12#define lowPixelMask (RGB_LOW_BITS_MASK)
13#define qlowPixelMask ((RGB_HI_BITS_MASK >> 3) | TWO_LOW_BITS_MASK)
14#define highBitsMask (ALL_COLOR_MASK & RGB_REMOVE_LOW_BITS_MASK)
15#define colorMask (((~RGB_HI_BITS_MASK & ALL_COLOR_MASK) << 16) | (~RGB_HI_BITS_MASK & ALL_COLOR_MASK))
16
17static snes_ntsc_t *ntsc = NULL;
18static uint8 *XDelta = NULL;
19
20
21bool8 S9xBlitFilterInit (void)
22{
23 XDelta = new uint8[SNES_WIDTH * SNES_HEIGHT_EXTENDED * 4];
24 if (!XDelta)
25 return (FALSE);
26
27 S9xBlitClearDelta();
28
29 return (TRUE);
30}
31
32void S9xBlitFilterDeinit (void)
33{
34 if (XDelta)
35 {
36 delete[] XDelta;
37 XDelta = NULL;
38 }
39}
40
41void S9xBlitClearDelta (void)
42{
43 uint32 *d = (uint32 *) XDelta;
44
45 for (int y = 0; y < SNES_HEIGHT_EXTENDED; y++)
46 for (int x = 0; x < SNES_WIDTH; x++)
47 *d++ = 0x80008000;
48}
49
50bool8 S9xBlitNTSCFilterInit (void)
51{
52 ntsc = (snes_ntsc_t *) malloc(sizeof(snes_ntsc_t));
53 if (!ntsc)
54 return (FALSE);
55
56 snes_ntsc_init(ntsc, &snes_ntsc_composite);
57 return (TRUE);
58}
59
60void S9xBlitNTSCFilterDeinit (void)
61{
62 if (ntsc)
63 {
64 free(ntsc);
65 ntsc = NULL;
66 }
67}
68
69void S9xBlitNTSCFilterSet (const snes_ntsc_setup_t *setup)
70{
71 snes_ntsc_init(ntsc, setup);
72}
73
74void S9xBlitPixSimple1x1 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
75{
76 width <<= 1;
77
78 for (; height; height--)
79 {
80 memcpy(dstPtr, srcPtr, width);
81 srcPtr += srcRowBytes;
82 dstPtr += dstRowBytes;
83 }
84}
85
86void S9xBlitPixSimple1x2 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
87{
88 width <<= 1;
89
90 for (; height; height--)
91 {
92 memcpy(dstPtr, srcPtr, width);
93 dstPtr += dstRowBytes;
94 memcpy(dstPtr, srcPtr, width);
95 srcPtr += srcRowBytes;
96 dstPtr += dstRowBytes;
97 }
98}
99
100void S9xBlitPixSimple2x1 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
101{
102 for (; height; height--)
103 {
104 uint16 *dP = (uint16 *) dstPtr, *bP = (uint16 *) srcPtr;
105
106 for (int i = 0; i < (width >> 1); i++)
107 {
108 *dP++ = *bP;
109 *dP++ = *bP++;
110
111 *dP++ = *bP;
112 *dP++ = *bP++;
113 }
114
115 srcPtr += srcRowBytes;
116 dstPtr += dstRowBytes;
117 }
118}
119
120void S9xBlitPixSimple2x2 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
121{
122 uint8 *dstPtr2 = dstPtr + dstRowBytes, *deltaPtr = XDelta;
123 dstRowBytes <<= 1;
124
125 for (; height; height--)
126 {
127 uint32 *dP1 = (uint32 *) dstPtr, *dP2 = (uint32 *) dstPtr2, *bP = (uint32 *) srcPtr, *xP = (uint32 *) deltaPtr;
128 uint32 currentPixel, lastPixel, currentPixA, currentPixB, colorA, colorB;
129
130 for (int i = 0; i < (width >> 1); i++)
131 {
132 currentPixel = *bP;
133 lastPixel = *xP;
134
135 if (currentPixel != lastPixel)
136 {
137 #ifdef MSB_FIRST
138 colorA = (currentPixel >> 16) & 0xFFFF;
139 colorB = (currentPixel ) & 0xFFFF;
140 #else
141 colorA = (currentPixel ) & 0xFFFF;
142 colorB = (currentPixel >> 16) & 0xFFFF;
143 #endif
144
145 currentPixA = (colorA << 16) | colorA;
146 currentPixB = (colorB << 16) | colorB;
147
148 dP1[0] = currentPixA;
149 dP1[1] = currentPixB;
150 dP2[0] = currentPixA;
151 dP2[1] = currentPixB;
152
153 *xP = *bP;
154 }
155
156 bP++;
157 xP++;
158 dP1 += 2;
159 dP2 += 2;
160 }
161
162 srcPtr += srcRowBytes;
163 deltaPtr += srcRowBytes;
164 dstPtr += dstRowBytes;
165 dstPtr2 += dstRowBytes;
166 }
167}
168
169void S9xBlitPixBlend1x1 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
170{
171 for (; height; height--)
172 {
173 uint16 *dP = (uint16 *) dstPtr, *bP = (uint16 *) srcPtr;
174 uint16 prev, curr;
175
176 prev = *bP;
177
178 for (int i = 0; i < (width >> 1); i++)
179 {
180 curr = *bP++;
181 *dP++ = (prev & curr) + (((prev ^ curr) & highBitsMask) >> 1);
182 prev = curr;
183
184 curr = *bP++;
185 *dP++ = (prev & curr) + (((prev ^ curr) & highBitsMask) >> 1);
186 prev = curr;
187 }
188
189 srcPtr += srcRowBytes;
190 dstPtr += dstRowBytes;
191 }
192}
193
194void S9xBlitPixBlend2x1 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
195{
196 for (; height; height--)
197 {
198 uint16 *dP = (uint16 *) dstPtr, *bP = (uint16 *) srcPtr;
199 uint16 prev, curr;
200
201 prev = *bP;
202
203 for (int i = 0; i < (width >> 1); i++)
204 {
205 curr = *bP++;
206 *dP++ = (prev & curr) + (((prev ^ curr) & highBitsMask) >> 1);
207 *dP++ = curr;
208 prev = curr;
209
210 curr = *bP++;
211 *dP++ = (prev & curr) + (((prev ^ curr) & highBitsMask) >> 1);
212 *dP++ = curr;
213 prev = curr;
214 }
215
216 srcPtr += srcRowBytes;
217 dstPtr += dstRowBytes;
218 }
219}
220
221void S9xBlitPixTV1x2 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
222{
223 uint8 *dstPtr2 = dstPtr + dstRowBytes;
224 dstRowBytes <<= 1;
225
226 for (; height; height--)
227 {
228 uint32 *dP1 = (uint32 *) dstPtr, *dP2 = (uint32 *) dstPtr2, *bP = (uint32 *) srcPtr;
229 uint32 product, darkened;
230
231 for (int i = 0; i < (width >> 1); i++)
232 {
233 product = *dP1++ = *bP++;
234 darkened = (product = (product >> 1) & colorMask);
235 darkened += (product = (product >> 1) & colorMask);
236 *dP2++ = darkened;
237 }
238
239 srcPtr += srcRowBytes;
240 dstPtr += dstRowBytes;
241 dstPtr2 += dstRowBytes;
242 }
243}
244
245void S9xBlitPixTV2x2 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
246{
247 uint8 *dstPtr2 = dstPtr + dstRowBytes, *deltaPtr = XDelta;
248 dstRowBytes <<= 1;
249
250 for (; height; height--)
251 {
252 uint32 *dP1 = (uint32 *) dstPtr, *dP2 = (uint32 *) dstPtr2, *bP = (uint32 *) srcPtr, *xP = (uint32 *) deltaPtr;
253 uint32 currentPixel, nextPixel, currentDelta, nextDelta, colorA, colorB, product, darkened;
254
255 for (int i = 0; i < (width >> 1) - 1; i++)
256 {
257 currentPixel = *bP;
258 currentDelta = *xP;
259 nextPixel = *(bP + 1);
260 nextDelta = *(xP + 1);
261
262 if ((currentPixel != currentDelta) || (nextPixel != nextDelta))
263 {
264 *xP = *bP;
265
266 #ifdef MSB_FIRST
267 colorA = (currentPixel >> 16) & 0xFFFF;
268 colorB = (currentPixel ) & 0xFFFF;
269 #else
270 colorA = (currentPixel ) & 0xFFFF;
271 colorB = (currentPixel >> 16) & 0xFFFF;
272 #endif
273
274 #ifdef MSB_FIRST
275 *dP1 = product = (colorA << 16) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) );
276 #else
277 *dP1 = product = (colorA ) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) << 16);
278 #endif
279
280 darkened = (product = ((product >> 1) & colorMask));
281 darkened += (product = ((product >> 1) & colorMask));
282 darkened += (product >> 1) & colorMask;
283
284 *dP2 = darkened;
285
286 #ifdef MSB_FIRST
287 colorA = (nextPixel >> 16) & 0xFFFF;
288 #else
289 colorA = (nextPixel ) & 0xFFFF;
290 #endif
291
292 #ifdef MSB_FIRST
293 *(dP1 + 1) = product = (colorB << 16) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) );
294 #else
295 *(dP1 + 1) = product = (colorB ) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) << 16);
296 #endif
297
298 darkened = (product = ((product >> 1) & colorMask));
299 darkened += (product = ((product >> 1) & colorMask));
300 darkened += (product >> 1) & colorMask;
301
302 *(dP2 + 1) = darkened;
303 }
304
305 bP++;
306 xP++;
307 dP1 += 2;
308 dP2 += 2;
309 }
310
311 // Last 2 Pixels
312
313 currentPixel = *bP;
314 currentDelta = *xP;
315
316 if (currentPixel != currentDelta)
317 {
318 *xP = *bP;
319
320 #ifdef MSB_FIRST
321 colorA = (currentPixel >> 16) & 0xFFFF;
322 colorB = (currentPixel ) & 0xFFFF;
323 #else
324 colorA = (currentPixel ) & 0xFFFF;
325 colorB = (currentPixel >> 16) & 0xFFFF;
326 #endif
327
328 #ifdef MSB_FIRST
329 *dP1 = product = (colorA << 16) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) );
330 #else
331 *dP1 = product = (colorA ) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) << 16);
332 #endif
333
334 darkened = (product = ((product >> 1) & colorMask));
335 darkened += (product = ((product >> 1) & colorMask));
336 darkened += (product >> 1) & colorMask;
337
338 *dP2 = darkened;
339
340 *(dP1 + 1) = product = (colorB << 16) | colorB;
341
342 darkened = (product = ((product >> 1) & colorMask));
343 darkened += (product = ((product >> 1) & colorMask));
344 darkened += (product >> 1) & colorMask;
345
346 *(dP2 + 1) = darkened;
347 }
348
349 srcPtr += srcRowBytes;
350 deltaPtr += srcRowBytes;
351 dstPtr += dstRowBytes;
352 dstPtr2 += dstRowBytes;
353 }
354}
355
356void S9xBlitPixMixedTV1x2 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
357{
358 uint8 *dstPtr2 = dstPtr + dstRowBytes, *srcPtr2 = srcPtr + srcRowBytes;
359 dstRowBytes <<= 1;
360
361 for (; height > 1; height--)
362 {
363 uint16 *dP1 = (uint16 *) dstPtr, *dP2 = (uint16 *) dstPtr2, *bP1 = (uint16 *) srcPtr, *bP2 = (uint16 *) srcPtr2;
364 uint16 prev, next, mixed;
365
366 for (int i = 0; i < width; i++)
367 {
368 prev = *bP1++;
369 next = *bP2++;
370 mixed = prev + next + ((prev ^ next) & lowPixelMask);
371
372 *dP1++ = prev;
373 *dP2++ = (mixed >> 1) - (mixed >> 4 & qlowPixelMask);
374 }
375
376 srcPtr += srcRowBytes;
377 srcPtr2 += srcRowBytes;
378 dstPtr += dstRowBytes;
379 dstPtr2 += dstRowBytes;
380 }
381
382 // Last 1 line
383
384 uint16 *dP1 = (uint16 *) dstPtr, *dP2 = (uint16 *) dstPtr2, *bP1 = (uint16 *) srcPtr;
385 uint16 prev, mixed;
386
387 for (int i = 0; i < width; i++)
388 {
389 prev = *bP1++;
390 mixed = prev + ((prev ^ 0) & lowPixelMask);
391
392 *dP1++ = prev;
393 *dP2++ = (mixed >> 1) - (mixed >> 4 & qlowPixelMask);
394 }
395}
396
397void S9xBlitPixSmooth2x2 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
398{
399 uint8 *dstPtr2 = dstPtr + dstRowBytes, *deltaPtr = XDelta;
400 uint32 lastLinePix[SNES_WIDTH << 1];
401 uint8 lastLineChg[SNES_WIDTH >> 1];
402 int lineBytes = width << 1;
403
404 dstRowBytes <<= 1;
405
406 memset(lastLinePix, 0, sizeof(lastLinePix));
407 memset(lastLineChg, 0, sizeof(lastLineChg));
408
409 for (; height; height--)
410 {
411 uint32 *dP1 = (uint32 *) dstPtr, *dP2 = (uint32 *) dstPtr2, *bP = (uint32 *) srcPtr, *xP = (uint32 *) deltaPtr;
412 uint32 *lL = lastLinePix;
413 uint8 *lC = lastLineChg;
414 uint32 currentPixel, nextPixel, currentDelta, nextDelta, lastPix, lastChg, thisChg, currentPixA, currentPixB, colorA, colorB, colorC;
415 uint16 savePixel;
416
417 savePixel = *(uint16 *) (srcPtr + lineBytes);
418 *(uint16 *) (srcPtr + lineBytes) = *(uint16 *) (srcPtr + lineBytes - 2);
419 *(uint32 *) (deltaPtr + lineBytes) = *(uint32 *) (srcPtr + lineBytes);
420
421 nextPixel = *bP++;
422 nextDelta = *xP++;
423
424 for (int i = 0; i < (width >> 1); i++)
425 {
426 currentPixel = nextPixel;
427 currentDelta = nextDelta;
428 nextPixel = *bP++;
429 nextDelta = *xP++;
430 lastChg = *lC;
431 thisChg = (nextPixel - nextDelta) | (currentPixel - currentDelta);
432
433 #ifdef MSB_FIRST
434 colorA = (currentPixel >> 16) & 0xFFFF;
435 colorB = (currentPixel ) & 0xFFFF;
436 colorC = (nextPixel >> 16) & 0xFFFF;
437
438 currentPixA = (colorA << 16) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) );
439 currentPixB = (colorB << 16) | ((((colorC >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorC & colorB & lowPixelMask)) );
440 #else
441 colorA = (currentPixel ) & 0xFFFF;
442 colorB = (currentPixel >> 16) & 0xFFFF;
443 colorC = (nextPixel ) & 0xFFFF;
444
445 currentPixA = (colorA ) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) << 16);
446 currentPixB = (colorB ) | ((((colorC >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorC & colorB & lowPixelMask)) << 16);
447 #endif
448
449 if (thisChg | lastChg)
450 {
451 xP[-2] = currentPixel;
452
453 lastPix = lL[0];
454 dP1[0] = ((currentPixA >> 1) & colorMask) + ((lastPix >> 1) & colorMask) + (currentPixA & lastPix & lowPixelMask);
455 dP2[0] = currentPixA;
456 lL[0] = currentPixA;
457
458 lastPix = lL[1];
459 dP1[1] = ((currentPixB >> 1) & colorMask) + ((lastPix >> 1) & colorMask) + (currentPixB & lastPix & lowPixelMask);
460 dP2[1] = currentPixB;
461 lL[1] = currentPixB;
462
463 *lC++ = (thisChg != 0);
464 }
465 else
466 {
467 lL[0] = currentPixA;
468 lL[1] = currentPixB;
469 *lC++ = 0;
470 }
471
472 lL += 2;
473 dP2 += 2;
474 dP1 += 2;
475 }
476
477 *(uint16 *) (srcPtr + lineBytes) = savePixel;
478
479 srcPtr += srcRowBytes;
480 deltaPtr += srcRowBytes;
481 dstPtr += dstRowBytes;
482 dstPtr2 += dstRowBytes;
483 }
484}
485
486void S9xBlitPixSuper2xSaI16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
487{
488 Super2xSaI(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height);
489}
490
491void S9xBlitPix2xSaI16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
492{
493 _2xSaI(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height);
494}
495
496void S9xBlitPixSuperEagle16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
497{
498 SuperEagle(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height);
499}
500
501void S9xBlitPixEPX16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
502{
503 EPX_16(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height);
504}
505
506void S9xBlitPixHQ2x16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
507{
508 HQ2X_16(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height);
509}
510
511void S9xBlitPixHQ3x16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
512{
513 HQ3X_16(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height);
514}
515
516void S9xBlitPixHQ4x16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
517{
518 HQ4X_16(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height);
519}
520
521void S9xBlitPixNTSC16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
522{
523 snes_ntsc_blit(ntsc, (SNES_NTSC_IN_T const *) srcPtr, srcRowBytes >> 1, 0, width, height, dstPtr, dstRowBytes);
524}
525
526void S9xBlitPixHiResNTSC16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height)
527{
528 snes_ntsc_blit_hires(ntsc, (SNES_NTSC_IN_T const *) srcPtr, srcRowBytes >> 1, 0, width, height, dstPtr, dstRowBytes);
529}
530