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