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