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 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 s8 * 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 s8 * GetConfigInfos(int hW)
\r
214 HDC hdc;HGLRC hglrc;
\r
216 s8 szO[2][4]={"off","on "};
\r
218 s8 * pB=(s8 *)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,(s8 *)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=(u8 *)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 #ifdef MAEMO_CHANGES
\r
564 iResX=800;iResY=480;
\r
575 // bAdvancedBlend=FALSE;
\r
577 // bUseLines=FALSE;
\r
578 bUseFrameLimit=FALSE;
\r
579 bUseFrameSkip=FALSE;
\r
582 iOffscreenDrawing=0;
\r
583 //bOpaquePass=FALSE;
\r
584 //bUseAntiAlias=FALSE;
\r
587 iWinSize=MAKELONG(iResX,iResY);
\r
591 bUseFastMdec=FALSE;
\r
592 bUse15bitMdec=FALSE;
\r
595 // iUseScanLines=0;
\r
602 iTexGarbageCollection=0;
\r
604 //iHiResTextures=0;
\r
611 memset(&dv,0,sizeof(DEVMODE));
\r
612 dv.dmSize=sizeof(DEVMODE);
\r
613 EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv);
\r
615 bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows!
\r
618 if(bWindowMode) // win mode?
\r
620 DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers)
\r
621 dw&=~WS_THICKFRAME;
\r
622 dw|=WS_BORDER|WS_CAPTION|CS_OWNDC;
\r
623 SetWindowLong(hWWindow, GWL_STYLE, dw);
\r
625 hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any)
\r
626 if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);
\r
628 iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize);
\r
629 ShowWindow(hWWindow,SW_SHOWNORMAL);
\r
631 MoveWindow(hWWindow, // -> center wnd
\r
632 GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2,
\r
633 GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2,
\r
634 iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3,
\r
635 iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3,
\r
637 UpdateWindow(hWWindow); // -> let windows do some update
\r
639 if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info
\r
640 iColDepth=dv.dmBitsPerPel;
\r
642 else // fullscreen mode:
\r
644 if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution
\r
645 dv.dmPelsWidth !=(unsigned int)iResX ||
\r
646 dv.dmPelsHeight!=(unsigned int)iResY)
\r
647 bChangeRes=TRUE; else bChangeRes=FALSE;
\r
649 if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations')
\r
651 SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure)
\r
653 hPSEMenu=GetMenu(hWWindow); // -> hide menu
\r
654 if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL);
\r
655 ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode
\r
658 rRatioRect.left = rRatioRect.top=0;
\r
659 rRatioRect.right = iResX;
\r
660 rRatioRect.bottom = iResY;
\r
663 r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized
\r
664 hdc = GetDC(hWWindow);
\r
665 FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH));
\r
666 bSetupPixelFormat(hdc);
\r
667 ReleaseDC(hWWindow,hdc);
\r
669 bDisplayNotSet = TRUE;
\r
672 SetFixes(); // setup game fixes
\r
674 InitializeTextureStore(); // init texture mem
\r
676 // lGPUstatusRet = 0x74000000;
\r
678 // with some emus, we could do the OGL init right here... oh my
\r
679 // if(bIsFirstFrame) GLinitialize();
\r
684 ////////////////////////////////////////////////////////////////////////
\r
686 ////////////////////////////////////////////////////////////////////////
\r
689 long CALLBACK GPUclose() // WINDOWS CLOSE
\r
691 // ExitKeyHandler();
\r
693 GLcleanup(); // close OGL
\r
695 if(bChangeRes) // change res back
\r
696 ChangeDisplaySettings(NULL,0);
\r
698 if(hPSEMenu) // set menu again
\r
699 SetMenu(hWWindow,hPSEMenu);
\r
701 if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory
\r
704 // if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again
\r
711 long GPUclose() // LINUX CLOSE
\r
713 GLcleanup(); // close OGL
\r
715 if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory
\r
718 // osd_close_display(); // destroy display
\r
724 ////////////////////////////////////////////////////////////////////////
\r
725 // I shot the sheriff... last function called from emu
\r
726 ////////////////////////////////////////////////////////////////////////
\r
729 long CALLBACK GPUshutdown()
\r
731 long CALLBACK GPUshutdown()
\r
734 if(psxVSecure) free(psxVSecure); // kill emulated vram memory
\r
740 ////////////////////////////////////////////////////////////////////////
\r
741 // paint it black: simple func to clean up optical border garbage
\r
742 ////////////////////////////////////////////////////////////////////////
\r
744 void PaintBlackBorders(void)
\r
748 glDisable(GL_SCISSOR_TEST);
\r
749 if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;}
\r
750 if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;}
\r
751 if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;}
\r
752 glDisable(GL_ALPHA_TEST);
\r
754 glEnable(GL_ALPHA_TEST);
\r
755 glEnable(GL_SCISSOR_TEST);
\r
758 ////////////////////////////////////////////////////////////////////////
\r
759 // helper to draw scanlines
\r
760 ////////////////////////////////////////////////////////////////////////
\r
762 __inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2,
\r
763 OGLVertex* vertex3, OGLVertex* vertex4)
\r
768 ////////////////////////////////////////////////////////////////////////
\r
770 ////////////////////////////////////////////////////////////////////////
\r
772 void SetScanLines(void)
\r
776 ////////////////////////////////////////////////////////////////////////
\r
777 // blur, babe, blur (heavy performance hit for a so-so fullscreen effect)
\r
778 ////////////////////////////////////////////////////////////////////////
\r
781 ////////////////////////////////////////////////////////////////////////
\r
782 // Update display (swap buffers)... called in interlaced mode on
\r
783 // every emulated vsync, otherwise whenever the displayed screen region
\r
784 // has been changed
\r
785 ////////////////////////////////////////////////////////////////////////
\r
787 int iLastRGB24=0; // special vars for checking when to skip two display updates
\r
789 void GPUvSinc(void){
\r
792 void updateDisplay(void) // UPDATE DISPLAY
\r
797 HDC hdc=GetDC(hWWindow); // windows:
\r
798 wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again
\r
801 bFakeFrontBuffer=FALSE;
\r
802 bRenderFrontBuffer=FALSE;
\r
804 if(iRenderFVR) // frame buffer read fix mode still active?
\r
806 iRenderFVR--; // -> if some frames in a row without read access: turn off mode
\r
807 if(!iRenderFVR) bFullVRam=FALSE;
\r
810 if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check
\r
812 iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes
\r
816 if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted?
\r
818 PrepareFullScreenUpload(-1);
\r
819 UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram
\r
820 bNeedUploadTest=FALSE;
\r
821 bNeedInterlaceUpdate=FALSE;
\r
822 bNeedUploadAfter=FALSE;
\r
823 bNeedRGB24Update=FALSE;
\r
826 if(bNeedInterlaceUpdate) // smaller upload?
\r
828 bNeedInterlaceUpdate=FALSE;
\r
829 xrUploadArea=xrUploadAreaIL; // -> upload this rect
\r
830 UploadScreen(TRUE);
\r
833 if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9
\r
835 if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed
\r
836 PreviousPSXDisplay.Range.y0)
\r
837 PaintBlackBorders();
\r
839 if(PSXDisplay.Disabled) // display disabled?
\r
842 glDisable(GL_SCISSOR_TEST);
\r
843 glClearColor(0,0,0,128); // -> clear whole backbuffer
\r
844 glClear(uiBufferBits);
\r
845 glEnable(GL_SCISSOR_TEST);
\r
847 bDisplayNotSet = TRUE;
\r
850 if(iSkipTwo) // we are in skipping mood?
\r
853 iDrawnSomething=0; // -> simply lie about something drawn
\r
856 //if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated?
\r
857 // {BlurBackBuffer();bBlur=TRUE;} // -> blur it
\r
859 // if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it
\r
861 // if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em
\r
863 if(dwActFixes&128) // special FPS limitation mode?
\r
865 if(bUseFrameLimit) PCFrameCap(); // -> ok, do it
\r
866 // if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS)
\r
870 // if(gTexPicName) DisplayPic(); // some gpu info picture active? display it
\r
872 // if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :)
\r
874 // if(ulKeybits&KEY_SHOWFPS) // wanna see FPS?
\r
876 // sprintf(szDispBuf,"%06.1f",fps_cur);
\r
877 // DisplayText(); // -> show it
\r
880 //----------------------------------------------------//
\r
881 // main buffer swapping (well, or skip it)
\r
883 if(bUseFrameSkip) // frame skipping active ?
\r
885 if(!bSkipNextFrame)
\r
887 if(iDrawnSomething)
\r
889 SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip
\r
891 eglSwapBuffers(display,surface);
\r
894 if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row
\r
896 if((fps_skip < fFrameRateHz) && !(bSkipNextFrame))
\r
897 {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}
\r
898 else bSkipNextFrame = FALSE;
\r
904 if(iDrawnSomething)
\r
906 SwapBuffers(wglGetCurrentDC()); // -> swap
\r
908 eglSwapBuffers(display,surface);
\r
914 //----------------------------------------------------//
\r
916 if(lClearOnSwap) // clear buffer after swap?
\r
920 if(bDisplayNotSet) // -> set new vals
\r
921 SetOGLDisplaySettings(1);
\r
923 g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col
\r
924 b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f;
\r
925 r=((GLclampf)RED(lClearOnSwapColor))/255.0f;
\r
927 glDisable(GL_SCISSOR_TEST);
\r
928 glClearColor(r,g,b,128); // -> clear
\r
929 glClear(uiBufferBits);
\r
930 glEnable(GL_SCISSOR_TEST);
\r
931 lClearOnSwap=0; // -> done
\r
935 // if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before
\r
937 if(iZBufferDepth) // clear zbuffer as well (if activated)
\r
939 glDisable(GL_SCISSOR_TEST);
\r
940 glClear(GL_DEPTH_BUFFER_BIT);
\r
941 glEnable(GL_SCISSOR_TEST);
\r
946 //----------------------------------------------------//
\r
947 // additional uploads immediatly after swapping
\r
949 if(bNeedUploadAfter) // upload wanted?
\r
951 bNeedUploadAfter=FALSE;
\r
952 bNeedUploadTest=FALSE;
\r
953 UploadScreen(-1); // -> upload
\r
956 if(bNeedUploadTest)
\r
958 bNeedUploadTest=FALSE;
\r
959 if(PSXDisplay.InterlacedTest &&
\r
960 //iOffscreenDrawing>2 &&
\r
961 PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x &&
\r
962 PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x &&
\r
963 PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y &&
\r
964 PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y)
\r
966 PrepareFullScreenUpload(TRUE);
\r
967 UploadScreen(TRUE);
\r
971 //----------------------------------------------------//
\r
972 // rumbling (main emu pad effect)
\r
974 if(iRumbleTime) // shake screen by modifying view port
\r
976 int i1=0,i2=0,i3=0,i4=0;
\r
981 i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
982 i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
983 i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
984 i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2);
\r
987 glViewport(rRatioRect.left+i1,
\r
988 iResY-(rRatioRect.top+rRatioRect.bottom)+i2,
\r
989 rRatioRect.right+i3,
\r
990 rRatioRect.bottom+i4);
\r
993 //----------------------------------------------------//
\r
997 // if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled
\r
1000 ////////////////////////////////////////////////////////////////////////
\r
1001 // update front display: smaller update func, if something has changed
\r
1002 // in the frontbuffer... dirty, but hey... real men know no pain
\r
1003 ////////////////////////////////////////////////////////////////////////
\r
1005 void updateFrontDisplay(void)
\r
1007 if(PreviousPSXDisplay.Range.x0||
\r
1008 PreviousPSXDisplay.Range.y0)
\r
1009 PaintBlackBorders();
\r
1011 //if(iBlurBuffer) BlurBackBuffer();
\r
1013 //if(iUseScanLines) SetScanLines();
\r
1015 // if(usCursorActive) ShowGunCursor();
\r
1017 bFakeFrontBuffer=FALSE;
\r
1018 bRenderFrontBuffer=FALSE;
\r
1020 // if(gTexPicName) DisplayPic();
\r
1021 // if(ulKeybits&KEY_SHOWFPS) DisplayText();
\r
1025 HDC hdc=GetDC(hWWindow);
\r
1026 wglMakeCurrent(hdc,GLCONTEXT); // -> make current again
\r
1027 if(iDrawnSomething)
\r
1028 SwapBuffers(wglGetCurrentDC()); // -> swap
\r
1029 ReleaseDC(hWWindow,hdc); // -> ! important !
\r
1032 if(iDrawnSomething) // linux:
\r
1033 eglSwapBuffers(display,surface);
\r
1036 //if(iBlurBuffer) UnBlurBackBuffer();
\r
1039 ////////////////////////////////////////////////////////////////////////
\r
1040 // check if update needed
\r
1041 ////////////////////////////////////////////////////////////////////////
\r
1042 void ChangeDispOffsetsX(void) // CENTER X
\r
1044 long lx,l;short sO;
\r
1046 if(!PSXDisplay.Range.x1) return; // some range given?
\r
1048 l=PSXDisplay.DisplayMode.x;
\r
1050 l*=(long)PSXDisplay.Range.x1; // some funky calculation
\r
1051 l/=2560;lx=l;l&=0xfffffff8;
\r
1053 if(l==PreviousPSXDisplay.Range.x1) return; // some change?
\r
1055 sO=PreviousPSXDisplay.Range.x0; // store old
\r
1057 if(lx>=PSXDisplay.DisplayMode.x) // range bigger?
\r
1059 PreviousPSXDisplay.Range.x1= // -> take display width
\r
1060 PSXDisplay.DisplayMode.x;
\r
1061 PreviousPSXDisplay.Range.x0=0; // -> start pos is 0
\r
1063 else // range smaller? center it
\r
1065 PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned)
\r
1066 PreviousPSXDisplay.Range.x0= // -> calc start pos
\r
1067 (PSXDisplay.Range.x0-500)/8;
\r
1068 if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet
\r
1069 PreviousPSXDisplay.Range.x0=0;
\r
1071 if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much
\r
1072 PSXDisplay.DisplayMode.x)
\r
1074 PreviousPSXDisplay.Range.x0= // -> adjust start
\r
1075 PSXDisplay.DisplayMode.x-lx;
\r
1076 PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width
\r
1080 if(sO!=PreviousPSXDisplay.Range.x0) // something changed?
\r
1082 bDisplayNotSet=TRUE; // -> recalc display stuff
\r
1086 ////////////////////////////////////////////////////////////////////////
\r
1088 void ChangeDispOffsetsY(void) // CENTER Y
\r
1090 int iT;short sO; // store previous y size
\r
1092 if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC
\r
1094 if(PSXDisplay.Range.y0>=iT) // crossed the security line? :)
\r
1096 PreviousPSXDisplay.Range.y1= // -> store width
\r
1097 PSXDisplay.DisplayModeNew.y;
\r
1099 sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset
\r
1102 PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too
\r
1104 else sO=0; // else no offset
\r
1106 if(sO!=PreviousPSXDisplay.Range.y0) // something changed?
\r
1108 PreviousPSXDisplay.Range.y0=sO;
\r
1109 bDisplayNotSet=TRUE; // -> recalc display stuff
\r
1113 ////////////////////////////////////////////////////////////////////////
\r
1114 // Aspect ratio of ogl screen: simply adjusting ogl view port
\r
1115 ////////////////////////////////////////////////////////////////////////
\r
1117 void SetAspectRatio(void)
\r
1119 float xs,ys,s;RECT r;
\r
1121 if(!PSXDisplay.DisplayModeNew.x) return;
\r
1122 if(!PSXDisplay.DisplayModeNew.y) return;
\r
1125 xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x;
\r
1126 ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y;
\r
1129 r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s);
\r
1130 r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s);
\r
1131 if(r.right > iResX) r.right = iResX;
\r
1132 if(r.bottom > iResY) r.bottom = iResY;
\r
1133 if(r.right < 1) r.right = 1;
\r
1134 if(r.bottom < 1) r.bottom = 1;
\r
1136 r.left = (iResX-r.right)/2;
\r
1137 r.top = (iResY-r.bottom)/2;
\r
1139 if(r.bottom<rRatioRect.bottom ||
\r
1140 r.right <rRatioRect.right)
\r
1143 glClearColor(0,0,0,128);
\r
1145 if(r.right <rRatioRect.right)
\r
1151 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1152 glClear(uiBufferBits);
\r
1153 rC.left=iResX-rC.right;
\r
1154 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1155 glClear(uiBufferBits);
\r
1158 if(r.bottom <rRatioRect.bottom)
\r
1164 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1165 glClear(uiBufferBits);
\r
1166 rC.top=iResY-rC.bottom;
\r
1167 glScissor(rC.left,rC.top,rC.right,rC.bottom);
\r
1168 glClear(uiBufferBits);
\r
1172 bDisplayNotSet=TRUE;
\r
1177 // pcsx-rearmed hack
\r
1178 if (rearmed_get_layer_pos != NULL)
\r
1179 rearmed_get_layer_pos(&rRatioRect.left, &rRatioRect.top, &rRatioRect.right, &rRatioRect.bottom);
\r
1182 glViewport(rRatioRect.left,
\r
1183 iResY-(rRatioRect.top+rRatioRect.bottom),
\r
1185 rRatioRect.bottom); // init viewport
\r
1188 ////////////////////////////////////////////////////////////////////////
\r
1189 // big ass check, if an ogl swap buffer is needed
\r
1190 ////////////////////////////////////////////////////////////////////////
\r
1192 void updateDisplayIfChanged(void)
\r
1196 if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) &&
\r
1197 (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))
\r
1199 if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) &&
\r
1200 (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew))
\r
1201 return; // nothing has changed? fine, no swap buffer needed
\r
1203 else // some res change?
\r
1206 glOrtho(0,PSXDisplay.DisplayModeNew.x, // -> new psx resolution
\r
1207 PSXDisplay.DisplayModeNew.y, 0, -1, 1);
\r
1208 if(bKeepRatio) SetAspectRatio();
\r
1211 bDisplayNotSet = TRUE; // re-calc offsets/display area
\r
1214 if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off)
\r
1216 PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet
\r
1217 ResetTextureArea(FALSE);
\r
1221 PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos
\r
1222 PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;
\r
1223 PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;
\r
1224 PSXDisplay.Interlaced = PSXDisplay.InterlacedNew;
\r
1226 PSXDisplay.DisplayEnd.x= // calc new ends
\r
1227 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1228 PSXDisplay.DisplayEnd.y=
\r
1229 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1230 PreviousPSXDisplay.DisplayEnd.x=
\r
1231 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1232 PreviousPSXDisplay.DisplayEnd.y=
\r
1233 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1235 ChangeDispOffsetsX();
\r
1237 if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace)
\r
1239 if(bUp) updateDisplay(); // yeah, real update (swap buffer)
\r
1242 ////////////////////////////////////////////////////////////////////////
\r
1243 // window mode <-> fullscreen mode (windows)
\r
1244 ////////////////////////////////////////////////////////////////////////
\r
1247 void ChangeWindowMode(void)
\r
1250 bWindowMode=!bWindowMode;
\r
1251 GPUopen(hWWindow);
\r
1252 bChangeWinMode=FALSE;
\r
1256 ////////////////////////////////////////////////////////////////////////
\r
1257 // swap update check (called by psx vsync function)
\r
1258 ////////////////////////////////////////////////////////////////////////
\r
1260 BOOL bSwapCheck(void)
\r
1262 static int iPosCheck=0;
\r
1263 static PSXPoint_t pO;
\r
1264 static PSXPoint_t pD;
\r
1265 static int iDoAgain=0;
\r
1267 if(PSXDisplay.DisplayPosition.x==pO.x &&
\r
1268 PSXDisplay.DisplayPosition.y==pO.y &&
\r
1269 PSXDisplay.DisplayEnd.x==pD.x &&
\r
1270 PSXDisplay.DisplayEnd.y==pD.y)
\r
1274 pO=PSXDisplay.DisplayPosition;
\r
1275 pD=PSXDisplay.DisplayEnd;
\r
1277 if(iPosCheck<=4) return FALSE;
\r
1281 if(PSXDisplay.Interlaced) return FALSE;
\r
1283 if (bNeedInterlaceUpdate||
\r
1284 bNeedRGB24Update ||
\r
1285 bNeedUploadAfter||
\r
1286 bNeedUploadTest ||
\r
1291 if(bNeedUploadAfter)
\r
1293 if(bNeedUploadTest && PSXDisplay.InterlacedTest)
\r
1296 bDisplayNotSet = TRUE;
\r
1299 PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x;
\r
1300 PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y;
\r
1301 PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x;
\r
1302 PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y;
\r
1303 pO=PSXDisplay.DisplayPosition;
\r
1304 pD=PSXDisplay.DisplayEnd;
\r
1311 ////////////////////////////////////////////////////////////////////////
\r
1312 // gun cursor func: player=0-7, x=0-511, y=0-255
\r
1313 ////////////////////////////////////////////////////////////////////////
\r
1315 ////////////////////////////////////////////////////////////////////////
\r
1316 // update lace is called every VSync. Basically we limit frame rate
\r
1317 // here, and in interlaced mode we swap ogl display buffers.
\r
1318 ////////////////////////////////////////////////////////////////////////
\r
1320 static unsigned short usFirstPos=2;
\r
1323 void CALLBACK GPUupdateLace(void)
\r
1325 void CALLBACK GPUupdateLace(void)
\r
1328 if(!(dwActFixes&0x1000))
\r
1329 STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus)
\r
1331 if(!(dwActFixes&128)) // normal frame limit func
\r
1334 if(iOffscreenDrawing==4) // special check if high offscreen drawing is on
\r
1336 if(bSwapCheck()) return;
\r
1339 if(PSXDisplay.Interlaced) // interlaced mode?
\r
1341 if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)
\r
1343 updateDisplay(); // -> swap buffers (new frame)
\r
1346 else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed?
\r
1348 updateFrontDisplay(); // -> update front buffer
\r
1350 else if(usFirstPos==1) // initial updates (after startup)
\r
1356 if(bChangeWinMode) ChangeWindowMode();
\r
1360 ////////////////////////////////////////////////////////////////////////
\r
1361 // process read request from GPU status register
\r
1362 ////////////////////////////////////////////////////////////////////////
\r
1365 unsigned long CALLBACK GPUreadStatus(void)
\r
1367 unsigned long CALLBACK GPUreadStatus(void)
\r
1370 if(dwActFixes&0x1000) // CC game fix
\r
1372 static int iNumRead=0;
\r
1373 if((iNumRead++)==2)
\r
1376 STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross)
\r
1380 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
1384 if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims
\r
1387 GPUIsNotReadyForCommands;
\r
1392 GPUIsReadyForCommands;
\r
1399 ////////////////////////////////////////////////////////////////////////
\r
1400 // processes data send to GPU status register
\r
1401 // these are always single packet commands.
\r
1402 ////////////////////////////////////////////////////////////////////////
\r
1405 void CALLBACK GPUwriteStatus(unsigned long gdata)
\r
1407 void CALLBACK GPUwriteStatus(unsigned long gdata)
\r
1410 unsigned long lCommand=(gdata>>24)&0xff;
\r
1413 if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus)
\r
1416 ulStatusControl[lCommand]=gdata;
\r
1420 //--------------------------------------------------//
\r
1423 memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long));
\r
1424 lGPUstatusRet=0x14802000;
\r
1425 PSXDisplay.Disabled=1;
\r
1426 iDataWriteMode=iDataReadMode=DR_NORMAL;
\r
1427 PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;
\r
1428 drawX=drawY=0;drawW=drawH=0;
\r
1429 sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0;
\r
1431 GlobalTextAddrX=0;GlobalTextAddrY=0;
\r
1432 GlobalTextTP=0;GlobalTextABR=0;
\r
1433 PSXDisplay.RGB24=FALSE;
\r
1434 PSXDisplay.Interlaced=FALSE;
\r
1435 bUsingTWin = FALSE;
\r
1438 // dis/enable display
\r
1440 PreviousPSXDisplay.Disabled = PSXDisplay.Disabled;
\r
1441 PSXDisplay.Disabled = (gdata & 1);
\r
1443 if(PSXDisplay.Disabled)
\r
1444 STATUSREG|=GPUSTATUS_DISPLAYDISABLED;
\r
1445 else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED;
\r
1447 if (iOffscreenDrawing==4 &&
\r
1448 PreviousPSXDisplay.Disabled &&
\r
1449 !(PSXDisplay.Disabled))
\r
1452 if(!PSXDisplay.RGB24)
\r
1454 PrepareFullScreenUpload(TRUE);
\r
1455 UploadScreen(TRUE);
\r
1462 // setting transfer mode
\r
1464 gdata &= 0x03; // only want the lower two bits
\r
1466 iDataWriteMode=iDataReadMode=DR_NORMAL;
\r
1467 if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER;
\r
1468 if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER;
\r
1470 STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits
\r
1471 STATUSREG|=(gdata << 29); // set the DMA bits according to the received data
\r
1475 // setting display position
\r
1478 short sx=(short)(gdata & 0x3ff);
\r
1481 if(iGPUHeight==1024)
\r
1483 if(dwGPUVersion==2)
\r
1484 sy = (short)((gdata>>12)&0x3ff);
\r
1485 else sy = (short)((gdata>>10)&0x3ff);
\r
1487 else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later
\r
1492 PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double;
\r
1495 else PreviousPSXDisplay.DisplayModeNew.y=0;
\r
1504 PreviousPSXDisplay.DisplayPosition.x = sx;
\r
1505 PreviousPSXDisplay.DisplayPosition.y = sy;
\r
1506 PSXDisplay.DisplayPosition.x = sx;
\r
1507 PSXDisplay.DisplayPosition.y = sy;
\r
1513 if((!PSXDisplay.Interlaced) &&
\r
1514 PreviousPSXDisplay.DisplayPosition.x == sx &&
\r
1515 PreviousPSXDisplay.DisplayPosition.y == sy)
\r
1518 PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x;
\r
1519 PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y;
\r
1520 PreviousPSXDisplay.DisplayPosition.x = sx;
\r
1521 PreviousPSXDisplay.DisplayPosition.y = sy;
\r
1525 if((!PSXDisplay.Interlaced) &&
\r
1526 PSXDisplay.DisplayPosition.x == sx &&
\r
1527 PSXDisplay.DisplayPosition.y == sy)
\r
1529 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
\r
1530 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
\r
1531 PSXDisplay.DisplayPosition.x = sx;
\r
1532 PSXDisplay.DisplayPosition.y = sy;
\r
1535 PSXDisplay.DisplayEnd.x=
\r
1536 PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1537 PSXDisplay.DisplayEnd.y=
\r
1538 PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1540 PreviousPSXDisplay.DisplayEnd.x=
\r
1541 PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x;
\r
1542 PreviousPSXDisplay.DisplayEnd.y=
\r
1543 PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y;
\r
1545 bDisplayNotSet = TRUE;
\r
1547 if (!(PSXDisplay.Interlaced))
\r
1552 if(PSXDisplay.InterlacedTest &&
\r
1553 ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)||
\r
1554 (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y)))
\r
1555 PSXDisplay.InterlacedTest--;
\r
1563 PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff;
\r
1564 PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff;
\r
1566 PSXDisplay.Range.x1-=PSXDisplay.Range.x0;
\r
1568 ChangeDispOffsetsX();
\r
1575 PreviousPSXDisplay.Height = PSXDisplay.Height;
\r
1577 PSXDisplay.Range.y0=gdata & 0x3ff;
\r
1578 PSXDisplay.Range.y1=(gdata>>10) & 0x3ff;
\r
1580 PSXDisplay.Height = PSXDisplay.Range.y1 -
\r
1581 PSXDisplay.Range.y0 +
\r
1582 PreviousPSXDisplay.DisplayModeNew.y;
\r
1584 if (PreviousPSXDisplay.Height != PSXDisplay.Height)
\r
1586 PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
\r
1587 ChangeDispOffsetsY();
\r
1588 updateDisplayIfChanged();
\r
1592 // setting display infos
\r
1595 PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)];
\r
1597 if (gdata&0x04) PSXDisplay.Double=2;
\r
1598 else PSXDisplay.Double=1;
\r
1599 PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double;
\r
1601 ChangeDispOffsetsY();
\r
1603 PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC
\r
1604 PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor
\r
1605 PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace
\r
1607 STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits
\r
1610 (((gdata & 0x03) << 17) |
\r
1611 ((gdata & 0x40) << 10)); // set the width bits
\r
1613 PreviousPSXDisplay.InterlacedNew=FALSE;
\r
1614 if (PSXDisplay.InterlacedNew)
\r
1616 if(!PSXDisplay.Interlaced)
\r
1618 PSXDisplay.InterlacedTest=2;
\r
1619 PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
\r
1620 PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
\r
1621 PreviousPSXDisplay.InterlacedNew=TRUE;
\r
1624 STATUSREG|=GPUSTATUS_INTERLACED;
\r
1628 PSXDisplay.InterlacedTest=0;
\r
1629 STATUSREG&=~GPUSTATUS_INTERLACED;
\r
1632 if (PSXDisplay.PAL)
\r
1633 STATUSREG|=GPUSTATUS_PAL;
\r
1634 else STATUSREG&=~GPUSTATUS_PAL;
\r
1636 if (PSXDisplay.Double==2)
\r
1637 STATUSREG|=GPUSTATUS_DOUBLEHEIGHT;
\r
1638 else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT;
\r
1640 if (PSXDisplay.RGB24New)
\r
1641 STATUSREG|=GPUSTATUS_RGB24;
\r
1642 else STATUSREG&=~GPUSTATUS_RGB24;
\r
1644 updateDisplayIfChanged();
\r
1648 //--------------------------------------------------//
\r
1649 // ask about GPU version and other stuff
\r
1657 GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos
\r
1660 GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start
\r
1663 GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end
\r
1667 GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset
\r
1670 if(dwGPUVersion==2)
\r
1672 else GPUdataRet=0x02; // gpu type
\r
1675 case 0x0F: // some bios addr?
\r
1676 GPUdataRet=0xBFC03720;
\r
1680 //--------------------------------------------------//
\r
1684 ////////////////////////////////////////////////////////////////////////
\r
1685 // vram read/write helpers
\r
1686 ////////////////////////////////////////////////////////////////////////
\r
1688 BOOL bNeedWriteUpload=FALSE;
\r
1690 __inline void FinishedVRAMWrite(void)
\r
1692 if(bNeedWriteUpload)
\r
1694 bNeedWriteUpload=FALSE;
\r
1695 CheckWriteUpdate();
\r
1698 // set register to NORMAL operation
\r
1699 iDataWriteMode = DR_NORMAL;
\r
1701 // reset transfer values, to prevent mis-transfer of data
\r
1702 VRAMWrite.ColsRemaining = 0;
\r
1703 VRAMWrite.RowsRemaining = 0;
\r
1706 __inline void FinishedVRAMRead(void)
\r
1708 // set register to NORMAL operation
\r
1709 iDataReadMode = DR_NORMAL;
\r
1710 // reset transfer values, to prevent mis-transfer of data
\r
1713 VRAMRead.Width = 0;
\r
1714 VRAMRead.Height = 0;
\r
1715 VRAMRead.ColsRemaining = 0;
\r
1716 VRAMRead.RowsRemaining = 0;
\r
1718 // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER
\r
1719 STATUSREG&=~GPUSTATUS_READYFORVRAM;
\r
1722 ////////////////////////////////////////////////////////////////////////
\r
1723 // vram read check ex (reading from card's back/frontbuffer if needed...
\r
1725 ////////////////////////////////////////////////////////////////////////
\r
1727 void CheckVRamReadEx(int x, int y, int dx, int dy)
\r
1729 unsigned short sArea;
\r
1730 int ux,uy,udx,udy,wx,wy;
\r
1731 unsigned short * p1, *p2;
\r
1735 unsigned short s,sx;
\r
1737 if(STATUSREG&GPUSTATUS_RGB24) return;
\r
1739 if(((dx > PSXDisplay.DisplayPosition.x) &&
\r
1740 (x < PSXDisplay.DisplayEnd.x) &&
\r
1741 (dy > PSXDisplay.DisplayPosition.y) &&
\r
1742 (y < PSXDisplay.DisplayEnd.y)))
\r
1745 if((!(PSXDisplay.InterlacedTest) &&
\r
1746 (dx > PreviousPSXDisplay.DisplayPosition.x) &&
\r
1747 (x < PreviousPSXDisplay.DisplayEnd.x) &&
\r
1748 (dy > PreviousPSXDisplay.DisplayPosition.y) &&
\r
1749 (y < PreviousPSXDisplay.DisplayEnd.y)))
\r
1760 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1762 bFullVRam=TRUE;iRenderFVR=2;
\r
1770 ux=PSXDisplay.DisplayPosition.x;
\r
1771 uy=PSXDisplay.DisplayPosition.y;
\r
1772 udx=PSXDisplay.DisplayEnd.x-ux;
\r
1773 udy=PSXDisplay.DisplayEnd.y-uy;
\r
1774 if((PreviousPSXDisplay.DisplayEnd.x-
\r
1775 PreviousPSXDisplay.DisplayPosition.x)==udx &&
\r
1776 (PreviousPSXDisplay.DisplayEnd.y-
\r
1777 PreviousPSXDisplay.DisplayPosition.y)==udy)
\r
1778 p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) +
\r
1779 PreviousPSXDisplay.DisplayPosition.x);
\r
1783 ux=PreviousPSXDisplay.DisplayPosition.x;
\r
1784 uy=PreviousPSXDisplay.DisplayPosition.y;
\r
1785 udx=PreviousPSXDisplay.DisplayEnd.x-ux;
\r
1786 udy=PreviousPSXDisplay.DisplayEnd.y-uy;
\r
1787 if((PSXDisplay.DisplayEnd.x-
\r
1788 PSXDisplay.DisplayPosition.x)==udx &&
\r
1789 (PSXDisplay.DisplayEnd.y-
\r
1790 PSXDisplay.DisplayPosition.y)==udy)
\r
1791 p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) +
\r
1792 PSXDisplay.DisplayPosition.x);
\r
1795 p1=(psxVuw + (1024*uy) + ux);
\r
1799 wx=dx=udx;wy=dy=udy;
\r
1801 if(udx<=0) return;
\r
1802 if(udy<=0) return;
\r
1808 XS=(float)rRatioRect.right/(float)wx;
\r
1809 YS=(float)rRatioRect.bottom/(float)wy;
\r
1811 dx=(int)((float)(dx)*XS);
\r
1812 dy=(int)((float)(dy)*YS);
\r
1814 if(dx>iResX) dx=iResX;
\r
1815 if(dy>iResY) dy=iResY;
\r
1823 x+=rRatioRect.left;
\r
1824 y-=rRatioRect.top;
\r
1826 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1828 if(!pGfxCardScreen)
\r
1830 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1831 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);
\r
1834 ps=pGfxCardScreen;
\r
1836 //if(!sArea) glReadBuffer(GL_FRONT);
\r
1838 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1840 //if(!sArea) glReadBuffer(GL_BACK);
\r
1844 XS=(float)dx/(float)(udx);
\r
1845 YS=(float)dy/(float)(udy+1);
\r
1847 for(y=udy;y>0;y--)
\r
1849 for(x=0;x<udx;x++)
\r
1851 if(p1>=psxVuw && p1<psxVuw_eom)
\r
1853 px=ps+(3*((int)((float)x * XS))+
\r
1854 (3*dx)*((int)((float)y*YS)));
\r
1864 if(p2>=psxVuw && p2<psxVuw_eom) *p2=s;
\r
1871 if(p2) p2 += 1024 - udx;
\r
1875 ////////////////////////////////////////////////////////////////////////
\r
1876 // vram read check (reading from card's back/frontbuffer if needed...
\r
1878 ////////////////////////////////////////////////////////////////////////
\r
1880 void CheckVRamRead(int x, int y, int dx, int dy, bool bFront)
\r
1882 unsigned short sArea;unsigned short * p;
\r
1883 int ux,uy,udx,udy,wx,wy;float XS,YS;
\r
1885 unsigned short s=0,sx;
\r
1887 if(STATUSREG&GPUSTATUS_RGB24) return;
\r
1889 if(((dx > PSXDisplay.DisplayPosition.x) &&
\r
1890 (x < PSXDisplay.DisplayEnd.x) &&
\r
1891 (dy > PSXDisplay.DisplayPosition.y) &&
\r
1892 (y < PSXDisplay.DisplayEnd.y)))
\r
1895 if((!(PSXDisplay.InterlacedTest) &&
\r
1896 (dx > PreviousPSXDisplay.DisplayPosition.x) &&
\r
1897 (x < PreviousPSXDisplay.DisplayEnd.x) &&
\r
1898 (dy > PreviousPSXDisplay.DisplayPosition.y) &&
\r
1899 (y < PreviousPSXDisplay.DisplayEnd.y)))
\r
1906 if(dwActFixes&0x40)
\r
1910 bFullVRam=TRUE;iRenderFVR=2;return;
\r
1912 bFullVRam=TRUE;iRenderFVR=2;
\r
1915 ux=x;uy=y;udx=dx;udy=dy;
\r
1919 x -=PSXDisplay.DisplayPosition.x;
\r
1920 dx-=PSXDisplay.DisplayPosition.x;
\r
1921 y -=PSXDisplay.DisplayPosition.y;
\r
1922 dy-=PSXDisplay.DisplayPosition.y;
\r
1923 wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x;
\r
1924 wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y;
\r
1928 x -=PreviousPSXDisplay.DisplayPosition.x;
\r
1929 dx-=PreviousPSXDisplay.DisplayPosition.x;
\r
1930 y -=PreviousPSXDisplay.DisplayPosition.y;
\r
1931 dy-=PreviousPSXDisplay.DisplayPosition.y;
\r
1932 wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x;
\r
1933 wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y;
\r
1935 if(x<0) {ux-=x;x=0;}
\r
1936 if(y<0) {uy-=y;y=0;}
\r
1937 if(dx>wx) {udx-=(dx-wx);dx=wx;}
\r
1938 if(dy>wy) {udy-=(dy-wy);dy=wy;}
\r
1942 p=(psxVuw + (1024*uy) + ux);
\r
1944 if(udx<=0) return;
\r
1945 if(udy<=0) return;
\r
1951 XS=(float)rRatioRect.right/(float)wx;
\r
1952 YS=(float)rRatioRect.bottom/(float)wy;
\r
1954 dx=(int)((float)(dx)*XS);
\r
1955 dy=(int)((float)(dy)*YS);
\r
1956 x=(int)((float)x*XS);
\r
1957 y=(int)((float)y*YS);
\r
1962 if(dx>iResX) dx=iResX;
\r
1963 if(dy>iResY) dy=iResY;
\r
1971 x+=rRatioRect.left;
\r
1972 y-=rRatioRect.top;
\r
1974 if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y;
\r
1976 if(!pGfxCardScreen)
\r
1978 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
1979 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);
\r
1982 ps=pGfxCardScreen;
\r
1984 // if(bFront) glReadBuffer(GL_FRONT);
\r
1986 glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
1988 // if(bFront) glReadBuffer(GL_BACK);
\r
1990 XS=(float)dx/(float)(udx);
\r
1991 YS=(float)dy/(float)(udy+1);
\r
1993 for(y=udy;y>0;y--)
\r
1995 for(x=0;x<udx;x++)
\r
1997 if(p>=psxVuw && p<psxVuw_eom)
\r
1999 px=ps+(3*((int)((float)x * XS))+
\r
2000 (3*dx)*((int)((float)y*YS)));
\r
2016 ////////////////////////////////////////////////////////////////////////
\r
2017 // core read from vram
\r
2018 ////////////////////////////////////////////////////////////////////////
\r
2021 void CALLBACK GPUreadDataMem(unsigned int * pMem, int iSize)
\r
2023 void CALLBACK GPUreadDataMem(unsigned long * pMem, int iSize)
\r
2028 if(iDataReadMode!=DR_VRAMTRANSFER) return;
\r
2032 // adjust read ptr, if necessary
\r
2033 while(VRAMRead.ImagePtr>=psxVuw_eom)
\r
2034 VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2035 while(VRAMRead.ImagePtr<psxVuw)
\r
2036 VRAMRead.ImagePtr+=iGPUHeight*1024;
\r
2038 if((iFrameReadType&1 && iSize>1) &&
\r
2039 !(iDrawnSomething==2 &&
\r
2040 VRAMRead.x == VRAMWrite.x &&
\r
2041 VRAMRead.y == VRAMWrite.y &&
\r
2042 VRAMRead.Width == VRAMWrite.Width &&
\r
2043 VRAMRead.Height == VRAMWrite.Height))
\r
2044 CheckVRamRead(VRAMRead.x,VRAMRead.y,
\r
2045 VRAMRead.x+VRAMRead.RowsRemaining,
\r
2046 VRAMRead.y+VRAMRead.ColsRemaining,
\r
2049 for(i=0;i<iSize;i++)
\r
2051 // do 2 seperate 16bit reads for compatibility (wrap issues)
\r
2052 if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))
\r
2055 GPUdataRet=(unsigned long)*VRAMRead.ImagePtr;
\r
2057 VRAMRead.ImagePtr++;
\r
2058 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2059 VRAMRead.RowsRemaining --;
\r
2061 if(VRAMRead.RowsRemaining<=0)
\r
2063 VRAMRead.RowsRemaining = VRAMRead.Width;
\r
2064 VRAMRead.ColsRemaining--;
\r
2065 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
\r
2066 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2069 // higher 16 bit (always, even if it's an odd width)
\r
2070 GPUdataRet|=(unsigned long)(*VRAMRead.ImagePtr)<<16;
\r
2071 *pMem++=GPUdataRet;
\r
2073 if(VRAMRead.ColsRemaining <= 0)
\r
2074 {FinishedVRAMRead();goto ENDREAD;}
\r
2076 VRAMRead.ImagePtr++;
\r
2077 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2078 VRAMRead.RowsRemaining--;
\r
2079 if(VRAMRead.RowsRemaining<=0)
\r
2081 VRAMRead.RowsRemaining = VRAMRead.Width;
\r
2082 VRAMRead.ColsRemaining--;
\r
2083 VRAMRead.ImagePtr += 1024 - VRAMRead.Width;
\r
2084 if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024;
\r
2086 if(VRAMRead.ColsRemaining <= 0)
\r
2087 {FinishedVRAMRead();goto ENDREAD;}
\r
2089 else {FinishedVRAMRead();goto ENDREAD;}
\r
2097 unsigned long CALLBACK GPUreadData(void)
\r
2099 unsigned long CALLBACK GPUreadData(void)
\r
2104 GPUreadDataMem(&l,1);
\r
2106 GPUreadDataMem(&l,1);
\r
2108 return GPUdataRet;
\r
2111 ////////////////////////////////////////////////////////////////////////
\r
2112 // helper table to know how much data is used by drawing commands
\r
2113 ////////////////////////////////////////////////////////////////////////
\r
2115 const u8 primTableCX[256] =
\r
2132 8,8,8,8,12,12,12,12,
\r
2136 // 5,5,5,5,6,6,6,6, //FLINE
\r
2137 254,254,254,254,254,254,254,254,
\r
2141 // 7,7,7,7,9,9,9,9, // LINEG3 LINEG4
\r
2142 255,255,255,255,255,255,255,255,
\r
2144 3,3,3,3,4,4,4,4, // TILE SPRT
\r
2146 2,2,2,2,3,3,3,3, // TILE1
\r
2185 ////////////////////////////////////////////////////////////////////////
\r
2186 // processes data send to GPU data register
\r
2187 ////////////////////////////////////////////////////////////////////////
\r
2190 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)
\r
2192 void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize)
\r
2196 unsigned long gdata=0;
\r
2199 GPUIsNotReadyForCommands;
\r
2203 if(iDataWriteMode==DR_VRAMTRANSFER)
\r
2205 // make sure we are in vram
\r
2206 while(VRAMWrite.ImagePtr>=psxVuw_eom)
\r
2207 VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2208 while(VRAMWrite.ImagePtr<psxVuw)
\r
2209 VRAMWrite.ImagePtr+=iGPUHeight*1024;
\r
2211 // now do the loop
\r
2212 while(VRAMWrite.ColsRemaining>0)
\r
2214 while(VRAMWrite.RowsRemaining>0)
\r
2216 if(i>=iSize) {goto ENDVRAM;}
\r
2221 *VRAMWrite.ImagePtr++ = (unsigned short)gdata;
\r
2222 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2223 VRAMWrite.RowsRemaining --;
\r
2225 if(VRAMWrite.RowsRemaining <= 0)
\r
2227 VRAMWrite.ColsRemaining--;
\r
2228 if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width
\r
2230 gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16);
\r
2231 FinishedVRAMWrite();
\r
2234 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
2235 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
2238 *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16);
\r
2239 if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
\r
2240 VRAMWrite.RowsRemaining --;
\r
2243 VRAMWrite.RowsRemaining = VRAMWrite.Width;
\r
2244 VRAMWrite.ColsRemaining--;
\r
2245 VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
\r
2248 FinishedVRAMWrite();
\r
2253 if(iDataWriteMode==DR_NORMAL)
\r
2255 void (* *primFunc)(u8 *);
\r
2256 if(bSkipNextFrame) primFunc=primTableSkip;
\r
2257 else primFunc=primTableJ;
\r
2261 if(iDataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;
\r
2263 gdata=*pMem++;i++;
\r
2267 command = (u8)((gdata>>24) & 0xff);
\r
2269 if(primTableCX[command])
\r
2271 gpuDataC = primTableCX[command];
\r
2272 gpuCommand = command;
\r
2273 gpuDataM[0] = gdata;
\r
2280 gpuDataM[gpuDataP] = gdata;
\r
2283 if((gpuDataC==254 && gpuDataP>=3) ||
\r
2284 (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1)))
\r
2286 if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000)
\r
2287 gpuDataP=gpuDataC-1;
\r
2293 if(gpuDataP == gpuDataC)
\r
2295 gpuDataC=gpuDataP=0;
\r
2296 primFunc[gpuCommand]((u8 *)gpuDataM);
\r
2298 if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games
\r
2306 GPUIsReadyForCommands;
\r
2310 ////////////////////////////////////////////////////////////////////////
\r
2313 void CALLBACK GPUwriteData(unsigned long gdata)
\r
2315 void CALLBACK GPUwriteData(unsigned long gdata)
\r
2319 GPUwriteDataMem(&gdata,1);
\r
2321 GPUwriteDataMem(&gdata,1);
\r
2325 ////////////////////////////////////////////////////////////////////////
\r
2326 // this function will be removed soon (or 'soonish') (or never)
\r
2327 ////////////////////////////////////////////////////////////////////////
\r
2329 void CALLBACK GPUsetMode(unsigned int gdata)
\r
2331 // ignore old psemu setmode:
\r
2333 // imageTransfer = gdata;
\r
2334 // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2335 // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;
\r
2338 // and this function will be removed soon as well, hehehe...
\r
2339 long CALLBACK GPUgetMode(void)
\r
2341 // ignore old psemu setmode
\r
2342 // return imageTransfer;
\r
2346 if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1;
\r
2347 if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2;
\r
2352 ////////////////////////////////////////////////////////////////////////
\r
2353 // call config dlg (Windows + Linux)
\r
2354 ////////////////////////////////////////////////////////////////////////
\r
2358 /*#include <unistd.h>
\r
2360 void StartCfgTool(s8 * pCmdLine) // linux: start external cfg tool
\r
2362 FILE * cf;s8 filename[255],t[255];
\r
2364 strcpy(filename,"cfg/cfgPeopsMesaGL"); // look in cfg sub folder first
\r
2365 cf=fopen(filename,"rb");
\r
2371 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2377 strcpy(filename,"cfgPeopsMesaGL"); // look in current folder
\r
2378 cf=fopen(filename,"rb");
\r
2382 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2387 sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder
\r
2388 cf=fopen(filename,"rb");
\r
2393 chdir(getenv("HOME"));
\r
2394 sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine);
\r
2398 else printf("cfgPeopsMesaGL not found!\n");
\r
2407 long CALLBACK GPUconfigure(void)
\r
2409 long CALLBACK GPUconfigure(void)
\r
2414 // HWND hWP=GetActiveWindow();
\r
2415 // DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG),
\r
2416 // hWP,(DLGPROC)CfgDlgProc);
\r
2419 // StartCfgTool("CFG");
\r
2426 ////////////////////////////////////////////////////////////////////////
\r
2427 // sets all kind of act fixes
\r
2428 ////////////////////////////////////////////////////////////////////////
\r
2430 void SetFixes(void)
\r
2434 if(dwActFixes & 0x2000)
\r
2435 dispWidths[4]=384;
\r
2436 else dispWidths[4]=368;
\r
2439 ////////////////////////////////////////////////////////////////////////
\r
2440 // Pete Special: make an 'intelligent' dma chain check (<-Tekken3)
\r
2441 ////////////////////////////////////////////////////////////////////////
\r
2443 unsigned long lUsedAddr[3];
\r
2445 __inline BOOL CheckForEndlessLoop(unsigned long laddr)
\r
2447 if(laddr==lUsedAddr[1]) return TRUE;
\r
2448 if(laddr==lUsedAddr[2]) return TRUE;
\r
2450 if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
\r
2451 else lUsedAddr[2]=laddr;
\r
2452 lUsedAddr[0]=laddr;
\r
2456 ////////////////////////////////////////////////////////////////////////
\r
2457 // core gives a dma chain to gpu: same as the gpuwrite interface funcs
\r
2458 ////////////////////////////////////////////////////////////////////////
\r
2461 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)
\r
2463 long CALLBACK GPUdmaChain(unsigned long * baseAddrL, unsigned long addr)
\r
2466 unsigned long dmaMem;
\r
2468 short count;unsigned int DMACommandCounter = 0;
\r
2470 if(bIsFirstFrame) GLinitialize();
\r
2474 lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
\r
2476 baseAddrB = (u8*) baseAddrL;
\r
2480 if(iGPUHeight==512) addr&=0x1FFFFC;
\r
2482 if(DMACommandCounter++ > 2000000) break;
\r
2483 if(CheckForEndlessLoop(addr)) break;
\r
2485 count = baseAddrB[addr+3];
\r
2490 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
\r
2492 if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
\r
2495 addr = baseAddrL[addr>>2]&0xffffff;
\r
2497 while (addr != 0xffffff);
\r
2504 ////////////////////////////////////////////////////////////////////////
\r
2506 ////////////////////////////////////////////////////////////////////////
\r
2509 void CALLBACK GPUabout(void)
\r
2511 void CALLBACK GPUabout(void)
\r
2517 ////////////////////////////////////////////////////////////////////////
\r
2518 // We are ever fine ;)
\r
2519 ////////////////////////////////////////////////////////////////////////
\r
2522 long CALLBACK GPUtest(void)
\r
2524 long CALLBACK GPUtest(void)
\r
2527 // if test fails this function should return negative value for error (unable to continue)
\r
2528 // and positive value for warning (can continue but output might be crappy)
\r
2533 ////////////////////////////////////////////////////////////////////////
\r
2534 // save state funcs
\r
2535 ////////////////////////////////////////////////////////////////////////
\r
2537 ////////////////////////////////////////////////////////////////////////
\r
2540 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)
\r
2542 long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF)
\r
2545 if(ulGetFreezeData==2)
\r
2547 long lSlotNum=*((long *)pF);
\r
2548 if(lSlotNum<0) return 0;
\r
2549 if(lSlotNum>8) return 0;
\r
2550 lSelectedSlot=lSlotNum+1;
\r
2554 if(!pF) return 0;
\r
2555 if(pF->ulFreezeVersion!=1) return 0;
\r
2557 if(ulGetFreezeData==1)
\r
2559 pF->ulStatus=STATUSREG;
\r
2560 memcpy(pF->ulControl,ulStatusControl,256*sizeof(unsigned long));
\r
2561 memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2);
\r
2566 if(ulGetFreezeData!=0) return 0;
\r
2568 STATUSREG=pF->ulStatus;
\r
2569 memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long));
\r
2570 memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2);
\r
2572 ResetTextureArea(TRUE);
\r
2575 GPUwriteStatus(ulStatusControl[0]);
\r
2576 GPUwriteStatus(ulStatusControl[1]);
\r
2577 GPUwriteStatus(ulStatusControl[2]);
\r
2578 GPUwriteStatus(ulStatusControl[3]);
\r
2579 GPUwriteStatus(ulStatusControl[8]);
\r
2580 GPUwriteStatus(ulStatusControl[6]);
\r
2581 GPUwriteStatus(ulStatusControl[7]);
\r
2582 GPUwriteStatus(ulStatusControl[5]);
\r
2583 GPUwriteStatus(ulStatusControl[4]);
\r
2585 GPUwriteStatus(ulStatusControl[0]);
\r
2586 GPUwriteStatus(ulStatusControl[1]);
\r
2587 GPUwriteStatus(ulStatusControl[2]);
\r
2588 GPUwriteStatus(ulStatusControl[3]);
\r
2589 GPUwriteStatus(ulStatusControl[8]);
\r
2590 GPUwriteStatus(ulStatusControl[6]);
\r
2591 GPUwriteStatus(ulStatusControl[7]);
\r
2592 GPUwriteStatus(ulStatusControl[5]);
\r
2593 GPUwriteStatus(ulStatusControl[4]);
\r
2598 ////////////////////////////////////////////////////////////////////////
\r
2599 // special "emu infos" / "emu effects" functions
\r
2600 ////////////////////////////////////////////////////////////////////////
\r
2605 //11 = transparent
\r
2607 u8 cFont[10][120]=
\r
2610 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2611 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2612 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2613 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2614 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2615 0x80,0x00,0x05,0x54,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,0x14,0x05,0x00,0x00,
\r
2623 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2624 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2625 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2626 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2627 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2628 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2629 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2632 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2633 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2634 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2635 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2636 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2637 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2638 0x80,0x00,0x05,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,0x00,0x50,0x00,0x00,
\r
2645 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2646 0x80,0x00,0x05,0x55,0x00,0x00,
\r
2647 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2648 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2649 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2650 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2651 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2654 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2655 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2656 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2657 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2658 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2659 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2660 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2661 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2662 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2663 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2664 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2665 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2666 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2667 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2668 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2669 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2670 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2671 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2672 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2673 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2676 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2677 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2678 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2679 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2680 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2681 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2682 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2683 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2684 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2685 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2686 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2687 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2688 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2689 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2690 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2691 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2692 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2693 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2694 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2695 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2698 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2699 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2700 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2701 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2702 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2703 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2704 0x80,0x00,0x00,0x54,0x00,0x00,
\r
2705 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2706 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2707 0x80,0x00,0x05,0x14,0x00,0x00,
\r
2708 0x80,0x00,0x14,0x14,0x00,0x00,
\r
2709 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2710 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2711 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2712 0x80,0x00,0x00,0x55,0x00,0x00,
\r
2713 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2714 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2715 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2716 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2717 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2720 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2721 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2722 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2723 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2724 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2725 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2726 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2727 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2728 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2729 0x80,0x00,0x15,0x54,0x00,0x00,
\r
2730 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2731 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2732 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2733 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2734 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2735 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2736 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2737 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2738 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2739 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2742 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2743 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2744 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2745 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2746 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2747 0x80,0x00,0x01,0x54,0x00,0x00,
\r
2748 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2749 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2750 0x80,0x00,0x14,0x00,0x00,0x00,
\r
2751 0x80,0x00,0x15,0x54,0x00,0x00,
\r
2752 0x80,0x00,0x15,0x05,0x00,0x00,
\r
2753 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2754 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2755 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2756 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2757 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2758 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2759 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2760 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2761 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2764 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2765 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2766 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2767 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2768 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2769 0x80,0x00,0x15,0x55,0x00,0x00,
\r
2770 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2771 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2772 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2773 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2774 0x80,0x00,0x00,0x50,0x00,0x00,
\r
2775 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2776 0x80,0x00,0x01,0x40,0x00,0x00,
\r
2777 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2778 0x80,0x00,0x05,0x00,0x00,0x00,
\r
2779 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2780 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2781 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2782 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2783 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2786 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2787 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2788 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2789 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2790 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2791 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2792 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2793 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2794 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2795 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2796 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2797 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2798 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2799 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2800 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2801 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2802 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2803 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2804 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2805 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2808 {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
\r
2809 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2810 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2811 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2812 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2813 0x80,0x00,0x05,0x54,0x00,0x00,
\r
2814 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2815 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2816 0x80,0x00,0x14,0x05,0x00,0x00,
\r
2817 0x80,0x00,0x14,0x15,0x00,0x00,
\r
2818 0x80,0x00,0x05,0x55,0x00,0x00,
\r
2819 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2820 0x80,0x00,0x00,0x05,0x00,0x00,
\r
2821 0x80,0x00,0x00,0x14,0x00,0x00,
\r
2822 0x80,0x00,0x05,0x50,0x00,0x00,
\r
2823 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2824 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2825 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2826 0x80,0x00,0x00,0x00,0x00,0x00,
\r
2827 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa
\r
2831 ////////////////////////////////////////////////////////////////////////
\r
2833 void PaintPicDot(u8 * p,u8 c)
\r
2835 if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;}
\r
2836 if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;}
\r
2837 if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;}
\r
2840 ////////////////////////////////////////////////////////////////////////
\r
2843 void CALLBACK GPUgetScreenPic(u8 * pMem)
\r
2845 long CALLBACK GPUgetScreenPic(u8 * pMem)
\r
2848 float XS,YS;int x,y,v;
\r
2849 u8 * ps, * px, * pf;
\r
2852 if(!pGfxCardScreen)
\r
2854 glPixelStorei(GL_PACK_ALIGNMENT,1);
\r
2855 pGfxCardScreen=(u8 *)malloc(iResX*iResY*4);
\r
2858 ps=pGfxCardScreen;
\r
2860 // glReadBuffer(GL_FRONT);
\r
2862 glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps);
\r
2864 // glReadBuffer(GL_BACK);
\r
2866 XS=(float)iResX/128;
\r
2867 YS=(float)iResY/96;
\r
2872 for(x=0;x<128;x++)
\r
2874 px=ps+(3*((int)((float)x * XS))+
\r
2875 (3*iResX)*((int)((float)y*YS)));
\r
2883 /////////////////////////////////////////////////////////////////////
\r
2884 // generic number/border painter
\r
2892 c=cFont[lSelectedSlot][x+y*6];
\r
2894 PaintPicDot(pf,(u8)v);pf+=3; // paint the dots into the rect
\r
2896 PaintPicDot(pf,(u8)v);pf+=3;
\r
2898 PaintPicDot(pf,(u8)v);pf+=3;
\r
2900 PaintPicDot(pf,(u8)v);pf+=3;
\r
2906 for(x=0;x<128;x++)
\r
2908 *(pf+(95*128*3))=0x00;*pf++=0x00;
\r
2909 *(pf+(95*128*3))=0x00;*pf++=0x00;
\r
2910 *(pf+(95*128*3))=0xff;*pf++=0xff;
\r
2915 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2916 *(pf+(127*3))=0x00;*pf++=0x00;
\r
2917 *(pf+(127*3))=0xff;*pf++=0xff;
\r
2923 ////////////////////////////////////////////////////////////////////////
\r
2926 void CALLBACK GPUshowScreenPic(u8 * pMem)
\r
2928 long CALLBACK GPUshowScreenPic(u8 * pMem)
\r
2932 // if(pMem==0) return;
\r
2933 // CreatePic(pMem);
\r
2936 ////////////////////////////////////////////////////////////////////////
\r
2938 void CALLBACK GPUsetfix(unsigned long dwFixBits)
\r
2940 dwEmuFixes=dwFixBits;
\r
2943 ////////////////////////////////////////////////////////////////////////
\r
2945 void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig)
\r
2949 if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width
\r
2950 iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x);
\r
2952 // big rumble: 4...15 sp ; small rumble 1...3 sp
\r
2953 if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10));
\r
2954 else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10));
\r
2956 srand(timeGetTime()); // init rand (will be used in BufferSwap)
\r
2958 iRumbleTime=15; // let the rumble last 16 buffer swaps
\r
2961 ////////////////////////////////////////////////////////////////////////
\r
2962 // main emu can set display infos (A/M/G/D)
\r
2963 ////////////////////////////////////////////////////////////////////////
\r
2965 void CALLBACK GPUdisplayFlags(unsigned long dwFlags)
\r
2967 // dwCoreFlags=dwFlags;
\r
2970 // pcsx-rearmed callbacks
\r
2971 void CALLBACK GPUrearmedCallbacks(const void **cbs)
\r
2973 rearmed_get_layer_pos = cbs[0];
\r