gpu_unai: basic frameskip
[pcsx_rearmed.git] / plugins / dfxvideo / draw.c
1 /***************************************************************************
2                           draw.c  -  description
3                              -------------------
4     begin                : Sun Oct 28 2001
5     copyright            : (C) 2001 by Pete Bernert
6     email                : BlackDove@addcom.de
7  ***************************************************************************/
8 /***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version. See also the license.txt file for *
14  *   additional informations.                                              *
15  *                                                                         *
16  ***************************************************************************/
17
18 #define _IN_DRAW
19
20 #include "externals.h"
21 #include "gpu.h"
22 #include "draw.h"
23 #include "prim.h"
24 #include "menu.h"
25 #include "interp.h"
26 #include "swap.h"
27
28 // misc globals
29 int            iResX;
30 int            iResY;
31 long           lLowerpart;
32 BOOL           bIsFirstFrame = TRUE;
33 BOOL           bCheckMask = FALSE;
34 unsigned short sSetMask = 0;
35 unsigned long  lSetMask = 0;
36 int            iDesktopCol = 16;
37 int            iShowFPS = 0;
38 int            iWinSize; 
39 int            iMaintainAspect = 0;
40 int            iUseNoStretchBlt = 0;
41 int            iFastFwd = 0;
42 //int            iDebugMode = 0;
43 int            iFVDisplay = 0;
44 PSXPoint_t     ptCursorPoint[8];
45 unsigned short usCursorActive = 0;
46
47 //unsigned int   LUT16to32[65536];
48 //unsigned int   RGBtoYUV[65536];
49
50 #include <sys/ipc.h>
51 #include <sys/shm.h>
52 #include <X11/extensions/Xv.h>
53 #include <X11/extensions/Xvlib.h>
54 #include <X11/extensions/XShm.h>
55 int xv_port = -1;
56 int xv_id = -1;
57 int xv_depth = 0;
58 int yuv_port = -1;
59 int yuv_id = -1;
60 int use_yuv = 0;
61 int xv_vsync = 0;
62
63 XShmSegmentInfo shminfo;
64 int finalw,finalh;
65
66 extern XvImage  *XvShmCreateImage(Display*, XvPortID, int, char*, int, int, XShmSegmentInfo*);
67
68 #include <time.h>
69
70 // prototypes
71 void hq2x_32( unsigned char * srcPtr, DWORD srcPitch, unsigned char * dstPtr, int width, int height);
72 void hq3x_32( unsigned char * srcPtr,  DWORD srcPitch, unsigned char * dstPtr, int width, int height);
73
74 ////////////////////////////////////////////////////////////////////////
75 // generic 2xSaI helpers
76 ////////////////////////////////////////////////////////////////////////
77
78 void *         pSaISmallBuff=NULL;
79 void *         pSaIBigBuff=NULL;
80
81 #define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D))
82
83 static __inline int GetResult1(DWORD A, DWORD B, DWORD C, DWORD D, DWORD E)
84 {
85  int x = 0;
86  int y = 0;
87  int r = 0;
88  if (A == C) x+=1; else if (B == C) y+=1;
89  if (A == D) x+=1; else if (B == D) y+=1;
90  if (x <= 1) r+=1; 
91  if (y <= 1) r-=1;
92  return r;
93 }
94
95 static __inline int GetResult2(DWORD A, DWORD B, DWORD C, DWORD D, DWORD E) 
96 {
97  int x = 0; 
98  int y = 0;
99  int r = 0;
100  if (A == C) x+=1; else if (B == C) y+=1;
101  if (A == D) x+=1; else if (B == D) y+=1;
102  if (x <= 1) r-=1; 
103  if (y <= 1) r+=1;
104  return r;
105 }
106
107 #define colorMask8     0x00FEFEFE
108 #define lowPixelMask8  0x00010101
109 #define qcolorMask8    0x00FCFCFC
110 #define qlowpixelMask8 0x00030303
111
112 #define INTERPOLATE8(A, B) ((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8)))
113 #define Q_INTERPOLATE8(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) \
114         + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8))))
115
116
117 void Super2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch,
118                     unsigned char  *dstBitmap, int width, int height)
119 {
120  DWORD dstPitch        = srcPitch<<1;
121  DWORD srcPitchHalf    = srcPitch>>1;
122  int   finWidth        = srcPitch>>2;
123  DWORD line;
124  DWORD *dP;
125  DWORD *bP;
126  int iXA,iXB,iXC,iYA,iYB,iYC,finish;
127  DWORD color4, color5, color6;
128  DWORD color1, color2, color3;
129  DWORD colorA0, colorA1, colorA2, colorA3,
130        colorB0, colorB1, colorB2, colorB3,
131        colorS1, colorS2;
132  DWORD product1a, product1b,
133        product2a, product2b;
134
135  finalw=width<<1;
136  finalh=height<<1;
137
138  line = 0;
139
140   {
141    for (; height; height-=1)
142         {
143      bP = (DWORD *)srcPtr;
144          dP = (DWORD *)(dstBitmap + line*dstPitch);
145      for (finish = width; finish; finish -= 1 )
146       {
147 //---------------------------------------    B1 B2
148 //                                         4  5  6 S2
149 //                                         1  2  3 S1
150 //                                           A1 A2
151        if(finish==finWidth) iXA=0;
152        else                 iXA=1;
153        if(finish>4) {iXB=1;iXC=2;}
154        else
155        if(finish>3) {iXB=1;iXC=1;}
156        else         {iXB=0;iXC=0;}
157        if(line==0)  {iYA=0;}
158        else         {iYA=finWidth;}
159        if(height>4) {iYB=finWidth;iYC=srcPitchHalf;}
160        else
161        if(height>3) {iYB=finWidth;iYC=finWidth;}
162        else         {iYB=0;iYC=0;}
163
164        colorB0 = *(bP- iYA - iXA);
165        colorB1 = *(bP- iYA);
166        colorB2 = *(bP- iYA + iXB);
167        colorB3 = *(bP- iYA + iXC);
168
169        color4 = *(bP  - iXA);
170        color5 = *(bP);
171        color6 = *(bP  + iXB);
172        colorS2 = *(bP + iXC);
173
174        color1 = *(bP  + iYB  - iXA);
175        color2 = *(bP  + iYB);
176        color3 = *(bP  + iYB  + iXB);
177        colorS1= *(bP  + iYB  + iXC);
178
179        colorA0 = *(bP + iYC - iXA);
180        colorA1 = *(bP + iYC);
181        colorA2 = *(bP + iYC + iXB);
182        colorA3 = *(bP + iYC + iXC);
183
184        if (color2 == color6 && color5 != color3)
185         {
186          product2b = product1b = color2;
187         }
188        else
189        if (color5 == color3 && color2 != color6)
190         {
191          product2b = product1b = color5;
192         }
193        else
194        if (color5 == color3 && color2 == color6)
195         {
196          register int r = 0;
197
198          r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff),  (colorA1&0x00ffffff));
199          r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff),  (colorB1&0x00ffffff));
200          r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff));
201          r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff));
202
203          if (r > 0)
204           product2b = product1b = color6;
205          else
206          if (r < 0)
207           product2b = product1b = color5;
208          else
209           {
210            product2b = product1b = INTERPOLATE8(color5, color6);
211           }
212         }
213        else
214         {
215          if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0)
216              product2b = Q_INTERPOLATE8 (color3, color3, color3, color2);
217          else
218          if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3)
219              product2b = Q_INTERPOLATE8 (color2, color2, color2, color3);
220          else
221              product2b = INTERPOLATE8 (color2, color3);
222
223          if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0)
224              product1b = Q_INTERPOLATE8 (color6, color6, color6, color5);
225          else
226          if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3)
227              product1b = Q_INTERPOLATE8 (color6, color5, color5, color5);
228          else
229              product1b = INTERPOLATE8 (color5, color6);
230         }
231
232        if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2)
233         product2a = INTERPOLATE8(color2, color5);
234        else
235        if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0)
236         product2a = INTERPOLATE8(color2, color5);
237        else
238         product2a = color2;
239
240        if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2)
241         product1a = INTERPOLATE8(color2, color5);
242        else
243        if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0)
244         product1a = INTERPOLATE8(color2, color5);
245        else
246         product1a = color5;
247
248        *dP=product1a;
249        *(dP+1)=product1b;
250        *(dP+(srcPitchHalf))=product2a;
251        *(dP+1+(srcPitchHalf))=product2b;
252
253        bP += 1;
254        dP += 2;
255       }//end of for ( finish= width etc..)
256
257      line += 2;
258      srcPtr += srcPitch;
259         }; //endof: for (; height; height--)
260   }
261 }
262
263 ////////////////////////////////////////////////////////////////////////
264
265 void Std2xSaI_ex8(unsigned char *srcPtr, DWORD srcPitch,
266                   unsigned char *dstBitmap, int width, int height)
267 {
268  DWORD dstPitch        = srcPitch<<1;
269  DWORD srcPitchHalf    = srcPitch>>1;
270  int   finWidth        = srcPitch>>2;
271  DWORD line;
272  DWORD *dP;
273  DWORD *bP;
274  int iXA,iXB,iXC,iYA,iYB,iYC,finish;
275
276  finalw=width<<1;
277  finalh=height<<1;
278
279  DWORD colorA, colorB;
280  DWORD colorC, colorD,
281        colorE, colorF, colorG, colorH,
282        colorI, colorJ, colorK, colorL,
283        colorM, colorN, colorO, colorP;
284  DWORD product, product1, product2;
285
286  line = 0;
287
288   {
289    for (; height; height-=1)
290         {
291      bP = (DWORD *)srcPtr;
292          dP = (DWORD *)(dstBitmap + line*dstPitch);
293      for (finish = width; finish; finish -= 1 )
294       {
295 //---------------------------------------
296 // Map of the pixels:                    I|E F|J
297 //                                       G|A B|K
298 //                                       H|C D|L
299 //                                       M|N O|P
300        if(finish==finWidth) iXA=0;
301        else                 iXA=1;
302        if(finish>4) {iXB=1;iXC=2;}
303        else
304        if(finish>3) {iXB=1;iXC=1;}
305        else         {iXB=0;iXC=0;}
306        if(line==0)  {iYA=0;}
307        else         {iYA=finWidth;}
308        if(height>4) {iYB=finWidth;iYC=srcPitchHalf;}
309        else
310        if(height>3) {iYB=finWidth;iYC=finWidth;}
311        else         {iYB=0;iYC=0;}
312
313        colorI = *(bP- iYA - iXA);
314        colorE = *(bP- iYA);
315        colorF = *(bP- iYA + iXB);
316        colorJ = *(bP- iYA + iXC);
317
318        colorG = *(bP  - iXA);
319        colorA = *(bP);
320        colorB = *(bP  + iXB);
321        colorK = *(bP + iXC);
322
323        colorH = *(bP  + iYB  - iXA);
324        colorC = *(bP  + iYB);
325        colorD = *(bP  + iYB  + iXB);
326        colorL = *(bP  + iYB  + iXC);
327
328        colorM = *(bP + iYC - iXA);
329        colorN = *(bP + iYC);
330        colorO = *(bP + iYC + iXB);
331        colorP = *(bP + iYC + iXC);
332
333
334        if((colorA == colorD) && (colorB != colorC))
335         {
336          if(((colorA == colorE) && (colorB == colorL)) ||
337             ((colorA == colorC) && (colorA == colorF) && 
338              (colorB != colorE) && (colorB == colorJ)))
339           {
340            product = colorA;
341           }
342          else
343           {
344            product = INTERPOLATE8(colorA, colorB);
345           }
346
347          if(((colorA == colorG) && (colorC == colorO)) ||
348             ((colorA == colorB) && (colorA == colorH) && 
349              (colorG != colorC) && (colorC == colorM)))
350           {
351            product1 = colorA;
352           }
353          else
354           {
355            product1 = INTERPOLATE8(colorA, colorC);
356           }
357          product2 = colorA;
358         }
359        else
360        if((colorB == colorC) && (colorA != colorD))
361         {
362          if(((colorB == colorF) && (colorA == colorH)) ||
363             ((colorB == colorE) && (colorB == colorD) && 
364              (colorA != colorF) && (colorA == colorI)))
365           {
366            product = colorB;
367           }
368          else
369           {
370            product = INTERPOLATE8(colorA, colorB);
371           }
372
373          if(((colorC == colorH) && (colorA == colorF)) ||
374             ((colorC == colorG) && (colorC == colorD) && 
375              (colorA != colorH) && (colorA == colorI)))
376           {
377            product1 = colorC;
378           }
379          else
380           {
381            product1=INTERPOLATE8(colorA, colorC);
382           }
383          product2 = colorB;
384         }
385        else
386        if((colorA == colorD) && (colorB == colorC))
387         {
388          if (colorA == colorB)
389           {
390            product = colorA;
391            product1 = colorA;
392            product2 = colorA;
393           }
394          else
395           {
396            register int r = 0;
397            product1 = INTERPOLATE8(colorA, colorC);
398            product = INTERPOLATE8(colorA, colorB);
399
400            r += GetResult1 (colorA&0x00FFFFFF, colorB&0x00FFFFFF, colorG&0x00FFFFFF, colorE&0x00FFFFFF, colorI&0x00FFFFFF);
401            r += GetResult2 (colorB&0x00FFFFFF, colorA&0x00FFFFFF, colorK&0x00FFFFFF, colorF&0x00FFFFFF, colorJ&0x00FFFFFF);
402            r += GetResult2 (colorB&0x00FFFFFF, colorA&0x00FFFFFF, colorH&0x00FFFFFF, colorN&0x00FFFFFF, colorM&0x00FFFFFF);
403            r += GetResult1 (colorA&0x00FFFFFF, colorB&0x00FFFFFF, colorL&0x00FFFFFF, colorO&0x00FFFFFF, colorP&0x00FFFFFF);
404
405            if (r > 0)
406             product2 = colorA;
407            else
408            if (r < 0)
409             product2 = colorB;
410            else
411             {
412              product2 = Q_INTERPOLATE8(colorA, colorB, colorC, colorD);
413             }
414           }
415         }
416        else
417         {
418          product2 = Q_INTERPOLATE8(colorA, colorB, colorC, colorD);
419
420          if ((colorA == colorC) && (colorA == colorF) && 
421              (colorB != colorE) && (colorB == colorJ))
422           {
423            product = colorA;
424           }
425          else
426          if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI))
427           {
428            product = colorB;
429           }
430          else
431           {
432            product = INTERPOLATE8(colorA, colorB);
433           }
434
435          if ((colorA == colorB) && (colorA == colorH) && 
436              (colorG != colorC) && (colorC == colorM))
437           {
438            product1 = colorA;
439           }
440          else
441          if ((colorC == colorG) && (colorC == colorD) && 
442              (colorA != colorH) && (colorA == colorI))
443           {
444            product1 = colorC;
445           }
446          else
447           {
448            product1 = INTERPOLATE8(colorA, colorC);
449           }
450         }
451
452 //////////////////////////
453
454        *dP=colorA;
455        *(dP+1)=product;
456        *(dP+(srcPitchHalf))=product1;
457        *(dP+1+(srcPitchHalf))=product2;
458
459        bP += 1;
460        dP += 2;
461       }//end of for ( finish= width etc..)
462
463      line += 2;
464      srcPtr += srcPitch;
465         }; //endof: for (; height; height--)
466   }
467 }
468
469 ////////////////////////////////////////////////////////////////////////
470
471 void SuperEagle_ex8(unsigned char *srcPtr, DWORD srcPitch,
472                         unsigned char  *dstBitmap, int width, int height)
473 {
474  DWORD dstPitch        = srcPitch<<1;
475  DWORD srcPitchHalf    = srcPitch>>1;
476  int   finWidth        = srcPitch>>2;
477  DWORD line;
478  DWORD *dP;
479  DWORD *bP;
480  int iXA,iXB,iXC,iYA,iYB,iYC,finish;
481  DWORD color4, color5, color6;
482  DWORD color1, color2, color3;
483  DWORD colorA1, colorA2, 
484        colorB1, colorB2,
485        colorS1, colorS2;
486  DWORD product1a, product1b,
487        product2a, product2b;
488
489  finalw=width<<1;
490  finalh=height<<1;
491
492  line = 0;
493
494   {
495    for (; height; height-=1)
496         {
497      bP = (DWORD *)srcPtr;
498          dP = (DWORD *)(dstBitmap + line*dstPitch);
499      for (finish = width; finish; finish -= 1 )
500       {
501        if(finish==finWidth) iXA=0;
502        else                 iXA=1;
503        if(finish>4) {iXB=1;iXC=2;}
504        else
505        if(finish>3) {iXB=1;iXC=1;}
506        else         {iXB=0;iXC=0;}
507        if(line==0)  {iYA=0;}
508        else         {iYA=finWidth;}
509        if(height>4) {iYB=finWidth;iYC=srcPitchHalf;}
510        else
511        if(height>3) {iYB=finWidth;iYC=finWidth;}
512        else         {iYB=0;iYC=0;}
513
514        colorB1 = *(bP- iYA);
515        colorB2 = *(bP- iYA + iXB);
516
517        color4 = *(bP  - iXA);
518        color5 = *(bP);
519        color6 = *(bP  + iXB);
520        colorS2 = *(bP + iXC);
521
522        color1 = *(bP  + iYB  - iXA);
523        color2 = *(bP  + iYB);
524        color3 = *(bP  + iYB  + iXB);
525        colorS1= *(bP  + iYB  + iXC);
526
527        colorA1 = *(bP + iYC);
528        colorA2 = *(bP + iYC + iXB);
529
530        if(color2 == color6 && color5 != color3)
531         {
532          product1b = product2a = color2;
533          if((color1 == color2) ||
534             (color6 == colorB2))
535           {
536            product1a = INTERPOLATE8(color2, color5);
537            product1a = INTERPOLATE8(color2, product1a);
538           }
539          else
540           {
541            product1a = INTERPOLATE8(color5, color6);
542           }
543  
544          if((color6 == colorS2) ||
545             (color2 == colorA1))
546           {
547            product2b = INTERPOLATE8(color2, color3);
548            product2b = INTERPOLATE8(color2, product2b);
549           }
550          else
551           {
552            product2b = INTERPOLATE8(color2, color3);
553           }
554         }
555        else
556        if (color5 == color3 && color2 != color6)
557         {
558          product2b = product1a = color5;
559
560          if ((colorB1 == color5) ||
561              (color3 == colorS1))
562           {
563            product1b = INTERPOLATE8(color5, color6);
564            product1b = INTERPOLATE8(color5, product1b);
565           }
566          else
567           {
568            product1b = INTERPOLATE8(color5, color6);
569           }
570
571          if ((color3 == colorA2) ||
572              (color4 == color5))
573           {
574            product2a = INTERPOLATE8(color5, color2);
575            product2a = INTERPOLATE8(color5, product2a);
576           }
577          else
578           {
579            product2a = INTERPOLATE8(color2, color3);
580           }
581         }
582        else
583        if (color5 == color3 && color2 == color6)
584         {
585          register int r = 0;
586
587          r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff),  (colorA1&0x00ffffff));
588          r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff),  (colorB1&0x00ffffff));
589          r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff));
590          r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff));
591
592          if (r > 0)
593           {
594            product1b = product2a = color2;
595            product1a = product2b = INTERPOLATE8(color5, color6);
596           }
597          else
598          if (r < 0)
599           {
600            product2b = product1a = color5;
601            product1b = product2a = INTERPOLATE8(color5, color6);
602           }
603          else
604           {
605            product2b = product1a = color5;
606            product1b = product2a = color2;
607           }
608         }
609        else
610         {
611          product2b = product1a = INTERPOLATE8(color2, color6);
612          product2b = Q_INTERPOLATE8(color3, color3, color3, product2b);
613          product1a = Q_INTERPOLATE8(color5, color5, color5, product1a);
614
615          product2a = product1b = INTERPOLATE8(color5, color3);
616          product2a = Q_INTERPOLATE8(color2, color2, color2, product2a);
617          product1b = Q_INTERPOLATE8(color6, color6, color6, product1b);
618         }
619
620 ////////////////////////////////
621
622        *dP=product1a;
623        *(dP+1)=product1b;
624        *(dP+(srcPitchHalf))=product2a;
625        *(dP+1+(srcPitchHalf))=product2b;
626
627        bP += 1;
628        dP += 2;
629       }//end of for ( finish= width etc..)
630
631      line += 2;
632      srcPtr += srcPitch;
633         }; //endof: for (; height; height--)
634   }
635 }
636
637 /////////////////////////
638
639 //#include <assert.h>
640
641 static __inline void scale2x_32_def_whole(uint32_t*  dst0, uint32_t* dst1, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count)
642 {
643
644         //assert(count >= 2);
645
646         // first pixel
647         if (src0[0] != src2[0] && src1[0] != src1[1]) {
648                 dst0[0] = src1[0] == src0[0] ? src0[0] : src1[0];
649                 dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0];
650                 dst1[0] = src1[0] == src2[0] ? src2[0] : src1[0];
651                 dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0];
652         } else {
653                 dst0[0] = src1[0];
654                 dst0[1] = src1[0];
655                 dst1[0] = src1[0];
656                 dst1[1] = src1[0];
657         }
658         ++src0;
659         ++src1;
660         ++src2;
661         dst0 += 2;
662         dst1 += 2;
663
664         // central pixels
665         count -= 2;
666         while (count) {
667                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
668                         dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
669                         dst0[1] = src1[1] == src0[0] ? src0[0] : src1[0];
670                         dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0];
671                         dst1[1] = src1[1] == src2[0] ? src2[0] : src1[0];
672                 } else {
673                         dst0[0] = src1[0];
674                         dst0[1] = src1[0];
675                         dst1[0] = src1[0];
676                         dst1[1] = src1[0];
677                 }
678
679                 ++src0;
680                 ++src1;
681                 ++src2;
682                 dst0 += 2;
683                 dst1 += 2;
684                 --count;
685         }
686
687         // last pixel
688         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
689                 dst0[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
690                 dst0[1] = src1[0] == src0[0] ? src0[0] : src1[0];
691                 dst1[0] = src1[-1] == src2[0] ? src2[0] : src1[0];
692                 dst1[1] = src1[0] == src2[0] ? src2[0] : src1[0];
693         } else {
694                 dst0[0] = src1[0];
695                 dst0[1] = src1[0];
696                 dst1[0] = src1[0];
697                 dst1[1] = src1[0];
698         }
699 }
700
701 void Scale2x_ex8(unsigned char *srcPtr, DWORD srcPitch,
702                                  unsigned char  *dstPtr, int width, int height)
703 {
704         //const int srcpitch = srcPitch;
705         const int dstPitch = srcPitch<<1;
706
707         int count = height;
708
709         finalw=width<<1;
710         finalh=height<<1;
711
712         uint32_t  *dst0 = (uint32_t  *)dstPtr;
713         uint32_t  *dst1 = dst0 + (dstPitch >> 2);
714
715         uint32_t  *src0 = (uint32_t  *)srcPtr;
716         uint32_t  *src1 = src0 + (srcPitch >> 2);
717         uint32_t  *src2 = src1 + (srcPitch >> 2);
718         scale2x_32_def_whole(dst0, dst1, src0, src0, src1, width);
719
720         count -= 2;
721         while(count) {
722                 dst0 += dstPitch >> 1;
723                 dst1 += dstPitch >> 1;
724                 scale2x_32_def_whole(dst0, dst1, src0, src0, src1, width);
725                 src0 = src1;
726                 src1 = src2;
727                 src2 += srcPitch >> 2;
728                 --count;
729         }
730         dst0 += dstPitch >> 1;
731         dst1 += dstPitch >> 1;
732         scale2x_32_def_whole(dst0, dst1, src0, src1, src1, width);
733
734 }
735
736 ////////////////////////////////////////////////////////////////////////
737
738 static __inline void scale3x_32_def_whole(uint32_t* dst0, uint32_t* dst1, uint32_t* dst2, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count)
739 {
740         //assert(count >= 2);
741
742         //first pixel
743         if (src0[0] != src2[0] && src1[0] != src1[1]) {
744                 dst0[0] = src1[0];
745                 dst0[1] = (src1[0] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[0]) ? src0[0] : src1[0];
746                 dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
747                 dst1[0] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
748                 dst1[1] = src1[0];
749                 dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
750                 dst2[0] = src1[0];
751                 dst2[1] = (src1[0] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[0]) ? src2[0] : src1[0];
752                 dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
753         } else {
754                 dst0[0] = src1[0];
755                 dst0[1] = src1[0];
756                 dst0[2] = src1[0];
757                 dst1[0] = src1[0];
758                 dst1[1] = src1[0];
759                 dst1[2] = src1[0];
760                 dst2[0] = src1[0];
761                 dst2[1] = src1[0];
762                 dst2[2] = src1[0];
763         }
764         ++src0;
765         ++src1;
766         ++src2;
767         dst0 += 3;
768         dst1 += 3;
769         dst2 += 3;
770
771         //central pixels
772         count -= 2;
773         while (count) {
774                 if (src0[0] != src2[0] && src1[-1] != src1[1]) {
775                         dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
776                         dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
777                         dst0[2] = src1[1] == src0[0] ? src1[1] : src1[0];
778                         dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
779                         dst1[1] = src1[0];
780                         dst1[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
781                         dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
782                         dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
783                         dst2[2] = src1[1] == src2[0] ? src1[1] : src1[0];
784                 } else {
785                         dst0[0] = src1[0];
786                         dst0[1] = src1[0];
787                         dst0[2] = src1[0];
788                         dst1[0] = src1[0];
789                         dst1[1] = src1[0];
790                         dst1[2] = src1[0];
791                         dst2[0] = src1[0];
792                         dst2[1] = src1[0];
793                         dst2[2] = src1[0];
794                 }
795
796                 ++src0;
797                 ++src1;
798                 ++src2;
799                 dst0 += 3;
800                 dst1 += 3;
801                 dst2 += 3;
802                 --count;
803         }
804
805         // last pixel
806         if (src0[0] != src2[0] && src1[-1] != src1[0]) {
807                 dst0[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
808                 dst0[1] = (src1[-1] == src0[0] && src1[0] != src0[0]) || (src1[0] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
809                 dst0[2] = src1[0];
810                 dst1[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
811                 dst1[1] = src1[0];
812                 dst1[2] = (src1[0] == src0[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src0[0]) ? src1[0] : src1[0];
813                 dst2[0] = src1[-1] == src2[0] ? src1[-1] : src1[0];
814                 dst2[1] = (src1[-1] == src2[0] && src1[0] != src2[0]) || (src1[0] == src2[0] && src1[0] != src2[-1]) ? src2[0] : src1[0];
815                 dst2[2] = src1[0];
816         } else {
817                 dst0[0] = src1[0];
818                 dst0[1] = src1[0];
819                 dst0[2] = src1[0];
820                 dst1[0] = src1[0];
821                 dst1[1] = src1[0];
822                 dst1[2] = src1[0];
823                 dst2[0] = src1[0];
824                 dst2[1] = src1[0];
825                 dst2[2] = src1[0];
826         }
827 }
828
829
830 void Scale3x_ex8(unsigned char *srcPtr, DWORD srcPitch,
831                                  unsigned char  *dstPtr, int width, int height)
832 {
833         int count = height;
834
835         int dstPitch = srcPitch*3;
836         int dstRowPixels = dstPitch>>2; 
837
838         finalw=width*3;
839         finalh=height*3;
840
841         uint32_t  *dst0 = (uint32_t  *)dstPtr;
842         uint32_t  *dst1 = dst0 + dstRowPixels;
843         uint32_t  *dst2 = dst1 + dstRowPixels;
844
845         uint32_t  *src0 = (uint32_t  *)srcPtr;
846         uint32_t  *src1 = src0 + (srcPitch >> 2);
847         uint32_t  *src2 = src1 + (srcPitch >> 2);
848         scale3x_32_def_whole(dst0, dst1, dst2, src0, src0, src2, width);
849
850         count -= 2;
851         while(count) {
852                 dst0 += dstRowPixels*3;
853                 dst1 += dstRowPixels*3;
854                 dst2 += dstRowPixels*3;
855
856                 scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src2, width);
857                 src0 = src1;
858                 src1 = src2;
859                 src2 += srcPitch >> 2;
860                 --count;
861         }
862
863         dst0 += dstRowPixels*3;
864         dst1 += dstRowPixels*3;
865         dst2 += dstRowPixels*3;
866
867         scale3x_32_def_whole(dst0, dst1, dst2, src0, src1, src1, width);
868 }
869
870
871 ////////////////////////////////////////////////////////////////////////
872
873 #ifndef MAX
874 #define MAX(a,b)    (((a) > (b)) ? (a) : (b))
875 #define MIN(a,b)    (((a) < (b)) ? (a) : (b))
876 #endif
877
878
879 ////////////////////////////////////////////////////////////////////////
880 // X STUFF :)
881 ////////////////////////////////////////////////////////////////////////
882
883
884 static Cursor        cursor;
885 XVisualInfo          vi;
886 static XVisualInfo   *myvisual;
887 Display              *display;
888 static Colormap      colormap;
889 Window        window;
890 static GC            hGC;
891 static XImage      * Ximage;
892 static XvImage     * XCimage; 
893 static XImage      * XFimage; 
894 static XImage      * XPimage=0 ; 
895 char *               Xpixels;
896 char *               pCaptionText;
897
898 static int fx=0;
899
900
901 static Atom xv_intern_atom_if_exists( Display *display, char const * atom_name )
902 {
903   XvAttribute * attributes;
904   int attrib_count,i;
905   Atom xv_atom = None;
906
907   attributes = XvQueryPortAttributes( display, xv_port, &attrib_count );
908   if( attributes!=NULL )
909   {
910     for ( i = 0; i < attrib_count; ++i )
911     {
912       if ( strcmp(attributes[i].name, atom_name ) == 0 )
913       {
914         xv_atom = XInternAtom( display, atom_name, False );
915         break; // found what we want, break out
916       }
917     }
918     XFree( attributes );
919   }
920
921   return xv_atom;
922 }
923
924
925
926 // close display
927
928 void DestroyDisplay(void)
929 {
930  if(display)
931   {
932    XFreeColormap(display, colormap);
933    if(hGC) 
934     {
935      XFreeGC(display,hGC);
936      hGC = 0;
937     }
938    if(Ximage)
939     {
940      XDestroyImage(Ximage);
941      Ximage=0;
942     }
943    if(XCimage) 
944     { 
945      XFree(XCimage); 
946      XCimage=0; 
947     } 
948    if(XFimage) 
949     { 
950      XDestroyImage(XFimage);
951      XFimage=0; 
952     } 
953
954         XShmDetach(display,&shminfo);
955         shmdt(shminfo.shmaddr);
956         shmctl(shminfo.shmid,IPC_RMID,NULL);
957
958   Atom atom_vsync = xv_intern_atom_if_exists(display, "XV_SYNC_TO_VBLANK");
959   if (atom_vsync != None) {
960         XvSetPortAttribute(display, xv_port, atom_vsync, xv_vsync);
961   }
962
963    XSync(display,False);
964
965    XCloseDisplay(display);
966   }
967 }
968
969 static int depth=0;
970 int root_window_id=0;
971
972
973 // Create display
974
975 void CreateDisplay(void)
976 {
977  XSetWindowAttributes winattr;
978  int                  myscreen;
979  Screen *             screen;
980  XEvent               event;
981  XSizeHints           hints;
982  XWMHints             wm_hints;
983  MotifWmHints         mwmhints;
984  Atom                 mwmatom;
985
986  Atom                   delwindow;
987
988  XGCValues            gcv;
989  int i;
990
991  int ret, j, p;
992  int formats;
993  unsigned int p_num_adaptors=0, p_num_ports=0;
994
995  XvAdaptorInfo          *ai;
996  XvImageFormatValues    *fo;
997
998  // Open display
999  display = XOpenDisplay(NULL);
1000
1001  if (!display)
1002   {
1003    fprintf (stderr,"Failed to open display!!!\n");
1004    DestroyDisplay();
1005    return;
1006   }
1007
1008  myscreen=DefaultScreen(display);
1009
1010  // desktop fullscreen switch
1011  if (!iWindowMode) fx = 1;
1012
1013  screen=DefaultScreenOfDisplay(display);
1014
1015  root_window_id=RootWindow(display,DefaultScreen(display));
1016
1017   //Look for an Xvideo RGB port
1018   ret = XvQueryAdaptors(display, root_window_id, &p_num_adaptors, &ai);
1019   if (ret != Success) {
1020     if (ret == XvBadExtension)
1021       printf("XvBadExtension returned at XvQueryExtension.\n");
1022     else
1023       if (ret == XvBadAlloc)
1024         printf("XvBadAlloc returned at XvQueryExtension.\n");
1025       else
1026         printf("other error happaned at XvQueryAdaptors.\n");
1027
1028     exit(-1);
1029   }
1030
1031   depth = DefaultDepth(display, myscreen);
1032
1033   for (i = 0; i < p_num_adaptors; i++) {
1034         p_num_ports = ai[i].base_id + ai[i].num_ports;
1035         for (p = ai[i].base_id; p < p_num_ports; p++) {
1036                 fo = XvListImageFormats(display, p, &formats);
1037                 for (j = 0; j < formats; j++) {
1038                         //backup YUV mode
1039                         //hmm, should I bother check guid == 55595659-0000-0010-8000-00aa00389b71?
1040                         //and check byte order?   fo[j].byte_order == LSBFirst
1041 #ifdef __BIG_ENDIAN__
1042                         if ( fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 && fo[j].format == XvPacked && strncmp("YUYV", fo[j].component_order, 5) == 0 )
1043 #else
1044                         if ( fo[j].type == XvYUV && fo[j].bits_per_pixel == 16 && fo[j].format == XvPacked && strncmp("UYVY", fo[j].component_order, 5) == 0 )
1045 #endif
1046                         {
1047                                 yuv_port = p;
1048                                 yuv_id = fo[j].id;
1049                         }
1050                         if (fo[j].type == XvRGB && fo[j].bits_per_pixel == 32)
1051                         {
1052                                 xv_port = p;
1053                                 xv_id = fo[j].id;
1054                                 xv_depth = fo[j].depth;
1055                                 printf("RGB mode found.  id: %x, depth: %d\n", xv_id, xv_depth);
1056
1057                                 if (xv_depth != depth) {
1058                                         printf("Warning: Depth does not match screen depth (%d)\n", depth);
1059                                 }
1060                                 else {
1061                                         //break out of loops
1062                                         j = formats;
1063                                         p = p_num_ports;
1064                                         i = p_num_adaptors;
1065                                 }
1066                         }
1067                 }
1068                 if (fo)
1069                         XFree(fo);
1070         }
1071   }
1072   if (p_num_adaptors > 0)
1073     XvFreeAdaptorInfo(ai);
1074   if (xv_port == -1 && yuv_port == -1)
1075   {
1076         printf("RGB & YUV not found.  Quitting.\n");
1077         exit(-1);
1078   }
1079   else if (xv_port == -1 && yuv_port != -1)
1080   {
1081         use_yuv = 1;
1082         printf("RGB not found.  Using YUV.\n");
1083         xv_port = yuv_port;
1084         xv_id = yuv_id;
1085   }
1086   else if (xv_depth && xv_depth != depth && yuv_port != -1)
1087   {
1088         use_yuv = 1;
1089         printf("Acceptable RGB mode not found.  Using YUV.\n");
1090         xv_port = yuv_port;
1091         xv_id = yuv_id;
1092   }
1093
1094   Atom atom_vsync = xv_intern_atom_if_exists(display, "XV_SYNC_TO_VBLANK");
1095   if (atom_vsync != None) {
1096         XvGetPortAttribute(display, xv_port, atom_vsync, &xv_vsync);
1097         XvSetPortAttribute(display, xv_port, atom_vsync, 0);
1098   }
1099
1100 myvisual = 0;
1101
1102 if(XMatchVisualInfo(display,myscreen, depth, TrueColor, &vi))
1103         myvisual = &vi;
1104
1105 if (!myvisual)
1106 {
1107         fprintf(stderr,"Failed to obtain visual!\n");
1108         DestroyDisplay();
1109         return;
1110 }
1111
1112  if(myvisual->red_mask==0x00007c00 &&
1113     myvisual->green_mask==0x000003e0 &&
1114     myvisual->blue_mask==0x0000001f)
1115      {iColDepth=15;}
1116  else
1117  if(myvisual->red_mask==0x0000f800 &&
1118     myvisual->green_mask==0x000007e0 &&
1119     myvisual->blue_mask==0x0000001f)
1120      {iColDepth=16;}
1121  else
1122  if(myvisual->red_mask==0x00ff0000 &&
1123     myvisual->green_mask==0x0000ff00 &&
1124     myvisual->blue_mask==0x000000ff)
1125      {iColDepth=32;}
1126  else
1127   {
1128    iColDepth=0;
1129 /*   fprintf(stderr,"COLOR DEPTH NOT SUPPORTED!\n");
1130    fprintf(stderr,"r: %08lx\n",myvisual->red_mask);
1131    fprintf(stderr,"g: %08lx\n",myvisual->green_mask);
1132    fprintf(stderr,"b: %08lx\n",myvisual->blue_mask);
1133    DestroyDisplay();
1134    return;*/
1135   }
1136
1137  // pffff... much work for a simple blank cursor... oh, well...
1138  if(iWindowMode) cursor=XCreateFontCursor(display,XC_trek);
1139  else
1140   {
1141    Pixmap p1,p2;
1142    XImage * img;
1143    XColor b,w;
1144    char * idata;
1145    XGCValues GCv;
1146    GC        GCc;
1147
1148    memset(&b,0,sizeof(XColor));
1149    memset(&w,0,sizeof(XColor));
1150    idata=(char *)malloc(8);
1151    memset(idata,0,8);
1152
1153    p1=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1);
1154    p2=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1);
1155
1156    img = XCreateImage(display,myvisual->visual,
1157                       1,XYBitmap,0,idata,8,8,8,1);
1158
1159    GCv.function   = GXcopy;
1160    GCv.foreground = ~0;
1161    GCv.background =  0;
1162    GCv.plane_mask = AllPlanes;
1163    GCc = XCreateGC(display,p1,
1164                    (GCFunction|GCForeground|GCBackground|GCPlaneMask),&GCv);
1165
1166    XPutImage(display, p1,GCc,img,0,0,0,0,8,8);
1167    XPutImage(display, p2,GCc,img,0,0,0,0,8,8);
1168    XFreeGC(display, GCc);
1169
1170    cursor = XCreatePixmapCursor(display,p1,p2,&b,&w,0,0);
1171
1172    XFreePixmap(display,p1);
1173    XFreePixmap(display,p2);
1174    XDestroyImage(img); // will free idata as well
1175   }
1176
1177  colormap=XCreateColormap(display,root_window_id,
1178                           myvisual->visual,AllocNone);
1179
1180  winattr.background_pixel=0;
1181  winattr.border_pixel=WhitePixelOfScreen(screen);
1182  winattr.bit_gravity=ForgetGravity;
1183  winattr.win_gravity=NorthWestGravity;
1184  winattr.backing_store=NotUseful;
1185
1186  winattr.override_redirect=False;
1187  winattr.save_under=False;
1188  winattr.event_mask=0;
1189  winattr.do_not_propagate_mask=0;
1190  winattr.colormap=colormap;
1191  winattr.cursor=None;
1192
1193  window=XCreateWindow(display,root_window_id,
1194                       0,0,iResX,iResY,
1195                       0,myvisual->depth,
1196                       InputOutput,myvisual->visual,
1197                       CWBorderPixel | CWBackPixel |
1198                       CWEventMask | CWDontPropagate |
1199                       CWColormap | CWCursor,
1200                       &winattr);
1201
1202  if(!window)
1203   {
1204    fprintf(stderr,"Failed in XCreateWindow()!!!\n");
1205    DestroyDisplay();
1206    return;
1207   }
1208
1209  delwindow = XInternAtom(display,"WM_DELETE_WINDOW",0);
1210  XSetWMProtocols(display, window, &delwindow, 1);
1211
1212  hints.flags=USPosition|USSize;
1213  hints.base_width = iResX;
1214  hints.base_height = iResY;
1215
1216  wm_hints.input=1;
1217  wm_hints.flags=InputHint;
1218
1219  XSetWMHints(display,window,&wm_hints);
1220  XSetWMNormalHints(display,window,&hints);
1221  if(pCaptionText)
1222       XStoreName(display,window,pCaptionText);
1223  else XStoreName(display,window,"P.E.Op.S SoftX PSX Gpu");
1224
1225  XDefineCursor(display,window,cursor);
1226
1227  // hack to get rid of window title bar 
1228  if (fx)
1229   {
1230    mwmhints.flags=MWM_HINTS_DECORATIONS;
1231    mwmhints.decorations=0;
1232    mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0);
1233    XChangeProperty(display,window,mwmatom,mwmatom,32,
1234                    PropModeReplace,(unsigned char *)&mwmhints,4);
1235   }
1236
1237  // key stuff
1238  XSelectInput(display,
1239               window,
1240               FocusChangeMask | ExposureMask |
1241               KeyPressMask | KeyReleaseMask
1242              );
1243
1244  XMapRaised(display,window);
1245  XClearWindow(display,window);
1246  XWindowEvent(display,window,ExposureMask,&event);
1247
1248  if (fx) // fullscreen
1249   {
1250    XResizeWindow(display,window,screen->width,screen->height);
1251
1252    hints.min_width   = hints.max_width = hints.base_width = screen->width;
1253    hints.min_height= hints.max_height = hints.base_height = screen->height;
1254
1255    XSetWMNormalHints(display,window,&hints);
1256
1257    // set the window layer for GNOME
1258    {
1259     XEvent xev;
1260
1261     memset(&xev, 0, sizeof(xev));
1262     xev.xclient.type = ClientMessage;
1263     xev.xclient.serial = 0;
1264     xev.xclient.send_event = 1;
1265     xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0);
1266     xev.xclient.window = window;
1267     xev.xclient.format = 32;
1268     xev.xclient.data.l[0] = 1;
1269     xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0);
1270     xev.xclient.data.l[2] = 0;
1271     xev.xclient.data.l[3] = 0;
1272     xev.xclient.data.l[4] = 0;
1273
1274     XSendEvent(display, root_window_id, 0,
1275       SubstructureRedirectMask | SubstructureNotifyMask, &xev);
1276    }
1277   }
1278
1279  gcv.graphics_exposures = False;
1280  hGC = XCreateGC(display,window,
1281                  GCGraphicsExposures, &gcv);
1282  if(!hGC) 
1283   {
1284    fprintf(stderr,"No gfx context!!!\n");
1285    DestroyDisplay();
1286   }
1287
1288
1289
1290  Xpixels = (char *)malloc(220*15*4);
1291  memset(Xpixels,255,220*15*4);
1292  XFimage = XCreateImage(display,myvisual->visual, 
1293                       depth, ZPixmap, 0, 
1294                       (char *)Xpixels,  
1295                       220, 15, 
1296                       depth>16 ? 32 : 16,
1297                       0); 
1298
1299  Xpixels = (char *)malloc(8*8*4);
1300  memset(Xpixels,0,8*8*4);
1301  XCimage = XvCreateImage(display,xv_port,xv_id,
1302                       (char *)Xpixels, 8, 8);
1303
1304
1305 /*
1306 Allocate max that could be needed:
1307 Big(est?) PSX res: 640x512
1308 32bpp (times 4)
1309 2xsai func= 3xwidth,3xheight
1310 = approx 11.8mb
1311 */
1312 shminfo.shmid = shmget(IPC_PRIVATE, 640*512*4*3*3, IPC_CREAT | 0777);
1313 shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
1314 shminfo.readOnly = 0;
1315  
1316  if (!XShmAttach(display, &shminfo)) {
1317     printf("XShmAttach failed !\n");
1318     exit (-1);
1319  }
1320 }
1321
1322 void (*p2XSaIFunc) (unsigned char *, DWORD, unsigned char *, int, int);
1323 unsigned char *pBackBuffer = 0;
1324
1325 void BlitScreen32(unsigned char *surf, int32_t x, int32_t y)
1326 {
1327  unsigned char *pD;
1328  unsigned int startxy;
1329  uint32_t lu;
1330  unsigned short s;
1331  unsigned short row, column;
1332  unsigned short dx = PreviousPSXDisplay.Range.x1;
1333  unsigned short dy = PreviousPSXDisplay.DisplayMode.y;
1334
1335  int32_t lPitch = PSXDisplay.DisplayMode.x << 2;
1336
1337  uint32_t *destpix;
1338
1339  if (PreviousPSXDisplay.Range.y0) // centering needed?
1340   {
1341    memset(surf, 0, (PreviousPSXDisplay.Range.y0 >> 1) * lPitch);
1342
1343    dy -= PreviousPSXDisplay.Range.y0;
1344    surf += (PreviousPSXDisplay.Range.y0 >> 1) * lPitch;
1345
1346    memset(surf + dy * lPitch,
1347           0, ((PreviousPSXDisplay.Range.y0 + 1) >> 1) * lPitch);
1348   }
1349
1350  if (PreviousPSXDisplay.Range.x0)
1351   {
1352    for (column = 0; column < dy; column++)
1353     {
1354      destpix = (uint32_t *)(surf + (column * lPitch));
1355      memset(destpix, 0, PreviousPSXDisplay.Range.x0 << 2);
1356     }
1357    surf += PreviousPSXDisplay.Range.x0 << 2;
1358   }
1359
1360  if (PSXDisplay.RGB24)
1361   {
1362    for (column = 0; column < dy; column++)
1363     {
1364      startxy = ((1024) * (column + y)) + x;
1365      pD = (unsigned char *)&psxVuw[startxy];
1366      destpix = (uint32_t *)(surf + (column * lPitch));
1367      for (row = 0; row < dx; row++)
1368       {
1369        lu = *((uint32_t *)pD);
1370        destpix[row] = 
1371           0xff000000 | (RED(lu) << 16) | (GREEN(lu) << 8) | (BLUE(lu));
1372        pD += 3;
1373       }
1374     }
1375   }
1376  else
1377   {
1378    for (column = 0;column<dy;column++)
1379     {
1380      startxy = (1024 * (column + y)) + x;
1381      destpix = (uint32_t *)(surf + (column * lPitch));
1382      for (row = 0; row < dx; row++)
1383       {
1384        s = GETLE16(&psxVuw[startxy++]);
1385        destpix[row] = 
1386           (((s << 19) & 0xf80000) | ((s << 6) & 0xf800) | ((s >> 7) & 0xf8)) | 0xff000000;
1387       }
1388     }
1389   }
1390 }
1391
1392 void BlitToYUV(unsigned char * surf,int32_t x,int32_t y)
1393 {
1394  unsigned char * pD;
1395  unsigned int startxy;
1396  uint32_t lu;unsigned short s;
1397  unsigned short row,column;
1398  unsigned short dx = PreviousPSXDisplay.Range.x1;
1399  unsigned short dy = PreviousPSXDisplay.DisplayMode.y;
1400  int Y,U,V, R,G,B;
1401
1402  int32_t lPitch = PSXDisplay.DisplayMode.x << 2;
1403  uint32_t *destpix;
1404
1405  if (PreviousPSXDisplay.Range.y0) // centering needed?
1406   {
1407    for (column = 0; column < (PreviousPSXDisplay.Range.y0 >> 1); column++)
1408     {
1409      destpix = (uint32_t *)(surf + column * lPitch);
1410      for (row = 0; row < dx; row++)
1411      {
1412       destpix[row] = (4 << 24) | (128 << 16) | (4 << 8) | 128;
1413      }
1414     }
1415
1416    dy -= PreviousPSXDisplay.Range.y0;
1417    surf += (PreviousPSXDisplay.Range.y0 >> 1) * lPitch;
1418
1419    for (column = 0; column < (PreviousPSXDisplay.Range.y0 + 1) >> 1; column++)
1420     {
1421      destpix = (uint32_t *)(surf + (dy + column) * lPitch);
1422      for (row = 0; row < dx; row++)
1423      {
1424       destpix[row] = (4 << 24) | (128 << 16) | (4 << 8) | 128;
1425      }
1426     }
1427   }
1428
1429  if (PreviousPSXDisplay.Range.x0)
1430   {
1431    for (column = 0; column < dy; column++)
1432     {
1433      destpix = (uint32_t *)(surf + (column * lPitch));
1434      for (row = 0; row < PreviousPSXDisplay.Range.x0; row++)
1435       {
1436        destpix[row] = (4 << 24) | (128 << 16) | (4 << 8) | 128;
1437       }
1438     }
1439    surf += PreviousPSXDisplay.Range.x0 << 2;
1440   }
1441
1442  if (PSXDisplay.RGB24)
1443   {
1444    for (column = 0; column < dy; column++)
1445     {
1446      startxy = (1024 * (column + y)) + x;
1447      pD = (unsigned char *)&psxVuw[startxy];
1448      destpix = (uint32_t *)(surf + (column * lPitch));
1449      for (row = 0; row < dx; row++)
1450       {
1451        lu = *((uint32_t *)pD);
1452
1453        R = RED(lu);
1454        G = GREEN(lu);
1455        B = BLUE(lu);
1456
1457        Y = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235);
1458        U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240);
1459        V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240);
1460
1461 #ifdef __BIG_ENDIAN__
1462        destpix[row] = Y << 24 | U << 16 | Y << 8 | V;
1463 #else
1464        destpix[row] = Y << 24 | V << 16 | Y << 8 | U;
1465 #endif
1466        pD += 3;
1467       }
1468     }
1469   }
1470  else
1471   {
1472    for (column = 0; column < dy; column++)
1473     {
1474      startxy = (1024 * (column + y)) + x;
1475      destpix = (uint32_t *)(surf + (column * lPitch));
1476      for (row = 0; row < dx; row++)
1477       {
1478        s = GETLE16(&psxVuw[startxy++]);
1479
1480        R = (s << 3) &0xf8;
1481        G = (s >> 2) &0xf8;
1482        B = (s >> 7) &0xf8;
1483
1484        Y = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235);
1485        U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240);
1486        V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240);
1487
1488 #ifdef __BIG_ENDIAN__
1489        destpix[row] = Y << 24 | U << 16 | Y << 8 | V;
1490 #else
1491        destpix[row] = Y << 24 | V << 16 | Y << 8 | U;
1492 #endif
1493       }
1494     }
1495   }
1496 }
1497
1498 //dst will have half the pitch (32bit to 16bit)
1499 void RGB2YUV(uint32_t *s, int width, int height, uint32_t *d)
1500 {
1501         int x,y;
1502         int R,G,B, Y1,Y2,U,V;
1503
1504         for (y=0; y<height; y++) {
1505                 for(x=0; x<width>>1; x++) {
1506                         R = (*s >> 16) & 0xff;
1507                         G = (*s >> 8) & 0xff;
1508                         B = *s & 0xff;
1509                         s++;
1510
1511                         Y1 = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235);
1512                         U = min(abs(R * -1214 + G * -2384 + B * 3598 + 4096 + 1048576) >> 13, 240);
1513                         V = min(abs(R * 3598 + G * -3013 + B * -585 + 4096 + 1048576) >> 13, 240);
1514
1515                         R = (*s >> 16) & 0xff;
1516                         G = (*s >> 8) & 0xff;
1517                         B = *s & 0xff;
1518                         s++;
1519
1520                         Y2 = min(abs(R * 2104 + G * 4130 + B * 802 + 4096 + 131072) >> 13, 235);
1521
1522 #ifdef __BIG_ENDIAN__
1523                         *d = V | Y2 << 8 | U << 16 | Y1 << 24;
1524 #else
1525                         *d = U | Y1 << 8 | V << 16 | Y2 << 24;
1526 #endif
1527                         d++;
1528                 }
1529         }
1530 }
1531
1532 extern time_t tStart;
1533
1534 //Note: dest x,y,w,h are both input and output variables
1535 inline void MaintainAspect(unsigned int *dx,unsigned int *dy,unsigned int *dw,unsigned int *dh)
1536 {
1537         //Currently just 4/3 aspect ratio
1538         int t;
1539
1540         if (*dw * 3 > *dh * 4) {
1541                 t = *dh * 4.0f / 3;     //new width aspect
1542                 *dx = (*dw - t) / 2;    //centering
1543                 *dw = t;
1544         } else {
1545                 t = *dw * 3.0f / 4;
1546                 *dy = (*dh - t) / 2;
1547                 *dh = t;
1548         }
1549 }
1550
1551 void DoBufferSwap(void)
1552 {
1553         Screen *screen;
1554         Window _dw;
1555         XvImage *xvi;
1556         unsigned int dstx, dsty, srcy = 0;
1557         unsigned int _d, _w, _h;        //don't care about _d
1558
1559         finalw = PSXDisplay.DisplayMode.x;
1560         finalh = PSXDisplay.DisplayMode.y;
1561
1562         if (finalw == 0 || finalh == 0)
1563                 return;
1564
1565         XSync(display,False);
1566
1567         if(use_yuv) {
1568                 if (iUseNoStretchBlt==0 || finalw > 320 || finalh > 256) {
1569                         BlitToYUV((unsigned char *)shminfo.shmaddr, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y);
1570                         finalw <<= 1;
1571                 } else {
1572                         BlitScreen32((unsigned char *)pBackBuffer, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y);
1573                         p2XSaIFunc(pBackBuffer, finalw<<2, (unsigned char *)pSaIBigBuff,finalw,finalh);
1574                         RGB2YUV( (uint32_t*)pSaIBigBuff, finalw, finalh, (uint32_t*)shminfo.shmaddr);
1575                 }
1576         } else if(iUseNoStretchBlt==0 || finalw > 320 || finalh > 256) {
1577                 BlitScreen32((unsigned char *)shminfo.shmaddr, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y);
1578         } else {
1579                 BlitScreen32((unsigned char *)pBackBuffer, PSXDisplay.DisplayPosition.x, PSXDisplay.DisplayPosition.y);
1580                 p2XSaIFunc(pBackBuffer, finalw<<2, (unsigned char *)shminfo.shmaddr,finalw,finalh);
1581         }
1582
1583         XGetGeometry(display, window, &_dw, (int *)&_d, (int *)&_d, &_w, &_h, &_d, &_d);
1584         if (use_yuv) {
1585                 xvi = XvShmCreateImage(display, yuv_port, yuv_id, 0, finalw, finalh, &shminfo);
1586         } else
1587                 xvi = XvShmCreateImage(display, xv_port, xv_id, 0, finalw, finalh, &shminfo);
1588
1589         xvi->data = shminfo.shmaddr;
1590
1591         screen=DefaultScreenOfDisplay(display); 
1592         //screennum = DefaultScreen(display);
1593
1594         if (!iWindowMode) {
1595                 _w = screen->width;
1596                 _h = screen->height;
1597         }
1598
1599         dstx = 0;
1600         dsty = 0;
1601
1602         if (iMaintainAspect)
1603                 MaintainAspect(&dstx, &dsty, &_w, &_h);
1604
1605         if (ulKeybits&KEY_SHOWFPS)      //to avoid flicker, don't paint overtop FPS bar
1606         {
1607                 srcy = 15 * finalh / _h;
1608                 dsty += 15;
1609         }
1610
1611         XvShmPutImage(display, xv_port, window, hGC, xvi, 
1612                 0,srcy,         //src x,y
1613                 finalw,finalh,  //src w,h
1614                 dstx,dsty,      //dst x,y
1615                 _w,_h,          //dst w,h
1616                 1
1617                 );
1618
1619         if(ulKeybits&KEY_SHOWFPS) //DisplayText();               // paint menu text 
1620         {
1621                 if(szDebugText[0] && ((time(NULL) - tStart) < 2))
1622                 {
1623                         strcpy(szDispBuf,szDebugText);
1624                 }
1625                 else 
1626                 {
1627                         szDebugText[0]=0;
1628                         strcat(szDispBuf,szMenuBuf);
1629                 }
1630
1631                 //XPutImage(display,window,hGC, XFimage, 
1632                 //          0, 0, 0, 0, 220,15);
1633                 XFree(xvi);
1634                 xvi = XvCreateImage(display, xv_port, xv_id, XFimage->data, 220, 15);
1635                 XvPutImage(display, xv_port, window, hGC, xvi, 
1636                         0,0,            //src x,y
1637                         220,15,         //src w,h
1638                         0,0,            //dst x,y
1639                         220,15          //dst w,h
1640                         );
1641
1642                 XDrawString(display,window,hGC,2,13,szDispBuf,strlen(szDispBuf));
1643         }
1644         
1645         //if(XPimage) DisplayPic();
1646         
1647
1648         XFree(xvi);
1649 }
1650
1651 void DoClearScreenBuffer(void)                         // CLEAR DX BUFFER
1652 {
1653  Window _dw;
1654  unsigned int _d, _w, _h;       //don't care about _d
1655
1656  XGetGeometry(display, window, &_dw, (int *)&_d, (int *)&_d, &_w, &_h, &_d, &_d);
1657
1658  XvPutImage(display, xv_port, window, hGC, XCimage,
1659            0, 0, 8, 8, 0, 0, _w, _h);
1660  //XSync(display,False);
1661 }
1662
1663 void DoClearFrontBuffer(void)                          // CLEAR DX BUFFER
1664 {/*
1665  XPutImage(display,window,hGC, XCimage,
1666            0, 0, 0, 0, iResX, iResY);
1667  XSync(display,False);*/
1668 }
1669
1670 int Xinitialize()
1671 {
1672    iDesktopCol=32;
1673
1674
1675  if(iUseNoStretchBlt>0)
1676   {
1677    pBackBuffer=(unsigned char *)malloc(640*512*sizeof(uint32_t));
1678    memset(pBackBuffer,0,640*512*sizeof(uint32_t));
1679    if (use_yuv) {
1680     pSaIBigBuff=malloc(640*512*4*3*3);
1681     memset(pSaIBigBuff,0,640*512*4*3*3);
1682    }
1683   }
1684
1685  p2XSaIFunc=NULL;
1686
1687  if(iUseNoStretchBlt==1)
1688   {
1689    p2XSaIFunc=Std2xSaI_ex8;
1690   }
1691
1692  if(iUseNoStretchBlt==2)
1693   {
1694    p2XSaIFunc=Super2xSaI_ex8;
1695   }
1696
1697  if(iUseNoStretchBlt==3)
1698   {
1699    p2XSaIFunc=SuperEagle_ex8;
1700   }
1701
1702  if(iUseNoStretchBlt==4)
1703   {
1704    p2XSaIFunc=Scale2x_ex8;
1705   }
1706  if(iUseNoStretchBlt==5)
1707   {
1708    p2XSaIFunc=Scale3x_ex8;
1709   }
1710  if(iUseNoStretchBlt==6)
1711   {
1712    p2XSaIFunc=hq2x_32;
1713   }
1714  if(iUseNoStretchBlt==7)
1715   {
1716    p2XSaIFunc=hq3x_32;
1717   }
1718
1719  bUsingTWin=FALSE;
1720
1721  InitMenu();
1722
1723  bIsFirstFrame = FALSE;                                // done
1724
1725  if(iShowFPS)
1726   {
1727    iShowFPS=0;
1728    ulKeybits|=KEY_SHOWFPS;
1729    szDispBuf[0]=0;
1730    BuildDispMenu(0);
1731   }
1732
1733  return 0;
1734 }
1735
1736 void Xcleanup()                                        // X CLEANUP
1737 {
1738  CloseMenu();
1739
1740  if(iUseNoStretchBlt>0) 
1741   {
1742    if(pBackBuffer)  free(pBackBuffer);
1743    pBackBuffer=0;
1744    if(pSaIBigBuff) free(pSaIBigBuff);
1745    pSaIBigBuff=0;
1746   }
1747 }
1748
1749 unsigned long ulInitDisplay(void)
1750 {
1751  CreateDisplay();                                      // x stuff
1752  Xinitialize();                                        // init x
1753  return (unsigned long)display;
1754 }
1755
1756 void CloseDisplay(void)
1757 {
1758  Xcleanup();                                           // cleanup dx
1759  DestroyDisplay();
1760 }
1761
1762 void CreatePic(unsigned char * pMem)
1763 {
1764  unsigned char * p=(unsigned char *)malloc(128*96*4);
1765  unsigned char * ps; int x,y;
1766
1767  ps=p;
1768
1769  if(iDesktopCol==16)
1770   {
1771    unsigned short s;
1772    for(y=0;y<96;y++)
1773     {
1774      for(x=0;x<128;x++)
1775       {
1776        s=(*(pMem+0))>>3;
1777        s|=((*(pMem+1))&0xfc)<<3;
1778        s|=((*(pMem+2))&0xf8)<<8;
1779        pMem+=3;
1780        *((unsigned short *)(ps+y*256+x*2))=s;
1781       }
1782     }
1783   }
1784  else
1785  if(iDesktopCol==15)
1786   {
1787    unsigned short s;
1788    for(y=0;y<96;y++)
1789     {
1790      for(x=0;x<128;x++)
1791       {
1792        s=(*(pMem+0))>>3;
1793        s|=((*(pMem+1))&0xfc)<<2;
1794        s|=((*(pMem+2))&0xf8)<<7;
1795        pMem+=3;
1796        *((unsigned short *)(ps+y*256+x*2))=s;
1797       }
1798     }
1799   }
1800  else
1801  if(iDesktopCol==32)
1802   {
1803    uint32_t l;
1804    for(y=0;y<96;y++)
1805     {
1806      for(x=0;x<128;x++)
1807       {
1808        l=  *(pMem+0);
1809        l|=(*(pMem+1))<<8;
1810        l|=(*(pMem+2))<<16;
1811        pMem+=3;
1812        *((uint32_t *)(ps+y*512+x*4))=l;
1813       }
1814     }
1815   }
1816
1817  XPimage = XCreateImage(display,myvisual->visual,
1818                         depth, ZPixmap, 0,
1819                         (char *)p, 
1820                         128, 96,
1821                         depth>16 ? 32 : 16,
1822                         0);
1823 }
1824
1825 void DestroyPic(void)
1826 {
1827  if(XPimage) 
1828   { /*
1829    XPutImage(display,window,hGC, XCimage,
1830           0, 0, 0, 0, iResX, iResY);*/
1831    XDestroyImage(XPimage);
1832    XPimage=0; 
1833   } 
1834 }
1835
1836 void DisplayPic(void)
1837 {
1838  XPutImage(display,window,hGC, XPimage,
1839            0, 0, iResX-128, 0,128,96);
1840 }
1841
1842 void ShowGpuPic(void)
1843 {
1844 }
1845
1846 void ShowTextGpuPic(void)
1847 {
1848 }
1849
1850 static void hq2x_32_def(uint32_t * dst0, uint32_t * dst1, const uint32_t * src0, const uint32_t * src1, const uint32_t * src2, unsigned count)
1851 {
1852         static unsigned char cache_vert_mask[640];
1853         unsigned char cache_horiz_mask = 0;
1854         
1855         unsigned i;
1856         unsigned char mask;
1857         uint32_t  c[9];
1858
1859         if (src0 == src1)       //processing first row
1860                 memset(cache_vert_mask, 0, count);      
1861         
1862         for(i=0;i<count;++i) {
1863                 c[1] = src0[0];
1864                 c[4] = src1[0];
1865                 c[7] = src2[0];
1866
1867                 if (i>0) {
1868                         c[0] = src0[-1];
1869                         c[3] = src1[-1];
1870                         c[6] = src2[-1];
1871                 } else {
1872                         c[0] = c[1];
1873                         c[3] = c[4];
1874                         c[6] = c[7];
1875                 }
1876
1877                 if (i<count-1) {
1878                         c[2] = src0[1];
1879                         c[5] = src1[1];
1880                         c[8] = src2[1];
1881                 } else {
1882                         c[2] = c[1];
1883                         c[5] = c[4];
1884                         c[8] = c[7];
1885                 }
1886
1887                 mask = 0;
1888
1889                 mask |= interp_32_diff(c[0], c[4]) << 0;
1890                 mask |= cache_vert_mask[i];
1891                 mask |= interp_32_diff(c[2], c[4]) << 2;
1892                 mask |= cache_horiz_mask;
1893                 cache_horiz_mask = interp_32_diff(c[5], c[4]) << 3;
1894                 mask |= cache_horiz_mask << 1;  // << 3 << 1 == << 4
1895                 mask |= interp_32_diff(c[6], c[4]) << 5;
1896                 cache_vert_mask[i] = interp_32_diff(c[7], c[4]) << 1;
1897                 mask |= cache_vert_mask[i] << 5; // << 1 << 5 == << 6
1898                 mask |= interp_32_diff(c[8], c[4]) << 7;
1899
1900
1901                 switch (mask) {
1902 #include "hq2x.h"
1903                 }
1904
1905
1906                 src0 += 1;
1907                 src1 += 1;
1908                 src2 += 1;
1909                 dst0 += 2;
1910                 dst1 += 2;
1911         }
1912 }
1913
1914 void hq2x_32( unsigned char * srcPtr,  DWORD srcPitch, unsigned char * dstPtr, int width, int height)
1915 {
1916         const int dstPitch = srcPitch<<1;
1917
1918         int count = height;
1919
1920         finalw=width*2;
1921         finalh=height*2;
1922
1923         uint32_t  *dst0 = (uint32_t  *)dstPtr;
1924         uint32_t  *dst1 = dst0 + (dstPitch >> 2);
1925
1926         uint32_t  *src0 = (uint32_t  *)srcPtr;
1927         uint32_t  *src1 = src0 + (srcPitch >> 2);
1928         uint32_t  *src2 = src1 + (srcPitch >> 2);
1929         hq2x_32_def(dst0, dst1, src0, src0, src1, width);
1930
1931
1932         count -= 2;
1933         while(count) {
1934                 dst0 += dstPitch >> 1;          //next 2 lines (dstPitch / 4 char per int * 2)
1935                 dst1 += dstPitch >> 1;
1936                 hq2x_32_def(dst0, dst1, src0, src1, src2, width);
1937                 src0 = src1;
1938                 src1 = src2;
1939                 src2 += srcPitch >> 2;
1940                 --count;
1941         }
1942         dst0 += dstPitch >> 1;
1943         dst1 += dstPitch >> 1;
1944         hq2x_32_def(dst0, dst1, src0, src1, src1, width);
1945 }
1946
1947 static void hq3x_32_def(uint32_t*  dst0, uint32_t*  dst1, uint32_t*  dst2, const uint32_t* src0, const uint32_t* src1, const uint32_t* src2, unsigned count)
1948 {
1949         static unsigned char cache_vert_mask[640];
1950         unsigned char cache_horiz_mask = 0;
1951
1952         unsigned i;
1953         unsigned char mask;
1954         uint32_t  c[9];
1955
1956         if (src0 == src1)       //processing first row
1957                 memset(cache_vert_mask, 0, count);      
1958
1959         for(i=0;i<count;++i) {
1960                 c[1] = src0[0];
1961                 c[4] = src1[0];
1962                 c[7] = src2[0];
1963
1964                 if (i>0) {
1965                         c[0] = src0[-1];
1966                         c[3] = src1[-1];
1967                         c[6] = src2[-1];
1968                 } else {
1969                         c[0] = c[1];
1970                         c[3] = c[4];
1971                         c[6] = c[7];
1972                 }
1973
1974                 if (i<count-1) {
1975                         c[2] = src0[1];
1976                         c[5] = src1[1];
1977                         c[8] = src2[1];
1978                 } else {
1979                         c[2] = c[1];
1980                         c[5] = c[4];
1981                         c[8] = c[7];
1982                 }
1983
1984                 mask = 0;
1985                 
1986                 mask |= interp_32_diff(c[0], c[4]) << 0;
1987                 mask |= cache_vert_mask[i];
1988                 mask |= interp_32_diff(c[2], c[4]) << 2;
1989                 mask |= cache_horiz_mask;
1990                 cache_horiz_mask = interp_32_diff(c[5], c[4]) << 3;
1991                 mask |= cache_horiz_mask << 1;  // << 3 << 1 == << 4
1992                 mask |= interp_32_diff(c[6], c[4]) << 5;
1993                 cache_vert_mask[i] = interp_32_diff(c[7], c[4]) << 1;
1994                 mask |= cache_vert_mask[i] << 5; // << 1 << 5 == << 6
1995                 mask |= interp_32_diff(c[8], c[4]) << 7;
1996
1997                 switch (mask) {
1998 #include "hq3x.h"
1999                 }
2000
2001                 src0 += 1;
2002                 src1 += 1;
2003                 src2 += 1;
2004                 dst0 += 3;
2005                 dst1 += 3;
2006                 dst2 += 3;
2007         }
2008 }
2009
2010 void hq3x_32( unsigned char * srcPtr,  DWORD srcPitch, unsigned char * dstPtr, int width, int height)
2011 {
2012         int count = height;
2013
2014         int dstPitch = srcPitch*3;
2015         int dstRowPixels = dstPitch>>2;
2016
2017         finalw=width*3;
2018         finalh=height*3;
2019
2020         uint32_t  *dst0 = (uint32_t  *)dstPtr;
2021         uint32_t  *dst1 = dst0 + dstRowPixels;
2022         uint32_t  *dst2 = dst1 + dstRowPixels;
2023
2024         uint32_t  *src0 = (uint32_t  *)srcPtr;
2025         uint32_t  *src1 = src0 + (srcPitch >> 2);
2026         uint32_t  *src2 = src1 + (srcPitch >> 2);
2027         hq3x_32_def(dst0, dst1, dst2, src0, src0, src2, width);
2028
2029         count -= 2;
2030         while(count) {
2031                 dst0 += dstRowPixels * 3;
2032                 dst1 += dstRowPixels * 3;
2033                 dst2 += dstRowPixels * 3;
2034
2035                 hq3x_32_def(dst0, dst1, dst2, src0, src1, src2, width);
2036                 src0 = src1;
2037                 src1 = src2;
2038                 src2 += srcPitch >> 2;
2039                 --count;
2040         }
2041         dst0 += dstRowPixels * 3;
2042         dst1 += dstRowPixels * 3;
2043         dst2 += dstRowPixels * 3;
2044
2045         hq3x_32_def(dst0, dst1, dst2, src0, src1, src1, width);
2046
2047 }