From a58cfdac407bc1d8fedc11acd924b275ba28cc51 Mon Sep 17 00:00:00 2001 From: "SND\\dario86_cp" Date: Sat, 12 Mar 2011 18:54:28 +0000 Subject: Commited patch in issue #8171 (by darktjm). git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@64524 e17a0e51-4ae3-4d35-97c3-1a29b211df97 --- plugins/peopsxgl/gpu.c | 7056 ++++++++++++++++++++++++------------------------ 1 file changed, 3527 insertions(+), 3529 deletions(-) (limited to 'plugins/peopsxgl/gpu.c') diff --git a/plugins/peopsxgl/gpu.c b/plugins/peopsxgl/gpu.c index f379372b..092d32a5 100644 --- a/plugins/peopsxgl/gpu.c +++ b/plugins/peopsxgl/gpu.c @@ -1,3529 +1,3527 @@ -/*************************************************************************** - gpu.c - description - ------------------- - begin : Sun Mar 08 2009 - copyright : (C) 1999-2009 by Pete Bernert - email : BlackDove@addcom.de - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. See also the license.txt file for * - * additional informations. * - * * - ***************************************************************************/ - -// !!! enable this, if Linux XF86VidMode is not supported: -//#define NOVMODE - -#include "stdafx.h" - -#if !defined(_MACGL) && !defined(_WINDOWS) - -#include "config.h" - -#ifndef NOVMODE -#include -static XF86VidModeModeInfo **modes=0; -static int iOldMode=0; -#endif - -#endif - -#define _IN_GPU - -#include "externals.h" -#include "gpu.h" -#include "draw.h" -#include "cfg.h" -#include "prim.h" -#include "psemu_plugin_defs.h" -#include "texture.h" -#include "menu.h" -#include "fps.h" -#include "key.h" -#ifdef _WINDOWS -#include "resource.h" -#include "ssave.h" -#endif -#ifdef ENABLE_NLS -#include -#include -#define _(x) gettext(x) -#define N_(x) (x) -#else -#define _(x) (x) -#define N_(x) (x) -#endif - -//////////////////////////////////////////////////////////////////////// -// PPDK developer must change libraryName field and can change revision and build -//////////////////////////////////////////////////////////////////////// - -const unsigned char version = 1; // do not touch - library for PSEmu 1.x -const unsigned char revision = 1; -const unsigned char build = 78; - -static char *libraryName = N_("OpenGL Driver"); - -static char *PluginAuthor = N_("Pete Bernert"); -static char *libraryInfo = N_("Based on P.E.Op.S. MesaGL Driver V1.78\nCoded by Pete Bernert\n"); - -//////////////////////////////////////////////////////////////////////// -// memory image of the PSX vram -//////////////////////////////////////////////////////////////////////// - -unsigned char *psxVSecure; -unsigned char *psxVub; -signed char *psxVsb; -unsigned short *psxVuw; -unsigned short *psxVuw_eom; -signed short *psxVsw; -uint32_t *psxVul; -signed int *psxVsl; - -// macro for easy access to packet information -#define GPUCOMMAND(x) ((x>>24) & 0xff) - -GLfloat gl_z=0.0f; -BOOL bNeedInterlaceUpdate=FALSE; -BOOL bNeedRGB24Update=FALSE; -BOOL bChangeWinMode=FALSE; - -#ifdef _WINDOWS -extern HGLRC GLCONTEXT; -#endif - -uint32_t ulStatusControl[256]; - -//////////////////////////////////////////////////////////////////////// -// global GPU vars -//////////////////////////////////////////////////////////////////////// - -static int GPUdataRet; -int lGPUstatusRet; -char szDispBuf[64]; - -uint32_t dwGPUVersion = 0; -int iGPUHeight = 512; -int iGPUHeightMask = 511; -int GlobalTextIL = 0; -int iTileCheat = 0; - -static uint32_t gpuDataM[256]; -static unsigned char gpuCommand = 0; -static int gpuDataC = 0; -static int gpuDataP = 0; - -VRAMLoad_t VRAMWrite; -VRAMLoad_t VRAMRead; -int iDataWriteMode; -int iDataReadMode; - -int lClearOnSwap; -int lClearOnSwapColor; -BOOL bSkipNextFrame = FALSE; -int iColDepth; -BOOL bChangeRes; -BOOL bWindowMode; -int iWinSize; - -// possible psx display widths -short dispWidths[8] = {256,320,512,640,368,384,512,640}; - -PSXDisplay_t PSXDisplay; -PSXDisplay_t PreviousPSXDisplay; -TWin_t TWin; -short imageX0,imageX1; -short imageY0,imageY1; -BOOL bDisplayNotSet = TRUE; -GLuint uiScanLine=0; -int iUseScanLines=0; -float iScanlineColor[] = {0,0,0, 0.3}; // easy on the eyes. -int lSelectedSlot=0; -unsigned char * pGfxCardScreen=0; -int iBlurBuffer=0; -int iScanBlend=0; -int iRenderFVR=0; -int iNoScreenSaver=0; -uint32_t ulGPUInfoVals[16]; -int iFakePrimBusy = 0; -int iRumbleVal = 0; -int iRumbleTime = 0; -uint32_t vBlank=0; - -//////////////////////////////////////////////////////////////////////// -// stuff to make this a true PDK module -//////////////////////////////////////////////////////////////////////// - -char * CALLBACK PSEgetLibName(void) -{ - return _(libraryName); -} - -unsigned long CALLBACK PSEgetLibType(void) -{ - return PSE_LT_GPU; -} - -unsigned long CALLBACK PSEgetLibVersion(void) -{ - return version<<16|revision<<8|build; -} - -char * GPUgetLibInfos(void) -{ - return _(libraryInfo); -} - -//////////////////////////////////////////////////////////////////////// -// snapshot funcs (saves screen to bitmap / text infos into file) -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS -char * GetConfigInfos(HWND hW) -#else -char * GetConfigInfos(int hW) -#endif -{ -#ifdef _WINDOWS - HDC hdc;HGLRC hglrc; -#endif - char szO[2][4]={"off","on "}; - char szTxt[256]; - char * pB=(char *)malloc(32767); - - if(!pB) return NULL; - *pB=0; - //----------------------------------------------------// - sprintf(szTxt,"Plugin: %s %d.%d.%d (mod)\r\n",libraryName,version,revision,build); - strcat(pB,szTxt); - sprintf(szTxt,"Author: %s\r\n",PluginAuthor); - strcat(pB,szTxt); - -#ifdef _WINDOWS - if(hW) - { - hdc = GetDC(hW); - bSetupPixelFormat(hdc); - hglrc = wglCreateContext(hdc); - wglMakeCurrent(hdc, hglrc); - } -#endif - - sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR)); - strcat(pB,szTxt); - sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER)); - strcat(pB,szTxt); - sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION)); - strcat(pB,szTxt); - //strcat(pB,(char *)glGetString(GL_EXTENSIONS)); - //strcat(pB,"\r\n\r\n"); - -#ifdef _WINDOWS - if(hW) - { - wglMakeCurrent(NULL, NULL); - wglDeleteContext(hglrc); - ReleaseDC(hW,hdc); - } - //----------------------------------------------------// -#endif - - if(hW && bWindowMode) - sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize)); - else - sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY); - strcat(pB,szTxt); - if(bWindowMode) sprintf(szTxt,"Window mode\r\n"); - else - { - sprintf(szTxt,"Fullscreen "); - strcat(pB,szTxt); - if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth); - else sprintf(szTxt,"- NO desktop changing\r\n"); - } - strcat(pB,szTxt); - - if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]); - else strcpy(szTxt,"- V-Sync: Driver\r\n"); - strcat(pB,szTxt); - sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]); - strcat(pB,szTxt); - //----------------------------------------------------// - strcpy(szTxt,"Textures:\r\n- "); - if(iTexQuality==0) strcat(szTxt,"Default"); - else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4"); - else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1"); - else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8"); - else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8"); - if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n"); - else strcat(szTxt,"\r\n"); - strcat(pB,szTxt); - if(!hW) - { - sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType); - if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n"); - else strcat(szTxt,"NOT supported\r\n"); - } - else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType); - strcat(pB,szTxt); - sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures); - strcat(pB,szTxt); - if(!hW) - { - sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]); - strcat(pB,szTxt); - } - sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize); - if(!hW) - sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt); - else strcat(szTxt,"\r\n\r\n"); - strcat(pB,szTxt); - //----------------------------------------------------// - sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]); - strcat(pB,szTxt); - sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]); - strcat(pB,szTxt); - if(iFrameLimit==2) - strcpy(szTxt,"- FPS limit: Auto\r\n\r\n"); - else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate); - strcat(pB,szTxt); - //----------------------------------------------------// - sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing); - strcat(pB,szTxt); - sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType); - if(!hW && iFrameTexType==2) - { - if(gTexFrameName) strcat(szTxt," - texture created\r\n"); - else strcat(szTxt," - not used yet\r\n"); - } - else strcat(szTxt,"\r\n"); - strcat(pB,szTxt); - sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType); - strcat(pB,szTxt); - sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]); - strcat(pB,szTxt); - sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]); - strcat(pB,szTxt); - sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]); - if(!hW && bAdvancedBlend) - { - if(bGLBlend) strcat(szTxt," (hardware)\r\n"); - else strcat(szTxt," (software)\r\n"); - } - else strcat(szTxt,"\r\n"); - strcat(pB,szTxt); - - if(!hW) - { - strcpy(szTxt,"- Subtractive blending: "); - if(glBlendEquationEXTEx) - { - if(bUseMultiPass) strcat(szTxt,"supported, but not used!"); - else strcat(szTxt,"activated"); - } - else strcat(szTxt," NOT supported!"); - strcat(szTxt,"\r\n\r\n"); - } - else strcpy(szTxt,"\r\n"); - - strcat(pB,szTxt); - //----------------------------------------------------// - sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]); - strcat(pB,szTxt); - if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend); - else strcpy(szTxt,"\r\n"); - strcat(pB,szTxt); - sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]); - strcat(pB,szTxt); -// sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]); -// fwrite(szTxt,lstrlen(szTxt),1,txtfile); - sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]); - strcat(pB,szTxt); - sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]); - strcat(pB,szTxt); - sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]); - strcat(pB,szTxt); - sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]); - strcat(pB,szTxt); - if(!hW && iBlurBuffer) - { - if(gTexBlurName) strcat(pB," - supported\r\n"); - else strcat(pB," - not supported\r\n"); - } - else strcat(pB,"\r\n"); - sprintf(szTxt,"- Game fixes: %s [%08x]\r\n",szO[bUseFixes],dwCfgFixes); - strcat(pB,szTxt); - //----------------------------------------------------// - return pB; -} - -//////////////////////////////////////////////////////////////////////// -// save text infos to file -//////////////////////////////////////////////////////////////////////// - -void DoTextSnapShot(int iNum) -{ - FILE *txtfile;char szTxt[256];char * pB; - -#ifdef _WINDOWS - sprintf(szTxt,"snap\\pcsx%04d.txt",iNum); -#else - sprintf(szTxt,"%s/pcsx%04d.txt",getenv("HOME"),iNum); -#endif - - if((txtfile=fopen(szTxt,"wb"))==NULL) - return; - - pB=GetConfigInfos(0); - if(pB) - { - fwrite(pB,strlen(pB),1,txtfile); - free(pB); - } - fclose(txtfile); -} - -//////////////////////////////////////////////////////////////////////// -// saves screen bitmap to file -//////////////////////////////////////////////////////////////////////// - -void DoSnapShot(void) -{ - unsigned char * snapshotdumpmem=NULL,* p,c; - FILE *bmpfile;char filename[256]; - unsigned char header[0x36];int size; - unsigned char empty[2]={0,0};int i; - unsigned int snapshotnr = 0; - short SnapWidth; - short SnapHeigth; - - bSnapShot=FALSE; - - SnapWidth = iResX; - SnapHeigth = iResY; - - size=SnapWidth * SnapHeigth * 3 + 0x38; - - if((snapshotdumpmem=(unsigned char *) - malloc(SnapWidth*SnapHeigth*3))==NULL) - return; - - // fill in proper values for BMP - for(i=0;i<0x36;i++) header[i]=0; - header[0]='B'; - header[1]='M'; - header[2]=(unsigned char)(size&0xff); - header[3]=(unsigned char)((size>>8)&0xff); - header[4]=(unsigned char)((size>>16)&0xff); - header[5]=(unsigned char)((size>>24)&0xff); - header[0x0a]=0x36; - header[0x0e]=0x28; - header[0x12]=(unsigned char)(SnapWidth%256); - header[0x13]=(unsigned char)(SnapWidth/256); - header[0x16]=(unsigned char)(SnapHeigth%256); - header[0x17]=(unsigned char)(SnapHeigth/256); - header[0x1a]=0x01; - header[0x1c]=0x18; - header[0x26]=0x12; - header[0x27]=0x0B; - header[0x2A]=0x12; - header[0x2B]=0x0B; - - // increment snapshot value - // get filename - do - { - snapshotnr++; -#ifdef _WINDOWS - sprintf(filename,"snap/pcsx%04d.bmp",snapshotnr); -#else - sprintf(filename,"%s/pcsx%04d.bmp",getenv("HOME"),snapshotnr); -#endif - bmpfile=fopen(filename,"rb"); - if(bmpfile==NULL)break; - fclose(bmpfile); - if(snapshotnr==9999) break; - } - while(TRUE); - - // try opening new snapshot file - if((bmpfile=fopen(filename,"wb"))==NULL) - {free(snapshotdumpmem);return;} - - fwrite(header,0x36,1,bmpfile); - - glReadPixels(0,0,SnapWidth,SnapHeigth,GL_RGB, - GL_UNSIGNED_BYTE,snapshotdumpmem); - p=snapshotdumpmem; - size=SnapWidth * SnapHeigth; - - for(i=0;i get sizes again - } - else // first real startup - { - ReadConfig(); // -> read config from registry - - SetFrameRateConfig(); // -> setup frame rate stuff - } - - if(iNoScreenSaver) EnableScreenSaver(FALSE); // at least we can try - - - memset(&dv,0,sizeof(DEVMODE)); - dv.dmSize=sizeof(DEVMODE); - EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv); - - bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows! - - if(bWindowMode) // win mode? - { - DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers) - dw&=~WS_THICKFRAME; - dw|=WS_BORDER|WS_CAPTION|CS_OWNDC; - SetWindowLong(hWWindow, GWL_STYLE, dw); - - hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any) - if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); - - iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize); - ShowWindow(hWWindow,SW_SHOWNORMAL); - - MoveWindow(hWWindow, // -> center wnd - GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2, - GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2, - iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3, - iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3, - TRUE); - UpdateWindow(hWWindow); // -> let windows do some update - - if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info - iColDepth=dv.dmBitsPerPel; - } - else // fullscreen mode: - { - if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution - dv.dmPelsWidth !=(unsigned int)iResX || - dv.dmPelsHeight!=(unsigned int)iResY) - bChangeRes=TRUE; else bChangeRes=FALSE; - - if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations') - - SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure) - - hPSEMenu=GetMenu(hWWindow); // -> hide menu - if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); - ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode - } - - rRatioRect.left = rRatioRect.top=0; - rRatioRect.right = iResX; - rRatioRect.bottom = iResY; - - r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized - hdc = GetDC(hWWindow); - FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH)); - bSetupPixelFormat(hdc); - ReleaseDC(hWWindow,hdc); - - bDisplayNotSet = TRUE; - bSetClip=TRUE; - - SetFixes(); // setup game fixes - - InitializeTextureStore(); // init texture mem - -// lGPUstatusRet = 0x74000000; - -// with some emus, we could do the OGL init right here... oh my -// if(bIsFirstFrame) GLinitialize(); - - return 0; -} - -#elif !defined (_MACGL) - -//////////////////////////////////////////////////////////////////////// -// LINUX GPU OPEN: func to open up the gpu display (X stuff) -// please note: in linux we are creating our own display, and we return -// the display ID to the main emu... that's cleaner -//////////////////////////////////////////////////////////////////////// - -char * pCaptionText=0; -int bFullScreen=0; -Display *display; - -static Cursor cursor; -static XVisualInfo *myvisual; -static Colormap colormap; -static Window window; - -static int bModeChanged=0; - -typedef struct -{ -#define MWM_HINTS_DECORATIONS 2 - long flags; - long functions; - long decorations; - long input_mode; -} MotifWmHints; - -static int dbdepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,GLX_DEPTH_SIZE,16,None}; -static int dbnodepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,None}; -static GLXContext cx; - -static int fx=0; - -//////////////////////////////////////////////////////////////////////// - -void osd_close_display (void) // close display -{ - if(display) // display exists? - { - glXDestroyContext(display,cx); // -> kill context - XFreeColormap(display, colormap); // -> kill colormap - XSync(display,False); // -> sync events - -#ifndef NOVMODE - if(bModeChanged) // -> repair screen mode - { - int myscreen=DefaultScreen(display); - XF86VidModeSwitchToMode(display,myscreen, // --> switch mode back - modes[iOldMode]); - XF86VidModeSetViewPort(display,myscreen,0,0); // --> set viewport upperleft - free(modes); // --> finally kill mode infos - bModeChanged=0; // --> done - } -#endif - - XCloseDisplay(display); // -> close display - } -} - -//////////////////////////////////////////////////////////////////////// - -void sysdep_create_display(void) // create display -{ - XSetWindowAttributes winattr;float fxgamma=2; - int myscreen;char gammastr[14]; - Screen * screen;XEvent event; - XSizeHints hints;XWMHints wm_hints; - MotifWmHints mwmhints;Atom mwmatom;Atom delwindow; - char *glxfx; - - glxfx=getenv("MESA_GLX_FX"); // 3dfx mesa fullscreen flag - if(glxfx) - { - if(glxfx[0]=='f') // -> yup, fullscreen needed - { - fx=1; // -> raise flag - putenv("FX_GLIDE_NO_SPLASH="); - sprintf(gammastr,"SST_GAMMA=%2.1f",fxgamma); // -> set gamma - putenv(gammastr); - } - } - - display=XOpenDisplay(NULL); // open display - if(!display) // no display? - { - fprintf (stderr,"Failed to open display!!!\n"); - osd_close_display(); - return; // -> bye - } - - myscreen=DefaultScreen(display); // get screen id - -#ifdef NOVMODE - if(bFullScreen) {fx=1;bModeChanged=0;} -#else - if(bFullScreen) - { - XF86VidModeModeLine mode; - int nmodes,iC; - fx=1; // raise flag - XF86VidModeGetModeLine(display,myscreen,&iC,&mode); // get actual mode info - if(mode.privsize) XFree(mode.private); // no need for private stuff - bModeChanged=0; // init mode change flag - if(iResX!=mode.hdisplay || iResY!=mode.vdisplay) // wanted mode is different? - { - XF86VidModeGetAllModeLines(display,myscreen, // -> enum all mode infos - &nmodes,&modes); - if(modes) // -> infos got? - { - for(iC=0;iC loop modes - { - if(mode.hdisplay==modes[iC]->hdisplay && // -> act mode found? - mode.vdisplay==modes[iC]->vdisplay) // if yes: store mode id - iOldMode=iC; - - if(iResX==modes[iC]->hdisplay && // -> wanted mode found? - iResY==modes[iC]->vdisplay) - { - XF86VidModeSwitchToMode(display,myscreen, // --> switch to mode - modes[iC]); - XF86VidModeSetViewPort(display,myscreen,0,0); - bModeChanged=1; // --> raise flag for repairing mode on close - } - } - - if(bModeChanged==0) // -> no mode found? - { - free(modes); // --> free infos - printf("No proper fullscreen mode found!\n"); // --> some info output - } - } - } - } -#endif - - screen=DefaultScreenOfDisplay(display); - - if(iZBufferDepth) // visual (with or without zbuffer) - myvisual=glXChooseVisual(display,myscreen,dbdepat); - else myvisual=glXChooseVisual(display,myscreen,dbnodepat); - - if(!myvisual) // no visual? - { - fprintf(stderr,"Failed to obtain visual!!!\n"); // -> bye - osd_close_display(); - return; - } - - cx=glXCreateContext(display,myvisual,0,GL_TRUE); // create rendering context - - if(!cx) // no context? - { - fprintf(stderr,"Failed to create OpenGL context!!!\n"); - osd_close_display(); // -> bxe - return; - } - - // pffff... much work for a simple blank cursor... oh, well... - if(!bFullScreen) cursor=XCreateFontCursor(display,XC_trek); - else - { - Pixmap p1,p2;XImage * img; - XColor b,w;unsigned char * idata; - XGCValues GCv; - GC GCc; - - memset(&b,0,sizeof(XColor)); - memset(&w,0,sizeof(XColor)); - idata=(unsigned char *)malloc(8); - memset(idata,0,8); - - p1=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); - p2=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); - - img = XCreateImage(display,myvisual->visual, - 1,XYBitmap,0,idata,8,8,8,1); - - GCv.function = GXcopy; - GCv.foreground = ~0; - GCv.background = 0; - GCv.plane_mask = AllPlanes; - GCc = XCreateGC(display,p1, - (GCFunction|GCForeground|GCBackground|GCPlaneMask),&GCv); - - XPutImage(display, p1,GCc,img,0,0,0,0,8,8); - XPutImage(display, p2,GCc,img,0,0,0,0,8,8); - XFreeGC(display, GCc); - - cursor = XCreatePixmapCursor(display,p1,p2,&b,&w,0,0); - - XFreePixmap(display,p1); - XFreePixmap(display,p2); - XDestroyImage(img); // will free idata as well - } - - colormap=XCreateColormap(display, // create colormap - RootWindow(display,myvisual->screen), - myvisual->visual,AllocNone); - - winattr.background_pixel=0; - winattr.border_pixel=WhitePixelOfScreen(screen); - winattr.bit_gravity=ForgetGravity; - winattr.win_gravity=NorthWestGravity; - winattr.backing_store=NotUseful; - winattr.override_redirect=False; - winattr.save_under=False; - winattr.event_mask=0; - winattr.do_not_propagate_mask=0; - winattr.colormap=colormap; - winattr.cursor=None; - - window=XCreateWindow(display, // create own window - RootWindow(display,DefaultScreen(display)), - 0,0,iResX,iResY, - 0,myvisual->depth, - InputOutput,myvisual->visual, - CWBorderPixel | CWBackPixel | - CWEventMask | CWDontPropagate | - CWColormap | CWCursor, - &winattr); - - if(!window) // no window? - { - fprintf(stderr,"Failed in XCreateWindow()!!!\n"); - osd_close_display(); // -> bye - return; - } - - delwindow = XInternAtom(display,"WM_DELETE_WINDOW",0); - XSetWMProtocols(display, window, &delwindow, 1); - - hints.flags=PMinSize|PMaxSize; // hints - if(fx) hints.flags|=USPosition|USSize; - else hints.flags|=PSize; - - hints.min_width = hints.max_width = hints.base_width = iResX; - hints.min_height = hints.max_height = hints.base_height = iResY; - - wm_hints.input=1; - wm_hints.flags=InputHint; - - XSetWMHints(display,window,&wm_hints); - XSetWMNormalHints(display,window,&hints); - if(pCaptionText) // caption - XStoreName(display,window,pCaptionText); - else XStoreName(display,window,"Pete MesaGL PSX Gpu"); - - XDefineCursor(display,window,cursor); // cursor - - if(fx) // window title bar hack - { - mwmhints.flags=MWM_HINTS_DECORATIONS; - mwmhints.decorations=0; - mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); - XChangeProperty(display,window,mwmatom,mwmatom,32, - PropModeReplace,(unsigned char *)&mwmhints,4); - } - - XSelectInput(display,window, // input setup - FocusChangeMask | ExposureMask | - KeyPressMask | KeyReleaseMask); - - XMapRaised(display,window); - XClearWindow(display,window); - XWindowEvent(display,window,ExposureMask,&event); - glXMakeCurrent(display,window,cx); - -/* - printf(glGetString(GL_VENDOR)); - printf("\n"); - printf(glGetString(GL_RENDERER)); - printf("\n"); -*/ - - if (fx) // after make current: fullscreen resize - { - XResizeWindow(display,window,screen->width,screen->height); - hints.min_width = hints.max_width = hints.base_width = screen->width; - hints.min_height= hints.max_height = hints.base_height = screen->height; - XSetWMNormalHints(display,window,&hints); - - // set the window layer for GNOME - { - XEvent xev; - - memset(&xev, 0, sizeof(xev)); - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = 1; - xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0); - xev.xclient.window = window; - xev.xclient.format = 32; - xev.xclient.data.l[0] = 1; - xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0); - xev.xclient.data.l[2] = 0; - xev.xclient.data.l[3] = 0; - xev.xclient.data.l[4] = 0; - - XSendEvent(display, RootWindow(display, DefaultScreen(display)), 0, - SubstructureRedirectMask | SubstructureNotifyMask, &xev); - } - } -} - -#endif // !defined(_MACGL) - -#ifndef _WINDOWS - -#if defined(_MACGL) -extern char * pCaptionText; -#endif - -//////////////////////////////////////////////////////////////////////// - -long GPUopen(unsigned long * disp,char * CapText,char * CfgFile) -{ - pCaptionText=CapText; - pConfigFile=CfgFile; - - ReadConfig(); // read text file for config - - SetFrameRateConfig(); // setup frame rate stuff - - bIsFirstFrame = TRUE; // we have to init later (well, no really... in Linux we do all in GPUopen) - - #if defined (_MACGL) - unsigned long display = ulInitDisplay(); - #else - sysdep_create_display(); // create display - #endif - - InitializeTextureStore(); // init texture mem - - rRatioRect.left = rRatioRect.top=0; - rRatioRect.right = iResX; - rRatioRect.bottom = iResY; - - GLinitialize(); // init opengl - - if(disp) - { - #if defined (_MACGL) - *disp = display; - #else - *disp=(unsigned long *)display; // return display ID to main emu - #endif - } - - if(display) return 0; - return -1; -} - -#endif // ndef _WINDOWS - - - -//////////////////////////////////////////////////////////////////////// -// close -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS - -long CALLBACK GPUclose() // WINDOWS CLOSE -{ - ExitKeyHandler(); - - GLcleanup(); // close OGL - - if(bChangeRes) // change res back - ChangeDisplaySettings(NULL,0); - - if(hPSEMenu) // set menu again - SetMenu(hWWindow,hPSEMenu); - - if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory - pGfxCardScreen=0; - - if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again - - return 0; -} - -#else - -long GPUclose() // LINUX CLOSE -{ - GLcleanup(); // close OGL - - if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory - pGfxCardScreen=0; - #if defined (_MACGL) - CloseDisplay(); - #else - osd_close_display(); // destroy display - #endif - return 0; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -// I shot the sheriff... last function called from emu -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUshutdown() -{ - if(psxVSecure) free(psxVSecure); // kill emulated vram memory - psxVSecure=0; - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// paint it black: simple func to clean up optical border garbage -//////////////////////////////////////////////////////////////////////// - -void PaintBlackBorders(void) -{ - short s; - - glDisable(GL_SCISSOR_TEST); - if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} - if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} - if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} - glDisable(GL_ALPHA_TEST); - - glBegin(GL_QUADS); - - vertex[0].c.lcol=0xff000000; - SETCOL(vertex[0]); - - if(PreviousPSXDisplay.Range.x0) - { - s=PreviousPSXDisplay.Range.x0+1; - glVertex3f(0,0,0.99996f); - glVertex3f(0,PSXDisplay.DisplayMode.y,0.99996f); - glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f); - glVertex3f(s,0,0.99996f); - - s+=PreviousPSXDisplay.Range.x1-2; - - glVertex3f(s,0,0.99996f); - glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f); - glVertex3f(PSXDisplay.DisplayMode.x,PSXDisplay.DisplayMode.y,0.99996f); - glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f); - } - - if(PreviousPSXDisplay.Range.y0) - { - s=PreviousPSXDisplay.Range.y0+1; - glVertex3f(0,0,0.99996f); - glVertex3f(0,s,0.99996f); - glVertex3f(PSXDisplay.DisplayMode.x,s,0.99996f); - glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f); - } - - glEnd(); - - glEnable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); -} - -//////////////////////////////////////////////////////////////////////// -// helper to draw scanlines -//////////////////////////////////////////////////////////////////////// - -__inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, - OGLVertex* vertex3, OGLVertex* vertex4) -{ - - glBegin(GL_QUAD_STRIP); - glTexCoord2fv(&vertex1->sow); - glVertex3fv(&vertex1->x); - - glTexCoord2fv(&vertex2->sow); - glVertex3fv(&vertex2->x); - - glTexCoord2fv(&vertex4->sow); - glVertex3fv(&vertex4->x); - - glTexCoord2fv(&vertex3->sow); - glVertex3fv(&vertex3->x); - glEnd(); -} - -//////////////////////////////////////////////////////////////////////// -// scanlines -//////////////////////////////////////////////////////////////////////// - -void SetScanLines(void) -{ - glLoadIdentity(); - glOrtho(0,iResX,iResY, 0, -1, 1); - - if(bKeepRatio) - glViewport(0,0,iResX,iResY); - - glDisable(GL_SCISSOR_TEST); - glDisable(GL_ALPHA_TEST); - if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} - - if(iScanBlend<0) // special texture mask scanline mode - { - if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} - gTexName=gTexScanName; - glBindTexture(GL_TEXTURE_2D, gTexName); - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - if(!bBlendEnable) {glEnable(GL_BLEND);bBlendEnable=TRUE;} - SetScanTexTrans(); - - vertex[0].x=0; - vertex[0].y=iResY; - vertex[0].z=0.99996f; - - vertex[1].x=iResX; - vertex[1].y=iResY; - vertex[1].z=0.99996f; - - vertex[2].x=iResX; - vertex[2].y=0; - vertex[2].z=0.99996f; - - vertex[3].x=0; - vertex[3].y=0; - vertex[3].z=0.99996f; - - vertex[0].sow=0; - vertex[0].tow=0; - vertex[1].sow=(float)iResX/4.0f; - vertex[1].tow=0; - vertex[2].sow=vertex[1].sow; - vertex[2].tow=(float)iResY/4.0f; - vertex[3].sow=0; - vertex[3].tow=vertex[2].tow; - - vertex[0].c.lcol=0xffffffff; - SETCOL(vertex[0]); - - XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); - } - else // typical line mode - { - if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} - - if(iScanBlend==0) - { - if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} - vertex[0].c.lcol=0xff000000; - } - else - { - if(!bBlendEnable) {glEnable(GL_BLEND);bBlendEnable=TRUE;} - SetScanTrans(); - vertex[0].c.lcol=iScanBlend<<24; - } - - SETCOL(vertex[0]); - - glCallList(uiScanLine); - } - - glLoadIdentity(); - glOrtho(0,PSXDisplay.DisplayMode.x, - PSXDisplay.DisplayMode.y, 0, -1, 1); - - if(bKeepRatio) - glViewport(rRatioRect.left, - iResY-(rRatioRect.top+rRatioRect.bottom), - rRatioRect.right, - rRatioRect.bottom); // init viewport - - glEnable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); -} - -//////////////////////////////////////////////////////////////////////// -// blur, babe, blur (heavy performance hit for a so-so fullscreen effect) -//////////////////////////////////////////////////////////////////////// - -void BlurBackBuffer(void) -{ - if(!gTexBlurName) return; - - if(bKeepRatio) glViewport(0,0,iResX,iResY); - - glDisable(GL_SCISSOR_TEST); - glDisable(GL_ALPHA_TEST); - if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} - if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} - if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} - if(iZBufferDepth) glDisable(GL_DEPTH_TEST); - if(bDrawDither) glDisable(GL_DITHER); - - gTexName=gTexBlurName; - glBindTexture(GL_TEXTURE_2D, gTexName); - - glCopyTexSubImage2D( GL_TEXTURE_2D, 0, // get back buffer in texture - 0, - 0, - 0, - 0, - iResX,iResY); - - vertex[0].x=0; - vertex[0].y=PSXDisplay.DisplayMode.y; - vertex[1].x=PSXDisplay.DisplayMode.x; - vertex[1].y=PSXDisplay.DisplayMode.y; - vertex[2].x=PSXDisplay.DisplayMode.x; - vertex[2].y=0; - vertex[3].x=0; - vertex[3].y=0; - vertex[0].sow=0; - vertex[0].tow=0; - -#ifdef OWNSCALE - vertex[1].sow=((GLfloat)iFTexA)/256.0f; - vertex[2].tow=((GLfloat)iFTexB)/256.0f; -#else - vertex[1].sow=iFTexA; - vertex[2].tow=iFTexB; -#endif - vertex[1].tow=0; - vertex[2].sow=vertex[1].sow; - vertex[3].sow=0; - vertex[3].tow=vertex[2].tow; - - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - vertex[0].c.lcol=0x7fffffff; - SETCOL(vertex[0]); - - DrawMultiBlur(); // draw the backbuffer texture to create blur effect - - glEnable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); - if(iZBufferDepth) glEnable(GL_DEPTH_TEST); - if(bDrawDither) glEnable(GL_DITHER); - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); - - if(bKeepRatio) - glViewport(rRatioRect.left, // re-init viewport - iResY-(rRatioRect.top+rRatioRect.bottom), - rRatioRect.right, - rRatioRect.bottom); -} - -//////////////////////////////////////////////////////////////////////// -// "unblur" repairs the backbuffer after a blur - -void UnBlurBackBuffer(void) -{ - if(!gTexBlurName) return; - - if(bKeepRatio) glViewport(0,0,iResX,iResY); - - glDisable(GL_SCISSOR_TEST); - glDisable(GL_ALPHA_TEST); - if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} - if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} - if(iZBufferDepth) glDisable(GL_DEPTH_TEST); - if(bDrawDither) glDisable(GL_DITHER); - - gTexName=gTexBlurName; - glBindTexture(GL_TEXTURE_2D, gTexName); - - vertex[0].x=0; - vertex[0].y=PSXDisplay.DisplayMode.y; - vertex[1].x=PSXDisplay.DisplayMode.x; - vertex[1].y=PSXDisplay.DisplayMode.y; - vertex[2].x=PSXDisplay.DisplayMode.x; - vertex[2].y=0; - vertex[3].x=0; - vertex[3].y=0; - vertex[0].sow=0; - vertex[0].tow=0; -#ifdef OWNSCALE - vertex[1].sow=((GLfloat)iFTexA)/256.0f; - vertex[2].tow=((GLfloat)iFTexB)/256.0f; -#else - vertex[1].sow=iFTexA; - vertex[2].tow=iFTexB; -#endif - vertex[1].tow=0; - vertex[2].sow=vertex[1].sow; - vertex[3].sow=0; - vertex[3].tow=vertex[2].tow; - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - vertex[0].c.lcol=0xffffffff; - SETCOL(vertex[0]); - - // simply draw the backbuffer texture (without blur) - XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); - - glEnable(GL_ALPHA_TEST); - glEnable(GL_SCISSOR_TEST); - if(iZBufferDepth) glEnable(GL_DEPTH_TEST); - if(bDrawDither) glEnable(GL_DITHER); // dither mode - if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); - - if(bKeepRatio) - glViewport(rRatioRect.left, - iResY-(rRatioRect.top+rRatioRect.bottom), - rRatioRect.right, - rRatioRect.bottom); // init viewport -} - -//////////////////////////////////////////////////////////////////////// -// Update display (swap buffers)... called in interlaced mode on -// every emulated vsync, otherwise whenever the displayed screen region -// has been changed -//////////////////////////////////////////////////////////////////////// - -int iLastRGB24=0; // special vars for checking when to skip two display updates -int iSkipTwo=0; - -void updateDisplay(void) // UPDATE DISPLAY -{ - BOOL bBlur=FALSE; - -#ifdef _WINDOWS - HDC hdc=GetDC(hWWindow); // windows: - wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again -#endif -#if defined (_MACGL) - BringContextForward(); -#endif - bFakeFrontBuffer=FALSE; - bRenderFrontBuffer=FALSE; - - if(iRenderFVR) // frame buffer read fix mode still active? - { - iRenderFVR--; // -> if some frames in a row without read access: turn off mode - if(!iRenderFVR) bFullVRam=FALSE; - } - - if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check - { - iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes - } - iLastRGB24=0; - - if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted? - { - PrepareFullScreenUpload(-1); - UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram - bNeedUploadTest=FALSE; - bNeedInterlaceUpdate=FALSE; - bNeedUploadAfter=FALSE; - bNeedRGB24Update=FALSE; - } - else - if(bNeedInterlaceUpdate) // smaller upload? - { - bNeedInterlaceUpdate=FALSE; - xrUploadArea=xrUploadAreaIL; // -> upload this rect - UploadScreen(TRUE); - } - - if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9 - - if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed - PreviousPSXDisplay.Range.y0) - PaintBlackBorders(); - - if(PSXDisplay.Disabled) // display disabled? - { - // moved here - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,128); // -> clear whole backbuffer - glClear(uiBufferBits); - glEnable(GL_SCISSOR_TEST); - gl_z=0.0f; - bDisplayNotSet = TRUE; - } - - if(iSkipTwo) // we are in skipping mood? - { - iSkipTwo--; - iDrawnSomething=0; // -> simply lie about something drawn - } - - if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated? - {BlurBackBuffer();bBlur=TRUE;} // -> blur it - - if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it - - if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em - - if(dwActFixes&128) // special FPS limitation mode? - { - if(bUseFrameLimit) PCFrameCap(); // -> ok, do it - if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS) - PCcalcfps(); - } - - if(gTexPicName) DisplayPic(); // some gpu info picture active? display it - - if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :) - - if(ulKeybits&KEY_SHOWFPS) // wanna see FPS? - { - sprintf(szDispBuf,"%06.1f",fps_cur); - DisplayText(); // -> show it - } - - //----------------------------------------------------// - // main buffer swapping (well, or skip it) - - if(bUseFrameSkip) // frame skipping active ? - { - if(!bSkipNextFrame) - { - if(iDrawnSomething) -#ifdef _WINDOWS - SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip -#elif defined(_MACGL) - DoBufferSwap(); -#else - glXSwapBuffers(display,window); -#endif - } - if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row - { - if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) - {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} - else bSkipNextFrame = FALSE; - } - else FrameSkip(); - } - else // no skip ? - { - if(iDrawnSomething) -#ifdef _WINDOWS - SwapBuffers(wglGetCurrentDC()); // -> swap -#elif defined(_MACGL) - DoBufferSwap(); -#else - glXSwapBuffers(display,window); -#endif - } - - iDrawnSomething=0; - - //----------------------------------------------------// - - if(lClearOnSwap) // clear buffer after swap? - { - GLclampf g,b,r; - - if(bDisplayNotSet) // -> set new vals - SetOGLDisplaySettings(1); - - g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col - b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f; - r=((GLclampf)RED(lClearOnSwapColor))/255.0f; - - glDisable(GL_SCISSOR_TEST); - glClearColor(r,g,b,128); // -> clear - glClear(uiBufferBits); - glEnable(GL_SCISSOR_TEST); - lClearOnSwap=0; // -> done - } - else - { - if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before - - if(iZBufferDepth) // clear zbuffer as well (if activated) - { - glDisable(GL_SCISSOR_TEST); - glClear(GL_DEPTH_BUFFER_BIT); - glEnable(GL_SCISSOR_TEST); - } - } - gl_z=0.0f; - - //----------------------------------------------------// - // additional uploads immediatly after swapping - - if(bNeedUploadAfter) // upload wanted? - { - bNeedUploadAfter=FALSE; - bNeedUploadTest=FALSE; - UploadScreen(-1); // -> upload - } - - if(bNeedUploadTest) - { - bNeedUploadTest=FALSE; - if(PSXDisplay.InterlacedTest && - //iOffscreenDrawing>2 && - PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && - PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && - PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && - PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) - { - PrepareFullScreenUpload(TRUE); - UploadScreen(TRUE); - } - } - - //----------------------------------------------------// - // rumbling (main emu pad effect) - - if(iRumbleTime) // shake screen by modifying view port - { - int i1=0,i2=0,i3=0,i4=0; - - iRumbleTime--; - if(iRumbleTime) - { - i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); - i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); - i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); - i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); - } - - glViewport(rRatioRect.left+i1, - iResY-(rRatioRect.top+rRatioRect.bottom)+i2, - rRatioRect.right+i3, - rRatioRect.bottom+i4); - } - -#ifdef _WINDOWS - ReleaseDC(hWWindow,hdc); // ! important ! -#endif - - if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled -} - -//////////////////////////////////////////////////////////////////////// -// update front display: smaller update func, if something has changed -// in the frontbuffer... dirty, but hey... real men know no pain -//////////////////////////////////////////////////////////////////////// - -void updateFrontDisplay(void) -{ - if(PreviousPSXDisplay.Range.x0|| - PreviousPSXDisplay.Range.y0) - PaintBlackBorders(); - - if(iBlurBuffer) BlurBackBuffer(); - - if(iUseScanLines) SetScanLines(); - - if(usCursorActive) ShowGunCursor(); - - bFakeFrontBuffer=FALSE; - bRenderFrontBuffer=FALSE; - - if(gTexPicName) DisplayPic(); - if(ulKeybits&KEY_SHOWFPS) DisplayText(); - -#ifdef _WINDOWS - { // windows: - HDC hdc=GetDC(hWWindow); - wglMakeCurrent(hdc,GLCONTEXT); // -> make current again - if(iDrawnSomething) - SwapBuffers(wglGetCurrentDC()); // -> swap - ReleaseDC(hWWindow,hdc); // -> ! important ! - } -#elif defined (_MACGL) -if (iDrawnSomething){ - DoBufferSwap(); - } -#else - if(iDrawnSomething) // linux: - glXSwapBuffers(display,window); -#endif - - if(iBlurBuffer) UnBlurBackBuffer(); -} - -//////////////////////////////////////////////////////////////////////// -// check if update needed -//////////////////////////////////////////////////////////////////////// - -void ChangeDispOffsetsX(void) // CENTER X -{ - int lx,l;short sO; - - if(!PSXDisplay.Range.x1) return; // some range given? - - l=PSXDisplay.DisplayMode.x; - - l*=(int)PSXDisplay.Range.x1; // some funky calculation - l/=2560;lx=l;l&=0xfffffff8; - - if(l==PreviousPSXDisplay.Range.x1) return; // some change? - - sO=PreviousPSXDisplay.Range.x0; // store old - - if(lx>=PSXDisplay.DisplayMode.x) // range bigger? - { - PreviousPSXDisplay.Range.x1= // -> take display width - PSXDisplay.DisplayMode.x; - PreviousPSXDisplay.Range.x0=0; // -> start pos is 0 - } - else // range smaller? center it - { - PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned) - PreviousPSXDisplay.Range.x0= // -> calc start pos - (PSXDisplay.Range.x0-500)/8; - if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet - PreviousPSXDisplay.Range.x0=0; - - if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much - PSXDisplay.DisplayMode.x) - { - PreviousPSXDisplay.Range.x0= // -> adjust start - PSXDisplay.DisplayMode.x-lx; - PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width - } - } - - if(sO!=PreviousPSXDisplay.Range.x0) // something changed? - { - bDisplayNotSet=TRUE; // -> recalc display stuff - } -} - -//////////////////////////////////////////////////////////////////////// - -void ChangeDispOffsetsY(void) // CENTER Y -{ - int iT;short sO; // store previous y size - - if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC - - if(PSXDisplay.Range.y0>=iT) // crossed the security line? :) - { - PreviousPSXDisplay.Range.y1= // -> store width - PSXDisplay.DisplayModeNew.y; - - sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset - if(sO<0) sO=0; - - PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too - } - else sO=0; // else no offset - - if(sO!=PreviousPSXDisplay.Range.y0) // something changed? - { - PreviousPSXDisplay.Range.y0=sO; - bDisplayNotSet=TRUE; // -> recalc display stuff - } -} - -//////////////////////////////////////////////////////////////////////// -// Aspect ratio of ogl screen: simply adjusting ogl view port -//////////////////////////////////////////////////////////////////////// - -void SetAspectRatio(void) -{ - float xs,ys,s;RECT r; - - if(!PSXDisplay.DisplayModeNew.x) return; - if(!PSXDisplay.DisplayModeNew.y) return; - - xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x; - ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y; - - s=min(xs,ys); - r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s); - r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s); - if(r.right > iResX) r.right = iResX; - if(r.bottom > iResY) r.bottom = iResY; - if(r.right < 1) r.right = 1; - if(r.bottom < 1) r.bottom = 1; - - r.left = (iResX-r.right)/2; - r.top = (iResY-r.bottom)/2; - - if(r.bottom new psx resolution - PSXDisplay.DisplayModeNew.y, 0, -1, 1); - if(bKeepRatio) SetAspectRatio(); - } - - bDisplayNotSet = TRUE; // re-calc offsets/display area - - bUp=FALSE; - if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off) - { - PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet - ResetTextureArea(FALSE); - bUp=TRUE; - } - - PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos - PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; - PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; - PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; - - PSXDisplay.DisplayEnd.x= // calc new ends - PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PSXDisplay.DisplayEnd.y= - PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - PreviousPSXDisplay.DisplayEnd.x= - PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PreviousPSXDisplay.DisplayEnd.y= - PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - - ChangeDispOffsetsX(); - - if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace) - - if(bUp) updateDisplay(); // yeah, real update (swap buffer) -} - -//////////////////////////////////////////////////////////////////////// -// window mode <-> fullscreen mode (windows) -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS -void ChangeWindowMode(void) - { - GPUclose(); - bWindowMode=!bWindowMode; - GPUopen(hWWindow); - bChangeWinMode=FALSE; - } -#endif - -//////////////////////////////////////////////////////////////////////// -// swap update check (called by psx vsync function) -//////////////////////////////////////////////////////////////////////// - -BOOL bSwapCheck(void) -{ - static int iPosCheck=0; - static PSXPoint_t pO; - static PSXPoint_t pD; - static int iDoAgain=0; - - if(PSXDisplay.DisplayPosition.x==pO.x && - PSXDisplay.DisplayPosition.y==pO.y && - PSXDisplay.DisplayEnd.x==pD.x && - PSXDisplay.DisplayEnd.y==pD.y) - iPosCheck++; - else iPosCheck=0; - - pO=PSXDisplay.DisplayPosition; - pD=PSXDisplay.DisplayEnd; - - if(iPosCheck<=4) return FALSE; - - iPosCheck=4; - - if(PSXDisplay.Interlaced) return FALSE; - - if (bNeedInterlaceUpdate|| - bNeedRGB24Update || - bNeedUploadAfter|| - bNeedUploadTest || - iDoAgain - ) - { - iDoAgain=0; - if(bNeedUploadAfter) - iDoAgain=1; - if(bNeedUploadTest && PSXDisplay.InterlacedTest) - iDoAgain=1; - - bDisplayNotSet = TRUE; - updateDisplay(); - - PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x; - PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y; - PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x; - PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y; - pO=PSXDisplay.DisplayPosition; - pD=PSXDisplay.DisplayEnd; - - return TRUE; - } - - return FALSE; -} - -//////////////////////////////////////////////////////////////////////// -// gun cursor func: player=0-7, x=0-511, y=0-255 -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUcursor(int iPlayer,int x,int y) -{ - if(iPlayer<0) return; - if(iPlayer>7) return; - - usCursorActive|=(1<iGPUHeightMask) x=iGPUHeightMask; - if(y<0) y=0; - if(y>255) y=255; - - ptCursorPoint[iPlayer].x=x; - ptCursorPoint[iPlayer].y=y; -} - -//////////////////////////////////////////////////////////////////////// -// update lace is called every VSync. Basically we limit frame rate -// here, and in interlaced mode we swap ogl display buffers. -//////////////////////////////////////////////////////////////////////// - -static unsigned short usFirstPos=2; - -void CALLBACK GPUupdateLace(void) -{ - //if(!(dwActFixes&0x1000)) - // STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus) - - if(!(dwActFixes&128)) // normal frame limit func - CheckFrameRate(); - - if(iOffscreenDrawing==4) // special check if high offscreen drawing is on - { - if(bSwapCheck()) return; - } - - if(PSXDisplay.Interlaced) // interlaced mode? - { - STATUSREG^=0x80000000; - if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) - { - updateDisplay(); // -> swap buffers (new frame) - } - } - else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed? - { - updateFrontDisplay(); // -> update front buffer - } - else if(usFirstPos==1) // initial updates (after startup) - { - updateDisplay(); - } - -#if defined(_WINDOWS) || defined(_MACGL) - if(bChangeWinMode) ChangeWindowMode(); -#endif -} - -//////////////////////////////////////////////////////////////////////// -// process read request from GPU status register -//////////////////////////////////////////////////////////////////////// - -uint32_t CALLBACK GPUreadStatus(void) -{ - if(dwActFixes&0x1000) // CC game fix - { - static int iNumRead=0; - if((iNumRead++)==2) - { - iNumRead=0; - STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross) - } - } - - 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... - { - iFakePrimBusy--; - - if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims - { - GPUIsBusy; - GPUIsNotReadyForCommands; - } - else - { - GPUIsIdle; - GPUIsReadyForCommands; - } - } - - return STATUSREG | (vBlank ? 0x80000000 : 0 );; -} - -//////////////////////////////////////////////////////////////////////// -// processes data send to GPU status register -// these are always single packet commands. -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUwriteStatus(uint32_t gdata) -{ - uint32_t lCommand=(gdata>>24)&0xff; - -#ifdef _WINDOWS - if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus) -#endif - - ulStatusControl[lCommand]=gdata; - - switch(lCommand) - { - //--------------------------------------------------// - // reset gpu - case 0x00: - memset(ulGPUInfoVals, 0x00, 16 * sizeof(uint32_t)); - lGPUstatusRet = 0x14802000; - PSXDisplay.Disabled=1; - iDataWriteMode=iDataReadMode=DR_NORMAL; - PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; - drawX=drawY=0;drawW=drawH=0; - sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0; - usMirror=0; - GlobalTextAddrX=0;GlobalTextAddrY=0; - GlobalTextTP=0;GlobalTextABR=0; - PSXDisplay.RGB24=FALSE; - PSXDisplay.Interlaced=FALSE; - bUsingTWin = FALSE; - return; - - // dis/enable display - case 0x03: - PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; - PSXDisplay.Disabled = (gdata & 1); - - if(PSXDisplay.Disabled) - STATUSREG|=GPUSTATUS_DISPLAYDISABLED; - else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED; - - if (iOffscreenDrawing==4 && - PreviousPSXDisplay.Disabled && - !(PSXDisplay.Disabled)) - { - - if(!PSXDisplay.RGB24) - { - PrepareFullScreenUpload(TRUE); - UploadScreen(TRUE); - updateDisplay(); - } - } - - return; - - // setting transfer mode - case 0x04: - gdata &= 0x03; // only want the lower two bits - - iDataWriteMode=iDataReadMode=DR_NORMAL; - if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER; - if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER; - - STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits - STATUSREG|=(gdata << 29); // set the DMA bits according to the received data - - return; - - // setting display position - case 0x05: - { - short sx=(short)(gdata & 0x3ff); - short sy; - - if(iGPUHeight==1024) - { - if(dwGPUVersion==2) - sy = (short)((gdata>>12)&0x3ff); - else sy = (short)((gdata>>10)&0x3ff); - } - else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later - - if (sy & 0x200) - { - sy|=0xfc00; - PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double; - sy=0; - } - else PreviousPSXDisplay.DisplayModeNew.y=0; - - if(sx>1000) sx=0; - - if(usFirstPos) - { - usFirstPos--; - if(usFirstPos) - { - PreviousPSXDisplay.DisplayPosition.x = sx; - PreviousPSXDisplay.DisplayPosition.y = sy; - PSXDisplay.DisplayPosition.x = sx; - PSXDisplay.DisplayPosition.y = sy; - } - } - - if(dwActFixes&8) - { - if((!PSXDisplay.Interlaced) && - PreviousPSXDisplay.DisplayPosition.x == sx && - PreviousPSXDisplay.DisplayPosition.y == sy) - return; - - PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x; - PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y; - PreviousPSXDisplay.DisplayPosition.x = sx; - PreviousPSXDisplay.DisplayPosition.y = sy; - } - else - { - if((!PSXDisplay.Interlaced) && - PSXDisplay.DisplayPosition.x == sx && - PSXDisplay.DisplayPosition.y == sy) - return; - PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; - PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; - PSXDisplay.DisplayPosition.x = sx; - PSXDisplay.DisplayPosition.y = sy; - } - - PSXDisplay.DisplayEnd.x= - PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PSXDisplay.DisplayEnd.y= - PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - - PreviousPSXDisplay.DisplayEnd.x= - PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; - PreviousPSXDisplay.DisplayEnd.y= - PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; - - bDisplayNotSet = TRUE; - - if (!(PSXDisplay.Interlaced)) - { - updateDisplay(); - } - else - if(PSXDisplay.InterlacedTest && - ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)|| - (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y))) - PSXDisplay.InterlacedTest--; - - return; - } - - // setting width - case 0x06: - - PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff; - PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff; - - PSXDisplay.Range.x1-=PSXDisplay.Range.x0; - - ChangeDispOffsetsX(); - - return; - - // setting height - case 0x07: - - PreviousPSXDisplay.Height = PSXDisplay.Height; - - PSXDisplay.Range.y0=gdata & 0x3ff; - PSXDisplay.Range.y1=(gdata>>10) & 0x3ff; - - PSXDisplay.Height = PSXDisplay.Range.y1 - - PSXDisplay.Range.y0 + - PreviousPSXDisplay.DisplayModeNew.y; - - if (PreviousPSXDisplay.Height != PSXDisplay.Height) - { - PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; - ChangeDispOffsetsY(); - updateDisplayIfChanged(); - } - return; - - // setting display infos - case 0x08: - - PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; - - if (gdata&0x04) PSXDisplay.Double=2; - else PSXDisplay.Double=1; - PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; - - ChangeDispOffsetsY(); - - PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC - PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor - PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace - - STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits - - STATUSREG|= - (((gdata & 0x03) << 17) | - ((gdata & 0x40) << 10)); // set the width bits - - PreviousPSXDisplay.InterlacedNew=FALSE; - if (PSXDisplay.InterlacedNew) - { - if(!PSXDisplay.Interlaced) - { - PSXDisplay.InterlacedTest=2; - PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; - PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; - PreviousPSXDisplay.InterlacedNew=TRUE; - } - - STATUSREG|=GPUSTATUS_INTERLACED; - } - else - { - PSXDisplay.InterlacedTest=0; - STATUSREG&=~GPUSTATUS_INTERLACED; - } - - if (PSXDisplay.PAL) - STATUSREG|=GPUSTATUS_PAL; - else STATUSREG&=~GPUSTATUS_PAL; - - if (PSXDisplay.Double==2) - STATUSREG|=GPUSTATUS_DOUBLEHEIGHT; - else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT; - - if (PSXDisplay.RGB24New) - STATUSREG|=GPUSTATUS_RGB24; - else STATUSREG&=~GPUSTATUS_RGB24; - - updateDisplayIfChanged(); - - return; - - //--------------------------------------------------// - // ask about GPU version and other stuff - case 0x10: - - gdata&=0xff; - - switch(gdata) - { - case 0x02: - GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos - return; - case 0x03: - GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start - return; - case 0x04: - GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end - return; - case 0x05: - case 0x06: - GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset - return; - case 0x07: - if(dwGPUVersion==2) - GPUdataRet=0x01; - else GPUdataRet=0x02; // gpu type - return; - case 0x08: - case 0x0F: // some bios addr? - GPUdataRet=0xBFC03720; - return; - } - return; - //--------------------------------------------------// - } -} - -//////////////////////////////////////////////////////////////////////// -// vram read/write helpers -//////////////////////////////////////////////////////////////////////// - -BOOL bNeedWriteUpload=FALSE; - -__inline void FinishedVRAMWrite(void) -{ - if(bNeedWriteUpload) - { - bNeedWriteUpload=FALSE; - CheckWriteUpdate(); - } - - // set register to NORMAL operation - iDataWriteMode = DR_NORMAL; - - // reset transfer values, to prevent mis-transfer of data - VRAMWrite.ColsRemaining = 0; - VRAMWrite.RowsRemaining = 0; -} - -__inline void FinishedVRAMRead(void) -{ - // set register to NORMAL operation - iDataReadMode = DR_NORMAL; - // reset transfer values, to prevent mis-transfer of data - VRAMRead.x = 0; - VRAMRead.y = 0; - VRAMRead.Width = 0; - VRAMRead.Height = 0; - VRAMRead.ColsRemaining = 0; - VRAMRead.RowsRemaining = 0; - - // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER - STATUSREG&=~GPUSTATUS_READYFORVRAM; -} - -//////////////////////////////////////////////////////////////////////// -// vram read check ex (reading from card's back/frontbuffer if needed... -// slow!) -//////////////////////////////////////////////////////////////////////// - -void CheckVRamReadEx(int x, int y, int dx, int dy) -{ - unsigned short sArea; - int ux,uy,udx,udy,wx,wy; - unsigned short * p1, *p2; - float XS,YS; - unsigned char * ps; - unsigned char * px; - unsigned short s,sx; - - if(STATUSREG&GPUSTATUS_RGB24) return; - - if(((dx > PSXDisplay.DisplayPosition.x) && - (x < PSXDisplay.DisplayEnd.x) && - (dy > PSXDisplay.DisplayPosition.y) && - (y < PSXDisplay.DisplayEnd.y))) - sArea=0; - else - if((!(PSXDisplay.InterlacedTest) && - (dx > PreviousPSXDisplay.DisplayPosition.x) && - (x < PreviousPSXDisplay.DisplayEnd.x) && - (dy > PreviousPSXDisplay.DisplayPosition.y) && - (y < PreviousPSXDisplay.DisplayEnd.y))) - sArea=1; - else - { - return; - } - - ////////////// - - if(iRenderFVR) - { - bFullVRam=TRUE;iRenderFVR=2;return; - } - bFullVRam=TRUE;iRenderFVR=2; - - ////////////// - - p2=0; - - if(sArea==0) - { - ux=PSXDisplay.DisplayPosition.x; - uy=PSXDisplay.DisplayPosition.y; - udx=PSXDisplay.DisplayEnd.x-ux; - udy=PSXDisplay.DisplayEnd.y-uy; - if((PreviousPSXDisplay.DisplayEnd.x- - PreviousPSXDisplay.DisplayPosition.x)==udx && - (PreviousPSXDisplay.DisplayEnd.y- - PreviousPSXDisplay.DisplayPosition.y)==udy) - p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) + - PreviousPSXDisplay.DisplayPosition.x); - } - else - { - ux=PreviousPSXDisplay.DisplayPosition.x; - uy=PreviousPSXDisplay.DisplayPosition.y; - udx=PreviousPSXDisplay.DisplayEnd.x-ux; - udy=PreviousPSXDisplay.DisplayEnd.y-uy; - if((PSXDisplay.DisplayEnd.x- - PSXDisplay.DisplayPosition.x)==udx && - (PSXDisplay.DisplayEnd.y- - PSXDisplay.DisplayPosition.y)==udy) - p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) + - PSXDisplay.DisplayPosition.x); - } - - p1=(psxVuw + (1024*uy) + ux); - if(p1==p2) p2=0; - - x=0;y=0; - wx=dx=udx;wy=dy=udy; - - if(udx<=0) return; - if(udy<=0) return; - if(dx<=0) return; - if(dy<=0) return; - if(wx<=0) return; - if(wy<=0) return; - - XS=(float)rRatioRect.right/(float)wx; - YS=(float)rRatioRect.bottom/(float)wy; - - dx=(int)((float)(dx)*XS); - dy=(int)((float)(dy)*YS); - - if(dx>iResX) dx=iResX; - if(dy>iResY) dy=iResY; - - if(dx<=0) return; - if(dy<=0) return; - - // ogl y adjust - y=iResY-y-dy; - - x+=rRatioRect.left; - y-=rRatioRect.top; - - if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; - - if(!pGfxCardScreen) - { - glPixelStorei(GL_PACK_ALIGNMENT,1); - pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); - } - - ps=pGfxCardScreen; - - if(!sArea) glReadBuffer(GL_FRONT); - - glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); - - if(!sArea) glReadBuffer(GL_BACK); - - s=0; - - XS=(float)dx/(float)(udx); - YS=(float)dy/(float)(udy+1); - - for(y=udy;y>0;y--) - { - for(x=0;x=psxVuw && p1>3;px++; - s=sx; - sx=(*px)>>3;px++; - s|=sx<<5; - sx=(*px)>>3; - s|=sx<<10; - s&=~0x8000; - *p1=s; - } - if(p2>=psxVuw && p2 PSXDisplay.DisplayPosition.x) && - (x < PSXDisplay.DisplayEnd.x) && - (dy > PSXDisplay.DisplayPosition.y) && - (y < PSXDisplay.DisplayEnd.y))) - sArea=0; - else - if((!(PSXDisplay.InterlacedTest) && - (dx > PreviousPSXDisplay.DisplayPosition.x) && - (x < PreviousPSXDisplay.DisplayEnd.x) && - (dy > PreviousPSXDisplay.DisplayPosition.y) && - (y < PreviousPSXDisplay.DisplayEnd.y))) - sArea=1; - else - { - return; - } - - if(dwActFixes&0x40) - { - if(iRenderFVR) - { - bFullVRam=TRUE;iRenderFVR=2;return; - } - bFullVRam=TRUE;iRenderFVR=2; - } - - ux=x;uy=y;udx=dx;udy=dy; - - if(sArea==0) - { - x -=PSXDisplay.DisplayPosition.x; - dx-=PSXDisplay.DisplayPosition.x; - y -=PSXDisplay.DisplayPosition.y; - dy-=PSXDisplay.DisplayPosition.y; - wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x; - wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y; - } - else - { - x -=PreviousPSXDisplay.DisplayPosition.x; - dx-=PreviousPSXDisplay.DisplayPosition.x; - y -=PreviousPSXDisplay.DisplayPosition.y; - dy-=PreviousPSXDisplay.DisplayPosition.y; - wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x; - wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y; - } - if(x<0) {ux-=x;x=0;} - if(y<0) {uy-=y;y=0;} - if(dx>wx) {udx-=(dx-wx);dx=wx;} - if(dy>wy) {udy-=(dy-wy);dy=wy;} - udx-=ux; - udy-=uy; - - p=(psxVuw + (1024*uy) + ux); - - if(udx<=0) return; - if(udy<=0) return; - if(dx<=0) return; - if(dy<=0) return; - if(wx<=0) return; - if(wy<=0) return; - - XS=(float)rRatioRect.right/(float)wx; - YS=(float)rRatioRect.bottom/(float)wy; - - dx=(int)((float)(dx)*XS); - dy=(int)((float)(dy)*YS); - x=(int)((float)x*XS); - y=(int)((float)y*YS); - - dx-=x; - dy-=y; - - if(dx>iResX) dx=iResX; - if(dy>iResY) dy=iResY; - - if(dx<=0) return; - if(dy<=0) return; - - // ogl y adjust - y=iResY-y-dy; - - x+=rRatioRect.left; - y-=rRatioRect.top; - - if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; - - if(!pGfxCardScreen) - { - glPixelStorei(GL_PACK_ALIGNMENT,1); - pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); - } - - ps=pGfxCardScreen; - - if(bFront) glReadBuffer(GL_FRONT); - - glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); - - if(bFront) glReadBuffer(GL_BACK); - - XS=(float)dx/(float)(udx); - YS=(float)dy/(float)(udy+1); - - for(y=udy;y>0;y--) - { - for(x=0;x=psxVuw && p>3;px++; - s=sx; - sx=(*px)>>3;px++; - s|=sx<<5; - sx=(*px)>>3; - s|=sx<<10; - s&=~0x8000; - *p=s; - } - p++; - } - p += 1024 - udx; - } -} - -//////////////////////////////////////////////////////////////////////// -// core read from vram -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUreadDataMem(uint32_t *pMem, int iSize) -{ - int i; - - if(iDataReadMode!=DR_VRAMTRANSFER) return; - - GPUIsBusy; - - // adjust read ptr, if necessary - while(VRAMRead.ImagePtr>=psxVuw_eom) - VRAMRead.ImagePtr-=iGPUHeight*1024; - while(VRAMRead.ImagePtr1) && - !(iDrawnSomething==2 && - VRAMRead.x == VRAMWrite.x && - VRAMRead.y == VRAMWrite.y && - VRAMRead.Width == VRAMWrite.Width && - VRAMRead.Height == VRAMWrite.Height)) - CheckVRamRead(VRAMRead.x,VRAMRead.y, - VRAMRead.x+VRAMRead.RowsRemaining, - VRAMRead.y+VRAMRead.ColsRemaining, - TRUE); - - for(i=0;i 0) && (VRAMRead.RowsRemaining > 0)) - { - // lower 16 bit - GPUdataRet=(uint32_t)*VRAMRead.ImagePtr; - - VRAMRead.ImagePtr++; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - VRAMRead.RowsRemaining --; - - if(VRAMRead.RowsRemaining<=0) - { - VRAMRead.RowsRemaining = VRAMRead.Width; - VRAMRead.ColsRemaining--; - VRAMRead.ImagePtr += 1024 - VRAMRead.Width; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - } - - // higher 16 bit (always, even if it's an odd width) - GPUdataRet|=(uint32_t)(*VRAMRead.ImagePtr)<<16; - *pMem++=GPUdataRet; - - if(VRAMRead.ColsRemaining <= 0) - {FinishedVRAMRead();goto ENDREAD;} - - VRAMRead.ImagePtr++; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - VRAMRead.RowsRemaining--; - if(VRAMRead.RowsRemaining<=0) - { - VRAMRead.RowsRemaining = VRAMRead.Width; - VRAMRead.ColsRemaining--; - VRAMRead.ImagePtr += 1024 - VRAMRead.Width; - if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; - } - if(VRAMRead.ColsRemaining <= 0) - {FinishedVRAMRead();goto ENDREAD;} - } - else {FinishedVRAMRead();goto ENDREAD;} - } - -ENDREAD: - GPUIsIdle; -} - -uint32_t CALLBACK GPUreadData(void) -{ - uint32_t l; - GPUreadDataMem(&l,1); - return GPUdataRet; -} - -//////////////////////////////////////////////////////////////////////// -// helper table to know how much data is used by drawing commands -//////////////////////////////////////////////////////////////////////// - -const unsigned char primTableCX[256] = -{ - // 00 - 0,0,3,0,0,0,0,0, - // 08 - 0,0,0,0,0,0,0,0, - // 10 - 0,0,0,0,0,0,0,0, - // 18 - 0,0,0,0,0,0,0,0, - // 20 - 4,4,4,4,7,7,7,7, - // 28 - 5,5,5,5,9,9,9,9, - // 30 - 6,6,6,6,9,9,9,9, - // 38 - 8,8,8,8,12,12,12,12, - // 40 - 3,3,3,3,0,0,0,0, - // 48 -// 5,5,5,5,6,6,6,6, //FLINE - 254,254,254,254,254,254,254,254, - // 50 - 4,4,4,4,0,0,0,0, - // 58 -// 7,7,7,7,9,9,9,9, // LINEG3 LINEG4 - 255,255,255,255,255,255,255,255, - // 60 - 3,3,3,3,4,4,4,4, // TILE SPRT - // 68 - 2,2,2,2,3,3,3,3, // TILE1 - // 70 - 2,2,2,2,3,3,3,3, - // 78 - 2,2,2,2,3,3,3,3, - // 80 - 4,0,0,0,0,0,0,0, - // 88 - 0,0,0,0,0,0,0,0, - // 90 - 0,0,0,0,0,0,0,0, - // 98 - 0,0,0,0,0,0,0,0, - // a0 - 3,0,0,0,0,0,0,0, - // a8 - 0,0,0,0,0,0,0,0, - // b0 - 0,0,0,0,0,0,0,0, - // b8 - 0,0,0,0,0,0,0,0, - // c0 - 3,0,0,0,0,0,0,0, - // c8 - 0,0,0,0,0,0,0,0, - // d0 - 0,0,0,0,0,0,0,0, - // d8 - 0,0,0,0,0,0,0,0, - // e0 - 0,1,1,1,1,1,1,0, - // e8 - 0,0,0,0,0,0,0,0, - // f0 - 0,0,0,0,0,0,0,0, - // f8 - 0,0,0,0,0,0,0,0 -}; - -//////////////////////////////////////////////////////////////////////// -// processes data send to GPU data register -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUwriteDataMem(uint32_t *pMem, int iSize) -{ - unsigned char command; - uint32_t gdata=0; - int i=0; - GPUIsBusy; - GPUIsNotReadyForCommands; - -STARTVRAM: - - if(iDataWriteMode==DR_VRAMTRANSFER) - { - // make sure we are in vram - while(VRAMWrite.ImagePtr>=psxVuw_eom) - VRAMWrite.ImagePtr-=iGPUHeight*1024; - while(VRAMWrite.ImagePtr0) - { - while(VRAMWrite.RowsRemaining>0) - { - if(i>=iSize) {goto ENDVRAM;} - i++; - - gdata=*pMem++; - - *VRAMWrite.ImagePtr++ = (unsigned short)gdata; - if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; - VRAMWrite.RowsRemaining --; - - if(VRAMWrite.RowsRemaining <= 0) - { - VRAMWrite.ColsRemaining--; - if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width - { - gdata=(gdata&0xFFFF)|(((uint32_t)(*VRAMWrite.ImagePtr))<<16); - FinishedVRAMWrite(); - goto ENDVRAM; - } - VRAMWrite.RowsRemaining = VRAMWrite.Width; - VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; - } - - *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16); - if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; - VRAMWrite.RowsRemaining --; - } - - VRAMWrite.RowsRemaining = VRAMWrite.Width; - VRAMWrite.ColsRemaining--; - VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; - } - - FinishedVRAMWrite(); - } - -ENDVRAM: - - if(iDataWriteMode==DR_NORMAL) - { - void (* *primFunc)(unsigned char *); - if(bSkipNextFrame) primFunc=primTableSkip; - else primFunc=primTableJ; - - for(;i>24) & 0xff); - - if(primTableCX[command]) - { - gpuDataC = primTableCX[command]; - gpuCommand = command; - gpuDataM[0] = gdata; - gpuDataP = 1; - } - else continue; - } - else - { - gpuDataM[gpuDataP] = gdata; - if(gpuDataC>128) - { - if((gpuDataC==254 && gpuDataP>=3) || - (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1))) - { - if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000) - gpuDataP=gpuDataC-1; - } - } - gpuDataP++; - } - - if(gpuDataP == gpuDataC) - { - gpuDataC=gpuDataP=0; - primFunc[gpuCommand]((unsigned char *)gpuDataM); - - if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games - iFakePrimBusy=4; - } - } - } - - GPUdataRet=gdata; - - GPUIsReadyForCommands; - GPUIsIdle; -} - -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUwriteData(uint32_t gdata) -{ - GPUwriteDataMem(&gdata,1); -} - -//////////////////////////////////////////////////////////////////////// -// call config dlg -//////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS - -long CALLBACK GPUconfigure(void) -{ - HWND hWP=GetActiveWindow(); - DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), - hWP,(DLGPROC)CfgDlgProc); - - return 0; -} - -#elif defined(_MACGL) -long CALLBACK GPUconfigure(void) -{ - DlgProc(); - return 0; -} -#else - -void StartCfgTool(char *arg) // linux: start external cfg tool -{ - char cfg[256]; - struct stat buf; - - strcpy(cfg, "./cfgpeopsxgl"); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgpeopsxgl", arg, NULL); - exit(0); - } - return; - } - - strcpy(cfg, "./cfg/cfgpeopsxgl"); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgpeopsxgl", arg, NULL); - exit(0); - } - return; - } - - sprintf(cfg, "%s/.pcsx/plugins/cfg/cfgpeopsxgl", getenv("HOME")); - if (stat(cfg, &buf) != -1) { - if (fork() == 0) { - execl(cfg, "cfgpeopsxgl", arg, NULL); - exit(0); - } - return; - } - - printf("ERROR: cfgpeopsxgl file not found!\n"); -} - -long CALLBACK GPUconfigure(void) -{ - StartCfgTool("CFG"); - return 0; -} - -#endif // def _WINDOWS / _MACGL - -//////////////////////////////////////////////////////////////////////// -// sets all kind of act fixes -//////////////////////////////////////////////////////////////////////// - -void SetFixes(void) -{ - ReInitFrameCap(); - - if(dwActFixes & 0x2000) - dispWidths[4]=384; - else dispWidths[4]=368; -} - -//////////////////////////////////////////////////////////////////////// -// Pete Special: make an 'intelligent' dma chain check (<-Tekken3) -//////////////////////////////////////////////////////////////////////// - -uint32_t lUsedAddr[3]; - -__inline BOOL CheckForEndlessLoop(uint32_t laddr) -{ - if(laddr==lUsedAddr[1]) return TRUE; - if(laddr==lUsedAddr[2]) return TRUE; - - if(laddr 2000000) break; - if(CheckForEndlessLoop(addr)) break; - - count = baseAddrB[addr+3]; - - dmaMem=addr+4; - - if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); - - addr = baseAddrL[addr>>2]&0xffffff; - } - while (addr != 0xffffff); - - GPUIsIdle; - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// show about dlg -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUabout(void) -{ -#ifdef _WINDOWS - HWND hWP=GetActiveWindow(); // to be sure - DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG_ABOUT), - hWP,(DLGPROC)AboutDlgProc); -#elif defined(_MACGL) - - AboutDlgProc(); -#else - - StartCfgTool("ABOUT"); - -#endif -} - -//////////////////////////////////////////////////////////////////////// -// We are ever fine ;) -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUtest(void) -{ - // if test fails this function should return negative value for error (unable to continue) - // and positive value for warning (can continue but output might be crappy) - - return 0; -} - -//////////////////////////////////////////////////////////////////////// -// save state funcs -//////////////////////////////////////////////////////////////////////// - -typedef struct GPUFREEZETAG -{ - uint32_t ulFreezeVersion; // should be always 1 for now (set by main emu) - uint32_t ulStatus; // current gpu status - uint32_t ulControl[256]; // latest control register values - unsigned char psxVRam[1024*1024*2]; // current VRam image (full 2 MB for ZN) -} GPUFreeze_t; - -//////////////////////////////////////////////////////////////////////// - -long CALLBACK GPUfreeze(uint32_t ulGetFreezeData,GPUFreeze_t * pF) -{ - if(ulGetFreezeData==2) - { - int lSlotNum=*((int *)pF); - if(lSlotNum<0) return 0; - if(lSlotNum>8) return 0; - lSelectedSlot=lSlotNum+1; - return 1; - } - - if(!pF) return 0; - if(pF->ulFreezeVersion!=1) return 0; - - if(ulGetFreezeData==1) - { - pF->ulStatus=STATUSREG; - memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t)); - memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); - - return 1; - } - - if(ulGetFreezeData!=0) return 0; - - STATUSREG=pF->ulStatus; - memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t)); - memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); - - ResetTextureArea(TRUE); - - GPUwriteStatus(ulStatusControl[0]); - GPUwriteStatus(ulStatusControl[1]); - GPUwriteStatus(ulStatusControl[2]); - GPUwriteStatus(ulStatusControl[3]); - GPUwriteStatus(ulStatusControl[8]); - GPUwriteStatus(ulStatusControl[6]); - GPUwriteStatus(ulStatusControl[7]); - GPUwriteStatus(ulStatusControl[5]); - GPUwriteStatus(ulStatusControl[4]); - - return 1; -} - -//////////////////////////////////////////////////////////////////////// -// special "emu infos" / "emu effects" functions -//////////////////////////////////////////////////////////////////////// - -//00 = black -//01 = white -//10 = red -//11 = transparent - -unsigned char cFont[10][120]= -{ -// 0 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -}, -// 1 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x05,0x50,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x05,0x55,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -}, -// 2 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x00,0x14,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x01,0x40,0x00,0x00, - 0x80,0x00,0x05,0x00,0x00,0x00, - 0x80,0x00,0x14,0x00,0x00,0x00, - 0x80,0x00,0x15,0x55,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -}, -// 3 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x01,0x54,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -}, -// 4 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x14,0x00,0x00, - 0x80,0x00,0x00,0x54,0x00,0x00, - 0x80,0x00,0x01,0x54,0x00,0x00, - 0x80,0x00,0x01,0x54,0x00,0x00, - 0x80,0x00,0x05,0x14,0x00,0x00, - 0x80,0x00,0x14,0x14,0x00,0x00, - 0x80,0x00,0x15,0x55,0x00,0x00, - 0x80,0x00,0x00,0x14,0x00,0x00, - 0x80,0x00,0x00,0x14,0x00,0x00, - 0x80,0x00,0x00,0x55,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -}, -// 5 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x15,0x55,0x00,0x00, - 0x80,0x00,0x14,0x00,0x00,0x00, - 0x80,0x00,0x14,0x00,0x00,0x00, - 0x80,0x00,0x14,0x00,0x00,0x00, - 0x80,0x00,0x15,0x54,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -}, -// 6 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x01,0x54,0x00,0x00, - 0x80,0x00,0x05,0x00,0x00,0x00, - 0x80,0x00,0x14,0x00,0x00,0x00, - 0x80,0x00,0x14,0x00,0x00,0x00, - 0x80,0x00,0x15,0x54,0x00,0x00, - 0x80,0x00,0x15,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -}, -// 7 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x15,0x55,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x00,0x14,0x00,0x00, - 0x80,0x00,0x00,0x14,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x00,0x50,0x00,0x00, - 0x80,0x00,0x01,0x40,0x00,0x00, - 0x80,0x00,0x01,0x40,0x00,0x00, - 0x80,0x00,0x05,0x00,0x00,0x00, - 0x80,0x00,0x05,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -}, -// 8 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -}, -// 9 -{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x05,0x54,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x05,0x00,0x00, - 0x80,0x00,0x14,0x15,0x00,0x00, - 0x80,0x00,0x05,0x55,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x00,0x05,0x00,0x00, - 0x80,0x00,0x00,0x14,0x00,0x00, - 0x80,0x00,0x05,0x50,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0x80,0x00,0x00,0x00,0x00,0x00, - 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa -} -}; - -//////////////////////////////////////////////////////////////////////// - -void PaintPicDot(unsigned char * p,unsigned char c) -{ - if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;} - if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} - if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} -} - -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUgetScreenPic(unsigned char * pMem) -{ - float XS,YS;int x,y,v; - unsigned char * ps, * px, * pf; - unsigned char c; - - if(!pGfxCardScreen) - { - glPixelStorei(GL_PACK_ALIGNMENT,1); - pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); - } - - ps=pGfxCardScreen; - - glReadBuffer(GL_FRONT); - - glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps); - - glReadBuffer(GL_BACK); - - XS=(float)iResX/128; - YS=(float)iResY/96; - pf=pMem; - - for(y=96;y>0;y--) - { - for(x=0;x<128;x++) - { - px=ps+(3*((int)((float)x * XS))+ - (3*iResX)*((int)((float)y*YS))); - *(pf+0)=*(px+2); - *(pf+1)=*(px+1); - *(pf+2)=*(px+0); - pf+=3; - } - } - - ///////////////////////////////////////////////////////////////////// - // generic number/border painter - - pf=pMem+(103*3); - - for(y=0;y<20;y++) - { - for(x=0;x<6;x++) - { - c=cFont[lSelectedSlot][x+y*6]; - v=(c&0xc0)>>6; - PaintPicDot(pf,(unsigned char)v);pf+=3; // paint the dots into the rect - v=(c&0x30)>>4; - PaintPicDot(pf,(unsigned char)v);pf+=3; - v=(c&0x0c)>>2; - PaintPicDot(pf,(unsigned char)v);pf+=3; - v=c&0x03; - PaintPicDot(pf,(unsigned char)v);pf+=3; - } - pf+=104*3; - } - - pf=pMem; - for(x=0;x<128;x++) - { - *(pf+(95*128*3))=0x00;*pf++=0x00; - *(pf+(95*128*3))=0x00;*pf++=0x00; - *(pf+(95*128*3))=0xff;*pf++=0xff; - } - pf=pMem; - for(y=0;y<96;y++) - { - *(pf+(127*3))=0x00;*pf++=0x00; - *(pf+(127*3))=0x00;*pf++=0x00; - *(pf+(127*3))=0xff;*pf++=0xff; - pf+=127*3; - } - -} - -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUshowScreenPic(unsigned char * pMem) -{ - DestroyPic(); - if(pMem==0) return; - CreatePic(pMem); -} - -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUsetfix(uint32_t dwFixBits) -{ - dwEmuFixes=dwFixBits; -} - -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUvisualVibration(uint32_t iSmall, uint32_t iBig) -{ - int iVibVal; - - if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width - iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x); - else iVibVal=1; - // big rumble: 4...15 sp ; small rumble 1...3 sp - if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10)); - else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10)); - - srand(timeGetTime()); // init rand (will be used in BufferSwap) - - iRumbleTime=15; // let the rumble last 16 buffer swaps -} - -//////////////////////////////////////////////////////////////////////// -// main emu can set display infos (A/M/G/D) -//////////////////////////////////////////////////////////////////////// - -void CALLBACK GPUdisplayFlags(uint32_t dwFlags) -{ - dwCoreFlags=dwFlags; -} - -void CALLBACK GPUvBlank( int val ) -{ - vBlank = val; -} +/*************************************************************************** + gpu.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +// !!! enable this, if Linux XF86VidMode is not supported: +//#define NOVMODE + +#include "stdafx.h" + +#if !defined(_MACGL) && !defined(_WINDOWS) + +#include "config.h" + +#ifndef NOVMODE +#include +static XF86VidModeModeInfo **modes=0; +static int iOldMode=0; +#endif + +#endif + +#define _IN_GPU + +#include "externals.h" +#include "psemu_plugin_defs.h" +#include "gpu.h" +#include "draw.h" +#include "cfg.h" +#include "prim.h" +#include "psemu_plugin_defs.h" +#include "texture.h" +#include "menu.h" +#include "fps.h" +#include "key.h" +#ifdef _WINDOWS +#include "resource.h" +#include "ssave.h" +#endif + +//////////////////////////////////////////////////////////////////////// +// PPDK developer must change libraryName field and can change revision and build +//////////////////////////////////////////////////////////////////////// + +const unsigned char version = 1; // do not touch - library for PSEmu 1.x +const unsigned char revision = 1; +const unsigned char build = 78; + +static char *libraryName = N_("OpenGL Driver"); + +static char *PluginAuthor = N_("Pete Bernert"); +#if 0 +static char *libraryInfo = N_("Based on P.E.Op.S. MesaGL Driver V1.78\nCoded by Pete Bernert\n"); +#endif + +//////////////////////////////////////////////////////////////////////// +// memory image of the PSX vram +//////////////////////////////////////////////////////////////////////// + +unsigned char *psxVSecure; +unsigned char *psxVub; +signed char *psxVsb; +unsigned short *psxVuw; +unsigned short *psxVuw_eom; +signed short *psxVsw; +uint32_t *psxVul; +signed int *psxVsl; + +// macro for easy access to packet information +#define GPUCOMMAND(x) ((x>>24) & 0xff) + +GLfloat gl_z=0.0f; +BOOL bNeedInterlaceUpdate=FALSE; +BOOL bNeedRGB24Update=FALSE; +BOOL bChangeWinMode=FALSE; + +uint32_t ulStatusControl[256]; + +//////////////////////////////////////////////////////////////////////// +// global GPU vars +//////////////////////////////////////////////////////////////////////// + +static int GPUdataRet; +int lGPUstatusRet; +char szDispBuf[64]; + +uint32_t dwGPUVersion = 0; +int iGPUHeight = 512; +int iGPUHeightMask = 511; +int GlobalTextIL = 0; +int iTileCheat = 0; + +static uint32_t gpuDataM[256]; +static unsigned char gpuCommand = 0; +static int gpuDataC = 0; +static int gpuDataP = 0; + +VRAMLoad_t VRAMWrite; +VRAMLoad_t VRAMRead; +int iDataWriteMode; +int iDataReadMode; + +int lClearOnSwap; +int lClearOnSwapColor; +BOOL bSkipNextFrame = FALSE; +int iColDepth; +BOOL bChangeRes; +BOOL bWindowMode; +int iWinSize; + +// possible psx display widths +short dispWidths[8] = {256,320,512,640,368,384,512,640}; + +PSXDisplay_t PSXDisplay; +PSXDisplay_t PreviousPSXDisplay; +TWin_t TWin; +short imageX0,imageX1; +short imageY0,imageY1; +BOOL bDisplayNotSet = TRUE; +GLuint uiScanLine=0; +int iUseScanLines=0; +float iScanlineColor[] = {0,0,0, 0.3}; // easy on the eyes. +int lSelectedSlot=0; +unsigned char * pGfxCardScreen=0; +int iBlurBuffer=0; +int iScanBlend=0; +int iRenderFVR=0; +int iNoScreenSaver=0; +uint32_t ulGPUInfoVals[16]; +int iFakePrimBusy = 0; +int iRumbleVal = 0; +int iRumbleTime = 0; +uint32_t vBlank=0; + +//////////////////////////////////////////////////////////////////////// +// stuff to make this a true PDK module +//////////////////////////////////////////////////////////////////////// + +char * CALLBACK PSEgetLibName(void) +{ + return _(libraryName); +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return PSE_LT_GPU; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return version<<16|revision<<8|build; +} + +#if 0 +char * GPUgetLibInfos(void) +{ + return _(libraryInfo); +} +#endif + +//////////////////////////////////////////////////////////////////////// +// snapshot funcs (saves screen to bitmap / text infos into file) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +static char * GetConfigInfos(HWND hW) +#else +static char * GetConfigInfos(int hW) +#endif +{ +#ifdef _WINDOWS + HDC hdc;HGLRC hglrc; +#endif + char szO[2][4]={"off","on "}; + char szTxt[256]; + char * pB=(char *)malloc(32767); + + if(!pB) return NULL; + *pB=0; + //----------------------------------------------------// + sprintf(szTxt,"Plugin: %s %d.%d.%d (mod)\r\n",libraryName,version,revision,build); + strcat(pB,szTxt); + sprintf(szTxt,"Author: %s\r\n",PluginAuthor); + strcat(pB,szTxt); + +#ifdef _WINDOWS + if(hW) + { + hdc = GetDC(hW); + bSetupPixelFormat(hdc); + hglrc = wglCreateContext(hdc); + wglMakeCurrent(hdc, hglrc); + } +#endif + + sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR)); + strcat(pB,szTxt); + sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER)); + strcat(pB,szTxt); + sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION)); + strcat(pB,szTxt); + //strcat(pB,(char *)glGetString(GL_EXTENSIONS)); + //strcat(pB,"\r\n\r\n"); + +#ifdef _WINDOWS + if(hW) + { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hglrc); + ReleaseDC(hW,hdc); + } + //----------------------------------------------------// +#endif + + if(hW && bWindowMode) + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize)); + else + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY); + strcat(pB,szTxt); + if(bWindowMode) sprintf(szTxt,"Window mode\r\n"); + else + { + sprintf(szTxt,"Fullscreen "); + strcat(pB,szTxt); + if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth); + else sprintf(szTxt,"- NO desktop changing\r\n"); + } + strcat(pB,szTxt); + + if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]); + else strcpy(szTxt,"- V-Sync: Driver\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]); + strcat(pB,szTxt); + //----------------------------------------------------// + strcpy(szTxt,"Textures:\r\n- "); + if(iTexQuality==0) strcat(szTxt,"Default"); + else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4"); + else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1"); + else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8"); + else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8"); + if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n"); + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + if(!hW) + { + sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType); + if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n"); + else strcat(szTxt,"NOT supported\r\n"); + } + else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType); + strcat(pB,szTxt); + sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures); + strcat(pB,szTxt); + if(!hW) + { + sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]); + strcat(pB,szTxt); + } + sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize); + if(!hW) + sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt); + else strcat(szTxt,"\r\n\r\n"); + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]); + strcat(pB,szTxt); + sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]); + strcat(pB,szTxt); + if(iFrameLimit==2) + strcpy(szTxt,"- FPS limit: Auto\r\n\r\n"); + else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate); + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing); + strcat(pB,szTxt); + sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType); + if(!hW && iFrameTexType==2) + { + if(gTexFrameName) strcat(szTxt," - texture created\r\n"); + else strcat(szTxt," - not used yet\r\n"); + } + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType); + strcat(pB,szTxt); + sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]); + strcat(pB,szTxt); + sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]); + strcat(pB,szTxt); + sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]); + if(!hW && bAdvancedBlend) + { + if(bGLBlend) strcat(szTxt," (hardware)\r\n"); + else strcat(szTxt," (software)\r\n"); + } + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + + if(!hW) + { + strcpy(szTxt,"- Subtractive blending: "); + if(glBlendEquationEXTEx) + { + if(bUseMultiPass) strcat(szTxt,"supported, but not used!"); + else strcat(szTxt,"activated"); + } + else strcat(szTxt," NOT supported!"); + strcat(szTxt,"\r\n\r\n"); + } + else strcpy(szTxt,"\r\n"); + + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]); + strcat(pB,szTxt); + if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend); + else strcpy(szTxt,"\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]); + strcat(pB,szTxt); +// sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]); +// fwrite(szTxt,lstrlen(szTxt),1,txtfile); + sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]); + strcat(pB,szTxt); + sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]); + strcat(pB,szTxt); + sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]); + strcat(pB,szTxt); + sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]); + strcat(pB,szTxt); + if(!hW && iBlurBuffer) + { + if(gTexBlurName) strcat(pB," - supported\r\n"); + else strcat(pB," - not supported\r\n"); + } + else strcat(pB,"\r\n"); + sprintf(szTxt,"- Game fixes: %s [%08x]\r\n",szO[bUseFixes],dwCfgFixes); + strcat(pB,szTxt); + //----------------------------------------------------// + return pB; +} + +//////////////////////////////////////////////////////////////////////// +// save text infos to file +//////////////////////////////////////////////////////////////////////// + +static void DoTextSnapShot(int iNum) +{ + FILE *txtfile;char szTxt[256];char * pB; + +#ifdef _WINDOWS + sprintf(szTxt,"snap\\pcsx%04d.txt",iNum); +#else + sprintf(szTxt,"%s/pcsx%04d.txt",getenv("HOME"),iNum); +#endif + + if((txtfile=fopen(szTxt,"wb"))==NULL) + return; + + pB=GetConfigInfos(0); + if(pB) + { + if(fwrite(pB,strlen(pB),1,txtfile) != 1) { + free(pB); + fclose(txtfile); + remove(szTxt); + return; + } + free(pB); + } + fclose(txtfile); +} + +//////////////////////////////////////////////////////////////////////// +// saves screen bitmap to file +//////////////////////////////////////////////////////////////////////// + +void DoSnapShot(void) +{ + unsigned char * snapshotdumpmem=NULL,* p,c; + FILE *bmpfile;char filename[256]; + unsigned char header[0x36];int size; + unsigned char empty[2]={0,0};int i; + unsigned int snapshotnr = 0; + short SnapWidth; + short SnapHeigth; + + bSnapShot=FALSE; + + SnapWidth = iResX; + SnapHeigth = iResY; + + size=SnapWidth * SnapHeigth * 3 + 0x38; + + if((snapshotdumpmem=(unsigned char *) + malloc(SnapWidth*SnapHeigth*3))==NULL) + return; + + // fill in proper values for BMP + for(i=0;i<0x36;i++) header[i]=0; + header[0]='B'; + header[1]='M'; + header[2]=(unsigned char)(size&0xff); + header[3]=(unsigned char)((size>>8)&0xff); + header[4]=(unsigned char)((size>>16)&0xff); + header[5]=(unsigned char)((size>>24)&0xff); + header[0x0a]=0x36; + header[0x0e]=0x28; + header[0x12]=(unsigned char)(SnapWidth%256); + header[0x13]=(unsigned char)(SnapWidth/256); + header[0x16]=(unsigned char)(SnapHeigth%256); + header[0x17]=(unsigned char)(SnapHeigth/256); + header[0x1a]=0x01; + header[0x1c]=0x18; + header[0x26]=0x12; + header[0x27]=0x0B; + header[0x2A]=0x12; + header[0x2B]=0x0B; + + // increment snapshot value + // get filename + do + { + snapshotnr++; +#ifdef _WINDOWS + sprintf(filename,"snap/pcsx%04d.bmp",snapshotnr); +#else + sprintf(filename,"%s/pcsx%04d.bmp",getenv("HOME"),snapshotnr); +#endif + bmpfile=fopen(filename,"rb"); + if(bmpfile==NULL)break; + fclose(bmpfile); + if(snapshotnr==9999) break; + } + while(TRUE); + + // try opening new snapshot file + if((bmpfile=fopen(filename,"wb"))==NULL) + {free(snapshotdumpmem);return;} + + if(fwrite(header,0x36,1,bmpfile) != 1) { + free(snapshotdumpmem); + fclose(bmpfile); + remove(filename); + return; + } + + glReadPixels(0,0,SnapWidth,SnapHeigth,GL_RGB, + GL_UNSIGNED_BYTE,snapshotdumpmem); + p=snapshotdumpmem; + size=SnapWidth * SnapHeigth; + + for(i=0;i get sizes again + } + else // first real startup + { + ReadConfig(); // -> read config from registry + + SetFrameRateConfig(); // -> setup frame rate stuff + } + + if(iNoScreenSaver) EnableScreenSaver(FALSE); // at least we can try + + + memset(&dv,0,sizeof(DEVMODE)); + dv.dmSize=sizeof(DEVMODE); + EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv); + + bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows! + + if(bWindowMode) // win mode? + { + DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers) + dw&=~WS_THICKFRAME; + dw|=WS_BORDER|WS_CAPTION|CS_OWNDC; + SetWindowLong(hWWindow, GWL_STYLE, dw); + + hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any) + if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); + + iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize); + ShowWindow(hWWindow,SW_SHOWNORMAL); + + MoveWindow(hWWindow, // -> center wnd + GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2, + GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2, + iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3, + iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3, + TRUE); + UpdateWindow(hWWindow); // -> let windows do some update + + if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info + iColDepth=dv.dmBitsPerPel; + } + else // fullscreen mode: + { + if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution + dv.dmPelsWidth !=(unsigned int)iResX || + dv.dmPelsHeight!=(unsigned int)iResY) + bChangeRes=TRUE; else bChangeRes=FALSE; + + if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations') + + SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure) + + hPSEMenu=GetMenu(hWWindow); // -> hide menu + if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); + ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode + } + + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + + r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized + hdc = GetDC(hWWindow); + FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH)); + bSetupPixelFormat(hdc); + ReleaseDC(hWWindow,hdc); + + bDisplayNotSet = TRUE; + bSetClip=TRUE; + + SetFixes(); // setup game fixes + + InitializeTextureStore(); // init texture mem + +// lGPUstatusRet = 0x74000000; + +// with some emus, we could do the OGL init right here... oh my +// if(bIsFirstFrame) GLinitialize(); + + return 0; +} + +#elif !defined (_MACGL) + +//////////////////////////////////////////////////////////////////////// +// LINUX GPU OPEN: func to open up the gpu display (X stuff) +// please note: in linux we are creating our own display, and we return +// the display ID to the main emu... that's cleaner +//////////////////////////////////////////////////////////////////////// + +char * pCaptionText=0; +int bFullScreen=0; +Display *display; + +static Cursor cursor; +static XVisualInfo *myvisual; +static Colormap colormap; +static Window window; + +static int bModeChanged=0; + +typedef struct +{ +#define MWM_HINTS_DECORATIONS 2 + long flags; + long functions; + long decorations; + long input_mode; +} MotifWmHints; + +static int dbdepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,GLX_DEPTH_SIZE,16,None}; +static int dbnodepat[]={GLX_RGBA,GLX_DOUBLEBUFFER,None}; +static GLXContext cx; + +static int fx=0; + +//////////////////////////////////////////////////////////////////////// + +static void osd_close_display (void) // close display +{ + if(display) // display exists? + { + glXDestroyContext(display,cx); // -> kill context + XFreeColormap(display, colormap); // -> kill colormap + XSync(display,False); // -> sync events + +#ifndef NOVMODE + if(bModeChanged) // -> repair screen mode + { + int myscreen=DefaultScreen(display); + XF86VidModeSwitchToMode(display,myscreen, // --> switch mode back + modes[iOldMode]); + XF86VidModeSetViewPort(display,myscreen,0,0); // --> set viewport upperleft + free(modes); // --> finally kill mode infos + bModeChanged=0; // --> done + } +#endif + + XCloseDisplay(display); // -> close display + } +} + +//////////////////////////////////////////////////////////////////////// + +static void sysdep_create_display(void) // create display +{ + XSetWindowAttributes winattr;float fxgamma=2; + int myscreen;char gammastr[14]; + Screen * screen;XEvent event; + XSizeHints hints;XWMHints wm_hints; + MotifWmHints mwmhints;Atom mwmatom;Atom delwindow; + char *glxfx; + + glxfx=getenv("MESA_GLX_FX"); // 3dfx mesa fullscreen flag + if(glxfx) + { + if(glxfx[0]=='f') // -> yup, fullscreen needed + { + fx=1; // -> raise flag + putenv("FX_GLIDE_NO_SPLASH="); + sprintf(gammastr,"SST_GAMMA=%2.1f",fxgamma); // -> set gamma + putenv(gammastr); + } + } + + display=XOpenDisplay(NULL); // open display + if(!display) // no display? + { + fprintf (stderr,"Failed to open display!!!\n"); + osd_close_display(); + return; // -> bye + } + + myscreen=DefaultScreen(display); // get screen id + +#ifdef NOVMODE + if(bFullScreen) {fx=1;bModeChanged=0;} +#else + if(bFullScreen) + { + XF86VidModeModeLine mode; + int nmodes,iC; + fx=1; // raise flag + XF86VidModeGetModeLine(display,myscreen,&iC,&mode); // get actual mode info + if(mode.privsize) XFree(mode.private); // no need for private stuff + bModeChanged=0; // init mode change flag + if(iResX!=mode.hdisplay || iResY!=mode.vdisplay) // wanted mode is different? + { + XF86VidModeGetAllModeLines(display,myscreen, // -> enum all mode infos + &nmodes,&modes); + if(modes) // -> infos got? + { + for(iC=0;iC loop modes + { + if(mode.hdisplay==modes[iC]->hdisplay && // -> act mode found? + mode.vdisplay==modes[iC]->vdisplay) // if yes: store mode id + iOldMode=iC; + + if(iResX==modes[iC]->hdisplay && // -> wanted mode found? + iResY==modes[iC]->vdisplay) + { + XF86VidModeSwitchToMode(display,myscreen, // --> switch to mode + modes[iC]); + XF86VidModeSetViewPort(display,myscreen,0,0); + bModeChanged=1; // --> raise flag for repairing mode on close + } + } + + if(bModeChanged==0) // -> no mode found? + { + free(modes); // --> free infos + printf("No proper fullscreen mode found!\n"); // --> some info output + } + } + } + } +#endif + + screen=DefaultScreenOfDisplay(display); + + if(iZBufferDepth) // visual (with or without zbuffer) + myvisual=glXChooseVisual(display,myscreen,dbdepat); + else myvisual=glXChooseVisual(display,myscreen,dbnodepat); + + if(!myvisual) // no visual? + { + fprintf(stderr,"Failed to obtain visual!!!\n"); // -> bye + osd_close_display(); + return; + } + + cx=glXCreateContext(display,myvisual,0,GL_TRUE); // create rendering context + + if(!cx) // no context? + { + fprintf(stderr,"Failed to create OpenGL context!!!\n"); + osd_close_display(); // -> bxe + return; + } + + // pffff... much work for a simple blank cursor... oh, well... + if(!bFullScreen) cursor=XCreateFontCursor(display,XC_trek); + else + { + Pixmap p1,p2;XImage * img; + XColor b,w;unsigned char * idata; + XGCValues GCv; + GC GCc; + + memset(&b,0,sizeof(XColor)); + memset(&w,0,sizeof(XColor)); + idata=(unsigned char *)malloc(8); + memset(idata,0,8); + + p1=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); + p2=XCreatePixmap(display,RootWindow(display,myvisual->screen),8,8,1); + + img = XCreateImage(display,myvisual->visual, + 1,XYBitmap,0,(char *)idata,8,8,8,1); + + GCv.function = GXcopy; + GCv.foreground = ~0; + GCv.background = 0; + GCv.plane_mask = AllPlanes; + GCc = XCreateGC(display,p1, + (GCFunction|GCForeground|GCBackground|GCPlaneMask),&GCv); + + XPutImage(display, p1,GCc,img,0,0,0,0,8,8); + XPutImage(display, p2,GCc,img,0,0,0,0,8,8); + XFreeGC(display, GCc); + + cursor = XCreatePixmapCursor(display,p1,p2,&b,&w,0,0); + + XFreePixmap(display,p1); + XFreePixmap(display,p2); + XDestroyImage(img); // will free idata as well + } + + colormap=XCreateColormap(display, // create colormap + RootWindow(display,myvisual->screen), + myvisual->visual,AllocNone); + + winattr.background_pixel=0; + winattr.border_pixel=WhitePixelOfScreen(screen); + winattr.bit_gravity=ForgetGravity; + winattr.win_gravity=NorthWestGravity; + winattr.backing_store=NotUseful; + winattr.override_redirect=False; + winattr.save_under=False; + winattr.event_mask=0; + winattr.do_not_propagate_mask=0; + winattr.colormap=colormap; + winattr.cursor=None; + + window=XCreateWindow(display, // create own window + RootWindow(display,DefaultScreen(display)), + 0,0,iResX,iResY, + 0,myvisual->depth, + InputOutput,myvisual->visual, + CWBorderPixel | CWBackPixel | + CWEventMask | CWDontPropagate | + CWColormap | CWCursor, + &winattr); + + if(!window) // no window? + { + fprintf(stderr,"Failed in XCreateWindow()!!!\n"); + osd_close_display(); // -> bye + return; + } + + delwindow = XInternAtom(display,"WM_DELETE_WINDOW",0); + XSetWMProtocols(display, window, &delwindow, 1); + + hints.flags=PMinSize|PMaxSize; // hints + if(fx) hints.flags|=USPosition|USSize; + else hints.flags|=PSize; + + hints.min_width = hints.max_width = hints.base_width = iResX; + hints.min_height = hints.max_height = hints.base_height = iResY; + + wm_hints.input=1; + wm_hints.flags=InputHint; + + XSetWMHints(display,window,&wm_hints); + XSetWMNormalHints(display,window,&hints); + if(pCaptionText) // caption + XStoreName(display,window,pCaptionText); + else XStoreName(display,window,"Pete MesaGL PSX Gpu"); + + XDefineCursor(display,window,cursor); // cursor + + if(fx) // window title bar hack + { + mwmhints.flags=MWM_HINTS_DECORATIONS; + mwmhints.decorations=0; + mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); + XChangeProperty(display,window,mwmatom,mwmatom,32, + PropModeReplace,(unsigned char *)&mwmhints,4); + } + + XSelectInput(display,window, // input setup + FocusChangeMask | ExposureMask | + KeyPressMask | KeyReleaseMask); + + XMapRaised(display,window); + XClearWindow(display,window); + XWindowEvent(display,window,ExposureMask,&event); + glXMakeCurrent(display,window,cx); + +/* + printf(glGetString(GL_VENDOR)); + printf("\n"); + printf(glGetString(GL_RENDERER)); + printf("\n"); +*/ + + if (fx) // after make current: fullscreen resize + { + XResizeWindow(display,window,screen->width,screen->height); + hints.min_width = hints.max_width = hints.base_width = screen->width; + hints.min_height= hints.max_height = hints.base_height = screen->height; + XSetWMNormalHints(display,window,&hints); + + // set the window layer for GNOME + { + XEvent xev; + + memset(&xev, 0, sizeof(xev)); + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = 1; + xev.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", 0); + xev.xclient.window = window; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", 0); + xev.xclient.data.l[2] = 0; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent(display, RootWindow(display, DefaultScreen(display)), 0, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } + } +} + +#endif // !defined(_MACGL) + +#ifndef _WINDOWS + +#if defined(_MACGL) +extern char * pCaptionText; +#endif + +//////////////////////////////////////////////////////////////////////// + +long GPUopen(unsigned long * disp,char * CapText,char * CfgFile) +{ + pCaptionText=CapText; + pConfigFile=CfgFile; + + ReadConfig(); // read text file for config + + SetFrameRateConfig(); // setup frame rate stuff + + bIsFirstFrame = TRUE; // we have to init later (well, no really... in Linux we do all in GPUopen) + + #if defined (_MACGL) + unsigned long display = ulInitDisplay(); + #else + sysdep_create_display(); // create display + #endif + + InitializeTextureStore(); // init texture mem + + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + + GLinitialize(); // init opengl + + if(disp) + { + *disp = display; + } + + if(display) return 0; + return -1; +} + +#endif // ndef _WINDOWS + + + +//////////////////////////////////////////////////////////////////////// +// close +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +long CALLBACK GPUclose() // WINDOWS CLOSE +{ + ExitKeyHandler(); + + GLcleanup(); // close OGL + + if(bChangeRes) // change res back + ChangeDisplaySettings(NULL,0); + + if(hPSEMenu) // set menu again + SetMenu(hWWindow,hPSEMenu); + + if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory + pGfxCardScreen=0; + + if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again + + return 0; +} + +#else + +long GPUclose() // LINUX CLOSE +{ + GLcleanup(); // close OGL + + if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory + pGfxCardScreen=0; + #if defined (_MACGL) + CloseDisplay(); + #else + osd_close_display(); // destroy display + #endif + return 0; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// I shot the sheriff... last function called from emu +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUshutdown() +{ + if(psxVSecure) free(psxVSecure); // kill emulated vram memory + psxVSecure=0; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// paint it black: simple func to clean up optical border garbage +//////////////////////////////////////////////////////////////////////// + +static void PaintBlackBorders(void) +{ + short s; + + glDisable(GL_SCISSOR_TEST); + if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} + if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + glDisable(GL_ALPHA_TEST); + + glBegin(GL_QUADS); + + vertex[0].c.lcol=0xff000000; + SETCOL(vertex[0]); + + if(PreviousPSXDisplay.Range.x0) + { + s=PreviousPSXDisplay.Range.x0+1; + glVertex3f(0,0,0.99996f); + glVertex3f(0,PSXDisplay.DisplayMode.y,0.99996f); + glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f); + glVertex3f(s,0,0.99996f); + + s+=PreviousPSXDisplay.Range.x1-2; + + glVertex3f(s,0,0.99996f); + glVertex3f(s,PSXDisplay.DisplayMode.y,0.99996f); + glVertex3f(PSXDisplay.DisplayMode.x,PSXDisplay.DisplayMode.y,0.99996f); + glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f); + } + + if(PreviousPSXDisplay.Range.y0) + { + s=PreviousPSXDisplay.Range.y0+1; + glVertex3f(0,0,0.99996f); + glVertex3f(0,s,0.99996f); + glVertex3f(PSXDisplay.DisplayMode.x,s,0.99996f); + glVertex3f(PSXDisplay.DisplayMode.x,0,0.99996f); + } + + glEnd(); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// +// helper to draw scanlines +//////////////////////////////////////////////////////////////////////// + +static __inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + + glBegin(GL_QUAD_STRIP); + glTexCoord2fv(&vertex1->sow); + glVertex3fv(&vertex1->x); + + glTexCoord2fv(&vertex2->sow); + glVertex3fv(&vertex2->x); + + glTexCoord2fv(&vertex4->sow); + glVertex3fv(&vertex4->x); + + glTexCoord2fv(&vertex3->sow); + glVertex3fv(&vertex3->x); + glEnd(); +} + +//////////////////////////////////////////////////////////////////////// +// scanlines +//////////////////////////////////////////////////////////////////////// + +static void SetScanLines(void) +{ + glLoadIdentity(); + glOrtho(0,iResX,iResY, 0, -1, 1); + + if(bKeepRatio) + glViewport(0,0,iResX,iResY); + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_ALPHA_TEST); + if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} + + if(iScanBlend<0) // special texture mask scanline mode + { + if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} + gTexName=gTexScanName; + glBindTexture(GL_TEXTURE_2D, gTexName); + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + if(!bBlendEnable) {glEnable(GL_BLEND);bBlendEnable=TRUE;} + SetScanTexTrans(); + + vertex[0].x=0; + vertex[0].y=iResY; + vertex[0].z=0.99996f; + + vertex[1].x=iResX; + vertex[1].y=iResY; + vertex[1].z=0.99996f; + + vertex[2].x=iResX; + vertex[2].y=0; + vertex[2].z=0.99996f; + + vertex[3].x=0; + vertex[3].y=0; + vertex[3].z=0.99996f; + + vertex[0].sow=0; + vertex[0].tow=0; + vertex[1].sow=(float)iResX/4.0f; + vertex[1].tow=0; + vertex[2].sow=vertex[1].sow; + vertex[2].tow=(float)iResY/4.0f; + vertex[3].sow=0; + vertex[3].tow=vertex[2].tow; + + vertex[0].c.lcol=0xffffffff; + SETCOL(vertex[0]); + + XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); + } + else // typical line mode + { + if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} + + if(iScanBlend==0) + { + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + vertex[0].c.lcol=0xff000000; + } + else + { + if(!bBlendEnable) {glEnable(GL_BLEND);bBlendEnable=TRUE;} + SetScanTrans(); + vertex[0].c.lcol=iScanBlend<<24; + } + + SETCOL(vertex[0]); + + glCallList(uiScanLine); + } + + glLoadIdentity(); + glOrtho(0,PSXDisplay.DisplayMode.x, + PSXDisplay.DisplayMode.y, 0, -1, 1); + + if(bKeepRatio) + glViewport(rRatioRect.left, + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); // init viewport + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// +// blur, babe, blur (heavy performance hit for a so-so fullscreen effect) +//////////////////////////////////////////////////////////////////////// + +static void BlurBackBuffer(void) +{ + if(!gTexBlurName) return; + + if(bKeepRatio) glViewport(0,0,iResX,iResY); + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_ALPHA_TEST); + if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} + if(iZBufferDepth) glDisable(GL_DEPTH_TEST); + if(bDrawDither) glDisable(GL_DITHER); + + gTexName=gTexBlurName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glCopyTexSubImage2D( GL_TEXTURE_2D, 0, // get back buffer in texture + 0, + 0, + 0, + 0, + iResX,iResY); + + vertex[0].x=0; + vertex[0].y=PSXDisplay.DisplayMode.y; + vertex[1].x=PSXDisplay.DisplayMode.x; + vertex[1].y=PSXDisplay.DisplayMode.y; + vertex[2].x=PSXDisplay.DisplayMode.x; + vertex[2].y=0; + vertex[3].x=0; + vertex[3].y=0; + vertex[0].sow=0; + vertex[0].tow=0; + +#ifdef OWNSCALE + vertex[1].sow=((GLfloat)iFTexA)/256.0f; + vertex[2].tow=((GLfloat)iFTexB)/256.0f; +#else + vertex[1].sow=iFTexA; + vertex[2].tow=iFTexB; +#endif + vertex[1].tow=0; + vertex[2].sow=vertex[1].sow; + vertex[3].sow=0; + vertex[3].tow=vertex[2].tow; + + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + vertex[0].c.lcol=0x7fffffff; + SETCOL(vertex[0]); + + DrawMultiBlur(); // draw the backbuffer texture to create blur effect + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); + if(iZBufferDepth) glEnable(GL_DEPTH_TEST); + if(bDrawDither) glEnable(GL_DITHER); + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); + + if(bKeepRatio) + glViewport(rRatioRect.left, // re-init viewport + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); +} + +//////////////////////////////////////////////////////////////////////// +// "unblur" repairs the backbuffer after a blur + +static void UnBlurBackBuffer(void) +{ + if(!gTexBlurName) return; + + if(bKeepRatio) glViewport(0,0,iResX,iResY); + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_ALPHA_TEST); + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + if(!bTexEnabled) {glEnable(GL_TEXTURE_2D);bTexEnabled=TRUE;} + if(iZBufferDepth) glDisable(GL_DEPTH_TEST); + if(bDrawDither) glDisable(GL_DITHER); + + gTexName=gTexBlurName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + vertex[0].x=0; + vertex[0].y=PSXDisplay.DisplayMode.y; + vertex[1].x=PSXDisplay.DisplayMode.x; + vertex[1].y=PSXDisplay.DisplayMode.y; + vertex[2].x=PSXDisplay.DisplayMode.x; + vertex[2].y=0; + vertex[3].x=0; + vertex[3].y=0; + vertex[0].sow=0; + vertex[0].tow=0; +#ifdef OWNSCALE + vertex[1].sow=((GLfloat)iFTexA)/256.0f; + vertex[2].tow=((GLfloat)iFTexB)/256.0f; +#else + vertex[1].sow=iFTexA; + vertex[2].tow=iFTexB; +#endif + vertex[1].tow=0; + vertex[2].sow=vertex[1].sow; + vertex[3].sow=0; + vertex[3].tow=vertex[2].tow; + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + vertex[0].c.lcol=0xffffffff; + SETCOL(vertex[0]); + + // simply draw the backbuffer texture (without blur) + XPRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); + if(iZBufferDepth) glEnable(GL_DEPTH_TEST); + if(bDrawDither) glEnable(GL_DITHER); // dither mode + if(bGLBlend) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT); + + if(bKeepRatio) + glViewport(rRatioRect.left, + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); // init viewport +} + +//////////////////////////////////////////////////////////////////////// +// Update display (swap buffers)... called in interlaced mode on +// every emulated vsync, otherwise whenever the displayed screen region +// has been changed +//////////////////////////////////////////////////////////////////////// + +int iLastRGB24=0; // special vars for checking when to skip two display updates +int iSkipTwo=0; + +void updateDisplay(void) // UPDATE DISPLAY +{ + BOOL bBlur=FALSE; + +#ifdef _WINDOWS + HDC hdc=GetDC(hWWindow); // windows: + wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again +#endif +#if defined (_MACGL) + BringContextForward(); +#endif + bFakeFrontBuffer=FALSE; + bRenderFrontBuffer=FALSE; + + if(iRenderFVR) // frame buffer read fix mode still active? + { + iRenderFVR--; // -> if some frames in a row without read access: turn off mode + if(!iRenderFVR) bFullVRam=FALSE; + } + + if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check + { + iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes + } + iLastRGB24=0; + + if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted? + { + PrepareFullScreenUpload(-1); + UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram + bNeedUploadTest=FALSE; + bNeedInterlaceUpdate=FALSE; + bNeedUploadAfter=FALSE; + bNeedRGB24Update=FALSE; + } + else + if(bNeedInterlaceUpdate) // smaller upload? + { + bNeedInterlaceUpdate=FALSE; + xrUploadArea=xrUploadAreaIL; // -> upload this rect + UploadScreen(TRUE); + } + + if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9 + + if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed + PreviousPSXDisplay.Range.y0) + PaintBlackBorders(); + + if(PSXDisplay.Disabled) // display disabled? + { + // moved here + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,128); // -> clear whole backbuffer + glClear(uiBufferBits); + glEnable(GL_SCISSOR_TEST); + gl_z=0.0f; + bDisplayNotSet = TRUE; + } + + if(iSkipTwo) // we are in skipping mood? + { + iSkipTwo--; + iDrawnSomething=0; // -> simply lie about something drawn + } + + if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated? + {BlurBackBuffer();bBlur=TRUE;} // -> blur it + + if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it + + if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em + + if(dwActFixes&128) // special FPS limitation mode? + { + if(bUseFrameLimit) PCFrameCap(); // -> ok, do it + if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS) + PCcalcfps(); + } + + if(gTexPicName) DisplayPic(); // some gpu info picture active? display it + + if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :) + + if(ulKeybits&KEY_SHOWFPS) // wanna see FPS? + { + sprintf(szDispBuf,"%06.1f",fps_cur); + DisplayText(); // -> show it + } + + //----------------------------------------------------// + // main buffer swapping (well, or skip it) + + if(bUseFrameSkip) // frame skipping active ? + { + if(!bSkipNextFrame) + { + if(iDrawnSomething) +#ifdef _WINDOWS + SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip +#elif defined(_MACGL) + DoBufferSwap(); +#else + glXSwapBuffers(display,window); +#endif + } + if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row + { + if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) + {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} + else bSkipNextFrame = FALSE; + } + else FrameSkip(); + } + else // no skip ? + { + if(iDrawnSomething) +#ifdef _WINDOWS + SwapBuffers(wglGetCurrentDC()); // -> swap +#elif defined(_MACGL) + DoBufferSwap(); +#else + glXSwapBuffers(display,window); +#endif + } + + iDrawnSomething=0; + + //----------------------------------------------------// + + if(lClearOnSwap) // clear buffer after swap? + { + GLclampf g,b,r; + + if(bDisplayNotSet) // -> set new vals + SetOGLDisplaySettings(1); + + g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col + b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f; + r=((GLclampf)RED(lClearOnSwapColor))/255.0f; + + glDisable(GL_SCISSOR_TEST); + glClearColor(r,g,b,128); // -> clear + glClear(uiBufferBits); + glEnable(GL_SCISSOR_TEST); + lClearOnSwap=0; // -> done + } + else + { + if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before + + if(iZBufferDepth) // clear zbuffer as well (if activated) + { + glDisable(GL_SCISSOR_TEST); + glClear(GL_DEPTH_BUFFER_BIT); + glEnable(GL_SCISSOR_TEST); + } + } + gl_z=0.0f; + + //----------------------------------------------------// + // additional uploads immediatly after swapping + + if(bNeedUploadAfter) // upload wanted? + { + bNeedUploadAfter=FALSE; + bNeedUploadTest=FALSE; + UploadScreen(-1); // -> upload + } + + if(bNeedUploadTest) + { + bNeedUploadTest=FALSE; + if(PSXDisplay.InterlacedTest && + //iOffscreenDrawing>2 && + PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && + PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && + PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && + PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) + { + PrepareFullScreenUpload(TRUE); + UploadScreen(TRUE); + } + } + + //----------------------------------------------------// + // rumbling (main emu pad effect) + + if(iRumbleTime) // shake screen by modifying view port + { + int i1=0,i2=0,i3=0,i4=0; + + iRumbleTime--; + if(iRumbleTime) + { + i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + } + + glViewport(rRatioRect.left+i1, + iResY-(rRatioRect.top+rRatioRect.bottom)+i2, + rRatioRect.right+i3, + rRatioRect.bottom+i4); + } + +#ifdef _WINDOWS + ReleaseDC(hWWindow,hdc); // ! important ! +#endif + + if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled +} + +//////////////////////////////////////////////////////////////////////// +// update front display: smaller update func, if something has changed +// in the frontbuffer... dirty, but hey... real men know no pain +//////////////////////////////////////////////////////////////////////// + +void updateFrontDisplay(void) +{ + if(PreviousPSXDisplay.Range.x0|| + PreviousPSXDisplay.Range.y0) + PaintBlackBorders(); + + if(iBlurBuffer) BlurBackBuffer(); + + if(iUseScanLines) SetScanLines(); + + if(usCursorActive) ShowGunCursor(); + + bFakeFrontBuffer=FALSE; + bRenderFrontBuffer=FALSE; + + if(gTexPicName) DisplayPic(); + if(ulKeybits&KEY_SHOWFPS) DisplayText(); + +#ifdef _WINDOWS + { // windows: + HDC hdc=GetDC(hWWindow); + wglMakeCurrent(hdc,GLCONTEXT); // -> make current again + if(iDrawnSomething) + SwapBuffers(wglGetCurrentDC()); // -> swap + ReleaseDC(hWWindow,hdc); // -> ! important ! + } +#elif defined (_MACGL) +if (iDrawnSomething){ + DoBufferSwap(); + } +#else + if(iDrawnSomething) // linux: + glXSwapBuffers(display,window); +#endif + + if(iBlurBuffer) UnBlurBackBuffer(); +} + +//////////////////////////////////////////////////////////////////////// +// check if update needed +//////////////////////////////////////////////////////////////////////// + +static void ChangeDispOffsetsX(void) // CENTER X +{ + int lx,l;short sO; + + if(!PSXDisplay.Range.x1) return; // some range given? + + l=PSXDisplay.DisplayMode.x; + + l*=(int)PSXDisplay.Range.x1; // some funky calculation + l/=2560;lx=l;l&=0xfffffff8; + + if(l==PreviousPSXDisplay.Range.x1) return; // some change? + + sO=PreviousPSXDisplay.Range.x0; // store old + + if(lx>=PSXDisplay.DisplayMode.x) // range bigger? + { + PreviousPSXDisplay.Range.x1= // -> take display width + PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.Range.x0=0; // -> start pos is 0 + } + else // range smaller? center it + { + PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned) + PreviousPSXDisplay.Range.x0= // -> calc start pos + (PSXDisplay.Range.x0-500)/8; + if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet + PreviousPSXDisplay.Range.x0=0; + + if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much + PSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x0= // -> adjust start + PSXDisplay.DisplayMode.x-lx; + PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width + } + } + + if(sO!=PreviousPSXDisplay.Range.x0) // something changed? + { + bDisplayNotSet=TRUE; // -> recalc display stuff + } +} + +//////////////////////////////////////////////////////////////////////// + +static void ChangeDispOffsetsY(void) // CENTER Y +{ + int iT;short sO; // store previous y size + + if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC + + if(PSXDisplay.Range.y0>=iT) // crossed the security line? :) + { + PreviousPSXDisplay.Range.y1= // -> store width + PSXDisplay.DisplayModeNew.y; + + sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset + if(sO<0) sO=0; + + PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too + } + else sO=0; // else no offset + + if(sO!=PreviousPSXDisplay.Range.y0) // something changed? + { + PreviousPSXDisplay.Range.y0=sO; + bDisplayNotSet=TRUE; // -> recalc display stuff + } +} + +//////////////////////////////////////////////////////////////////////// +// Aspect ratio of ogl screen: simply adjusting ogl view port +//////////////////////////////////////////////////////////////////////// + +void SetAspectRatio(void) +{ + float xs,ys,s;RECT r; + + if(!PSXDisplay.DisplayModeNew.x) return; + if(!PSXDisplay.DisplayModeNew.y) return; + + xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x; + ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y; + + s=min(xs,ys); + r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s); + r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s); + if(r.right > iResX) r.right = iResX; + if(r.bottom > iResY) r.bottom = iResY; + if(r.right < 1) r.right = 1; + if(r.bottom < 1) r.bottom = 1; + + r.left = (iResX-r.right)/2; + r.top = (iResY-r.bottom)/2; + + if(r.bottom new psx resolution + PSXDisplay.DisplayModeNew.y, 0, -1, 1); + if(bKeepRatio) SetAspectRatio(); + } + + bDisplayNotSet = TRUE; // re-calc offsets/display area + + bUp=FALSE; + if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off) + { + PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet + ResetTextureArea(FALSE); + bUp=TRUE; + } + + PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos + PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; + PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; + PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; + + PSXDisplay.DisplayEnd.x= // calc new ends + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + ChangeDispOffsetsX(); + + if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace) + + if(bUp) updateDisplay(); // yeah, real update (swap buffer) +} + +//////////////////////////////////////////////////////////////////////// +// window mode <-> fullscreen mode (windows) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void ChangeWindowMode(void) + { + GPUclose(); + bWindowMode=!bWindowMode; + GPUopen(hWWindow); + bChangeWinMode=FALSE; + } +#endif + +//////////////////////////////////////////////////////////////////////// +// swap update check (called by psx vsync function) +//////////////////////////////////////////////////////////////////////// + +static BOOL bSwapCheck(void) +{ + static int iPosCheck=0; + static PSXPoint_t pO; + static PSXPoint_t pD; + static int iDoAgain=0; + + if(PSXDisplay.DisplayPosition.x==pO.x && + PSXDisplay.DisplayPosition.y==pO.y && + PSXDisplay.DisplayEnd.x==pD.x && + PSXDisplay.DisplayEnd.y==pD.y) + iPosCheck++; + else iPosCheck=0; + + pO=PSXDisplay.DisplayPosition; + pD=PSXDisplay.DisplayEnd; + + if(iPosCheck<=4) return FALSE; + + iPosCheck=4; + + if(PSXDisplay.Interlaced) return FALSE; + + if (bNeedInterlaceUpdate|| + bNeedRGB24Update || + bNeedUploadAfter|| + bNeedUploadTest || + iDoAgain + ) + { + iDoAgain=0; + if(bNeedUploadAfter) + iDoAgain=1; + if(bNeedUploadTest && PSXDisplay.InterlacedTest) + iDoAgain=1; + + bDisplayNotSet = TRUE; + updateDisplay(); + + PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x; + PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y; + pO=PSXDisplay.DisplayPosition; + pD=PSXDisplay.DisplayEnd; + + return TRUE; + } + + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// +// gun cursor func: player=0-7, x=0-511, y=0-255 +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUcursor(int iPlayer,int x,int y) +{ + if(iPlayer<0) return; + if(iPlayer>7) return; + + usCursorActive|=(1<iGPUHeightMask) x=iGPUHeightMask; + if(y<0) y=0; + if(y>255) y=255; + + ptCursorPoint[iPlayer].x=x; + ptCursorPoint[iPlayer].y=y; +} + +//////////////////////////////////////////////////////////////////////// +// update lace is called every VSync. Basically we limit frame rate +// here, and in interlaced mode we swap ogl display buffers. +//////////////////////////////////////////////////////////////////////// + +static unsigned short usFirstPos=2; + +void CALLBACK GPUupdateLace(void) +{ + //if(!(dwActFixes&0x1000)) + // STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus) + + if(!(dwActFixes&128)) // normal frame limit func + CheckFrameRate(); + + if(iOffscreenDrawing==4) // special check if high offscreen drawing is on + { + if(bSwapCheck()) return; + } + + if(PSXDisplay.Interlaced) // interlaced mode? + { + STATUSREG^=0x80000000; + if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) + { + updateDisplay(); // -> swap buffers (new frame) + } + } + else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed? + { + updateFrontDisplay(); // -> update front buffer + } + else if(usFirstPos==1) // initial updates (after startup) + { + updateDisplay(); + } + +#if defined(_WINDOWS) || defined(_MACGL) + if(bChangeWinMode) ChangeWindowMode(); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// process read request from GPU status register +//////////////////////////////////////////////////////////////////////// + +uint32_t CALLBACK GPUreadStatus(void) +{ + if(dwActFixes&0x1000) // CC game fix + { + static int iNumRead=0; + if((iNumRead++)==2) + { + iNumRead=0; + STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross) + } + } + + 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... + { + iFakePrimBusy--; + + if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims + { + GPUIsBusy; + GPUIsNotReadyForCommands; + } + else + { + GPUIsIdle; + GPUIsReadyForCommands; + } + } + + return STATUSREG | (vBlank ? 0x80000000 : 0 );; +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU status register +// these are always single packet commands. +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteStatus(uint32_t gdata) +{ + uint32_t lCommand=(gdata>>24)&0xff; + +#ifdef _WINDOWS + if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus) +#endif + + ulStatusControl[lCommand]=gdata; + + switch(lCommand) + { + //--------------------------------------------------// + // reset gpu + case 0x00: + memset(ulGPUInfoVals, 0x00, 16 * sizeof(uint32_t)); + lGPUstatusRet = 0x14802000; + PSXDisplay.Disabled=1; + iDataWriteMode=iDataReadMode=DR_NORMAL; + PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; + drawX=drawY=0;drawW=drawH=0; + sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0; + usMirror=0; + GlobalTextAddrX=0;GlobalTextAddrY=0; + GlobalTextTP=0;GlobalTextABR=0; + PSXDisplay.RGB24=FALSE; + PSXDisplay.Interlaced=FALSE; + bUsingTWin = FALSE; + return; + + // dis/enable display + case 0x03: + PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; + PSXDisplay.Disabled = (gdata & 1); + + if(PSXDisplay.Disabled) + STATUSREG|=GPUSTATUS_DISPLAYDISABLED; + else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED; + + if (iOffscreenDrawing==4 && + PreviousPSXDisplay.Disabled && + !(PSXDisplay.Disabled)) + { + + if(!PSXDisplay.RGB24) + { + PrepareFullScreenUpload(TRUE); + UploadScreen(TRUE); + updateDisplay(); + } + } + + return; + + // setting transfer mode + case 0x04: + gdata &= 0x03; // only want the lower two bits + + iDataWriteMode=iDataReadMode=DR_NORMAL; + if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER; + if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER; + + STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits + STATUSREG|=(gdata << 29); // set the DMA bits according to the received data + + return; + + // setting display position + case 0x05: + { + short sx=(short)(gdata & 0x3ff); + short sy; + + if(iGPUHeight==1024) + { + if(dwGPUVersion==2) + sy = (short)((gdata>>12)&0x3ff); + else sy = (short)((gdata>>10)&0x3ff); + } + else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later + + if (sy & 0x200) + { + sy|=0xfc00; + PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double; + sy=0; + } + else PreviousPSXDisplay.DisplayModeNew.y=0; + + if(sx>1000) sx=0; + + if(usFirstPos) + { + usFirstPos--; + if(usFirstPos) + { + PreviousPSXDisplay.DisplayPosition.x = sx; + PreviousPSXDisplay.DisplayPosition.y = sy; + PSXDisplay.DisplayPosition.x = sx; + PSXDisplay.DisplayPosition.y = sy; + } + } + + if(dwActFixes&8) + { + if((!PSXDisplay.Interlaced) && + PreviousPSXDisplay.DisplayPosition.x == sx && + PreviousPSXDisplay.DisplayPosition.y == sy) + return; + + PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x; + PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.DisplayPosition.x = sx; + PreviousPSXDisplay.DisplayPosition.y = sy; + } + else + { + if((!PSXDisplay.Interlaced) && + PSXDisplay.DisplayPosition.x == sx && + PSXDisplay.DisplayPosition.y == sy) + return; + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + PSXDisplay.DisplayPosition.x = sx; + PSXDisplay.DisplayPosition.y = sy; + } + + PSXDisplay.DisplayEnd.x= + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + bDisplayNotSet = TRUE; + + if (!(PSXDisplay.Interlaced)) + { + updateDisplay(); + } + else + if(PSXDisplay.InterlacedTest && + ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)|| + (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y))) + PSXDisplay.InterlacedTest--; + + return; + } + + // setting width + case 0x06: + + PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff; + PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff; + + PSXDisplay.Range.x1-=PSXDisplay.Range.x0; + + ChangeDispOffsetsX(); + + return; + + // setting height + case 0x07: + + PreviousPSXDisplay.Height = PSXDisplay.Height; + + PSXDisplay.Range.y0=gdata & 0x3ff; + PSXDisplay.Range.y1=(gdata>>10) & 0x3ff; + + PSXDisplay.Height = PSXDisplay.Range.y1 - + PSXDisplay.Range.y0 + + PreviousPSXDisplay.DisplayModeNew.y; + + if (PreviousPSXDisplay.Height != PSXDisplay.Height) + { + PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; + ChangeDispOffsetsY(); + updateDisplayIfChanged(); + } + return; + + // setting display infos + case 0x08: + + PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; + + if (gdata&0x04) PSXDisplay.Double=2; + else PSXDisplay.Double=1; + PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; + + ChangeDispOffsetsY(); + + PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC + PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor + PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace + + STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits + + STATUSREG|= + (((gdata & 0x03) << 17) | + ((gdata & 0x40) << 10)); // set the width bits + + PreviousPSXDisplay.InterlacedNew=FALSE; + if (PSXDisplay.InterlacedNew) + { + if(!PSXDisplay.Interlaced) + { + PSXDisplay.InterlacedTest=2; + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.InterlacedNew=TRUE; + } + + STATUSREG|=GPUSTATUS_INTERLACED; + } + else + { + PSXDisplay.InterlacedTest=0; + STATUSREG&=~GPUSTATUS_INTERLACED; + } + + if (PSXDisplay.PAL) + STATUSREG|=GPUSTATUS_PAL; + else STATUSREG&=~GPUSTATUS_PAL; + + if (PSXDisplay.Double==2) + STATUSREG|=GPUSTATUS_DOUBLEHEIGHT; + else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT; + + if (PSXDisplay.RGB24New) + STATUSREG|=GPUSTATUS_RGB24; + else STATUSREG&=~GPUSTATUS_RGB24; + + updateDisplayIfChanged(); + + return; + + //--------------------------------------------------// + // ask about GPU version and other stuff + case 0x10: + + gdata&=0xff; + + switch(gdata) + { + case 0x02: + GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos + return; + case 0x03: + GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start + return; + case 0x04: + GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end + return; + case 0x05: + case 0x06: + GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset + return; + case 0x07: + if(dwGPUVersion==2) + GPUdataRet=0x01; + else GPUdataRet=0x02; // gpu type + return; + case 0x08: + case 0x0F: // some bios addr? + GPUdataRet=0xBFC03720; + return; + } + return; + //--------------------------------------------------// + } +} + +//////////////////////////////////////////////////////////////////////// +// vram read/write helpers +//////////////////////////////////////////////////////////////////////// + +BOOL bNeedWriteUpload=FALSE; + +static __inline void FinishedVRAMWrite(void) +{ + if(bNeedWriteUpload) + { + bNeedWriteUpload=FALSE; + CheckWriteUpdate(); + } + + // set register to NORMAL operation + iDataWriteMode = DR_NORMAL; + + // reset transfer values, to prevent mis-transfer of data + VRAMWrite.ColsRemaining = 0; + VRAMWrite.RowsRemaining = 0; +} + +static __inline void FinishedVRAMRead(void) +{ + // set register to NORMAL operation + iDataReadMode = DR_NORMAL; + // reset transfer values, to prevent mis-transfer of data + VRAMRead.x = 0; + VRAMRead.y = 0; + VRAMRead.Width = 0; + VRAMRead.Height = 0; + VRAMRead.ColsRemaining = 0; + VRAMRead.RowsRemaining = 0; + + // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER + STATUSREG&=~GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// vram read check ex (reading from card's back/frontbuffer if needed... +// slow!) +//////////////////////////////////////////////////////////////////////// + +void CheckVRamReadEx(int x, int y, int dx, int dy) +{ + unsigned short sArea; + int ux,uy,udx,udy,wx,wy; + unsigned short * p1, *p2; + float XS,YS; + unsigned char * ps; + unsigned char * px; + unsigned short s,sx; + + if(STATUSREG&GPUSTATUS_RGB24) return; + + if(((dx > PSXDisplay.DisplayPosition.x) && + (x < PSXDisplay.DisplayEnd.x) && + (dy > PSXDisplay.DisplayPosition.y) && + (y < PSXDisplay.DisplayEnd.y))) + sArea=0; + else + if((!(PSXDisplay.InterlacedTest) && + (dx > PreviousPSXDisplay.DisplayPosition.x) && + (x < PreviousPSXDisplay.DisplayEnd.x) && + (dy > PreviousPSXDisplay.DisplayPosition.y) && + (y < PreviousPSXDisplay.DisplayEnd.y))) + sArea=1; + else + { + return; + } + + ////////////// + + if(iRenderFVR) + { + bFullVRam=TRUE;iRenderFVR=2;return; + } + bFullVRam=TRUE;iRenderFVR=2; + + ////////////// + + p2=0; + + if(sArea==0) + { + ux=PSXDisplay.DisplayPosition.x; + uy=PSXDisplay.DisplayPosition.y; + udx=PSXDisplay.DisplayEnd.x-ux; + udy=PSXDisplay.DisplayEnd.y-uy; + if((PreviousPSXDisplay.DisplayEnd.x- + PreviousPSXDisplay.DisplayPosition.x)==udx && + (PreviousPSXDisplay.DisplayEnd.y- + PreviousPSXDisplay.DisplayPosition.y)==udy) + p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) + + PreviousPSXDisplay.DisplayPosition.x); + } + else + { + ux=PreviousPSXDisplay.DisplayPosition.x; + uy=PreviousPSXDisplay.DisplayPosition.y; + udx=PreviousPSXDisplay.DisplayEnd.x-ux; + udy=PreviousPSXDisplay.DisplayEnd.y-uy; + if((PSXDisplay.DisplayEnd.x- + PSXDisplay.DisplayPosition.x)==udx && + (PSXDisplay.DisplayEnd.y- + PSXDisplay.DisplayPosition.y)==udy) + p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) + + PSXDisplay.DisplayPosition.x); + } + + p1=(psxVuw + (1024*uy) + ux); + if(p1==p2) p2=0; + + x=0;y=0; + wx=dx=udx;wy=dy=udy; + + if(udx<=0) return; + if(udy<=0) return; + if(dx<=0) return; + if(dy<=0) return; + if(wx<=0) return; + if(wy<=0) return; + + XS=(float)rRatioRect.right/(float)wx; + YS=(float)rRatioRect.bottom/(float)wy; + + dx=(int)((float)(dx)*XS); + dy=(int)((float)(dy)*YS); + + if(dx>iResX) dx=iResX; + if(dy>iResY) dy=iResY; + + if(dx<=0) return; + if(dy<=0) return; + + // ogl y adjust + y=iResY-y-dy; + + x+=rRatioRect.left; + y-=rRatioRect.top; + + if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + + if(!sArea) glReadBuffer(GL_FRONT); + + glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); + + if(!sArea) glReadBuffer(GL_BACK); + + s=0; + + XS=(float)dx/(float)(udx); + YS=(float)dy/(float)(udy+1); + + for(y=udy;y>0;y--) + { + for(x=0;x=psxVuw && p1>3;px++; + s=sx; + sx=(*px)>>3;px++; + s|=sx<<5; + sx=(*px)>>3; + s|=sx<<10; + s&=~0x8000; + *p1=s; + } + if(p2>=psxVuw && p2 PSXDisplay.DisplayPosition.x) && + (x < PSXDisplay.DisplayEnd.x) && + (dy > PSXDisplay.DisplayPosition.y) && + (y < PSXDisplay.DisplayEnd.y))) + sArea=0; + else + if((!(PSXDisplay.InterlacedTest) && + (dx > PreviousPSXDisplay.DisplayPosition.x) && + (x < PreviousPSXDisplay.DisplayEnd.x) && + (dy > PreviousPSXDisplay.DisplayPosition.y) && + (y < PreviousPSXDisplay.DisplayEnd.y))) + sArea=1; + else + { + return; + } + + if(dwActFixes&0x40) + { + if(iRenderFVR) + { + bFullVRam=TRUE;iRenderFVR=2;return; + } + bFullVRam=TRUE;iRenderFVR=2; + } + + ux=x;uy=y;udx=dx;udy=dy; + + if(sArea==0) + { + x -=PSXDisplay.DisplayPosition.x; + dx-=PSXDisplay.DisplayPosition.x; + y -=PSXDisplay.DisplayPosition.y; + dy-=PSXDisplay.DisplayPosition.y; + wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x; + wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y; + } + else + { + x -=PreviousPSXDisplay.DisplayPosition.x; + dx-=PreviousPSXDisplay.DisplayPosition.x; + y -=PreviousPSXDisplay.DisplayPosition.y; + dy-=PreviousPSXDisplay.DisplayPosition.y; + wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x; + wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y; + } + if(x<0) {ux-=x;x=0;} + if(y<0) {uy-=y;y=0;} + if(dx>wx) {udx-=(dx-wx);dx=wx;} + if(dy>wy) {udy-=(dy-wy);dy=wy;} + udx-=ux; + udy-=uy; + + p=(psxVuw + (1024*uy) + ux); + + if(udx<=0) return; + if(udy<=0) return; + if(dx<=0) return; + if(dy<=0) return; + if(wx<=0) return; + if(wy<=0) return; + + XS=(float)rRatioRect.right/(float)wx; + YS=(float)rRatioRect.bottom/(float)wy; + + dx=(int)((float)(dx)*XS); + dy=(int)((float)(dy)*YS); + x=(int)((float)x*XS); + y=(int)((float)y*YS); + + dx-=x; + dy-=y; + + if(dx>iResX) dx=iResX; + if(dy>iResY) dy=iResY; + + if(dx<=0) return; + if(dy<=0) return; + + // ogl y adjust + y=iResY-y-dy; + + x+=rRatioRect.left; + y-=rRatioRect.top; + + if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + + if(bFront) glReadBuffer(GL_FRONT); + + glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); + + if(bFront) glReadBuffer(GL_BACK); + + XS=(float)dx/(float)(udx); + YS=(float)dy/(float)(udy+1); + + for(y=udy;y>0;y--) + { + for(x=0;x=psxVuw && p>3;px++; + s=sx; + sx=(*px)>>3;px++; + s|=sx<<5; + sx=(*px)>>3; + s|=sx<<10; + s&=~0x8000; + *p=s; + } + p++; + } + p += 1024 - udx; + } +} + +//////////////////////////////////////////////////////////////////////// +// core read from vram +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUreadDataMem(uint32_t *pMem, int iSize) +{ + int i; + + if(iDataReadMode!=DR_VRAMTRANSFER) return; + + GPUIsBusy; + + // adjust read ptr, if necessary + while(VRAMRead.ImagePtr>=psxVuw_eom) + VRAMRead.ImagePtr-=iGPUHeight*1024; + while(VRAMRead.ImagePtr1) && + !(iDrawnSomething==2 && + VRAMRead.x == VRAMWrite.x && + VRAMRead.y == VRAMWrite.y && + VRAMRead.Width == VRAMWrite.Width && + VRAMRead.Height == VRAMWrite.Height)) + CheckVRamRead(VRAMRead.x,VRAMRead.y, + VRAMRead.x+VRAMRead.RowsRemaining, + VRAMRead.y+VRAMRead.ColsRemaining, + TRUE); + + for(i=0;i 0) && (VRAMRead.RowsRemaining > 0)) + { + // lower 16 bit + GPUdataRet=(uint32_t)*VRAMRead.ImagePtr; + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining --; + + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + + // higher 16 bit (always, even if it's an odd width) + GPUdataRet|=(uint32_t)(*VRAMRead.ImagePtr)<<16; + *pMem++=GPUdataRet; + + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining--; + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + } + else {FinishedVRAMRead();goto ENDREAD;} + } + +ENDREAD: + GPUIsIdle; +} + +uint32_t CALLBACK GPUreadData(void) +{ + uint32_t l; + GPUreadDataMem(&l,1); + return GPUdataRet; +} + +//////////////////////////////////////////////////////////////////////// +// helper table to know how much data is used by drawing commands +//////////////////////////////////////////////////////////////////////// + +const unsigned char primTableCX[256] = +{ + // 00 + 0,0,3,0,0,0,0,0, + // 08 + 0,0,0,0,0,0,0,0, + // 10 + 0,0,0,0,0,0,0,0, + // 18 + 0,0,0,0,0,0,0,0, + // 20 + 4,4,4,4,7,7,7,7, + // 28 + 5,5,5,5,9,9,9,9, + // 30 + 6,6,6,6,9,9,9,9, + // 38 + 8,8,8,8,12,12,12,12, + // 40 + 3,3,3,3,0,0,0,0, + // 48 +// 5,5,5,5,6,6,6,6, //FLINE + 254,254,254,254,254,254,254,254, + // 50 + 4,4,4,4,0,0,0,0, + // 58 +// 7,7,7,7,9,9,9,9, // LINEG3 LINEG4 + 255,255,255,255,255,255,255,255, + // 60 + 3,3,3,3,4,4,4,4, // TILE SPRT + // 68 + 2,2,2,2,3,3,3,3, // TILE1 + // 70 + 2,2,2,2,3,3,3,3, + // 78 + 2,2,2,2,3,3,3,3, + // 80 + 4,0,0,0,0,0,0,0, + // 88 + 0,0,0,0,0,0,0,0, + // 90 + 0,0,0,0,0,0,0,0, + // 98 + 0,0,0,0,0,0,0,0, + // a0 + 3,0,0,0,0,0,0,0, + // a8 + 0,0,0,0,0,0,0,0, + // b0 + 0,0,0,0,0,0,0,0, + // b8 + 0,0,0,0,0,0,0,0, + // c0 + 3,0,0,0,0,0,0,0, + // c8 + 0,0,0,0,0,0,0,0, + // d0 + 0,0,0,0,0,0,0,0, + // d8 + 0,0,0,0,0,0,0,0, + // e0 + 0,1,1,1,1,1,1,0, + // e8 + 0,0,0,0,0,0,0,0, + // f0 + 0,0,0,0,0,0,0,0, + // f8 + 0,0,0,0,0,0,0,0 +}; + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU data register +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteDataMem(uint32_t *pMem, int iSize) +{ + unsigned char command; + uint32_t gdata=0; + int i=0; + GPUIsBusy; + GPUIsNotReadyForCommands; + +STARTVRAM: + + if(iDataWriteMode==DR_VRAMTRANSFER) + { + // make sure we are in vram + while(VRAMWrite.ImagePtr>=psxVuw_eom) + VRAMWrite.ImagePtr-=iGPUHeight*1024; + while(VRAMWrite.ImagePtr0) + { + while(VRAMWrite.RowsRemaining>0) + { + if(i>=iSize) {goto ENDVRAM;} + i++; + + gdata=*pMem++; + + *VRAMWrite.ImagePtr++ = (unsigned short)gdata; + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + + if(VRAMWrite.RowsRemaining <= 0) + { + VRAMWrite.ColsRemaining--; + if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width + { + gdata=(gdata&0xFFFF)|(((uint32_t)(*VRAMWrite.ImagePtr))<<16); + FinishedVRAMWrite(); + goto ENDVRAM; + } + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16); + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + } + + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining--; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + FinishedVRAMWrite(); + } + +ENDVRAM: + + if(iDataWriteMode==DR_NORMAL) + { + void (* *primFunc)(unsigned char *); + if(bSkipNextFrame) primFunc=primTableSkip; + else primFunc=primTableJ; + + for(;i>24) & 0xff); + + if(primTableCX[command]) + { + gpuDataC = primTableCX[command]; + gpuCommand = command; + gpuDataM[0] = gdata; + gpuDataP = 1; + } + else continue; + } + else + { + gpuDataM[gpuDataP] = gdata; + if(gpuDataC>128) + { + if((gpuDataC==254 && gpuDataP>=3) || + (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1))) + { + if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000) + gpuDataP=gpuDataC-1; + } + } + gpuDataP++; + } + + if(gpuDataP == gpuDataC) + { + gpuDataC=gpuDataP=0; + primFunc[gpuCommand]((unsigned char *)gpuDataM); + + if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games + iFakePrimBusy=4; + } + } + } + + GPUdataRet=gdata; + + GPUIsReadyForCommands; + GPUIsIdle; +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteData(uint32_t gdata) +{ + GPUwriteDataMem(&gdata,1); +} + +//////////////////////////////////////////////////////////////////////// +// call config dlg +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +long CALLBACK GPUconfigure(void) +{ + HWND hWP=GetActiveWindow(); + DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), + hWP,(DLGPROC)CfgDlgProc); + + return 0; +} + +#elif defined(_MACGL) +long CALLBACK GPUconfigure(void) +{ + DlgProc(); + return 0; +} +#else + +static void StartCfgTool(char *arg) // linux: start external cfg tool +{ + char cfg[256]; + struct stat buf; + + strcpy(cfg, "./cfgpeopsxgl"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgpeopsxgl", arg, NULL); + exit(0); + } + return; + } + + strcpy(cfg, "./cfg/cfgpeopsxgl"); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgpeopsxgl", arg, NULL); + exit(0); + } + return; + } + + sprintf(cfg, "%s/.pcsx/plugins/cfg/cfgpeopsxgl", getenv("HOME")); + if (stat(cfg, &buf) != -1) { + if (fork() == 0) { + execl(cfg, "cfgpeopsxgl", arg, NULL); + exit(0); + } + return; + } + + printf("ERROR: cfgpeopsxgl file not found!\n"); +} + +long CALLBACK GPUconfigure(void) +{ + StartCfgTool("CFG"); + return 0; +} + +#endif // def _WINDOWS / _MACGL + +//////////////////////////////////////////////////////////////////////// +// sets all kind of act fixes +//////////////////////////////////////////////////////////////////////// + +void SetFixes(void) +{ + ReInitFrameCap(); + + if(dwActFixes & 0x2000) + dispWidths[4]=384; + else dispWidths[4]=368; +} + +//////////////////////////////////////////////////////////////////////// +// Pete Special: make an 'intelligent' dma chain check (<-Tekken3) +//////////////////////////////////////////////////////////////////////// + +uint32_t lUsedAddr[3]; + +static __inline BOOL CheckForEndlessLoop(uint32_t laddr) +{ + if(laddr==lUsedAddr[1]) return TRUE; + if(laddr==lUsedAddr[2]) return TRUE; + + if(laddr 2000000) break; + if(CheckForEndlessLoop(addr)) break; + + count = baseAddrB[addr+3]; + + dmaMem=addr+4; + + if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); + + addr = baseAddrL[addr>>2]&0xffffff; + } + while (addr != 0xffffff); + + GPUIsIdle; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// show about dlg +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUabout(void) +{ +#ifdef _WINDOWS + HWND hWP=GetActiveWindow(); // to be sure + DialogBox(hInst,MAKEINTRESOURCE(IDD_DIALOG_ABOUT), + hWP,(DLGPROC)AboutDlgProc); +#elif defined(_MACGL) + + AboutDlgProc(); +#else + + StartCfgTool("ABOUT"); + +#endif +} + +//////////////////////////////////////////////////////////////////////// +// We are ever fine ;) +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUtest(void) +{ + // if test fails this function should return negative value for error (unable to continue) + // and positive value for warning (can continue but output might be crappy) + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// save state funcs +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUfreeze(uint32_t ulGetFreezeData,GPUFreeze_t * pF) +{ + if(ulGetFreezeData==2) + { + int lSlotNum=*((int *)pF); + if(lSlotNum<0) return 0; + if(lSlotNum>8) return 0; + lSelectedSlot=lSlotNum+1; + return 1; + } + + if(!pF) return 0; + if(pF->ulFreezeVersion!=1) return 0; + + if(ulGetFreezeData==1) + { + pF->ulStatus=STATUSREG; + memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t)); + memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); + + return 1; + } + + if(ulGetFreezeData!=0) return 0; + + STATUSREG=pF->ulStatus; + memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t)); + memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); + + ResetTextureArea(TRUE); + + GPUwriteStatus(ulStatusControl[0]); + GPUwriteStatus(ulStatusControl[1]); + GPUwriteStatus(ulStatusControl[2]); + GPUwriteStatus(ulStatusControl[3]); + GPUwriteStatus(ulStatusControl[8]); + GPUwriteStatus(ulStatusControl[6]); + GPUwriteStatus(ulStatusControl[7]); + GPUwriteStatus(ulStatusControl[5]); + GPUwriteStatus(ulStatusControl[4]); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +// special "emu infos" / "emu effects" functions +//////////////////////////////////////////////////////////////////////// + +//00 = black +//01 = white +//10 = red +//11 = transparent + +unsigned char cFont[10][120]= +{ +// 0 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 1 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x05,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x05,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 2 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 3 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 4 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x54,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x05,0x14,0x00,0x00, + 0x80,0x00,0x14,0x14,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 5 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x54,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 6 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x54,0x00,0x00, + 0x80,0x00,0x15,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 7 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 8 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 9 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x15,0x00,0x00, + 0x80,0x00,0x05,0x55,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x05,0x50,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +} +}; + +//////////////////////////////////////////////////////////////////////// + +static void PaintPicDot(unsigned char * p,unsigned char c) +{ + if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;} + if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} + if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} +} + +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUgetScreenPic(unsigned char * pMem) +{ + float XS,YS;int x,y,v; + unsigned char * ps, * px, * pf; + unsigned char c; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(unsigned char *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + + glReadBuffer(GL_FRONT); + + glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps); + + glReadBuffer(GL_BACK); + + XS=(float)iResX/128; + YS=(float)iResY/96; + pf=pMem; + + for(y=96;y>0;y--) + { + for(x=0;x<128;x++) + { + px=ps+(3*((int)((float)x * XS))+ + (3*iResX)*((int)((float)y*YS))); + *(pf+0)=*(px+2); + *(pf+1)=*(px+1); + *(pf+2)=*(px+0); + pf+=3; + } + } + + ///////////////////////////////////////////////////////////////////// + // generic number/border painter + + pf=pMem+(103*3); + + for(y=0;y<20;y++) + { + for(x=0;x<6;x++) + { + c=cFont[lSelectedSlot][x+y*6]; + v=(c&0xc0)>>6; + PaintPicDot(pf,(unsigned char)v);pf+=3; // paint the dots into the rect + v=(c&0x30)>>4; + PaintPicDot(pf,(unsigned char)v);pf+=3; + v=(c&0x0c)>>2; + PaintPicDot(pf,(unsigned char)v);pf+=3; + v=c&0x03; + PaintPicDot(pf,(unsigned char)v);pf+=3; + } + pf+=104*3; + } + + pf=pMem; + for(x=0;x<128;x++) + { + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0xff;*pf++=0xff; + } + pf=pMem; + for(y=0;y<96;y++) + { + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0xff;*pf++=0xff; + pf+=127*3; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUshowScreenPic(unsigned char * pMem) +{ + DestroyPic(); + if(pMem==0) return 0; + CreatePic(pMem); + return 0; +} + +//////////////////////////////////////////////////////////////////////// + +#if 0 +void CALLBACK GPUsetfix(uint32_t dwFixBits) +{ + dwEmuFixes=dwFixBits; +} +#endif + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUvisualVibration(uint32_t iSmall, uint32_t iBig) +{ + int iVibVal; + + if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width + iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x); + else iVibVal=1; + // big rumble: 4...15 sp ; small rumble 1...3 sp + if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10)); + else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10)); + + srand(timeGetTime()); // init rand (will be used in BufferSwap) + + iRumbleTime=15; // let the rumble last 16 buffer swaps +} + +//////////////////////////////////////////////////////////////////////// +// main emu can set display infos (A/M/G/D) +//////////////////////////////////////////////////////////////////////// + +#if 0 +void CALLBACK GPUdisplayFlags(uint32_t dwFlags) +{ + dwCoreFlags=dwFlags; +} +#endif + +void CALLBACK GPUvBlank( int val ) +{ + vBlank = val; +} -- cgit v1.2.3