psx_gpu: do enhanced lines
[pcsx_rearmed.git] / plugins / gpu-gles / gpuPlugin.c
1 /***************************************************************************\r
2                            gpu.c  -  description\r
3                              -------------------\r
4     begin                : Sun Mar 08 2009\r
5     copyright            : (C) 1999-2009 by Pete Bernert\r
6     email                : BlackDove@addcom.de\r
7  ***************************************************************************/\r
8 \r
9 /***************************************************************************\r
10  *                                                                         *\r
11  *   This program is free software; you can redistribute it and/or modify  *\r
12  *   it under the terms of the GNU General Public License as published by  *\r
13  *   the Free Software Foundation; either version 2 of the License, or     *\r
14  *   (at your option) any later version. See also the license.txt file for *\r
15  *   additional informations.                                              *\r
16  *                                                                         *\r
17  ***************************************************************************/\r
18 \r
19 //*************************************************************************// \r
20 // History of changes:\r
21 //\r
22 // 2009/03/08 - Pete  \r
23 // - generic cleanup for the Peops release\r
24 //\r
25 //*************************************************************************// \r
26 \r
27 //#include "gpuStdafx.h"\r
28 \r
29 //#include <mmsystem.h>\r
30 #define _IN_GPU\r
31 \r
32 #include <stdlib.h>\r
33 #include <stdio.h>\r
34 #include <stdarg.h>\r
35 #include <string.h>\r
36 #include "gpuExternals.h"\r
37 #include "gpuPlugin.h"\r
38 #include "gpuDraw.h"\r
39 #include "gpuTexture.h"\r
40 #include "gpuFps.h"\r
41 #include "gpuPrim.h"\r
42 \r
43 //#include "NoPic.h"\r
44 \r
45 #include "gpuStdafx.h"\r
46 \r
47 short g_m1=255,g_m2=255,g_m3=255;\r
48 short DrawSemiTrans=FALSE;\r
49 short Ymin;\r
50 short Ymax;\r
51 \r
52 short          ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3;        // global psx vertex coords\r
53 long           GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP;\r
54 long           GlobalTextREST,GlobalTextABR,GlobalTextPAGE;\r
55 \r
56 unsigned long dwGPUVersion=0;\r
57 int           iGPUHeight=512;\r
58 int           iGPUHeightMask=511;\r
59 int           GlobalTextIL=0;\r
60 int           iTileCheat=0;\r
61 \r
62 ////////////////////////////////////////////////////////////////////////\r
63 // memory image of the PSX vram\r
64 ////////////////////////////////////////////////////////////////////////\r
65 \r
66 unsigned char  *psxVSecure;\r
67 unsigned char  *psxVub;\r
68 signed   char  *psxVsb;\r
69 unsigned short *psxVuw;\r
70 unsigned short *psxVuw_eom;\r
71 signed   short *psxVsw;\r
72 unsigned long  *psxVul;\r
73 signed   long  *psxVsl;\r
74 \r
75 // macro for easy access to packet information\r
76 #define GPUCOMMAND(x) ((x>>24) & 0xff)\r
77 \r
78 GLfloat         gl_z=0.0f;\r
79 BOOL            bNeedInterlaceUpdate=FALSE;\r
80 BOOL            bNeedRGB24Update=FALSE;\r
81 BOOL            bChangeWinMode=FALSE;\r
82 \r
83 unsigned long   ulStatusControl[256];\r
84 \r
85 ////////////////////////////////////////////////////////////////////////\r
86 // global GPU vars\r
87 ////////////////////////////////////////////////////////////////////////\r
88 \r
89 static long     GPUdataRet;\r
90 long            lGPUstatusRet;\r
91 char            szDispBuf[64];\r
92 \r
93 static unsigned long gpuDataM[256];\r
94 static unsigned char gpuCommand = 0;\r
95 static long          gpuDataC = 0;\r
96 static long          gpuDataP = 0;\r
97 \r
98 VRAMLoad_t      VRAMWrite;\r
99 VRAMLoad_t      VRAMRead;\r
100 int             iDataWriteMode;\r
101 int             iDataReadMode;\r
102 \r
103 long            lClearOnSwap;\r
104 long            lClearOnSwapColor;\r
105 BOOL            bSkipNextFrame = FALSE;\r
106 int             iColDepth;\r
107 BOOL            bChangeRes;\r
108 BOOL            bWindowMode;\r
109 int             iWinSize;\r
110 \r
111 // possible psx display widths\r
112 short dispWidths[8] = {256,320,512,640,368,384,512,640};\r
113 \r
114 PSXDisplay_t    PSXDisplay;\r
115 PSXDisplay_t    PreviousPSXDisplay;\r
116 TWin_t          TWin;\r
117 short           imageX0,imageX1;\r
118 short           imageY0,imageY1;\r
119 BOOL            bDisplayNotSet = TRUE;\r
120 GLuint          uiScanLine=0;\r
121 int             iUseScanLines=0;\r
122 long            lSelectedSlot=0;\r
123 unsigned char * pGfxCardScreen=0;\r
124 int             iBlurBuffer=0;\r
125 int             iScanBlend=0;\r
126 int             iRenderFVR=0;\r
127 int             iNoScreenSaver=0;\r
128 unsigned long   ulGPUInfoVals[16];\r
129 int             iFakePrimBusy = 0;\r
130 int             iRumbleVal    = 0;\r
131 int             iRumbleTime   = 0;\r
132 \r
133 static void (*rearmed_get_layer_pos)(int *x, int *y, int *w, int *h);\r
134 static void flipEGL(void);\r
135 \r
136 ////////////////////////////////////////////////////////////////////////\r
137 // stuff to make this a true PDK module\r
138 ////////////////////////////////////////////////////////////////////////\r
139 \r
140 ////////////////////////////////////////////////////////////////////////\r
141 // snapshot funcs (saves screen to bitmap / text infos into file)\r
142 ////////////////////////////////////////////////////////////////////////\r
143 \r
144 void ResizeWindow()\r
145 {\r
146  rRatioRect.left   = rRatioRect.top=0;\r
147  rRatioRect.right  = iResX;\r
148  rRatioRect.bottom = iResY;\r
149  glViewport(rRatioRect.left,                           // init viewport by ratio rect\r
150             iResY-(rRatioRect.top+rRatioRect.bottom),\r
151             rRatioRect.right, \r
152             rRatioRect.bottom); glError();\r
153                                                       \r
154  glScissor(0, 0, iResX, iResY); glError();             // init clipping (fullscreen)\r
155  glEnable(GL_SCISSOR_TEST); glError();\r
156 \r
157 #ifndef OWNSCALE\r
158  glMatrixMode(GL_TEXTURE);                             // init psx tex sow and tow if not "ownscale"\r
159  glLoadIdentity();\r
160  glScalef(1.0f/255.99f,1.0f/255.99f,1.0f);             // geforce precision hack\r
161 #endif \r
162 \r
163  glMatrixMode(GL_PROJECTION); glError();               // init projection with psx resolution\r
164  glLoadIdentity(); glError();\r
165  glOrtho(0,PSXDisplay.DisplayMode.x,\r
166          PSXDisplay.DisplayMode.y, 0, -1, 1); glError();\r
167  if (bKeepRatio)\r
168  SetAspectRatio();\r
169 }\r
170 \r
171 char * GetConfigInfos(int hW)\r
172 {\r
173  char szO[2][4]={"off","on "};\r
174  char szTxt[256];\r
175  char * pB=(char *)malloc(32767);\r
176 /*\r
177  if(!pB) return NULL;\r
178  *pB=0;\r
179  //----------------------------------------------------//\r
180  strcat(pB,szTxt);\r
181  strcat(pB,szTxt);\r
182 #ifdef _WINDOWS\r
183  if(hW)\r
184   {\r
185    hdc = GetDC(hW);\r
186    bSetupPixelFormat(hdc);\r
187    hglrc = wglCreateContext(hdc);\r
188    wglMakeCurrent(hdc, hglrc);\r
189   }\r
190 #endif\r
191  sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR));\r
192  strcat(pB,szTxt);\r
193  sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER));\r
194  strcat(pB,szTxt);\r
195  sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION));\r
196  strcat(pB,szTxt);\r
197  //strcat(pB,(char *)glGetString(GL_EXTENSIONS));\r
198  //strcat(pB,"\r\n\r\n");\r
199 \r
200 #ifdef _WINDOWS\r
201  if(hW)\r
202   {\r
203    wglMakeCurrent(NULL, NULL);\r
204    wglDeleteContext(hglrc);\r
205    ReleaseDC(hW,hdc);\r
206   }\r
207  //----------------------------------------------------//\r
208 #endif\r
209  if(hW && bWindowMode)\r
210   sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize));\r
211  else\r
212   sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY);\r
213  strcat(pB,szTxt);\r
214  if(bWindowMode) sprintf(szTxt,"Window mode\r\n");\r
215  else\r
216   {\r
217    sprintf(szTxt,"Fullscreen ");\r
218    strcat(pB,szTxt);\r
219    if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth);\r
220    else           sprintf(szTxt,"- NO desktop changing\r\n");\r
221   }                                                                                   \r
222  strcat(pB,szTxt);\r
223 \r
224 // if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]);\r
225 // else               strcpy(szTxt,"- V-Sync: Driver\r\n");\r
226  strcat(pB,szTxt); \r
227  sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]);\r
228  strcat(pB,szTxt);\r
229  //----------------------------------------------------//\r
230  strcpy(szTxt,"Textures:\r\n- ");\r
231 /*! if(iTexQuality==0)      strcat(szTxt,"Default");\r
232  else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4");\r
233  else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1");\r
234  else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8");\r
235  else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8");\r
236  if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n");\r
237  else              strcat(szTxt,"\r\n");\r
238  strcat(pB,szTxt);\r
239  if(!hW)\r
240   {\r
241    sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType);\r
242    if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n");\r
243    else                             strcat(szTxt,"NOT supported\r\n");\r
244   }\r
245  else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType);\r
246  strcat(pB,szTxt);\r
247  sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures);\r
248  strcat(pB,szTxt); \r
249  if(!hW)\r
250   {\r
251    sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]);\r
252    strcat(pB,szTxt); \r
253   }\r
254  !*/\r
255  /*sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize);\r
256  if(!hW)\r
257       sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt);\r
258  else strcat(szTxt,"\r\n\r\n");\r
259  strcat(pB,szTxt);\r
260  //----------------------------------------------------//\r
261  sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]);\r
262  strcat(pB,szTxt);\r
263  sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]);\r
264  strcat(pB,szTxt);\r
265  if(iFrameLimit==2)\r
266       strcpy(szTxt,"- FPS limit: Auto\r\n\r\n");\r
267  else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate);\r
268  strcat(pB,szTxt);\r
269  //----------------------------------------------------//\r
270  sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing);\r
271  strcat(pB,szTxt);\r
272  sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType);\r
273  if(!hW && iFrameTexType==2)\r
274   {\r
275    if(gTexFrameName) strcat(szTxt," - texture created\r\n");\r
276    else              strcat(szTxt," - not used yet\r\n");\r
277   }\r
278  else strcat(szTxt,"\r\n");\r
279  strcat(pB,szTxt);\r
280  sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType);\r
281  strcat(pB,szTxt);\r
282 // sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]);\r
283  strcat(pB,szTxt);\r
284  sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]);\r
285  strcat(pB,szTxt);\r
286  //sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]);\r
287  //if(!hW && bAdvancedBlend)\r
288 //  {\r
289 //   if(bGLBlend) strcat(szTxt," (hardware)\r\n");\r
290 //   else         strcat(szTxt," (software)\r\n");\r
291 //  }\r
292  strcat(szTxt,"\r\n");\r
293  strcat(pB,szTxt);\r
294 \r
295  if(!hW)\r
296   {\r
297    strcpy(szTxt,"- Subtractive blending: ");\r
298 //   if(glBlendEquationEXTEx)\r
299 //    {\r
300 //     if(bUseMultiPass) strcat(szTxt,"supported, but not used!");\r
301 //     else              strcat(szTxt,"activated");\r
302 //    }\r
303    strcat(szTxt," NOT supported!");\r
304    strcat(szTxt,"\r\n\r\n");\r
305   }\r
306  else strcpy(szTxt,"\r\n");\r
307  \r
308  strcat(pB,szTxt);             \r
309  //----------------------------------------------------//\r
310  sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]);\r
311  strcat(pB,szTxt);\r
312  if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend);\r
313  else strcpy(szTxt,"\r\n");\r
314  strcat(pB,szTxt);\r
315 // sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]);\r
316  strcat(pB,szTxt);\r
317 // sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]);\r
318 // fwrite(szTxt,lstrlen(szTxt),1,txtfile);\r
319  sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]);\r
320  strcat(pB,szTxt);\r
321  sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]);\r
322  strcat(pB,szTxt);\r
323  sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]);\r
324  strcat(pB,szTxt);\r
325  sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]);\r
326  strcat(pB,szTxt);\r
327  if(!hW && iBlurBuffer) \r
328   {\r
329    if(gTexBlurName) strcat(pB," - supported\r\n");\r
330    else             strcat(pB," - not supported\r\n");\r
331   }\r
332  else strcat(pB,"\r\n");\r
333  sprintf(szTxt,"- Game fixes: %s [%08lx]\r\n",szO[bUseFixes],dwCfgFixes);\r
334  strcat(pB,szTxt);\r
335  //----------------------------------------------------//\r
336 */ return pB;\r
337 }\r
338 \r
339 ////////////////////////////////////////////////////////////////////////\r
340 // save text infos to file\r
341 ////////////////////////////////////////////////////////////////////////\r
342 \r
343 void DoTextSnapShot(int iNum)\r
344 {\r
345 }\r
346 \r
347 ////////////////////////////////////////////////////////////////////////\r
348 // saves screen bitmap to file\r
349 ////////////////////////////////////////////////////////////////////////\r
350 \r
351 void DoSnapShot(void)\r
352 {\r
353 }       \r
354 \r
355 void CALLBACK GPUmakeSnapshot(void)\r
356 {\r
357  //bSnapShot = TRUE;\r
358 }        \r
359 \r
360 ////////////////////////////////////////////////////////////////////////\r
361 // GPU INIT... here starts it all (first func called by emu)\r
362 ////////////////////////////////////////////////////////////////////////\r
363 \r
364 long CALLBACK GPUinit()\r
365 {\r
366 memset(ulStatusControl,0,256*sizeof(unsigned long));\r
367 \r
368 bChangeRes=FALSE;\r
369 bWindowMode=FALSE;\r
370 \r
371 bKeepRatio = TRUE;\r
372 // different ways of accessing PSX VRAM\r
373 \r
374 psxVSecure=(unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security\r
375 if(!psxVSecure) return -1;\r
376 \r
377 psxVub=psxVSecure+512*1024;                           // security offset into double sized psx vram!\r
378 psxVsb=(signed char *)psxVub;\r
379 psxVsw=(signed short *)psxVub;\r
380 psxVsl=(signed long *)psxVub;\r
381 psxVuw=(unsigned short *)psxVub;\r
382 psxVul=(unsigned long *)psxVub;\r
383 \r
384 psxVuw_eom=psxVuw+1024*iGPUHeight;                    // pre-calc of end of vram\r
385 \r
386 memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024));\r
387 memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));\r
388 \r
389 InitFrameCap();                                       // init frame rate stuff\r
390 \r
391 PSXDisplay.RGB24        = 0;                          // init vars\r
392 PreviousPSXDisplay.RGB24= 0;\r
393 PSXDisplay.Interlaced   = 0;\r
394 PSXDisplay.InterlacedTest=0;\r
395 PSXDisplay.DrawOffset.x = 0;\r
396 PSXDisplay.DrawOffset.y = 0;\r
397 PSXDisplay.DrawArea.x0  = 0;\r
398 PSXDisplay.DrawArea.y0  = 0;\r
399 PSXDisplay.DrawArea.x1  = 320;\r
400 PSXDisplay.DrawArea.y1  = 240;\r
401 PSXDisplay.DisplayMode.x= 320;\r
402 PSXDisplay.DisplayMode.y= 240;\r
403 PSXDisplay.Disabled     = FALSE;\r
404 PreviousPSXDisplay.Range.x0 =0;\r
405 PreviousPSXDisplay.Range.x1 =0;\r
406 PreviousPSXDisplay.Range.y0 =0;\r
407 PreviousPSXDisplay.Range.y1 =0;\r
408 PSXDisplay.Range.x0=0;\r
409 PSXDisplay.Range.x1=0;\r
410 PSXDisplay.Range.y0=0;\r
411 PSXDisplay.Range.y1=0;\r
412 PreviousPSXDisplay.DisplayPosition.x = 1;\r
413 PreviousPSXDisplay.DisplayPosition.y = 1;\r
414 PSXDisplay.DisplayPosition.x = 1;\r
415 PSXDisplay.DisplayPosition.y = 1;\r
416 PreviousPSXDisplay.DisplayModeNew.y=0;\r
417 PSXDisplay.Double=1;\r
418 GPUdataRet=0x400;\r
419 \r
420 PSXDisplay.DisplayModeNew.x=0;\r
421 PSXDisplay.DisplayModeNew.y=0;\r
422 \r
423 //PreviousPSXDisplay.Height = PSXDisplay.Height = 239;\r
424 \r
425 iDataWriteMode = DR_NORMAL;\r
426 \r
427 // Reset transfer values, to prevent mis-transfer of data\r
428 memset(&VRAMWrite,0,sizeof(VRAMLoad_t));\r
429 memset(&VRAMRead,0,sizeof(VRAMLoad_t));\r
430 \r
431 // device initialised already !\r
432 //lGPUstatusRet = 0x74000000;\r
433 \r
434 STATUSREG = 0x14802000;\r
435 GPUIsIdle;\r
436 GPUIsReadyForCommands;\r
437 \r
438 return 0;\r
439 }                             \r
440 \r
441 \r
442 ////////////////////////////////////////////////////////////////////////\r
443 // OPEN interface func: attention! \r
444 // some emus are calling this func in their main Window thread,\r
445 // but all other interface funcs (to draw stuff) in a different thread!\r
446 // that's a problem, since OGL is thread safe! Therefore we cannot \r
447 // initialize the OGL stuff right here, we simply set a "bIsFirstFrame = TRUE"\r
448 // flag, to initialize OGL on the first real draw call.\r
449 // btw, we also call this open func ourselfes, each time when the user \r
450 // is changing between fullscreen/window mode (ENTER key)\r
451 // btw part 2: in windows the plugin gets the window handle from the\r
452 // main emu, and doesn't create it's own window (if it would do it,\r
453 // some PAD or SPU plugins would not work anymore)\r
454 ////////////////////////////////////////////////////////////////////////\r
455 \r
456 long CALLBACK GPUopen(int hwndGPU)\r
457 {\r
458          iResX=800;iResY=480;\r
459          iColDepth=8;\r
460          bChangeRes=FALSE;\r
461          bWindowMode=FALSE;\r
462          bFullVRam=FALSE;\r
463          iFilterType=0;\r
464         // bAdvancedBlend=FALSE;\r
465          bDrawDither=FALSE;\r
466         // bUseLines=FALSE;\r
467          bUseFrameLimit=FALSE;\r
468          bUseFrameSkip=FALSE;\r
469          iFrameLimit=0;\r
470          fFrameRate=50.0f;\r
471          iOffscreenDrawing=0;\r
472          //bOpaquePass=FALSE;\r
473          //bUseAntiAlias=FALSE;\r
474          //iTexQuality=0;\r
475          iUseMask=0;\r
476          iZBufferDepth=0;\r
477          bUseFastMdec=FALSE;\r
478          bUse15bitMdec=FALSE;\r
479          dwCfgFixes=0;\r
480          bUseFixes=FALSE;\r
481         // iUseScanLines=0;\r
482          iFrameTexType=0;\r
483          iFrameReadType=0;\r
484          //iShowFPS=0;\r
485          bKeepRatio=TRUE;\r
486          iScanBlend=0;\r
487          iVRamSize=0;\r
488          iTexGarbageCollection=0;\r
489          iBlurBuffer=0; \r
490          //iHiResTextures=0;\r
491          iNoScreenSaver=0;\r
492  //iForceVSync=0;\r
493 \r
494 \r
495 \r
496  bIsFirstFrame = TRUE;                                 // flag: we have to init OGL later in windows!\r
497 \r
498  rRatioRect.left   = rRatioRect.top=0;\r
499  rRatioRect.right  = iResX;\r
500  rRatioRect.bottom = iResY;\r
501 \r
502  bDisplayNotSet = TRUE; \r
503  bSetClip=TRUE;\r
504 \r
505  SetFixes();                                           // setup game fixes\r
506 \r
507  InitializeTextureStore();                             // init texture mem\r
508 \r
509  CSTEXTURE = CSVERTEX = CSCOLOR = 0;\r
510 \r
511 // lGPUstatusRet = 0x74000000;\r
512 \r
513 // with some emus, we could do the OGL init right here... oh my\r
514  if(bIsFirstFrame) GLinitialize();\r
515 \r
516  return 0;\r
517 }\r
518 \r
519 ////////////////////////////////////////////////////////////////////////\r
520 // close\r
521 ////////////////////////////////////////////////////////////////////////\r
522 \r
523 \r
524 long GPUclose()                                        // LINUX CLOSE\r
525 {\r
526  GLcleanup();                                          // close OGL\r
527 \r
528  if(pGfxCardScreen) free(pGfxCardScreen);              // free helper memory\r
529  pGfxCardScreen=0;\r
530 \r
531 // osd_close_display();                                  // destroy display\r
532 \r
533  return 0;\r
534 }\r
535 \r
536 ////////////////////////////////////////////////////////////////////////\r
537 // I shot the sheriff... last function called from emu \r
538 ////////////////////////////////////////////////////////////////////////\r
539 \r
540 long CALLBACK GPUshutdown()\r
541 {\r
542  if(psxVSecure) free(psxVSecure);                      // kill emulated vram memory\r
543  psxVSecure=0;\r
544 \r
545  return 0;\r
546 }\r
547 \r
548 ////////////////////////////////////////////////////////////////////////\r
549 // paint it black: simple func to clean up optical border garbage\r
550 ////////////////////////////////////////////////////////////////////////\r
551 \r
552 void PaintBlackBorders(void)\r
553 {\r
554  short s;\r
555  glDisable(GL_SCISSOR_TEST); glError();\r
556  if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} glError();\r
557  if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} glError();\r
558  if(bBlendEnable)     {glDisable(GL_BLEND);bBlendEnable=FALSE;} glError();\r
559  glDisable(GL_ALPHA_TEST); glError();\r
560 \r
561  glEnable(GL_ALPHA_TEST); glError();\r
562  glEnable(GL_SCISSOR_TEST); glError();\r
563 \r
564 }\r
565 \r
566 ////////////////////////////////////////////////////////////////////////\r
567 // helper to draw scanlines\r
568 ////////////////////////////////////////////////////////////////////////\r
569 \r
570 __inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, \r
571                                     OGLVertex* vertex3, OGLVertex* vertex4) \r
572 {\r
573 \r
574 }\r
575 \r
576 ////////////////////////////////////////////////////////////////////////\r
577 // scanlines\r
578 ////////////////////////////////////////////////////////////////////////\r
579 \r
580 void SetScanLines(void)\r
581 {\r
582 }\r
583 \r
584 ////////////////////////////////////////////////////////////////////////\r
585 // blur, babe, blur (heavy performance hit for a so-so fullscreen effect)\r
586 ////////////////////////////////////////////////////////////////////////\r
587 \r
588 \r
589 ////////////////////////////////////////////////////////////////////////\r
590 // Update display (swap buffers)... called in interlaced mode on \r
591 // every emulated vsync, otherwise whenever the displayed screen region\r
592 // has been changed\r
593 ////////////////////////////////////////////////////////////////////////\r
594 \r
595 int iLastRGB24=0;                                      // special vars for checking when to skip two display updates\r
596 int iSkipTwo=0;\r
597 void GPUvSinc(void){\r
598 updateDisplay();\r
599 }\r
600 void updateDisplay(void)                               // UPDATE DISPLAY\r
601 {\r
602 BOOL bBlur=FALSE;\r
603 \r
604 \r
605 bFakeFrontBuffer=FALSE;\r
606 bRenderFrontBuffer=FALSE;\r
607 \r
608 if(iRenderFVR)                                        // frame buffer read fix mode still active?\r
609  {\r
610   iRenderFVR--;                                       // -> if some frames in a row without read access: turn off mode\r
611   if(!iRenderFVR) bFullVRam=FALSE;\r
612  }\r
613 \r
614 if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1)      // (mdec) garbage check\r
615  {\r
616   iSkipTwo=2;                                         // -> skip two frames to avoid garbage if color mode changes\r
617  }\r
618 iLastRGB24=0;\r
619 \r
620 if(PSXDisplay.RGB24)// && !bNeedUploadAfter)          // (mdec) upload wanted?\r
621  {\r
622   PrepareFullScreenUpload(-1);\r
623   UploadScreen(PSXDisplay.Interlaced);                // -> upload whole screen from psx vram\r
624   bNeedUploadTest=FALSE;\r
625   bNeedInterlaceUpdate=FALSE;\r
626   bNeedUploadAfter=FALSE;\r
627   bNeedRGB24Update=FALSE;\r
628  }\r
629 else\r
630 if(bNeedInterlaceUpdate)                              // smaller upload?\r
631  {\r
632   bNeedInterlaceUpdate=FALSE;\r
633   xrUploadArea=xrUploadAreaIL;                        // -> upload this rect\r
634   UploadScreen(TRUE);\r
635  }\r
636 \r
637 if(dwActFixes&512) bCheckFF9G4(NULL);                 // special game fix for FF9 \r
638 \r
639 if(PreviousPSXDisplay.Range.x0||                      // paint black borders around display area, if needed\r
640    PreviousPSXDisplay.Range.y0)\r
641  PaintBlackBorders();\r
642 \r
643 if(PSXDisplay.Disabled)                               // display disabled?\r
644  {\r
645   //LOGE("PSXDisplay.Disabled");\r
646 \r
647   // moved here\r
648   glDisable(GL_SCISSOR_TEST); glError();                       \r
649   glClearColor(0,0,0,128); glError();                 // -> clear whole backbuffer\r
650   glClear(uiBufferBits); glError();\r
651   glEnable(GL_SCISSOR_TEST); glError();                       \r
652   gl_z=0.0f;\r
653   bDisplayNotSet = TRUE;\r
654  }\r
655 \r
656 if(iSkipTwo)                                          // we are in skipping mood?\r
657  {\r
658   iSkipTwo--;\r
659   iDrawnSomething=0;                                  // -> simply lie about something drawn\r
660  }\r
661 \r
662 //if(iBlurBuffer && !bSkipNextFrame)                    // "blur display" activated?\r
663 // {BlurBackBuffer();bBlur=TRUE;}                       // -> blur it\r
664 \r
665 // if(iUseScanLines) SetScanLines();                     // "scan lines" activated? do it\r
666 \r
667 // if(usCursorActive) ShowGunCursor();                   // "gun cursor" wanted? show 'em\r
668 \r
669 if(dwActFixes&128)                                    // special FPS limitation mode?\r
670  {\r
671   if(bUseFrameLimit) PCFrameCap();                    // -> ok, do it\r
672 //   if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS)  \r
673    PCcalcfps();         \r
674  }\r
675 \r
676 // if(gTexPicName) DisplayPic();                         // some gpu info picture active? display it\r
677 \r
678 // if(bSnapShot) DoSnapShot();                           // snapshot key pressed? cheeeese :)\r
679 \r
680 // if(ulKeybits&KEY_SHOWFPS)                             // wanna see FPS?\r
681  {\r
682 //   sprintf(szDispBuf,"%06.1f",fps_cur);\r
683 //   DisplayText();                                      // -> show it\r
684  }\r
685 \r
686 //----------------------------------------------------//\r
687 // main buffer swapping (well, or skip it)\r
688 \r
689 if(bUseFrameSkip)                                     // frame skipping active ?\r
690  {\r
691   if(!bSkipNextFrame) \r
692    {\r
693     if(iDrawnSomething)     flipEGL();\r
694    }\r
695     if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) \r
696      {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}\r
697     else bSkipNextFrame = FALSE;\r
698 \r
699  }\r
700 else                                                  // no skip ?\r
701  {\r
702   if(iDrawnSomething)  flipEGL();\r
703  }\r
704 \r
705 iDrawnSomething=0;\r
706 \r
707 //----------------------------------------------------//\r
708 \r
709 if(lClearOnSwap)                                      // clear buffer after swap?\r
710  {\r
711   GLclampf g,b,r;\r
712 \r
713   if(bDisplayNotSet)                                  // -> set new vals\r
714    SetOGLDisplaySettings(1);\r
715 \r
716   g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f;      // -> get col\r
717   b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f;\r
718   r=((GLclampf)RED(lClearOnSwapColor))/255.0f;\r
719   glDisable(GL_SCISSOR_TEST); glError();                       \r
720   glClearColor(r,g,b,128); glError();                 // -> clear \r
721   glClear(uiBufferBits); glError();\r
722   glEnable(GL_SCISSOR_TEST); glError();                       \r
723   lClearOnSwap=0;                                     // -> done\r
724  }\r
725 else \r
726  {\r
727 //  if(bBlur) UnBlurBackBuffer();                       // unblur buff, if blurred before\r
728 \r
729   if(iZBufferDepth)                                   // clear zbuffer as well (if activated)\r
730    {\r
731     glDisable(GL_SCISSOR_TEST); glError();\r
732     glClear(GL_DEPTH_BUFFER_BIT); glError();\r
733     glEnable(GL_SCISSOR_TEST); glError();\r
734    }\r
735  }\r
736 \r
737 gl_z=0.0f;\r
738 \r
739 //----------------------------------------------------//\r
740 // additional uploads immediatly after swapping\r
741 \r
742 if(bNeedUploadAfter)                                  // upload wanted?\r
743  {\r
744   bNeedUploadAfter=FALSE;                           \r
745   bNeedUploadTest=FALSE;\r
746   UploadScreen(-1);                                   // -> upload\r
747  }\r
748 \r
749 if(bNeedUploadTest)\r
750  {\r
751   bNeedUploadTest=FALSE;\r
752   if(PSXDisplay.InterlacedTest &&\r
753      //iOffscreenDrawing>2 &&\r
754      PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x &&\r
755      PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x &&\r
756      PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y &&\r
757      PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y)\r
758    {\r
759     PrepareFullScreenUpload(TRUE);\r
760     UploadScreen(TRUE);\r
761    }\r
762  }\r
763 \r
764 //----------------------------------------------------//\r
765 // rumbling (main emu pad effect)\r
766 \r
767 if(iRumbleTime)                                       // shake screen by modifying view port\r
768  {\r
769   int i1=0,i2=0,i3=0,i4=0;\r
770 \r
771   iRumbleTime--;\r
772   if(iRumbleTime) \r
773    {\r
774     i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
775     i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
776     i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
777     i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
778    }\r
779 \r
780   glViewport(rRatioRect.left+i1,                      \r
781              iResY-(rRatioRect.top+rRatioRect.bottom)+i2,\r
782              rRatioRect.right+i3, \r
783              rRatioRect.bottom+i4); glError();\r
784  }\r
785 \r
786 //----------------------------------------------------//\r
787 \r
788 \r
789 \r
790 // if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff();         // reset on gpu mode changes? do it before next frame is filled\r
791 }\r
792 \r
793 ////////////////////////////////////////////////////////////////////////\r
794 // update front display: smaller update func, if something has changed \r
795 // in the frontbuffer... dirty, but hey... real men know no pain\r
796 ////////////////////////////////////////////////////////////////////////\r
797 \r
798 void updateFrontDisplay(void)\r
799 {\r
800 if(PreviousPSXDisplay.Range.x0||\r
801    PreviousPSXDisplay.Range.y0)\r
802  PaintBlackBorders();\r
803 \r
804 //if(iBlurBuffer) BlurBackBuffer();\r
805 \r
806 //if(iUseScanLines) SetScanLines();\r
807 \r
808 // if(usCursorActive) ShowGunCursor();\r
809 \r
810 bFakeFrontBuffer=FALSE;\r
811 bRenderFrontBuffer=FALSE;\r
812 \r
813 // if(gTexPicName) DisplayPic();\r
814 // if(ulKeybits&KEY_SHOWFPS) DisplayText();\r
815 \r
816 if(iDrawnSomething)                                   // linux:\r
817       flipEGL();\r
818 \r
819 \r
820 //if(iBlurBuffer) UnBlurBackBuffer();\r
821 }\r
822                                              \r
823 ////////////////////////////////////////////////////////////////////////\r
824 // check if update needed\r
825 ////////////////////////////////////////////////////////////////////////\r
826 void ChangeDispOffsetsX(void)                          // CENTER X\r
827 {\r
828 long lx,l;short sO;\r
829 \r
830 if(!PSXDisplay.Range.x1) return;                      // some range given?\r
831 \r
832 l=PSXDisplay.DisplayMode.x;\r
833 \r
834 l*=(long)PSXDisplay.Range.x1;                         // some funky calculation\r
835 l/=2560;lx=l;l&=0xfffffff8;\r
836 \r
837 if(l==PreviousPSXDisplay.Range.x1) return;            // some change?\r
838 \r
839 sO=PreviousPSXDisplay.Range.x0;                       // store old\r
840 \r
841 if(lx>=PSXDisplay.DisplayMode.x)                      // range bigger?\r
842  {\r
843   PreviousPSXDisplay.Range.x1=                        // -> take display width\r
844    PSXDisplay.DisplayMode.x;\r
845   PreviousPSXDisplay.Range.x0=0;                      // -> start pos is 0\r
846  }\r
847 else                                                  // range smaller? center it\r
848  {\r
849   PreviousPSXDisplay.Range.x1=l;                      // -> store width (8 pixel aligned)\r
850    PreviousPSXDisplay.Range.x0=                       // -> calc start pos\r
851    (PSXDisplay.Range.x0-500)/8;\r
852   if(PreviousPSXDisplay.Range.x0<0)                   // -> we don't support neg. values yet\r
853    PreviousPSXDisplay.Range.x0=0;\r
854 \r
855   if((PreviousPSXDisplay.Range.x0+lx)>                // -> uhuu... that's too much\r
856      PSXDisplay.DisplayMode.x)\r
857    {\r
858     PreviousPSXDisplay.Range.x0=                      // -> adjust start\r
859      PSXDisplay.DisplayMode.x-lx;\r
860     PreviousPSXDisplay.Range.x1+=lx-l;                // -> adjust width\r
861    }                   \r
862  }\r
863 \r
864 if(sO!=PreviousPSXDisplay.Range.x0)                   // something changed?\r
865  {\r
866   bDisplayNotSet=TRUE;                                // -> recalc display stuff\r
867  }\r
868 }\r
869 \r
870 ////////////////////////////////////////////////////////////////////////\r
871 \r
872 void ChangeDispOffsetsY(void)                          // CENTER Y\r
873 {\r
874 int iT;short sO;                                      // store previous y size\r
875 \r
876 if(PSXDisplay.PAL) iT=48; else iT=28;                 // different offsets on PAL/NTSC\r
877 \r
878 if(PSXDisplay.Range.y0>=iT)                           // crossed the security line? :)\r
879  {\r
880   PreviousPSXDisplay.Range.y1=                        // -> store width\r
881    PSXDisplay.DisplayModeNew.y;\r
882   \r
883   sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double;    // -> calc offset\r
884   if(sO<0) sO=0;\r
885 \r
886   PSXDisplay.DisplayModeNew.y+=sO;                    // -> add offset to y size, too\r
887  }\r
888 else sO=0;                                            // else no offset\r
889 \r
890 if(sO!=PreviousPSXDisplay.Range.y0)                   // something changed?\r
891  {\r
892   PreviousPSXDisplay.Range.y0=sO;\r
893   bDisplayNotSet=TRUE;                                // -> recalc display stuff\r
894  }\r
895 }\r
896 \r
897 ////////////////////////////////////////////////////////////////////////\r
898 // Aspect ratio of ogl screen: simply adjusting ogl view port\r
899 ////////////////////////////////////////////////////////////////////////\r
900 \r
901 void SetAspectRatio(void)\r
902 {\r
903 float xs,ys,s;RECT r;\r
904 \r
905 if(!PSXDisplay.DisplayModeNew.x) return;\r
906 if(!PSXDisplay.DisplayModeNew.y) return;\r
907 \r
908 #if 0\r
909 xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x;\r
910 ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y;\r
911 \r
912 s=min(xs,ys);\r
913 r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s);\r
914 r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s);\r
915 if(r.right  > iResX) r.right  = iResX;\r
916 if(r.bottom > iResY) r.bottom = iResY;\r
917 if(r.right  < 1)     r.right  = 1;\r
918 if(r.bottom < 1)     r.bottom = 1;\r
919 \r
920 r.left = (iResX-r.right)/2;\r
921 r.top  = (iResY-r.bottom)/2;\r
922 if(r.bottom<rRatioRect.bottom ||\r
923    r.right <rRatioRect.right)\r
924  {\r
925   RECT rC;\r
926   glClearColor(0,0,0,128); glError();\r
927 \r
928   if(r.right <rRatioRect.right)\r
929    {\r
930     rC.left=0;\r
931     rC.top=0;\r
932     rC.right=r.left;\r
933     rC.bottom=iResY;\r
934     glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();\r
935     glClear(uiBufferBits); glError();\r
936     rC.left=iResX-rC.right;\r
937     glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();\r
938     \r
939     glClear(uiBufferBits); glError();\r
940    }\r
941 \r
942   if(r.bottom <rRatioRect.bottom)\r
943    {\r
944     rC.left=0;\r
945     rC.top=0;\r
946     rC.right=iResX;\r
947     rC.bottom=r.top;\r
948     glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();\r
949 \r
950     glClear(uiBufferBits); glError();\r
951     rC.top=iResY-rC.bottom;\r
952     glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();\r
953     glClear(uiBufferBits); glError();\r
954    }\r
955   \r
956   bSetClip=TRUE;\r
957   bDisplayNotSet=TRUE;\r
958  }\r
959 \r
960 rRatioRect=r;\r
961 #else\r
962  // pcsx-rearmed hack\r
963  if (rearmed_get_layer_pos != NULL)\r
964    rearmed_get_layer_pos(&rRatioRect.left, &rRatioRect.top, &rRatioRect.right, &rRatioRect.bottom);\r
965 #endif\r
966 \r
967 glViewport(rRatioRect.left,\r
968            iResY-(rRatioRect.top+rRatioRect.bottom),\r
969            rRatioRect.right,\r
970            rRatioRect.bottom); glError();              // init viewport\r
971 }\r
972 \r
973 ////////////////////////////////////////////////////////////////////////\r
974 // big ass check, if an ogl swap buffer is needed\r
975 ////////////////////////////////////////////////////////////////////////\r
976 \r
977 void updateDisplayIfChanged(void)\r
978 {\r
979 BOOL bUp;\r
980 \r
981 if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) && \r
982     (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))\r
983  {\r
984   if((PSXDisplay.RGB24      == PSXDisplay.RGB24New) && \r
985      (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) \r
986      return;                                          // nothing has changed? fine, no swap buffer needed\r
987  }\r
988 else                                                  // some res change?\r
989  {\r
990   glLoadIdentity(); glError();\r
991   glOrtho(0,PSXDisplay.DisplayModeNew.x,              // -> new psx resolution\r
992             PSXDisplay.DisplayModeNew.y, 0, -1, 1); glError();\r
993   if(bKeepRatio) SetAspectRatio();\r
994  }\r
995 \r
996 bDisplayNotSet = TRUE;                                // re-calc offsets/display area\r
997 \r
998 bUp=FALSE;\r
999 if(PSXDisplay.RGB24!=PSXDisplay.RGB24New)             // clean up textures, if rgb mode change (usually mdec on/off)\r
1000  {\r
1001   PreviousPSXDisplay.RGB24=0;                         // no full 24 frame uploaded yet\r
1002   ResetTextureArea(FALSE);\r
1003   bUp=TRUE;\r
1004  }\r
1005 \r
1006 PSXDisplay.RGB24         = PSXDisplay.RGB24New;       // get new infos\r
1007 PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;\r
1008 PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;\r
1009 PSXDisplay.Interlaced    = PSXDisplay.InterlacedNew;\r
1010    \r
1011 PSXDisplay.DisplayEnd.x=                              // calc new ends\r
1012  PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1013 PSXDisplay.DisplayEnd.y=\r
1014  PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1015 PreviousPSXDisplay.DisplayEnd.x=\r
1016  PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1017 PreviousPSXDisplay.DisplayEnd.y=\r
1018  PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1019 \r
1020 ChangeDispOffsetsX();\r
1021 \r
1022 if(iFrameLimit==2) SetAutoFrameCap();                 // set new fps limit vals (depends on interlace)\r
1023 \r
1024 if(bUp) updateDisplay();                              // yeah, real update (swap buffer)\r
1025 }\r
1026 \r
1027 ////////////////////////////////////////////////////////////////////////\r
1028 // window mode <-> fullscreen mode (windows)\r
1029 ////////////////////////////////////////////////////////////////////////\r
1030 \r
1031 \r
1032 ////////////////////////////////////////////////////////////////////////\r
1033 // swap update check (called by psx vsync function)\r
1034 ////////////////////////////////////////////////////////////////////////\r
1035 \r
1036 BOOL bSwapCheck(void)\r
1037 {\r
1038 static int iPosCheck=0;\r
1039 static PSXPoint_t pO;\r
1040 static PSXPoint_t pD;\r
1041 static int iDoAgain=0;\r
1042 \r
1043 if(PSXDisplay.DisplayPosition.x==pO.x &&\r
1044    PSXDisplay.DisplayPosition.y==pO.y &&\r
1045    PSXDisplay.DisplayEnd.x==pD.x &&\r
1046    PSXDisplay.DisplayEnd.y==pD.y)\r
1047      iPosCheck++;\r
1048 else iPosCheck=0;\r
1049 \r
1050 pO=PSXDisplay.DisplayPosition;\r
1051 pD=PSXDisplay.DisplayEnd;\r
1052 \r
1053 if(iPosCheck<=4) return FALSE;\r
1054 \r
1055 iPosCheck=4;\r
1056 \r
1057 if(PSXDisplay.Interlaced) return FALSE;\r
1058 \r
1059 if (bNeedInterlaceUpdate||\r
1060     bNeedRGB24Update ||\r
1061     bNeedUploadAfter|| \r
1062     bNeedUploadTest || \r
1063     iDoAgain\r
1064    )\r
1065  {\r
1066   iDoAgain=0;\r
1067   if(bNeedUploadAfter) \r
1068    iDoAgain=1;\r
1069   if(bNeedUploadTest && PSXDisplay.InterlacedTest)\r
1070    iDoAgain=1;\r
1071 \r
1072   bDisplayNotSet = TRUE;\r
1073   updateDisplay();\r
1074 \r
1075   PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x;\r
1076   PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y;\r
1077   PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x;\r
1078   PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y;\r
1079   pO=PSXDisplay.DisplayPosition;\r
1080   pD=PSXDisplay.DisplayEnd;\r
1081 \r
1082   return TRUE;\r
1083  }\r
1084 \r
1085 return FALSE;\r
1086\r
1087 ////////////////////////////////////////////////////////////////////////\r
1088 // gun cursor func: player=0-7, x=0-511, y=0-255\r
1089 ////////////////////////////////////////////////////////////////////////\r
1090 \r
1091 ////////////////////////////////////////////////////////////////////////\r
1092 // update lace is called every VSync. Basically we limit frame rate \r
1093 // here, and in interlaced mode we swap ogl display buffers.\r
1094 ////////////////////////////////////////////////////////////////////////\r
1095 \r
1096 static unsigned short usFirstPos=2;\r
1097 \r
1098 void CALLBACK GPUupdateLace(void)\r
1099 {\r
1100 if(!(dwActFixes&0x1000))                               \r
1101  STATUSREG^=0x80000000;                               // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus)\r
1102 \r
1103 if(!(dwActFixes&128))                                 // normal frame limit func\r
1104  CheckFrameRate();\r
1105 \r
1106 if(iOffscreenDrawing==4)                              // special check if high offscreen drawing is on\r
1107  {\r
1108   if(bSwapCheck()) return;\r
1109  }\r
1110 \r
1111 if(PSXDisplay.Interlaced)                             // interlaced mode?\r
1112  {\r
1113   if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)\r
1114    {\r
1115     updateDisplay();                                  // -> swap buffers (new frame)\r
1116    }\r
1117  }\r
1118 else if(bRenderFrontBuffer)                           // no interlace mode? and some stuff in front has changed?\r
1119  {\r
1120   updateFrontDisplay();                               // -> update front buffer\r
1121  }\r
1122 else if(usFirstPos==1)                                // initial updates (after startup)\r
1123  {\r
1124   updateDisplay();\r
1125  }\r
1126 \r
1127 }\r
1128 \r
1129 ////////////////////////////////////////////////////////////////////////\r
1130 // process read request from GPU status register\r
1131 ////////////////////////////////////////////////////////////////////////\r
1132 \r
1133 unsigned long CALLBACK GPUreadStatus(void)\r
1134 {\r
1135 if(dwActFixes&0x1000)                                 // CC game fix\r
1136  {\r
1137   static int iNumRead=0;\r
1138   if((iNumRead++)==2)\r
1139    {\r
1140     iNumRead=0;\r
1141     STATUSREG^=0x80000000;                            // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross)\r
1142    }\r
1143  }\r
1144 \r
1145 if(iFakePrimBusy)                                     // 27.10.2007 - emulating some 'busy' while drawing... pfff... not perfect, but since our emulated dma is not done in an extra thread...\r
1146  {\r
1147   iFakePrimBusy--;\r
1148 \r
1149   if(iFakePrimBusy&1)                                 // we do a busy-idle-busy-idle sequence after/while drawing prims\r
1150    {\r
1151     GPUIsBusy;\r
1152     GPUIsNotReadyForCommands;\r
1153    }\r
1154   else\r
1155    {\r
1156     GPUIsIdle;\r
1157     GPUIsReadyForCommands;\r
1158    }\r
1159  }\r
1160 \r
1161 return STATUSREG;\r
1162 }\r
1163 \r
1164 ////////////////////////////////////////////////////////////////////////\r
1165 // processes data send to GPU status register\r
1166 // these are always single packet commands.\r
1167 ////////////////////////////////////////////////////////////////////////\r
1168 \r
1169 void CALLBACK GPUwriteStatus(unsigned long gdata)\r
1170 {\r
1171 unsigned long lCommand=(gdata>>24)&0xff;\r
1172 \r
1173 if(bIsFirstFrame) GLinitialize();                     // real ogl startup (needed by some emus)\r
1174 \r
1175 ulStatusControl[lCommand]=gdata;\r
1176 \r
1177 switch(lCommand)\r
1178  {\r
1179   //--------------------------------------------------//\r
1180   // reset gpu\r
1181   case 0x00:\r
1182    memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));\r
1183    lGPUstatusRet=0x14802000;\r
1184    PSXDisplay.Disabled=1;\r
1185    iDataWriteMode=iDataReadMode=DR_NORMAL;\r
1186    PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;\r
1187    drawX=drawY=0;drawW=drawH=0;\r
1188    sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0;\r
1189    usMirror=0;\r
1190    GlobalTextAddrX=0;GlobalTextAddrY=0;\r
1191    GlobalTextTP=0;GlobalTextABR=0;\r
1192    PSXDisplay.RGB24=FALSE;\r
1193    PSXDisplay.Interlaced=FALSE;\r
1194    bUsingTWin = FALSE;\r
1195    return;\r
1196 \r
1197   // dis/enable display\r
1198   case 0x03:  \r
1199    PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;\r
1200    PSXDisplay.Disabled = (gdata & 1);\r
1201 \r
1202    if(PSXDisplay.Disabled) \r
1203         STATUSREG|=GPUSTATUS_DISPLAYDISABLED;\r
1204    else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED;\r
1205 \r
1206    if (iOffscreenDrawing==4 &&\r
1207         PreviousPSXDisplay.Disabled && \r
1208        !(PSXDisplay.Disabled))\r
1209     {\r
1210 \r
1211      if(!PSXDisplay.RGB24)\r
1212       {\r
1213        PrepareFullScreenUpload(TRUE);\r
1214        UploadScreen(TRUE); \r
1215        updateDisplay();\r
1216       }\r
1217     }\r
1218 \r
1219    return;\r
1220 \r
1221   // setting transfer mode\r
1222   case 0x04:\r
1223    gdata &= 0x03;                                     // only want the lower two bits\r
1224 \r
1225    iDataWriteMode=iDataReadMode=DR_NORMAL;\r
1226    if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER;\r
1227    if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER;\r
1228 \r
1229    STATUSREG&=~GPUSTATUS_DMABITS;                     // clear the current settings of the DMA bits\r
1230    STATUSREG|=(gdata << 29);                          // set the DMA bits according to the received data\r
1231 \r
1232    return;\r
1233 \r
1234   // setting display position\r
1235   case 0x05: \r
1236    {\r
1237     short sx=(short)(gdata & 0x3ff);\r
1238     short sy;\r
1239 \r
1240     if(iGPUHeight==1024)\r
1241      {\r
1242       if(dwGPUVersion==2) \r
1243            sy = (short)((gdata>>12)&0x3ff);\r
1244       else sy = (short)((gdata>>10)&0x3ff);\r
1245      }\r
1246     else sy = (short)((gdata>>10)&0x3ff);             // really: 0x1ff, but we adjust it later\r
1247 \r
1248     if (sy & 0x200) \r
1249      {\r
1250       sy|=0xfc00;\r
1251       PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double;\r
1252       sy=0;\r
1253      }\r
1254     else PreviousPSXDisplay.DisplayModeNew.y=0;\r
1255 \r
1256     if(sx>1000) sx=0;\r
1257 \r
1258     if(usFirstPos)\r
1259      {\r
1260       usFirstPos--;\r
1261       if(usFirstPos)\r
1262        {\r
1263         PreviousPSXDisplay.DisplayPosition.x = sx;\r
1264         PreviousPSXDisplay.DisplayPosition.y = sy;\r
1265         PSXDisplay.DisplayPosition.x = sx;\r
1266         PSXDisplay.DisplayPosition.y = sy;\r
1267        }\r
1268      }\r
1269 \r
1270     if(dwActFixes&8) \r
1271      {\r
1272       if((!PSXDisplay.Interlaced) &&\r
1273          PreviousPSXDisplay.DisplayPosition.x == sx  &&\r
1274          PreviousPSXDisplay.DisplayPosition.y == sy)\r
1275        return;\r
1276 \r
1277       PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x;\r
1278       PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y;\r
1279       PreviousPSXDisplay.DisplayPosition.x = sx;\r
1280       PreviousPSXDisplay.DisplayPosition.y = sy;\r
1281      }\r
1282     else\r
1283      {\r
1284       if((!PSXDisplay.Interlaced) &&\r
1285          PSXDisplay.DisplayPosition.x == sx  &&\r
1286          PSXDisplay.DisplayPosition.y == sy)\r
1287        return;\r
1288       PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;\r
1289       PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;\r
1290       PSXDisplay.DisplayPosition.x = sx;\r
1291       PSXDisplay.DisplayPosition.y = sy;\r
1292      }\r
1293 \r
1294     PSXDisplay.DisplayEnd.x=\r
1295      PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1296     PSXDisplay.DisplayEnd.y=\r
1297      PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1298 \r
1299     PreviousPSXDisplay.DisplayEnd.x=\r
1300      PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1301     PreviousPSXDisplay.DisplayEnd.y=\r
1302      PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1303 \r
1304     bDisplayNotSet = TRUE;\r
1305 \r
1306     if (!(PSXDisplay.Interlaced))\r
1307      {\r
1308       updateDisplay();\r
1309      }\r
1310     else\r
1311     if(PSXDisplay.InterlacedTest && \r
1312        ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)||\r
1313         (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y)))\r
1314      PSXDisplay.InterlacedTest--;\r
1315 \r
1316     return;\r
1317    }\r
1318 \r
1319   // setting width\r
1320   case 0x06:\r
1321 \r
1322    PSXDisplay.Range.x0=gdata & 0x7ff;      //0x3ff;\r
1323    PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff;\r
1324 \r
1325    PSXDisplay.Range.x1-=PSXDisplay.Range.x0;\r
1326 \r
1327    ChangeDispOffsetsX();\r
1328 \r
1329    return;\r
1330 \r
1331   // setting height\r
1332   case 0x07:\r
1333 \r
1334    PreviousPSXDisplay.Height = PSXDisplay.Height;\r
1335 \r
1336    PSXDisplay.Range.y0=gdata & 0x3ff;\r
1337    PSXDisplay.Range.y1=(gdata>>10) & 0x3ff;\r
1338 \r
1339    PSXDisplay.Height = PSXDisplay.Range.y1 - \r
1340                        PSXDisplay.Range.y0 +\r
1341                        PreviousPSXDisplay.DisplayModeNew.y;\r
1342 \r
1343    if (PreviousPSXDisplay.Height != PSXDisplay.Height)\r
1344     {\r
1345      PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;\r
1346      ChangeDispOffsetsY();\r
1347      updateDisplayIfChanged();\r
1348     }\r
1349    return;\r
1350 \r
1351   // setting display infos\r
1352   case 0x08:\r
1353 \r
1354    PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];\r
1355 \r
1356    if (gdata&0x04) PSXDisplay.Double=2;\r
1357    else            PSXDisplay.Double=1;\r
1358    PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;\r
1359 \r
1360    ChangeDispOffsetsY();\r
1361  \r
1362    PSXDisplay.PAL           = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC\r
1363    PSXDisplay.RGB24New      = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor\r
1364    PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace\r
1365 \r
1366    STATUSREG&=~GPUSTATUS_WIDTHBITS;                   // clear the width bits\r
1367 \r
1368    STATUSREG|=\r
1369               (((gdata & 0x03) << 17) | \r
1370               ((gdata & 0x40) << 10));                // set the width bits\r
1371 \r
1372    PreviousPSXDisplay.InterlacedNew=FALSE;\r
1373    if (PSXDisplay.InterlacedNew)\r
1374     {\r
1375      if(!PSXDisplay.Interlaced)\r
1376       {\r
1377        PSXDisplay.InterlacedTest=2;\r
1378        PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;\r
1379        PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;\r
1380        PreviousPSXDisplay.InterlacedNew=TRUE;\r
1381       }\r
1382 \r
1383      STATUSREG|=GPUSTATUS_INTERLACED;\r
1384     }\r
1385    else \r
1386     {\r
1387      PSXDisplay.InterlacedTest=0;\r
1388      STATUSREG&=~GPUSTATUS_INTERLACED;\r
1389     }\r
1390 \r
1391    if (PSXDisplay.PAL)\r
1392         STATUSREG|=GPUSTATUS_PAL;\r
1393    else STATUSREG&=~GPUSTATUS_PAL;\r
1394 \r
1395    if (PSXDisplay.Double==2)\r
1396         STATUSREG|=GPUSTATUS_DOUBLEHEIGHT;\r
1397    else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT;\r
1398 \r
1399    if (PSXDisplay.RGB24New)\r
1400         STATUSREG|=GPUSTATUS_RGB24;\r
1401    else STATUSREG&=~GPUSTATUS_RGB24;\r
1402 \r
1403    updateDisplayIfChanged();\r
1404 \r
1405    return;\r
1406 \r
1407   //--------------------------------------------------//\r
1408   // ask about GPU version and other stuff\r
1409   case 0x10: \r
1410 \r
1411    gdata&=0xff;\r
1412 \r
1413    switch(gdata) \r
1414     {\r
1415      case 0x02:\r
1416       GPUdataRet=ulGPUInfoVals[INFO_TW];              // tw infos\r
1417       return;\r
1418      case 0x03:\r
1419       GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART];       // draw start\r
1420       return;\r
1421      case 0x04:\r
1422       GPUdataRet=ulGPUInfoVals[INFO_DRAWEND];         // draw end\r
1423       return;\r
1424      case 0x05:\r
1425      case 0x06:\r
1426       GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF];         // draw offset\r
1427       return;\r
1428      case 0x07:\r
1429       if(dwGPUVersion==2)\r
1430            GPUdataRet=0x01;\r
1431       else GPUdataRet=0x02;                           // gpu type\r
1432       return;\r
1433      case 0x08:\r
1434      case 0x0F:                                       // some bios addr?\r
1435       GPUdataRet=0xBFC03720;\r
1436       return;\r
1437     }\r
1438    return;\r
1439   //--------------------------------------------------//\r
1440  }\r
1441 }\r
1442 \r
1443 ////////////////////////////////////////////////////////////////////////\r
1444 // vram read/write helpers\r
1445 ////////////////////////////////////////////////////////////////////////\r
1446 \r
1447 BOOL bNeedWriteUpload=FALSE;\r
1448 \r
1449 __inline void FinishedVRAMWrite(void)\r
1450 {\r
1451  if(bNeedWriteUpload)\r
1452   {\r
1453    bNeedWriteUpload=FALSE;\r
1454    CheckWriteUpdate();\r
1455   }\r
1456 \r
1457  // set register to NORMAL operation\r
1458  iDataWriteMode = DR_NORMAL;\r
1459 \r
1460  // reset transfer values, to prevent mis-transfer of data\r
1461  VRAMWrite.ColsRemaining = 0;\r
1462  VRAMWrite.RowsRemaining = 0;\r
1463 }\r
1464 \r
1465 __inline void FinishedVRAMRead(void)\r
1466 {\r
1467  // set register to NORMAL operation\r
1468  iDataReadMode = DR_NORMAL;\r
1469  // reset transfer values, to prevent mis-transfer of data\r
1470  VRAMRead.x = 0;\r
1471  VRAMRead.y = 0;\r
1472  VRAMRead.Width = 0;\r
1473  VRAMRead.Height = 0;\r
1474  VRAMRead.ColsRemaining = 0;\r
1475  VRAMRead.RowsRemaining = 0;\r
1476 \r
1477  // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER\r
1478  STATUSREG&=~GPUSTATUS_READYFORVRAM;\r
1479 }\r
1480 \r
1481 ////////////////////////////////////////////////////////////////////////\r
1482 // vram read check ex (reading from card's back/frontbuffer if needed...\r
1483 // slow!)\r
1484 ////////////////////////////////////////////////////////////////////////\r
1485 \r
1486 void CheckVRamReadEx(int x, int y, int dx, int dy)\r
1487 {\r
1488  unsigned short sArea;\r
1489  int ux,uy,udx,udy,wx,wy;\r
1490  unsigned short * p1, *p2;\r
1491  float XS,YS;\r
1492  unsigned char * ps;\r
1493  unsigned char * px;\r
1494  unsigned short s,sx;\r
1495 \r
1496  if(STATUSREG&GPUSTATUS_RGB24) return;\r
1497 \r
1498  if(((dx  > PSXDisplay.DisplayPosition.x) &&\r
1499      (x   < PSXDisplay.DisplayEnd.x) &&\r
1500      (dy  > PSXDisplay.DisplayPosition.y) &&\r
1501      (y   < PSXDisplay.DisplayEnd.y)))\r
1502   sArea=0;\r
1503  else\r
1504  if((!(PSXDisplay.InterlacedTest) &&\r
1505      (dx  > PreviousPSXDisplay.DisplayPosition.x) &&\r
1506      (x   < PreviousPSXDisplay.DisplayEnd.x) &&\r
1507      (dy  > PreviousPSXDisplay.DisplayPosition.y) &&\r
1508      (y   < PreviousPSXDisplay.DisplayEnd.y)))\r
1509   sArea=1;\r
1510  else \r
1511   {\r
1512    return;\r
1513   }\r
1514 \r
1515  //////////////\r
1516 \r
1517  if(iRenderFVR)\r
1518   {\r
1519    bFullVRam=TRUE;iRenderFVR=2;return;\r
1520   }\r
1521  bFullVRam=TRUE;iRenderFVR=2;\r
1522 \r
1523  //////////////\r
1524 \r
1525  p2=0;\r
1526 \r
1527  if(sArea==0)\r
1528   {\r
1529    ux=PSXDisplay.DisplayPosition.x;\r
1530    uy=PSXDisplay.DisplayPosition.y;\r
1531    udx=PSXDisplay.DisplayEnd.x-ux;\r
1532    udy=PSXDisplay.DisplayEnd.y-uy;\r
1533    if((PreviousPSXDisplay.DisplayEnd.x-\r
1534        PreviousPSXDisplay.DisplayPosition.x)==udx &&\r
1535       (PreviousPSXDisplay.DisplayEnd.y-\r
1536        PreviousPSXDisplay.DisplayPosition.y)==udy)\r
1537     p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) + \r
1538         PreviousPSXDisplay.DisplayPosition.x);\r
1539   }\r
1540  else\r
1541   {\r
1542    ux=PreviousPSXDisplay.DisplayPosition.x;\r
1543    uy=PreviousPSXDisplay.DisplayPosition.y;\r
1544    udx=PreviousPSXDisplay.DisplayEnd.x-ux;\r
1545    udy=PreviousPSXDisplay.DisplayEnd.y-uy;\r
1546    if((PSXDisplay.DisplayEnd.x-\r
1547        PSXDisplay.DisplayPosition.x)==udx &&\r
1548       (PSXDisplay.DisplayEnd.y-\r
1549        PSXDisplay.DisplayPosition.y)==udy)\r
1550     p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) + \r
1551         PSXDisplay.DisplayPosition.x);\r
1552   }\r
1553 \r
1554  p1=(psxVuw + (1024*uy) + ux);\r
1555  if(p1==p2) p2=0;\r
1556 \r
1557  x=0;y=0;\r
1558  wx=dx=udx;wy=dy=udy;\r
1559 \r
1560  if(udx<=0) return;\r
1561  if(udy<=0) return;\r
1562  if(dx<=0)  return;\r
1563  if(dy<=0)  return;\r
1564  if(wx<=0)  return;\r
1565  if(wy<=0)  return;\r
1566 \r
1567  XS=(float)rRatioRect.right/(float)wx;\r
1568  YS=(float)rRatioRect.bottom/(float)wy;\r
1569 \r
1570  dx=(int)((float)(dx)*XS);\r
1571  dy=(int)((float)(dy)*YS);\r
1572 \r
1573  if(dx>iResX) dx=iResX;\r
1574  if(dy>iResY) dy=iResY;\r
1575 \r
1576  if(dx<=0) return;\r
1577  if(dy<=0) return;\r
1578 \r
1579  // ogl y adjust\r
1580  y=iResY-y-dy;\r
1581 \r
1582  x+=rRatioRect.left;\r
1583  y-=rRatioRect.top;\r
1584 \r
1585  if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;\r
1586 \r
1587  if(!pGfxCardScreen)\r
1588   {\r
1589    glPixelStorei(GL_PACK_ALIGNMENT,1); glError();\r
1590    pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);\r
1591   }\r
1592 \r
1593  ps=pGfxCardScreen;\r
1594  \r
1595  //if(!sArea) glReadBuffer(GL_FRONT);\r
1596 \r
1597  glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); glError();\r
1598  //if(!sArea) glReadBuffer(GL_BACK);\r
1599 \r
1600  s=0;\r
1601 \r
1602  XS=(float)dx/(float)(udx);\r
1603  YS=(float)dy/(float)(udy+1);\r
1604     \r
1605  for(y=udy;y>0;y--)\r
1606   {\r
1607    for(x=0;x<udx;x++)\r
1608     {\r
1609      if(p1>=psxVuw && p1<psxVuw_eom)\r
1610       {\r
1611        px=ps+(3*((int)((float)x * XS))+\r
1612              (3*dx)*((int)((float)y*YS)));\r
1613        sx=(*px)>>3;px++;\r
1614        s=sx;\r
1615        sx=(*px)>>3;px++;\r
1616        s|=sx<<5;\r
1617        sx=(*px)>>3;\r
1618        s|=sx<<10;\r
1619        s&=~0x8000;\r
1620        *p1=s;\r
1621       }\r
1622      if(p2>=psxVuw && p2<psxVuw_eom) *p2=s;\r
1623 \r
1624      p1++;\r
1625      if(p2) p2++;\r
1626     }\r
1627 \r
1628    p1 += 1024 - udx;\r
1629    if(p2) p2 += 1024 - udx;\r
1630   }\r
1631 }\r
1632 \r
1633 ////////////////////////////////////////////////////////////////////////\r
1634 // vram read check (reading from card's back/frontbuffer if needed... \r
1635 // slow!)\r
1636 ////////////////////////////////////////////////////////////////////////\r
1637 \r
1638 void CheckVRamRead(int x, int y, int dx, int dy, bool bFront)\r
1639 {\r
1640  unsigned short sArea;unsigned short * p;\r
1641  int ux,uy,udx,udy,wx,wy;float XS,YS;\r
1642  unsigned char * ps, * px;\r
1643  unsigned short s=0,sx;\r
1644 \r
1645  if(STATUSREG&GPUSTATUS_RGB24) return;\r
1646 \r
1647  if(((dx  > PSXDisplay.DisplayPosition.x) &&\r
1648      (x   < PSXDisplay.DisplayEnd.x) &&\r
1649      (dy  > PSXDisplay.DisplayPosition.y) &&\r
1650      (y   < PSXDisplay.DisplayEnd.y)))\r
1651   sArea=0;\r
1652  else\r
1653  if((!(PSXDisplay.InterlacedTest) &&\r
1654      (dx  > PreviousPSXDisplay.DisplayPosition.x) &&\r
1655      (x   < PreviousPSXDisplay.DisplayEnd.x) &&\r
1656      (dy  > PreviousPSXDisplay.DisplayPosition.y) &&\r
1657      (y   < PreviousPSXDisplay.DisplayEnd.y)))\r
1658   sArea=1;\r
1659  else \r
1660   {\r
1661    return;\r
1662   }\r
1663 \r
1664  if(dwActFixes&0x40)\r
1665   {\r
1666    if(iRenderFVR)\r
1667     {\r
1668      bFullVRam=TRUE;iRenderFVR=2;return;\r
1669     }\r
1670    bFullVRam=TRUE;iRenderFVR=2;\r
1671   }\r
1672 \r
1673  ux=x;uy=y;udx=dx;udy=dy;\r
1674 \r
1675  if(sArea==0)\r
1676   {\r
1677    x -=PSXDisplay.DisplayPosition.x;\r
1678    dx-=PSXDisplay.DisplayPosition.x;\r
1679    y -=PSXDisplay.DisplayPosition.y;\r
1680    dy-=PSXDisplay.DisplayPosition.y;\r
1681    wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x;\r
1682    wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y;\r
1683   }\r
1684  else\r
1685   {\r
1686    x -=PreviousPSXDisplay.DisplayPosition.x;\r
1687    dx-=PreviousPSXDisplay.DisplayPosition.x;\r
1688    y -=PreviousPSXDisplay.DisplayPosition.y;\r
1689    dy-=PreviousPSXDisplay.DisplayPosition.y;\r
1690    wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x;\r
1691    wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y;\r
1692   }\r
1693  if(x<0) {ux-=x;x=0;}\r
1694  if(y<0) {uy-=y;y=0;}\r
1695  if(dx>wx) {udx-=(dx-wx);dx=wx;}\r
1696  if(dy>wy) {udy-=(dy-wy);dy=wy;}\r
1697  udx-=ux;\r
1698  udy-=uy;\r
1699   \r
1700  p=(psxVuw + (1024*uy) + ux);\r
1701 \r
1702  if(udx<=0) return;\r
1703  if(udy<=0) return;\r
1704  if(dx<=0)  return;\r
1705  if(dy<=0)  return;\r
1706  if(wx<=0)  return;\r
1707  if(wy<=0)  return;\r
1708 \r
1709  XS=(float)rRatioRect.right/(float)wx;\r
1710  YS=(float)rRatioRect.bottom/(float)wy;\r
1711 \r
1712  dx=(int)((float)(dx)*XS);\r
1713  dy=(int)((float)(dy)*YS);\r
1714  x=(int)((float)x*XS);\r
1715  y=(int)((float)y*YS);\r
1716 \r
1717  dx-=x;\r
1718  dy-=y;\r
1719 \r
1720  if(dx>iResX) dx=iResX;\r
1721  if(dy>iResY) dy=iResY;\r
1722 \r
1723  if(dx<=0) return;\r
1724  if(dy<=0) return;\r
1725 \r
1726  // ogl y adjust\r
1727  y=iResY-y-dy;\r
1728 \r
1729  x+=rRatioRect.left;\r
1730  y-=rRatioRect.top;\r
1731 \r
1732  if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;\r
1733 \r
1734  if(!pGfxCardScreen)\r
1735   {\r
1736    glPixelStorei(GL_PACK_ALIGNMENT,1); glError();\r
1737    pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);\r
1738   }\r
1739 \r
1740  ps=pGfxCardScreen;\r
1741  \r
1742 // if(bFront) glReadBuffer(GL_FRONT);\r
1743 \r
1744  glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); glError(); glError();\r
1745 // if(bFront) glReadBuffer(GL_BACK);\r
1746 \r
1747  XS=(float)dx/(float)(udx);\r
1748  YS=(float)dy/(float)(udy+1);\r
1749     \r
1750  for(y=udy;y>0;y--)\r
1751   {\r
1752    for(x=0;x<udx;x++)\r
1753     {\r
1754      if(p>=psxVuw && p<psxVuw_eom)\r
1755       {\r
1756        px=ps+(3*((int)((float)x * XS))+\r
1757              (3*dx)*((int)((float)y*YS)));\r
1758        sx=(*px)>>3;px++;\r
1759        s=sx;\r
1760        sx=(*px)>>3;px++;\r
1761        s|=sx<<5;\r
1762        sx=(*px)>>3;\r
1763        s|=sx<<10;\r
1764        s&=~0x8000;\r
1765        *p=s;\r
1766       }\r
1767      p++;\r
1768     }\r
1769    p += 1024 - udx;\r
1770   }\r
1771 }\r
1772 \r
1773 ////////////////////////////////////////////////////////////////////////\r
1774 // core read from vram\r
1775 ////////////////////////////////////////////////////////////////////////\r
1776 \r
1777 void CALLBACK GPUreadDataMem(unsigned long * pMem, int iSize)\r
1778 {\r
1779 int i;\r
1780 \r
1781 if(iDataReadMode!=DR_VRAMTRANSFER) return;\r
1782 \r
1783 GPUIsBusy;\r
1784 \r
1785 // adjust read ptr, if necessary\r
1786 while(VRAMRead.ImagePtr>=psxVuw_eom)\r
1787  VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1788 while(VRAMRead.ImagePtr<psxVuw)\r
1789  VRAMRead.ImagePtr+=iGPUHeight*1024;\r
1790 \r
1791 if((iFrameReadType&1 && iSize>1) &&\r
1792    !(iDrawnSomething==2 &&\r
1793      VRAMRead.x      == VRAMWrite.x     &&\r
1794      VRAMRead.y      == VRAMWrite.y     &&\r
1795      VRAMRead.Width  == VRAMWrite.Width &&\r
1796      VRAMRead.Height == VRAMWrite.Height))\r
1797  CheckVRamRead(VRAMRead.x,VRAMRead.y,\r
1798                VRAMRead.x+VRAMRead.RowsRemaining,\r
1799                VRAMRead.y+VRAMRead.ColsRemaining,\r
1800                TRUE);\r
1801 \r
1802 for(i=0;i<iSize;i++)\r
1803  {\r
1804   // do 2 seperate 16bit reads for compatibility (wrap issues)\r
1805   if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))\r
1806    {\r
1807     // lower 16 bit\r
1808     GPUdataRet=(unsigned long)*VRAMRead.ImagePtr;\r
1809 \r
1810     VRAMRead.ImagePtr++;\r
1811     if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1812     VRAMRead.RowsRemaining --;\r
1813 \r
1814     if(VRAMRead.RowsRemaining<=0)\r
1815      {\r
1816       VRAMRead.RowsRemaining = VRAMRead.Width;\r
1817       VRAMRead.ColsRemaining--;\r
1818       VRAMRead.ImagePtr += 1024 - VRAMRead.Width;\r
1819       if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1820      }\r
1821 \r
1822     // higher 16 bit (always, even if it's an odd width)\r
1823     GPUdataRet|=(unsigned long)(*VRAMRead.ImagePtr)<<16;\r
1824     *pMem++=GPUdataRet;\r
1825 \r
1826     if(VRAMRead.ColsRemaining <= 0)\r
1827      {FinishedVRAMRead();goto ENDREAD;}\r
1828 \r
1829     VRAMRead.ImagePtr++;\r
1830     if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1831     VRAMRead.RowsRemaining--;\r
1832     if(VRAMRead.RowsRemaining<=0)\r
1833      {\r
1834       VRAMRead.RowsRemaining = VRAMRead.Width;\r
1835       VRAMRead.ColsRemaining--;\r
1836       VRAMRead.ImagePtr += 1024 - VRAMRead.Width;\r
1837       if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1838      }\r
1839     if(VRAMRead.ColsRemaining <= 0)\r
1840      {FinishedVRAMRead();goto ENDREAD;}\r
1841    }\r
1842   else {FinishedVRAMRead();goto ENDREAD;}\r
1843  }\r
1844 \r
1845 ENDREAD:\r
1846 GPUIsIdle;\r
1847 }\r
1848 \r
1849 unsigned long CALLBACK GPUreadData(void)\r
1850 {\r
1851  unsigned long l;\r
1852  GPUreadDataMem(&l,1);\r
1853  return GPUdataRet;\r
1854 }\r
1855 \r
1856 ////////////////////////////////////////////////////////////////////////\r
1857 // helper table to know how much data is used by drawing commands\r
1858 ////////////////////////////////////////////////////////////////////////\r
1859 \r
1860 const unsigned char primTableCX[256] =\r
1861 {\r
1862     // 00\r
1863     0,0,3,0,0,0,0,0,\r
1864     // 08\r
1865     0,0,0,0,0,0,0,0,\r
1866     // 10\r
1867     0,0,0,0,0,0,0,0,\r
1868     // 18\r
1869     0,0,0,0,0,0,0,0,\r
1870     // 20\r
1871     4,4,4,4,7,7,7,7,\r
1872     // 28\r
1873     5,5,5,5,9,9,9,9,\r
1874     // 30\r
1875     6,6,6,6,9,9,9,9,\r
1876     // 38\r
1877     8,8,8,8,12,12,12,12,\r
1878     // 40\r
1879     3,3,3,3,0,0,0,0,\r
1880     // 48\r
1881 //    5,5,5,5,6,6,6,6,      //FLINE\r
1882     254,254,254,254,254,254,254,254,\r
1883     // 50\r
1884     4,4,4,4,0,0,0,0,\r
1885     // 58\r
1886 //    7,7,7,7,9,9,9,9,    //    LINEG3    LINEG4\r
1887     255,255,255,255,255,255,255,255,\r
1888     // 60\r
1889     3,3,3,3,4,4,4,4,    //    TILE    SPRT\r
1890     // 68\r
1891     2,2,2,2,3,3,3,3,    //    TILE1\r
1892     // 70\r
1893     2,2,2,2,3,3,3,3,\r
1894     // 78\r
1895     2,2,2,2,3,3,3,3,\r
1896     // 80\r
1897     4,0,0,0,0,0,0,0,\r
1898     // 88\r
1899     0,0,0,0,0,0,0,0,\r
1900     // 90\r
1901     0,0,0,0,0,0,0,0,\r
1902     // 98\r
1903     0,0,0,0,0,0,0,0,\r
1904     // a0\r
1905     3,0,0,0,0,0,0,0,\r
1906     // a8\r
1907     0,0,0,0,0,0,0,0,\r
1908     // b0\r
1909     0,0,0,0,0,0,0,0,\r
1910     // b8\r
1911     0,0,0,0,0,0,0,0,\r
1912     // c0\r
1913     3,0,0,0,0,0,0,0,\r
1914     // c8\r
1915     0,0,0,0,0,0,0,0,\r
1916     // d0\r
1917     0,0,0,0,0,0,0,0,\r
1918     // d8\r
1919     0,0,0,0,0,0,0,0,\r
1920     // e0\r
1921     0,1,1,1,1,1,1,0,\r
1922     // e8\r
1923     0,0,0,0,0,0,0,0,\r
1924     // f0\r
1925     0,0,0,0,0,0,0,0,\r
1926     // f8\r
1927     0,0,0,0,0,0,0,0\r
1928 };\r
1929 \r
1930 ////////////////////////////////////////////////////////////////////////\r
1931 // processes data send to GPU data register\r
1932 ////////////////////////////////////////////////////////////////////////\r
1933 \r
1934 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)\r
1935 {\r
1936 unsigned char command;\r
1937 unsigned long gdata=0;\r
1938 int i=0;\r
1939 GPUIsBusy;\r
1940 GPUIsNotReadyForCommands;\r
1941 \r
1942 STARTVRAM:\r
1943 \r
1944 if(iDataWriteMode==DR_VRAMTRANSFER)\r
1945  {\r
1946   // make sure we are in vram\r
1947   while(VRAMWrite.ImagePtr>=psxVuw_eom)\r
1948    VRAMWrite.ImagePtr-=iGPUHeight*1024;\r
1949   while(VRAMWrite.ImagePtr<psxVuw)\r
1950    VRAMWrite.ImagePtr+=iGPUHeight*1024;\r
1951 \r
1952   // now do the loop\r
1953   while(VRAMWrite.ColsRemaining>0)\r
1954    {\r
1955     while(VRAMWrite.RowsRemaining>0)\r
1956      {\r
1957       if(i>=iSize) {goto ENDVRAM;}\r
1958       i++;\r
1959 \r
1960       gdata=*pMem++;\r
1961 \r
1962       *VRAMWrite.ImagePtr++ = (unsigned short)gdata;\r
1963       if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;\r
1964       VRAMWrite.RowsRemaining --;\r
1965 \r
1966       if(VRAMWrite.RowsRemaining <= 0)\r
1967        {\r
1968         VRAMWrite.ColsRemaining--;\r
1969         if (VRAMWrite.ColsRemaining <= 0)             // last pixel is odd width\r
1970          {\r
1971           gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16);\r
1972           FinishedVRAMWrite();\r
1973           goto ENDVRAM;\r
1974          }\r
1975         VRAMWrite.RowsRemaining = VRAMWrite.Width;\r
1976         VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;\r
1977        }\r
1978 \r
1979       *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16);\r
1980       if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;\r
1981       VRAMWrite.RowsRemaining --;\r
1982      }\r
1983 \r
1984     VRAMWrite.RowsRemaining = VRAMWrite.Width;\r
1985     VRAMWrite.ColsRemaining--;\r
1986     VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;\r
1987    }\r
1988 \r
1989   FinishedVRAMWrite();\r
1990  }\r
1991 \r
1992 ENDVRAM:\r
1993 \r
1994 if(iDataWriteMode==DR_NORMAL)\r
1995  {\r
1996   void (* *primFunc)(unsigned char *);\r
1997   if(bSkipNextFrame) primFunc=primTableSkip;\r
1998   else               primFunc=primTableJ;\r
1999 \r
2000   for(;i<iSize;)\r
2001    {\r
2002     if(iDataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;\r
2003 \r
2004     gdata=*pMem++;i++;\r
2005 \r
2006     if(gpuDataC == 0)\r
2007      {\r
2008       command = (unsigned char)((gdata>>24) & 0xff);\r
2009 \r
2010       if(primTableCX[command])\r
2011        {\r
2012         gpuDataC = primTableCX[command];\r
2013         gpuCommand = command;\r
2014         gpuDataM[0] = gdata;\r
2015         gpuDataP = 1;\r
2016        }\r
2017       else continue;\r
2018      }\r
2019     else\r
2020      {\r
2021       gpuDataM[gpuDataP] = gdata;\r
2022       if(gpuDataC>128)\r
2023        {\r
2024         if((gpuDataC==254 && gpuDataP>=3) ||\r
2025            (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))\r
2026          {\r
2027           if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)\r
2028            gpuDataP=gpuDataC-1;\r
2029          }\r
2030        }\r
2031       gpuDataP++;\r
2032      }\r
2033 \r
2034     if(gpuDataP == gpuDataC)\r
2035      {\r
2036       gpuDataC=gpuDataP=0;\r
2037       primFunc[gpuCommand]((unsigned char *)gpuDataM);\r
2038 \r
2039       if(dwEmuFixes&0x0001 || dwActFixes&0x20000)     // hack for emulating "gpu busy" in some games\r
2040        iFakePrimBusy=4;\r
2041      }\r
2042    } \r
2043  }\r
2044 \r
2045 GPUdataRet=gdata;\r
2046 \r
2047 GPUIsReadyForCommands;\r
2048 GPUIsIdle;                \r
2049 }\r
2050 \r
2051 ////////////////////////////////////////////////////////////////////////\r
2052 \r
2053 void CALLBACK GPUwriteData(unsigned long gdata)\r
2054 {\r
2055  GPUwriteDataMem(&gdata,1);\r
2056 }\r
2057 \r
2058 ////////////////////////////////////////////////////////////////////////\r
2059 // this function will be removed soon (or 'soonish') (or never)\r
2060 ////////////////////////////////////////////////////////////////////////\r
2061 \r
2062 void CALLBACK GPUsetMode(unsigned int gdata)\r
2063 {\r
2064  // ignore old psemu setmode:\r
2065 \r
2066  // imageTransfer = gdata;\r
2067  // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;\r
2068  // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;\r
2069 }\r
2070 \r
2071 // and this function will be removed soon as well, hehehe...\r
2072 long CALLBACK GPUgetMode(void)\r
2073 {\r
2074  // ignore old psemu setmode\r
2075  // return imageTransfer;\r
2076 \r
2077 long iT=0;\r
2078 \r
2079 if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1;\r
2080 if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2;\r
2081 \r
2082 return iT;\r
2083 }\r
2084 \r
2085 ////////////////////////////////////////////////////////////////////////\r
2086 // call config dlg (Windows + Linux)\r
2087 ////////////////////////////////////////////////////////////////////////\r
2088 \r
2089 #ifndef _WINDOWS\r
2090 \r
2091 /*#include <unistd.h>\r
2092 \r
2093 void StartCfgTool(char * pCmdLine)                     // linux: start external cfg tool\r
2094 {\r
2095  FILE * cf;char filename[255],t[255];\r
2096 \r
2097  strcpy(filename,"cfg/cfgPeopsMesaGL");                 // look in cfg sub folder first\r
2098  cf=fopen(filename,"rb");\r
2099  if(cf!=NULL)\r
2100   {\r
2101    fclose(cf);\r
2102    getcwd(t,255);\r
2103    chdir("cfg");\r
2104    sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);\r
2105    system(filename);\r
2106    chdir(t);\r
2107   }\r
2108  else\r
2109   {\r
2110    strcpy(filename,"cfgPeopsMesaGL");                   // look in current folder\r
2111    cf=fopen(filename,"rb");\r
2112    if(cf!=NULL)\r
2113     {\r
2114      fclose(cf);\r
2115      sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);\r
2116      system(filename);\r
2117     }\r
2118    else\r
2119     {\r
2120      sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder\r
2121      cf=fopen(filename,"rb");\r
2122      if(cf!=NULL)\r
2123       {\r
2124        fclose(cf);\r
2125        getcwd(t,255);\r
2126        chdir(getenv("HOME"));\r
2127        sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);\r
2128        system(filename);\r
2129        chdir(t);\r
2130       }\r
2131      else printf("cfgPeopsMesaGL not found!\n");\r
2132     }\r
2133   }\r
2134 }\r
2135 */\r
2136 #endif\r
2137 \r
2138 \r
2139 long CALLBACK GPUconfigure(void)\r
2140 {\r
2141 \r
2142 \r
2143  return 0;\r
2144 }\r
2145 \r
2146 ////////////////////////////////////////////////////////////////////////\r
2147 // sets all kind of act fixes\r
2148 ////////////////////////////////////////////////////////////////////////\r
2149 \r
2150 void SetFixes(void)\r
2151 {\r
2152  ReInitFrameCap();\r
2153 \r
2154  if(dwActFixes & 0x2000) \r
2155       dispWidths[4]=384;\r
2156  else dispWidths[4]=368;\r
2157 }\r
2158 \r
2159 ////////////////////////////////////////////////////////////////////////\r
2160 // Pete Special: make an 'intelligent' dma chain check (<-Tekken3)\r
2161 ////////////////////////////////////////////////////////////////////////\r
2162 \r
2163 unsigned long lUsedAddr[3];\r
2164 \r
2165 __inline BOOL CheckForEndlessLoop(unsigned long laddr)\r
2166 {\r
2167 if(laddr==lUsedAddr[1]) return TRUE;\r
2168 if(laddr==lUsedAddr[2]) return TRUE;\r
2169 \r
2170 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;\r
2171 else                   lUsedAddr[2]=laddr;\r
2172 lUsedAddr[0]=laddr;\r
2173 return FALSE;\r
2174 }\r
2175 \r
2176 ////////////////////////////////////////////////////////////////////////\r
2177 // core gives a dma chain to gpu: same as the gpuwrite interface funcs\r
2178 ////////////////////////////////////////////////////////////////////////\r
2179 \r
2180 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)\r
2181 {\r
2182 unsigned long dmaMem;\r
2183 unsigned char * baseAddrB;\r
2184 short count;unsigned int DMACommandCounter = 0;\r
2185 \r
2186 if(bIsFirstFrame) GLinitialize();\r
2187 \r
2188 GPUIsBusy;\r
2189 \r
2190 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;\r
2191 \r
2192 baseAddrB = (unsigned char*) baseAddrL;\r
2193 \r
2194 do\r
2195  {\r
2196   if(iGPUHeight==512) addr&=0x1FFFFC;\r
2197 \r
2198   if(DMACommandCounter++ > 2000000) break;\r
2199   if(CheckForEndlessLoop(addr)) break;\r
2200 \r
2201   count = baseAddrB[addr+3];\r
2202 \r
2203   dmaMem=addr+4;\r
2204 \r
2205   if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);\r
2206   \r
2207   addr = baseAddrL[addr>>2]&0xffffff;\r
2208  }\r
2209 while (addr != 0xffffff);\r
2210 \r
2211 GPUIsIdle;\r
2212 \r
2213 return 0;\r
2214 }\r
2215            \r
2216 ////////////////////////////////////////////////////////////////////////\r
2217 // show about dlg\r
2218 ////////////////////////////////////////////////////////////////////////\r
2219 \r
2220 void CALLBACK GPUabout(void)\r
2221 {\r
2222 \r
2223 }\r
2224 \r
2225 ////////////////////////////////////////////////////////////////////////\r
2226 // We are ever fine ;)\r
2227 ////////////////////////////////////////////////////////////////////////\r
2228 \r
2229 long CALLBACK GPUtest(void)\r
2230 {\r
2231  // if test fails this function should return negative value for error (unable to continue)\r
2232  // and positive value for warning (can continue but output might be crappy)\r
2233 \r
2234  return 0;\r
2235 }\r
2236 \r
2237 ////////////////////////////////////////////////////////////////////////\r
2238 // save state funcs\r
2239 ////////////////////////////////////////////////////////////////////////\r
2240 \r
2241 ////////////////////////////////////////////////////////////////////////\r
2242 \r
2243 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)\r
2244 {\r
2245 if(ulGetFreezeData==2) \r
2246  {\r
2247   long lSlotNum=*((long *)pF);\r
2248   if(lSlotNum<0) return 0;\r
2249   if(lSlotNum>8) return 0;\r
2250   lSelectedSlot=lSlotNum+1;\r
2251   return 1;\r
2252  }\r
2253 \r
2254 if(!pF)                    return 0; \r
2255 if(pF->ulFreezeVersion!=1) return 0;\r
2256 \r
2257 if(ulGetFreezeData==1)\r
2258  {\r
2259   pF->ulStatus=STATUSREG;\r
2260   memcpy(pF->ulControl,ulStatusControl,256*sizeof(unsigned long));\r
2261   memcpy(pF->psxVRam,  psxVub,         1024*iGPUHeight*2);\r
2262 \r
2263   return 1;\r
2264  }\r
2265 \r
2266 if(ulGetFreezeData!=0) return 0;\r
2267 \r
2268 STATUSREG=pF->ulStatus;\r
2269 memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long));\r
2270 memcpy(psxVub,         pF->psxVRam,  1024*iGPUHeight*2);\r
2271 \r
2272 ResetTextureArea(TRUE);\r
2273 \r
2274  GPUwriteStatus(ulStatusControl[0]);\r
2275  GPUwriteStatus(ulStatusControl[1]);\r
2276  GPUwriteStatus(ulStatusControl[2]);\r
2277  GPUwriteStatus(ulStatusControl[3]);\r
2278  GPUwriteStatus(ulStatusControl[8]);\r
2279  GPUwriteStatus(ulStatusControl[6]);\r
2280  GPUwriteStatus(ulStatusControl[7]);\r
2281  GPUwriteStatus(ulStatusControl[5]);\r
2282  GPUwriteStatus(ulStatusControl[4]);\r
2283  return 1;\r
2284 }\r
2285 \r
2286 ////////////////////////////////////////////////////////////////////////\r
2287 // special "emu infos" / "emu effects" functions\r
2288 ////////////////////////////////////////////////////////////////////////\r
2289 \r
2290 //00 = black\r
2291 //01 = white\r
2292 //10 = red\r
2293 //11 = transparent\r
2294 \r
2295 unsigned char cFont[10][120]=\r
2296 {\r
2297 // 0\r
2298 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2299  0x80,0x00,0x00,0x00,0x00,0x00,\r
2300  0x80,0x00,0x00,0x00,0x00,0x00,\r
2301  0x80,0x00,0x00,0x00,0x00,0x00,\r
2302  0x80,0x00,0x00,0x00,0x00,0x00,\r
2303  0x80,0x00,0x05,0x54,0x00,0x00,\r
2304  0x80,0x00,0x14,0x05,0x00,0x00,\r
2305  0x80,0x00,0x14,0x05,0x00,0x00,\r
2306  0x80,0x00,0x14,0x05,0x00,0x00,\r
2307  0x80,0x00,0x14,0x05,0x00,0x00,\r
2308  0x80,0x00,0x14,0x05,0x00,0x00,\r
2309  0x80,0x00,0x14,0x05,0x00,0x00,\r
2310  0x80,0x00,0x14,0x05,0x00,0x00,\r
2311  0x80,0x00,0x14,0x05,0x00,0x00,\r
2312  0x80,0x00,0x05,0x54,0x00,0x00,\r
2313  0x80,0x00,0x00,0x00,0x00,0x00,\r
2314  0x80,0x00,0x00,0x00,0x00,0x00,\r
2315  0x80,0x00,0x00,0x00,0x00,0x00,\r
2316  0x80,0x00,0x00,0x00,0x00,0x00,\r
2317  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2318 },\r
2319 // 1\r
2320 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2321  0x80,0x00,0x00,0x00,0x00,0x00,\r
2322  0x80,0x00,0x00,0x00,0x00,0x00,\r
2323  0x80,0x00,0x00,0x00,0x00,0x00,\r
2324  0x80,0x00,0x00,0x00,0x00,0x00,\r
2325  0x80,0x00,0x00,0x50,0x00,0x00,\r
2326  0x80,0x00,0x05,0x50,0x00,0x00,\r
2327  0x80,0x00,0x00,0x50,0x00,0x00,\r
2328  0x80,0x00,0x00,0x50,0x00,0x00,\r
2329  0x80,0x00,0x00,0x50,0x00,0x00,\r
2330  0x80,0x00,0x00,0x50,0x00,0x00,\r
2331  0x80,0x00,0x00,0x50,0x00,0x00,\r
2332  0x80,0x00,0x00,0x50,0x00,0x00,\r
2333  0x80,0x00,0x00,0x50,0x00,0x00,\r
2334  0x80,0x00,0x05,0x55,0x00,0x00,\r
2335  0x80,0x00,0x00,0x00,0x00,0x00,\r
2336  0x80,0x00,0x00,0x00,0x00,0x00,\r
2337  0x80,0x00,0x00,0x00,0x00,0x00,\r
2338  0x80,0x00,0x00,0x00,0x00,0x00,\r
2339  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2340 },\r
2341 // 2\r
2342 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2343  0x80,0x00,0x00,0x00,0x00,0x00,\r
2344  0x80,0x00,0x00,0x00,0x00,0x00,\r
2345  0x80,0x00,0x00,0x00,0x00,0x00,\r
2346  0x80,0x00,0x00,0x00,0x00,0x00,\r
2347  0x80,0x00,0x05,0x54,0x00,0x00,\r
2348  0x80,0x00,0x14,0x05,0x00,0x00,\r
2349  0x80,0x00,0x00,0x05,0x00,0x00,\r
2350  0x80,0x00,0x00,0x05,0x00,0x00,\r
2351  0x80,0x00,0x00,0x14,0x00,0x00,\r
2352  0x80,0x00,0x00,0x50,0x00,0x00,\r
2353  0x80,0x00,0x01,0x40,0x00,0x00,\r
2354  0x80,0x00,0x05,0x00,0x00,0x00,\r
2355  0x80,0x00,0x14,0x00,0x00,0x00,\r
2356  0x80,0x00,0x15,0x55,0x00,0x00,\r
2357  0x80,0x00,0x00,0x00,0x00,0x00,\r
2358  0x80,0x00,0x00,0x00,0x00,0x00,\r
2359  0x80,0x00,0x00,0x00,0x00,0x00,\r
2360  0x80,0x00,0x00,0x00,0x00,0x00,\r
2361  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2362 },\r
2363 // 3\r
2364 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2365  0x80,0x00,0x00,0x00,0x00,0x00,\r
2366  0x80,0x00,0x00,0x00,0x00,0x00,\r
2367  0x80,0x00,0x00,0x00,0x00,0x00,\r
2368  0x80,0x00,0x00,0x00,0x00,0x00,\r
2369  0x80,0x00,0x05,0x54,0x00,0x00,\r
2370  0x80,0x00,0x14,0x05,0x00,0x00,\r
2371  0x80,0x00,0x00,0x05,0x00,0x00,\r
2372  0x80,0x00,0x00,0x05,0x00,0x00,\r
2373  0x80,0x00,0x01,0x54,0x00,0x00,\r
2374  0x80,0x00,0x00,0x05,0x00,0x00,\r
2375  0x80,0x00,0x00,0x05,0x00,0x00,\r
2376  0x80,0x00,0x00,0x05,0x00,0x00,\r
2377  0x80,0x00,0x14,0x05,0x00,0x00,\r
2378  0x80,0x00,0x05,0x54,0x00,0x00,\r
2379  0x80,0x00,0x00,0x00,0x00,0x00,\r
2380  0x80,0x00,0x00,0x00,0x00,0x00,\r
2381  0x80,0x00,0x00,0x00,0x00,0x00,\r
2382  0x80,0x00,0x00,0x00,0x00,0x00,\r
2383  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2384 },\r
2385 // 4\r
2386 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2387  0x80,0x00,0x00,0x00,0x00,0x00,\r
2388  0x80,0x00,0x00,0x00,0x00,0x00,\r
2389  0x80,0x00,0x00,0x00,0x00,0x00,\r
2390  0x80,0x00,0x00,0x00,0x00,0x00,\r
2391  0x80,0x00,0x00,0x14,0x00,0x00,\r
2392  0x80,0x00,0x00,0x54,0x00,0x00,\r
2393  0x80,0x00,0x01,0x54,0x00,0x00,\r
2394  0x80,0x00,0x01,0x54,0x00,0x00,\r
2395  0x80,0x00,0x05,0x14,0x00,0x00,\r
2396  0x80,0x00,0x14,0x14,0x00,0x00,\r
2397  0x80,0x00,0x15,0x55,0x00,0x00,\r
2398  0x80,0x00,0x00,0x14,0x00,0x00,\r
2399  0x80,0x00,0x00,0x14,0x00,0x00,\r
2400  0x80,0x00,0x00,0x55,0x00,0x00,\r
2401  0x80,0x00,0x00,0x00,0x00,0x00,\r
2402  0x80,0x00,0x00,0x00,0x00,0x00,\r
2403  0x80,0x00,0x00,0x00,0x00,0x00,\r
2404  0x80,0x00,0x00,0x00,0x00,0x00,\r
2405  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2406 },\r
2407 // 5\r
2408 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2409  0x80,0x00,0x00,0x00,0x00,0x00,\r
2410  0x80,0x00,0x00,0x00,0x00,0x00,\r
2411  0x80,0x00,0x00,0x00,0x00,0x00,\r
2412  0x80,0x00,0x00,0x00,0x00,0x00,\r
2413  0x80,0x00,0x15,0x55,0x00,0x00,\r
2414  0x80,0x00,0x14,0x00,0x00,0x00,\r
2415  0x80,0x00,0x14,0x00,0x00,0x00,\r
2416  0x80,0x00,0x14,0x00,0x00,0x00,\r
2417  0x80,0x00,0x15,0x54,0x00,0x00,\r
2418  0x80,0x00,0x00,0x05,0x00,0x00,\r
2419  0x80,0x00,0x00,0x05,0x00,0x00,\r
2420  0x80,0x00,0x00,0x05,0x00,0x00,\r
2421  0x80,0x00,0x14,0x05,0x00,0x00,\r
2422  0x80,0x00,0x05,0x54,0x00,0x00,\r
2423  0x80,0x00,0x00,0x00,0x00,0x00,\r
2424  0x80,0x00,0x00,0x00,0x00,0x00,\r
2425  0x80,0x00,0x00,0x00,0x00,0x00,\r
2426  0x80,0x00,0x00,0x00,0x00,0x00,\r
2427  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2428 },\r
2429 // 6\r
2430 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2431  0x80,0x00,0x00,0x00,0x00,0x00,\r
2432  0x80,0x00,0x00,0x00,0x00,0x00,\r
2433  0x80,0x00,0x00,0x00,0x00,0x00,\r
2434  0x80,0x00,0x00,0x00,0x00,0x00,\r
2435  0x80,0x00,0x01,0x54,0x00,0x00,\r
2436  0x80,0x00,0x05,0x00,0x00,0x00,\r
2437  0x80,0x00,0x14,0x00,0x00,0x00,\r
2438  0x80,0x00,0x14,0x00,0x00,0x00,\r
2439  0x80,0x00,0x15,0x54,0x00,0x00,\r
2440  0x80,0x00,0x15,0x05,0x00,0x00,\r
2441  0x80,0x00,0x14,0x05,0x00,0x00,\r
2442  0x80,0x00,0x14,0x05,0x00,0x00,\r
2443  0x80,0x00,0x14,0x05,0x00,0x00,\r
2444  0x80,0x00,0x05,0x54,0x00,0x00,\r
2445  0x80,0x00,0x00,0x00,0x00,0x00,\r
2446  0x80,0x00,0x00,0x00,0x00,0x00,\r
2447  0x80,0x00,0x00,0x00,0x00,0x00,\r
2448  0x80,0x00,0x00,0x00,0x00,0x00,\r
2449  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2450 },\r
2451 // 7\r
2452 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2453  0x80,0x00,0x00,0x00,0x00,0x00,\r
2454  0x80,0x00,0x00,0x00,0x00,0x00,\r
2455  0x80,0x00,0x00,0x00,0x00,0x00,\r
2456  0x80,0x00,0x00,0x00,0x00,0x00,\r
2457  0x80,0x00,0x15,0x55,0x00,0x00,\r
2458  0x80,0x00,0x14,0x05,0x00,0x00,\r
2459  0x80,0x00,0x00,0x14,0x00,0x00,\r
2460  0x80,0x00,0x00,0x14,0x00,0x00,\r
2461  0x80,0x00,0x00,0x50,0x00,0x00,\r
2462  0x80,0x00,0x00,0x50,0x00,0x00,\r
2463  0x80,0x00,0x01,0x40,0x00,0x00,\r
2464  0x80,0x00,0x01,0x40,0x00,0x00,\r
2465  0x80,0x00,0x05,0x00,0x00,0x00,\r
2466  0x80,0x00,0x05,0x00,0x00,0x00,\r
2467  0x80,0x00,0x00,0x00,0x00,0x00,\r
2468  0x80,0x00,0x00,0x00,0x00,0x00,\r
2469  0x80,0x00,0x00,0x00,0x00,0x00,\r
2470  0x80,0x00,0x00,0x00,0x00,0x00,\r
2471  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2472 },\r
2473 // 8\r
2474 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2475  0x80,0x00,0x00,0x00,0x00,0x00,\r
2476  0x80,0x00,0x00,0x00,0x00,0x00,\r
2477  0x80,0x00,0x00,0x00,0x00,0x00,\r
2478  0x80,0x00,0x00,0x00,0x00,0x00,\r
2479  0x80,0x00,0x05,0x54,0x00,0x00,\r
2480  0x80,0x00,0x14,0x05,0x00,0x00,\r
2481  0x80,0x00,0x14,0x05,0x00,0x00,\r
2482  0x80,0x00,0x14,0x05,0x00,0x00,\r
2483  0x80,0x00,0x05,0x54,0x00,0x00,\r
2484  0x80,0x00,0x14,0x05,0x00,0x00,\r
2485  0x80,0x00,0x14,0x05,0x00,0x00,\r
2486  0x80,0x00,0x14,0x05,0x00,0x00,\r
2487  0x80,0x00,0x14,0x05,0x00,0x00,\r
2488  0x80,0x00,0x05,0x54,0x00,0x00,\r
2489  0x80,0x00,0x00,0x00,0x00,0x00,\r
2490  0x80,0x00,0x00,0x00,0x00,0x00,\r
2491  0x80,0x00,0x00,0x00,0x00,0x00,\r
2492  0x80,0x00,0x00,0x00,0x00,0x00,\r
2493  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2494 },\r
2495 // 9\r
2496 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2497  0x80,0x00,0x00,0x00,0x00,0x00,\r
2498  0x80,0x00,0x00,0x00,0x00,0x00,\r
2499  0x80,0x00,0x00,0x00,0x00,0x00,\r
2500  0x80,0x00,0x00,0x00,0x00,0x00,\r
2501  0x80,0x00,0x05,0x54,0x00,0x00,\r
2502  0x80,0x00,0x14,0x05,0x00,0x00,\r
2503  0x80,0x00,0x14,0x05,0x00,0x00,\r
2504  0x80,0x00,0x14,0x05,0x00,0x00,\r
2505  0x80,0x00,0x14,0x15,0x00,0x00,\r
2506  0x80,0x00,0x05,0x55,0x00,0x00,\r
2507  0x80,0x00,0x00,0x05,0x00,0x00,\r
2508  0x80,0x00,0x00,0x05,0x00,0x00,\r
2509  0x80,0x00,0x00,0x14,0x00,0x00,\r
2510  0x80,0x00,0x05,0x50,0x00,0x00,\r
2511  0x80,0x00,0x00,0x00,0x00,0x00,\r
2512  0x80,0x00,0x00,0x00,0x00,0x00,\r
2513  0x80,0x00,0x00,0x00,0x00,0x00,\r
2514  0x80,0x00,0x00,0x00,0x00,0x00,\r
2515  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2516 }\r
2517 };\r
2518 \r
2519 ////////////////////////////////////////////////////////////////////////\r
2520 \r
2521 void PaintPicDot(unsigned char * p,unsigned char c)\r
2522 {\r
2523  if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;}\r
2524  if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;}\r
2525  if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;}\r
2526 }\r
2527 \r
2528 ////////////////////////////////////////////////////////////////////////\r
2529 \r
2530 long CALLBACK GPUgetScreenPic(unsigned char * pMem)\r
2531 {\r
2532  float XS,YS;int x,y,v;\r
2533  unsigned char * ps, * px, * pf;\r
2534  unsigned char c;\r
2535 \r
2536  if(!pGfxCardScreen)\r
2537   {\r
2538    glPixelStorei(GL_PACK_ALIGNMENT,1); glError();\r
2539    pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);\r
2540   }\r
2541 \r
2542  ps=pGfxCardScreen;\r
2543 \r
2544 // glReadBuffer(GL_FRONT);\r
2545 \r
2546  glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps); glError();\r
2547                \r
2548 // glReadBuffer(GL_BACK);\r
2549 \r
2550  XS=(float)iResX/128;\r
2551  YS=(float)iResY/96;\r
2552  pf=pMem;\r
2553 \r
2554  for(y=96;y>0;y--)\r
2555   {\r
2556    for(x=0;x<128;x++)\r
2557     {\r
2558      px=ps+(3*((int)((float)x * XS))+\r
2559            (3*iResX)*((int)((float)y*YS)));\r
2560      *(pf+0)=*(px+2);\r
2561      *(pf+1)=*(px+1);\r
2562      *(pf+2)=*(px+0);\r
2563      pf+=3;\r
2564     }\r
2565   }\r
2566 \r
2567  /////////////////////////////////////////////////////////////////////\r
2568  // generic number/border painter\r
2569 \r
2570  pf=pMem+(103*3);\r
2571 \r
2572  for(y=0;y<20;y++)\r
2573   {\r
2574    for(x=0;x<6;x++)\r
2575     {\r
2576      c=cFont[lSelectedSlot][x+y*6];\r
2577      v=(c&0xc0)>>6;\r
2578      PaintPicDot(pf,(unsigned char)v);pf+=3;                // paint the dots into the rect\r
2579      v=(c&0x30)>>4;\r
2580      PaintPicDot(pf,(unsigned char)v);pf+=3;\r
2581      v=(c&0x0c)>>2;\r
2582      PaintPicDot(pf,(unsigned char)v);pf+=3;\r
2583      v=c&0x03;\r
2584      PaintPicDot(pf,(unsigned char)v);pf+=3;\r
2585     }\r
2586    pf+=104*3;\r
2587   }\r
2588 \r
2589  pf=pMem;\r
2590  for(x=0;x<128;x++)\r
2591   {\r
2592    *(pf+(95*128*3))=0x00;*pf++=0x00;\r
2593    *(pf+(95*128*3))=0x00;*pf++=0x00;\r
2594    *(pf+(95*128*3))=0xff;*pf++=0xff;\r
2595   }\r
2596  pf=pMem;\r
2597  for(y=0;y<96;y++)\r
2598   {\r
2599    *(pf+(127*3))=0x00;*pf++=0x00;\r
2600    *(pf+(127*3))=0x00;*pf++=0x00;\r
2601    *(pf+(127*3))=0xff;*pf++=0xff;\r
2602    pf+=127*3;\r
2603   }\r
2604 \r
2605 }\r
2606 \r
2607 ////////////////////////////////////////////////////////////////////////\r
2608 \r
2609 long CALLBACK GPUshowScreenPic(unsigned char * pMem)\r
2610 {\r
2611 // DestroyPic();\r
2612 // if(pMem==0) return;\r
2613 // CreatePic(pMem);\r
2614 }\r
2615 \r
2616 ////////////////////////////////////////////////////////////////////////\r
2617 \r
2618 void CALLBACK GPUsetfix(unsigned long dwFixBits)\r
2619 {\r
2620  dwEmuFixes=dwFixBits;\r
2621 }\r
2622 \r
2623 ////////////////////////////////////////////////////////////////////////\r
2624  \r
2625 void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig)\r
2626 {\r
2627  int iVibVal;\r
2628 \r
2629  if(PSXDisplay.DisplayModeNew.x)                       // calc min "shake pixel" from screen width\r
2630       iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x);\r
2631  else iVibVal=1;\r
2632                                                        // big rumble: 4...15 sp ; small rumble 1...3 sp\r
2633  if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig  *iVibVal)/10));\r
2634  else     iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10));\r
2635 \r
2636  srand(timeGetTime());                                 // init rand (will be used in BufferSwap)\r
2637 \r
2638  iRumbleTime=15;                                       // let the rumble last 16 buffer swaps\r
2639 }\r
2640                                                        \r
2641 ////////////////////////////////////////////////////////////////////////\r
2642 // main emu can set display infos (A/M/G/D) \r
2643 ////////////////////////////////////////////////////////////////////////\r
2644 \r
2645 void CALLBACK GPUdisplayFlags(unsigned long dwFlags)\r
2646 {\r
2647 // dwCoreFlags=dwFlags;\r
2648 }\r
2649 \r
2650 // pcsx-rearmed callbacks\r
2651 void CALLBACK GPUrearmedCallbacks(const void **cbs)\r
2652 {\r
2653  rearmed_get_layer_pos = cbs[0];\r
2654 }\r
2655 \r
2656 static void flipEGL(void)\r
2657 {\r
2658  eglSwapBuffers(display, surface);\r
2659 }\r