X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=blobdiff_plain;f=plugins%2Fgpu-gles%2FgpuPlugin.c;fp=plugins%2Fgpu-gles%2FgpuPlugin.c;h=07f158c3201063be1462a5585389f78f3e72287b;hp=0000000000000000000000000000000000000000;hb=ce879073e4f228deec8bec5db8a2ff640636c88f;hpb=3a255ce52a55a2065429b8baad000c72aed31e97 diff --git a/plugins/gpu-gles/gpuPlugin.c b/plugins/gpu-gles/gpuPlugin.c new file mode 100644 index 00000000..07f158c3 --- /dev/null +++ b/plugins/gpu-gles/gpuPlugin.c @@ -0,0 +1,2960 @@ +/*************************************************************************** + 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. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +//#include "gpuStdafx.h" + +//#include + +#define _IN_GPU + +#ifdef _WINDOWS +#include "stdafx.h" +#include +#include +#include +#include +#include + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "prim.h" +#include "texture.h" +#include "fps.h" +#include "resource.h" +#else +#include +#include +#include +#include +#include "gpuExternals.h" +#include "gpuPlugin.h" +#include "gpuDraw.h" +#include "gpuTexture.h" +#include "gpuFps.h" +#include "gpuPrim.h" + +//#include "NoPic.h" + +#include "gpuStdafx.h" +#endif + +extern void ProcessEvents(); + +short g_m1=255,g_m2=255,g_m3=255; +short DrawSemiTrans=FALSE; +short Ymin; +short Ymax; + +short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; // global psx vertex coords +long GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP; +long GlobalTextREST,GlobalTextABR,GlobalTextPAGE; + +unsigned long dwGPUVersion=0; +int iGPUHeight=512; +int iGPUHeightMask=511; +int GlobalTextIL=0; +int iTileCheat=0; + +//////////////////////////////////////////////////////////////////////// +// memory image of the PSX vram +//////////////////////////////////////////////////////////////////////// + +u8 *psxVSecure; +u8 *psxVub; +signed char *psxVsb; +unsigned short *psxVuw; +unsigned short *psxVuw_eom; +signed short *psxVsw; +unsigned long *psxVul; +signed long *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 + +unsigned long ulStatusControl[256]; + +//////////////////////////////////////////////////////////////////////// +// global GPU vars +//////////////////////////////////////////////////////////////////////// + +static long GPUdataRet; +long lGPUstatusRet; +s8 szDispBuf[64]; + +static unsigned long gpuDataM[256]; +static u8 gpuCommand = 0; +static long gpuDataC = 0; +static long gpuDataP = 0; + +VRAMLoad_t VRAMWrite; +VRAMLoad_t VRAMRead; +int iDataWriteMode; +int iDataReadMode; + +long lClearOnSwap; +long 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; +long lSelectedSlot=0; +u8 * pGfxCardScreen=0; +int iBlurBuffer=0; +int iScanBlend=0; +int iRenderFVR=0; +int iNoScreenSaver=0; +unsigned long ulGPUInfoVals[16]; +int iFakePrimBusy = 0; +int iRumbleVal = 0; +int iRumbleTime = 0; + +//////////////////////////////////////////////////////////////////////// +// stuff to make this a true PDK module +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +s8 * CALLBACK PSEgetLibName(void) +{ + return "name"; +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return 1; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return 1<<16|1<<8|1; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// snapshot funcs (saves screen to bitmap / text infos into file) +//////////////////////////////////////////////////////////////////////// + +void ResizeWindow() +{ + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + glViewport(rRatioRect.left, // init viewport by ratio rect + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); + + glScissor(0, 0, iResX, iResY); // init clipping (fullscreen) + glEnable(GL_SCISSOR_TEST); + +#ifndef OWNSCALE + glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale" + glLoadIdentity(); + glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack +#endif + + glMatrixMode(GL_PROJECTION); // init projection with psx resolution + glLoadIdentity(); + glOrtho(0,PSXDisplay.DisplayMode.x, + PSXDisplay.DisplayMode.y, 0, -1, 1); + if (bKeepRatio) + SetAspectRatio(); +} + +s8 * GetConfigInfos(int hW) +{ +#ifdef _WINDOWS + HDC hdc;HGLRC hglrc; +#endif + s8 szO[2][4]={"off","on "}; + s8 szTxt[256]; + s8 * pB=(s8 *)malloc(32767); +/* + if(!pB) return NULL; + *pB=0; + //----------------------------------------------------// + strcat(pB,szTxt); + 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,(s8 *)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"); +// } + 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"); +// } + 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 [%08lx]\r\n",szO[bUseFixes],dwCfgFixes); + strcat(pB,szTxt); + //----------------------------------------------------// +*/ return pB; +} + +//////////////////////////////////////////////////////////////////////// +// save text infos to file +//////////////////////////////////////////////////////////////////////// + +void DoTextSnapShot(int iNum) +{ +} + +//////////////////////////////////////////////////////////////////////// +// saves screen bitmap to file +//////////////////////////////////////////////////////////////////////// + +void DoSnapShot(void) +{ +} + +#ifdef _WINDOWS +void CALLBACK GPUmakeSnapshot(void) +#else +void CALLBACK GPU_makeSnapshot(void) +#endif +{ + //bSnapShot = TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// GPU INIT... here starts it all (first func called by emu) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUinit() +#else +long CALLBACK GPU_init() +#endif +{ +memset(ulStatusControl,0,256*sizeof(unsigned long)); + +#ifdef _WINDOWS +iResX=240;iResY=320; +#endif +bChangeRes=FALSE; +#ifdef _WINDOWS +bWindowMode=TRUE; +#else +bWindowMode=FALSE; +#endif +#ifdef _WINDOWS +iWinSize=MAKELONG(iResX,iResY); +#endif + +bKeepRatio = TRUE; +// different ways of accessing PSX VRAM + +psxVSecure=(u8 *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security +if(!psxVSecure) return -1; + +psxVub=psxVSecure+512*1024; // security offset into double sized psx vram! +psxVsb=(signed char *)psxVub; +psxVsw=(signed short *)psxVub; +psxVsl=(signed long *)psxVub; +psxVuw=(unsigned short *)psxVub; +psxVul=(unsigned long *)psxVub; + +psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram + +memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024)); +memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long)); + +InitFrameCap(); // init frame rate stuff + +PSXDisplay.RGB24 = 0; // init vars +PreviousPSXDisplay.RGB24= 0; +PSXDisplay.Interlaced = 0; +PSXDisplay.InterlacedTest=0; +PSXDisplay.DrawOffset.x = 0; +PSXDisplay.DrawOffset.y = 0; +PSXDisplay.DrawArea.x0 = 0; +PSXDisplay.DrawArea.y0 = 0; +PSXDisplay.DrawArea.x1 = 320; +PSXDisplay.DrawArea.y1 = 240; +PSXDisplay.DisplayMode.x= 320; +PSXDisplay.DisplayMode.y= 240; +PSXDisplay.Disabled = FALSE; +PreviousPSXDisplay.Range.x0 =0; +PreviousPSXDisplay.Range.x1 =0; +PreviousPSXDisplay.Range.y0 =0; +PreviousPSXDisplay.Range.y1 =0; +PSXDisplay.Range.x0=0; +PSXDisplay.Range.x1=0; +PSXDisplay.Range.y0=0; +PSXDisplay.Range.y1=0; +PreviousPSXDisplay.DisplayPosition.x = 1; +PreviousPSXDisplay.DisplayPosition.y = 1; +PSXDisplay.DisplayPosition.x = 1; +PSXDisplay.DisplayPosition.y = 1; +PreviousPSXDisplay.DisplayModeNew.y=0; +PSXDisplay.Double=1; +GPUdataRet=0x400; + +PSXDisplay.DisplayModeNew.x=0; +PSXDisplay.DisplayModeNew.y=0; + +//PreviousPSXDisplay.Height = PSXDisplay.Height = 239; + +iDataWriteMode = DR_NORMAL; + +// Reset transfer values, to prevent mis-transfer of data +memset(&VRAMWrite,0,sizeof(VRAMLoad_t)); +memset(&VRAMRead,0,sizeof(VRAMLoad_t)); + +// device initialised already ! +//lGPUstatusRet = 0x74000000; + +STATUSREG = 0x14802000; +GPUIsIdle; +GPUIsReadyForCommands; + +return 0; +} + + +//////////////////////////////////////////////////////////////////////// +// GPU OPEN: funcs to open up the gpu display (Windows) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +void ChangeDesktop() // change destop resolution +{ + DEVMODE dv;long lRes,iTry=0; + + while(iTry<10) // keep on hammering... + { + memset(&dv,0,sizeof(DEVMODE)); + dv.dmSize=sizeof(DEVMODE); + dv.dmBitsPerPel=iColDepth; + dv.dmPelsWidth=iResX; + dv.dmPelsHeight=iResY; + + dv.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + + lRes=ChangeDisplaySettings(&dv,0); // ...hammering the anvil + + if(lRes==DISP_CHANGE_SUCCESSFUL) return; + iTry++;Sleep(10); + } +} + +//////////////////////////////////////////////////////////////////////// +// OPEN interface func: attention! +// some emus are calling this func in their main Window thread, +// but all other interface funcs (to draw stuff) in a different thread! +// that's a problem, since OGL is thread safe! Therefore we cannot +// initialize the OGL stuff right here, we simply set a "bIsFirstFrame = TRUE" +// flag, to initialize OGL on the first real draw call. +// btw, we also call this open func ourselfes, each time when the user +// is changing between fullscreen/window mode (ENTER key) +// btw part 2: in windows the plugin gets the window handle from the +// main emu, and doesn't create it's own window (if it would do it, +// some PAD or SPU plugins would not work anymore) +//////////////////////////////////////////////////////////////////////// + +HMENU hPSEMenu=NULL; + +long CALLBACK GPUopen(HWND hwndGPU) +#else +long CALLBACK GPU_open(int hwndGPU) +#endif +{ + #ifdef _WINDOWS + HDC hdc;RECT r;DEVMODE dv; + + hWWindow = hwndGPU; // store hwnd globally + #endif + // InitKeyHandler(); // init key handler (subclass window) + + + + + + #ifdef _WINDOWS + iResX=240;iResY=320; + #endif + iColDepth=32; + bChangeRes=FALSE; + #ifdef _WINDOWS + bWindowMode=TRUE; + #else + bWindowMode=FALSE; + #endif + bFullVRam=FALSE; + iFilterType=0; + // bAdvancedBlend=FALSE; + bDrawDither=FALSE; + // bUseLines=FALSE; + bUseFrameLimit=FALSE; + bUseFrameSkip=FALSE; + iFrameLimit=0; + fFrameRate=50.0f; + iOffscreenDrawing=0; + //bOpaquePass=FALSE; + //bUseAntiAlias=FALSE; + //iTexQuality=0; + #ifdef _WINDOWS + iWinSize=MAKELONG(iResX,iResY); + #endif + iUseMask=0; + iZBufferDepth=0; + bUseFastMdec=FALSE; + bUse15bitMdec=FALSE; + dwCfgFixes=0; + bUseFixes=FALSE; + // iUseScanLines=0; + iFrameTexType=0; + iFrameReadType=0; + //iShowFPS=0; + bKeepRatio=TRUE; + iScanBlend=0; + iVRamSize=0; + iTexGarbageCollection=0; + iBlurBuffer=0; + //iHiResTextures=0; + iNoScreenSaver=0; + //iForceVSync=0; + + + +#ifdef _WINDOWS + memset(&dv,0,sizeof(DEVMODE)); + dv.dmSize=sizeof(DEVMODE); + EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv); +#endif + bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows! + +#ifdef _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 + } +#endif + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + +#ifdef _WINDOWS + 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); +#endif + 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; +} + +//////////////////////////////////////////////////////////////////////// +// 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 GPU_close() // LINUX CLOSE +{ + GLcleanup(); // close OGL + + if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory + pGfxCardScreen=0; + +// osd_close_display(); // destroy display + + return 0; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// I shot the sheriff... last function called from emu +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUshutdown() +#else +long CALLBACK GPU_shutdown() +#endif +{ + 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); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// +// helper to draw scanlines +//////////////////////////////////////////////////////////////////////// + +__inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + +} + +//////////////////////////////////////////////////////////////////////// +// scanlines +//////////////////////////////////////////////////////////////////////// + +void SetScanLines(void) +{ +} + +//////////////////////////////////////////////////////////////////////// +// blur, babe, blur (heavy performance hit for a so-so fullscreen effect) +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +// 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 GPU_vSinc(void){ +updateDisplay(); +} +void updateDisplay(void) // UPDATE DISPLAY +{ +BOOL bBlur=FALSE; + +#ifdef _WINDOWS +HDC hdc=GetDC(hWWindow); // windows: +wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again +#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 +#else + eglSwapBuffers(display,surface); +#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 +#else + eglSwapBuffers(display,surface); +#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); + } + +//----------------------------------------------------// + + + +// 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 ! + } +#else +if(iDrawnSomething) // linux: + eglSwapBuffers(display,surface); +#endif + +//if(iBlurBuffer) UnBlurBackBuffer(); +} + +//////////////////////////////////////////////////////////////////////// +// check if update needed +//////////////////////////////////////////////////////////////////////// +void ChangeDispOffsetsX(void) // CENTER X +{ +long lx,l;short sO; + +if(!PSXDisplay.Range.x1) return; // some range given? + +l=PSXDisplay.DisplayMode.x; + +l*=(long)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 +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// 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; + +#ifdef _WINDOWS +void CALLBACK GPUupdateLace(void) +#else +void CALLBACK GPU_updateLace(void) +#endif +{ +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? + { + 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(); + } + +#ifdef _WINDOWS +if(bChangeWinMode) ChangeWindowMode(); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// process read request from GPU status register +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +unsigned long CALLBACK GPUreadStatus(void) +#else +unsigned long CALLBACK GPU_readStatus(void) +#endif +{ +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; +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU status register +// these are always single packet commands. +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUwriteStatus(unsigned long gdata) +#else +void CALLBACK GPU_writeStatus(unsigned long gdata) +#endif +{ +unsigned long 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(unsigned long)); + 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; + u8 * ps; + u8 * 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=(u8 *)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=(u8 *)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 +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUreadDataMem(unsigned int * pMem, int iSize) +#else +void CALLBACK GPU_readDataMem(unsigned long * pMem, int iSize) +#endif +{ +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=(unsigned long)*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|=(unsigned long)(*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; +} + +#ifdef _WINDOWS +unsigned long CALLBACK GPUreadData(void) +#else +unsigned long CALLBACK GPU_readData(void) +#endif +{ + unsigned long l; +#ifdef _WINDOWS + GPUreadDataMem(&l,1); +#else + GPU_readDataMem(&l,1); +#endif + return GPUdataRet; +} + +//////////////////////////////////////////////////////////////////////// +// helper table to know how much data is used by drawing commands +//////////////////////////////////////////////////////////////////////// + +const u8 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 +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize) +#else +void CALLBACK GPU_writeDataMem(unsigned long * pMem, int iSize) +#endif +{ +u8 command; +unsigned long 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)|(((unsigned long)(*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)(u8 *); + 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]((u8 *)gpuDataM); + + if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games + iFakePrimBusy=4; + } + } + } + +GPUdataRet=gdata; + +GPUIsReadyForCommands; +GPUIsIdle; +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUwriteData(unsigned long gdata) +#else +void CALLBACK GPU_writeData(unsigned long gdata) +#endif +{ +#ifdef _WINDOWS + GPUwriteDataMem(&gdata,1); +#else + GPU_writeDataMem(&gdata,1); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// this function will be removed soon (or 'soonish') (or never) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetMode(unsigned int gdata) +{ + // ignore old psemu setmode: + + // imageTransfer = gdata; + // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL; + // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL; +} + +// and this function will be removed soon as well, hehehe... +long CALLBACK GPUgetMode(void) +{ + // ignore old psemu setmode + // return imageTransfer; + +long iT=0; + +if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1; +if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2; + +return iT; +} + +//////////////////////////////////////////////////////////////////////// +// call config dlg (Windows + Linux) +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS + +/*#include + +void StartCfgTool(s8 * pCmdLine) // linux: start external cfg tool +{ + FILE * cf;s8 filename[255],t[255]; + + strcpy(filename,"cfg/cfgPeopsMesaGL"); // look in cfg sub folder first + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + getcwd(t,255); + chdir("cfg"); + sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine); + system(filename); + chdir(t); + } + else + { + strcpy(filename,"cfgPeopsMesaGL"); // look in current folder + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine); + system(filename); + } + else + { + sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + getcwd(t,255); + chdir(getenv("HOME")); + sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine); + system(filename); + chdir(t); + } + else printf("cfgPeopsMesaGL not found!\n"); + } + } +} +*/ +#endif + + +#ifdef _WINDOWS +long CALLBACK GPUconfigure(void) +#else +long CALLBACK GPU_configure(void) +#endif +{ + +#ifdef _WINDOWS +// HWND hWP=GetActiveWindow(); +// DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), +// hWP,(DLGPROC)CfgDlgProc); +#else + +// StartCfgTool("CFG"); + +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// 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) +//////////////////////////////////////////////////////////////////////// + +unsigned long lUsedAddr[3]; + +__inline BOOL CheckForEndlessLoop(unsigned long 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; + +#ifdef _WINDOWS + if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); +#else + if(count>0) GPU_writeDataMem(&baseAddrL[dmaMem>>2],count); +#endif + + addr = baseAddrL[addr>>2]&0xffffff; + } +while (addr != 0xffffff); + +GPUIsIdle; + +return 0; +} + +//////////////////////////////////////////////////////////////////////// +// show about dlg +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUabout(void) +#else +void CALLBACK GPU_about(void) +#endif +{ + +} + +//////////////////////////////////////////////////////////////////////// +// We are ever fine ;) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUtest(void) +#else +long CALLBACK GPU_test(void) +#endif +{ + // 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 +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF) +#else +long CALLBACK GPU_freeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF) +#endif +{ +if(ulGetFreezeData==2) + { + long lSlotNum=*((long *)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(unsigned long)); + memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); + + return 1; + } + +if(ulGetFreezeData!=0) return 0; + +STATUSREG=pF->ulStatus; +memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long)); +memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); + +ResetTextureArea(TRUE); + +#ifdef _WINDOWS + 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]); +#else + GPU_writeStatus(ulStatusControl[0]); + GPU_writeStatus(ulStatusControl[1]); + GPU_writeStatus(ulStatusControl[2]); + GPU_writeStatus(ulStatusControl[3]); + GPU_writeStatus(ulStatusControl[8]); + GPU_writeStatus(ulStatusControl[6]); + GPU_writeStatus(ulStatusControl[7]); + GPU_writeStatus(ulStatusControl[5]); + GPU_writeStatus(ulStatusControl[4]); +#endif + return 1; +} + +//////////////////////////////////////////////////////////////////////// +// special "emu infos" / "emu effects" functions +//////////////////////////////////////////////////////////////////////// + +//00 = black +//01 = white +//10 = red +//11 = transparent + +u8 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(u8 * p,u8 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;} +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUgetScreenPic(u8 * pMem) +#else +long CALLBACK GPU_getScreenPic(u8 * pMem) +#endif +{ + float XS,YS;int x,y,v; + u8 * ps, * px, * pf; + u8 c; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(u8 *)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,(u8)v);pf+=3; // paint the dots into the rect + v=(c&0x30)>>4; + PaintPicDot(pf,(u8)v);pf+=3; + v=(c&0x0c)>>2; + PaintPicDot(pf,(u8)v);pf+=3; + v=c&0x03; + PaintPicDot(pf,(u8)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; + } + +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUshowScreenPic(u8 * pMem) +#else +long CALLBACK GPU_showScreenPic(u8 * pMem) +#endif +{ +// DestroyPic(); +// if(pMem==0) return; +// CreatePic(pMem); +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetfix(unsigned long dwFixBits) +{ + dwEmuFixes=dwFixBits; +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long 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(unsigned long dwFlags) +{ +// dwCoreFlags=dwFlags; +}