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