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