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
86 unsigned char *psxVSecure;
\r
87 unsigned char *psxVub;
\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
115 char szDispBuf[64];
\r
117 static unsigned long gpuDataM[256];
\r
118 static unsigned char 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 unsigned char * 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 static void (*rearmed_get_layer_pos)(int *x, int *y, int *w, int *h);
\r
159 ////////////////////////////////////////////////////////////////////////
\r
160 // stuff to make this a true PDK module
\r
161 ////////////////////////////////////////////////////////////////////////
\r
164 char * CALLBACK PSEgetLibName(void)
\r
169 unsigned long CALLBACK PSEgetLibType(void)
\r
174 unsigned long CALLBACK PSEgetLibVersion(void)
\r
176 return 1<<16|1<<8|1;
\r
180 ////////////////////////////////////////////////////////////////////////
\r
181 // snapshot funcs (saves screen to bitmap / text infos into file)
\r
182 ////////////////////////////////////////////////////////////////////////
\r
184 void ResizeWindow()
\r
186 rRatioRect.left = rRatioRect.top=0;
\r
187 rRatioRect.right = iResX;
\r
188 rRatioRect.bottom = iResY;
\r
189 glViewport(rRatioRect.left, // init viewport by ratio rect
\r
190 iResY-(rRatioRect.top+rRatioRect.bottom),
\r
192 rRatioRect.bottom);
\r
194 glScissor(0, 0, iResX, iResY); // init clipping (fullscreen)
\r
195 glEnable(GL_SCISSOR_TEST);
\r
198 glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale"
\r
200 glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack
\r
203 glMatrixMode(GL_PROJECTION); // init projection with psx resolution
\r
205 glOrtho(0,PSXDisplay.DisplayMode.x,
\r
206 PSXDisplay.DisplayMode.y, 0, -1, 1);
\r
211 char * GetConfigInfos(int hW)
\r
214 HDC hdc;HGLRC hglrc;
\r
216 char szO[2][4]={"off","on "};
\r
218 char * pB=(char *)malloc(32767);
\r
220 if(!pB) return NULL;
\r
222 //----------------------------------------------------//
\r
229 bSetupPixelFormat(hdc);
\r
230 hglrc = wglCreateContext(hdc);
\r
231 wglMakeCurrent(hdc, hglrc);
\r
234 sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR));
\r
236 sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER));
\r
238 sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION));
\r
240 //strcat(pB,(char *)glGetString(GL_EXTENSIONS));
\r
241 //strcat(pB,"\r\n\r\n");
\r
246 wglMakeCurrent(NULL, NULL);
\r
247 wglDeleteContext(hglrc);
\r
250 //----------------------------------------------------//
\r
252 if(hW && bWindowMode)
\r
253 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize));
\r
255 sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY);
\r
257 if(bWindowMode) sprintf(szTxt,"Window mode\r\n");
\r
260 sprintf(szTxt,"Fullscreen ");
\r
262 if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth);
\r
263 else sprintf(szTxt,"- NO desktop changing\r\n");
\r
267 // if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]);
\r
268 // else strcpy(szTxt,"- V-Sync: Driver\r\n");
\r
270 sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]);
\r
272 //----------------------------------------------------//
\r
273 strcpy(szTxt,"Textures:\r\n- ");
\r
274 /*! if(iTexQuality==0) strcat(szTxt,"Default");
\r
275 else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4");
\r
276 else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1");
\r
277 else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8");
\r
278 else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8");
\r
279 if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n");
\r
280 else strcat(szTxt,"\r\n");
\r
284 sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType);
\r
285 if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n");
\r
286 else strcat(szTxt,"NOT supported\r\n");
\r
288 else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType);
\r
290 sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures);
\r
294 sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]);
\r
298 /*sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize);
\r
300 sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt);
\r
301 else strcat(szTxt,"\r\n\r\n");
\r
303 //----------------------------------------------------//
\r
304 sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]);
\r
306 sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]);
\r
309 strcpy(szTxt,"- FPS limit: Auto\r\n\r\n");
\r
310 else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate);
\r
312 //----------------------------------------------------//
\r
313 sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing);
\r
315 sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType);
\r
316 if(!hW && iFrameTexType==2)
\r
318 if(gTexFrameName) strcat(szTxt," - texture created\r\n");
\r
319 else strcat(szTxt," - not used yet\r\n");
\r
321 else strcat(szTxt,"\r\n");
\r
323 sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType);
\r
325 // sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]);
\r
327 sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]);
\r
329 //sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]);
\r
330 //if(!hW && bAdvancedBlend)
\r
332 // if(bGLBlend) strcat(szTxt," (hardware)\r\n");
\r
333 // else strcat(szTxt," (software)\r\n");
\r
335 strcat(szTxt,"\r\n");
\r
340 strcpy(szTxt,"- Subtractive blending: ");
\r
341 // if(glBlendEquationEXTEx)
\r
343 // if(bUseMultiPass) strcat(szTxt,"supported, but not used!");
\r
344 // else strcat(szTxt,"activated");
\r
346 strcat(szTxt," NOT supported!");
\r
347 strcat(szTxt,"\r\n\r\n");
\r
349 else strcpy(szTxt,"\r\n");
\r
352 //----------------------------------------------------//
\r
353 sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]);
\r
355 if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend);
\r
356 else strcpy(szTxt,"\r\n");
\r
358 // sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]);
\r
360 // sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]);
\r
361 // fwrite(szTxt,lstrlen(szTxt),1,txtfile);
\r
362 sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]);
\r
364 sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]);
\r
366 sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]);
\r
368 sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]);
\r
370 if(!hW && iBlurBuffer)
\r
372 if(gTexBlurName) strcat(pB," - supported\r\n");
\r
373 else strcat(pB," - not supported\r\n");
\r
375 else strcat(pB,"\r\n");
\r
376 sprintf(szTxt,"- Game fixes: %s [%08lx]\r\n",szO[bUseFixes],dwCfgFixes);
\r
378 //----------------------------------------------------//
\r
382 ////////////////////////////////////////////////////////////////////////
\r
383 // save text infos to file
\r
384 ////////////////////////////////////////////////////////////////////////
\r
386 void DoTextSnapShot(int iNum)
\r
390 ////////////////////////////////////////////////////////////////////////
\r
391 // saves screen bitmap to file
\r
392 ////////////////////////////////////////////////////////////////////////
\r
394 void DoSnapShot(void)
\r
399 void CALLBACK GPUmakeSnapshot(void)
\r
401 void CALLBACK GPUmakeSnapshot(void)
\r
404 //bSnapShot = TRUE;
\r
407 ////////////////////////////////////////////////////////////////////////
\r
408 // GPU INIT... here starts it all (first func called by emu)
\r
409 ////////////////////////////////////////////////////////////////////////
\r
412 long CALLBACK GPUinit()
\r
414 long CALLBACK GPUinit()
\r
417 memset(ulStatusControl,0,256*sizeof(unsigned long));
\r
420 iResX=240;iResY=320;
\r
429 iWinSize=MAKELONG(iResX,iResY);
\r
433 // different ways of accessing PSX VRAM
\r
435 psxVSecure=(unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security
\r
436 if(!psxVSecure) return -1;
\r
438 psxVub=psxVSecure+512*1024; // security offset into double sized psx vram!
\r
439 psxVsb=(signed char *)psxVub;
\r
440 psxVsw=(signed short *)psxVub;
\r
441 psxVsl=(signed long *)psxVub;
\r
442 psxVuw=(unsigned short *)psxVub;
\r
443 psxVul=(unsigned long *)psxVub;
\r
445 psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram
\r
447 memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024));
\r
448 memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));
\r
450 InitFrameCap(); // init frame rate stuff
\r
452 PSXDisplay.RGB24 = 0; // init vars
\r
453 PreviousPSXDisplay.RGB24= 0;
\r
454 PSXDisplay.Interlaced = 0;
\r
455 PSXDisplay.InterlacedTest=0;
\r
456 PSXDisplay.DrawOffset.x = 0;
\r
457 PSXDisplay.DrawOffset.y = 0;
\r
458 PSXDisplay.DrawArea.x0 = 0;
\r
459 PSXDisplay.DrawArea.y0 = 0;
\r
460 PSXDisplay.DrawArea.x1 = 320;
\r
461 PSXDisplay.DrawArea.y1 = 240;
\r
462 PSXDisplay.DisplayMode.x= 320;
\r
463 PSXDisplay.DisplayMode.y= 240;
\r
464 PSXDisplay.Disabled = FALSE;
\r
465 PreviousPSXDisplay.Range.x0 =0;
\r
466 PreviousPSXDisplay.Range.x1 =0;
\r
467 PreviousPSXDisplay.Range.y0 =0;
\r
468 PreviousPSXDisplay.Range.y1 =0;
\r
469 PSXDisplay.Range.x0=0;
\r
470 PSXDisplay.Range.x1=0;
\r
471 PSXDisplay.Range.y0=0;
\r
472 PSXDisplay.Range.y1=0;
\r
473 PreviousPSXDisplay.DisplayPosition.x = 1;
\r
474 PreviousPSXDisplay.DisplayPosition.y = 1;
\r
475 PSXDisplay.DisplayPosition.x = 1;
\r
476 PSXDisplay.DisplayPosition.y = 1;
\r
477 PreviousPSXDisplay.DisplayModeNew.y=0;
\r
478 PSXDisplay.Double=1;
\r
481 PSXDisplay.DisplayModeNew.x=0;
\r
482 PSXDisplay.DisplayModeNew.y=0;
\r
484 //PreviousPSXDisplay.Height = PSXDisplay.Height = 239;
\r
486 iDataWriteMode = DR_NORMAL;
\r
488 // Reset transfer values, to prevent mis-transfer of data
\r
489 memset(&VRAMWrite,0,sizeof(VRAMLoad_t));
\r
490 memset(&VRAMRead,0,sizeof(VRAMLoad_t));
\r
492 // device initialised already !
\r
493 //lGPUstatusRet = 0x74000000;
\r
495 STATUSREG = 0x14802000;
\r
497 GPUIsReadyForCommands;
\r
503 ////////////////////////////////////////////////////////////////////////
\r
504 // GPU OPEN: funcs to open up the gpu display (Windows)
\r
505 ////////////////////////////////////////////////////////////////////////
\r
509 void ChangeDesktop() // change destop resolution
\r
511 DEVMODE dv;long lRes,iTry=0;
\r
513 while(iTry<10) // keep on hammering...
\r
515 memset(&dv,0,sizeof(DEVMODE));
\r
516 dv.dmSize=sizeof(DEVMODE);
\r
517 dv.dmBitsPerPel=iColDepth;
\r
518 dv.dmPelsWidth=iResX;
\r
519 dv.dmPelsHeight=iResY;
\r
521 dv.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
\r
523 lRes=ChangeDisplaySettings(&dv,0); // ...hammering the anvil
\r
525 if(lRes==DISP_CHANGE_SUCCESSFUL) return;
\r
530 ////////////////////////////////////////////////////////////////////////
\r
531 // OPEN interface func: attention!
\r
532 // some emus are calling this func in their main Window thread,
\r
533 // but all other interface funcs (to draw stuff) in a different thread!
\r
534 // that's a problem, since OGL is thread safe! Therefore we cannot
\r
535 // initialize the OGL stuff right here, we simply set a "bIsFirstFrame = TRUE"
\r
536 // flag, to initialize OGL on the first real draw call.
\r
537 // btw, we also call this open func ourselfes, each time when the user
\r
538 // is changing between fullscreen/window mode (ENTER key)
\r
539 // btw part 2: in windows the plugin gets the window handle from the
\r
540 // main emu, and doesn't create it's own window (if it would do it,
\r
541 // some PAD or SPU plugins would not work anymore)
\r
542 ////////////////////////////////////////////////////////////////////////
\r
544 HMENU hPSEMenu=NULL;
\r
546 long CALLBACK GPUopen(HWND hwndGPU)
\r
548 long CALLBACK GPUopen(int hwndGPU)
\r
552 HDC hdc;RECT r;DEVMODE dv;
\r
554 hWWindow = hwndGPU; // store hwnd globally
\r
556 // InitKeyHandler(); // init key handler (subclass window)
\r
561 iResX=240;iResY=320;
\r
563 iResX=800;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
1123 xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x;
\r
1124 ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y;
\r
1127 r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s);
\r
1128 r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s);
\r
1129 if(r.right > iResX) r.right = iResX;
\r
1130 if(r.bottom > iResY) r.bottom = iResY;
\r
1131 if(r.right < 1) r.right = 1;
\r
1132 if(r.bottom < 1) r.bottom = 1;
\r
1134 r.left = (iResX-r.right)/2;
\r
1135 r.top = (iResY-r.bottom)/2;
\r
1137 if(r.bottom<rRatioRect.bottom ||
\r
1138 r.right <rRatioRect.right)
\r
1141 glClearColor(0,0,0,128);
\r
1143 if(r.right <rRatioRect.right)
\r
1149 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1150 glClear(uiBufferBits);
\r
1151 rC.left=iResX-rC.right;
\r
1152 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1153 glClear(uiBufferBits);
\r
1156 if(r.bottom <rRatioRect.bottom)
\r
1162 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1163 glClear(uiBufferBits);
\r
1164 rC.top=iResY-rC.bottom;
\r
1165 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1166 glClear(uiBufferBits);
\r
1170 bDisplayNotSet=TRUE;
\r
1175 // pcsx-rearmed hack
\r
1176 if (rearmed_get_layer_pos != NULL)
\r
1177 rearmed_get_layer_pos(&rRatioRect.left, &rRatioRect.top, &rRatioRect.right, &rRatioRect.bottom);
\r
1180 glViewport(rRatioRect.left,
\r
1181 iResY-(rRatioRect.top+rRatioRect.bottom),
\r
1183 rRatioRect.bottom); // init viewport
\r
1186 ////////////////////////////////////////////////////////////////////////
\r
1187 // big ass check, if an ogl swap buffer is needed
\r
1188 ////////////////////////////////////////////////////////////////////////
\r
1190 void updateDisplayIfChanged(void)
\r
1194 if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) &&
\r
1195 (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))
\r
1197 if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) &&
\r
1198 (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew))
\r
1199 return; // nothing has changed? fine, no swap buffer needed
\r
1201 else // some res change?
\r
1204 glOrtho(0,PSXDisplay.DisplayModeNew.x, // -> new psx resolution
\r
1205 PSXDisplay.DisplayModeNew.y, 0, -1, 1);
\r
1206 if(bKeepRatio) SetAspectRatio();
\r
1209 bDisplayNotSet = TRUE; // re-calc offsets/display area
\r
1212 if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off)
\r
1214 PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet
\r
1215 ResetTextureArea(FALSE);
\r
1219 PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos
\r
1220 PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;
\r
1221 PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;
\r
1222 PSXDisplay.Interlaced = PSXDisplay.InterlacedNew;
\r
1224 PSXDisplay.DisplayEnd.x= // calc new ends
\r
1225 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1226 PSXDisplay.DisplayEnd.y=
\r
1227 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1228 PreviousPSXDisplay.DisplayEnd.x=
\r
1229 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1230 PreviousPSXDisplay.DisplayEnd.y=
\r
1231 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1233 ChangeDispOffsetsX();
\r
1235 if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace)
\r
1237 if(bUp) updateDisplay(); // yeah, real update (swap buffer)
\r
1240 ////////////////////////////////////////////////////////////////////////
\r
1241 // window mode <-> fullscreen mode (windows)
\r
1242 ////////////////////////////////////////////////////////////////////////
\r
1245 void ChangeWindowMode(void)
\r
1248 bWindowMode=!bWindowMode;
\r
1249 GPUopen(hWWindow);
\r
1250 bChangeWinMode=FALSE;
\r
1254 ////////////////////////////////////////////////////////////////////////
\r
1255 // swap update check (called by psx vsync function)
\r
1256 ////////////////////////////////////////////////////////////////////////
\r
1258 BOOL bSwapCheck(void)
\r
1260 static int iPosCheck=0;
\r
1261 static PSXPoint_t pO;
\r
1262 static PSXPoint_t pD;
\r
1263 static int iDoAgain=0;
\r
1265 if(PSXDisplay.DisplayPosition.x==pO.x &&
\r
1266 PSXDisplay.DisplayPosition.y==pO.y &&
\r
1267 PSXDisplay.DisplayEnd.x==pD.x &&
\r
1268 PSXDisplay.DisplayEnd.y==pD.y)
\r
1272 pO=PSXDisplay.DisplayPosition;
\r
1273 pD=PSXDisplay.DisplayEnd;
\r
1275 if(iPosCheck<=4) return FALSE;
\r
1279 if(PSXDisplay.Interlaced) return FALSE;
\r
1281 if (bNeedInterlaceUpdate||
\r
1282 bNeedRGB24Update ||
\r
1283 bNeedUploadAfter||
\r
1284 bNeedUploadTest ||
\r
1289 if(bNeedUploadAfter)
\r
1291 if(bNeedUploadTest && PSXDisplay.InterlacedTest)
\r
1294 bDisplayNotSet = TRUE;
\r
1297 PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x;
\r
1298 PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y;
\r
1299 PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x;
\r
1300 PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y;
\r
1301 pO=PSXDisplay.DisplayPosition;
\r
1302 pD=PSXDisplay.DisplayEnd;
\r
1309 ////////////////////////////////////////////////////////////////////////
\r
1310 // gun cursor func: player=0-7, x=0-511, y=0-255
\r
1311 ////////////////////////////////////////////////////////////////////////
\r
1313 ////////////////////////////////////////////////////////////////////////
\r
1314 // update lace is called every VSync. Basically we limit frame rate
\r
1315 // here, and in interlaced mode we swap ogl display buffers.
\r
1316 ////////////////////////////////////////////////////////////////////////
\r
1318 static unsigned short usFirstPos=2;
\r
1321 void CALLBACK GPUupdateLace(void)
\r
1323 void CALLBACK GPUupdateLace(void)
\r
1326 if(!(dwActFixes&0x1000))
\r
1327 STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus)
\r
1329 if(!(dwActFixes&128)) // normal frame limit func
\r
1332 if(iOffscreenDrawing==4) // special check if high offscreen drawing is on
\r
1334 if(bSwapCheck()) return;
\r
1337 if(PSXDisplay.Interlaced) // interlaced mode?
\r
1339 if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)
\r
1341 updateDisplay(); // -> swap buffers (new frame)
\r
1344 else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed?
\r
1346 updateFrontDisplay(); // -> update front buffer
\r
1348 else if(usFirstPos==1) // initial updates (after startup)
\r
1354 if(bChangeWinMode) ChangeWindowMode();
\r
1358 ////////////////////////////////////////////////////////////////////////
\r
1359 // process read request from GPU status register
\r
1360 ////////////////////////////////////////////////////////////////////////
\r
1363 unsigned long CALLBACK GPUreadStatus(void)
\r
1365 unsigned long CALLBACK GPUreadStatus(void)
\r
1368 if(dwActFixes&0x1000) // CC game fix
\r
1370 static int iNumRead=0;
\r
1371 if((iNumRead++)==2)
\r
1374 STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross)
\r
1378 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
1382 if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims
\r
1385 GPUIsNotReadyForCommands;
\r
1390 GPUIsReadyForCommands;
\r
1397 ////////////////////////////////////////////////////////////////////////
\r
1398 // processes data send to GPU status register
\r
1399 // these are always single packet commands.
\r
1400 ////////////////////////////////////////////////////////////////////////
\r
1403 void CALLBACK GPUwriteStatus(unsigned long gdata)
\r
1405 void CALLBACK GPUwriteStatus(unsigned long gdata)
\r
1408 unsigned long lCommand=(gdata>>24)&0xff;
\r
1411 if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus)
\r
1414 ulStatusControl[lCommand]=gdata;
\r
1418 //--------------------------------------------------//
\r
1421 memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));
\r
1422 lGPUstatusRet=0x14802000;
\r
1423 PSXDisplay.Disabled=1;
\r
1424 iDataWriteMode=iDataReadMode=DR_NORMAL;
\r
1425 PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;
\r
1426 drawX=drawY=0;drawW=drawH=0;
\r
1427 sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0;
\r
1429 GlobalTextAddrX=0;GlobalTextAddrY=0;
\r
1430 GlobalTextTP=0;GlobalTextABR=0;
\r
1431 PSXDisplay.RGB24=FALSE;
\r
1432 PSXDisplay.Interlaced=FALSE;
\r
1433 bUsingTWin = FALSE;
\r
1436 // dis/enable display
\r
1438 PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;
\r
1439 PSXDisplay.Disabled = (gdata & 1);
\r
1441 if(PSXDisplay.Disabled)
\r
1442 STATUSREG|=GPUSTATUS_DISPLAYDISABLED;
\r
1443 else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED;
\r
1445 if (iOffscreenDrawing==4 &&
\r
1446 PreviousPSXDisplay.Disabled &&
\r
1447 !(PSXDisplay.Disabled))
\r
1450 if(!PSXDisplay.RGB24)
\r
1452 PrepareFullScreenUpload(TRUE);
\r
1453 UploadScreen(TRUE);
\r
1460 // setting transfer mode
\r
1462 gdata &= 0x03; // only want the lower two bits
\r
1464 iDataWriteMode=iDataReadMode=DR_NORMAL;
\r
1465 if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER;
\r
1466 if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER;
\r
1468 STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits
\r
1469 STATUSREG|=(gdata << 29); // set the DMA bits according to the received data
\r
1473 // setting display position
\r
1476 short sx=(short)(gdata & 0x3ff);
\r
1479 if(iGPUHeight==1024)
\r
1481 if(dwGPUVersion==2)
\r
1482 sy = (short)((gdata>>12)&0x3ff);
\r
1483 else sy = (short)((gdata>>10)&0x3ff);
\r
1485 else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later
\r
1490 PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double;
\r
1493 else PreviousPSXDisplay.DisplayModeNew.y=0;
\r
1502 PreviousPSXDisplay.DisplayPosition.x = sx;
\r
1503 PreviousPSXDisplay.DisplayPosition.y = sy;
\r
1504 PSXDisplay.DisplayPosition.x = sx;
\r
1505 PSXDisplay.DisplayPosition.y = sy;
\r
1511 if((!PSXDisplay.Interlaced) &&
\r
1512 PreviousPSXDisplay.DisplayPosition.x == sx &&
\r
1513 PreviousPSXDisplay.DisplayPosition.y == sy)
\r
1516 PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x;
\r
1517 PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y;
\r
1518 PreviousPSXDisplay.DisplayPosition.x = sx;
\r
1519 PreviousPSXDisplay.DisplayPosition.y = sy;
\r
1523 if((!PSXDisplay.Interlaced) &&
\r
1524 PSXDisplay.DisplayPosition.x == sx &&
\r
1525 PSXDisplay.DisplayPosition.y == sy)
\r
1527 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
\r
1528 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
\r
1529 PSXDisplay.DisplayPosition.x = sx;
\r
1530 PSXDisplay.DisplayPosition.y = sy;
\r
1533 PSXDisplay.DisplayEnd.x=
\r
1534 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1535 PSXDisplay.DisplayEnd.y=
\r
1536 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1538 PreviousPSXDisplay.DisplayEnd.x=
\r
1539 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1540 PreviousPSXDisplay.DisplayEnd.y=
\r
1541 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1543 bDisplayNotSet = TRUE;
\r
1545 if (!(PSXDisplay.Interlaced))
\r
1550 if(PSXDisplay.InterlacedTest &&
\r
1551 ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)||
\r
1552 (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y)))
\r
1553 PSXDisplay.InterlacedTest--;
\r
1561 PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff;
\r
1562 PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff;
\r
1564 PSXDisplay.Range.x1-=PSXDisplay.Range.x0;
\r
1566 ChangeDispOffsetsX();
\r
1573 PreviousPSXDisplay.Height = PSXDisplay.Height;
\r
1575 PSXDisplay.Range.y0=gdata & 0x3ff;
\r
1576 PSXDisplay.Range.y1=(gdata>>10) & 0x3ff;
\r
1578 PSXDisplay.Height = PSXDisplay.Range.y1 -
\r
1579 PSXDisplay.Range.y0 +
\r
1580 PreviousPSXDisplay.DisplayModeNew.y;
\r
1582 if (PreviousPSXDisplay.Height != PSXDisplay.Height)
\r
1584 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
\r
1585 ChangeDispOffsetsY();
\r
1586 updateDisplayIfChanged();
\r
1590 // setting display infos
\r
1593 PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];
\r
1595 if (gdata&0x04) PSXDisplay.Double=2;
\r
1596 else PSXDisplay.Double=1;
\r
1597 PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;
\r
1599 ChangeDispOffsetsY();
\r
1601 PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC
\r
1602 PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor
\r
1603 PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace
\r
1605 STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits
\r
1608 (((gdata & 0x03) << 17) |
\r
1609 ((gdata & 0x40) << 10)); // set the width bits
\r
1611 PreviousPSXDisplay.InterlacedNew=FALSE;
\r
1612 if (PSXDisplay.InterlacedNew)
\r
1614 if(!PSXDisplay.Interlaced)
\r
1616 PSXDisplay.InterlacedTest=2;
\r
1617 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
\r
1618 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
\r
1619 PreviousPSXDisplay.InterlacedNew=TRUE;
\r
1622 STATUSREG|=GPUSTATUS_INTERLACED;
\r
1626 PSXDisplay.InterlacedTest=0;
\r
1627 STATUSREG&=~GPUSTATUS_INTERLACED;
\r
1630 if (PSXDisplay.PAL)
\r
1631 STATUSREG|=GPUSTATUS_PAL;
\r
1632 else STATUSREG&=~GPUSTATUS_PAL;
\r
1634 if (PSXDisplay.Double==2)
\r
1635 STATUSREG|=GPUSTATUS_DOUBLEHEIGHT;
\r
1636 else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT;
\r
1638 if (PSXDisplay.RGB24New)
\r
1639 STATUSREG|=GPUSTATUS_RGB24;
\r
1640 else STATUSREG&=~GPUSTATUS_RGB24;
\r
1642 updateDisplayIfChanged();
\r
1646 //--------------------------------------------------//
\r
1647 // ask about GPU version and other stuff
\r
1655 GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos
\r
1658 GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start
\r
1661 GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end
\r
1665 GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset
\r
1668 if(dwGPUVersion==2)
\r
1670 else GPUdataRet=0x02; // gpu type
\r
1673 case 0x0F: // some bios addr?
\r
1674 GPUdataRet=0xBFC03720;
\r
1678 //--------------------------------------------------//
\r
1682 ////////////////////////////////////////////////////////////////////////
\r
1683 // vram read/write helpers
\r
1684 ////////////////////////////////////////////////////////////////////////
\r
1686 BOOL bNeedWriteUpload=FALSE;
\r
1688 __inline void FinishedVRAMWrite(void)
\r
1690 if(bNeedWriteUpload)
\r
1692 bNeedWriteUpload=FALSE;
\r
1693 CheckWriteUpdate();
\r
1696 // set register to NORMAL operation
\r
1697 iDataWriteMode = DR_NORMAL;
\r
1699 // reset transfer values, to prevent mis-transfer of data
\r
1700 VRAMWrite.ColsRemaining = 0;
\r
1701 VRAMWrite.RowsRemaining = 0;
\r
1704 __inline void FinishedVRAMRead(void)
\r
1706 // set register to NORMAL operation
\r
1707 iDataReadMode = DR_NORMAL;
\r
1708 // reset transfer values, to prevent mis-transfer of data
\r
1711 VRAMRead.Width = 0;
\r
1712 VRAMRead.Height = 0;
\r
1713 VRAMRead.ColsRemaining = 0;
\r
1714 VRAMRead.RowsRemaining = 0;
\r
1716 // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER
\r
1717 STATUSREG&=~GPUSTATUS_READYFORVRAM;
\r
1720 ////////////////////////////////////////////////////////////////////////
\r
1721 // vram read check ex (reading from card's back/frontbuffer if needed...
\r
1723 ////////////////////////////////////////////////////////////////////////
\r
1725 void CheckVRamReadEx(int x, int y, int dx, int dy)
\r
1727 unsigned short sArea;
\r
1728 int ux,uy,udx,udy,wx,wy;
\r
1729 unsigned short * p1, *p2;
\r
1731 unsigned char * ps;
\r
1732 unsigned char * px;
\r
1733 unsigned short s,sx;
\r
1735 if(STATUSREG&GPUSTATUS_RGB24) return;
\r
1737 if(((dx > PSXDisplay.DisplayPosition.x) &&
\r
1738 (x < PSXDisplay.DisplayEnd.x) &&
\r
1739 (dy > PSXDisplay.DisplayPosition.y) &&
\r
1740 (y < PSXDisplay.DisplayEnd.y)))
\r
1743 if((!(PSXDisplay.InterlacedTest) &&
\r
1744 (dx > PreviousPSXDisplay.DisplayPosition.x) &&
\r
1745 (x < PreviousPSXDisplay.DisplayEnd.x) &&
\r
1746 (dy > PreviousPSXDisplay.DisplayPosition.y) &&
\r
1747 (y < PreviousPSXDisplay.DisplayEnd.y)))
\r
1758 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1760 bFullVRam=TRUE;iRenderFVR=2;
\r
1768 ux=PSXDisplay.DisplayPosition.x;
\r
1769 uy=PSXDisplay.DisplayPosition.y;
\r
1770 udx=PSXDisplay.DisplayEnd.x-ux;
\r
1771 udy=PSXDisplay.DisplayEnd.y-uy;
\r
1772 if((PreviousPSXDisplay.DisplayEnd.x-
\r
1773 PreviousPSXDisplay.DisplayPosition.x)==udx &&
\r
1774 (PreviousPSXDisplay.DisplayEnd.y-
\r
1775 PreviousPSXDisplay.DisplayPosition.y)==udy)
\r
1776 p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) +
\r
1777 PreviousPSXDisplay.DisplayPosition.x);
\r
1781 ux=PreviousPSXDisplay.DisplayPosition.x;
\r
1782 uy=PreviousPSXDisplay.DisplayPosition.y;
\r
1783 udx=PreviousPSXDisplay.DisplayEnd.x-ux;
\r
1784 udy=PreviousPSXDisplay.DisplayEnd.y-uy;
\r
1785 if((PSXDisplay.DisplayEnd.x-
\r
1786 PSXDisplay.DisplayPosition.x)==udx &&
\r
1787 (PSXDisplay.DisplayEnd.y-
\r
1788 PSXDisplay.DisplayPosition.y)==udy)
\r
1789 p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) +
\r
1790 PSXDisplay.DisplayPosition.x);
\r
1793 p1=(psxVuw + (1024*uy) + ux);
\r
1797 wx=dx=udx;wy=dy=udy;
\r
1799 if(udx<=0) return;
\r
1800 if(udy<=0) return;
\r
1806 XS=(float)rRatioRect.right/(float)wx;
\r
1807 YS=(float)rRatioRect.bottom/(float)wy;
\r
1809 dx=(int)((float)(dx)*XS);
\r
1810 dy=(int)((float)(dy)*YS);
\r
1812 if(dx>iResX) dx=iResX;
\r
1813 if(dy>iResY) dy=iResY;
\r
1821 x+=rRatioRect.left;
\r
1822 y-=rRatioRect.top;
\r
1824 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1826 if(!pGfxCardScreen)
\r
1828 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1829 pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);
\r
1832 ps=pGfxCardScreen;
\r
1834 //if(!sArea) glReadBuffer(GL_FRONT);
\r
1836 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1838 //if(!sArea) glReadBuffer(GL_BACK);
\r
1842 XS=(float)dx/(float)(udx);
\r
1843 YS=(float)dy/(float)(udy+1);
\r
1845 for(y=udy;y>0;y--)
\r
1847 for(x=0;x<udx;x++)
\r
1849 if(p1>=psxVuw && p1<psxVuw_eom)
\r
1851 px=ps+(3*((int)((float)x * XS))+
\r
1852 (3*dx)*((int)((float)y*YS)));
\r
1862 if(p2>=psxVuw && p2<psxVuw_eom) *p2=s;
\r
1869 if(p2) p2 += 1024 - udx;
\r
1873 ////////////////////////////////////////////////////////////////////////
\r
1874 // vram read check (reading from card's back/frontbuffer if needed...
\r
1876 ////////////////////////////////////////////////////////////////////////
\r
1878 void CheckVRamRead(int x, int y, int dx, int dy, bool bFront)
\r
1880 unsigned short sArea;unsigned short * p;
\r
1881 int ux,uy,udx,udy,wx,wy;float XS,YS;
\r
1882 unsigned char * ps, * px;
\r
1883 unsigned short s=0,sx;
\r
1885 if(STATUSREG&GPUSTATUS_RGB24) return;
\r
1887 if(((dx > PSXDisplay.DisplayPosition.x) &&
\r
1888 (x < PSXDisplay.DisplayEnd.x) &&
\r
1889 (dy > PSXDisplay.DisplayPosition.y) &&
\r
1890 (y < PSXDisplay.DisplayEnd.y)))
\r
1893 if((!(PSXDisplay.InterlacedTest) &&
\r
1894 (dx > PreviousPSXDisplay.DisplayPosition.x) &&
\r
1895 (x < PreviousPSXDisplay.DisplayEnd.x) &&
\r
1896 (dy > PreviousPSXDisplay.DisplayPosition.y) &&
\r
1897 (y < PreviousPSXDisplay.DisplayEnd.y)))
\r
1904 if(dwActFixes&0x40)
\r
1908 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1910 bFullVRam=TRUE;iRenderFVR=2;
\r
1913 ux=x;uy=y;udx=dx;udy=dy;
\r
1917 x -=PSXDisplay.DisplayPosition.x;
\r
1918 dx-=PSXDisplay.DisplayPosition.x;
\r
1919 y -=PSXDisplay.DisplayPosition.y;
\r
1920 dy-=PSXDisplay.DisplayPosition.y;
\r
1921 wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x;
\r
1922 wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y;
\r
1926 x -=PreviousPSXDisplay.DisplayPosition.x;
\r
1927 dx-=PreviousPSXDisplay.DisplayPosition.x;
\r
1928 y -=PreviousPSXDisplay.DisplayPosition.y;
\r
1929 dy-=PreviousPSXDisplay.DisplayPosition.y;
\r
1930 wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x;
\r
1931 wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y;
\r
1933 if(x<0) {ux-=x;x=0;}
\r
1934 if(y<0) {uy-=y;y=0;}
\r
1935 if(dx>wx) {udx-=(dx-wx);dx=wx;}
\r
1936 if(dy>wy) {udy-=(dy-wy);dy=wy;}
\r
1940 p=(psxVuw + (1024*uy) + ux);
\r
1942 if(udx<=0) return;
\r
1943 if(udy<=0) return;
\r
1949 XS=(float)rRatioRect.right/(float)wx;
\r
1950 YS=(float)rRatioRect.bottom/(float)wy;
\r
1952 dx=(int)((float)(dx)*XS);
\r
1953 dy=(int)((float)(dy)*YS);
\r
1954 x=(int)((float)x*XS);
\r
1955 y=(int)((float)y*YS);
\r
1960 if(dx>iResX) dx=iResX;
\r
1961 if(dy>iResY) dy=iResY;
\r
1969 x+=rRatioRect.left;
\r
1970 y-=rRatioRect.top;
\r
1972 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1974 if(!pGfxCardScreen)
\r
1976 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1977 pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);
\r
1980 ps=pGfxCardScreen;
\r
1982 // if(bFront) glReadBuffer(GL_FRONT);
\r
1984 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1986 // if(bFront) glReadBuffer(GL_BACK);
\r
1988 XS=(float)dx/(float)(udx);
\r
1989 YS=(float)dy/(float)(udy+1);
\r
1991 for(y=udy;y>0;y--)
\r
1993 for(x=0;x<udx;x++)
\r
1995 if(p>=psxVuw && p<psxVuw_eom)
\r
1997 px=ps+(3*((int)((float)x * XS))+
\r
1998 (3*dx)*((int)((float)y*YS)));
\r
2014 ////////////////////////////////////////////////////////////////////////
\r
2015 // core read from vram
\r
2016 ////////////////////////////////////////////////////////////////////////
\r
2019 void CALLBACK GPUreadDataMem(unsigned int * pMem, int iSize)
\r
2021 void CALLBACK GPUreadDataMem(unsigned long * pMem, int iSize)
\r
2026 if(iDataReadMode!=DR_VRAMTRANSFER) return;
\r
2030 // adjust read ptr, if necessary
\r
2031 while(VRAMRead.ImagePtr>=psxVuw_eom)
\r
2032 VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2033 while(VRAMRead.ImagePtr<psxVuw)
\r
2034 VRAMRead.ImagePtr+=iGPUHeight*1024;
\r
2036 if((iFrameReadType&1 && iSize>1) &&
\r
2037 !(iDrawnSomething==2 &&
\r
2038 VRAMRead.x == VRAMWrite.x &&
\r
2039 VRAMRead.y == VRAMWrite.y &&
\r
2040 VRAMRead.Width == VRAMWrite.Width &&
\r
2041 VRAMRead.Height == VRAMWrite.Height))
\r
2042 CheckVRamRead(VRAMRead.x,VRAMRead.y,
\r
2043 VRAMRead.x+VRAMRead.RowsRemaining,
\r
2044 VRAMRead.y+VRAMRead.ColsRemaining,
\r
2047 for(i=0;i<iSize;i++)
\r
2049 // do 2 seperate 16bit reads for compatibility (wrap issues)
\r
2050 if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))
\r
2053 GPUdataRet=(unsigned long)*VRAMRead.ImagePtr;
\r
2055 VRAMRead.ImagePtr++;
\r
2056 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2057 VRAMRead.RowsRemaining --;
\r
2059 if(VRAMRead.RowsRemaining<=0)
\r
2061 VRAMRead.RowsRemaining = VRAMRead.Width;
\r
2062 VRAMRead.ColsRemaining--;
\r
2063 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
\r
2064 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2067 // higher 16 bit (always, even if it's an odd width)
\r
2068 GPUdataRet|=(unsigned long)(*VRAMRead.ImagePtr)<<16;
\r
2069 *pMem++=GPUdataRet;
\r
2071 if(VRAMRead.ColsRemaining <= 0)
\r
2072 {FinishedVRAMRead();goto ENDREAD;}
\r
2074 VRAMRead.ImagePtr++;
\r
2075 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2076 VRAMRead.RowsRemaining--;
\r
2077 if(VRAMRead.RowsRemaining<=0)
\r
2079 VRAMRead.RowsRemaining = VRAMRead.Width;
\r
2080 VRAMRead.ColsRemaining--;
\r
2081 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
\r
2082 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2084 if(VRAMRead.ColsRemaining <= 0)
\r
2085 {FinishedVRAMRead();goto ENDREAD;}
\r
2087 else {FinishedVRAMRead();goto ENDREAD;}
\r
2095 unsigned long CALLBACK GPUreadData(void)
\r
2097 unsigned long CALLBACK GPUreadData(void)
\r
2102 GPUreadDataMem(&l,1);
\r
2104 GPUreadDataMem(&l,1);
\r
2106 return GPUdataRet;
\r
2109 ////////////////////////////////////////////////////////////////////////
\r
2110 // helper table to know how much data is used by drawing commands
\r
2111 ////////////////////////////////////////////////////////////////////////
\r
2113 const unsigned char primTableCX[256] =
\r
2130 8,8,8,8,12,12,12,12,
\r
2134 // 5,5,5,5,6,6,6,6, //FLINE
\r
2135 254,254,254,254,254,254,254,254,
\r
2139 // 7,7,7,7,9,9,9,9, // LINEG3 LINEG4
\r
2140 255,255,255,255,255,255,255,255,
\r
2142 3,3,3,3,4,4,4,4, // TILE SPRT
\r
2144 2,2,2,2,3,3,3,3, // TILE1
\r
2183 ////////////////////////////////////////////////////////////////////////
\r
2184 // processes data send to GPU data register
\r
2185 ////////////////////////////////////////////////////////////////////////
\r
2188 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)
\r
2190 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)
\r
2193 unsigned char command;
\r
2194 unsigned long gdata=0;
\r
2197 GPUIsNotReadyForCommands;
\r
2201 if(iDataWriteMode==DR_VRAMTRANSFER)
\r
2203 // make sure we are in vram
\r
2204 while(VRAMWrite.ImagePtr>=psxVuw_eom)
\r
2205 VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2206 while(VRAMWrite.ImagePtr<psxVuw)
\r
2207 VRAMWrite.ImagePtr+=iGPUHeight*1024;
\r
2209 // now do the loop
\r
2210 while(VRAMWrite.ColsRemaining>0)
\r
2212 while(VRAMWrite.RowsRemaining>0)
\r
2214 if(i>=iSize) {goto ENDVRAM;}
\r
2219 *VRAMWrite.ImagePtr++ = (unsigned short)gdata;
\r
2220 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2221 VRAMWrite.RowsRemaining --;
\r
2223 if(VRAMWrite.RowsRemaining <= 0)
\r
2225 VRAMWrite.ColsRemaining--;
\r
2226 if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width
\r
2228 gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16);
\r
2229 FinishedVRAMWrite();
\r
2232 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
2233 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
2236 *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16);
\r
2237 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2238 VRAMWrite.RowsRemaining --;
\r
2241 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
2242 VRAMWrite.ColsRemaining--;
\r
2243 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
2246 FinishedVRAMWrite();
\r
2251 if(iDataWriteMode==DR_NORMAL)
\r
2253 void (* *primFunc)(unsigned char *);
\r
2254 if(bSkipNextFrame) primFunc=primTableSkip;
\r
2255 else primFunc=primTableJ;
\r
2259 if(iDataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;
\r
2261 gdata=*pMem++;i++;
\r
2265 command = (unsigned char)((gdata>>24) & 0xff);
\r
2267 if(primTableCX[command])
\r
2269 gpuDataC = primTableCX[command];
\r
2270 gpuCommand = command;
\r
2271 gpuDataM[0] = gdata;
\r
2278 gpuDataM[gpuDataP] = gdata;
\r
2281 if((gpuDataC==254 && gpuDataP>=3) ||
\r
2282 (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))
\r
2284 if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)
\r
2285 gpuDataP=gpuDataC-1;
\r
2291 if(gpuDataP == gpuDataC)
\r
2293 gpuDataC=gpuDataP=0;
\r
2294 primFunc[gpuCommand]((unsigned char *)gpuDataM);
\r
2296 if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games
\r
2304 GPUIsReadyForCommands;
\r
2308 ////////////////////////////////////////////////////////////////////////
\r
2311 void CALLBACK GPUwriteData(unsigned long gdata)
\r
2313 void CALLBACK GPUwriteData(unsigned long gdata)
\r
2317 GPUwriteDataMem(&gdata,1);
\r
2319 GPUwriteDataMem(&gdata,1);
\r
2323 ////////////////////////////////////////////////////////////////////////
\r
2324 // this function will be removed soon (or 'soonish') (or never)
\r
2325 ////////////////////////////////////////////////////////////////////////
\r
2327 void CALLBACK GPUsetMode(unsigned int gdata)
\r
2329 // ignore old psemu setmode:
\r
2331 // imageTransfer = gdata;
\r
2332 // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2333 // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2336 // and this function will be removed soon as well, hehehe...
\r
2337 long CALLBACK GPUgetMode(void)
\r
2339 // ignore old psemu setmode
\r
2340 // return imageTransfer;
\r
2344 if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1;
\r
2345 if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2;
\r
2350 ////////////////////////////////////////////////////////////////////////
\r
2351 // call config dlg (Windows + Linux)
\r
2352 ////////////////////////////////////////////////////////////////////////
\r
2356 /*#include <unistd.h>
\r
2358 void StartCfgTool(char * pCmdLine) // linux: start external cfg tool
\r
2360 FILE * cf;char filename[255],t[255];
\r
2362 strcpy(filename,"cfg/cfgPeopsMesaGL"); // look in cfg sub folder first
\r
2363 cf=fopen(filename,"rb");
\r
2369 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2375 strcpy(filename,"cfgPeopsMesaGL"); // look in current folder
\r
2376 cf=fopen(filename,"rb");
\r
2380 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2385 sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder
\r
2386 cf=fopen(filename,"rb");
\r
2391 chdir(getenv("HOME"));
\r
2392 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2396 else printf("cfgPeopsMesaGL not found!\n");
\r
2405 long CALLBACK GPUconfigure(void)
\r
2407 long CALLBACK GPUconfigure(void)
\r
2412 // HWND hWP=GetActiveWindow();
\r
2413 // DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG),
\r
2414 // hWP,(DLGPROC)CfgDlgProc);
\r
2417 // StartCfgTool("CFG");
\r
2424 ////////////////////////////////////////////////////////////////////////
\r
2425 // sets all kind of act fixes
\r
2426 ////////////////////////////////////////////////////////////////////////
\r
2428 void SetFixes(void)
\r
2432 if(dwActFixes & 0x2000)
\r
2433 dispWidths[4]=384;
\r
2434 else dispWidths[4]=368;
\r
2437 ////////////////////////////////////////////////////////////////////////
\r
2438 // Pete Special: make an 'intelligent' dma chain check (<-Tekken3)
\r
2439 ////////////////////////////////////////////////////////////////////////
\r
2441 unsigned long lUsedAddr[3];
\r
2443 __inline BOOL CheckForEndlessLoop(unsigned long laddr)
\r
2445 if(laddr==lUsedAddr[1]) return TRUE;
\r
2446 if(laddr==lUsedAddr[2]) return TRUE;
\r
2448 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
\r
2449 else lUsedAddr[2]=laddr;
\r
2450 lUsedAddr[0]=laddr;
\r
2454 ////////////////////////////////////////////////////////////////////////
\r
2455 // core gives a dma chain to gpu: same as the gpuwrite interface funcs
\r
2456 ////////////////////////////////////////////////////////////////////////
\r
2459 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)
\r
2461 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)
\r
2464 unsigned long dmaMem;
\r
2465 unsigned char * baseAddrB;
\r
2466 short count;unsigned int DMACommandCounter = 0;
\r
2468 if(bIsFirstFrame) GLinitialize();
\r
2472 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
\r
2474 baseAddrB = (unsigned char*) baseAddrL;
\r
2478 if(iGPUHeight==512) addr&=0x1FFFFC;
\r
2480 if(DMACommandCounter++ > 2000000) break;
\r
2481 if(CheckForEndlessLoop(addr)) break;
\r
2483 count = baseAddrB[addr+3];
\r
2488 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
\r
2490 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
\r
2493 addr = baseAddrL[addr>>2]&0xffffff;
\r
2495 while (addr != 0xffffff);
\r
2502 ////////////////////////////////////////////////////////////////////////
\r
2504 ////////////////////////////////////////////////////////////////////////
\r
2507 void CALLBACK GPUabout(void)
\r
2509 void CALLBACK GPUabout(void)
\r
2515 ////////////////////////////////////////////////////////////////////////
\r
2516 // We are ever fine ;)
\r
2517 ////////////////////////////////////////////////////////////////////////
\r
2520 long CALLBACK GPUtest(void)
\r
2522 long CALLBACK GPUtest(void)
\r
2525 // if test fails this function should return negative value for error (unable to continue)
\r
2526 // and positive value for warning (can continue but output might be crappy)
\r
2531 ////////////////////////////////////////////////////////////////////////
\r
2532 // save state funcs
\r
2533 ////////////////////////////////////////////////////////////////////////
\r
2535 ////////////////////////////////////////////////////////////////////////
\r
2538 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)
\r
2540 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)
\r
2543 if(ulGetFreezeData==2)
\r
2545 long lSlotNum=*((long *)pF);
\r
2546 if(lSlotNum<0) return 0;
\r
2547 if(lSlotNum>8) return 0;
\r
2548 lSelectedSlot=lSlotNum+1;
\r
2552 if(!pF) return 0;
\r
2553 if(pF->ulFreezeVersion!=1) return 0;
\r
2555 if(ulGetFreezeData==1)
\r
2557 pF->ulStatus=STATUSREG;
\r
2558 memcpy(pF->ulControl,ulStatusControl,256*sizeof(unsigned long));
\r
2559 memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2);
\r
2564 if(ulGetFreezeData!=0) return 0;
\r
2566 STATUSREG=pF->ulStatus;
\r
2567 memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long));
\r
2568 memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2);
\r
2570 ResetTextureArea(TRUE);
\r
2573 GPUwriteStatus(ulStatusControl[0]);
\r
2574 GPUwriteStatus(ulStatusControl[1]);
\r
2575 GPUwriteStatus(ulStatusControl[2]);
\r
2576 GPUwriteStatus(ulStatusControl[3]);
\r
2577 GPUwriteStatus(ulStatusControl[8]);
\r
2578 GPUwriteStatus(ulStatusControl[6]);
\r
2579 GPUwriteStatus(ulStatusControl[7]);
\r
2580 GPUwriteStatus(ulStatusControl[5]);
\r
2581 GPUwriteStatus(ulStatusControl[4]);
\r
2583 GPUwriteStatus(ulStatusControl[0]);
\r
2584 GPUwriteStatus(ulStatusControl[1]);
\r
2585 GPUwriteStatus(ulStatusControl[2]);
\r
2586 GPUwriteStatus(ulStatusControl[3]);
\r
2587 GPUwriteStatus(ulStatusControl[8]);
\r
2588 GPUwriteStatus(ulStatusControl[6]);
\r
2589 GPUwriteStatus(ulStatusControl[7]);
\r
2590 GPUwriteStatus(ulStatusControl[5]);
\r
2591 GPUwriteStatus(ulStatusControl[4]);
\r
2596 ////////////////////////////////////////////////////////////////////////
\r
2597 // special "emu infos" / "emu effects" functions
\r
2598 ////////////////////////////////////////////////////////////////////////
\r
2603 //11 = transparent
\r
2605 unsigned char cFont[10][120]=
\r
2608 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2609 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2610 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2611 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2612 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2613 0x80,0x00,0x05,0x54,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,0x14,0x05,0x00,0x00,
\r
2618 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2619 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2620 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2621 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2622 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2623 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2624 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2625 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2626 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2627 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2630 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2631 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2632 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2633 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2634 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2635 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2636 0x80,0x00,0x05,0x50,0x00,0x00,
\r
2637 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2638 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2639 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2640 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2641 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2642 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2643 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2644 0x80,0x00,0x05,0x55,0x00,0x00,
\r
2645 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2646 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2647 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2648 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2649 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2652 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2653 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2654 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2655 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2656 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2657 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2658 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2659 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2660 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2661 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2662 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2663 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2664 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2665 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2666 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2667 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2668 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2669 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2670 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2671 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2674 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2675 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2676 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2677 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2678 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2679 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2680 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2681 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2682 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2683 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2684 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2685 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2686 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2687 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2688 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2689 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2690 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2691 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2692 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2693 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2696 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2697 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2698 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2699 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2700 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2701 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2702 0x80,0x00,0x00,0x54,0x00,0x00,
\r
2703 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2704 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2705 0x80,0x00,0x05,0x14,0x00,0x00,
\r
2706 0x80,0x00,0x14,0x14,0x00,0x00,
\r
2707 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2708 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2709 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2710 0x80,0x00,0x00,0x55,0x00,0x00,
\r
2711 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2712 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2713 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2714 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2715 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2718 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2719 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2720 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2721 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2722 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2723 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2724 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2725 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2726 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2727 0x80,0x00,0x15,0x54,0x00,0x00,
\r
2728 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2729 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2730 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2731 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2732 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2733 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2734 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2735 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2736 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2737 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2740 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2741 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2742 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2743 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2744 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2745 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2746 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2747 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2748 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2749 0x80,0x00,0x15,0x54,0x00,0x00,
\r
2750 0x80,0x00,0x15,0x05,0x00,0x00,
\r
2751 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2752 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2753 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2754 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2755 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2756 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2757 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2758 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2759 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2762 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2763 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2764 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2765 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2766 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2767 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2768 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2769 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2770 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2771 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2772 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2773 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2774 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2775 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2776 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2777 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2778 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2779 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2780 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2781 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2784 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2785 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2786 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2787 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2788 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2789 0x80,0x00,0x05,0x54,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,0x14,0x05,0x00,0x00,
\r
2795 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2796 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2797 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2798 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2799 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2800 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2801 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2802 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2803 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2806 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2807 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2808 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2809 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2810 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2811 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2812 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2813 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2814 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2815 0x80,0x00,0x14,0x15,0x00,0x00,
\r
2816 0x80,0x00,0x05,0x55,0x00,0x00,
\r
2817 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2818 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2819 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2820 0x80,0x00,0x05,0x50,0x00,0x00,
\r
2821 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2822 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2823 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2824 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2825 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2829 ////////////////////////////////////////////////////////////////////////
\r
2831 void PaintPicDot(unsigned char * p,unsigned char c)
\r
2833 if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;}
\r
2834 if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;}
\r
2835 if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;}
\r
2838 ////////////////////////////////////////////////////////////////////////
\r
2841 void CALLBACK GPUgetScreenPic(unsigned char * pMem)
\r
2843 long CALLBACK GPUgetScreenPic(unsigned char * pMem)
\r
2846 float XS,YS;int x,y,v;
\r
2847 unsigned char * ps, * px, * pf;
\r
2850 if(!pGfxCardScreen)
\r
2852 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
2853 pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4);
\r
2856 ps=pGfxCardScreen;
\r
2858 // glReadBuffer(GL_FRONT);
\r
2860 glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
2862 // glReadBuffer(GL_BACK);
\r
2864 XS=(float)iResX/128;
\r
2865 YS=(float)iResY/96;
\r
2870 for(x=0;x<128;x++)
\r
2872 px=ps+(3*((int)((float)x * XS))+
\r
2873 (3*iResX)*((int)((float)y*YS)));
\r
2881 /////////////////////////////////////////////////////////////////////
\r
2882 // generic number/border painter
\r
2890 c=cFont[lSelectedSlot][x+y*6];
\r
2892 PaintPicDot(pf,(unsigned char)v);pf+=3; // paint the dots into the rect
\r
2894 PaintPicDot(pf,(unsigned char)v);pf+=3;
\r
2896 PaintPicDot(pf,(unsigned char)v);pf+=3;
\r
2898 PaintPicDot(pf,(unsigned char)v);pf+=3;
\r
2904 for(x=0;x<128;x++)
\r
2906 *(pf+(95*128*3))=0x00;*pf++=0x00;
\r
2907 *(pf+(95*128*3))=0x00;*pf++=0x00;
\r
2908 *(pf+(95*128*3))=0xff;*pf++=0xff;
\r
2913 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2914 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2915 *(pf+(127*3))=0xff;*pf++=0xff;
\r
2921 ////////////////////////////////////////////////////////////////////////
\r
2924 void CALLBACK GPUshowScreenPic(unsigned char * pMem)
\r
2926 long CALLBACK GPUshowScreenPic(unsigned char * pMem)
\r
2930 // if(pMem==0) return;
\r
2931 // CreatePic(pMem);
\r
2934 ////////////////////////////////////////////////////////////////////////
\r
2936 void CALLBACK GPUsetfix(unsigned long dwFixBits)
\r
2938 dwEmuFixes=dwFixBits;
\r
2941 ////////////////////////////////////////////////////////////////////////
\r
2943 void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig)
\r
2947 if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width
\r
2948 iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x);
\r
2950 // big rumble: 4...15 sp ; small rumble 1...3 sp
\r
2951 if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10));
\r
2952 else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10));
\r
2954 srand(timeGetTime()); // init rand (will be used in BufferSwap)
\r
2956 iRumbleTime=15; // let the rumble last 16 buffer swaps
\r
2959 ////////////////////////////////////////////////////////////////////////
\r
2960 // main emu can set display infos (A/M/G/D)
\r
2961 ////////////////////////////////////////////////////////////////////////
\r
2963 void CALLBACK GPUdisplayFlags(unsigned long dwFlags)
\r
2965 // dwCoreFlags=dwFlags;
\r
2968 // pcsx-rearmed callbacks
\r
2969 void CALLBACK GPUrearmedCallbacks(const void **cbs)
\r
2971 rearmed_get_layer_pos = cbs[0];
\r