1 /***************************************************************************
\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
9 /***************************************************************************
\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
17 ***************************************************************************/
\r
19 //*************************************************************************//
\r
20 // History of changes:
\r
22 // 2009/03/08 - Pete
\r
23 // - generic cleanup for the Peops release
\r
25 //*************************************************************************//
\r
27 //#include "gpuStdafx.h"
\r
29 //#include <mmsystem.h>
\r
36 #include "gpuExternals.h"
\r
37 #include "gpuPlugin.h"
\r
38 #include "gpuDraw.h"
\r
39 #include "gpuTexture.h"
\r
41 #include "gpuPrim.h"
\r
43 //#include "NoPic.h"
\r
45 #include "gpuStdafx.h"
\r
47 short g_m1=255,g_m2=255,g_m3=255;
\r
48 short DrawSemiTrans=FALSE;
\r
52 short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; // global psx vertex coords
\r
53 long GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP;
\r
54 long GlobalTextREST,GlobalTextABR,GlobalTextPAGE;
\r
56 unsigned long dwGPUVersion=0;
\r
58 int iGPUHeightMask=511;
\r
62 ////////////////////////////////////////////////////////////////////////
\r
63 // memory image of the PSX vram
\r
64 ////////////////////////////////////////////////////////////////////////
\r
66 unsigned char *psxVSecure;
\r
67 unsigned char *psxVub;
\r
68 signed char *psxVsb;
\r
69 unsigned short *psxVuw;
\r
70 unsigned short *psxVuw_eom;
\r
71 signed short *psxVsw;
\r
72 unsigned long *psxVul;
\r
73 signed long *psxVsl;
\r
75 // macro for easy access to packet information
\r
76 #define GPUCOMMAND(x) ((x>>24) & 0xff)
\r
79 BOOL bNeedInterlaceUpdate=FALSE;
\r
80 BOOL bNeedRGB24Update=FALSE;
\r
81 BOOL bChangeWinMode=FALSE;
\r
83 unsigned long ulStatusControl[256];
\r
85 ////////////////////////////////////////////////////////////////////////
\r
87 ////////////////////////////////////////////////////////////////////////
\r
89 static long GPUdataRet;
\r
93 static unsigned long gpuDataM[256];
\r
94 static unsigned char gpuCommand = 0;
\r
95 static long gpuDataC = 0;
\r
96 static long gpuDataP = 0;
\r
98 VRAMLoad_t VRAMWrite;
\r
99 VRAMLoad_t VRAMRead;
\r
100 int iDataWriteMode;
\r
104 long lClearOnSwapColor;
\r
105 BOOL bSkipNextFrame = FALSE;
\r
111 // possible psx display widths
\r
112 short dispWidths[8] = {256,320,512,640,368,384,512,640};
\r
114 PSXDisplay_t PSXDisplay;
\r
115 PSXDisplay_t PreviousPSXDisplay;
\r
117 short imageX0,imageX1;
\r
118 short imageY0,imageY1;
\r
119 BOOL bDisplayNotSet = TRUE;
\r
120 GLuint uiScanLine=0;
\r
121 int iUseScanLines=0;
\r
122 long lSelectedSlot=0;
\r
123 unsigned char * pGfxCardScreen=0;
\r
127 int iNoScreenSaver=0;
\r
128 unsigned long ulGPUInfoVals[16];
\r
129 int iFakePrimBusy = 0;
\r
130 int iRumbleVal = 0;
\r
131 int iRumbleTime = 0;
\r
133 static void (*rearmed_get_layer_pos)(int *x, int *y, int *w, int *h);
\r
134 static void flipEGL(void);
\r
136 ////////////////////////////////////////////////////////////////////////
\r
137 // stuff to make this a true PDK module
\r
138 ////////////////////////////////////////////////////////////////////////
\r
140 ////////////////////////////////////////////////////////////////////////
\r
141 // snapshot funcs (saves screen to bitmap / text infos into file)
\r
142 ////////////////////////////////////////////////////////////////////////
\r
144 void ResizeWindow()
\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
152 rRatioRect.bottom);
\r
154 glScissor(0, 0, iResX, iResY); // init clipping (fullscreen)
\r
155 glEnable(GL_SCISSOR_TEST);
\r
158 glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale"
\r
160 glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack
\r
163 glMatrixMode(GL_PROJECTION); // init projection with psx resolution
\r
165 glOrtho(0,PSXDisplay.DisplayMode.x,
\r
166 PSXDisplay.DisplayMode.y, 0, -1, 1);
\r
171 char * GetConfigInfos(int hW)
\r
173 char szO[2][4]={"off","on "};
\r
175 char * pB=(char *)malloc(32767);
\r
177 if(!pB) return NULL;
\r
179 //----------------------------------------------------//
\r
186 bSetupPixelFormat(hdc);
\r
187 hglrc = wglCreateContext(hdc);
\r
188 wglMakeCurrent(hdc, hglrc);
\r
191 sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR));
\r
193 sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER));
\r
195 sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION));
\r
197 //strcat(pB,(char *)glGetString(GL_EXTENSIONS));
\r
198 //strcat(pB,"\r\n\r\n");
\r
203 wglMakeCurrent(NULL, NULL);
\r
204 wglDeleteContext(hglrc);
\r
207 //----------------------------------------------------//
\r
209 if(hW && bWindowMode)
\r
210 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize));
\r
212 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY);
\r
214 if(bWindowMode) sprintf(szTxt,"Window mode\r\n");
\r
217 sprintf(szTxt,"Fullscreen ");
\r
219 if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth);
\r
220 else sprintf(szTxt,"- NO desktop changing\r\n");
\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
227 sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]);
\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
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
245 else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType);
\r
247 sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures);
\r
251 sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]);
\r
255 /*sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize);
\r
257 sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt);
\r
258 else strcat(szTxt,"\r\n\r\n");
\r
260 //----------------------------------------------------//
\r
261 sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]);
\r
263 sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]);
\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
269 //----------------------------------------------------//
\r
270 sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing);
\r
272 sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType);
\r
273 if(!hW && iFrameTexType==2)
\r
275 if(gTexFrameName) strcat(szTxt," - texture created\r\n");
\r
276 else strcat(szTxt," - not used yet\r\n");
\r
278 else strcat(szTxt,"\r\n");
\r
280 sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType);
\r
282 // sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]);
\r
284 sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]);
\r
286 //sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]);
\r
287 //if(!hW && bAdvancedBlend)
\r
289 // if(bGLBlend) strcat(szTxt," (hardware)\r\n");
\r
290 // else strcat(szTxt," (software)\r\n");
\r
292 strcat(szTxt,"\r\n");
\r
297 strcpy(szTxt,"- Subtractive blending: ");
\r
298 // if(glBlendEquationEXTEx)
\r
300 // if(bUseMultiPass) strcat(szTxt,"supported, but not used!");
\r
301 // else strcat(szTxt,"activated");
\r
303 strcat(szTxt," NOT supported!");
\r
304 strcat(szTxt,"\r\n\r\n");
\r
306 else strcpy(szTxt,"\r\n");
\r
309 //----------------------------------------------------//
\r
310 sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]);
\r
312 if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend);
\r
313 else strcpy(szTxt,"\r\n");
\r
315 // sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]);
\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
321 sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]);
\r
323 sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]);
\r
325 sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]);
\r
327 if(!hW && iBlurBuffer)
\r
329 if(gTexBlurName) strcat(pB," - supported\r\n");
\r
330 else strcat(pB," - not supported\r\n");
\r
332 else strcat(pB,"\r\n");
\r
333 sprintf(szTxt,"- Game fixes: %s [%08lx]\r\n",szO[bUseFixes],dwCfgFixes);
\r
335 //----------------------------------------------------//
\r
339 ////////////////////////////////////////////////////////////////////////
\r
340 // save text infos to file
\r
341 ////////////////////////////////////////////////////////////////////////
\r
343 void DoTextSnapShot(int iNum)
\r
347 ////////////////////////////////////////////////////////////////////////
\r
348 // saves screen bitmap to file
\r
349 ////////////////////////////////////////////////////////////////////////
\r
351 void DoSnapShot(void)
\r
355 void CALLBACK GPUmakeSnapshot(void)
\r
357 //bSnapShot = TRUE;
\r
360 ////////////////////////////////////////////////////////////////////////
\r
361 // GPU INIT... here starts it all (first func called by emu)
\r
362 ////////////////////////////////////////////////////////////////////////
\r
364 long CALLBACK GPUinit()
\r
366 memset(ulStatusControl,0,256*sizeof(unsigned long));
\r
372 // different ways of accessing PSX VRAM
\r
374 psxVSecure=(unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security
\r
375 if(!psxVSecure) return -1;
\r
377 psxVub=psxVSecure+512*1024; // security offset into double sized psx vram!
\r
378 psxVsb=(signed char *)psxVub;
\r
379 psxVsw=(signed short *)psxVub;
\r
380 psxVsl=(signed long *)psxVub;
\r
381 psxVuw=(unsigned short *)psxVub;
\r
382 psxVul=(unsigned long *)psxVub;
\r
384 psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram
\r
386 memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024));
\r
387 memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));
\r
389 InitFrameCap(); // init frame rate stuff
\r
391 PSXDisplay.RGB24 = 0; // init vars
\r
392 PreviousPSXDisplay.RGB24= 0;
\r
393 PSXDisplay.Interlaced = 0;
\r
394 PSXDisplay.InterlacedTest=0;
\r
395 PSXDisplay.DrawOffset.x = 0;
\r
396 PSXDisplay.DrawOffset.y = 0;
\r
397 PSXDisplay.DrawArea.x0 = 0;
\r
398 PSXDisplay.DrawArea.y0 = 0;
\r
399 PSXDisplay.DrawArea.x1 = 320;
\r
400 PSXDisplay.DrawArea.y1 = 240;
\r
401 PSXDisplay.DisplayMode.x= 320;
\r
402 PSXDisplay.DisplayMode.y= 240;
\r
403 PSXDisplay.Disabled = FALSE;
\r
404 PreviousPSXDisplay.Range.x0 =0;
\r
405 PreviousPSXDisplay.Range.x1 =0;
\r
406 PreviousPSXDisplay.Range.y0 =0;
\r
407 PreviousPSXDisplay.Range.y1 =0;
\r
408 PSXDisplay.Range.x0=0;
\r
409 PSXDisplay.Range.x1=0;
\r
410 PSXDisplay.Range.y0=0;
\r
411 PSXDisplay.Range.y1=0;
\r
412 PreviousPSXDisplay.DisplayPosition.x = 1;
\r
413 PreviousPSXDisplay.DisplayPosition.y = 1;
\r
414 PSXDisplay.DisplayPosition.x = 1;
\r
415 PSXDisplay.DisplayPosition.y = 1;
\r
416 PreviousPSXDisplay.DisplayModeNew.y=0;
\r
417 PSXDisplay.Double=1;
\r
420 PSXDisplay.DisplayModeNew.x=0;
\r
421 PSXDisplay.DisplayModeNew.y=0;
\r
423 //PreviousPSXDisplay.Height = PSXDisplay.Height = 239;
\r
425 iDataWriteMode = DR_NORMAL;
\r
427 // Reset transfer values, to prevent mis-transfer of data
\r
428 memset(&VRAMWrite,0,sizeof(VRAMLoad_t));
\r
429 memset(&VRAMRead,0,sizeof(VRAMLoad_t));
\r
431 // device initialised already !
\r
432 //lGPUstatusRet = 0x74000000;
\r
434 STATUSREG = 0x14802000;
\r
436 GPUIsReadyForCommands;
\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
456 long CALLBACK GPUopen(int hwndGPU)
\r
458 iResX=800;iResY=480;
\r
464 // bAdvancedBlend=FALSE;
\r
466 // bUseLines=FALSE;
\r
467 bUseFrameLimit=FALSE;
\r
468 bUseFrameSkip=FALSE;
\r
471 iOffscreenDrawing=0;
\r
472 //bOpaquePass=FALSE;
\r
473 //bUseAntiAlias=FALSE;
\r
477 bUseFastMdec=FALSE;
\r
478 bUse15bitMdec=FALSE;
\r
481 // iUseScanLines=0;
\r
488 iTexGarbageCollection=0;
\r
490 //iHiResTextures=0;
\r
496 bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows!
\r
498 rRatioRect.left = rRatioRect.top=0;
\r
499 rRatioRect.right = iResX;
\r
500 rRatioRect.bottom = iResY;
\r
502 bDisplayNotSet = TRUE;
\r
505 SetFixes(); // setup game fixes
\r
507 InitializeTextureStore(); // init texture mem
\r
509 // lGPUstatusRet = 0x74000000;
\r
511 // with some emus, we could do the OGL init right here... oh my
\r
512 if(bIsFirstFrame) GLinitialize();
\r
517 ////////////////////////////////////////////////////////////////////////
\r
519 ////////////////////////////////////////////////////////////////////////
\r
522 long GPUclose() // LINUX CLOSE
\r
524 GLcleanup(); // close OGL
\r
526 if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory
\r
529 // osd_close_display(); // destroy display
\r
534 ////////////////////////////////////////////////////////////////////////
\r
535 // I shot the sheriff... last function called from emu
\r
536 ////////////////////////////////////////////////////////////////////////
\r
538 long CALLBACK GPUshutdown()
\r
540 if(psxVSecure) free(psxVSecure); // kill emulated vram memory
\r
546 ////////////////////////////////////////////////////////////////////////
\r
547 // paint it black: simple func to clean up optical border garbage
\r
548 ////////////////////////////////////////////////////////////////////////
\r
550 void PaintBlackBorders(void)
\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
560 glEnable(GL_ALPHA_TEST);
\r
561 glEnable(GL_SCISSOR_TEST);
\r
564 ////////////////////////////////////////////////////////////////////////
\r
565 // helper to draw scanlines
\r
566 ////////////////////////////////////////////////////////////////////////
\r
568 __inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2,
\r
569 OGLVertex* vertex3, OGLVertex* vertex4)
\r
574 ////////////////////////////////////////////////////////////////////////
\r
576 ////////////////////////////////////////////////////////////////////////
\r
578 void SetScanLines(void)
\r
582 ////////////////////////////////////////////////////////////////////////
\r
583 // blur, babe, blur (heavy performance hit for a so-so fullscreen effect)
\r
584 ////////////////////////////////////////////////////////////////////////
\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
593 int iLastRGB24=0; // special vars for checking when to skip two display updates
\r
595 void GPUvSinc(void){
\r
598 void updateDisplay(void) // UPDATE DISPLAY
\r
603 bFakeFrontBuffer=FALSE;
\r
604 bRenderFrontBuffer=FALSE;
\r
606 if(iRenderFVR) // frame buffer read fix mode still active?
\r
608 iRenderFVR--; // -> if some frames in a row without read access: turn off mode
\r
609 if(!iRenderFVR) bFullVRam=FALSE;
\r
612 if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check
\r
614 iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes
\r
618 if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted?
\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
628 if(bNeedInterlaceUpdate) // smaller upload?
\r
630 bNeedInterlaceUpdate=FALSE;
\r
631 xrUploadArea=xrUploadAreaIL; // -> upload this rect
\r
632 UploadScreen(TRUE);
\r
635 if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9
\r
637 if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed
\r
638 PreviousPSXDisplay.Range.y0)
\r
639 PaintBlackBorders();
\r
641 if(PSXDisplay.Disabled) // display disabled?
\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
649 bDisplayNotSet = TRUE;
\r
652 if(iSkipTwo) // we are in skipping mood?
\r
655 iDrawnSomething=0; // -> simply lie about something drawn
\r
658 //if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated?
\r
659 // {BlurBackBuffer();bBlur=TRUE;} // -> blur it
\r
661 // if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it
\r
663 // if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em
\r
665 if(dwActFixes&128) // special FPS limitation mode?
\r
667 if(bUseFrameLimit) PCFrameCap(); // -> ok, do it
\r
668 // if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS)
\r
672 // if(gTexPicName) DisplayPic(); // some gpu info picture active? display it
\r
674 // if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :)
\r
676 // if(ulKeybits&KEY_SHOWFPS) // wanna see FPS?
\r
678 // sprintf(szDispBuf,"%06.1f",fps_cur);
\r
679 // DisplayText(); // -> show it
\r
682 //----------------------------------------------------//
\r
683 // main buffer swapping (well, or skip it)
\r
685 if(bUseFrameSkip) // frame skipping active ?
\r
687 if(!bSkipNextFrame)
\r
689 if(iDrawnSomething) flipEGL();
\r
691 if((fps_skip < fFrameRateHz) && !(bSkipNextFrame))
\r
692 {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}
\r
693 else bSkipNextFrame = FALSE;
\r
698 if(iDrawnSomething) flipEGL();
\r
703 //----------------------------------------------------//
\r
705 if(lClearOnSwap) // clear buffer after swap?
\r
709 if(bDisplayNotSet) // -> set new vals
\r
710 SetOGLDisplaySettings(1);
\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
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
724 // if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before
\r
726 if(iZBufferDepth) // clear zbuffer as well (if activated)
\r
728 glDisable(GL_SCISSOR_TEST);
\r
729 glClear(GL_DEPTH_BUFFER_BIT);
\r
730 glEnable(GL_SCISSOR_TEST);
\r
735 //----------------------------------------------------//
\r
736 // additional uploads immediatly after swapping
\r
738 if(bNeedUploadAfter) // upload wanted?
\r
740 bNeedUploadAfter=FALSE;
\r
741 bNeedUploadTest=FALSE;
\r
742 UploadScreen(-1); // -> upload
\r
745 if(bNeedUploadTest)
\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
755 PrepareFullScreenUpload(TRUE);
\r
756 UploadScreen(TRUE);
\r
760 //----------------------------------------------------//
\r
761 // rumbling (main emu pad effect)
\r
763 if(iRumbleTime) // shake screen by modifying view port
\r
765 int i1=0,i2=0,i3=0,i4=0;
\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
776 glViewport(rRatioRect.left+i1,
\r
777 iResY-(rRatioRect.top+rRatioRect.bottom)+i2,
\r
778 rRatioRect.right+i3,
\r
779 rRatioRect.bottom+i4);
\r
782 //----------------------------------------------------//
\r
786 // if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled
\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
794 void updateFrontDisplay(void)
\r
796 if(PreviousPSXDisplay.Range.x0||
\r
797 PreviousPSXDisplay.Range.y0)
\r
798 PaintBlackBorders();
\r
800 //if(iBlurBuffer) BlurBackBuffer();
\r
802 //if(iUseScanLines) SetScanLines();
\r
804 // if(usCursorActive) ShowGunCursor();
\r
806 bFakeFrontBuffer=FALSE;
\r
807 bRenderFrontBuffer=FALSE;
\r
809 // if(gTexPicName) DisplayPic();
\r
810 // if(ulKeybits&KEY_SHOWFPS) DisplayText();
\r
812 if(iDrawnSomething) // linux:
\r
816 //if(iBlurBuffer) UnBlurBackBuffer();
\r
819 ////////////////////////////////////////////////////////////////////////
\r
820 // check if update needed
\r
821 ////////////////////////////////////////////////////////////////////////
\r
822 void ChangeDispOffsetsX(void) // CENTER X
\r
824 long lx,l;short sO;
\r
826 if(!PSXDisplay.Range.x1) return; // some range given?
\r
828 l=PSXDisplay.DisplayMode.x;
\r
830 l*=(long)PSXDisplay.Range.x1; // some funky calculation
\r
831 l/=2560;lx=l;l&=0xfffffff8;
\r
833 if(l==PreviousPSXDisplay.Range.x1) return; // some change?
\r
835 sO=PreviousPSXDisplay.Range.x0; // store old
\r
837 if(lx>=PSXDisplay.DisplayMode.x) // range bigger?
\r
839 PreviousPSXDisplay.Range.x1= // -> take display width
\r
840 PSXDisplay.DisplayMode.x;
\r
841 PreviousPSXDisplay.Range.x0=0; // -> start pos is 0
\r
843 else // range smaller? center it
\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
851 if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much
\r
852 PSXDisplay.DisplayMode.x)
\r
854 PreviousPSXDisplay.Range.x0= // -> adjust start
\r
855 PSXDisplay.DisplayMode.x-lx;
\r
856 PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width
\r
860 if(sO!=PreviousPSXDisplay.Range.x0) // something changed?
\r
862 bDisplayNotSet=TRUE; // -> recalc display stuff
\r
866 ////////////////////////////////////////////////////////////////////////
\r
868 void ChangeDispOffsetsY(void) // CENTER Y
\r
870 int iT;short sO; // store previous y size
\r
872 if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC
\r
874 if(PSXDisplay.Range.y0>=iT) // crossed the security line? :)
\r
876 PreviousPSXDisplay.Range.y1= // -> store width
\r
877 PSXDisplay.DisplayModeNew.y;
\r
879 sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset
\r
882 PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too
\r
884 else sO=0; // else no offset
\r
886 if(sO!=PreviousPSXDisplay.Range.y0) // something changed?
\r
888 PreviousPSXDisplay.Range.y0=sO;
\r
889 bDisplayNotSet=TRUE; // -> recalc display stuff
\r
893 ////////////////////////////////////////////////////////////////////////
\r
894 // Aspect ratio of ogl screen: simply adjusting ogl view port
\r
895 ////////////////////////////////////////////////////////////////////////
\r
897 void SetAspectRatio(void)
\r
899 float xs,ys,s;RECT r;
\r
901 if(!PSXDisplay.DisplayModeNew.x) return;
\r
902 if(!PSXDisplay.DisplayModeNew.y) return;
\r
905 xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x;
\r
906 ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y;
\r
909 r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s);
\r
910 r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s);
\r
911 if(r.right > iResX) r.right = iResX;
\r
912 if(r.bottom > iResY) r.bottom = iResY;
\r
913 if(r.right < 1) r.right = 1;
\r
914 if(r.bottom < 1) r.bottom = 1;
\r
916 r.left = (iResX-r.right)/2;
\r
917 r.top = (iResY-r.bottom)/2;
\r
919 if(r.bottom<rRatioRect.bottom ||
\r
920 r.right <rRatioRect.right)
\r
923 glClearColor(0,0,0,128);
\r
925 if(r.right <rRatioRect.right)
\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
938 if(r.bottom <rRatioRect.bottom)
\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
952 bDisplayNotSet=TRUE;
\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
962 glViewport(rRatioRect.left,
\r
963 iResY-(rRatioRect.top+rRatioRect.bottom),
\r
965 rRatioRect.bottom); // init viewport
\r
968 ////////////////////////////////////////////////////////////////////////
\r
969 // big ass check, if an ogl swap buffer is needed
\r
970 ////////////////////////////////////////////////////////////////////////
\r
972 void updateDisplayIfChanged(void)
\r
976 if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) &&
\r
977 (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))
\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
983 else // some res change?
\r
986 glOrtho(0,PSXDisplay.DisplayModeNew.x, // -> new psx resolution
\r
987 PSXDisplay.DisplayModeNew.y, 0, -1, 1);
\r
988 if(bKeepRatio) SetAspectRatio();
\r
991 bDisplayNotSet = TRUE; // re-calc offsets/display area
\r
994 if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off)
\r
996 PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet
\r
997 ResetTextureArea(FALSE);
\r
1001 PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos
\r
1002 PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;
\r
1003 PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;
\r
1004 PSXDisplay.Interlaced = PSXDisplay.InterlacedNew;
\r
1006 PSXDisplay.DisplayEnd.x= // calc new ends
\r
1007 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1008 PSXDisplay.DisplayEnd.y=
\r
1009 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1010 PreviousPSXDisplay.DisplayEnd.x=
\r
1011 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1012 PreviousPSXDisplay.DisplayEnd.y=
\r
1013 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1015 ChangeDispOffsetsX();
\r
1017 if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace)
\r
1019 if(bUp) updateDisplay(); // yeah, real update (swap buffer)
\r
1022 ////////////////////////////////////////////////////////////////////////
\r
1023 // window mode <-> fullscreen mode (windows)
\r
1024 ////////////////////////////////////////////////////////////////////////
\r
1027 ////////////////////////////////////////////////////////////////////////
\r
1028 // swap update check (called by psx vsync function)
\r
1029 ////////////////////////////////////////////////////////////////////////
\r
1031 BOOL bSwapCheck(void)
\r
1033 static int iPosCheck=0;
\r
1034 static PSXPoint_t pO;
\r
1035 static PSXPoint_t pD;
\r
1036 static int iDoAgain=0;
\r
1038 if(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
1045 pO=PSXDisplay.DisplayPosition;
\r
1046 pD=PSXDisplay.DisplayEnd;
\r
1048 if(iPosCheck<=4) return FALSE;
\r
1052 if(PSXDisplay.Interlaced) return FALSE;
\r
1054 if (bNeedInterlaceUpdate||
\r
1055 bNeedRGB24Update ||
\r
1056 bNeedUploadAfter||
\r
1057 bNeedUploadTest ||
\r
1062 if(bNeedUploadAfter)
\r
1064 if(bNeedUploadTest && PSXDisplay.InterlacedTest)
\r
1067 bDisplayNotSet = TRUE;
\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
1082 ////////////////////////////////////////////////////////////////////////
\r
1083 // gun cursor func: player=0-7, x=0-511, y=0-255
\r
1084 ////////////////////////////////////////////////////////////////////////
\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
1091 static unsigned short usFirstPos=2;
\r
1093 void CALLBACK GPUupdateLace(void)
\r
1095 if(!(dwActFixes&0x1000))
\r
1096 STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus)
\r
1098 if(!(dwActFixes&128)) // normal frame limit func
\r
1101 if(iOffscreenDrawing==4) // special check if high offscreen drawing is on
\r
1103 if(bSwapCheck()) return;
\r
1106 if(PSXDisplay.Interlaced) // interlaced mode?
\r
1108 if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)
\r
1110 updateDisplay(); // -> swap buffers (new frame)
\r
1113 else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed?
\r
1115 updateFrontDisplay(); // -> update front buffer
\r
1117 else if(usFirstPos==1) // initial updates (after startup)
\r
1124 ////////////////////////////////////////////////////////////////////////
\r
1125 // process read request from GPU status register
\r
1126 ////////////////////////////////////////////////////////////////////////
\r
1128 unsigned long CALLBACK GPUreadStatus(void)
\r
1130 if(dwActFixes&0x1000) // CC game fix
\r
1132 static int iNumRead=0;
\r
1133 if((iNumRead++)==2)
\r
1136 STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross)
\r
1140 if(iFakePrimBusy) // 27.10.2007 - emulating some 'busy' while drawing... pfff... not perfect, but since our emulated dma is not done in an extra thread...
\r
1144 if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims
\r
1147 GPUIsNotReadyForCommands;
\r
1152 GPUIsReadyForCommands;
\r
1159 ////////////////////////////////////////////////////////////////////////
\r
1160 // processes data send to GPU status register
\r
1161 // these are always single packet commands.
\r
1162 ////////////////////////////////////////////////////////////////////////
\r
1164 void CALLBACK GPUwriteStatus(unsigned long gdata)
\r
1166 unsigned long lCommand=(gdata>>24)&0xff;
\r
1168 if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus)
\r
1170 ulStatusControl[lCommand]=gdata;
\r
1174 //--------------------------------------------------//
\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
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
1192 // dis/enable display
\r
1194 PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;
\r
1195 PSXDisplay.Disabled = (gdata & 1);
\r
1197 if(PSXDisplay.Disabled)
\r
1198 STATUSREG|=GPUSTATUS_DISPLAYDISABLED;
\r
1199 else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED;
\r
1201 if (iOffscreenDrawing==4 &&
\r
1202 PreviousPSXDisplay.Disabled &&
\r
1203 !(PSXDisplay.Disabled))
\r
1206 if(!PSXDisplay.RGB24)
\r
1208 PrepareFullScreenUpload(TRUE);
\r
1209 UploadScreen(TRUE);
\r
1216 // setting transfer mode
\r
1218 gdata &= 0x03; // only want the lower two bits
\r
1220 iDataWriteMode=iDataReadMode=DR_NORMAL;
\r
1221 if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER;
\r
1222 if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER;
\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
1229 // setting display position
\r
1232 short sx=(short)(gdata & 0x3ff);
\r
1235 if(iGPUHeight==1024)
\r
1237 if(dwGPUVersion==2)
\r
1238 sy = (short)((gdata>>12)&0x3ff);
\r
1239 else sy = (short)((gdata>>10)&0x3ff);
\r
1241 else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later
\r
1246 PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double;
\r
1249 else PreviousPSXDisplay.DisplayModeNew.y=0;
\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
1267 if((!PSXDisplay.Interlaced) &&
\r
1268 PreviousPSXDisplay.DisplayPosition.x == sx &&
\r
1269 PreviousPSXDisplay.DisplayPosition.y == sy)
\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
1279 if((!PSXDisplay.Interlaced) &&
\r
1280 PSXDisplay.DisplayPosition.x == sx &&
\r
1281 PSXDisplay.DisplayPosition.y == sy)
\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
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
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
1299 bDisplayNotSet = TRUE;
\r
1301 if (!(PSXDisplay.Interlaced))
\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
1317 PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff;
\r
1318 PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff;
\r
1320 PSXDisplay.Range.x1-=PSXDisplay.Range.x0;
\r
1322 ChangeDispOffsetsX();
\r
1329 PreviousPSXDisplay.Height = PSXDisplay.Height;
\r
1331 PSXDisplay.Range.y0=gdata & 0x3ff;
\r
1332 PSXDisplay.Range.y1=(gdata>>10) & 0x3ff;
\r
1334 PSXDisplay.Height = PSXDisplay.Range.y1 -
\r
1335 PSXDisplay.Range.y0 +
\r
1336 PreviousPSXDisplay.DisplayModeNew.y;
\r
1338 if (PreviousPSXDisplay.Height != PSXDisplay.Height)
\r
1340 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
\r
1341 ChangeDispOffsetsY();
\r
1342 updateDisplayIfChanged();
\r
1346 // setting display infos
\r
1349 PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];
\r
1351 if (gdata&0x04) PSXDisplay.Double=2;
\r
1352 else PSXDisplay.Double=1;
\r
1353 PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;
\r
1355 ChangeDispOffsetsY();
\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
1361 STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits
\r
1364 (((gdata & 0x03) << 17) |
\r
1365 ((gdata & 0x40) << 10)); // set the width bits
\r
1367 PreviousPSXDisplay.InterlacedNew=FALSE;
\r
1368 if (PSXDisplay.InterlacedNew)
\r
1370 if(!PSXDisplay.Interlaced)
\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
1378 STATUSREG|=GPUSTATUS_INTERLACED;
\r
1382 PSXDisplay.InterlacedTest=0;
\r
1383 STATUSREG&=~GPUSTATUS_INTERLACED;
\r
1386 if (PSXDisplay.PAL)
\r
1387 STATUSREG|=GPUSTATUS_PAL;
\r
1388 else STATUSREG&=~GPUSTATUS_PAL;
\r
1390 if (PSXDisplay.Double==2)
\r
1391 STATUSREG|=GPUSTATUS_DOUBLEHEIGHT;
\r
1392 else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT;
\r
1394 if (PSXDisplay.RGB24New)
\r
1395 STATUSREG|=GPUSTATUS_RGB24;
\r
1396 else STATUSREG&=~GPUSTATUS_RGB24;
\r
1398 updateDisplayIfChanged();
\r
1402 //--------------------------------------------------//
\r
1403 // ask about GPU version and other stuff
\r
1411 GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos
\r
1414 GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start
\r
1417 GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end
\r
1421 GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset
\r
1424 if(dwGPUVersion==2)
\r
1426 else GPUdataRet=0x02; // gpu type
\r
1429 case 0x0F: // some bios addr?
\r
1430 GPUdataRet=0xBFC03720;
\r
1434 //--------------------------------------------------//
\r
1438 ////////////////////////////////////////////////////////////////////////
\r
1439 // vram read/write helpers
\r
1440 ////////////////////////////////////////////////////////////////////////
\r
1442 BOOL bNeedWriteUpload=FALSE;
\r
1444 __inline void FinishedVRAMWrite(void)
\r
1446 if(bNeedWriteUpload)
\r
1448 bNeedWriteUpload=FALSE;
\r
1449 CheckWriteUpdate();
\r
1452 // set register to NORMAL operation
\r
1453 iDataWriteMode = DR_NORMAL;
\r
1455 // reset transfer values, to prevent mis-transfer of data
\r
1456 VRAMWrite.ColsRemaining = 0;
\r
1457 VRAMWrite.RowsRemaining = 0;
\r
1460 __inline void FinishedVRAMRead(void)
\r
1462 // set register to NORMAL operation
\r
1463 iDataReadMode = DR_NORMAL;
\r
1464 // reset transfer values, to prevent mis-transfer of data
\r
1467 VRAMRead.Width = 0;
\r
1468 VRAMRead.Height = 0;
\r
1469 VRAMRead.ColsRemaining = 0;
\r
1470 VRAMRead.RowsRemaining = 0;
\r
1472 // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER
\r
1473 STATUSREG&=~GPUSTATUS_READYFORVRAM;
\r
1476 ////////////////////////////////////////////////////////////////////////
\r
1477 // vram read check ex (reading from card's back/frontbuffer if needed...
\r
1479 ////////////////////////////////////////////////////////////////////////
\r
1481 void CheckVRamReadEx(int x, int y, int dx, int dy)
\r
1483 unsigned short sArea;
\r
1484 int ux,uy,udx,udy,wx,wy;
\r
1485 unsigned short * p1, *p2;
\r
1487 unsigned char * ps;
\r
1488 unsigned char * px;
\r
1489 unsigned short s,sx;
\r
1491 if(STATUSREG&GPUSTATUS_RGB24) return;
\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
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
1514 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1516 bFullVRam=TRUE;iRenderFVR=2;
\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
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
1549 p1=(psxVuw + (1024*uy) + ux);
\r
1553 wx=dx=udx;wy=dy=udy;
\r
1555 if(udx<=0) return;
\r
1556 if(udy<=0) return;
\r
1562 XS=(float)rRatioRect.right/(float)wx;
\r
1563 YS=(float)rRatioRect.bottom/(float)wy;
\r
1565 dx=(int)((float)(dx)*XS);
\r
1566 dy=(int)((float)(dy)*YS);
\r
1568 if(dx>iResX) dx=iResX;
\r
1569 if(dy>iResY) dy=iResY;
\r
1577 x+=rRatioRect.left;
\r
1578 y-=rRatioRect.top;
\r
1580 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1582 if(!pGfxCardScreen)
\r
1584 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1585 pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);
\r
1588 ps=pGfxCardScreen;
\r
1590 //if(!sArea) glReadBuffer(GL_FRONT);
\r
1592 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1594 //if(!sArea) glReadBuffer(GL_BACK);
\r
1598 XS=(float)dx/(float)(udx);
\r
1599 YS=(float)dy/(float)(udy+1);
\r
1601 for(y=udy;y>0;y--)
\r
1603 for(x=0;x<udx;x++)
\r
1605 if(p1>=psxVuw && p1<psxVuw_eom)
\r
1607 px=ps+(3*((int)((float)x * XS))+
\r
1608 (3*dx)*((int)((float)y*YS)));
\r
1618 if(p2>=psxVuw && p2<psxVuw_eom) *p2=s;
\r
1625 if(p2) p2 += 1024 - udx;
\r
1629 ////////////////////////////////////////////////////////////////////////
\r
1630 // vram read check (reading from card's back/frontbuffer if needed...
\r
1632 ////////////////////////////////////////////////////////////////////////
\r
1634 void CheckVRamRead(int x, int y, int dx, int dy, bool bFront)
\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
1641 if(STATUSREG&GPUSTATUS_RGB24) return;
\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
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
1660 if(dwActFixes&0x40)
\r
1664 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1666 bFullVRam=TRUE;iRenderFVR=2;
\r
1669 ux=x;uy=y;udx=dx;udy=dy;
\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
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
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
1696 p=(psxVuw + (1024*uy) + ux);
\r
1698 if(udx<=0) return;
\r
1699 if(udy<=0) return;
\r
1705 XS=(float)rRatioRect.right/(float)wx;
\r
1706 YS=(float)rRatioRect.bottom/(float)wy;
\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
1716 if(dx>iResX) dx=iResX;
\r
1717 if(dy>iResY) dy=iResY;
\r
1725 x+=rRatioRect.left;
\r
1726 y-=rRatioRect.top;
\r
1728 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1730 if(!pGfxCardScreen)
\r
1732 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1733 pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);
\r
1736 ps=pGfxCardScreen;
\r
1738 // if(bFront) glReadBuffer(GL_FRONT);
\r
1740 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1742 // if(bFront) glReadBuffer(GL_BACK);
\r
1744 XS=(float)dx/(float)(udx);
\r
1745 YS=(float)dy/(float)(udy+1);
\r
1747 for(y=udy;y>0;y--)
\r
1749 for(x=0;x<udx;x++)
\r
1751 if(p>=psxVuw && p<psxVuw_eom)
\r
1753 px=ps+(3*((int)((float)x * XS))+
\r
1754 (3*dx)*((int)((float)y*YS)));
\r
1770 ////////////////////////////////////////////////////////////////////////
\r
1771 // core read from vram
\r
1772 ////////////////////////////////////////////////////////////////////////
\r
1774 void CALLBACK GPUreadDataMem(unsigned long * pMem, int iSize)
\r
1778 if(iDataReadMode!=DR_VRAMTRANSFER) return;
\r
1782 // adjust read ptr, if necessary
\r
1783 while(VRAMRead.ImagePtr>=psxVuw_eom)
\r
1784 VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
1785 while(VRAMRead.ImagePtr<psxVuw)
\r
1786 VRAMRead.ImagePtr+=iGPUHeight*1024;
\r
1788 if((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
1799 for(i=0;i<iSize;i++)
\r
1801 // do 2 seperate 16bit reads for compatibility (wrap issues)
\r
1802 if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))
\r
1805 GPUdataRet=(unsigned long)*VRAMRead.ImagePtr;
\r
1807 VRAMRead.ImagePtr++;
\r
1808 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
1809 VRAMRead.RowsRemaining --;
\r
1811 if(VRAMRead.RowsRemaining<=0)
\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
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
1823 if(VRAMRead.ColsRemaining <= 0)
\r
1824 {FinishedVRAMRead();goto ENDREAD;}
\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
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
1836 if(VRAMRead.ColsRemaining <= 0)
\r
1837 {FinishedVRAMRead();goto ENDREAD;}
\r
1839 else {FinishedVRAMRead();goto ENDREAD;}
\r
1846 unsigned long CALLBACK GPUreadData(void)
\r
1849 GPUreadDataMem(&l,1);
\r
1850 return GPUdataRet;
\r
1853 ////////////////////////////////////////////////////////////////////////
\r
1854 // helper table to know how much data is used by drawing commands
\r
1855 ////////////////////////////////////////////////////////////////////////
\r
1857 const unsigned char primTableCX[256] =
\r
1874 8,8,8,8,12,12,12,12,
\r
1878 // 5,5,5,5,6,6,6,6, //FLINE
\r
1879 254,254,254,254,254,254,254,254,
\r
1883 // 7,7,7,7,9,9,9,9, // LINEG3 LINEG4
\r
1884 255,255,255,255,255,255,255,255,
\r
1886 3,3,3,3,4,4,4,4, // TILE SPRT
\r
1888 2,2,2,2,3,3,3,3, // TILE1
\r
1927 ////////////////////////////////////////////////////////////////////////
\r
1928 // processes data send to GPU data register
\r
1929 ////////////////////////////////////////////////////////////////////////
\r
1931 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)
\r
1933 unsigned char command;
\r
1934 unsigned long gdata=0;
\r
1937 GPUIsNotReadyForCommands;
\r
1941 if(iDataWriteMode==DR_VRAMTRANSFER)
\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
1949 // now do the loop
\r
1950 while(VRAMWrite.ColsRemaining>0)
\r
1952 while(VRAMWrite.RowsRemaining>0)
\r
1954 if(i>=iSize) {goto ENDVRAM;}
\r
1959 *VRAMWrite.ImagePtr++ = (unsigned short)gdata;
\r
1960 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
1961 VRAMWrite.RowsRemaining --;
\r
1963 if(VRAMWrite.RowsRemaining <= 0)
\r
1965 VRAMWrite.ColsRemaining--;
\r
1966 if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width
\r
1968 gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16);
\r
1969 FinishedVRAMWrite();
\r
1972 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
1973 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
1976 *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16);
\r
1977 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
1978 VRAMWrite.RowsRemaining --;
\r
1981 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
1982 VRAMWrite.ColsRemaining--;
\r
1983 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
1986 FinishedVRAMWrite();
\r
1991 if(iDataWriteMode==DR_NORMAL)
\r
1993 void (* *primFunc)(unsigned char *);
\r
1994 if(bSkipNextFrame) primFunc=primTableSkip;
\r
1995 else primFunc=primTableJ;
\r
1999 if(iDataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;
\r
2001 gdata=*pMem++;i++;
\r
2005 command = (unsigned char)((gdata>>24) & 0xff);
\r
2007 if(primTableCX[command])
\r
2009 gpuDataC = primTableCX[command];
\r
2010 gpuCommand = command;
\r
2011 gpuDataM[0] = gdata;
\r
2018 gpuDataM[gpuDataP] = gdata;
\r
2021 if((gpuDataC==254 && gpuDataP>=3) ||
\r
2022 (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))
\r
2024 if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)
\r
2025 gpuDataP=gpuDataC-1;
\r
2031 if(gpuDataP == gpuDataC)
\r
2033 gpuDataC=gpuDataP=0;
\r
2034 primFunc[gpuCommand]((unsigned char *)gpuDataM);
\r
2036 if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games
\r
2044 GPUIsReadyForCommands;
\r
2048 ////////////////////////////////////////////////////////////////////////
\r
2050 void CALLBACK GPUwriteData(unsigned long gdata)
\r
2052 GPUwriteDataMem(&gdata,1);
\r
2055 ////////////////////////////////////////////////////////////////////////
\r
2056 // this function will be removed soon (or 'soonish') (or never)
\r
2057 ////////////////////////////////////////////////////////////////////////
\r
2059 void CALLBACK GPUsetMode(unsigned int gdata)
\r
2061 // ignore old psemu setmode:
\r
2063 // imageTransfer = gdata;
\r
2064 // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2065 // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2068 // and this function will be removed soon as well, hehehe...
\r
2069 long CALLBACK GPUgetMode(void)
\r
2071 // ignore old psemu setmode
\r
2072 // return imageTransfer;
\r
2076 if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1;
\r
2077 if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2;
\r
2082 ////////////////////////////////////////////////////////////////////////
\r
2083 // call config dlg (Windows + Linux)
\r
2084 ////////////////////////////////////////////////////////////////////////
\r
2088 /*#include <unistd.h>
\r
2090 void StartCfgTool(char * pCmdLine) // linux: start external cfg tool
\r
2092 FILE * cf;char filename[255],t[255];
\r
2094 strcpy(filename,"cfg/cfgPeopsMesaGL"); // look in cfg sub folder first
\r
2095 cf=fopen(filename,"rb");
\r
2101 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2107 strcpy(filename,"cfgPeopsMesaGL"); // look in current folder
\r
2108 cf=fopen(filename,"rb");
\r
2112 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2117 sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder
\r
2118 cf=fopen(filename,"rb");
\r
2123 chdir(getenv("HOME"));
\r
2124 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2128 else printf("cfgPeopsMesaGL not found!\n");
\r
2136 long CALLBACK GPUconfigure(void)
\r
2143 ////////////////////////////////////////////////////////////////////////
\r
2144 // sets all kind of act fixes
\r
2145 ////////////////////////////////////////////////////////////////////////
\r
2147 void SetFixes(void)
\r
2151 if(dwActFixes & 0x2000)
\r
2152 dispWidths[4]=384;
\r
2153 else dispWidths[4]=368;
\r
2156 ////////////////////////////////////////////////////////////////////////
\r
2157 // Pete Special: make an 'intelligent' dma chain check (<-Tekken3)
\r
2158 ////////////////////////////////////////////////////////////////////////
\r
2160 unsigned long lUsedAddr[3];
\r
2162 __inline BOOL CheckForEndlessLoop(unsigned long laddr)
\r
2164 if(laddr==lUsedAddr[1]) return TRUE;
\r
2165 if(laddr==lUsedAddr[2]) return TRUE;
\r
2167 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
\r
2168 else lUsedAddr[2]=laddr;
\r
2169 lUsedAddr[0]=laddr;
\r
2173 ////////////////////////////////////////////////////////////////////////
\r
2174 // core gives a dma chain to gpu: same as the gpuwrite interface funcs
\r
2175 ////////////////////////////////////////////////////////////////////////
\r
2177 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)
\r
2179 unsigned long dmaMem;
\r
2180 unsigned char * baseAddrB;
\r
2181 short count;unsigned int DMACommandCounter = 0;
\r
2183 if(bIsFirstFrame) GLinitialize();
\r
2187 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
\r
2189 baseAddrB = (unsigned char*) baseAddrL;
\r
2193 if(iGPUHeight==512) addr&=0x1FFFFC;
\r
2195 if(DMACommandCounter++ > 2000000) break;
\r
2196 if(CheckForEndlessLoop(addr)) break;
\r
2198 count = baseAddrB[addr+3];
\r
2202 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
\r
2204 addr = baseAddrL[addr>>2]&0xffffff;
\r
2206 while (addr != 0xffffff);
\r
2213 ////////////////////////////////////////////////////////////////////////
\r
2215 ////////////////////////////////////////////////////////////////////////
\r
2217 void CALLBACK GPUabout(void)
\r
2222 ////////////////////////////////////////////////////////////////////////
\r
2223 // We are ever fine ;)
\r
2224 ////////////////////////////////////////////////////////////////////////
\r
2226 long CALLBACK GPUtest(void)
\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
2234 ////////////////////////////////////////////////////////////////////////
\r
2235 // save state funcs
\r
2236 ////////////////////////////////////////////////////////////////////////
\r
2238 ////////////////////////////////////////////////////////////////////////
\r
2240 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)
\r
2242 if(ulGetFreezeData==2)
\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
2251 if(!pF) return 0;
\r
2252 if(pF->ulFreezeVersion!=1) return 0;
\r
2254 if(ulGetFreezeData==1)
\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
2263 if(ulGetFreezeData!=0) return 0;
\r
2265 STATUSREG=pF->ulStatus;
\r
2266 memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long));
\r
2267 memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2);
\r
2269 ResetTextureArea(TRUE);
\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
2283 ////////////////////////////////////////////////////////////////////////
\r
2284 // special "emu infos" / "emu effects" functions
\r
2285 ////////////////////////////////////////////////////////////////////////
\r
2290 //11 = transparent
\r
2292 unsigned char cFont[10][120]=
\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
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
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
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
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
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
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
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
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
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
2516 ////////////////////////////////////////////////////////////////////////
\r
2518 void PaintPicDot(unsigned char * p,unsigned char c)
\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
2525 ////////////////////////////////////////////////////////////////////////
\r
2527 long CALLBACK GPUgetScreenPic(unsigned char * pMem)
\r
2529 float XS,YS;int x,y,v;
\r
2530 unsigned char * ps, * px, * pf;
\r
2533 if(!pGfxCardScreen)
\r
2535 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
2536 pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);
\r
2539 ps=pGfxCardScreen;
\r
2541 // glReadBuffer(GL_FRONT);
\r
2543 glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
2545 // glReadBuffer(GL_BACK);
\r
2547 XS=(float)iResX/128;
\r
2548 YS=(float)iResY/96;
\r
2553 for(x=0;x<128;x++)
\r
2555 px=ps+(3*((int)((float)x * XS))+
\r
2556 (3*iResX)*((int)((float)y*YS)));
\r
2564 /////////////////////////////////////////////////////////////////////
\r
2565 // generic number/border painter
\r
2573 c=cFont[lSelectedSlot][x+y*6];
\r
2575 PaintPicDot(pf,(unsigned char)v);pf+=3; // paint the dots into the rect
\r
2577 PaintPicDot(pf,(unsigned char)v);pf+=3;
\r
2579 PaintPicDot(pf,(unsigned char)v);pf+=3;
\r
2581 PaintPicDot(pf,(unsigned char)v);pf+=3;
\r
2587 for(x=0;x<128;x++)
\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
2596 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2597 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2598 *(pf+(127*3))=0xff;*pf++=0xff;
\r
2604 ////////////////////////////////////////////////////////////////////////
\r
2606 long CALLBACK GPUshowScreenPic(unsigned char * pMem)
\r
2609 // if(pMem==0) return;
\r
2610 // CreatePic(pMem);
\r
2613 ////////////////////////////////////////////////////////////////////////
\r
2615 void CALLBACK GPUsetfix(unsigned long dwFixBits)
\r
2617 dwEmuFixes=dwFixBits;
\r
2620 ////////////////////////////////////////////////////////////////////////
\r
2622 void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig)
\r
2626 if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width
\r
2627 iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x);
\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
2633 srand(timeGetTime()); // init rand (will be used in BufferSwap)
\r
2635 iRumbleTime=15; // let the rumble last 16 buffer swaps
\r
2638 ////////////////////////////////////////////////////////////////////////
\r
2639 // main emu can set display infos (A/M/G/D)
\r
2640 ////////////////////////////////////////////////////////////////////////
\r
2642 void CALLBACK GPUdisplayFlags(unsigned long dwFlags)
\r
2644 // dwCoreFlags=dwFlags;
\r
2647 // pcsx-rearmed callbacks
\r
2648 void CALLBACK GPUrearmedCallbacks(const void **cbs)
\r
2650 rearmed_get_layer_pos = cbs[0];
\r
2653 static void flipEGL(void)
\r
2655 eglSwapBuffers(display, surface);
\r