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 GPUmakeSnapshot(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 GPUinit()
\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 GPUopen(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
559 iResX=240;iResY=320;
\r
561 #ifdef MAEMO_CHANGES
\r
562 iResX=640;iResY=480;
\r
573 // bAdvancedBlend=FALSE;
\r
575 // bUseLines=FALSE;
\r
576 bUseFrameLimit=FALSE;
\r
577 bUseFrameSkip=FALSE;
\r
580 iOffscreenDrawing=0;
\r
581 //bOpaquePass=FALSE;
\r
582 //bUseAntiAlias=FALSE;
\r
585 iWinSize=MAKELONG(iResX,iResY);
\r
589 bUseFastMdec=FALSE;
\r
590 bUse15bitMdec=FALSE;
\r
593 // iUseScanLines=0;
\r
600 iTexGarbageCollection=0;
\r
602 //iHiResTextures=0;
\r
609 memset(&dv,0,sizeof(DEVMODE));
\r
610 dv.dmSize=sizeof(DEVMODE);
\r
611 EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv);
\r
613 bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows!
\r
616 if(bWindowMode) // win mode?
\r
618 DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers)
\r
619 dw&=~WS_THICKFRAME;
\r
620 dw|=WS_BORDER|WS_CAPTION|CS_OWNDC;
\r
621 SetWindowLong(hWWindow, GWL_STYLE, dw);
\r
623 hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any)
\r
624 if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);
\r
626 iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize);
\r
627 ShowWindow(hWWindow,SW_SHOWNORMAL);
\r
629 MoveWindow(hWWindow, // -> center wnd
\r
630 GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2,
\r
631 GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2,
\r
632 iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3,
\r
633 iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3,
\r
635 UpdateWindow(hWWindow); // -> let windows do some update
\r
637 if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info
\r
638 iColDepth=dv.dmBitsPerPel;
\r
640 else // fullscreen mode:
\r
642 if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution
\r
643 dv.dmPelsWidth !=(unsigned int)iResX ||
\r
644 dv.dmPelsHeight!=(unsigned int)iResY)
\r
645 bChangeRes=TRUE; else bChangeRes=FALSE;
\r
647 if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations')
\r
649 SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure)
\r
651 hPSEMenu=GetMenu(hWWindow); // -> hide menu
\r
652 if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);
\r
653 ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode
\r
656 rRatioRect.left = rRatioRect.top=0;
\r
657 rRatioRect.right = iResX;
\r
658 rRatioRect.bottom = iResY;
\r
661 r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized
\r
662 hdc = GetDC(hWWindow);
\r
663 FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH));
\r
664 bSetupPixelFormat(hdc);
\r
665 ReleaseDC(hWWindow,hdc);
\r
667 bDisplayNotSet = TRUE;
\r
670 SetFixes(); // setup game fixes
\r
672 InitializeTextureStore(); // init texture mem
\r
674 // lGPUstatusRet = 0x74000000;
\r
676 // with some emus, we could do the OGL init right here... oh my
\r
677 // if(bIsFirstFrame) GLinitialize();
\r
682 ////////////////////////////////////////////////////////////////////////
\r
684 ////////////////////////////////////////////////////////////////////////
\r
687 long CALLBACK GPUclose() // WINDOWS CLOSE
\r
689 // ExitKeyHandler();
\r
691 GLcleanup(); // close OGL
\r
693 if(bChangeRes) // change res back
\r
694 ChangeDisplaySettings(NULL,0);
\r
696 if(hPSEMenu) // set menu again
\r
697 SetMenu(hWWindow,hPSEMenu);
\r
699 if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory
\r
702 // if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again
\r
709 long GPUclose() // LINUX CLOSE
\r
711 GLcleanup(); // close OGL
\r
713 if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory
\r
716 // osd_close_display(); // destroy display
\r
722 ////////////////////////////////////////////////////////////////////////
\r
723 // I shot the sheriff... last function called from emu
\r
724 ////////////////////////////////////////////////////////////////////////
\r
727 long CALLBACK GPUshutdown()
\r
729 long CALLBACK GPUshutdown()
\r
732 if(psxVSecure) free(psxVSecure); // kill emulated vram memory
\r
738 ////////////////////////////////////////////////////////////////////////
\r
739 // paint it black: simple func to clean up optical border garbage
\r
740 ////////////////////////////////////////////////////////////////////////
\r
742 void PaintBlackBorders(void)
\r
746 glDisable(GL_SCISSOR_TEST);
\r
747 if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;}
\r
748 if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;}
\r
749 if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;}
\r
750 glDisable(GL_ALPHA_TEST);
\r
752 glEnable(GL_ALPHA_TEST);
\r
753 glEnable(GL_SCISSOR_TEST);
\r
756 ////////////////////////////////////////////////////////////////////////
\r
757 // helper to draw scanlines
\r
758 ////////////////////////////////////////////////////////////////////////
\r
760 __inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2,
\r
761 OGLVertex* vertex3, OGLVertex* vertex4)
\r
766 ////////////////////////////////////////////////////////////////////////
\r
768 ////////////////////////////////////////////////////////////////////////
\r
770 void SetScanLines(void)
\r
774 ////////////////////////////////////////////////////////////////////////
\r
775 // blur, babe, blur (heavy performance hit for a so-so fullscreen effect)
\r
776 ////////////////////////////////////////////////////////////////////////
\r
779 ////////////////////////////////////////////////////////////////////////
\r
780 // Update display (swap buffers)... called in interlaced mode on
\r
781 // every emulated vsync, otherwise whenever the displayed screen region
\r
782 // has been changed
\r
783 ////////////////////////////////////////////////////////////////////////
\r
785 int iLastRGB24=0; // special vars for checking when to skip two display updates
\r
787 void GPUvSinc(void){
\r
790 void updateDisplay(void) // UPDATE DISPLAY
\r
795 HDC hdc=GetDC(hWWindow); // windows:
\r
796 wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again
\r
799 bFakeFrontBuffer=FALSE;
\r
800 bRenderFrontBuffer=FALSE;
\r
802 if(iRenderFVR) // frame buffer read fix mode still active?
\r
804 iRenderFVR--; // -> if some frames in a row without read access: turn off mode
\r
805 if(!iRenderFVR) bFullVRam=FALSE;
\r
808 if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check
\r
810 iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes
\r
814 if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted?
\r
816 PrepareFullScreenUpload(-1);
\r
817 UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram
\r
818 bNeedUploadTest=FALSE;
\r
819 bNeedInterlaceUpdate=FALSE;
\r
820 bNeedUploadAfter=FALSE;
\r
821 bNeedRGB24Update=FALSE;
\r
824 if(bNeedInterlaceUpdate) // smaller upload?
\r
826 bNeedInterlaceUpdate=FALSE;
\r
827 xrUploadArea=xrUploadAreaIL; // -> upload this rect
\r
828 UploadScreen(TRUE);
\r
831 if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9
\r
833 if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed
\r
834 PreviousPSXDisplay.Range.y0)
\r
835 PaintBlackBorders();
\r
837 if(PSXDisplay.Disabled) // display disabled?
\r
840 glDisable(GL_SCISSOR_TEST);
\r
841 glClearColor(0,0,0,128); // -> clear whole backbuffer
\r
842 glClear(uiBufferBits);
\r
843 glEnable(GL_SCISSOR_TEST);
\r
845 bDisplayNotSet = TRUE;
\r
848 if(iSkipTwo) // we are in skipping mood?
\r
851 iDrawnSomething=0; // -> simply lie about something drawn
\r
854 //if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated?
\r
855 // {BlurBackBuffer();bBlur=TRUE;} // -> blur it
\r
857 // if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it
\r
859 // if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em
\r
861 if(dwActFixes&128) // special FPS limitation mode?
\r
863 if(bUseFrameLimit) PCFrameCap(); // -> ok, do it
\r
864 // if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS)
\r
868 // if(gTexPicName) DisplayPic(); // some gpu info picture active? display it
\r
870 // if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :)
\r
872 // if(ulKeybits&KEY_SHOWFPS) // wanna see FPS?
\r
874 // sprintf(szDispBuf,"%06.1f",fps_cur);
\r
875 // DisplayText(); // -> show it
\r
878 //----------------------------------------------------//
\r
879 // main buffer swapping (well, or skip it)
\r
881 if(bUseFrameSkip) // frame skipping active ?
\r
883 if(!bSkipNextFrame)
\r
885 if(iDrawnSomething)
\r
887 SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip
\r
889 eglSwapBuffers(display,surface);
\r
892 if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row
\r
894 if((fps_skip < fFrameRateHz) && !(bSkipNextFrame))
\r
895 {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}
\r
896 else bSkipNextFrame = FALSE;
\r
902 if(iDrawnSomething)
\r
904 SwapBuffers(wglGetCurrentDC()); // -> swap
\r
906 eglSwapBuffers(display,surface);
\r
912 //----------------------------------------------------//
\r
914 if(lClearOnSwap) // clear buffer after swap?
\r
918 if(bDisplayNotSet) // -> set new vals
\r
919 SetOGLDisplaySettings(1);
\r
921 g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col
\r
922 b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f;
\r
923 r=((GLclampf)RED(lClearOnSwapColor))/255.0f;
\r
925 glDisable(GL_SCISSOR_TEST);
\r
926 glClearColor(r,g,b,128); // -> clear
\r
927 glClear(uiBufferBits);
\r
928 glEnable(GL_SCISSOR_TEST);
\r
929 lClearOnSwap=0; // -> done
\r
933 // if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before
\r
935 if(iZBufferDepth) // clear zbuffer as well (if activated)
\r
937 glDisable(GL_SCISSOR_TEST);
\r
938 glClear(GL_DEPTH_BUFFER_BIT);
\r
939 glEnable(GL_SCISSOR_TEST);
\r
944 //----------------------------------------------------//
\r
945 // additional uploads immediatly after swapping
\r
947 if(bNeedUploadAfter) // upload wanted?
\r
949 bNeedUploadAfter=FALSE;
\r
950 bNeedUploadTest=FALSE;
\r
951 UploadScreen(-1); // -> upload
\r
954 if(bNeedUploadTest)
\r
956 bNeedUploadTest=FALSE;
\r
957 if(PSXDisplay.InterlacedTest &&
\r
958 //iOffscreenDrawing>2 &&
\r
959 PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x &&
\r
960 PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x &&
\r
961 PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y &&
\r
962 PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y)
\r
964 PrepareFullScreenUpload(TRUE);
\r
965 UploadScreen(TRUE);
\r
969 //----------------------------------------------------//
\r
970 // rumbling (main emu pad effect)
\r
972 if(iRumbleTime) // shake screen by modifying view port
\r
974 int i1=0,i2=0,i3=0,i4=0;
\r
979 i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
980 i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
981 i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
982 i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
985 glViewport(rRatioRect.left+i1,
\r
986 iResY-(rRatioRect.top+rRatioRect.bottom)+i2,
\r
987 rRatioRect.right+i3,
\r
988 rRatioRect.bottom+i4);
\r
991 //----------------------------------------------------//
\r
995 // if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled
\r
998 ////////////////////////////////////////////////////////////////////////
\r
999 // update front display: smaller update func, if something has changed
\r
1000 // in the frontbuffer... dirty, but hey... real men know no pain
\r
1001 ////////////////////////////////////////////////////////////////////////
\r
1003 void updateFrontDisplay(void)
\r
1005 if(PreviousPSXDisplay.Range.x0||
\r
1006 PreviousPSXDisplay.Range.y0)
\r
1007 PaintBlackBorders();
\r
1009 //if(iBlurBuffer) BlurBackBuffer();
\r
1011 //if(iUseScanLines) SetScanLines();
\r
1013 // if(usCursorActive) ShowGunCursor();
\r
1015 bFakeFrontBuffer=FALSE;
\r
1016 bRenderFrontBuffer=FALSE;
\r
1018 // if(gTexPicName) DisplayPic();
\r
1019 // if(ulKeybits&KEY_SHOWFPS) DisplayText();
\r
1023 HDC hdc=GetDC(hWWindow);
\r
1024 wglMakeCurrent(hdc,GLCONTEXT); // -> make current again
\r
1025 if(iDrawnSomething)
\r
1026 SwapBuffers(wglGetCurrentDC()); // -> swap
\r
1027 ReleaseDC(hWWindow,hdc); // -> ! important !
\r
1030 if(iDrawnSomething) // linux:
\r
1031 eglSwapBuffers(display,surface);
\r
1034 //if(iBlurBuffer) UnBlurBackBuffer();
\r
1037 ////////////////////////////////////////////////////////////////////////
\r
1038 // check if update needed
\r
1039 ////////////////////////////////////////////////////////////////////////
\r
1040 void ChangeDispOffsetsX(void) // CENTER X
\r
1042 long lx,l;short sO;
\r
1044 if(!PSXDisplay.Range.x1) return; // some range given?
\r
1046 l=PSXDisplay.DisplayMode.x;
\r
1048 l*=(long)PSXDisplay.Range.x1; // some funky calculation
\r
1049 l/=2560;lx=l;l&=0xfffffff8;
\r
1051 if(l==PreviousPSXDisplay.Range.x1) return; // some change?
\r
1053 sO=PreviousPSXDisplay.Range.x0; // store old
\r
1055 if(lx>=PSXDisplay.DisplayMode.x) // range bigger?
\r
1057 PreviousPSXDisplay.Range.x1= // -> take display width
\r
1058 PSXDisplay.DisplayMode.x;
\r
1059 PreviousPSXDisplay.Range.x0=0; // -> start pos is 0
\r
1061 else // range smaller? center it
\r
1063 PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned)
\r
1064 PreviousPSXDisplay.Range.x0= // -> calc start pos
\r
1065 (PSXDisplay.Range.x0-500)/8;
\r
1066 if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet
\r
1067 PreviousPSXDisplay.Range.x0=0;
\r
1069 if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much
\r
1070 PSXDisplay.DisplayMode.x)
\r
1072 PreviousPSXDisplay.Range.x0= // -> adjust start
\r
1073 PSXDisplay.DisplayMode.x-lx;
\r
1074 PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width
\r
1078 if(sO!=PreviousPSXDisplay.Range.x0) // something changed?
\r
1080 bDisplayNotSet=TRUE; // -> recalc display stuff
\r
1084 ////////////////////////////////////////////////////////////////////////
\r
1086 void ChangeDispOffsetsY(void) // CENTER Y
\r
1088 int iT;short sO; // store previous y size
\r
1090 if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC
\r
1092 if(PSXDisplay.Range.y0>=iT) // crossed the security line? :)
\r
1094 PreviousPSXDisplay.Range.y1= // -> store width
\r
1095 PSXDisplay.DisplayModeNew.y;
\r
1097 sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset
\r
1100 PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too
\r
1102 else sO=0; // else no offset
\r
1104 if(sO!=PreviousPSXDisplay.Range.y0) // something changed?
\r
1106 PreviousPSXDisplay.Range.y0=sO;
\r
1107 bDisplayNotSet=TRUE; // -> recalc display stuff
\r
1111 ////////////////////////////////////////////////////////////////////////
\r
1112 // Aspect ratio of ogl screen: simply adjusting ogl view port
\r
1113 ////////////////////////////////////////////////////////////////////////
\r
1115 void SetAspectRatio(void)
\r
1117 float xs,ys,s;RECT r;
\r
1119 if(!PSXDisplay.DisplayModeNew.x) return;
\r
1120 if(!PSXDisplay.DisplayModeNew.y) return;
\r
1122 xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x;
\r
1123 ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y;
\r
1126 r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s);
\r
1127 r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s);
\r
1128 if(r.right > iResX) r.right = iResX;
\r
1129 if(r.bottom > iResY) r.bottom = iResY;
\r
1130 if(r.right < 1) r.right = 1;
\r
1131 if(r.bottom < 1) r.bottom = 1;
\r
1133 r.left = (iResX-r.right)/2;
\r
1134 r.top = (iResY-r.bottom)/2;
\r
1136 if(r.bottom<rRatioRect.bottom ||
\r
1137 r.right <rRatioRect.right)
\r
1140 glClearColor(0,0,0,128);
\r
1142 if(r.right <rRatioRect.right)
\r
1148 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1149 glClear(uiBufferBits);
\r
1150 rC.left=iResX-rC.right;
\r
1151 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1152 glClear(uiBufferBits);
\r
1155 if(r.bottom <rRatioRect.bottom)
\r
1161 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1162 glClear(uiBufferBits);
\r
1163 rC.top=iResY-rC.bottom;
\r
1164 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1165 glClear(uiBufferBits);
\r
1169 bDisplayNotSet=TRUE;
\r
1175 glViewport(rRatioRect.left,
\r
1176 iResY-(rRatioRect.top+rRatioRect.bottom),
\r
1178 rRatioRect.bottom); // init viewport
\r
1181 ////////////////////////////////////////////////////////////////////////
\r
1182 // big ass check, if an ogl swap buffer is needed
\r
1183 ////////////////////////////////////////////////////////////////////////
\r
1185 void updateDisplayIfChanged(void)
\r
1189 if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) &&
\r
1190 (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))
\r
1192 if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) &&
\r
1193 (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew))
\r
1194 return; // nothing has changed? fine, no swap buffer needed
\r
1196 else // some res change?
\r
1199 glOrtho(0,PSXDisplay.DisplayModeNew.x, // -> new psx resolution
\r
1200 PSXDisplay.DisplayModeNew.y, 0, -1, 1);
\r
1201 if(bKeepRatio) SetAspectRatio();
\r
1204 bDisplayNotSet = TRUE; // re-calc offsets/display area
\r
1207 if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off)
\r
1209 PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet
\r
1210 ResetTextureArea(FALSE);
\r
1214 PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos
\r
1215 PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;
\r
1216 PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;
\r
1217 PSXDisplay.Interlaced = PSXDisplay.InterlacedNew;
\r
1219 PSXDisplay.DisplayEnd.x= // calc new ends
\r
1220 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1221 PSXDisplay.DisplayEnd.y=
\r
1222 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1223 PreviousPSXDisplay.DisplayEnd.x=
\r
1224 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1225 PreviousPSXDisplay.DisplayEnd.y=
\r
1226 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1228 ChangeDispOffsetsX();
\r
1230 if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace)
\r
1232 if(bUp) updateDisplay(); // yeah, real update (swap buffer)
\r
1235 ////////////////////////////////////////////////////////////////////////
\r
1236 // window mode <-> fullscreen mode (windows)
\r
1237 ////////////////////////////////////////////////////////////////////////
\r
1240 void ChangeWindowMode(void)
\r
1243 bWindowMode=!bWindowMode;
\r
1244 GPUopen(hWWindow);
\r
1245 bChangeWinMode=FALSE;
\r
1249 ////////////////////////////////////////////////////////////////////////
\r
1250 // swap update check (called by psx vsync function)
\r
1251 ////////////////////////////////////////////////////////////////////////
\r
1253 BOOL bSwapCheck(void)
\r
1255 static int iPosCheck=0;
\r
1256 static PSXPoint_t pO;
\r
1257 static PSXPoint_t pD;
\r
1258 static int iDoAgain=0;
\r
1260 if(PSXDisplay.DisplayPosition.x==pO.x &&
\r
1261 PSXDisplay.DisplayPosition.y==pO.y &&
\r
1262 PSXDisplay.DisplayEnd.x==pD.x &&
\r
1263 PSXDisplay.DisplayEnd.y==pD.y)
\r
1267 pO=PSXDisplay.DisplayPosition;
\r
1268 pD=PSXDisplay.DisplayEnd;
\r
1270 if(iPosCheck<=4) return FALSE;
\r
1274 if(PSXDisplay.Interlaced) return FALSE;
\r
1276 if (bNeedInterlaceUpdate||
\r
1277 bNeedRGB24Update ||
\r
1278 bNeedUploadAfter||
\r
1279 bNeedUploadTest ||
\r
1284 if(bNeedUploadAfter)
\r
1286 if(bNeedUploadTest && PSXDisplay.InterlacedTest)
\r
1289 bDisplayNotSet = TRUE;
\r
1292 PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x;
\r
1293 PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y;
\r
1294 PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x;
\r
1295 PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y;
\r
1296 pO=PSXDisplay.DisplayPosition;
\r
1297 pD=PSXDisplay.DisplayEnd;
\r
1304 ////////////////////////////////////////////////////////////////////////
\r
1305 // gun cursor func: player=0-7, x=0-511, y=0-255
\r
1306 ////////////////////////////////////////////////////////////////////////
\r
1308 ////////////////////////////////////////////////////////////////////////
\r
1309 // update lace is called every VSync. Basically we limit frame rate
\r
1310 // here, and in interlaced mode we swap ogl display buffers.
\r
1311 ////////////////////////////////////////////////////////////////////////
\r
1313 static unsigned short usFirstPos=2;
\r
1316 void CALLBACK GPUupdateLace(void)
\r
1318 void CALLBACK GPUupdateLace(void)
\r
1321 if(!(dwActFixes&0x1000))
\r
1322 STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus)
\r
1324 if(!(dwActFixes&128)) // normal frame limit func
\r
1327 if(iOffscreenDrawing==4) // special check if high offscreen drawing is on
\r
1329 if(bSwapCheck()) return;
\r
1332 if(PSXDisplay.Interlaced) // interlaced mode?
\r
1334 if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)
\r
1336 updateDisplay(); // -> swap buffers (new frame)
\r
1339 else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed?
\r
1341 updateFrontDisplay(); // -> update front buffer
\r
1343 else if(usFirstPos==1) // initial updates (after startup)
\r
1349 if(bChangeWinMode) ChangeWindowMode();
\r
1353 ////////////////////////////////////////////////////////////////////////
\r
1354 // process read request from GPU status register
\r
1355 ////////////////////////////////////////////////////////////////////////
\r
1358 unsigned long CALLBACK GPUreadStatus(void)
\r
1360 unsigned long CALLBACK GPUreadStatus(void)
\r
1363 if(dwActFixes&0x1000) // CC game fix
\r
1365 static int iNumRead=0;
\r
1366 if((iNumRead++)==2)
\r
1369 STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross)
\r
1373 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
1377 if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims
\r
1380 GPUIsNotReadyForCommands;
\r
1385 GPUIsReadyForCommands;
\r
1392 ////////////////////////////////////////////////////////////////////////
\r
1393 // processes data send to GPU status register
\r
1394 // these are always single packet commands.
\r
1395 ////////////////////////////////////////////////////////////////////////
\r
1398 void CALLBACK GPUwriteStatus(unsigned long gdata)
\r
1400 void CALLBACK GPUwriteStatus(unsigned long gdata)
\r
1403 unsigned long lCommand=(gdata>>24)&0xff;
\r
1406 if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus)
\r
1409 ulStatusControl[lCommand]=gdata;
\r
1413 //--------------------------------------------------//
\r
1416 memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));
\r
1417 lGPUstatusRet=0x14802000;
\r
1418 PSXDisplay.Disabled=1;
\r
1419 iDataWriteMode=iDataReadMode=DR_NORMAL;
\r
1420 PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;
\r
1421 drawX=drawY=0;drawW=drawH=0;
\r
1422 sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0;
\r
1424 GlobalTextAddrX=0;GlobalTextAddrY=0;
\r
1425 GlobalTextTP=0;GlobalTextABR=0;
\r
1426 PSXDisplay.RGB24=FALSE;
\r
1427 PSXDisplay.Interlaced=FALSE;
\r
1428 bUsingTWin = FALSE;
\r
1431 // dis/enable display
\r
1433 PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;
\r
1434 PSXDisplay.Disabled = (gdata & 1);
\r
1436 if(PSXDisplay.Disabled)
\r
1437 STATUSREG|=GPUSTATUS_DISPLAYDISABLED;
\r
1438 else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED;
\r
1440 if (iOffscreenDrawing==4 &&
\r
1441 PreviousPSXDisplay.Disabled &&
\r
1442 !(PSXDisplay.Disabled))
\r
1445 if(!PSXDisplay.RGB24)
\r
1447 PrepareFullScreenUpload(TRUE);
\r
1448 UploadScreen(TRUE);
\r
1455 // setting transfer mode
\r
1457 gdata &= 0x03; // only want the lower two bits
\r
1459 iDataWriteMode=iDataReadMode=DR_NORMAL;
\r
1460 if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER;
\r
1461 if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER;
\r
1463 STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits
\r
1464 STATUSREG|=(gdata << 29); // set the DMA bits according to the received data
\r
1468 // setting display position
\r
1471 short sx=(short)(gdata & 0x3ff);
\r
1474 if(iGPUHeight==1024)
\r
1476 if(dwGPUVersion==2)
\r
1477 sy = (short)((gdata>>12)&0x3ff);
\r
1478 else sy = (short)((gdata>>10)&0x3ff);
\r
1480 else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later
\r
1485 PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double;
\r
1488 else PreviousPSXDisplay.DisplayModeNew.y=0;
\r
1497 PreviousPSXDisplay.DisplayPosition.x = sx;
\r
1498 PreviousPSXDisplay.DisplayPosition.y = sy;
\r
1499 PSXDisplay.DisplayPosition.x = sx;
\r
1500 PSXDisplay.DisplayPosition.y = sy;
\r
1506 if((!PSXDisplay.Interlaced) &&
\r
1507 PreviousPSXDisplay.DisplayPosition.x == sx &&
\r
1508 PreviousPSXDisplay.DisplayPosition.y == sy)
\r
1511 PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x;
\r
1512 PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y;
\r
1513 PreviousPSXDisplay.DisplayPosition.x = sx;
\r
1514 PreviousPSXDisplay.DisplayPosition.y = sy;
\r
1518 if((!PSXDisplay.Interlaced) &&
\r
1519 PSXDisplay.DisplayPosition.x == sx &&
\r
1520 PSXDisplay.DisplayPosition.y == sy)
\r
1522 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
\r
1523 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
\r
1524 PSXDisplay.DisplayPosition.x = sx;
\r
1525 PSXDisplay.DisplayPosition.y = sy;
\r
1528 PSXDisplay.DisplayEnd.x=
\r
1529 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1530 PSXDisplay.DisplayEnd.y=
\r
1531 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1533 PreviousPSXDisplay.DisplayEnd.x=
\r
1534 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1535 PreviousPSXDisplay.DisplayEnd.y=
\r
1536 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1538 bDisplayNotSet = TRUE;
\r
1540 if (!(PSXDisplay.Interlaced))
\r
1545 if(PSXDisplay.InterlacedTest &&
\r
1546 ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)||
\r
1547 (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y)))
\r
1548 PSXDisplay.InterlacedTest--;
\r
1556 PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff;
\r
1557 PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff;
\r
1559 PSXDisplay.Range.x1-=PSXDisplay.Range.x0;
\r
1561 ChangeDispOffsetsX();
\r
1568 PreviousPSXDisplay.Height = PSXDisplay.Height;
\r
1570 PSXDisplay.Range.y0=gdata & 0x3ff;
\r
1571 PSXDisplay.Range.y1=(gdata>>10) & 0x3ff;
\r
1573 PSXDisplay.Height = PSXDisplay.Range.y1 -
\r
1574 PSXDisplay.Range.y0 +
\r
1575 PreviousPSXDisplay.DisplayModeNew.y;
\r
1577 if (PreviousPSXDisplay.Height != PSXDisplay.Height)
\r
1579 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
\r
1580 ChangeDispOffsetsY();
\r
1581 updateDisplayIfChanged();
\r
1585 // setting display infos
\r
1588 PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];
\r
1590 if (gdata&0x04) PSXDisplay.Double=2;
\r
1591 else PSXDisplay.Double=1;
\r
1592 PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;
\r
1594 ChangeDispOffsetsY();
\r
1596 PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC
\r
1597 PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor
\r
1598 PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace
\r
1600 STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits
\r
1603 (((gdata & 0x03) << 17) |
\r
1604 ((gdata & 0x40) << 10)); // set the width bits
\r
1606 PreviousPSXDisplay.InterlacedNew=FALSE;
\r
1607 if (PSXDisplay.InterlacedNew)
\r
1609 if(!PSXDisplay.Interlaced)
\r
1611 PSXDisplay.InterlacedTest=2;
\r
1612 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
\r
1613 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
\r
1614 PreviousPSXDisplay.InterlacedNew=TRUE;
\r
1617 STATUSREG|=GPUSTATUS_INTERLACED;
\r
1621 PSXDisplay.InterlacedTest=0;
\r
1622 STATUSREG&=~GPUSTATUS_INTERLACED;
\r
1625 if (PSXDisplay.PAL)
\r
1626 STATUSREG|=GPUSTATUS_PAL;
\r
1627 else STATUSREG&=~GPUSTATUS_PAL;
\r
1629 if (PSXDisplay.Double==2)
\r
1630 STATUSREG|=GPUSTATUS_DOUBLEHEIGHT;
\r
1631 else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT;
\r
1633 if (PSXDisplay.RGB24New)
\r
1634 STATUSREG|=GPUSTATUS_RGB24;
\r
1635 else STATUSREG&=~GPUSTATUS_RGB24;
\r
1637 updateDisplayIfChanged();
\r
1641 //--------------------------------------------------//
\r
1642 // ask about GPU version and other stuff
\r
1650 GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos
\r
1653 GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start
\r
1656 GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end
\r
1660 GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset
\r
1663 if(dwGPUVersion==2)
\r
1665 else GPUdataRet=0x02; // gpu type
\r
1668 case 0x0F: // some bios addr?
\r
1669 GPUdataRet=0xBFC03720;
\r
1673 //--------------------------------------------------//
\r
1677 ////////////////////////////////////////////////////////////////////////
\r
1678 // vram read/write helpers
\r
1679 ////////////////////////////////////////////////////////////////////////
\r
1681 BOOL bNeedWriteUpload=FALSE;
\r
1683 __inline void FinishedVRAMWrite(void)
\r
1685 if(bNeedWriteUpload)
\r
1687 bNeedWriteUpload=FALSE;
\r
1688 CheckWriteUpdate();
\r
1691 // set register to NORMAL operation
\r
1692 iDataWriteMode = DR_NORMAL;
\r
1694 // reset transfer values, to prevent mis-transfer of data
\r
1695 VRAMWrite.ColsRemaining = 0;
\r
1696 VRAMWrite.RowsRemaining = 0;
\r
1699 __inline void FinishedVRAMRead(void)
\r
1701 // set register to NORMAL operation
\r
1702 iDataReadMode = DR_NORMAL;
\r
1703 // reset transfer values, to prevent mis-transfer of data
\r
1706 VRAMRead.Width = 0;
\r
1707 VRAMRead.Height = 0;
\r
1708 VRAMRead.ColsRemaining = 0;
\r
1709 VRAMRead.RowsRemaining = 0;
\r
1711 // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER
\r
1712 STATUSREG&=~GPUSTATUS_READYFORVRAM;
\r
1715 ////////////////////////////////////////////////////////////////////////
\r
1716 // vram read check ex (reading from card's back/frontbuffer if needed...
\r
1718 ////////////////////////////////////////////////////////////////////////
\r
1720 void CheckVRamReadEx(int x, int y, int dx, int dy)
\r
1722 unsigned short sArea;
\r
1723 int ux,uy,udx,udy,wx,wy;
\r
1724 unsigned short * p1, *p2;
\r
1728 unsigned short s,sx;
\r
1730 if(STATUSREG&GPUSTATUS_RGB24) return;
\r
1732 if(((dx > PSXDisplay.DisplayPosition.x) &&
\r
1733 (x < PSXDisplay.DisplayEnd.x) &&
\r
1734 (dy > PSXDisplay.DisplayPosition.y) &&
\r
1735 (y < PSXDisplay.DisplayEnd.y)))
\r
1738 if((!(PSXDisplay.InterlacedTest) &&
\r
1739 (dx > PreviousPSXDisplay.DisplayPosition.x) &&
\r
1740 (x < PreviousPSXDisplay.DisplayEnd.x) &&
\r
1741 (dy > PreviousPSXDisplay.DisplayPosition.y) &&
\r
1742 (y < PreviousPSXDisplay.DisplayEnd.y)))
\r
1753 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1755 bFullVRam=TRUE;iRenderFVR=2;
\r
1763 ux=PSXDisplay.DisplayPosition.x;
\r
1764 uy=PSXDisplay.DisplayPosition.y;
\r
1765 udx=PSXDisplay.DisplayEnd.x-ux;
\r
1766 udy=PSXDisplay.DisplayEnd.y-uy;
\r
1767 if((PreviousPSXDisplay.DisplayEnd.x-
\r
1768 PreviousPSXDisplay.DisplayPosition.x)==udx &&
\r
1769 (PreviousPSXDisplay.DisplayEnd.y-
\r
1770 PreviousPSXDisplay.DisplayPosition.y)==udy)
\r
1771 p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) +
\r
1772 PreviousPSXDisplay.DisplayPosition.x);
\r
1776 ux=PreviousPSXDisplay.DisplayPosition.x;
\r
1777 uy=PreviousPSXDisplay.DisplayPosition.y;
\r
1778 udx=PreviousPSXDisplay.DisplayEnd.x-ux;
\r
1779 udy=PreviousPSXDisplay.DisplayEnd.y-uy;
\r
1780 if((PSXDisplay.DisplayEnd.x-
\r
1781 PSXDisplay.DisplayPosition.x)==udx &&
\r
1782 (PSXDisplay.DisplayEnd.y-
\r
1783 PSXDisplay.DisplayPosition.y)==udy)
\r
1784 p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) +
\r
1785 PSXDisplay.DisplayPosition.x);
\r
1788 p1=(psxVuw + (1024*uy) + ux);
\r
1792 wx=dx=udx;wy=dy=udy;
\r
1794 if(udx<=0) return;
\r
1795 if(udy<=0) return;
\r
1801 XS=(float)rRatioRect.right/(float)wx;
\r
1802 YS=(float)rRatioRect.bottom/(float)wy;
\r
1804 dx=(int)((float)(dx)*XS);
\r
1805 dy=(int)((float)(dy)*YS);
\r
1807 if(dx>iResX) dx=iResX;
\r
1808 if(dy>iResY) dy=iResY;
\r
1816 x+=rRatioRect.left;
\r
1817 y-=rRatioRect.top;
\r
1819 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1821 if(!pGfxCardScreen)
\r
1823 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1824 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);
\r
1827 ps=pGfxCardScreen;
\r
1829 //if(!sArea) glReadBuffer(GL_FRONT);
\r
1831 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1833 //if(!sArea) glReadBuffer(GL_BACK);
\r
1837 XS=(float)dx/(float)(udx);
\r
1838 YS=(float)dy/(float)(udy+1);
\r
1840 for(y=udy;y>0;y--)
\r
1842 for(x=0;x<udx;x++)
\r
1844 if(p1>=psxVuw && p1<psxVuw_eom)
\r
1846 px=ps+(3*((int)((float)x * XS))+
\r
1847 (3*dx)*((int)((float)y*YS)));
\r
1857 if(p2>=psxVuw && p2<psxVuw_eom) *p2=s;
\r
1864 if(p2) p2 += 1024 - udx;
\r
1868 ////////////////////////////////////////////////////////////////////////
\r
1869 // vram read check (reading from card's back/frontbuffer if needed...
\r
1871 ////////////////////////////////////////////////////////////////////////
\r
1873 void CheckVRamRead(int x, int y, int dx, int dy, bool bFront)
\r
1875 unsigned short sArea;unsigned short * p;
\r
1876 int ux,uy,udx,udy,wx,wy;float XS,YS;
\r
1878 unsigned short s=0,sx;
\r
1880 if(STATUSREG&GPUSTATUS_RGB24) return;
\r
1882 if(((dx > PSXDisplay.DisplayPosition.x) &&
\r
1883 (x < PSXDisplay.DisplayEnd.x) &&
\r
1884 (dy > PSXDisplay.DisplayPosition.y) &&
\r
1885 (y < PSXDisplay.DisplayEnd.y)))
\r
1888 if((!(PSXDisplay.InterlacedTest) &&
\r
1889 (dx > PreviousPSXDisplay.DisplayPosition.x) &&
\r
1890 (x < PreviousPSXDisplay.DisplayEnd.x) &&
\r
1891 (dy > PreviousPSXDisplay.DisplayPosition.y) &&
\r
1892 (y < PreviousPSXDisplay.DisplayEnd.y)))
\r
1899 if(dwActFixes&0x40)
\r
1903 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1905 bFullVRam=TRUE;iRenderFVR=2;
\r
1908 ux=x;uy=y;udx=dx;udy=dy;
\r
1912 x -=PSXDisplay.DisplayPosition.x;
\r
1913 dx-=PSXDisplay.DisplayPosition.x;
\r
1914 y -=PSXDisplay.DisplayPosition.y;
\r
1915 dy-=PSXDisplay.DisplayPosition.y;
\r
1916 wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x;
\r
1917 wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y;
\r
1921 x -=PreviousPSXDisplay.DisplayPosition.x;
\r
1922 dx-=PreviousPSXDisplay.DisplayPosition.x;
\r
1923 y -=PreviousPSXDisplay.DisplayPosition.y;
\r
1924 dy-=PreviousPSXDisplay.DisplayPosition.y;
\r
1925 wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x;
\r
1926 wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y;
\r
1928 if(x<0) {ux-=x;x=0;}
\r
1929 if(y<0) {uy-=y;y=0;}
\r
1930 if(dx>wx) {udx-=(dx-wx);dx=wx;}
\r
1931 if(dy>wy) {udy-=(dy-wy);dy=wy;}
\r
1935 p=(psxVuw + (1024*uy) + ux);
\r
1937 if(udx<=0) return;
\r
1938 if(udy<=0) return;
\r
1944 XS=(float)rRatioRect.right/(float)wx;
\r
1945 YS=(float)rRatioRect.bottom/(float)wy;
\r
1947 dx=(int)((float)(dx)*XS);
\r
1948 dy=(int)((float)(dy)*YS);
\r
1949 x=(int)((float)x*XS);
\r
1950 y=(int)((float)y*YS);
\r
1955 if(dx>iResX) dx=iResX;
\r
1956 if(dy>iResY) dy=iResY;
\r
1964 x+=rRatioRect.left;
\r
1965 y-=rRatioRect.top;
\r
1967 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1969 if(!pGfxCardScreen)
\r
1971 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1972 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);
\r
1975 ps=pGfxCardScreen;
\r
1977 // if(bFront) glReadBuffer(GL_FRONT);
\r
1979 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1981 // if(bFront) glReadBuffer(GL_BACK);
\r
1983 XS=(float)dx/(float)(udx);
\r
1984 YS=(float)dy/(float)(udy+1);
\r
1986 for(y=udy;y>0;y--)
\r
1988 for(x=0;x<udx;x++)
\r
1990 if(p>=psxVuw && p<psxVuw_eom)
\r
1992 px=ps+(3*((int)((float)x * XS))+
\r
1993 (3*dx)*((int)((float)y*YS)));
\r
2009 ////////////////////////////////////////////////////////////////////////
\r
2010 // core read from vram
\r
2011 ////////////////////////////////////////////////////////////////////////
\r
2014 void CALLBACK GPUreadDataMem(unsigned int * pMem, int iSize)
\r
2016 void CALLBACK GPUreadDataMem(unsigned long * pMem, int iSize)
\r
2021 if(iDataReadMode!=DR_VRAMTRANSFER) return;
\r
2025 // adjust read ptr, if necessary
\r
2026 while(VRAMRead.ImagePtr>=psxVuw_eom)
\r
2027 VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2028 while(VRAMRead.ImagePtr<psxVuw)
\r
2029 VRAMRead.ImagePtr+=iGPUHeight*1024;
\r
2031 if((iFrameReadType&1 && iSize>1) &&
\r
2032 !(iDrawnSomething==2 &&
\r
2033 VRAMRead.x == VRAMWrite.x &&
\r
2034 VRAMRead.y == VRAMWrite.y &&
\r
2035 VRAMRead.Width == VRAMWrite.Width &&
\r
2036 VRAMRead.Height == VRAMWrite.Height))
\r
2037 CheckVRamRead(VRAMRead.x,VRAMRead.y,
\r
2038 VRAMRead.x+VRAMRead.RowsRemaining,
\r
2039 VRAMRead.y+VRAMRead.ColsRemaining,
\r
2042 for(i=0;i<iSize;i++)
\r
2044 // do 2 seperate 16bit reads for compatibility (wrap issues)
\r
2045 if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))
\r
2048 GPUdataRet=(unsigned long)*VRAMRead.ImagePtr;
\r
2050 VRAMRead.ImagePtr++;
\r
2051 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2052 VRAMRead.RowsRemaining --;
\r
2054 if(VRAMRead.RowsRemaining<=0)
\r
2056 VRAMRead.RowsRemaining = VRAMRead.Width;
\r
2057 VRAMRead.ColsRemaining--;
\r
2058 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
\r
2059 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2062 // higher 16 bit (always, even if it's an odd width)
\r
2063 GPUdataRet|=(unsigned long)(*VRAMRead.ImagePtr)<<16;
\r
2064 *pMem++=GPUdataRet;
\r
2066 if(VRAMRead.ColsRemaining <= 0)
\r
2067 {FinishedVRAMRead();goto ENDREAD;}
\r
2069 VRAMRead.ImagePtr++;
\r
2070 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2071 VRAMRead.RowsRemaining--;
\r
2072 if(VRAMRead.RowsRemaining<=0)
\r
2074 VRAMRead.RowsRemaining = VRAMRead.Width;
\r
2075 VRAMRead.ColsRemaining--;
\r
2076 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
\r
2077 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2079 if(VRAMRead.ColsRemaining <= 0)
\r
2080 {FinishedVRAMRead();goto ENDREAD;}
\r
2082 else {FinishedVRAMRead();goto ENDREAD;}
\r
2090 unsigned long CALLBACK GPUreadData(void)
\r
2092 unsigned long CALLBACK GPUreadData(void)
\r
2097 GPUreadDataMem(&l,1);
\r
2099 GPUreadDataMem(&l,1);
\r
2101 return GPUdataRet;
\r
2104 ////////////////////////////////////////////////////////////////////////
\r
2105 // helper table to know how much data is used by drawing commands
\r
2106 ////////////////////////////////////////////////////////////////////////
\r
2108 const u8 primTableCX[256] =
\r
2125 8,8,8,8,12,12,12,12,
\r
2129 // 5,5,5,5,6,6,6,6, //FLINE
\r
2130 254,254,254,254,254,254,254,254,
\r
2134 // 7,7,7,7,9,9,9,9, // LINEG3 LINEG4
\r
2135 255,255,255,255,255,255,255,255,
\r
2137 3,3,3,3,4,4,4,4, // TILE SPRT
\r
2139 2,2,2,2,3,3,3,3, // TILE1
\r
2178 ////////////////////////////////////////////////////////////////////////
\r
2179 // processes data send to GPU data register
\r
2180 ////////////////////////////////////////////////////////////////////////
\r
2183 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)
\r
2185 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)
\r
2189 unsigned long gdata=0;
\r
2192 GPUIsNotReadyForCommands;
\r
2196 if(iDataWriteMode==DR_VRAMTRANSFER)
\r
2198 // make sure we are in vram
\r
2199 while(VRAMWrite.ImagePtr>=psxVuw_eom)
\r
2200 VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2201 while(VRAMWrite.ImagePtr<psxVuw)
\r
2202 VRAMWrite.ImagePtr+=iGPUHeight*1024;
\r
2204 // now do the loop
\r
2205 while(VRAMWrite.ColsRemaining>0)
\r
2207 while(VRAMWrite.RowsRemaining>0)
\r
2209 if(i>=iSize) {goto ENDVRAM;}
\r
2214 *VRAMWrite.ImagePtr++ = (unsigned short)gdata;
\r
2215 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2216 VRAMWrite.RowsRemaining --;
\r
2218 if(VRAMWrite.RowsRemaining <= 0)
\r
2220 VRAMWrite.ColsRemaining--;
\r
2221 if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width
\r
2223 gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16);
\r
2224 FinishedVRAMWrite();
\r
2227 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
2228 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
2231 *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16);
\r
2232 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2233 VRAMWrite.RowsRemaining --;
\r
2236 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
2237 VRAMWrite.ColsRemaining--;
\r
2238 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
2241 FinishedVRAMWrite();
\r
2246 if(iDataWriteMode==DR_NORMAL)
\r
2248 void (* *primFunc)(u8 *);
\r
2249 if(bSkipNextFrame) primFunc=primTableSkip;
\r
2250 else primFunc=primTableJ;
\r
2254 if(iDataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;
\r
2256 gdata=*pMem++;i++;
\r
2260 command = (u8)((gdata>>24) & 0xff);
\r
2262 if(primTableCX[command])
\r
2264 gpuDataC = primTableCX[command];
\r
2265 gpuCommand = command;
\r
2266 gpuDataM[0] = gdata;
\r
2273 gpuDataM[gpuDataP] = gdata;
\r
2276 if((gpuDataC==254 && gpuDataP>=3) ||
\r
2277 (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))
\r
2279 if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)
\r
2280 gpuDataP=gpuDataC-1;
\r
2286 if(gpuDataP == gpuDataC)
\r
2288 gpuDataC=gpuDataP=0;
\r
2289 primFunc[gpuCommand]((u8 *)gpuDataM);
\r
2291 if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games
\r
2299 GPUIsReadyForCommands;
\r
2303 ////////////////////////////////////////////////////////////////////////
\r
2306 void CALLBACK GPUwriteData(unsigned long gdata)
\r
2308 void CALLBACK GPUwriteData(unsigned long gdata)
\r
2312 GPUwriteDataMem(&gdata,1);
\r
2314 GPUwriteDataMem(&gdata,1);
\r
2318 ////////////////////////////////////////////////////////////////////////
\r
2319 // this function will be removed soon (or 'soonish') (or never)
\r
2320 ////////////////////////////////////////////////////////////////////////
\r
2322 void CALLBACK GPUsetMode(unsigned int gdata)
\r
2324 // ignore old psemu setmode:
\r
2326 // imageTransfer = gdata;
\r
2327 // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2328 // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2331 // and this function will be removed soon as well, hehehe...
\r
2332 long CALLBACK GPUgetMode(void)
\r
2334 // ignore old psemu setmode
\r
2335 // return imageTransfer;
\r
2339 if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1;
\r
2340 if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2;
\r
2345 ////////////////////////////////////////////////////////////////////////
\r
2346 // call config dlg (Windows + Linux)
\r
2347 ////////////////////////////////////////////////////////////////////////
\r
2351 /*#include <unistd.h>
\r
2353 void StartCfgTool(s8 * pCmdLine) // linux: start external cfg tool
\r
2355 FILE * cf;s8 filename[255],t[255];
\r
2357 strcpy(filename,"cfg/cfgPeopsMesaGL"); // look in cfg sub folder first
\r
2358 cf=fopen(filename,"rb");
\r
2364 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2370 strcpy(filename,"cfgPeopsMesaGL"); // look in current folder
\r
2371 cf=fopen(filename,"rb");
\r
2375 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2380 sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder
\r
2381 cf=fopen(filename,"rb");
\r
2386 chdir(getenv("HOME"));
\r
2387 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2391 else printf("cfgPeopsMesaGL not found!\n");
\r
2400 long CALLBACK GPUconfigure(void)
\r
2402 long CALLBACK GPUconfigure(void)
\r
2407 // HWND hWP=GetActiveWindow();
\r
2408 // DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG),
\r
2409 // hWP,(DLGPROC)CfgDlgProc);
\r
2412 // StartCfgTool("CFG");
\r
2419 ////////////////////////////////////////////////////////////////////////
\r
2420 // sets all kind of act fixes
\r
2421 ////////////////////////////////////////////////////////////////////////
\r
2423 void SetFixes(void)
\r
2427 if(dwActFixes & 0x2000)
\r
2428 dispWidths[4]=384;
\r
2429 else dispWidths[4]=368;
\r
2432 ////////////////////////////////////////////////////////////////////////
\r
2433 // Pete Special: make an 'intelligent' dma chain check (<-Tekken3)
\r
2434 ////////////////////////////////////////////////////////////////////////
\r
2436 unsigned long lUsedAddr[3];
\r
2438 __inline BOOL CheckForEndlessLoop(unsigned long laddr)
\r
2440 if(laddr==lUsedAddr[1]) return TRUE;
\r
2441 if(laddr==lUsedAddr[2]) return TRUE;
\r
2443 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
\r
2444 else lUsedAddr[2]=laddr;
\r
2445 lUsedAddr[0]=laddr;
\r
2449 ////////////////////////////////////////////////////////////////////////
\r
2450 // core gives a dma chain to gpu: same as the gpuwrite interface funcs
\r
2451 ////////////////////////////////////////////////////////////////////////
\r
2454 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)
\r
2456 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)
\r
2459 unsigned long dmaMem;
\r
2461 short count;unsigned int DMACommandCounter = 0;
\r
2463 if(bIsFirstFrame) GLinitialize();
\r
2467 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
\r
2469 baseAddrB = (u8*) baseAddrL;
\r
2473 if(iGPUHeight==512) addr&=0x1FFFFC;
\r
2475 if(DMACommandCounter++ > 2000000) break;
\r
2476 if(CheckForEndlessLoop(addr)) break;
\r
2478 count = baseAddrB[addr+3];
\r
2483 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
\r
2485 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
\r
2488 addr = baseAddrL[addr>>2]&0xffffff;
\r
2490 while (addr != 0xffffff);
\r
2497 ////////////////////////////////////////////////////////////////////////
\r
2499 ////////////////////////////////////////////////////////////////////////
\r
2502 void CALLBACK GPUabout(void)
\r
2504 void CALLBACK GPUabout(void)
\r
2510 ////////////////////////////////////////////////////////////////////////
\r
2511 // We are ever fine ;)
\r
2512 ////////////////////////////////////////////////////////////////////////
\r
2515 long CALLBACK GPUtest(void)
\r
2517 long CALLBACK GPUtest(void)
\r
2520 // if test fails this function should return negative value for error (unable to continue)
\r
2521 // and positive value for warning (can continue but output might be crappy)
\r
2526 ////////////////////////////////////////////////////////////////////////
\r
2527 // save state funcs
\r
2528 ////////////////////////////////////////////////////////////////////////
\r
2530 ////////////////////////////////////////////////////////////////////////
\r
2533 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)
\r
2535 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)
\r
2538 if(ulGetFreezeData==2)
\r
2540 long lSlotNum=*((long *)pF);
\r
2541 if(lSlotNum<0) return 0;
\r
2542 if(lSlotNum>8) return 0;
\r
2543 lSelectedSlot=lSlotNum+1;
\r
2547 if(!pF) return 0;
\r
2548 if(pF->ulFreezeVersion!=1) return 0;
\r
2550 if(ulGetFreezeData==1)
\r
2552 pF->ulStatus=STATUSREG;
\r
2553 memcpy(pF->ulControl,ulStatusControl,256*sizeof(unsigned long));
\r
2554 memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2);
\r
2559 if(ulGetFreezeData!=0) return 0;
\r
2561 STATUSREG=pF->ulStatus;
\r
2562 memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long));
\r
2563 memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2);
\r
2565 ResetTextureArea(TRUE);
\r
2568 GPUwriteStatus(ulStatusControl[0]);
\r
2569 GPUwriteStatus(ulStatusControl[1]);
\r
2570 GPUwriteStatus(ulStatusControl[2]);
\r
2571 GPUwriteStatus(ulStatusControl[3]);
\r
2572 GPUwriteStatus(ulStatusControl[8]);
\r
2573 GPUwriteStatus(ulStatusControl[6]);
\r
2574 GPUwriteStatus(ulStatusControl[7]);
\r
2575 GPUwriteStatus(ulStatusControl[5]);
\r
2576 GPUwriteStatus(ulStatusControl[4]);
\r
2578 GPUwriteStatus(ulStatusControl[0]);
\r
2579 GPUwriteStatus(ulStatusControl[1]);
\r
2580 GPUwriteStatus(ulStatusControl[2]);
\r
2581 GPUwriteStatus(ulStatusControl[3]);
\r
2582 GPUwriteStatus(ulStatusControl[8]);
\r
2583 GPUwriteStatus(ulStatusControl[6]);
\r
2584 GPUwriteStatus(ulStatusControl[7]);
\r
2585 GPUwriteStatus(ulStatusControl[5]);
\r
2586 GPUwriteStatus(ulStatusControl[4]);
\r
2591 ////////////////////////////////////////////////////////////////////////
\r
2592 // special "emu infos" / "emu effects" functions
\r
2593 ////////////////////////////////////////////////////////////////////////
\r
2598 //11 = transparent
\r
2600 u8 cFont[10][120]=
\r
2603 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,0x00,
\r
2608 0x80,0x00,0x05,0x54,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,0x14,0x05,0x00,0x00,
\r
2617 0x80,0x00,0x05,0x54,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2622 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2625 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,
\r
2630 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2631 0x80,0x00,0x05,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,0x00,0x50,0x00,0x00,
\r
2639 0x80,0x00,0x05,0x55,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2644 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2647 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,0x00,
\r
2652 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2653 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2654 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2655 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2656 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2657 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2658 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2659 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2660 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2661 0x80,0x00,0x15,0x55,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2666 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2669 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,0x00,
\r
2674 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2675 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2676 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2677 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2678 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2679 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2680 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2681 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2682 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2683 0x80,0x00,0x05,0x54,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2688 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2691 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,
\r
2696 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2697 0x80,0x00,0x00,0x54,0x00,0x00,
\r
2698 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2699 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2700 0x80,0x00,0x05,0x14,0x00,0x00,
\r
2701 0x80,0x00,0x14,0x14,0x00,0x00,
\r
2702 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2703 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2704 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2705 0x80,0x00,0x00,0x55,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2710 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2713 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,0x00,
\r
2718 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2719 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2720 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2721 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2722 0x80,0x00,0x15,0x54,0x00,0x00,
\r
2723 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2724 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2725 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2726 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2727 0x80,0x00,0x05,0x54,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2732 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2735 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,0x00,
\r
2740 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2741 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2742 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2743 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2744 0x80,0x00,0x15,0x54,0x00,0x00,
\r
2745 0x80,0x00,0x15,0x05,0x00,0x00,
\r
2746 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2747 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2748 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2749 0x80,0x00,0x05,0x54,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2754 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2757 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,0x00,
\r
2762 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2763 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2764 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2765 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2766 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2767 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2768 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2769 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2770 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2771 0x80,0x00,0x05,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2776 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2779 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,0x00,
\r
2784 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2785 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2786 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2787 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2788 0x80,0x00,0x05,0x54,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,0x14,0x05,0x00,0x00,
\r
2793 0x80,0x00,0x05,0x54,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2798 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2801 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\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,0x00,0x00,0x00,0x00,
\r
2806 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2807 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2808 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2809 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2810 0x80,0x00,0x14,0x15,0x00,0x00,
\r
2811 0x80,0x00,0x05,0x55,0x00,0x00,
\r
2812 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2813 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2814 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2815 0x80,0x00,0x05,0x50,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 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2820 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2824 ////////////////////////////////////////////////////////////////////////
\r
2826 void PaintPicDot(u8 * p,u8 c)
\r
2828 if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;}
\r
2829 if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;}
\r
2830 if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;}
\r
2833 ////////////////////////////////////////////////////////////////////////
\r
2836 void CALLBACK GPUgetScreenPic(u8 * pMem)
\r
2838 long CALLBACK GPUgetScreenPic(u8 * pMem)
\r
2841 float XS,YS;int x,y,v;
\r
2842 u8 * ps, * px, * pf;
\r
2845 if(!pGfxCardScreen)
\r
2847 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
2848 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);
\r
2851 ps=pGfxCardScreen;
\r
2853 // glReadBuffer(GL_FRONT);
\r
2855 glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
2857 // glReadBuffer(GL_BACK);
\r
2859 XS=(float)iResX/128;
\r
2860 YS=(float)iResY/96;
\r
2865 for(x=0;x<128;x++)
\r
2867 px=ps+(3*((int)((float)x * XS))+
\r
2868 (3*iResX)*((int)((float)y*YS)));
\r
2876 /////////////////////////////////////////////////////////////////////
\r
2877 // generic number/border painter
\r
2885 c=cFont[lSelectedSlot][x+y*6];
\r
2887 PaintPicDot(pf,(u8)v);pf+=3; // paint the dots into the rect
\r
2889 PaintPicDot(pf,(u8)v);pf+=3;
\r
2891 PaintPicDot(pf,(u8)v);pf+=3;
\r
2893 PaintPicDot(pf,(u8)v);pf+=3;
\r
2899 for(x=0;x<128;x++)
\r
2901 *(pf+(95*128*3))=0x00;*pf++=0x00;
\r
2902 *(pf+(95*128*3))=0x00;*pf++=0x00;
\r
2903 *(pf+(95*128*3))=0xff;*pf++=0xff;
\r
2908 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2909 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2910 *(pf+(127*3))=0xff;*pf++=0xff;
\r
2916 ////////////////////////////////////////////////////////////////////////
\r
2919 void CALLBACK GPUshowScreenPic(u8 * pMem)
\r
2921 long CALLBACK GPUshowScreenPic(u8 * pMem)
\r
2925 // if(pMem==0) return;
\r
2926 // CreatePic(pMem);
\r
2929 ////////////////////////////////////////////////////////////////////////
\r
2931 void CALLBACK GPUsetfix(unsigned long dwFixBits)
\r
2933 dwEmuFixes=dwFixBits;
\r
2936 ////////////////////////////////////////////////////////////////////////
\r
2938 void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig)
\r
2942 if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width
\r
2943 iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x);
\r
2945 // big rumble: 4...15 sp ; small rumble 1...3 sp
\r
2946 if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10));
\r
2947 else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10));
\r
2949 srand(timeGetTime()); // init rand (will be used in BufferSwap)
\r
2951 iRumbleTime=15; // let the rumble last 16 buffer swaps
\r
2954 ////////////////////////////////////////////////////////////////////////
\r
2955 // main emu can set display infos (A/M/G/D)
\r
2956 ////////////////////////////////////////////////////////////////////////
\r
2958 void CALLBACK GPUdisplayFlags(unsigned long dwFlags)
\r
2960 // dwCoreFlags=dwFlags;
\r