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