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