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
39 #include <mmsystem.h>
\r
41 #include "externals.h"
\r
45 #include "texture.h"
\r
47 #include "resource.h"
\r
53 #include "gpuExternals.h"
\r
54 #include "gpuPlugin.h"
\r
55 #include "gpuDraw.h"
\r
56 #include "gpuTexture.h"
\r
58 #include "gpuPrim.h"
\r
60 //#include "NoPic.h"
\r
62 #include "gpuStdafx.h"
\r
65 extern void ProcessEvents();
\r
67 short g_m1=255,g_m2=255,g_m3=255;
\r
68 short DrawSemiTrans=FALSE;
\r
72 short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; // global psx vertex coords
\r
73 long GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP;
\r
74 long GlobalTextREST,GlobalTextABR,GlobalTextPAGE;
\r
76 unsigned long dwGPUVersion=0;
\r
78 int iGPUHeightMask=511;
\r
82 ////////////////////////////////////////////////////////////////////////
\r
83 // memory image of the PSX vram
\r
84 ////////////////////////////////////////////////////////////////////////
\r
88 signed char *psxVsb;
\r
89 unsigned short *psxVuw;
\r
90 unsigned short *psxVuw_eom;
\r
91 signed short *psxVsw;
\r
92 unsigned long *psxVul;
\r
93 signed long *psxVsl;
\r
95 // macro for easy access to packet information
\r
96 #define GPUCOMMAND(x) ((x>>24) & 0xff)
\r
99 BOOL bNeedInterlaceUpdate=FALSE;
\r
100 BOOL bNeedRGB24Update=FALSE;
\r
101 BOOL bChangeWinMode=FALSE;
\r
104 extern HGLRC GLCONTEXT;
\r
107 unsigned long ulStatusControl[256];
\r
109 ////////////////////////////////////////////////////////////////////////
\r
111 ////////////////////////////////////////////////////////////////////////
\r
113 static long GPUdataRet;
\r
114 long lGPUstatusRet;
\r
117 static unsigned long gpuDataM[256];
\r
118 static u8 gpuCommand = 0;
\r
119 static long gpuDataC = 0;
\r
120 static long gpuDataP = 0;
\r
122 VRAMLoad_t VRAMWrite;
\r
123 VRAMLoad_t VRAMRead;
\r
124 int iDataWriteMode;
\r
128 long lClearOnSwapColor;
\r
129 BOOL bSkipNextFrame = FALSE;
\r
135 // possible psx display widths
\r
136 short dispWidths[8] = {256,320,512,640,368,384,512,640};
\r
138 PSXDisplay_t PSXDisplay;
\r
139 PSXDisplay_t PreviousPSXDisplay;
\r
141 short imageX0,imageX1;
\r
142 short imageY0,imageY1;
\r
143 BOOL bDisplayNotSet = TRUE;
\r
144 GLuint uiScanLine=0;
\r
145 int iUseScanLines=0;
\r
146 long lSelectedSlot=0;
\r
147 u8 * pGfxCardScreen=0;
\r
151 int iNoScreenSaver=0;
\r
152 unsigned long ulGPUInfoVals[16];
\r
153 int iFakePrimBusy = 0;
\r
154 int iRumbleVal = 0;
\r
155 int iRumbleTime = 0;
\r
157 ////////////////////////////////////////////////////////////////////////
\r
158 // stuff to make this a true PDK module
\r
159 ////////////////////////////////////////////////////////////////////////
\r
162 s8 * CALLBACK PSEgetLibName(void)
\r
167 unsigned long CALLBACK PSEgetLibType(void)
\r
172 unsigned long CALLBACK PSEgetLibVersion(void)
\r
174 return 1<<16|1<<8|1;
\r
178 ////////////////////////////////////////////////////////////////////////
\r
179 // snapshot funcs (saves screen to bitmap / text infos into file)
\r
180 ////////////////////////////////////////////////////////////////////////
\r
182 void ResizeWindow()
\r
184 rRatioRect.left = rRatioRect.top=0;
\r
185 rRatioRect.right = iResX;
\r
186 rRatioRect.bottom = iResY;
\r
187 glViewport(rRatioRect.left, // init viewport by ratio rect
\r
188 iResY-(rRatioRect.top+rRatioRect.bottom),
\r
190 rRatioRect.bottom);
\r
192 glScissor(0, 0, iResX, iResY); // init clipping (fullscreen)
\r
193 glEnable(GL_SCISSOR_TEST);
\r
196 glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale"
\r
198 glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack
\r
201 glMatrixMode(GL_PROJECTION); // init projection with psx resolution
\r
203 glOrtho(0,PSXDisplay.DisplayMode.x,
\r
204 PSXDisplay.DisplayMode.y, 0, -1, 1);
\r
209 s8 * GetConfigInfos(int hW)
\r
212 HDC hdc;HGLRC hglrc;
\r
214 s8 szO[2][4]={"off","on "};
\r
216 s8 * pB=(s8 *)malloc(32767);
\r
218 if(!pB) return NULL;
\r
220 //----------------------------------------------------//
\r
227 bSetupPixelFormat(hdc);
\r
228 hglrc = wglCreateContext(hdc);
\r
229 wglMakeCurrent(hdc, hglrc);
\r
232 sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR));
\r
234 sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER));
\r
236 sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION));
\r
238 //strcat(pB,(s8 *)glGetString(GL_EXTENSIONS));
\r
239 //strcat(pB,"\r\n\r\n");
\r
244 wglMakeCurrent(NULL, NULL);
\r
245 wglDeleteContext(hglrc);
\r
248 //----------------------------------------------------//
\r
250 if(hW && bWindowMode)
\r
251 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize));
\r
253 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY);
\r
255 if(bWindowMode) sprintf(szTxt,"Window mode\r\n");
\r
258 sprintf(szTxt,"Fullscreen ");
\r
260 if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth);
\r
261 else sprintf(szTxt,"- NO desktop changing\r\n");
\r
265 // if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]);
\r
266 // else strcpy(szTxt,"- V-Sync: Driver\r\n");
\r
268 sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]);
\r
270 //----------------------------------------------------//
\r
271 strcpy(szTxt,"Textures:\r\n- ");
\r
272 /*! if(iTexQuality==0) strcat(szTxt,"Default");
\r
273 else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4");
\r
274 else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1");
\r
275 else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8");
\r
276 else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8");
\r
277 if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n");
\r
278 else strcat(szTxt,"\r\n");
\r
282 sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType);
\r
283 if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n");
\r
284 else strcat(szTxt,"NOT supported\r\n");
\r
286 else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType);
\r
288 sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures);
\r
292 sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]);
\r
296 /*sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize);
\r
298 sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt);
\r
299 else strcat(szTxt,"\r\n\r\n");
\r
301 //----------------------------------------------------//
\r
302 sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]);
\r
304 sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]);
\r
307 strcpy(szTxt,"- FPS limit: Auto\r\n\r\n");
\r
308 else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate);
\r
310 //----------------------------------------------------//
\r
311 sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing);
\r
313 sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType);
\r
314 if(!hW && iFrameTexType==2)
\r
316 if(gTexFrameName) strcat(szTxt," - texture created\r\n");
\r
317 else strcat(szTxt," - not used yet\r\n");
\r
319 else strcat(szTxt,"\r\n");
\r
321 sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType);
\r
323 // sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]);
\r
325 sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]);
\r
327 //sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]);
\r
328 //if(!hW && bAdvancedBlend)
\r
330 // if(bGLBlend) strcat(szTxt," (hardware)\r\n");
\r
331 // else strcat(szTxt," (software)\r\n");
\r
333 strcat(szTxt,"\r\n");
\r
338 strcpy(szTxt,"- Subtractive blending: ");
\r
339 // if(glBlendEquationEXTEx)
\r
341 // if(bUseMultiPass) strcat(szTxt,"supported, but not used!");
\r
342 // else strcat(szTxt,"activated");
\r
344 strcat(szTxt," NOT supported!");
\r
345 strcat(szTxt,"\r\n\r\n");
\r
347 else strcpy(szTxt,"\r\n");
\r
350 //----------------------------------------------------//
\r
351 sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]);
\r
353 if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend);
\r
354 else strcpy(szTxt,"\r\n");
\r
356 // sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]);
\r
358 // sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]);
\r
359 // fwrite(szTxt,lstrlen(szTxt),1,txtfile);
\r
360 sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]);
\r
362 sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]);
\r
364 sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]);
\r
366 sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]);
\r
368 if(!hW && iBlurBuffer)
\r
370 if(gTexBlurName) strcat(pB," - supported\r\n");
\r
371 else strcat(pB," - not supported\r\n");
\r
373 else strcat(pB,"\r\n");
\r
374 sprintf(szTxt,"- Game fixes: %s [%08lx]\r\n",szO[bUseFixes],dwCfgFixes);
\r
376 //----------------------------------------------------//
\r
380 ////////////////////////////////////////////////////////////////////////
\r
381 // save text infos to file
\r
382 ////////////////////////////////////////////////////////////////////////
\r
384 void DoTextSnapShot(int iNum)
\r
388 ////////////////////////////////////////////////////////////////////////
\r
389 // saves screen bitmap to file
\r
390 ////////////////////////////////////////////////////////////////////////
\r
392 void DoSnapShot(void)
\r
397 void CALLBACK GPUmakeSnapshot(void)
\r
399 void CALLBACK GPU_makeSnapshot(void)
\r
402 //bSnapShot = TRUE;
\r
405 ////////////////////////////////////////////////////////////////////////
\r
406 // GPU INIT... here starts it all (first func called by emu)
\r
407 ////////////////////////////////////////////////////////////////////////
\r
410 long CALLBACK GPUinit()
\r
412 long CALLBACK GPU_init()
\r
415 memset(ulStatusControl,0,256*sizeof(unsigned long));
\r
418 iResX=240;iResY=320;
\r
427 iWinSize=MAKELONG(iResX,iResY);
\r
431 // different ways of accessing PSX VRAM
\r
433 psxVSecure=(u8 *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security
\r
434 if(!psxVSecure) return -1;
\r
436 psxVub=psxVSecure+512*1024; // security offset into double sized psx vram!
\r
437 psxVsb=(signed char *)psxVub;
\r
438 psxVsw=(signed short *)psxVub;
\r
439 psxVsl=(signed long *)psxVub;
\r
440 psxVuw=(unsigned short *)psxVub;
\r
441 psxVul=(unsigned long *)psxVub;
\r
443 psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram
\r
445 memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024));
\r
446 memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));
\r
448 InitFrameCap(); // init frame rate stuff
\r
450 PSXDisplay.RGB24 = 0; // init vars
\r
451 PreviousPSXDisplay.RGB24= 0;
\r
452 PSXDisplay.Interlaced = 0;
\r
453 PSXDisplay.InterlacedTest=0;
\r
454 PSXDisplay.DrawOffset.x = 0;
\r
455 PSXDisplay.DrawOffset.y = 0;
\r
456 PSXDisplay.DrawArea.x0 = 0;
\r
457 PSXDisplay.DrawArea.y0 = 0;
\r
458 PSXDisplay.DrawArea.x1 = 320;
\r
459 PSXDisplay.DrawArea.y1 = 240;
\r
460 PSXDisplay.DisplayMode.x= 320;
\r
461 PSXDisplay.DisplayMode.y= 240;
\r
462 PSXDisplay.Disabled = FALSE;
\r
463 PreviousPSXDisplay.Range.x0 =0;
\r
464 PreviousPSXDisplay.Range.x1 =0;
\r
465 PreviousPSXDisplay.Range.y0 =0;
\r
466 PreviousPSXDisplay.Range.y1 =0;
\r
467 PSXDisplay.Range.x0=0;
\r
468 PSXDisplay.Range.x1=0;
\r
469 PSXDisplay.Range.y0=0;
\r
470 PSXDisplay.Range.y1=0;
\r
471 PreviousPSXDisplay.DisplayPosition.x = 1;
\r
472 PreviousPSXDisplay.DisplayPosition.y = 1;
\r
473 PSXDisplay.DisplayPosition.x = 1;
\r
474 PSXDisplay.DisplayPosition.y = 1;
\r
475 PreviousPSXDisplay.DisplayModeNew.y=0;
\r
476 PSXDisplay.Double=1;
\r
479 PSXDisplay.DisplayModeNew.x=0;
\r
480 PSXDisplay.DisplayModeNew.y=0;
\r
482 //PreviousPSXDisplay.Height = PSXDisplay.Height = 239;
\r
484 iDataWriteMode = DR_NORMAL;
\r
486 // Reset transfer values, to prevent mis-transfer of data
\r
487 memset(&VRAMWrite,0,sizeof(VRAMLoad_t));
\r
488 memset(&VRAMRead,0,sizeof(VRAMLoad_t));
\r
490 // device initialised already !
\r
491 //lGPUstatusRet = 0x74000000;
\r
493 STATUSREG = 0x14802000;
\r
495 GPUIsReadyForCommands;
\r
501 ////////////////////////////////////////////////////////////////////////
\r
502 // GPU OPEN: funcs to open up the gpu display (Windows)
\r
503 ////////////////////////////////////////////////////////////////////////
\r
507 void ChangeDesktop() // change destop resolution
\r
509 DEVMODE dv;long lRes,iTry=0;
\r
511 while(iTry<10) // keep on hammering...
\r
513 memset(&dv,0,sizeof(DEVMODE));
\r
514 dv.dmSize=sizeof(DEVMODE);
\r
515 dv.dmBitsPerPel=iColDepth;
\r
516 dv.dmPelsWidth=iResX;
\r
517 dv.dmPelsHeight=iResY;
\r
519 dv.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
\r
521 lRes=ChangeDisplaySettings(&dv,0); // ...hammering the anvil
\r
523 if(lRes==DISP_CHANGE_SUCCESSFUL) return;
\r
528 ////////////////////////////////////////////////////////////////////////
\r
529 // OPEN interface func: attention!
\r
530 // some emus are calling this func in their main Window thread,
\r
531 // but all other interface funcs (to draw stuff) in a different thread!
\r
532 // that's a problem, since OGL is thread safe! Therefore we cannot
\r
533 // initialize the OGL stuff right here, we simply set a "bIsFirstFrame = TRUE"
\r
534 // flag, to initialize OGL on the first real draw call.
\r
535 // btw, we also call this open func ourselfes, each time when the user
\r
536 // is changing between fullscreen/window mode (ENTER key)
\r
537 // btw part 2: in windows the plugin gets the window handle from the
\r
538 // main emu, and doesn't create it's own window (if it would do it,
\r
539 // some PAD or SPU plugins would not work anymore)
\r
540 ////////////////////////////////////////////////////////////////////////
\r
542 HMENU hPSEMenu=NULL;
\r
544 long CALLBACK GPUopen(HWND hwndGPU)
\r
546 long CALLBACK GPU_open(int hwndGPU)
\r
550 HDC hdc;RECT r;DEVMODE dv;
\r
552 hWWindow = hwndGPU; // store hwnd globally
\r
554 // InitKeyHandler(); // init key handler (subclass window)
\r
561 iResX=240;iResY=320;
\r
572 // bAdvancedBlend=FALSE;
\r
574 // bUseLines=FALSE;
\r
575 bUseFrameLimit=FALSE;
\r
576 bUseFrameSkip=FALSE;
\r
579 iOffscreenDrawing=0;
\r
580 //bOpaquePass=FALSE;
\r
581 //bUseAntiAlias=FALSE;
\r
584 iWinSize=MAKELONG(iResX,iResY);
\r
588 bUseFastMdec=FALSE;
\r
589 bUse15bitMdec=FALSE;
\r
592 // iUseScanLines=0;
\r
599 iTexGarbageCollection=0;
\r
601 //iHiResTextures=0;
\r
608 memset(&dv,0,sizeof(DEVMODE));
\r
609 dv.dmSize=sizeof(DEVMODE);
\r
610 EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv);
\r
612 bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows!
\r
615 if(bWindowMode) // win mode?
\r
617 DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers)
\r
618 dw&=~WS_THICKFRAME;
\r
619 dw|=WS_BORDER|WS_CAPTION|CS_OWNDC;
\r
620 SetWindowLong(hWWindow, GWL_STYLE, dw);
\r
622 hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any)
\r
623 if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);
\r
625 iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize);
\r
626 ShowWindow(hWWindow,SW_SHOWNORMAL);
\r
628 MoveWindow(hWWindow, // -> center wnd
\r
629 GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2,
\r
630 GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2,
\r
631 iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3,
\r
632 iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3,
\r
634 UpdateWindow(hWWindow); // -> let windows do some update
\r
636 if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info
\r
637 iColDepth=dv.dmBitsPerPel;
\r
639 else // fullscreen mode:
\r
641 if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution
\r
642 dv.dmPelsWidth !=(unsigned int)iResX ||
\r
643 dv.dmPelsHeight!=(unsigned int)iResY)
\r
644 bChangeRes=TRUE; else bChangeRes=FALSE;
\r
646 if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations')
\r
648 SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure)
\r
650 hPSEMenu=GetMenu(hWWindow); // -> hide menu
\r
651 if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);
\r
652 ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode
\r
655 rRatioRect.left = rRatioRect.top=0;
\r
656 rRatioRect.right = iResX;
\r
657 rRatioRect.bottom = iResY;
\r
660 r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized
\r
661 hdc = GetDC(hWWindow);
\r
662 FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH));
\r
663 bSetupPixelFormat(hdc);
\r
664 ReleaseDC(hWWindow,hdc);
\r
666 bDisplayNotSet = TRUE;
\r
669 SetFixes(); // setup game fixes
\r
671 InitializeTextureStore(); // init texture mem
\r
673 // lGPUstatusRet = 0x74000000;
\r
675 // with some emus, we could do the OGL init right here... oh my
\r
676 // if(bIsFirstFrame) GLinitialize();
\r
681 ////////////////////////////////////////////////////////////////////////
\r
683 ////////////////////////////////////////////////////////////////////////
\r
686 long CALLBACK GPUclose() // WINDOWS CLOSE
\r
688 // ExitKeyHandler();
\r
690 GLcleanup(); // close OGL
\r
692 if(bChangeRes) // change res back
\r
693 ChangeDisplaySettings(NULL,0);
\r
695 if(hPSEMenu) // set menu again
\r
696 SetMenu(hWWindow,hPSEMenu);
\r
698 if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory
\r
701 // if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again
\r
708 long GPU_close() // LINUX CLOSE
\r
710 GLcleanup(); // close OGL
\r
712 if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory
\r
715 // osd_close_display(); // destroy display
\r
721 ////////////////////////////////////////////////////////////////////////
\r
722 // I shot the sheriff... last function called from emu
\r
723 ////////////////////////////////////////////////////////////////////////
\r
726 long CALLBACK GPUshutdown()
\r
728 long CALLBACK GPU_shutdown()
\r
731 if(psxVSecure) free(psxVSecure); // kill emulated vram memory
\r
737 ////////////////////////////////////////////////////////////////////////
\r
738 // paint it black: simple func to clean up optical border garbage
\r
739 ////////////////////////////////////////////////////////////////////////
\r
741 void PaintBlackBorders(void)
\r
745 glDisable(GL_SCISSOR_TEST);
\r
746 if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;}
\r
747 if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;}
\r
748 if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;}
\r
749 glDisable(GL_ALPHA_TEST);
\r
751 glEnable(GL_ALPHA_TEST);
\r
752 glEnable(GL_SCISSOR_TEST);
\r
755 ////////////////////////////////////////////////////////////////////////
\r
756 // helper to draw scanlines
\r
757 ////////////////////////////////////////////////////////////////////////
\r
759 __inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2,
\r
760 OGLVertex* vertex3, OGLVertex* vertex4)
\r
765 ////////////////////////////////////////////////////////////////////////
\r
767 ////////////////////////////////////////////////////////////////////////
\r
769 void SetScanLines(void)
\r
773 ////////////////////////////////////////////////////////////////////////
\r
774 // blur, babe, blur (heavy performance hit for a so-so fullscreen effect)
\r
775 ////////////////////////////////////////////////////////////////////////
\r
778 ////////////////////////////////////////////////////////////////////////
\r
779 // Update display (swap buffers)... called in interlaced mode on
\r
780 // every emulated vsync, otherwise whenever the displayed screen region
\r
781 // has been changed
\r
782 ////////////////////////////////////////////////////////////////////////
\r
784 int iLastRGB24=0; // special vars for checking when to skip two display updates
\r
786 void GPU_vSinc(void){
\r
789 void updateDisplay(void) // UPDATE DISPLAY
\r
794 HDC hdc=GetDC(hWWindow); // windows:
\r
795 wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again
\r
798 bFakeFrontBuffer=FALSE;
\r
799 bRenderFrontBuffer=FALSE;
\r
801 if(iRenderFVR) // frame buffer read fix mode still active?
\r
803 iRenderFVR--; // -> if some frames in a row without read access: turn off mode
\r
804 if(!iRenderFVR) bFullVRam=FALSE;
\r
807 if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check
\r
809 iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes
\r
813 if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted?
\r
815 PrepareFullScreenUpload(-1);
\r
816 UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram
\r
817 bNeedUploadTest=FALSE;
\r
818 bNeedInterlaceUpdate=FALSE;
\r
819 bNeedUploadAfter=FALSE;
\r
820 bNeedRGB24Update=FALSE;
\r
823 if(bNeedInterlaceUpdate) // smaller upload?
\r
825 bNeedInterlaceUpdate=FALSE;
\r
826 xrUploadArea=xrUploadAreaIL; // -> upload this rect
\r
827 UploadScreen(TRUE);
\r
830 if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9
\r
832 if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed
\r
833 PreviousPSXDisplay.Range.y0)
\r
834 PaintBlackBorders();
\r
836 if(PSXDisplay.Disabled) // display disabled?
\r
839 glDisable(GL_SCISSOR_TEST);
\r
840 glClearColor(0,0,0,128); // -> clear whole backbuffer
\r
841 glClear(uiBufferBits);
\r
842 glEnable(GL_SCISSOR_TEST);
\r
844 bDisplayNotSet = TRUE;
\r
847 if(iSkipTwo) // we are in skipping mood?
\r
850 iDrawnSomething=0; // -> simply lie about something drawn
\r
853 //if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated?
\r
854 // {BlurBackBuffer();bBlur=TRUE;} // -> blur it
\r
856 // if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it
\r
858 // if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em
\r
860 if(dwActFixes&128) // special FPS limitation mode?
\r
862 if(bUseFrameLimit) PCFrameCap(); // -> ok, do it
\r
863 // if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS)
\r
867 // if(gTexPicName) DisplayPic(); // some gpu info picture active? display it
\r
869 // if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :)
\r
871 // if(ulKeybits&KEY_SHOWFPS) // wanna see FPS?
\r
873 // sprintf(szDispBuf,"%06.1f",fps_cur);
\r
874 // DisplayText(); // -> show it
\r
877 //----------------------------------------------------//
\r
878 // main buffer swapping (well, or skip it)
\r
880 if(bUseFrameSkip) // frame skipping active ?
\r
882 if(!bSkipNextFrame)
\r
884 if(iDrawnSomething)
\r
886 SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip
\r
888 eglSwapBuffers(display,surface);
\r
891 if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row
\r
893 if((fps_skip < fFrameRateHz) && !(bSkipNextFrame))
\r
894 {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}
\r
895 else bSkipNextFrame = FALSE;
\r
901 if(iDrawnSomething)
\r
903 SwapBuffers(wglGetCurrentDC()); // -> swap
\r
905 eglSwapBuffers(display,surface);
\r
911 //----------------------------------------------------//
\r
913 if(lClearOnSwap) // clear buffer after swap?
\r
917 if(bDisplayNotSet) // -> set new vals
\r
918 SetOGLDisplaySettings(1);
\r
920 g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col
\r
921 b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f;
\r
922 r=((GLclampf)RED(lClearOnSwapColor))/255.0f;
\r
924 glDisable(GL_SCISSOR_TEST);
\r
925 glClearColor(r,g,b,128); // -> clear
\r
926 glClear(uiBufferBits);
\r
927 glEnable(GL_SCISSOR_TEST);
\r
928 lClearOnSwap=0; // -> done
\r
932 // if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before
\r
934 if(iZBufferDepth) // clear zbuffer as well (if activated)
\r
936 glDisable(GL_SCISSOR_TEST);
\r
937 glClear(GL_DEPTH_BUFFER_BIT);
\r
938 glEnable(GL_SCISSOR_TEST);
\r
943 //----------------------------------------------------//
\r
944 // additional uploads immediatly after swapping
\r
946 if(bNeedUploadAfter) // upload wanted?
\r
948 bNeedUploadAfter=FALSE;
\r
949 bNeedUploadTest=FALSE;
\r
950 UploadScreen(-1); // -> upload
\r
953 if(bNeedUploadTest)
\r
955 bNeedUploadTest=FALSE;
\r
956 if(PSXDisplay.InterlacedTest &&
\r
957 //iOffscreenDrawing>2 &&
\r
958 PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x &&
\r
959 PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x &&
\r
960 PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y &&
\r
961 PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y)
\r
963 PrepareFullScreenUpload(TRUE);
\r
964 UploadScreen(TRUE);
\r
968 //----------------------------------------------------//
\r
969 // rumbling (main emu pad effect)
\r
971 if(iRumbleTime) // shake screen by modifying view port
\r
973 int i1=0,i2=0,i3=0,i4=0;
\r
978 i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
979 i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
980 i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
981 i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
984 glViewport(rRatioRect.left+i1,
\r
985 iResY-(rRatioRect.top+rRatioRect.bottom)+i2,
\r
986 rRatioRect.right+i3,
\r
987 rRatioRect.bottom+i4);
\r
990 //----------------------------------------------------//
\r
994 // if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled
\r
997 ////////////////////////////////////////////////////////////////////////
\r
998 // update front display: smaller update func, if something has changed
\r
999 // in the frontbuffer... dirty, but hey... real men know no pain
\r
1000 ////////////////////////////////////////////////////////////////////////
\r
1002 void updateFrontDisplay(void)
\r
1004 if(PreviousPSXDisplay.Range.x0||
\r
1005 PreviousPSXDisplay.Range.y0)
\r
1006 PaintBlackBorders();
\r
1008 //if(iBlurBuffer) BlurBackBuffer();
\r
1010 //if(iUseScanLines) SetScanLines();
\r
1012 // if(usCursorActive) ShowGunCursor();
\r
1014 bFakeFrontBuffer=FALSE;
\r
1015 bRenderFrontBuffer=FALSE;
\r
1017 // if(gTexPicName) DisplayPic();
\r
1018 // if(ulKeybits&KEY_SHOWFPS) DisplayText();
\r
1022 HDC hdc=GetDC(hWWindow);
\r
1023 wglMakeCurrent(hdc,GLCONTEXT); // -> make current again
\r
1024 if(iDrawnSomething)
\r
1025 SwapBuffers(wglGetCurrentDC()); // -> swap
\r
1026 ReleaseDC(hWWindow,hdc); // -> ! important !
\r
1029 if(iDrawnSomething) // linux:
\r
1030 eglSwapBuffers(display,surface);
\r
1033 //if(iBlurBuffer) UnBlurBackBuffer();
\r
1036 ////////////////////////////////////////////////////////////////////////
\r
1037 // check if update needed
\r
1038 ////////////////////////////////////////////////////////////////////////
\r
1039 void ChangeDispOffsetsX(void) // CENTER X
\r
1041 long lx,l;short sO;
\r
1043 if(!PSXDisplay.Range.x1) return; // some range given?
\r
1045 l=PSXDisplay.DisplayMode.x;
\r
1047 l*=(long)PSXDisplay.Range.x1; // some funky calculation
\r
1048 l/=2560;lx=l;l&=0xfffffff8;
\r
1050 if(l==PreviousPSXDisplay.Range.x1) return; // some change?
\r
1052 sO=PreviousPSXDisplay.Range.x0; // store old
\r
1054 if(lx>=PSXDisplay.DisplayMode.x) // range bigger?
\r
1056 PreviousPSXDisplay.Range.x1= // -> take display width
\r
1057 PSXDisplay.DisplayMode.x;
\r
1058 PreviousPSXDisplay.Range.x0=0; // -> start pos is 0
\r
1060 else // range smaller? center it
\r
1062 PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned)
\r
1063 PreviousPSXDisplay.Range.x0= // -> calc start pos
\r
1064 (PSXDisplay.Range.x0-500)/8;
\r
1065 if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet
\r
1066 PreviousPSXDisplay.Range.x0=0;
\r
1068 if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much
\r
1069 PSXDisplay.DisplayMode.x)
\r
1071 PreviousPSXDisplay.Range.x0= // -> adjust start
\r
1072 PSXDisplay.DisplayMode.x-lx;
\r
1073 PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width
\r
1077 if(sO!=PreviousPSXDisplay.Range.x0) // something changed?
\r
1079 bDisplayNotSet=TRUE; // -> recalc display stuff
\r
1083 ////////////////////////////////////////////////////////////////////////
\r
1085 void ChangeDispOffsetsY(void) // CENTER Y
\r
1087 int iT;short sO; // store previous y size
\r
1089 if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC
\r
1091 if(PSXDisplay.Range.y0>=iT) // crossed the security line? :)
\r
1093 PreviousPSXDisplay.Range.y1= // -> store width
\r
1094 PSXDisplay.DisplayModeNew.y;
\r
1096 sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset
\r
1099 PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too
\r
1101 else sO=0; // else no offset
\r
1103 if(sO!=PreviousPSXDisplay.Range.y0) // something changed?
\r
1105 PreviousPSXDisplay.Range.y0=sO;
\r
1106 bDisplayNotSet=TRUE; // -> recalc display stuff
\r
1110 ////////////////////////////////////////////////////////////////////////
\r
1111 // Aspect ratio of ogl screen: simply adjusting ogl view port
\r
1112 ////////////////////////////////////////////////////////////////////////
\r
1114 void SetAspectRatio(void)
\r
1116 float xs,ys,s;RECT r;
\r
1118 if(!PSXDisplay.DisplayModeNew.x) return;
\r
1119 if(!PSXDisplay.DisplayModeNew.y) return;
\r
1121 xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x;
\r
1122 ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y;
\r
1125 r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s);
\r
1126 r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s);
\r
1127 if(r.right > iResX) r.right = iResX;
\r
1128 if(r.bottom > iResY) r.bottom = iResY;
\r
1129 if(r.right < 1) r.right = 1;
\r
1130 if(r.bottom < 1) r.bottom = 1;
\r
1132 r.left = (iResX-r.right)/2;
\r
1133 r.top = (iResY-r.bottom)/2;
\r
1135 if(r.bottom<rRatioRect.bottom ||
\r
1136 r.right <rRatioRect.right)
\r
1139 glClearColor(0,0,0,128);
\r
1141 if(r.right <rRatioRect.right)
\r
1147 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1148 glClear(uiBufferBits);
\r
1149 rC.left=iResX-rC.right;
\r
1150 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1151 glClear(uiBufferBits);
\r
1154 if(r.bottom <rRatioRect.bottom)
\r
1160 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1161 glClear(uiBufferBits);
\r
1162 rC.top=iResY-rC.bottom;
\r
1163 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1164 glClear(uiBufferBits);
\r
1168 bDisplayNotSet=TRUE;
\r
1174 glViewport(rRatioRect.left,
\r
1175 iResY-(rRatioRect.top+rRatioRect.bottom),
\r
1177 rRatioRect.bottom); // init viewport
\r
1180 ////////////////////////////////////////////////////////////////////////
\r
1181 // big ass check, if an ogl swap buffer is needed
\r
1182 ////////////////////////////////////////////////////////////////////////
\r
1184 void updateDisplayIfChanged(void)
\r
1188 if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) &&
\r
1189 (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))
\r
1191 if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) &&
\r
1192 (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew))
\r
1193 return; // nothing has changed? fine, no swap buffer needed
\r
1195 else // some res change?
\r
1198 glOrtho(0,PSXDisplay.DisplayModeNew.x, // -> new psx resolution
\r
1199 PSXDisplay.DisplayModeNew.y, 0, -1, 1);
\r
1200 if(bKeepRatio) SetAspectRatio();
\r
1203 bDisplayNotSet = TRUE; // re-calc offsets/display area
\r
1206 if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off)
\r
1208 PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet
\r
1209 ResetTextureArea(FALSE);
\r
1213 PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos
\r
1214 PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;
\r
1215 PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;
\r
1216 PSXDisplay.Interlaced = PSXDisplay.InterlacedNew;
\r
1218 PSXDisplay.DisplayEnd.x= // calc new ends
\r
1219 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1220 PSXDisplay.DisplayEnd.y=
\r
1221 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1222 PreviousPSXDisplay.DisplayEnd.x=
\r
1223 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1224 PreviousPSXDisplay.DisplayEnd.y=
\r
1225 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1227 ChangeDispOffsetsX();
\r
1229 if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace)
\r
1231 if(bUp) updateDisplay(); // yeah, real update (swap buffer)
\r
1234 ////////////////////////////////////////////////////////////////////////
\r
1235 // window mode <-> fullscreen mode (windows)
\r
1236 ////////////////////////////////////////////////////////////////////////
\r
1239 void ChangeWindowMode(void)
\r
1242 bWindowMode=!bWindowMode;
\r
1243 GPUopen(hWWindow);
\r
1244 bChangeWinMode=FALSE;
\r
1248 ////////////////////////////////////////////////////////////////////////
\r
1249 // swap update check (called by psx vsync function)
\r
1250 ////////////////////////////////////////////////////////////////////////
\r
1252 BOOL bSwapCheck(void)
\r
1254 static int iPosCheck=0;
\r
1255 static PSXPoint_t pO;
\r
1256 static PSXPoint_t pD;
\r
1257 static int iDoAgain=0;
\r
1259 if(PSXDisplay.DisplayPosition.x==pO.x &&
\r
1260 PSXDisplay.DisplayPosition.y==pO.y &&
\r
1261 PSXDisplay.DisplayEnd.x==pD.x &&
\r
1262 PSXDisplay.DisplayEnd.y==pD.y)
\r
1266 pO=PSXDisplay.DisplayPosition;
\r
1267 pD=PSXDisplay.DisplayEnd;
\r
1269 if(iPosCheck<=4) return FALSE;
\r
1273 if(PSXDisplay.Interlaced) return FALSE;
\r
1275 if (bNeedInterlaceUpdate||
\r
1276 bNeedRGB24Update ||
\r
1277 bNeedUploadAfter||
\r
1278 bNeedUploadTest ||
\r
1283 if(bNeedUploadAfter)
\r
1285 if(bNeedUploadTest && PSXDisplay.InterlacedTest)
\r
1288 bDisplayNotSet = TRUE;
\r
1291 PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x;
\r
1292 PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y;
\r
1293 PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x;
\r
1294 PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y;
\r
1295 pO=PSXDisplay.DisplayPosition;
\r
1296 pD=PSXDisplay.DisplayEnd;
\r
1303 ////////////////////////////////////////////////////////////////////////
\r
1304 // gun cursor func: player=0-7, x=0-511, y=0-255
\r
1305 ////////////////////////////////////////////////////////////////////////
\r
1307 ////////////////////////////////////////////////////////////////////////
\r
1308 // update lace is called every VSync. Basically we limit frame rate
\r
1309 // here, and in interlaced mode we swap ogl display buffers.
\r
1310 ////////////////////////////////////////////////////////////////////////
\r
1312 static unsigned short usFirstPos=2;
\r
1315 void CALLBACK GPUupdateLace(void)
\r
1317 void CALLBACK GPU_updateLace(void)
\r
1320 if(!(dwActFixes&0x1000))
\r
1321 STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus)
\r
1323 if(!(dwActFixes&128)) // normal frame limit func
\r
1326 if(iOffscreenDrawing==4) // special check if high offscreen drawing is on
\r
1328 if(bSwapCheck()) return;
\r
1331 if(PSXDisplay.Interlaced) // interlaced mode?
\r
1333 if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)
\r
1335 updateDisplay(); // -> swap buffers (new frame)
\r
1338 else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed?
\r
1340 updateFrontDisplay(); // -> update front buffer
\r
1342 else if(usFirstPos==1) // initial updates (after startup)
\r
1348 if(bChangeWinMode) ChangeWindowMode();
\r
1352 ////////////////////////////////////////////////////////////////////////
\r
1353 // process read request from GPU status register
\r
1354 ////////////////////////////////////////////////////////////////////////
\r
1357 unsigned long CALLBACK GPUreadStatus(void)
\r
1359 unsigned long CALLBACK GPU_readStatus(void)
\r
1362 if(dwActFixes&0x1000) // CC game fix
\r
1364 static int iNumRead=0;
\r
1365 if((iNumRead++)==2)
\r
1368 STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross)
\r
1372 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
1376 if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims
\r
1379 GPUIsNotReadyForCommands;
\r
1384 GPUIsReadyForCommands;
\r
1391 ////////////////////////////////////////////////////////////////////////
\r
1392 // processes data send to GPU status register
\r
1393 // these are always single packet commands.
\r
1394 ////////////////////////////////////////////////////////////////////////
\r
1397 void CALLBACK GPUwriteStatus(unsigned long gdata)
\r
1399 void CALLBACK GPU_writeStatus(unsigned long gdata)
\r
1402 unsigned long lCommand=(gdata>>24)&0xff;
\r
1405 if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus)
\r
1408 ulStatusControl[lCommand]=gdata;
\r
1412 //--------------------------------------------------//
\r
1415 memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));
\r
1416 lGPUstatusRet=0x14802000;
\r
1417 PSXDisplay.Disabled=1;
\r
1418 iDataWriteMode=iDataReadMode=DR_NORMAL;
\r
1419 PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;
\r
1420 drawX=drawY=0;drawW=drawH=0;
\r
1421 sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0;
\r
1423 GlobalTextAddrX=0;GlobalTextAddrY=0;
\r
1424 GlobalTextTP=0;GlobalTextABR=0;
\r
1425 PSXDisplay.RGB24=FALSE;
\r
1426 PSXDisplay.Interlaced=FALSE;
\r
1427 bUsingTWin = FALSE;
\r
1430 // dis/enable display
\r
1432 PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;
\r
1433 PSXDisplay.Disabled = (gdata & 1);
\r
1435 if(PSXDisplay.Disabled)
\r
1436 STATUSREG|=GPUSTATUS_DISPLAYDISABLED;
\r
1437 else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED;
\r
1439 if (iOffscreenDrawing==4 &&
\r
1440 PreviousPSXDisplay.Disabled &&
\r
1441 !(PSXDisplay.Disabled))
\r
1444 if(!PSXDisplay.RGB24)
\r
1446 PrepareFullScreenUpload(TRUE);
\r
1447 UploadScreen(TRUE);
\r
1454 // setting transfer mode
\r
1456 gdata &= 0x03; // only want the lower two bits
\r
1458 iDataWriteMode=iDataReadMode=DR_NORMAL;
\r
1459 if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER;
\r
1460 if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER;
\r
1462 STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits
\r
1463 STATUSREG|=(gdata << 29); // set the DMA bits according to the received data
\r
1467 // setting display position
\r
1470 short sx=(short)(gdata & 0x3ff);
\r
1473 if(iGPUHeight==1024)
\r
1475 if(dwGPUVersion==2)
\r
1476 sy = (short)((gdata>>12)&0x3ff);
\r
1477 else sy = (short)((gdata>>10)&0x3ff);
\r
1479 else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later
\r
1484 PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double;
\r
1487 else PreviousPSXDisplay.DisplayModeNew.y=0;
\r
1496 PreviousPSXDisplay.DisplayPosition.x = sx;
\r
1497 PreviousPSXDisplay.DisplayPosition.y = sy;
\r
1498 PSXDisplay.DisplayPosition.x = sx;
\r
1499 PSXDisplay.DisplayPosition.y = sy;
\r
1505 if((!PSXDisplay.Interlaced) &&
\r
1506 PreviousPSXDisplay.DisplayPosition.x == sx &&
\r
1507 PreviousPSXDisplay.DisplayPosition.y == sy)
\r
1510 PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x;
\r
1511 PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y;
\r
1512 PreviousPSXDisplay.DisplayPosition.x = sx;
\r
1513 PreviousPSXDisplay.DisplayPosition.y = sy;
\r
1517 if((!PSXDisplay.Interlaced) &&
\r
1518 PSXDisplay.DisplayPosition.x == sx &&
\r
1519 PSXDisplay.DisplayPosition.y == sy)
\r
1521 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
\r
1522 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
\r
1523 PSXDisplay.DisplayPosition.x = sx;
\r
1524 PSXDisplay.DisplayPosition.y = sy;
\r
1527 PSXDisplay.DisplayEnd.x=
\r
1528 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1529 PSXDisplay.DisplayEnd.y=
\r
1530 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1532 PreviousPSXDisplay.DisplayEnd.x=
\r
1533 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1534 PreviousPSXDisplay.DisplayEnd.y=
\r
1535 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1537 bDisplayNotSet = TRUE;
\r
1539 if (!(PSXDisplay.Interlaced))
\r
1544 if(PSXDisplay.InterlacedTest &&
\r
1545 ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)||
\r
1546 (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y)))
\r
1547 PSXDisplay.InterlacedTest--;
\r
1555 PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff;
\r
1556 PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff;
\r
1558 PSXDisplay.Range.x1-=PSXDisplay.Range.x0;
\r
1560 ChangeDispOffsetsX();
\r
1567 PreviousPSXDisplay.Height = PSXDisplay.Height;
\r
1569 PSXDisplay.Range.y0=gdata & 0x3ff;
\r
1570 PSXDisplay.Range.y1=(gdata>>10) & 0x3ff;
\r
1572 PSXDisplay.Height = PSXDisplay.Range.y1 -
\r
1573 PSXDisplay.Range.y0 +
\r
1574 PreviousPSXDisplay.DisplayModeNew.y;
\r
1576 if (PreviousPSXDisplay.Height != PSXDisplay.Height)
\r
1578 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
\r
1579 ChangeDispOffsetsY();
\r
1580 updateDisplayIfChanged();
\r
1584 // setting display infos
\r
1587 PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];
\r
1589 if (gdata&0x04) PSXDisplay.Double=2;
\r
1590 else PSXDisplay.Double=1;
\r
1591 PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;
\r
1593 ChangeDispOffsetsY();
\r
1595 PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC
\r
1596 PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor
\r
1597 PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace
\r
1599 STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits
\r
1602 (((gdata & 0x03) << 17) |
\r
1603 ((gdata & 0x40) << 10)); // set the width bits
\r
1605 PreviousPSXDisplay.InterlacedNew=FALSE;
\r
1606 if (PSXDisplay.InterlacedNew)
\r
1608 if(!PSXDisplay.Interlaced)
\r
1610 PSXDisplay.InterlacedTest=2;
\r
1611 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
\r
1612 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
\r
1613 PreviousPSXDisplay.InterlacedNew=TRUE;
\r
1616 STATUSREG|=GPUSTATUS_INTERLACED;
\r
1620 PSXDisplay.InterlacedTest=0;
\r
1621 STATUSREG&=~GPUSTATUS_INTERLACED;
\r
1624 if (PSXDisplay.PAL)
\r
1625 STATUSREG|=GPUSTATUS_PAL;
\r
1626 else STATUSREG&=~GPUSTATUS_PAL;
\r
1628 if (PSXDisplay.Double==2)
\r
1629 STATUSREG|=GPUSTATUS_DOUBLEHEIGHT;
\r
1630 else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT;
\r
1632 if (PSXDisplay.RGB24New)
\r
1633 STATUSREG|=GPUSTATUS_RGB24;
\r
1634 else STATUSREG&=~GPUSTATUS_RGB24;
\r
1636 updateDisplayIfChanged();
\r
1640 //--------------------------------------------------//
\r
1641 // ask about GPU version and other stuff
\r
1649 GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos
\r
1652 GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start
\r
1655 GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end
\r
1659 GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset
\r
1662 if(dwGPUVersion==2)
\r
1664 else GPUdataRet=0x02; // gpu type
\r
1667 case 0x0F: // some bios addr?
\r
1668 GPUdataRet=0xBFC03720;
\r
1672 //--------------------------------------------------//
\r
1676 ////////////////////////////////////////////////////////////////////////
\r
1677 // vram read/write helpers
\r
1678 ////////////////////////////////////////////////////////////////////////
\r
1680 BOOL bNeedWriteUpload=FALSE;
\r
1682 __inline void FinishedVRAMWrite(void)
\r
1684 if(bNeedWriteUpload)
\r
1686 bNeedWriteUpload=FALSE;
\r
1687 CheckWriteUpdate();
\r
1690 // set register to NORMAL operation
\r
1691 iDataWriteMode = DR_NORMAL;
\r
1693 // reset transfer values, to prevent mis-transfer of data
\r
1694 VRAMWrite.ColsRemaining = 0;
\r
1695 VRAMWrite.RowsRemaining = 0;
\r
1698 __inline void FinishedVRAMRead(void)
\r
1700 // set register to NORMAL operation
\r
1701 iDataReadMode = DR_NORMAL;
\r
1702 // reset transfer values, to prevent mis-transfer of data
\r
1705 VRAMRead.Width = 0;
\r
1706 VRAMRead.Height = 0;
\r
1707 VRAMRead.ColsRemaining = 0;
\r
1708 VRAMRead.RowsRemaining = 0;
\r
1710 // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER
\r
1711 STATUSREG&=~GPUSTATUS_READYFORVRAM;
\r
1714 ////////////////////////////////////////////////////////////////////////
\r
1715 // vram read check ex (reading from card's back/frontbuffer if needed...
\r
1717 ////////////////////////////////////////////////////////////////////////
\r
1719 void CheckVRamReadEx(int x, int y, int dx, int dy)
\r
1721 unsigned short sArea;
\r
1722 int ux,uy,udx,udy,wx,wy;
\r
1723 unsigned short * p1, *p2;
\r
1727 unsigned short s,sx;
\r
1729 if(STATUSREG&GPUSTATUS_RGB24) return;
\r
1731 if(((dx > PSXDisplay.DisplayPosition.x) &&
\r
1732 (x < PSXDisplay.DisplayEnd.x) &&
\r
1733 (dy > PSXDisplay.DisplayPosition.y) &&
\r
1734 (y < PSXDisplay.DisplayEnd.y)))
\r
1737 if((!(PSXDisplay.InterlacedTest) &&
\r
1738 (dx > PreviousPSXDisplay.DisplayPosition.x) &&
\r
1739 (x < PreviousPSXDisplay.DisplayEnd.x) &&
\r
1740 (dy > PreviousPSXDisplay.DisplayPosition.y) &&
\r
1741 (y < PreviousPSXDisplay.DisplayEnd.y)))
\r
1752 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1754 bFullVRam=TRUE;iRenderFVR=2;
\r
1762 ux=PSXDisplay.DisplayPosition.x;
\r
1763 uy=PSXDisplay.DisplayPosition.y;
\r
1764 udx=PSXDisplay.DisplayEnd.x-ux;
\r
1765 udy=PSXDisplay.DisplayEnd.y-uy;
\r
1766 if((PreviousPSXDisplay.DisplayEnd.x-
\r
1767 PreviousPSXDisplay.DisplayPosition.x)==udx &&
\r
1768 (PreviousPSXDisplay.DisplayEnd.y-
\r
1769 PreviousPSXDisplay.DisplayPosition.y)==udy)
\r
1770 p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) +
\r
1771 PreviousPSXDisplay.DisplayPosition.x);
\r
1775 ux=PreviousPSXDisplay.DisplayPosition.x;
\r
1776 uy=PreviousPSXDisplay.DisplayPosition.y;
\r
1777 udx=PreviousPSXDisplay.DisplayEnd.x-ux;
\r
1778 udy=PreviousPSXDisplay.DisplayEnd.y-uy;
\r
1779 if((PSXDisplay.DisplayEnd.x-
\r
1780 PSXDisplay.DisplayPosition.x)==udx &&
\r
1781 (PSXDisplay.DisplayEnd.y-
\r
1782 PSXDisplay.DisplayPosition.y)==udy)
\r
1783 p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) +
\r
1784 PSXDisplay.DisplayPosition.x);
\r
1787 p1=(psxVuw + (1024*uy) + ux);
\r
1791 wx=dx=udx;wy=dy=udy;
\r
1793 if(udx<=0) return;
\r
1794 if(udy<=0) return;
\r
1800 XS=(float)rRatioRect.right/(float)wx;
\r
1801 YS=(float)rRatioRect.bottom/(float)wy;
\r
1803 dx=(int)((float)(dx)*XS);
\r
1804 dy=(int)((float)(dy)*YS);
\r
1806 if(dx>iResX) dx=iResX;
\r
1807 if(dy>iResY) dy=iResY;
\r
1815 x+=rRatioRect.left;
\r
1816 y-=rRatioRect.top;
\r
1818 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1820 if(!pGfxCardScreen)
\r
1822 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1823 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);
\r
1826 ps=pGfxCardScreen;
\r
1828 //if(!sArea) glReadBuffer(GL_FRONT);
\r
1830 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1832 //if(!sArea) glReadBuffer(GL_BACK);
\r
1836 XS=(float)dx/(float)(udx);
\r
1837 YS=(float)dy/(float)(udy+1);
\r
1839 for(y=udy;y>0;y--)
\r
1841 for(x=0;x<udx;x++)
\r
1843 if(p1>=psxVuw && p1<psxVuw_eom)
\r
1845 px=ps+(3*((int)((float)x * XS))+
\r
1846 (3*dx)*((int)((float)y*YS)));
\r
1856 if(p2>=psxVuw && p2<psxVuw_eom) *p2=s;
\r
1863 if(p2) p2 += 1024 - udx;
\r
1867 ////////////////////////////////////////////////////////////////////////
\r
1868 // vram read check (reading from card's back/frontbuffer if needed...
\r
1870 ////////////////////////////////////////////////////////////////////////
\r
1872 void CheckVRamRead(int x, int y, int dx, int dy, bool bFront)
\r
1874 unsigned short sArea;unsigned short * p;
\r
1875 int ux,uy,udx,udy,wx,wy;float XS,YS;
\r
1877 unsigned short s=0,sx;
\r
1879 if(STATUSREG&GPUSTATUS_RGB24) return;
\r
1881 if(((dx > PSXDisplay.DisplayPosition.x) &&
\r
1882 (x < PSXDisplay.DisplayEnd.x) &&
\r
1883 (dy > PSXDisplay.DisplayPosition.y) &&
\r
1884 (y < PSXDisplay.DisplayEnd.y)))
\r
1887 if((!(PSXDisplay.InterlacedTest) &&
\r
1888 (dx > PreviousPSXDisplay.DisplayPosition.x) &&
\r
1889 (x < PreviousPSXDisplay.DisplayEnd.x) &&
\r
1890 (dy > PreviousPSXDisplay.DisplayPosition.y) &&
\r
1891 (y < PreviousPSXDisplay.DisplayEnd.y)))
\r
1898 if(dwActFixes&0x40)
\r
1902 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1904 bFullVRam=TRUE;iRenderFVR=2;
\r
1907 ux=x;uy=y;udx=dx;udy=dy;
\r
1911 x -=PSXDisplay.DisplayPosition.x;
\r
1912 dx-=PSXDisplay.DisplayPosition.x;
\r
1913 y -=PSXDisplay.DisplayPosition.y;
\r
1914 dy-=PSXDisplay.DisplayPosition.y;
\r
1915 wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x;
\r
1916 wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y;
\r
1920 x -=PreviousPSXDisplay.DisplayPosition.x;
\r
1921 dx-=PreviousPSXDisplay.DisplayPosition.x;
\r
1922 y -=PreviousPSXDisplay.DisplayPosition.y;
\r
1923 dy-=PreviousPSXDisplay.DisplayPosition.y;
\r
1924 wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x;
\r
1925 wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y;
\r
1927 if(x<0) {ux-=x;x=0;}
\r
1928 if(y<0) {uy-=y;y=0;}
\r
1929 if(dx>wx) {udx-=(dx-wx);dx=wx;}
\r
1930 if(dy>wy) {udy-=(dy-wy);dy=wy;}
\r
1934 p=(psxVuw + (1024*uy) + ux);
\r
1936 if(udx<=0) return;
\r
1937 if(udy<=0) return;
\r
1943 XS=(float)rRatioRect.right/(float)wx;
\r
1944 YS=(float)rRatioRect.bottom/(float)wy;
\r
1946 dx=(int)((float)(dx)*XS);
\r
1947 dy=(int)((float)(dy)*YS);
\r
1948 x=(int)((float)x*XS);
\r
1949 y=(int)((float)y*YS);
\r
1954 if(dx>iResX) dx=iResX;
\r
1955 if(dy>iResY) dy=iResY;
\r
1963 x+=rRatioRect.left;
\r
1964 y-=rRatioRect.top;
\r
1966 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1968 if(!pGfxCardScreen)
\r
1970 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1971 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);
\r
1974 ps=pGfxCardScreen;
\r
1976 // if(bFront) glReadBuffer(GL_FRONT);
\r
1978 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1980 // if(bFront) glReadBuffer(GL_BACK);
\r
1982 XS=(float)dx/(float)(udx);
\r
1983 YS=(float)dy/(float)(udy+1);
\r
1985 for(y=udy;y>0;y--)
\r
1987 for(x=0;x<udx;x++)
\r
1989 if(p>=psxVuw && p<psxVuw_eom)
\r
1991 px=ps+(3*((int)((float)x * XS))+
\r
1992 (3*dx)*((int)((float)y*YS)));
\r
2008 ////////////////////////////////////////////////////////////////////////
\r
2009 // core read from vram
\r
2010 ////////////////////////////////////////////////////////////////////////
\r
2013 void CALLBACK GPUreadDataMem(unsigned int * pMem, int iSize)
\r
2015 void CALLBACK GPU_readDataMem(unsigned long * pMem, int iSize)
\r
2020 if(iDataReadMode!=DR_VRAMTRANSFER) return;
\r
2024 // adjust read ptr, if necessary
\r
2025 while(VRAMRead.ImagePtr>=psxVuw_eom)
\r
2026 VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2027 while(VRAMRead.ImagePtr<psxVuw)
\r
2028 VRAMRead.ImagePtr+=iGPUHeight*1024;
\r
2030 if((iFrameReadType&1 && iSize>1) &&
\r
2031 !(iDrawnSomething==2 &&
\r
2032 VRAMRead.x == VRAMWrite.x &&
\r
2033 VRAMRead.y == VRAMWrite.y &&
\r
2034 VRAMRead.Width == VRAMWrite.Width &&
\r
2035 VRAMRead.Height == VRAMWrite.Height))
\r
2036 CheckVRamRead(VRAMRead.x,VRAMRead.y,
\r
2037 VRAMRead.x+VRAMRead.RowsRemaining,
\r
2038 VRAMRead.y+VRAMRead.ColsRemaining,
\r
2041 for(i=0;i<iSize;i++)
\r
2043 // do 2 seperate 16bit reads for compatibility (wrap issues)
\r
2044 if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))
\r
2047 GPUdataRet=(unsigned long)*VRAMRead.ImagePtr;
\r
2049 VRAMRead.ImagePtr++;
\r
2050 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2051 VRAMRead.RowsRemaining --;
\r
2053 if(VRAMRead.RowsRemaining<=0)
\r
2055 VRAMRead.RowsRemaining = VRAMRead.Width;
\r
2056 VRAMRead.ColsRemaining--;
\r
2057 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
\r
2058 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2061 // higher 16 bit (always, even if it's an odd width)
\r
2062 GPUdataRet|=(unsigned long)(*VRAMRead.ImagePtr)<<16;
\r
2063 *pMem++=GPUdataRet;
\r
2065 if(VRAMRead.ColsRemaining <= 0)
\r
2066 {FinishedVRAMRead();goto ENDREAD;}
\r
2068 VRAMRead.ImagePtr++;
\r
2069 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2070 VRAMRead.RowsRemaining--;
\r
2071 if(VRAMRead.RowsRemaining<=0)
\r
2073 VRAMRead.RowsRemaining = VRAMRead.Width;
\r
2074 VRAMRead.ColsRemaining--;
\r
2075 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
\r
2076 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2078 if(VRAMRead.ColsRemaining <= 0)
\r
2079 {FinishedVRAMRead();goto ENDREAD;}
\r
2081 else {FinishedVRAMRead();goto ENDREAD;}
\r
2089 unsigned long CALLBACK GPUreadData(void)
\r
2091 unsigned long CALLBACK GPU_readData(void)
\r
2096 GPUreadDataMem(&l,1);
\r
2098 GPU_readDataMem(&l,1);
\r
2100 return GPUdataRet;
\r
2103 ////////////////////////////////////////////////////////////////////////
\r
2104 // helper table to know how much data is used by drawing commands
\r
2105 ////////////////////////////////////////////////////////////////////////
\r
2107 const u8 primTableCX[256] =
\r
2124 8,8,8,8,12,12,12,12,
\r
2128 // 5,5,5,5,6,6,6,6, //FLINE
\r
2129 254,254,254,254,254,254,254,254,
\r
2133 // 7,7,7,7,9,9,9,9, // LINEG3 LINEG4
\r
2134 255,255,255,255,255,255,255,255,
\r
2136 3,3,3,3,4,4,4,4, // TILE SPRT
\r
2138 2,2,2,2,3,3,3,3, // TILE1
\r
2177 ////////////////////////////////////////////////////////////////////////
\r
2178 // processes data send to GPU data register
\r
2179 ////////////////////////////////////////////////////////////////////////
\r
2182 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)
\r
2184 void CALLBACK GPU_writeDataMem(unsigned long * pMem, int iSize)
\r
2188 unsigned long gdata=0;
\r
2191 GPUIsNotReadyForCommands;
\r
2195 if(iDataWriteMode==DR_VRAMTRANSFER)
\r
2197 // make sure we are in vram
\r
2198 while(VRAMWrite.ImagePtr>=psxVuw_eom)
\r
2199 VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2200 while(VRAMWrite.ImagePtr<psxVuw)
\r
2201 VRAMWrite.ImagePtr+=iGPUHeight*1024;
\r
2203 // now do the loop
\r
2204 while(VRAMWrite.ColsRemaining>0)
\r
2206 while(VRAMWrite.RowsRemaining>0)
\r
2208 if(i>=iSize) {goto ENDVRAM;}
\r
2213 *VRAMWrite.ImagePtr++ = (unsigned short)gdata;
\r
2214 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2215 VRAMWrite.RowsRemaining --;
\r
2217 if(VRAMWrite.RowsRemaining <= 0)
\r
2219 VRAMWrite.ColsRemaining--;
\r
2220 if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width
\r
2222 gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16);
\r
2223 FinishedVRAMWrite();
\r
2226 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
2227 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
2230 *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16);
\r
2231 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2232 VRAMWrite.RowsRemaining --;
\r
2235 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
2236 VRAMWrite.ColsRemaining--;
\r
2237 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
2240 FinishedVRAMWrite();
\r
2245 if(iDataWriteMode==DR_NORMAL)
\r
2247 void (* *primFunc)(u8 *);
\r
2248 if(bSkipNextFrame) primFunc=primTableSkip;
\r
2249 else primFunc=primTableJ;
\r
2253 if(iDataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;
\r
2255 gdata=*pMem++;i++;
\r
2259 command = (u8)((gdata>>24) & 0xff);
\r
2261 if(primTableCX[command])
\r
2263 gpuDataC = primTableCX[command];
\r
2264 gpuCommand = command;
\r
2265 gpuDataM[0] = gdata;
\r
2272 gpuDataM[gpuDataP] = gdata;
\r
2275 if((gpuDataC==254 && gpuDataP>=3) ||
\r
2276 (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))
\r
2278 if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)
\r
2279 gpuDataP=gpuDataC-1;
\r
2285 if(gpuDataP == gpuDataC)
\r
2287 gpuDataC=gpuDataP=0;
\r
2288 primFunc[gpuCommand]((u8 *)gpuDataM);
\r
2290 if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games
\r
2298 GPUIsReadyForCommands;
\r
2302 ////////////////////////////////////////////////////////////////////////
\r
2305 void CALLBACK GPUwriteData(unsigned long gdata)
\r
2307 void CALLBACK GPU_writeData(unsigned long gdata)
\r
2311 GPUwriteDataMem(&gdata,1);
\r
2313 GPU_writeDataMem(&gdata,1);
\r
2317 ////////////////////////////////////////////////////////////////////////
\r
2318 // this function will be removed soon (or 'soonish') (or never)
\r
2319 ////////////////////////////////////////////////////////////////////////
\r
2321 void CALLBACK GPUsetMode(unsigned int gdata)
\r
2323 // ignore old psemu setmode:
\r
2325 // imageTransfer = gdata;
\r
2326 // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2327 // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2330 // and this function will be removed soon as well, hehehe...
\r
2331 long CALLBACK GPUgetMode(void)
\r
2333 // ignore old psemu setmode
\r
2334 // return imageTransfer;
\r
2338 if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1;
\r
2339 if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2;
\r
2344 ////////////////////////////////////////////////////////////////////////
\r
2345 // call config dlg (Windows + Linux)
\r
2346 ////////////////////////////////////////////////////////////////////////
\r
2350 /*#include <unistd.h>
\r
2352 void StartCfgTool(s8 * pCmdLine) // linux: start external cfg tool
\r
2354 FILE * cf;s8 filename[255],t[255];
\r
2356 strcpy(filename,"cfg/cfgPeopsMesaGL"); // look in cfg sub folder first
\r
2357 cf=fopen(filename,"rb");
\r
2363 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2369 strcpy(filename,"cfgPeopsMesaGL"); // look in current folder
\r
2370 cf=fopen(filename,"rb");
\r
2374 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2379 sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder
\r
2380 cf=fopen(filename,"rb");
\r
2385 chdir(getenv("HOME"));
\r
2386 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2390 else printf("cfgPeopsMesaGL not found!\n");
\r
2399 long CALLBACK GPUconfigure(void)
\r
2401 long CALLBACK GPU_configure(void)
\r
2406 // HWND hWP=GetActiveWindow();
\r
2407 // DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG),
\r
2408 // hWP,(DLGPROC)CfgDlgProc);
\r
2411 // StartCfgTool("CFG");
\r
2418 ////////////////////////////////////////////////////////////////////////
\r
2419 // sets all kind of act fixes
\r
2420 ////////////////////////////////////////////////////////////////////////
\r
2422 void SetFixes(void)
\r
2426 if(dwActFixes & 0x2000)
\r
2427 dispWidths[4]=384;
\r
2428 else dispWidths[4]=368;
\r
2431 ////////////////////////////////////////////////////////////////////////
\r
2432 // Pete Special: make an 'intelligent' dma chain check (<-Tekken3)
\r
2433 ////////////////////////////////////////////////////////////////////////
\r
2435 unsigned long lUsedAddr[3];
\r
2437 __inline BOOL CheckForEndlessLoop(unsigned long laddr)
\r
2439 if(laddr==lUsedAddr[1]) return TRUE;
\r
2440 if(laddr==lUsedAddr[2]) return TRUE;
\r
2442 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
\r
2443 else lUsedAddr[2]=laddr;
\r
2444 lUsedAddr[0]=laddr;
\r
2448 ////////////////////////////////////////////////////////////////////////
\r
2449 // core gives a dma chain to gpu: same as the gpuwrite interface funcs
\r
2450 ////////////////////////////////////////////////////////////////////////
\r
2453 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)
\r
2455 long CALLBACK GPU_dmaChain(unsigned long * baseAddrL, unsigned long addr)
\r
2458 unsigned long dmaMem;
\r
2460 short count;unsigned int DMACommandCounter = 0;
\r
2462 if(bIsFirstFrame) GLinitialize();
\r
2466 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
\r
2468 baseAddrB = (u8*) baseAddrL;
\r
2472 if(iGPUHeight==512) addr&=0x1FFFFC;
\r
2474 if(DMACommandCounter++ > 2000000) break;
\r
2475 if(CheckForEndlessLoop(addr)) break;
\r
2477 count = baseAddrB[addr+3];
\r
2482 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
\r
2484 if(count>0) GPU_writeDataMem(&baseAddrL[dmaMem>>2],count);
\r
2487 addr = baseAddrL[addr>>2]&0xffffff;
\r
2489 while (addr != 0xffffff);
\r
2496 ////////////////////////////////////////////////////////////////////////
\r
2498 ////////////////////////////////////////////////////////////////////////
\r
2501 void CALLBACK GPUabout(void)
\r
2503 void CALLBACK GPU_about(void)
\r
2509 ////////////////////////////////////////////////////////////////////////
\r
2510 // We are ever fine ;)
\r
2511 ////////////////////////////////////////////////////////////////////////
\r
2514 long CALLBACK GPUtest(void)
\r
2516 long CALLBACK GPU_test(void)
\r
2519 // if test fails this function should return negative value for error (unable to continue)
\r
2520 // and positive value for warning (can continue but output might be crappy)
\r
2525 ////////////////////////////////////////////////////////////////////////
\r
2526 // save state funcs
\r
2527 ////////////////////////////////////////////////////////////////////////
\r
2529 ////////////////////////////////////////////////////////////////////////
\r
2532 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)
\r
2534 long CALLBACK GPU_freeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)
\r
2537 if(ulGetFreezeData==2)
\r
2539 long lSlotNum=*((long *)pF);
\r
2540 if(lSlotNum<0) return 0;
\r
2541 if(lSlotNum>8) return 0;
\r
2542 lSelectedSlot=lSlotNum+1;
\r
2546 if(!pF) return 0;
\r
2547 if(pF->ulFreezeVersion!=1) return 0;
\r
2549 if(ulGetFreezeData==1)
\r
2551 pF->ulStatus=STATUSREG;
\r
2552 memcpy(pF->ulControl,ulStatusControl,256*sizeof(unsigned long));
\r
2553 memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2);
\r
2558 if(ulGetFreezeData!=0) return 0;
\r
2560 STATUSREG=pF->ulStatus;
\r
2561 memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long));
\r
2562 memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2);
\r
2564 ResetTextureArea(TRUE);
\r
2567 GPUwriteStatus(ulStatusControl[0]);
\r
2568 GPUwriteStatus(ulStatusControl[1]);
\r
2569 GPUwriteStatus(ulStatusControl[2]);
\r
2570 GPUwriteStatus(ulStatusControl[3]);
\r
2571 GPUwriteStatus(ulStatusControl[8]);
\r
2572 GPUwriteStatus(ulStatusControl[6]);
\r
2573 GPUwriteStatus(ulStatusControl[7]);
\r
2574 GPUwriteStatus(ulStatusControl[5]);
\r
2575 GPUwriteStatus(ulStatusControl[4]);
\r
2577 GPU_writeStatus(ulStatusControl[0]);
\r
2578 GPU_writeStatus(ulStatusControl[1]);
\r
2579 GPU_writeStatus(ulStatusControl[2]);
\r
2580 GPU_writeStatus(ulStatusControl[3]);
\r
2581 GPU_writeStatus(ulStatusControl[8]);
\r
2582 GPU_writeStatus(ulStatusControl[6]);
\r
2583 GPU_writeStatus(ulStatusControl[7]);
\r
2584 GPU_writeStatus(ulStatusControl[5]);
\r
2585 GPU_writeStatus(ulStatusControl[4]);
\r
2590 ////////////////////////////////////////////////////////////////////////
\r
2591 // special "emu infos" / "emu effects" functions
\r
2592 ////////////////////////////////////////////////////////////////////////
\r
2597 //11 = transparent
\r
2599 u8 cFont[10][120]=
\r
2602 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2603 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2604 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2605 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2606 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2607 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2608 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2609 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2610 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2611 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2612 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2613 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2614 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2615 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2616 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2617 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2618 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2619 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2620 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2621 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2624 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2625 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2626 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2627 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2628 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2629 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2630 0x80,0x00,0x05,0x50,0x00,0x00,
\r
2631 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2632 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2633 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2634 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2635 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2636 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2637 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2638 0x80,0x00,0x05,0x55,0x00,0x00,
\r
2639 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2640 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2641 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2642 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2643 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2646 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2647 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2648 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2649 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2650 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2651 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2652 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2653 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2654 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2655 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2656 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2657 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2658 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2659 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2660 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2661 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2662 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2663 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2664 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2665 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2668 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2669 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2670 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2671 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2672 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2673 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2674 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2675 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2676 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2677 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2678 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2679 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2680 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2681 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2682 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2683 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2684 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2685 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2686 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2687 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2690 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2691 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2692 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2693 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2694 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2695 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2696 0x80,0x00,0x00,0x54,0x00,0x00,
\r
2697 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2698 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2699 0x80,0x00,0x05,0x14,0x00,0x00,
\r
2700 0x80,0x00,0x14,0x14,0x00,0x00,
\r
2701 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2702 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2703 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2704 0x80,0x00,0x00,0x55,0x00,0x00,
\r
2705 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2706 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2707 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2708 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2709 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2712 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2713 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2714 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2715 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2716 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2717 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2718 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2719 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2720 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2721 0x80,0x00,0x15,0x54,0x00,0x00,
\r
2722 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2723 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2724 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2725 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2726 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2727 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2728 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2729 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2730 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2731 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2734 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2735 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2736 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2737 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2738 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2739 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2740 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2741 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2742 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2743 0x80,0x00,0x15,0x54,0x00,0x00,
\r
2744 0x80,0x00,0x15,0x05,0x00,0x00,
\r
2745 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2746 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2747 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2748 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2749 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2750 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2751 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2752 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2753 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2756 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2757 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2758 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2759 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2760 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2761 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2762 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2763 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2764 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2765 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2766 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2767 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2768 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2769 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2770 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2771 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2772 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2773 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2774 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2775 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2778 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2779 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2780 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2781 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2782 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2783 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2784 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2785 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2786 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2787 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2788 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2789 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2790 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2791 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2792 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2793 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2794 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2795 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2796 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2797 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2800 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2801 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2802 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2803 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2804 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2805 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2806 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2807 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2808 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2809 0x80,0x00,0x14,0x15,0x00,0x00,
\r
2810 0x80,0x00,0x05,0x55,0x00,0x00,
\r
2811 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2812 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2813 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2814 0x80,0x00,0x05,0x50,0x00,0x00,
\r
2815 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2816 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2817 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2818 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2819 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2823 ////////////////////////////////////////////////////////////////////////
\r
2825 void PaintPicDot(u8 * p,u8 c)
\r
2827 if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;}
\r
2828 if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;}
\r
2829 if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;}
\r
2832 ////////////////////////////////////////////////////////////////////////
\r
2835 void CALLBACK GPUgetScreenPic(u8 * pMem)
\r
2837 long CALLBACK GPU_getScreenPic(u8 * pMem)
\r
2840 float XS,YS;int x,y,v;
\r
2841 u8 * ps, * px, * pf;
\r
2844 if(!pGfxCardScreen)
\r
2846 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
2847 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);
\r
2850 ps=pGfxCardScreen;
\r
2852 // glReadBuffer(GL_FRONT);
\r
2854 glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
2856 // glReadBuffer(GL_BACK);
\r
2858 XS=(float)iResX/128;
\r
2859 YS=(float)iResY/96;
\r
2864 for(x=0;x<128;x++)
\r
2866 px=ps+(3*((int)((float)x * XS))+
\r
2867 (3*iResX)*((int)((float)y*YS)));
\r
2875 /////////////////////////////////////////////////////////////////////
\r
2876 // generic number/border painter
\r
2884 c=cFont[lSelectedSlot][x+y*6];
\r
2886 PaintPicDot(pf,(u8)v);pf+=3; // paint the dots into the rect
\r
2888 PaintPicDot(pf,(u8)v);pf+=3;
\r
2890 PaintPicDot(pf,(u8)v);pf+=3;
\r
2892 PaintPicDot(pf,(u8)v);pf+=3;
\r
2898 for(x=0;x<128;x++)
\r
2900 *(pf+(95*128*3))=0x00;*pf++=0x00;
\r
2901 *(pf+(95*128*3))=0x00;*pf++=0x00;
\r
2902 *(pf+(95*128*3))=0xff;*pf++=0xff;
\r
2907 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2908 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2909 *(pf+(127*3))=0xff;*pf++=0xff;
\r
2915 ////////////////////////////////////////////////////////////////////////
\r
2918 void CALLBACK GPUshowScreenPic(u8 * pMem)
\r
2920 long CALLBACK GPU_showScreenPic(u8 * pMem)
\r
2924 // if(pMem==0) return;
\r
2925 // CreatePic(pMem);
\r
2928 ////////////////////////////////////////////////////////////////////////
\r
2930 void CALLBACK GPUsetfix(unsigned long dwFixBits)
\r
2932 dwEmuFixes=dwFixBits;
\r
2935 ////////////////////////////////////////////////////////////////////////
\r
2937 void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig)
\r
2941 if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width
\r
2942 iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x);
\r
2944 // big rumble: 4...15 sp ; small rumble 1...3 sp
\r
2945 if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10));
\r
2946 else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10));
\r
2948 srand(timeGetTime()); // init rand (will be used in BufferSwap)
\r
2950 iRumbleTime=15; // let the rumble last 16 buffer swaps
\r
2953 ////////////////////////////////////////////////////////////////////////
\r
2954 // main emu can set display infos (A/M/G/D)
\r
2955 ////////////////////////////////////////////////////////////////////////
\r
2957 void CALLBACK GPUdisplayFlags(unsigned long dwFlags)
\r
2959 // dwCoreFlags=dwFlags;
\r