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