gpu-gles: schtruck/fpse merge: ClientState optimization
[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 // lGPUstatusRet = 0x74000000;\r
510 \r
511 // with some emus, we could do the OGL init right here... oh my\r
512  if(bIsFirstFrame) GLinitialize();\r
513 \r
514  return 0;\r
515 }\r
516 \r
517 ////////////////////////////////////////////////////////////////////////\r
518 // close\r
519 ////////////////////////////////////////////////////////////////////////\r
520 \r
521 \r
522 long GPUclose()                                        // LINUX CLOSE\r
523 {\r
524  GLcleanup();                                          // close OGL\r
525 \r
526  if(pGfxCardScreen) free(pGfxCardScreen);              // free helper memory\r
527  pGfxCardScreen=0;\r
528 \r
529 // osd_close_display();                                  // destroy display\r
530 \r
531  return 0;\r
532 }\r
533 \r
534 ////////////////////////////////////////////////////////////////////////\r
535 // I shot the sheriff... last function called from emu \r
536 ////////////////////////////////////////////////////////////////////////\r
537 \r
538 long CALLBACK GPUshutdown()\r
539 {\r
540  if(psxVSecure) free(psxVSecure);                      // kill emulated vram memory\r
541  psxVSecure=0;\r
542 \r
543  return 0;\r
544 }\r
545 \r
546 ////////////////////////////////////////////////////////////////////////\r
547 // paint it black: simple func to clean up optical border garbage\r
548 ////////////////////////////////////////////////////////////////////////\r
549 \r
550 void PaintBlackBorders(void)\r
551 {\r
552  short s;\r
553  glDisable(GL_SCISSOR_TEST); glError();\r
554  if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} glError();\r
555  if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} glError();\r
556  if(bBlendEnable)     {glDisable(GL_BLEND);bBlendEnable=FALSE;} glError();\r
557  glDisable(GL_ALPHA_TEST); glError();\r
558 \r
559  glEnable(GL_ALPHA_TEST); glError();\r
560  glEnable(GL_SCISSOR_TEST); glError();\r
561 \r
562 }\r
563 \r
564 ////////////////////////////////////////////////////////////////////////\r
565 // helper to draw scanlines\r
566 ////////////////////////////////////////////////////////////////////////\r
567 \r
568 __inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, \r
569                                     OGLVertex* vertex3, OGLVertex* vertex4) \r
570 {\r
571 \r
572 }\r
573 \r
574 ////////////////////////////////////////////////////////////////////////\r
575 // scanlines\r
576 ////////////////////////////////////////////////////////////////////////\r
577 \r
578 void SetScanLines(void)\r
579 {\r
580 }\r
581 \r
582 ////////////////////////////////////////////////////////////////////////\r
583 // blur, babe, blur (heavy performance hit for a so-so fullscreen effect)\r
584 ////////////////////////////////////////////////////////////////////////\r
585 \r
586 \r
587 ////////////////////////////////////////////////////////////////////////\r
588 // Update display (swap buffers)... called in interlaced mode on \r
589 // every emulated vsync, otherwise whenever the displayed screen region\r
590 // has been changed\r
591 ////////////////////////////////////////////////////////////////////////\r
592 \r
593 int iLastRGB24=0;                                      // special vars for checking when to skip two display updates\r
594 int iSkipTwo=0;\r
595 void GPUvSinc(void){\r
596 updateDisplay();\r
597 }\r
598 void updateDisplay(void)                               // UPDATE DISPLAY\r
599 {\r
600 BOOL bBlur=FALSE;\r
601 \r
602 \r
603 bFakeFrontBuffer=FALSE;\r
604 bRenderFrontBuffer=FALSE;\r
605 \r
606 if(iRenderFVR)                                        // frame buffer read fix mode still active?\r
607  {\r
608   iRenderFVR--;                                       // -> if some frames in a row without read access: turn off mode\r
609   if(!iRenderFVR) bFullVRam=FALSE;\r
610  }\r
611 \r
612 if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1)      // (mdec) garbage check\r
613  {\r
614   iSkipTwo=2;                                         // -> skip two frames to avoid garbage if color mode changes\r
615  }\r
616 iLastRGB24=0;\r
617 \r
618 if(PSXDisplay.RGB24)// && !bNeedUploadAfter)          // (mdec) upload wanted?\r
619  {\r
620   PrepareFullScreenUpload(-1);\r
621   UploadScreen(PSXDisplay.Interlaced);                // -> upload whole screen from psx vram\r
622   bNeedUploadTest=FALSE;\r
623   bNeedInterlaceUpdate=FALSE;\r
624   bNeedUploadAfter=FALSE;\r
625   bNeedRGB24Update=FALSE;\r
626  }\r
627 else\r
628 if(bNeedInterlaceUpdate)                              // smaller upload?\r
629  {\r
630   bNeedInterlaceUpdate=FALSE;\r
631   xrUploadArea=xrUploadAreaIL;                        // -> upload this rect\r
632   UploadScreen(TRUE);\r
633  }\r
634 \r
635 if(dwActFixes&512) bCheckFF9G4(NULL);                 // special game fix for FF9 \r
636 \r
637 if(PreviousPSXDisplay.Range.x0||                      // paint black borders around display area, if needed\r
638    PreviousPSXDisplay.Range.y0)\r
639  PaintBlackBorders();\r
640 \r
641 if(PSXDisplay.Disabled)                               // display disabled?\r
642  {\r
643   //LOGE("PSXDisplay.Disabled");\r
644 \r
645   // moved here\r
646   glDisable(GL_SCISSOR_TEST); glError();                       \r
647   glClearColor(0,0,0,128); glError();                 // -> clear whole backbuffer\r
648   glClear(uiBufferBits); glError();\r
649   glEnable(GL_SCISSOR_TEST); glError();                       \r
650   gl_z=0.0f;\r
651   bDisplayNotSet = TRUE;\r
652  }\r
653 \r
654 if(iSkipTwo)                                          // we are in skipping mood?\r
655  {\r
656   iSkipTwo--;\r
657   iDrawnSomething=0;                                  // -> simply lie about something drawn\r
658  }\r
659 \r
660 //if(iBlurBuffer && !bSkipNextFrame)                    // "blur display" activated?\r
661 // {BlurBackBuffer();bBlur=TRUE;}                       // -> blur it\r
662 \r
663 // if(iUseScanLines) SetScanLines();                     // "scan lines" activated? do it\r
664 \r
665 // if(usCursorActive) ShowGunCursor();                   // "gun cursor" wanted? show 'em\r
666 \r
667 if(dwActFixes&128)                                    // special FPS limitation mode?\r
668  {\r
669   if(bUseFrameLimit) PCFrameCap();                    // -> ok, do it\r
670 //   if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS)  \r
671    PCcalcfps();         \r
672  }\r
673 \r
674 // if(gTexPicName) DisplayPic();                         // some gpu info picture active? display it\r
675 \r
676 // if(bSnapShot) DoSnapShot();                           // snapshot key pressed? cheeeese :)\r
677 \r
678 // if(ulKeybits&KEY_SHOWFPS)                             // wanna see FPS?\r
679  {\r
680 //   sprintf(szDispBuf,"%06.1f",fps_cur);\r
681 //   DisplayText();                                      // -> show it\r
682  }\r
683 \r
684 //----------------------------------------------------//\r
685 // main buffer swapping (well, or skip it)\r
686 \r
687 if(bUseFrameSkip)                                     // frame skipping active ?\r
688  {\r
689   if(!bSkipNextFrame) \r
690    {\r
691     if(iDrawnSomething)     flipEGL();\r
692    }\r
693     if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) \r
694      {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}\r
695     else bSkipNextFrame = FALSE;\r
696 \r
697  }\r
698 else                                                  // no skip ?\r
699  {\r
700   if(iDrawnSomething)  flipEGL();\r
701  }\r
702 \r
703 iDrawnSomething=0;\r
704 \r
705 //----------------------------------------------------//\r
706 \r
707 if(lClearOnSwap)                                      // clear buffer after swap?\r
708  {\r
709   GLclampf g,b,r;\r
710 \r
711   if(bDisplayNotSet)                                  // -> set new vals\r
712    SetOGLDisplaySettings(1);\r
713 \r
714   g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f;      // -> get col\r
715   b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f;\r
716   r=((GLclampf)RED(lClearOnSwapColor))/255.0f;\r
717   glDisable(GL_SCISSOR_TEST); glError();                       \r
718   glClearColor(r,g,b,128); glError();                 // -> clear \r
719   glClear(uiBufferBits); glError();\r
720   glEnable(GL_SCISSOR_TEST); glError();                       \r
721   lClearOnSwap=0;                                     // -> done\r
722  }\r
723 else \r
724  {\r
725 //  if(bBlur) UnBlurBackBuffer();                       // unblur buff, if blurred before\r
726 \r
727   if(iZBufferDepth)                                   // clear zbuffer as well (if activated)\r
728    {\r
729     glDisable(GL_SCISSOR_TEST); glError();\r
730     glClear(GL_DEPTH_BUFFER_BIT); glError();\r
731     glEnable(GL_SCISSOR_TEST); glError();\r
732    }\r
733  }\r
734 \r
735 gl_z=0.0f;\r
736 \r
737 //----------------------------------------------------//\r
738 // additional uploads immediatly after swapping\r
739 \r
740 if(bNeedUploadAfter)                                  // upload wanted?\r
741  {\r
742   bNeedUploadAfter=FALSE;                           \r
743   bNeedUploadTest=FALSE;\r
744   UploadScreen(-1);                                   // -> upload\r
745  }\r
746 \r
747 if(bNeedUploadTest)\r
748  {\r
749   bNeedUploadTest=FALSE;\r
750   if(PSXDisplay.InterlacedTest &&\r
751      //iOffscreenDrawing>2 &&\r
752      PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x &&\r
753      PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x &&\r
754      PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y &&\r
755      PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y)\r
756    {\r
757     PrepareFullScreenUpload(TRUE);\r
758     UploadScreen(TRUE);\r
759    }\r
760  }\r
761 \r
762 //----------------------------------------------------//\r
763 // rumbling (main emu pad effect)\r
764 \r
765 if(iRumbleTime)                                       // shake screen by modifying view port\r
766  {\r
767   int i1=0,i2=0,i3=0,i4=0;\r
768 \r
769   iRumbleTime--;\r
770   if(iRumbleTime) \r
771    {\r
772     i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
773     i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
774     i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
775     i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); \r
776    }\r
777 \r
778   glViewport(rRatioRect.left+i1,                      \r
779              iResY-(rRatioRect.top+rRatioRect.bottom)+i2,\r
780              rRatioRect.right+i3, \r
781              rRatioRect.bottom+i4); glError();\r
782  }\r
783 \r
784 //----------------------------------------------------//\r
785 \r
786 \r
787 \r
788 // if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff();         // reset on gpu mode changes? do it before next frame is filled\r
789 }\r
790 \r
791 ////////////////////////////////////////////////////////////////////////\r
792 // update front display: smaller update func, if something has changed \r
793 // in the frontbuffer... dirty, but hey... real men know no pain\r
794 ////////////////////////////////////////////////////////////////////////\r
795 \r
796 void updateFrontDisplay(void)\r
797 {\r
798 if(PreviousPSXDisplay.Range.x0||\r
799    PreviousPSXDisplay.Range.y0)\r
800  PaintBlackBorders();\r
801 \r
802 //if(iBlurBuffer) BlurBackBuffer();\r
803 \r
804 //if(iUseScanLines) SetScanLines();\r
805 \r
806 // if(usCursorActive) ShowGunCursor();\r
807 \r
808 bFakeFrontBuffer=FALSE;\r
809 bRenderFrontBuffer=FALSE;\r
810 \r
811 // if(gTexPicName) DisplayPic();\r
812 // if(ulKeybits&KEY_SHOWFPS) DisplayText();\r
813 \r
814 if(iDrawnSomething)                                   // linux:\r
815       flipEGL();\r
816 \r
817 \r
818 //if(iBlurBuffer) UnBlurBackBuffer();\r
819 }\r
820                                              \r
821 ////////////////////////////////////////////////////////////////////////\r
822 // check if update needed\r
823 ////////////////////////////////////////////////////////////////////////\r
824 void ChangeDispOffsetsX(void)                          // CENTER X\r
825 {\r
826 long lx,l;short sO;\r
827 \r
828 if(!PSXDisplay.Range.x1) return;                      // some range given?\r
829 \r
830 l=PSXDisplay.DisplayMode.x;\r
831 \r
832 l*=(long)PSXDisplay.Range.x1;                         // some funky calculation\r
833 l/=2560;lx=l;l&=0xfffffff8;\r
834 \r
835 if(l==PreviousPSXDisplay.Range.x1) return;            // some change?\r
836 \r
837 sO=PreviousPSXDisplay.Range.x0;                       // store old\r
838 \r
839 if(lx>=PSXDisplay.DisplayMode.x)                      // range bigger?\r
840  {\r
841   PreviousPSXDisplay.Range.x1=                        // -> take display width\r
842    PSXDisplay.DisplayMode.x;\r
843   PreviousPSXDisplay.Range.x0=0;                      // -> start pos is 0\r
844  }\r
845 else                                                  // range smaller? center it\r
846  {\r
847   PreviousPSXDisplay.Range.x1=l;                      // -> store width (8 pixel aligned)\r
848    PreviousPSXDisplay.Range.x0=                       // -> calc start pos\r
849    (PSXDisplay.Range.x0-500)/8;\r
850   if(PreviousPSXDisplay.Range.x0<0)                   // -> we don't support neg. values yet\r
851    PreviousPSXDisplay.Range.x0=0;\r
852 \r
853   if((PreviousPSXDisplay.Range.x0+lx)>                // -> uhuu... that's too much\r
854      PSXDisplay.DisplayMode.x)\r
855    {\r
856     PreviousPSXDisplay.Range.x0=                      // -> adjust start\r
857      PSXDisplay.DisplayMode.x-lx;\r
858     PreviousPSXDisplay.Range.x1+=lx-l;                // -> adjust width\r
859    }                   \r
860  }\r
861 \r
862 if(sO!=PreviousPSXDisplay.Range.x0)                   // something changed?\r
863  {\r
864   bDisplayNotSet=TRUE;                                // -> recalc display stuff\r
865  }\r
866 }\r
867 \r
868 ////////////////////////////////////////////////////////////////////////\r
869 \r
870 void ChangeDispOffsetsY(void)                          // CENTER Y\r
871 {\r
872 int iT;short sO;                                      // store previous y size\r
873 \r
874 if(PSXDisplay.PAL) iT=48; else iT=28;                 // different offsets on PAL/NTSC\r
875 \r
876 if(PSXDisplay.Range.y0>=iT)                           // crossed the security line? :)\r
877  {\r
878   PreviousPSXDisplay.Range.y1=                        // -> store width\r
879    PSXDisplay.DisplayModeNew.y;\r
880   \r
881   sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double;    // -> calc offset\r
882   if(sO<0) sO=0;\r
883 \r
884   PSXDisplay.DisplayModeNew.y+=sO;                    // -> add offset to y size, too\r
885  }\r
886 else sO=0;                                            // else no offset\r
887 \r
888 if(sO!=PreviousPSXDisplay.Range.y0)                   // something changed?\r
889  {\r
890   PreviousPSXDisplay.Range.y0=sO;\r
891   bDisplayNotSet=TRUE;                                // -> recalc display stuff\r
892  }\r
893 }\r
894 \r
895 ////////////////////////////////////////////////////////////////////////\r
896 // Aspect ratio of ogl screen: simply adjusting ogl view port\r
897 ////////////////////////////////////////////////////////////////////////\r
898 \r
899 void SetAspectRatio(void)\r
900 {\r
901 float xs,ys,s;RECT r;\r
902 \r
903 if(!PSXDisplay.DisplayModeNew.x) return;\r
904 if(!PSXDisplay.DisplayModeNew.y) return;\r
905 \r
906 #if 0\r
907 xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x;\r
908 ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y;\r
909 \r
910 s=min(xs,ys);\r
911 r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s);\r
912 r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s);\r
913 if(r.right  > iResX) r.right  = iResX;\r
914 if(r.bottom > iResY) r.bottom = iResY;\r
915 if(r.right  < 1)     r.right  = 1;\r
916 if(r.bottom < 1)     r.bottom = 1;\r
917 \r
918 r.left = (iResX-r.right)/2;\r
919 r.top  = (iResY-r.bottom)/2;\r
920 if(r.bottom<rRatioRect.bottom ||\r
921    r.right <rRatioRect.right)\r
922  {\r
923   RECT rC;\r
924   glClearColor(0,0,0,128); glError();\r
925 \r
926   if(r.right <rRatioRect.right)\r
927    {\r
928     rC.left=0;\r
929     rC.top=0;\r
930     rC.right=r.left;\r
931     rC.bottom=iResY;\r
932     glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();\r
933     glClear(uiBufferBits); glError();\r
934     rC.left=iResX-rC.right;\r
935     glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();\r
936     \r
937     glClear(uiBufferBits); glError();\r
938    }\r
939 \r
940   if(r.bottom <rRatioRect.bottom)\r
941    {\r
942     rC.left=0;\r
943     rC.top=0;\r
944     rC.right=iResX;\r
945     rC.bottom=r.top;\r
946     glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();\r
947 \r
948     glClear(uiBufferBits); glError();\r
949     rC.top=iResY-rC.bottom;\r
950     glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();\r
951     glClear(uiBufferBits); glError();\r
952    }\r
953   \r
954   bSetClip=TRUE;\r
955   bDisplayNotSet=TRUE;\r
956  }\r
957 \r
958 rRatioRect=r;\r
959 #else\r
960  // pcsx-rearmed hack\r
961  if (rearmed_get_layer_pos != NULL)\r
962    rearmed_get_layer_pos(&rRatioRect.left, &rRatioRect.top, &rRatioRect.right, &rRatioRect.bottom);\r
963 #endif\r
964 \r
965 glViewport(rRatioRect.left,\r
966            iResY-(rRatioRect.top+rRatioRect.bottom),\r
967            rRatioRect.right,\r
968            rRatioRect.bottom); glError();              // init viewport\r
969 }\r
970 \r
971 ////////////////////////////////////////////////////////////////////////\r
972 // big ass check, if an ogl swap buffer is needed\r
973 ////////////////////////////////////////////////////////////////////////\r
974 \r
975 void updateDisplayIfChanged(void)\r
976 {\r
977 BOOL bUp;\r
978 \r
979 if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) && \r
980     (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))\r
981  {\r
982   if((PSXDisplay.RGB24      == PSXDisplay.RGB24New) && \r
983      (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) \r
984      return;                                          // nothing has changed? fine, no swap buffer needed\r
985  }\r
986 else                                                  // some res change?\r
987  {\r
988   glLoadIdentity(); glError();\r
989   glOrtho(0,PSXDisplay.DisplayModeNew.x,              // -> new psx resolution\r
990             PSXDisplay.DisplayModeNew.y, 0, -1, 1); glError();\r
991   if(bKeepRatio) SetAspectRatio();\r
992  }\r
993 \r
994 bDisplayNotSet = TRUE;                                // re-calc offsets/display area\r
995 \r
996 bUp=FALSE;\r
997 if(PSXDisplay.RGB24!=PSXDisplay.RGB24New)             // clean up textures, if rgb mode change (usually mdec on/off)\r
998  {\r
999   PreviousPSXDisplay.RGB24=0;                         // no full 24 frame uploaded yet\r
1000   ResetTextureArea(FALSE);\r
1001   bUp=TRUE;\r
1002  }\r
1003 \r
1004 PSXDisplay.RGB24         = PSXDisplay.RGB24New;       // get new infos\r
1005 PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;\r
1006 PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;\r
1007 PSXDisplay.Interlaced    = PSXDisplay.InterlacedNew;\r
1008    \r
1009 PSXDisplay.DisplayEnd.x=                              // calc new ends\r
1010  PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1011 PSXDisplay.DisplayEnd.y=\r
1012  PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1013 PreviousPSXDisplay.DisplayEnd.x=\r
1014  PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1015 PreviousPSXDisplay.DisplayEnd.y=\r
1016  PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1017 \r
1018 ChangeDispOffsetsX();\r
1019 \r
1020 if(iFrameLimit==2) SetAutoFrameCap();                 // set new fps limit vals (depends on interlace)\r
1021 \r
1022 if(bUp) updateDisplay();                              // yeah, real update (swap buffer)\r
1023 }\r
1024 \r
1025 ////////////////////////////////////////////////////////////////////////\r
1026 // window mode <-> fullscreen mode (windows)\r
1027 ////////////////////////////////////////////////////////////////////////\r
1028 \r
1029 \r
1030 ////////////////////////////////////////////////////////////////////////\r
1031 // swap update check (called by psx vsync function)\r
1032 ////////////////////////////////////////////////////////////////////////\r
1033 \r
1034 BOOL bSwapCheck(void)\r
1035 {\r
1036 static int iPosCheck=0;\r
1037 static PSXPoint_t pO;\r
1038 static PSXPoint_t pD;\r
1039 static int iDoAgain=0;\r
1040 \r
1041 if(PSXDisplay.DisplayPosition.x==pO.x &&\r
1042    PSXDisplay.DisplayPosition.y==pO.y &&\r
1043    PSXDisplay.DisplayEnd.x==pD.x &&\r
1044    PSXDisplay.DisplayEnd.y==pD.y)\r
1045      iPosCheck++;\r
1046 else iPosCheck=0;\r
1047 \r
1048 pO=PSXDisplay.DisplayPosition;\r
1049 pD=PSXDisplay.DisplayEnd;\r
1050 \r
1051 if(iPosCheck<=4) return FALSE;\r
1052 \r
1053 iPosCheck=4;\r
1054 \r
1055 if(PSXDisplay.Interlaced) return FALSE;\r
1056 \r
1057 if (bNeedInterlaceUpdate||\r
1058     bNeedRGB24Update ||\r
1059     bNeedUploadAfter|| \r
1060     bNeedUploadTest || \r
1061     iDoAgain\r
1062    )\r
1063  {\r
1064   iDoAgain=0;\r
1065   if(bNeedUploadAfter) \r
1066    iDoAgain=1;\r
1067   if(bNeedUploadTest && PSXDisplay.InterlacedTest)\r
1068    iDoAgain=1;\r
1069 \r
1070   bDisplayNotSet = TRUE;\r
1071   updateDisplay();\r
1072 \r
1073   PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x;\r
1074   PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y;\r
1075   PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x;\r
1076   PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y;\r
1077   pO=PSXDisplay.DisplayPosition;\r
1078   pD=PSXDisplay.DisplayEnd;\r
1079 \r
1080   return TRUE;\r
1081  }\r
1082 \r
1083 return FALSE;\r
1084\r
1085 ////////////////////////////////////////////////////////////////////////\r
1086 // gun cursor func: player=0-7, x=0-511, y=0-255\r
1087 ////////////////////////////////////////////////////////////////////////\r
1088 \r
1089 ////////////////////////////////////////////////////////////////////////\r
1090 // update lace is called every VSync. Basically we limit frame rate \r
1091 // here, and in interlaced mode we swap ogl display buffers.\r
1092 ////////////////////////////////////////////////////////////////////////\r
1093 \r
1094 static unsigned short usFirstPos=2;\r
1095 \r
1096 void CALLBACK GPUupdateLace(void)\r
1097 {\r
1098 if(!(dwActFixes&0x1000))                               \r
1099  STATUSREG^=0x80000000;                               // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus)\r
1100 \r
1101 if(!(dwActFixes&128))                                 // normal frame limit func\r
1102  CheckFrameRate();\r
1103 \r
1104 if(iOffscreenDrawing==4)                              // special check if high offscreen drawing is on\r
1105  {\r
1106   if(bSwapCheck()) return;\r
1107  }\r
1108 \r
1109 if(PSXDisplay.Interlaced)                             // interlaced mode?\r
1110  {\r
1111   if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)\r
1112    {\r
1113     updateDisplay();                                  // -> swap buffers (new frame)\r
1114    }\r
1115  }\r
1116 else if(bRenderFrontBuffer)                           // no interlace mode? and some stuff in front has changed?\r
1117  {\r
1118   updateFrontDisplay();                               // -> update front buffer\r
1119  }\r
1120 else if(usFirstPos==1)                                // initial updates (after startup)\r
1121  {\r
1122   updateDisplay();\r
1123  }\r
1124 \r
1125 }\r
1126 \r
1127 ////////////////////////////////////////////////////////////////////////\r
1128 // process read request from GPU status register\r
1129 ////////////////////////////////////////////////////////////////////////\r
1130 \r
1131 unsigned long CALLBACK GPUreadStatus(void)\r
1132 {\r
1133 if(dwActFixes&0x1000)                                 // CC game fix\r
1134  {\r
1135   static int iNumRead=0;\r
1136   if((iNumRead++)==2)\r
1137    {\r
1138     iNumRead=0;\r
1139     STATUSREG^=0x80000000;                            // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross)\r
1140    }\r
1141  }\r
1142 \r
1143 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
1144  {\r
1145   iFakePrimBusy--;\r
1146 \r
1147   if(iFakePrimBusy&1)                                 // we do a busy-idle-busy-idle sequence after/while drawing prims\r
1148    {\r
1149     GPUIsBusy;\r
1150     GPUIsNotReadyForCommands;\r
1151    }\r
1152   else\r
1153    {\r
1154     GPUIsIdle;\r
1155     GPUIsReadyForCommands;\r
1156    }\r
1157  }\r
1158 \r
1159 return STATUSREG;\r
1160 }\r
1161 \r
1162 ////////////////////////////////////////////////////////////////////////\r
1163 // processes data send to GPU status register\r
1164 // these are always single packet commands.\r
1165 ////////////////////////////////////////////////////////////////////////\r
1166 \r
1167 void CALLBACK GPUwriteStatus(unsigned long gdata)\r
1168 {\r
1169 unsigned long lCommand=(gdata>>24)&0xff;\r
1170 \r
1171 if(bIsFirstFrame) GLinitialize();                     // real ogl startup (needed by some emus)\r
1172 \r
1173 ulStatusControl[lCommand]=gdata;\r
1174 \r
1175 switch(lCommand)\r
1176  {\r
1177   //--------------------------------------------------//\r
1178   // reset gpu\r
1179   case 0x00:\r
1180    memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));\r
1181    lGPUstatusRet=0x14802000;\r
1182    PSXDisplay.Disabled=1;\r
1183    iDataWriteMode=iDataReadMode=DR_NORMAL;\r
1184    PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;\r
1185    drawX=drawY=0;drawW=drawH=0;\r
1186    sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0;\r
1187    usMirror=0;\r
1188    GlobalTextAddrX=0;GlobalTextAddrY=0;\r
1189    GlobalTextTP=0;GlobalTextABR=0;\r
1190    PSXDisplay.RGB24=FALSE;\r
1191    PSXDisplay.Interlaced=FALSE;\r
1192    bUsingTWin = FALSE;\r
1193    return;\r
1194 \r
1195   // dis/enable display\r
1196   case 0x03:  \r
1197    PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;\r
1198    PSXDisplay.Disabled = (gdata & 1);\r
1199 \r
1200    if(PSXDisplay.Disabled) \r
1201         STATUSREG|=GPUSTATUS_DISPLAYDISABLED;\r
1202    else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED;\r
1203 \r
1204    if (iOffscreenDrawing==4 &&\r
1205         PreviousPSXDisplay.Disabled && \r
1206        !(PSXDisplay.Disabled))\r
1207     {\r
1208 \r
1209      if(!PSXDisplay.RGB24)\r
1210       {\r
1211        PrepareFullScreenUpload(TRUE);\r
1212        UploadScreen(TRUE); \r
1213        updateDisplay();\r
1214       }\r
1215     }\r
1216 \r
1217    return;\r
1218 \r
1219   // setting transfer mode\r
1220   case 0x04:\r
1221    gdata &= 0x03;                                     // only want the lower two bits\r
1222 \r
1223    iDataWriteMode=iDataReadMode=DR_NORMAL;\r
1224    if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER;\r
1225    if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER;\r
1226 \r
1227    STATUSREG&=~GPUSTATUS_DMABITS;                     // clear the current settings of the DMA bits\r
1228    STATUSREG|=(gdata << 29);                          // set the DMA bits according to the received data\r
1229 \r
1230    return;\r
1231 \r
1232   // setting display position\r
1233   case 0x05: \r
1234    {\r
1235     short sx=(short)(gdata & 0x3ff);\r
1236     short sy;\r
1237 \r
1238     if(iGPUHeight==1024)\r
1239      {\r
1240       if(dwGPUVersion==2) \r
1241            sy = (short)((gdata>>12)&0x3ff);\r
1242       else sy = (short)((gdata>>10)&0x3ff);\r
1243      }\r
1244     else sy = (short)((gdata>>10)&0x3ff);             // really: 0x1ff, but we adjust it later\r
1245 \r
1246     if (sy & 0x200) \r
1247      {\r
1248       sy|=0xfc00;\r
1249       PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double;\r
1250       sy=0;\r
1251      }\r
1252     else PreviousPSXDisplay.DisplayModeNew.y=0;\r
1253 \r
1254     if(sx>1000) sx=0;\r
1255 \r
1256     if(usFirstPos)\r
1257      {\r
1258       usFirstPos--;\r
1259       if(usFirstPos)\r
1260        {\r
1261         PreviousPSXDisplay.DisplayPosition.x = sx;\r
1262         PreviousPSXDisplay.DisplayPosition.y = sy;\r
1263         PSXDisplay.DisplayPosition.x = sx;\r
1264         PSXDisplay.DisplayPosition.y = sy;\r
1265        }\r
1266      }\r
1267 \r
1268     if(dwActFixes&8) \r
1269      {\r
1270       if((!PSXDisplay.Interlaced) &&\r
1271          PreviousPSXDisplay.DisplayPosition.x == sx  &&\r
1272          PreviousPSXDisplay.DisplayPosition.y == sy)\r
1273        return;\r
1274 \r
1275       PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x;\r
1276       PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y;\r
1277       PreviousPSXDisplay.DisplayPosition.x = sx;\r
1278       PreviousPSXDisplay.DisplayPosition.y = sy;\r
1279      }\r
1280     else\r
1281      {\r
1282       if((!PSXDisplay.Interlaced) &&\r
1283          PSXDisplay.DisplayPosition.x == sx  &&\r
1284          PSXDisplay.DisplayPosition.y == sy)\r
1285        return;\r
1286       PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;\r
1287       PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;\r
1288       PSXDisplay.DisplayPosition.x = sx;\r
1289       PSXDisplay.DisplayPosition.y = sy;\r
1290      }\r
1291 \r
1292     PSXDisplay.DisplayEnd.x=\r
1293      PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1294     PSXDisplay.DisplayEnd.y=\r
1295      PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1296 \r
1297     PreviousPSXDisplay.DisplayEnd.x=\r
1298      PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;\r
1299     PreviousPSXDisplay.DisplayEnd.y=\r
1300      PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;\r
1301 \r
1302     bDisplayNotSet = TRUE;\r
1303 \r
1304     if (!(PSXDisplay.Interlaced))\r
1305      {\r
1306       updateDisplay();\r
1307      }\r
1308     else\r
1309     if(PSXDisplay.InterlacedTest && \r
1310        ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)||\r
1311         (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y)))\r
1312      PSXDisplay.InterlacedTest--;\r
1313 \r
1314     return;\r
1315    }\r
1316 \r
1317   // setting width\r
1318   case 0x06:\r
1319 \r
1320    PSXDisplay.Range.x0=gdata & 0x7ff;      //0x3ff;\r
1321    PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff;\r
1322 \r
1323    PSXDisplay.Range.x1-=PSXDisplay.Range.x0;\r
1324 \r
1325    ChangeDispOffsetsX();\r
1326 \r
1327    return;\r
1328 \r
1329   // setting height\r
1330   case 0x07:\r
1331 \r
1332    PreviousPSXDisplay.Height = PSXDisplay.Height;\r
1333 \r
1334    PSXDisplay.Range.y0=gdata & 0x3ff;\r
1335    PSXDisplay.Range.y1=(gdata>>10) & 0x3ff;\r
1336 \r
1337    PSXDisplay.Height = PSXDisplay.Range.y1 - \r
1338                        PSXDisplay.Range.y0 +\r
1339                        PreviousPSXDisplay.DisplayModeNew.y;\r
1340 \r
1341    if (PreviousPSXDisplay.Height != PSXDisplay.Height)\r
1342     {\r
1343      PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;\r
1344      ChangeDispOffsetsY();\r
1345      updateDisplayIfChanged();\r
1346     }\r
1347    return;\r
1348 \r
1349   // setting display infos\r
1350   case 0x08:\r
1351 \r
1352    PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];\r
1353 \r
1354    if (gdata&0x04) PSXDisplay.Double=2;\r
1355    else            PSXDisplay.Double=1;\r
1356    PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;\r
1357 \r
1358    ChangeDispOffsetsY();\r
1359  \r
1360    PSXDisplay.PAL           = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC\r
1361    PSXDisplay.RGB24New      = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor\r
1362    PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace\r
1363 \r
1364    STATUSREG&=~GPUSTATUS_WIDTHBITS;                   // clear the width bits\r
1365 \r
1366    STATUSREG|=\r
1367               (((gdata & 0x03) << 17) | \r
1368               ((gdata & 0x40) << 10));                // set the width bits\r
1369 \r
1370    PreviousPSXDisplay.InterlacedNew=FALSE;\r
1371    if (PSXDisplay.InterlacedNew)\r
1372     {\r
1373      if(!PSXDisplay.Interlaced)\r
1374       {\r
1375        PSXDisplay.InterlacedTest=2;\r
1376        PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;\r
1377        PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;\r
1378        PreviousPSXDisplay.InterlacedNew=TRUE;\r
1379       }\r
1380 \r
1381      STATUSREG|=GPUSTATUS_INTERLACED;\r
1382     }\r
1383    else \r
1384     {\r
1385      PSXDisplay.InterlacedTest=0;\r
1386      STATUSREG&=~GPUSTATUS_INTERLACED;\r
1387     }\r
1388 \r
1389    if (PSXDisplay.PAL)\r
1390         STATUSREG|=GPUSTATUS_PAL;\r
1391    else STATUSREG&=~GPUSTATUS_PAL;\r
1392 \r
1393    if (PSXDisplay.Double==2)\r
1394         STATUSREG|=GPUSTATUS_DOUBLEHEIGHT;\r
1395    else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT;\r
1396 \r
1397    if (PSXDisplay.RGB24New)\r
1398         STATUSREG|=GPUSTATUS_RGB24;\r
1399    else STATUSREG&=~GPUSTATUS_RGB24;\r
1400 \r
1401    updateDisplayIfChanged();\r
1402 \r
1403    return;\r
1404 \r
1405   //--------------------------------------------------//\r
1406   // ask about GPU version and other stuff\r
1407   case 0x10: \r
1408 \r
1409    gdata&=0xff;\r
1410 \r
1411    switch(gdata) \r
1412     {\r
1413      case 0x02:\r
1414       GPUdataRet=ulGPUInfoVals[INFO_TW];              // tw infos\r
1415       return;\r
1416      case 0x03:\r
1417       GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART];       // draw start\r
1418       return;\r
1419      case 0x04:\r
1420       GPUdataRet=ulGPUInfoVals[INFO_DRAWEND];         // draw end\r
1421       return;\r
1422      case 0x05:\r
1423      case 0x06:\r
1424       GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF];         // draw offset\r
1425       return;\r
1426      case 0x07:\r
1427       if(dwGPUVersion==2)\r
1428            GPUdataRet=0x01;\r
1429       else GPUdataRet=0x02;                           // gpu type\r
1430       return;\r
1431      case 0x08:\r
1432      case 0x0F:                                       // some bios addr?\r
1433       GPUdataRet=0xBFC03720;\r
1434       return;\r
1435     }\r
1436    return;\r
1437   //--------------------------------------------------//\r
1438  }\r
1439 }\r
1440 \r
1441 ////////////////////////////////////////////////////////////////////////\r
1442 // vram read/write helpers\r
1443 ////////////////////////////////////////////////////////////////////////\r
1444 \r
1445 BOOL bNeedWriteUpload=FALSE;\r
1446 \r
1447 __inline void FinishedVRAMWrite(void)\r
1448 {\r
1449  if(bNeedWriteUpload)\r
1450   {\r
1451    bNeedWriteUpload=FALSE;\r
1452    CheckWriteUpdate();\r
1453   }\r
1454 \r
1455  // set register to NORMAL operation\r
1456  iDataWriteMode = DR_NORMAL;\r
1457 \r
1458  // reset transfer values, to prevent mis-transfer of data\r
1459  VRAMWrite.ColsRemaining = 0;\r
1460  VRAMWrite.RowsRemaining = 0;\r
1461 }\r
1462 \r
1463 __inline void FinishedVRAMRead(void)\r
1464 {\r
1465  // set register to NORMAL operation\r
1466  iDataReadMode = DR_NORMAL;\r
1467  // reset transfer values, to prevent mis-transfer of data\r
1468  VRAMRead.x = 0;\r
1469  VRAMRead.y = 0;\r
1470  VRAMRead.Width = 0;\r
1471  VRAMRead.Height = 0;\r
1472  VRAMRead.ColsRemaining = 0;\r
1473  VRAMRead.RowsRemaining = 0;\r
1474 \r
1475  // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER\r
1476  STATUSREG&=~GPUSTATUS_READYFORVRAM;\r
1477 }\r
1478 \r
1479 ////////////////////////////////////////////////////////////////////////\r
1480 // vram read check ex (reading from card's back/frontbuffer if needed...\r
1481 // slow!)\r
1482 ////////////////////////////////////////////////////////////////////////\r
1483 \r
1484 void CheckVRamReadEx(int x, int y, int dx, int dy)\r
1485 {\r
1486  unsigned short sArea;\r
1487  int ux,uy,udx,udy,wx,wy;\r
1488  unsigned short * p1, *p2;\r
1489  float XS,YS;\r
1490  unsigned char * ps;\r
1491  unsigned char * px;\r
1492  unsigned short s,sx;\r
1493 \r
1494  if(STATUSREG&GPUSTATUS_RGB24) return;\r
1495 \r
1496  if(((dx  > PSXDisplay.DisplayPosition.x) &&\r
1497      (x   < PSXDisplay.DisplayEnd.x) &&\r
1498      (dy  > PSXDisplay.DisplayPosition.y) &&\r
1499      (y   < PSXDisplay.DisplayEnd.y)))\r
1500   sArea=0;\r
1501  else\r
1502  if((!(PSXDisplay.InterlacedTest) &&\r
1503      (dx  > PreviousPSXDisplay.DisplayPosition.x) &&\r
1504      (x   < PreviousPSXDisplay.DisplayEnd.x) &&\r
1505      (dy  > PreviousPSXDisplay.DisplayPosition.y) &&\r
1506      (y   < PreviousPSXDisplay.DisplayEnd.y)))\r
1507   sArea=1;\r
1508  else \r
1509   {\r
1510    return;\r
1511   }\r
1512 \r
1513  //////////////\r
1514 \r
1515  if(iRenderFVR)\r
1516   {\r
1517    bFullVRam=TRUE;iRenderFVR=2;return;\r
1518   }\r
1519  bFullVRam=TRUE;iRenderFVR=2;\r
1520 \r
1521  //////////////\r
1522 \r
1523  p2=0;\r
1524 \r
1525  if(sArea==0)\r
1526   {\r
1527    ux=PSXDisplay.DisplayPosition.x;\r
1528    uy=PSXDisplay.DisplayPosition.y;\r
1529    udx=PSXDisplay.DisplayEnd.x-ux;\r
1530    udy=PSXDisplay.DisplayEnd.y-uy;\r
1531    if((PreviousPSXDisplay.DisplayEnd.x-\r
1532        PreviousPSXDisplay.DisplayPosition.x)==udx &&\r
1533       (PreviousPSXDisplay.DisplayEnd.y-\r
1534        PreviousPSXDisplay.DisplayPosition.y)==udy)\r
1535     p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) + \r
1536         PreviousPSXDisplay.DisplayPosition.x);\r
1537   }\r
1538  else\r
1539   {\r
1540    ux=PreviousPSXDisplay.DisplayPosition.x;\r
1541    uy=PreviousPSXDisplay.DisplayPosition.y;\r
1542    udx=PreviousPSXDisplay.DisplayEnd.x-ux;\r
1543    udy=PreviousPSXDisplay.DisplayEnd.y-uy;\r
1544    if((PSXDisplay.DisplayEnd.x-\r
1545        PSXDisplay.DisplayPosition.x)==udx &&\r
1546       (PSXDisplay.DisplayEnd.y-\r
1547        PSXDisplay.DisplayPosition.y)==udy)\r
1548     p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) + \r
1549         PSXDisplay.DisplayPosition.x);\r
1550   }\r
1551 \r
1552  p1=(psxVuw + (1024*uy) + ux);\r
1553  if(p1==p2) p2=0;\r
1554 \r
1555  x=0;y=0;\r
1556  wx=dx=udx;wy=dy=udy;\r
1557 \r
1558  if(udx<=0) return;\r
1559  if(udy<=0) return;\r
1560  if(dx<=0)  return;\r
1561  if(dy<=0)  return;\r
1562  if(wx<=0)  return;\r
1563  if(wy<=0)  return;\r
1564 \r
1565  XS=(float)rRatioRect.right/(float)wx;\r
1566  YS=(float)rRatioRect.bottom/(float)wy;\r
1567 \r
1568  dx=(int)((float)(dx)*XS);\r
1569  dy=(int)((float)(dy)*YS);\r
1570 \r
1571  if(dx>iResX) dx=iResX;\r
1572  if(dy>iResY) dy=iResY;\r
1573 \r
1574  if(dx<=0) return;\r
1575  if(dy<=0) return;\r
1576 \r
1577  // ogl y adjust\r
1578  y=iResY-y-dy;\r
1579 \r
1580  x+=rRatioRect.left;\r
1581  y-=rRatioRect.top;\r
1582 \r
1583  if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;\r
1584 \r
1585  if(!pGfxCardScreen)\r
1586   {\r
1587    glPixelStorei(GL_PACK_ALIGNMENT,1); glError();\r
1588    pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);\r
1589   }\r
1590 \r
1591  ps=pGfxCardScreen;\r
1592  \r
1593  //if(!sArea) glReadBuffer(GL_FRONT);\r
1594 \r
1595  glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); glError();\r
1596  //if(!sArea) glReadBuffer(GL_BACK);\r
1597 \r
1598  s=0;\r
1599 \r
1600  XS=(float)dx/(float)(udx);\r
1601  YS=(float)dy/(float)(udy+1);\r
1602     \r
1603  for(y=udy;y>0;y--)\r
1604   {\r
1605    for(x=0;x<udx;x++)\r
1606     {\r
1607      if(p1>=psxVuw && p1<psxVuw_eom)\r
1608       {\r
1609        px=ps+(3*((int)((float)x * XS))+\r
1610              (3*dx)*((int)((float)y*YS)));\r
1611        sx=(*px)>>3;px++;\r
1612        s=sx;\r
1613        sx=(*px)>>3;px++;\r
1614        s|=sx<<5;\r
1615        sx=(*px)>>3;\r
1616        s|=sx<<10;\r
1617        s&=~0x8000;\r
1618        *p1=s;\r
1619       }\r
1620      if(p2>=psxVuw && p2<psxVuw_eom) *p2=s;\r
1621 \r
1622      p1++;\r
1623      if(p2) p2++;\r
1624     }\r
1625 \r
1626    p1 += 1024 - udx;\r
1627    if(p2) p2 += 1024 - udx;\r
1628   }\r
1629 }\r
1630 \r
1631 ////////////////////////////////////////////////////////////////////////\r
1632 // vram read check (reading from card's back/frontbuffer if needed... \r
1633 // slow!)\r
1634 ////////////////////////////////////////////////////////////////////////\r
1635 \r
1636 void CheckVRamRead(int x, int y, int dx, int dy, bool bFront)\r
1637 {\r
1638  unsigned short sArea;unsigned short * p;\r
1639  int ux,uy,udx,udy,wx,wy;float XS,YS;\r
1640  unsigned char * ps, * px;\r
1641  unsigned short s=0,sx;\r
1642 \r
1643  if(STATUSREG&GPUSTATUS_RGB24) return;\r
1644 \r
1645  if(((dx  > PSXDisplay.DisplayPosition.x) &&\r
1646      (x   < PSXDisplay.DisplayEnd.x) &&\r
1647      (dy  > PSXDisplay.DisplayPosition.y) &&\r
1648      (y   < PSXDisplay.DisplayEnd.y)))\r
1649   sArea=0;\r
1650  else\r
1651  if((!(PSXDisplay.InterlacedTest) &&\r
1652      (dx  > PreviousPSXDisplay.DisplayPosition.x) &&\r
1653      (x   < PreviousPSXDisplay.DisplayEnd.x) &&\r
1654      (dy  > PreviousPSXDisplay.DisplayPosition.y) &&\r
1655      (y   < PreviousPSXDisplay.DisplayEnd.y)))\r
1656   sArea=1;\r
1657  else \r
1658   {\r
1659    return;\r
1660   }\r
1661 \r
1662  if(dwActFixes&0x40)\r
1663   {\r
1664    if(iRenderFVR)\r
1665     {\r
1666      bFullVRam=TRUE;iRenderFVR=2;return;\r
1667     }\r
1668    bFullVRam=TRUE;iRenderFVR=2;\r
1669   }\r
1670 \r
1671  ux=x;uy=y;udx=dx;udy=dy;\r
1672 \r
1673  if(sArea==0)\r
1674   {\r
1675    x -=PSXDisplay.DisplayPosition.x;\r
1676    dx-=PSXDisplay.DisplayPosition.x;\r
1677    y -=PSXDisplay.DisplayPosition.y;\r
1678    dy-=PSXDisplay.DisplayPosition.y;\r
1679    wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x;\r
1680    wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y;\r
1681   }\r
1682  else\r
1683   {\r
1684    x -=PreviousPSXDisplay.DisplayPosition.x;\r
1685    dx-=PreviousPSXDisplay.DisplayPosition.x;\r
1686    y -=PreviousPSXDisplay.DisplayPosition.y;\r
1687    dy-=PreviousPSXDisplay.DisplayPosition.y;\r
1688    wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x;\r
1689    wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y;\r
1690   }\r
1691  if(x<0) {ux-=x;x=0;}\r
1692  if(y<0) {uy-=y;y=0;}\r
1693  if(dx>wx) {udx-=(dx-wx);dx=wx;}\r
1694  if(dy>wy) {udy-=(dy-wy);dy=wy;}\r
1695  udx-=ux;\r
1696  udy-=uy;\r
1697   \r
1698  p=(psxVuw + (1024*uy) + ux);\r
1699 \r
1700  if(udx<=0) return;\r
1701  if(udy<=0) return;\r
1702  if(dx<=0)  return;\r
1703  if(dy<=0)  return;\r
1704  if(wx<=0)  return;\r
1705  if(wy<=0)  return;\r
1706 \r
1707  XS=(float)rRatioRect.right/(float)wx;\r
1708  YS=(float)rRatioRect.bottom/(float)wy;\r
1709 \r
1710  dx=(int)((float)(dx)*XS);\r
1711  dy=(int)((float)(dy)*YS);\r
1712  x=(int)((float)x*XS);\r
1713  y=(int)((float)y*YS);\r
1714 \r
1715  dx-=x;\r
1716  dy-=y;\r
1717 \r
1718  if(dx>iResX) dx=iResX;\r
1719  if(dy>iResY) dy=iResY;\r
1720 \r
1721  if(dx<=0) return;\r
1722  if(dy<=0) return;\r
1723 \r
1724  // ogl y adjust\r
1725  y=iResY-y-dy;\r
1726 \r
1727  x+=rRatioRect.left;\r
1728  y-=rRatioRect.top;\r
1729 \r
1730  if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;\r
1731 \r
1732  if(!pGfxCardScreen)\r
1733   {\r
1734    glPixelStorei(GL_PACK_ALIGNMENT,1); glError();\r
1735    pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);\r
1736   }\r
1737 \r
1738  ps=pGfxCardScreen;\r
1739  \r
1740 // if(bFront) glReadBuffer(GL_FRONT);\r
1741 \r
1742  glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); glError(); glError();\r
1743 // if(bFront) glReadBuffer(GL_BACK);\r
1744 \r
1745  XS=(float)dx/(float)(udx);\r
1746  YS=(float)dy/(float)(udy+1);\r
1747     \r
1748  for(y=udy;y>0;y--)\r
1749   {\r
1750    for(x=0;x<udx;x++)\r
1751     {\r
1752      if(p>=psxVuw && p<psxVuw_eom)\r
1753       {\r
1754        px=ps+(3*((int)((float)x * XS))+\r
1755              (3*dx)*((int)((float)y*YS)));\r
1756        sx=(*px)>>3;px++;\r
1757        s=sx;\r
1758        sx=(*px)>>3;px++;\r
1759        s|=sx<<5;\r
1760        sx=(*px)>>3;\r
1761        s|=sx<<10;\r
1762        s&=~0x8000;\r
1763        *p=s;\r
1764       }\r
1765      p++;\r
1766     }\r
1767    p += 1024 - udx;\r
1768   }\r
1769 }\r
1770 \r
1771 ////////////////////////////////////////////////////////////////////////\r
1772 // core read from vram\r
1773 ////////////////////////////////////////////////////////////////////////\r
1774 \r
1775 void CALLBACK GPUreadDataMem(unsigned long * pMem, int iSize)\r
1776 {\r
1777 int i;\r
1778 \r
1779 if(iDataReadMode!=DR_VRAMTRANSFER) return;\r
1780 \r
1781 GPUIsBusy;\r
1782 \r
1783 // adjust read ptr, if necessary\r
1784 while(VRAMRead.ImagePtr>=psxVuw_eom)\r
1785  VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1786 while(VRAMRead.ImagePtr<psxVuw)\r
1787  VRAMRead.ImagePtr+=iGPUHeight*1024;\r
1788 \r
1789 if((iFrameReadType&1 && iSize>1) &&\r
1790    !(iDrawnSomething==2 &&\r
1791      VRAMRead.x      == VRAMWrite.x     &&\r
1792      VRAMRead.y      == VRAMWrite.y     &&\r
1793      VRAMRead.Width  == VRAMWrite.Width &&\r
1794      VRAMRead.Height == VRAMWrite.Height))\r
1795  CheckVRamRead(VRAMRead.x,VRAMRead.y,\r
1796                VRAMRead.x+VRAMRead.RowsRemaining,\r
1797                VRAMRead.y+VRAMRead.ColsRemaining,\r
1798                TRUE);\r
1799 \r
1800 for(i=0;i<iSize;i++)\r
1801  {\r
1802   // do 2 seperate 16bit reads for compatibility (wrap issues)\r
1803   if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))\r
1804    {\r
1805     // lower 16 bit\r
1806     GPUdataRet=(unsigned long)*VRAMRead.ImagePtr;\r
1807 \r
1808     VRAMRead.ImagePtr++;\r
1809     if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1810     VRAMRead.RowsRemaining --;\r
1811 \r
1812     if(VRAMRead.RowsRemaining<=0)\r
1813      {\r
1814       VRAMRead.RowsRemaining = VRAMRead.Width;\r
1815       VRAMRead.ColsRemaining--;\r
1816       VRAMRead.ImagePtr += 1024 - VRAMRead.Width;\r
1817       if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1818      }\r
1819 \r
1820     // higher 16 bit (always, even if it's an odd width)\r
1821     GPUdataRet|=(unsigned long)(*VRAMRead.ImagePtr)<<16;\r
1822     *pMem++=GPUdataRet;\r
1823 \r
1824     if(VRAMRead.ColsRemaining <= 0)\r
1825      {FinishedVRAMRead();goto ENDREAD;}\r
1826 \r
1827     VRAMRead.ImagePtr++;\r
1828     if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1829     VRAMRead.RowsRemaining--;\r
1830     if(VRAMRead.RowsRemaining<=0)\r
1831      {\r
1832       VRAMRead.RowsRemaining = VRAMRead.Width;\r
1833       VRAMRead.ColsRemaining--;\r
1834       VRAMRead.ImagePtr += 1024 - VRAMRead.Width;\r
1835       if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;\r
1836      }\r
1837     if(VRAMRead.ColsRemaining <= 0)\r
1838      {FinishedVRAMRead();goto ENDREAD;}\r
1839    }\r
1840   else {FinishedVRAMRead();goto ENDREAD;}\r
1841  }\r
1842 \r
1843 ENDREAD:\r
1844 GPUIsIdle;\r
1845 }\r
1846 \r
1847 unsigned long CALLBACK GPUreadData(void)\r
1848 {\r
1849  unsigned long l;\r
1850  GPUreadDataMem(&l,1);\r
1851  return GPUdataRet;\r
1852 }\r
1853 \r
1854 ////////////////////////////////////////////////////////////////////////\r
1855 // helper table to know how much data is used by drawing commands\r
1856 ////////////////////////////////////////////////////////////////////////\r
1857 \r
1858 const unsigned char primTableCX[256] =\r
1859 {\r
1860     // 00\r
1861     0,0,3,0,0,0,0,0,\r
1862     // 08\r
1863     0,0,0,0,0,0,0,0,\r
1864     // 10\r
1865     0,0,0,0,0,0,0,0,\r
1866     // 18\r
1867     0,0,0,0,0,0,0,0,\r
1868     // 20\r
1869     4,4,4,4,7,7,7,7,\r
1870     // 28\r
1871     5,5,5,5,9,9,9,9,\r
1872     // 30\r
1873     6,6,6,6,9,9,9,9,\r
1874     // 38\r
1875     8,8,8,8,12,12,12,12,\r
1876     // 40\r
1877     3,3,3,3,0,0,0,0,\r
1878     // 48\r
1879 //    5,5,5,5,6,6,6,6,      //FLINE\r
1880     254,254,254,254,254,254,254,254,\r
1881     // 50\r
1882     4,4,4,4,0,0,0,0,\r
1883     // 58\r
1884 //    7,7,7,7,9,9,9,9,    //    LINEG3    LINEG4\r
1885     255,255,255,255,255,255,255,255,\r
1886     // 60\r
1887     3,3,3,3,4,4,4,4,    //    TILE    SPRT\r
1888     // 68\r
1889     2,2,2,2,3,3,3,3,    //    TILE1\r
1890     // 70\r
1891     2,2,2,2,3,3,3,3,\r
1892     // 78\r
1893     2,2,2,2,3,3,3,3,\r
1894     // 80\r
1895     4,0,0,0,0,0,0,0,\r
1896     // 88\r
1897     0,0,0,0,0,0,0,0,\r
1898     // 90\r
1899     0,0,0,0,0,0,0,0,\r
1900     // 98\r
1901     0,0,0,0,0,0,0,0,\r
1902     // a0\r
1903     3,0,0,0,0,0,0,0,\r
1904     // a8\r
1905     0,0,0,0,0,0,0,0,\r
1906     // b0\r
1907     0,0,0,0,0,0,0,0,\r
1908     // b8\r
1909     0,0,0,0,0,0,0,0,\r
1910     // c0\r
1911     3,0,0,0,0,0,0,0,\r
1912     // c8\r
1913     0,0,0,0,0,0,0,0,\r
1914     // d0\r
1915     0,0,0,0,0,0,0,0,\r
1916     // d8\r
1917     0,0,0,0,0,0,0,0,\r
1918     // e0\r
1919     0,1,1,1,1,1,1,0,\r
1920     // e8\r
1921     0,0,0,0,0,0,0,0,\r
1922     // f0\r
1923     0,0,0,0,0,0,0,0,\r
1924     // f8\r
1925     0,0,0,0,0,0,0,0\r
1926 };\r
1927 \r
1928 ////////////////////////////////////////////////////////////////////////\r
1929 // processes data send to GPU data register\r
1930 ////////////////////////////////////////////////////////////////////////\r
1931 \r
1932 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)\r
1933 {\r
1934 unsigned char command;\r
1935 unsigned long gdata=0;\r
1936 int i=0;\r
1937 GPUIsBusy;\r
1938 GPUIsNotReadyForCommands;\r
1939 \r
1940 STARTVRAM:\r
1941 \r
1942 if(iDataWriteMode==DR_VRAMTRANSFER)\r
1943  {\r
1944   // make sure we are in vram\r
1945   while(VRAMWrite.ImagePtr>=psxVuw_eom)\r
1946    VRAMWrite.ImagePtr-=iGPUHeight*1024;\r
1947   while(VRAMWrite.ImagePtr<psxVuw)\r
1948    VRAMWrite.ImagePtr+=iGPUHeight*1024;\r
1949 \r
1950   // now do the loop\r
1951   while(VRAMWrite.ColsRemaining>0)\r
1952    {\r
1953     while(VRAMWrite.RowsRemaining>0)\r
1954      {\r
1955       if(i>=iSize) {goto ENDVRAM;}\r
1956       i++;\r
1957 \r
1958       gdata=*pMem++;\r
1959 \r
1960       *VRAMWrite.ImagePtr++ = (unsigned short)gdata;\r
1961       if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;\r
1962       VRAMWrite.RowsRemaining --;\r
1963 \r
1964       if(VRAMWrite.RowsRemaining <= 0)\r
1965        {\r
1966         VRAMWrite.ColsRemaining--;\r
1967         if (VRAMWrite.ColsRemaining <= 0)             // last pixel is odd width\r
1968          {\r
1969           gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16);\r
1970           FinishedVRAMWrite();\r
1971           goto ENDVRAM;\r
1972          }\r
1973         VRAMWrite.RowsRemaining = VRAMWrite.Width;\r
1974         VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;\r
1975        }\r
1976 \r
1977       *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16);\r
1978       if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;\r
1979       VRAMWrite.RowsRemaining --;\r
1980      }\r
1981 \r
1982     VRAMWrite.RowsRemaining = VRAMWrite.Width;\r
1983     VRAMWrite.ColsRemaining--;\r
1984     VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;\r
1985    }\r
1986 \r
1987   FinishedVRAMWrite();\r
1988  }\r
1989 \r
1990 ENDVRAM:\r
1991 \r
1992 if(iDataWriteMode==DR_NORMAL)\r
1993  {\r
1994   void (* *primFunc)(unsigned char *);\r
1995   if(bSkipNextFrame) primFunc=primTableSkip;\r
1996   else               primFunc=primTableJ;\r
1997 \r
1998   for(;i<iSize;)\r
1999    {\r
2000     if(iDataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;\r
2001 \r
2002     gdata=*pMem++;i++;\r
2003 \r
2004     if(gpuDataC == 0)\r
2005      {\r
2006       command = (unsigned char)((gdata>>24) & 0xff);\r
2007 \r
2008       if(primTableCX[command])\r
2009        {\r
2010         gpuDataC = primTableCX[command];\r
2011         gpuCommand = command;\r
2012         gpuDataM[0] = gdata;\r
2013         gpuDataP = 1;\r
2014        }\r
2015       else continue;\r
2016      }\r
2017     else\r
2018      {\r
2019       gpuDataM[gpuDataP] = gdata;\r
2020       if(gpuDataC>128)\r
2021        {\r
2022         if((gpuDataC==254 && gpuDataP>=3) ||\r
2023            (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))\r
2024          {\r
2025           if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)\r
2026            gpuDataP=gpuDataC-1;\r
2027          }\r
2028        }\r
2029       gpuDataP++;\r
2030      }\r
2031 \r
2032     if(gpuDataP == gpuDataC)\r
2033      {\r
2034       gpuDataC=gpuDataP=0;\r
2035       primFunc[gpuCommand]((unsigned char *)gpuDataM);\r
2036 \r
2037       if(dwEmuFixes&0x0001 || dwActFixes&0x20000)     // hack for emulating "gpu busy" in some games\r
2038        iFakePrimBusy=4;\r
2039      }\r
2040    } \r
2041  }\r
2042 \r
2043 GPUdataRet=gdata;\r
2044 \r
2045 GPUIsReadyForCommands;\r
2046 GPUIsIdle;                \r
2047 }\r
2048 \r
2049 ////////////////////////////////////////////////////////////////////////\r
2050 \r
2051 void CALLBACK GPUwriteData(unsigned long gdata)\r
2052 {\r
2053  GPUwriteDataMem(&gdata,1);\r
2054 }\r
2055 \r
2056 ////////////////////////////////////////////////////////////////////////\r
2057 // this function will be removed soon (or 'soonish') (or never)\r
2058 ////////////////////////////////////////////////////////////////////////\r
2059 \r
2060 void CALLBACK GPUsetMode(unsigned int gdata)\r
2061 {\r
2062  // ignore old psemu setmode:\r
2063 \r
2064  // imageTransfer = gdata;\r
2065  // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;\r
2066  // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;\r
2067 }\r
2068 \r
2069 // and this function will be removed soon as well, hehehe...\r
2070 long CALLBACK GPUgetMode(void)\r
2071 {\r
2072  // ignore old psemu setmode\r
2073  // return imageTransfer;\r
2074 \r
2075 long iT=0;\r
2076 \r
2077 if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1;\r
2078 if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2;\r
2079 \r
2080 return iT;\r
2081 }\r
2082 \r
2083 ////////////////////////////////////////////////////////////////////////\r
2084 // call config dlg (Windows + Linux)\r
2085 ////////////////////////////////////////////////////////////////////////\r
2086 \r
2087 #ifndef _WINDOWS\r
2088 \r
2089 /*#include <unistd.h>\r
2090 \r
2091 void StartCfgTool(char * pCmdLine)                     // linux: start external cfg tool\r
2092 {\r
2093  FILE * cf;char filename[255],t[255];\r
2094 \r
2095  strcpy(filename,"cfg/cfgPeopsMesaGL");                 // look in cfg sub folder first\r
2096  cf=fopen(filename,"rb");\r
2097  if(cf!=NULL)\r
2098   {\r
2099    fclose(cf);\r
2100    getcwd(t,255);\r
2101    chdir("cfg");\r
2102    sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);\r
2103    system(filename);\r
2104    chdir(t);\r
2105   }\r
2106  else\r
2107   {\r
2108    strcpy(filename,"cfgPeopsMesaGL");                   // look in current folder\r
2109    cf=fopen(filename,"rb");\r
2110    if(cf!=NULL)\r
2111     {\r
2112      fclose(cf);\r
2113      sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);\r
2114      system(filename);\r
2115     }\r
2116    else\r
2117     {\r
2118      sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder\r
2119      cf=fopen(filename,"rb");\r
2120      if(cf!=NULL)\r
2121       {\r
2122        fclose(cf);\r
2123        getcwd(t,255);\r
2124        chdir(getenv("HOME"));\r
2125        sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);\r
2126        system(filename);\r
2127        chdir(t);\r
2128       }\r
2129      else printf("cfgPeopsMesaGL not found!\n");\r
2130     }\r
2131   }\r
2132 }\r
2133 */\r
2134 #endif\r
2135 \r
2136 \r
2137 long CALLBACK GPUconfigure(void)\r
2138 {\r
2139 \r
2140 \r
2141  return 0;\r
2142 }\r
2143 \r
2144 ////////////////////////////////////////////////////////////////////////\r
2145 // sets all kind of act fixes\r
2146 ////////////////////////////////////////////////////////////////////////\r
2147 \r
2148 void SetFixes(void)\r
2149 {\r
2150  ReInitFrameCap();\r
2151 \r
2152  if(dwActFixes & 0x2000) \r
2153       dispWidths[4]=384;\r
2154  else dispWidths[4]=368;\r
2155 }\r
2156 \r
2157 ////////////////////////////////////////////////////////////////////////\r
2158 // Pete Special: make an 'intelligent' dma chain check (<-Tekken3)\r
2159 ////////////////////////////////////////////////////////////////////////\r
2160 \r
2161 unsigned long lUsedAddr[3];\r
2162 \r
2163 __inline BOOL CheckForEndlessLoop(unsigned long laddr)\r
2164 {\r
2165 if(laddr==lUsedAddr[1]) return TRUE;\r
2166 if(laddr==lUsedAddr[2]) return TRUE;\r
2167 \r
2168 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;\r
2169 else                   lUsedAddr[2]=laddr;\r
2170 lUsedAddr[0]=laddr;\r
2171 return FALSE;\r
2172 }\r
2173 \r
2174 ////////////////////////////////////////////////////////////////////////\r
2175 // core gives a dma chain to gpu: same as the gpuwrite interface funcs\r
2176 ////////////////////////////////////////////////////////////////////////\r
2177 \r
2178 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)\r
2179 {\r
2180 unsigned long dmaMem;\r
2181 unsigned char * baseAddrB;\r
2182 short count;unsigned int DMACommandCounter = 0;\r
2183 \r
2184 if(bIsFirstFrame) GLinitialize();\r
2185 \r
2186 GPUIsBusy;\r
2187 \r
2188 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;\r
2189 \r
2190 baseAddrB = (unsigned char*) baseAddrL;\r
2191 \r
2192 do\r
2193  {\r
2194   if(iGPUHeight==512) addr&=0x1FFFFC;\r
2195 \r
2196   if(DMACommandCounter++ > 2000000) break;\r
2197   if(CheckForEndlessLoop(addr)) break;\r
2198 \r
2199   count = baseAddrB[addr+3];\r
2200 \r
2201   dmaMem=addr+4;\r
2202 \r
2203   if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);\r
2204   \r
2205   addr = baseAddrL[addr>>2]&0xffffff;\r
2206  }\r
2207 while (addr != 0xffffff);\r
2208 \r
2209 GPUIsIdle;\r
2210 \r
2211 return 0;\r
2212 }\r
2213            \r
2214 ////////////////////////////////////////////////////////////////////////\r
2215 // show about dlg\r
2216 ////////////////////////////////////////////////////////////////////////\r
2217 \r
2218 void CALLBACK GPUabout(void)\r
2219 {\r
2220 \r
2221 }\r
2222 \r
2223 ////////////////////////////////////////////////////////////////////////\r
2224 // We are ever fine ;)\r
2225 ////////////////////////////////////////////////////////////////////////\r
2226 \r
2227 long CALLBACK GPUtest(void)\r
2228 {\r
2229  // if test fails this function should return negative value for error (unable to continue)\r
2230  // and positive value for warning (can continue but output might be crappy)\r
2231 \r
2232  return 0;\r
2233 }\r
2234 \r
2235 ////////////////////////////////////////////////////////////////////////\r
2236 // save state funcs\r
2237 ////////////////////////////////////////////////////////////////////////\r
2238 \r
2239 ////////////////////////////////////////////////////////////////////////\r
2240 \r
2241 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)\r
2242 {\r
2243 if(ulGetFreezeData==2) \r
2244  {\r
2245   long lSlotNum=*((long *)pF);\r
2246   if(lSlotNum<0) return 0;\r
2247   if(lSlotNum>8) return 0;\r
2248   lSelectedSlot=lSlotNum+1;\r
2249   return 1;\r
2250  }\r
2251 \r
2252 if(!pF)                    return 0; \r
2253 if(pF->ulFreezeVersion!=1) return 0;\r
2254 \r
2255 if(ulGetFreezeData==1)\r
2256  {\r
2257   pF->ulStatus=STATUSREG;\r
2258   memcpy(pF->ulControl,ulStatusControl,256*sizeof(unsigned long));\r
2259   memcpy(pF->psxVRam,  psxVub,         1024*iGPUHeight*2);\r
2260 \r
2261   return 1;\r
2262  }\r
2263 \r
2264 if(ulGetFreezeData!=0) return 0;\r
2265 \r
2266 STATUSREG=pF->ulStatus;\r
2267 memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long));\r
2268 memcpy(psxVub,         pF->psxVRam,  1024*iGPUHeight*2);\r
2269 \r
2270 ResetTextureArea(TRUE);\r
2271 \r
2272  GPUwriteStatus(ulStatusControl[0]);\r
2273  GPUwriteStatus(ulStatusControl[1]);\r
2274  GPUwriteStatus(ulStatusControl[2]);\r
2275  GPUwriteStatus(ulStatusControl[3]);\r
2276  GPUwriteStatus(ulStatusControl[8]);\r
2277  GPUwriteStatus(ulStatusControl[6]);\r
2278  GPUwriteStatus(ulStatusControl[7]);\r
2279  GPUwriteStatus(ulStatusControl[5]);\r
2280  GPUwriteStatus(ulStatusControl[4]);\r
2281  return 1;\r
2282 }\r
2283 \r
2284 ////////////////////////////////////////////////////////////////////////\r
2285 // special "emu infos" / "emu effects" functions\r
2286 ////////////////////////////////////////////////////////////////////////\r
2287 \r
2288 //00 = black\r
2289 //01 = white\r
2290 //10 = red\r
2291 //11 = transparent\r
2292 \r
2293 unsigned char cFont[10][120]=\r
2294 {\r
2295 // 0\r
2296 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2297  0x80,0x00,0x00,0x00,0x00,0x00,\r
2298  0x80,0x00,0x00,0x00,0x00,0x00,\r
2299  0x80,0x00,0x00,0x00,0x00,0x00,\r
2300  0x80,0x00,0x00,0x00,0x00,0x00,\r
2301  0x80,0x00,0x05,0x54,0x00,0x00,\r
2302  0x80,0x00,0x14,0x05,0x00,0x00,\r
2303  0x80,0x00,0x14,0x05,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,0x05,0x54,0x00,0x00,\r
2311  0x80,0x00,0x00,0x00,0x00,0x00,\r
2312  0x80,0x00,0x00,0x00,0x00,0x00,\r
2313  0x80,0x00,0x00,0x00,0x00,0x00,\r
2314  0x80,0x00,0x00,0x00,0x00,0x00,\r
2315  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2316 },\r
2317 // 1\r
2318 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2319  0x80,0x00,0x00,0x00,0x00,0x00,\r
2320  0x80,0x00,0x00,0x00,0x00,0x00,\r
2321  0x80,0x00,0x00,0x00,0x00,0x00,\r
2322  0x80,0x00,0x00,0x00,0x00,0x00,\r
2323  0x80,0x00,0x00,0x50,0x00,0x00,\r
2324  0x80,0x00,0x05,0x50,0x00,0x00,\r
2325  0x80,0x00,0x00,0x50,0x00,0x00,\r
2326  0x80,0x00,0x00,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,0x05,0x55,0x00,0x00,\r
2333  0x80,0x00,0x00,0x00,0x00,0x00,\r
2334  0x80,0x00,0x00,0x00,0x00,0x00,\r
2335  0x80,0x00,0x00,0x00,0x00,0x00,\r
2336  0x80,0x00,0x00,0x00,0x00,0x00,\r
2337  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2338 },\r
2339 // 2\r
2340 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2341  0x80,0x00,0x00,0x00,0x00,0x00,\r
2342  0x80,0x00,0x00,0x00,0x00,0x00,\r
2343  0x80,0x00,0x00,0x00,0x00,0x00,\r
2344  0x80,0x00,0x00,0x00,0x00,0x00,\r
2345  0x80,0x00,0x05,0x54,0x00,0x00,\r
2346  0x80,0x00,0x14,0x05,0x00,0x00,\r
2347  0x80,0x00,0x00,0x05,0x00,0x00,\r
2348  0x80,0x00,0x00,0x05,0x00,0x00,\r
2349  0x80,0x00,0x00,0x14,0x00,0x00,\r
2350  0x80,0x00,0x00,0x50,0x00,0x00,\r
2351  0x80,0x00,0x01,0x40,0x00,0x00,\r
2352  0x80,0x00,0x05,0x00,0x00,0x00,\r
2353  0x80,0x00,0x14,0x00,0x00,0x00,\r
2354  0x80,0x00,0x15,0x55,0x00,0x00,\r
2355  0x80,0x00,0x00,0x00,0x00,0x00,\r
2356  0x80,0x00,0x00,0x00,0x00,0x00,\r
2357  0x80,0x00,0x00,0x00,0x00,0x00,\r
2358  0x80,0x00,0x00,0x00,0x00,0x00,\r
2359  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2360 },\r
2361 // 3\r
2362 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2363  0x80,0x00,0x00,0x00,0x00,0x00,\r
2364  0x80,0x00,0x00,0x00,0x00,0x00,\r
2365  0x80,0x00,0x00,0x00,0x00,0x00,\r
2366  0x80,0x00,0x00,0x00,0x00,0x00,\r
2367  0x80,0x00,0x05,0x54,0x00,0x00,\r
2368  0x80,0x00,0x14,0x05,0x00,0x00,\r
2369  0x80,0x00,0x00,0x05,0x00,0x00,\r
2370  0x80,0x00,0x00,0x05,0x00,0x00,\r
2371  0x80,0x00,0x01,0x54,0x00,0x00,\r
2372  0x80,0x00,0x00,0x05,0x00,0x00,\r
2373  0x80,0x00,0x00,0x05,0x00,0x00,\r
2374  0x80,0x00,0x00,0x05,0x00,0x00,\r
2375  0x80,0x00,0x14,0x05,0x00,0x00,\r
2376  0x80,0x00,0x05,0x54,0x00,0x00,\r
2377  0x80,0x00,0x00,0x00,0x00,0x00,\r
2378  0x80,0x00,0x00,0x00,0x00,0x00,\r
2379  0x80,0x00,0x00,0x00,0x00,0x00,\r
2380  0x80,0x00,0x00,0x00,0x00,0x00,\r
2381  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2382 },\r
2383 // 4\r
2384 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2385  0x80,0x00,0x00,0x00,0x00,0x00,\r
2386  0x80,0x00,0x00,0x00,0x00,0x00,\r
2387  0x80,0x00,0x00,0x00,0x00,0x00,\r
2388  0x80,0x00,0x00,0x00,0x00,0x00,\r
2389  0x80,0x00,0x00,0x14,0x00,0x00,\r
2390  0x80,0x00,0x00,0x54,0x00,0x00,\r
2391  0x80,0x00,0x01,0x54,0x00,0x00,\r
2392  0x80,0x00,0x01,0x54,0x00,0x00,\r
2393  0x80,0x00,0x05,0x14,0x00,0x00,\r
2394  0x80,0x00,0x14,0x14,0x00,0x00,\r
2395  0x80,0x00,0x15,0x55,0x00,0x00,\r
2396  0x80,0x00,0x00,0x14,0x00,0x00,\r
2397  0x80,0x00,0x00,0x14,0x00,0x00,\r
2398  0x80,0x00,0x00,0x55,0x00,0x00,\r
2399  0x80,0x00,0x00,0x00,0x00,0x00,\r
2400  0x80,0x00,0x00,0x00,0x00,0x00,\r
2401  0x80,0x00,0x00,0x00,0x00,0x00,\r
2402  0x80,0x00,0x00,0x00,0x00,0x00,\r
2403  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2404 },\r
2405 // 5\r
2406 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2407  0x80,0x00,0x00,0x00,0x00,0x00,\r
2408  0x80,0x00,0x00,0x00,0x00,0x00,\r
2409  0x80,0x00,0x00,0x00,0x00,0x00,\r
2410  0x80,0x00,0x00,0x00,0x00,0x00,\r
2411  0x80,0x00,0x15,0x55,0x00,0x00,\r
2412  0x80,0x00,0x14,0x00,0x00,0x00,\r
2413  0x80,0x00,0x14,0x00,0x00,0x00,\r
2414  0x80,0x00,0x14,0x00,0x00,0x00,\r
2415  0x80,0x00,0x15,0x54,0x00,0x00,\r
2416  0x80,0x00,0x00,0x05,0x00,0x00,\r
2417  0x80,0x00,0x00,0x05,0x00,0x00,\r
2418  0x80,0x00,0x00,0x05,0x00,0x00,\r
2419  0x80,0x00,0x14,0x05,0x00,0x00,\r
2420  0x80,0x00,0x05,0x54,0x00,0x00,\r
2421  0x80,0x00,0x00,0x00,0x00,0x00,\r
2422  0x80,0x00,0x00,0x00,0x00,0x00,\r
2423  0x80,0x00,0x00,0x00,0x00,0x00,\r
2424  0x80,0x00,0x00,0x00,0x00,0x00,\r
2425  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2426 },\r
2427 // 6\r
2428 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2429  0x80,0x00,0x00,0x00,0x00,0x00,\r
2430  0x80,0x00,0x00,0x00,0x00,0x00,\r
2431  0x80,0x00,0x00,0x00,0x00,0x00,\r
2432  0x80,0x00,0x00,0x00,0x00,0x00,\r
2433  0x80,0x00,0x01,0x54,0x00,0x00,\r
2434  0x80,0x00,0x05,0x00,0x00,0x00,\r
2435  0x80,0x00,0x14,0x00,0x00,0x00,\r
2436  0x80,0x00,0x14,0x00,0x00,0x00,\r
2437  0x80,0x00,0x15,0x54,0x00,0x00,\r
2438  0x80,0x00,0x15,0x05,0x00,0x00,\r
2439  0x80,0x00,0x14,0x05,0x00,0x00,\r
2440  0x80,0x00,0x14,0x05,0x00,0x00,\r
2441  0x80,0x00,0x14,0x05,0x00,0x00,\r
2442  0x80,0x00,0x05,0x54,0x00,0x00,\r
2443  0x80,0x00,0x00,0x00,0x00,0x00,\r
2444  0x80,0x00,0x00,0x00,0x00,0x00,\r
2445  0x80,0x00,0x00,0x00,0x00,0x00,\r
2446  0x80,0x00,0x00,0x00,0x00,0x00,\r
2447  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2448 },\r
2449 // 7\r
2450 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2451  0x80,0x00,0x00,0x00,0x00,0x00,\r
2452  0x80,0x00,0x00,0x00,0x00,0x00,\r
2453  0x80,0x00,0x00,0x00,0x00,0x00,\r
2454  0x80,0x00,0x00,0x00,0x00,0x00,\r
2455  0x80,0x00,0x15,0x55,0x00,0x00,\r
2456  0x80,0x00,0x14,0x05,0x00,0x00,\r
2457  0x80,0x00,0x00,0x14,0x00,0x00,\r
2458  0x80,0x00,0x00,0x14,0x00,0x00,\r
2459  0x80,0x00,0x00,0x50,0x00,0x00,\r
2460  0x80,0x00,0x00,0x50,0x00,0x00,\r
2461  0x80,0x00,0x01,0x40,0x00,0x00,\r
2462  0x80,0x00,0x01,0x40,0x00,0x00,\r
2463  0x80,0x00,0x05,0x00,0x00,0x00,\r
2464  0x80,0x00,0x05,0x00,0x00,0x00,\r
2465  0x80,0x00,0x00,0x00,0x00,0x00,\r
2466  0x80,0x00,0x00,0x00,0x00,0x00,\r
2467  0x80,0x00,0x00,0x00,0x00,0x00,\r
2468  0x80,0x00,0x00,0x00,0x00,0x00,\r
2469  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2470 },\r
2471 // 8\r
2472 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2473  0x80,0x00,0x00,0x00,0x00,0x00,\r
2474  0x80,0x00,0x00,0x00,0x00,0x00,\r
2475  0x80,0x00,0x00,0x00,0x00,0x00,\r
2476  0x80,0x00,0x00,0x00,0x00,0x00,\r
2477  0x80,0x00,0x05,0x54,0x00,0x00,\r
2478  0x80,0x00,0x14,0x05,0x00,0x00,\r
2479  0x80,0x00,0x14,0x05,0x00,0x00,\r
2480  0x80,0x00,0x14,0x05,0x00,0x00,\r
2481  0x80,0x00,0x05,0x54,0x00,0x00,\r
2482  0x80,0x00,0x14,0x05,0x00,0x00,\r
2483  0x80,0x00,0x14,0x05,0x00,0x00,\r
2484  0x80,0x00,0x14,0x05,0x00,0x00,\r
2485  0x80,0x00,0x14,0x05,0x00,0x00,\r
2486  0x80,0x00,0x05,0x54,0x00,0x00,\r
2487  0x80,0x00,0x00,0x00,0x00,0x00,\r
2488  0x80,0x00,0x00,0x00,0x00,0x00,\r
2489  0x80,0x00,0x00,0x00,0x00,0x00,\r
2490  0x80,0x00,0x00,0x00,0x00,0x00,\r
2491  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2492 },\r
2493 // 9\r
2494 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,\r
2495  0x80,0x00,0x00,0x00,0x00,0x00,\r
2496  0x80,0x00,0x00,0x00,0x00,0x00,\r
2497  0x80,0x00,0x00,0x00,0x00,0x00,\r
2498  0x80,0x00,0x00,0x00,0x00,0x00,\r
2499  0x80,0x00,0x05,0x54,0x00,0x00,\r
2500  0x80,0x00,0x14,0x05,0x00,0x00,\r
2501  0x80,0x00,0x14,0x05,0x00,0x00,\r
2502  0x80,0x00,0x14,0x05,0x00,0x00,\r
2503  0x80,0x00,0x14,0x15,0x00,0x00,\r
2504  0x80,0x00,0x05,0x55,0x00,0x00,\r
2505  0x80,0x00,0x00,0x05,0x00,0x00,\r
2506  0x80,0x00,0x00,0x05,0x00,0x00,\r
2507  0x80,0x00,0x00,0x14,0x00,0x00,\r
2508  0x80,0x00,0x05,0x50,0x00,0x00,\r
2509  0x80,0x00,0x00,0x00,0x00,0x00,\r
2510  0x80,0x00,0x00,0x00,0x00,0x00,\r
2511  0x80,0x00,0x00,0x00,0x00,0x00,\r
2512  0x80,0x00,0x00,0x00,0x00,0x00,\r
2513  0xaa,0xaa,0xaa,0xaa,0xaa,0xaa\r
2514 }\r
2515 };\r
2516 \r
2517 ////////////////////////////////////////////////////////////////////////\r
2518 \r
2519 void PaintPicDot(unsigned char * p,unsigned char c)\r
2520 {\r
2521  if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;}\r
2522  if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;}\r
2523  if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;}\r
2524 }\r
2525 \r
2526 ////////////////////////////////////////////////////////////////////////\r
2527 \r
2528 long CALLBACK GPUgetScreenPic(unsigned char * pMem)\r
2529 {\r
2530  float XS,YS;int x,y,v;\r
2531  unsigned char * ps, * px, * pf;\r
2532  unsigned char c;\r
2533 \r
2534  if(!pGfxCardScreen)\r
2535   {\r
2536    glPixelStorei(GL_PACK_ALIGNMENT,1); glError();\r
2537    pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);\r
2538   }\r
2539 \r
2540  ps=pGfxCardScreen;\r
2541 \r
2542 // glReadBuffer(GL_FRONT);\r
2543 \r
2544  glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps); glError();\r
2545                \r
2546 // glReadBuffer(GL_BACK);\r
2547 \r
2548  XS=(float)iResX/128;\r
2549  YS=(float)iResY/96;\r
2550  pf=pMem;\r
2551 \r
2552  for(y=96;y>0;y--)\r
2553   {\r
2554    for(x=0;x<128;x++)\r
2555     {\r
2556      px=ps+(3*((int)((float)x * XS))+\r
2557            (3*iResX)*((int)((float)y*YS)));\r
2558      *(pf+0)=*(px+2);\r
2559      *(pf+1)=*(px+1);\r
2560      *(pf+2)=*(px+0);\r
2561      pf+=3;\r
2562     }\r
2563   }\r
2564 \r
2565  /////////////////////////////////////////////////////////////////////\r
2566  // generic number/border painter\r
2567 \r
2568  pf=pMem+(103*3);\r
2569 \r
2570  for(y=0;y<20;y++)\r
2571   {\r
2572    for(x=0;x<6;x++)\r
2573     {\r
2574      c=cFont[lSelectedSlot][x+y*6];\r
2575      v=(c&0xc0)>>6;\r
2576      PaintPicDot(pf,(unsigned char)v);pf+=3;                // paint the dots into the rect\r
2577      v=(c&0x30)>>4;\r
2578      PaintPicDot(pf,(unsigned char)v);pf+=3;\r
2579      v=(c&0x0c)>>2;\r
2580      PaintPicDot(pf,(unsigned char)v);pf+=3;\r
2581      v=c&0x03;\r
2582      PaintPicDot(pf,(unsigned char)v);pf+=3;\r
2583     }\r
2584    pf+=104*3;\r
2585   }\r
2586 \r
2587  pf=pMem;\r
2588  for(x=0;x<128;x++)\r
2589   {\r
2590    *(pf+(95*128*3))=0x00;*pf++=0x00;\r
2591    *(pf+(95*128*3))=0x00;*pf++=0x00;\r
2592    *(pf+(95*128*3))=0xff;*pf++=0xff;\r
2593   }\r
2594  pf=pMem;\r
2595  for(y=0;y<96;y++)\r
2596   {\r
2597    *(pf+(127*3))=0x00;*pf++=0x00;\r
2598    *(pf+(127*3))=0x00;*pf++=0x00;\r
2599    *(pf+(127*3))=0xff;*pf++=0xff;\r
2600    pf+=127*3;\r
2601   }\r
2602 \r
2603 }\r
2604 \r
2605 ////////////////////////////////////////////////////////////////////////\r
2606 \r
2607 long CALLBACK GPUshowScreenPic(unsigned char * pMem)\r
2608 {\r
2609 // DestroyPic();\r
2610 // if(pMem==0) return;\r
2611 // CreatePic(pMem);\r
2612 }\r
2613 \r
2614 ////////////////////////////////////////////////////////////////////////\r
2615 \r
2616 void CALLBACK GPUsetfix(unsigned long dwFixBits)\r
2617 {\r
2618  dwEmuFixes=dwFixBits;\r
2619 }\r
2620 \r
2621 ////////////////////////////////////////////////////////////////////////\r
2622  \r
2623 void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig)\r
2624 {\r
2625  int iVibVal;\r
2626 \r
2627  if(PSXDisplay.DisplayModeNew.x)                       // calc min "shake pixel" from screen width\r
2628       iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x);\r
2629  else iVibVal=1;\r
2630                                                        // big rumble: 4...15 sp ; small rumble 1...3 sp\r
2631  if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig  *iVibVal)/10));\r
2632  else     iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10));\r
2633 \r
2634  srand(timeGetTime());                                 // init rand (will be used in BufferSwap)\r
2635 \r
2636  iRumbleTime=15;                                       // let the rumble last 16 buffer swaps\r
2637 }\r
2638                                                        \r
2639 ////////////////////////////////////////////////////////////////////////\r
2640 // main emu can set display infos (A/M/G/D) \r
2641 ////////////////////////////////////////////////////////////////////////\r
2642 \r
2643 void CALLBACK GPUdisplayFlags(unsigned long dwFlags)\r
2644 {\r
2645 // dwCoreFlags=dwFlags;\r
2646 }\r
2647 \r
2648 // pcsx-rearmed callbacks\r
2649 void CALLBACK GPUrearmedCallbacks(const void **cbs)\r
2650 {\r
2651  rearmed_get_layer_pos = cbs[0];\r
2652 }\r
2653 \r
2654 static void flipEGL(void)\r
2655 {\r
2656  eglSwapBuffers(display, surface);\r
2657 }\r