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