diff options
Diffstat (limited to 'plugins/dfxvideo/gpu.c')
| -rwxr-xr-x[-rw-r--r--] | plugins/dfxvideo/gpu.c | 4634 |
1 files changed, 2317 insertions, 2317 deletions
diff --git a/plugins/dfxvideo/gpu.c b/plugins/dfxvideo/gpu.c index d2e24bee..72160435 100644..100755 --- a/plugins/dfxvideo/gpu.c +++ b/plugins/dfxvideo/gpu.c @@ -1,2317 +1,2317 @@ -/***************************************************************************
- gpu.c - description
- -------------------
- begin : Sun Oct 28 2001
- copyright : (C) 2001 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. *
- * *
- ***************************************************************************/
-
-#if !defined(_MACGL) && !defined(_WINDOWS)
-#include "config.h"
-#endif
-
-#define _IN_GPU
-
-#include "externals.h"
-#include "gpu.h"
-#include "draw.h"
-#include "cfg.h"
-#include "prim.h"
-#include "stdint.h"
-#include "psemu_plugin_defs.h"
-#include "menu.h"
-#include "key.h"
-#include "fps.h"
-#include "swap.h"
-
-#ifdef ENABLE_NLS
-#include <libintl.h>
-#include <locale.h>
-#define _(x) gettext(x)
-#define N_(x) (x)
-
-//If running under Mac OS X, use the Localizable.strings file instead.
-#elif defined(_MACOSX)
-#ifdef PCSXRCORE
-extern char* Pcsxr_locale_text(char* toloc);
-#define _(String) Pcsxr_locale_text(String)
-#define N_(String) String
-#else
-#ifndef PCSXRPLUG
-#warning please define the plug being built to use Mac OS X localization!
-#define _(msgid) msgid
-#define N_(msgid) msgid
-#else
-//Kludge to get the preprocessor to accept PCSXRPLUG as a variable.
-#define PLUGLOC_x(x,y) x ## y
-#define PLUGLOC_y(x,y) PLUGLOC_x(x,y)
-#define PLUGLOC PLUGLOC_y(PCSXRPLUG,_locale_text)
-extern const char* PLUGLOC(char* toloc);
-#define _(String) PLUGLOC(String)
-#define N_(String) String
-#endif
-#endif
-#else
-#define _(x) (x)
-#define N_(x) (x)
-#endif
-
-#ifdef _WINDOWS
-#include "resource.h"
-#include "record.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 = 17; // increase that with each version
-
-#if defined (_WINDOWS)
-static char *libraryName = N_("Soft Driver");
-static char *libraryInfo = N_("P.E.Op.S. Soft Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n");
-#elif defined (_MACGL)
-static char *libraryName = N_("SoftGL Driver");
-static char *libraryInfo = N_("P.E.Op.S. SoftGL Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n");
-#else
-static char *libraryName = N_("XVideo Driver");
-static char *libraryInfo = N_("P.E.Op.S. Xvideo Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n");
-#endif
-
-static char *PluginAuthor = N_("Pete Bernert and the P.E.Op.S. team");
-
-////////////////////////////////////////////////////////////////////////
-// 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;
-int32_t *psxVsl;
-
-////////////////////////////////////////////////////////////////////////
-// GPU globals
-////////////////////////////////////////////////////////////////////////
-
-static long lGPUdataRet;
-long lGPUstatusRet;
-char szDispBuf[64];
-char szMenuBuf[36];
-char szDebugText[512];
-uint32_t ulStatusControl[256];
-
-static uint32_t gpuDataM[256];
-static unsigned char gpuCommand = 0;
-static long gpuDataC = 0;
-static long gpuDataP = 0;
-
-VRAMLoad_t VRAMWrite;
-VRAMLoad_t VRAMRead;
-DATAREGISTERMODES DataWriteMode;
-DATAREGISTERMODES DataReadMode;
-
-BOOL bSkipNextFrame = FALSE;
-DWORD dwLaceCnt=0;
-int iColDepth;
-int iWindowMode;
-short sDispWidths[8] = {256,320,512,640,368,384,512,640};
-PSXDisplay_t PSXDisplay;
-PSXDisplay_t PreviousPSXDisplay;
-long lSelectedSlot=0;
-BOOL bChangeWinMode=FALSE;
-BOOL bDoLazyUpdate=FALSE;
-uint32_t lGPUInfoVals[16];
-static int iFakePrimBusy=0;
-uint32_t vBlank=0;
-int iRumbleVal=0;
-int iRumbleTime=0;
-
-#ifdef _WINDOWS
-
-////////////////////////////////////////////////////////////////////////
-// screensaver stuff: dynamically load kernel32.dll to avoid export dependeny
-////////////////////////////////////////////////////////////////////////
-
-int iStopSaver=0;
-HINSTANCE kernel32LibHandle = NULL;
-
-// A stub function, that does nothing .... but it does "nothing" well :)
-EXECUTION_STATE WINAPI STUB_SetThreadExecutionState(EXECUTION_STATE esFlags)
-{
- return esFlags;
-}
-
-// The dynamic version of the system call is prepended with a "D_"
-EXECUTION_STATE (WINAPI *D_SetThreadExecutionState)(EXECUTION_STATE esFlags) = STUB_SetThreadExecutionState;
-
-BOOL LoadKernel32(void)
-{
- // Get a handle to the kernel32.dll (which is actually already loaded)
- kernel32LibHandle = LoadLibrary("kernel32.dll");
-
- // If we've got a handle, then locate the entry point for the SetThreadExecutionState function
- if (kernel32LibHandle != NULL)
- {
- if ((D_SetThreadExecutionState = (EXECUTION_STATE (WINAPI *)(EXECUTION_STATE))GetProcAddress (kernel32LibHandle, "SetThreadExecutionState")) == NULL)
- D_SetThreadExecutionState = STUB_SetThreadExecutionState;
- }
-
- return TRUE;
-}
-
-BOOL FreeKernel32(void)
-{
- // Release the handle to kernel32.dll
- if (kernel32LibHandle != NULL)
- FreeLibrary(kernel32LibHandle);
-
- // Set to stub function, to avoid nasty suprises if called :)
- D_SetThreadExecutionState = STUB_SetThreadExecutionState;
-
- return TRUE;
-}
-#else
-
-// Linux: Stub the functions
-BOOL LoadKernel32(void)
-{
- return TRUE;
-}
-
-BOOL FreeKernel32(void)
-{
- return TRUE;
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////
-// some misc external display funcs
-////////////////////////////////////////////////////////////////////////
-
-#include <time.h>
-time_t tStart;
-
-void CALLBACK GPUdisplayText(char * pText) // some debug func
-{
- if(!pText) {szDebugText[0]=0;return;}
- if(strlen(pText)>511) return;
- time(&tStart);
- strcpy(szDebugText,pText);
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void CALLBACK GPUdisplayFlags(unsigned long dwFlags) // some info func
-{
- dwCoreFlags=dwFlags;
- BuildDispMenu(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 func
-////////////////////////////////////////////////////////////////////////
-
-char * pGetConfigInfos(int iCfg)
-{
- 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\r\n",libraryName,version,revision,build);
- strcat(pB,szTxt);
- sprintf(szTxt,"Author: %s\r\n\r\n",PluginAuthor);
- strcat(pB,szTxt);
- //----------------------------------------------------//
- if(iCfg && iWindowMode)
- 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(iWindowMode && iCfg)
- strcpy(szTxt,"Window mode\r\n");
- else
- if(iWindowMode)
- sprintf(szTxt,"Window mode - [%d Bit]\r\n",iDesktopCol);
- else
- sprintf(szTxt,"Fullscreen - [%d Bit]\r\n",iColDepth);
- strcat(pB,szTxt);
-
- sprintf(szTxt,"Stretch mode: %d\r\n",iUseNoStretchBlt);
- strcat(pB,szTxt);
- sprintf(szTxt,"Dither mode: %d\r\n\r\n",iUseDither);
- strcat(pB,szTxt);
- //----------------------------------------------------//
- sprintf(szTxt,"Framerate:\r\n- FPS limit: %s\r\n",szO[UseFrameLimit]);
- strcat(pB,szTxt);
- sprintf(szTxt,"- Frame skipping: %s",szO[UseFrameSkip]);
- strcat(pB,szTxt);
- if(iFastFwd) strcat(pB," (fast forward)");
- strcat(pB,"\r\n");
- 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);
- //----------------------------------------------------//
-#if !defined (_MACGL) && !defined (_WINDOWS)
- strcpy(szTxt,"Misc:\r\n- MaintainAspect: ");
- if(iMaintainAspect == 0) strcat(szTxt,"disabled");
- else
- if(iMaintainAspect == 1) strcat(szTxt,"enabled");
- strcat(szTxt,"\r\n");
- strcat(pB,szTxt);
-#endif
- sprintf(szTxt,"- Game fixes: %s [%08x]\r\n",szO[iUseFixes],dwCfgFixes);
- strcat(pB,szTxt);
- //----------------------------------------------------//
- return pB;
-}
-
-static void DoTextSnapShot(int iNum)
-{
- FILE *txtfile;
- char szTxt[256];
- char *pB;
-
-#ifdef _WINDOWS
- sprintf(szTxt,"snap\\pcsxr%04d.txt",iNum);
-#else
- sprintf(szTxt,"%s/pcsxr%04d.txt",getenv("HOME"),iNum);
-#endif
-
- if ((txtfile = fopen(szTxt, "wb")) == NULL)
- return;
-
- pB = pGetConfigInfos(0);
- if (pB)
- {
- fwrite(pB, strlen(pB), 1, txtfile);
- free(pB);
- }
- fclose(txtfile);
-}
-
-void CALLBACK GPUmakeSnapshot(void)
-{
- FILE *bmpfile;
- char filename[256];
- unsigned char header[0x36];
- long size, height;
- unsigned char line[1024 * 3];
- short i, j;
- unsigned char empty[2] = {0,0};
- unsigned short color;
- unsigned long snapshotnr = 0;
- unsigned char *pD;
-
- height = PreviousPSXDisplay.DisplayMode.y;
-
- size = height * PreviousPSXDisplay.Range.x1 * 3 + 0x38;
-
- // fill in proper values for BMP
-
- // hardcoded BMP header
- memset(header, 0, 0x36);
- header[0] = 'B';
- header[1] = 'M';
- header[2] = size & 0xff;
- header[3] = (size >> 8) & 0xff;
- header[4] = (size >> 16) & 0xff;
- header[5] = (size >> 24) & 0xff;
- header[0x0a] = 0x36;
- header[0x0e] = 0x28;
- header[0x12] = PreviousPSXDisplay.Range.x1 % 256;
- header[0x13] = PreviousPSXDisplay.Range.x1 / 256;
- header[0x16] = height % 256;
- header[0x17] = height / 256;
- header[0x1a] = 0x01;
- header[0x1c] = 0x18;
- header[0x26] = 0x12;
- header[0x27] = 0x0B;
- header[0x2A] = 0x12;
- header[0x2B] = 0x0B;
-
- // increment snapshot value & try to get filename
- do
- {
- snapshotnr++;
-#ifdef _WINDOWS
- sprintf(filename,"snap\\pcsxr%04ld.bmp",snapshotnr);
-#else
- sprintf(filename, "%s/pcsxr%04ld.bmp", getenv("HOME"), snapshotnr);
-#endif
-
- bmpfile = fopen(filename,"rb");
- if (bmpfile == NULL)
- break;
-
- fclose(bmpfile);
- }
- while(TRUE);
-
- // try opening new snapshot file
- if ((bmpfile = fopen(filename,"wb")) == NULL)
- return;
-
- fwrite(header, 0x36, 1, bmpfile);
- for (i = height + PSXDisplay.DisplayPosition.y - 1; i >= PSXDisplay.DisplayPosition.y; i--)
- {
- pD = (unsigned char *)&psxVuw[i * 1024 + PSXDisplay.DisplayPosition.x];
- for (j = 0; j < PreviousPSXDisplay.Range.x1; j++)
- {
- if (PSXDisplay.RGB24)
- {
- uint32_t lu = *(uint32_t *)pD;
- line[j * 3 + 2] = (unsigned char)RED(lu);
- line[j * 3 + 1] = (unsigned char)GREEN(lu);
- line[j * 3 + 0] = (unsigned char)BLUE(lu);
- pD += 3;
- }
- else
- {
- color = GETLE16(pD);
- line[j * 3 + 2] = (color << 3) & 0xf1;
- line[j * 3 + 1] = (color >> 2) & 0xf1;
- line[j * 3 + 0] = (color >> 7) & 0xf1;
- pD += 2;
- }
- }
- fwrite(line, PreviousPSXDisplay.Range.x1 * 3, 1, bmpfile);
- }
- fwrite(empty, 0x2, 1, bmpfile);
- fclose(bmpfile);
-
- DoTextSnapShot(snapshotnr);
-}
-
-////////////////////////////////////////////////////////////////////////
-// INIT, will be called after lib load... well, just do some var init...
-////////////////////////////////////////////////////////////////////////
-
-long CALLBACK GPUinit() // GPU INIT
-{
- memset(ulStatusControl,0,256*sizeof(uint32_t)); // init save state scontrol field
-
- szDebugText[0] = 0; // init debug text buffer
-
- psxVSecure = (unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security
- if (!psxVSecure)
- return -1;
-
- //!!! ATTENTION !!!
- psxVub=psxVSecure + 512 * 1024; // security offset into double sized psx vram!
-
- psxVsb=(signed char *)psxVub; // different ways of accessing PSX VRAM
- psxVsw=(signed short *)psxVub;
- psxVsl=(int32_t *)psxVub;
- psxVuw=(unsigned short *)psxVub;
- psxVul=(uint32_t *)psxVub;
-
- psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram
-
- memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024));
- memset(lGPUInfoVals,0x00,16*sizeof(uint32_t));
-
- SetFPSHandler();
-
- PSXDisplay.RGB24 = FALSE; // init some stuff
- PSXDisplay.Interlaced = FALSE;
- PSXDisplay.DrawOffset.x = 0;
- PSXDisplay.DrawOffset.y = 0;
- PSXDisplay.DisplayMode.x= 320;
- PSXDisplay.DisplayMode.y= 240;
- PreviousPSXDisplay.DisplayMode.x= 320;
- PreviousPSXDisplay.DisplayMode.y= 240;
- PSXDisplay.Disabled = FALSE;
- PreviousPSXDisplay.Range.x0 =0;
- PreviousPSXDisplay.Range.y0 =0;
- PSXDisplay.Range.x0=0;
- PSXDisplay.Range.x1=0;
- PreviousPSXDisplay.DisplayModeNew.y=0;
- PSXDisplay.Double = 1;
- lGPUdataRet = 0x400;
-
- DataWriteMode = 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 = 0x14802000;
- GPUIsIdle;
- GPUIsReadyForCommands;
- bDoVSyncUpdate = TRUE;
- vBlank = 0;
-
- // Get a handle for kernel32.dll, and access the required export function
- LoadKernel32();
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// Here starts all...
-////////////////////////////////////////////////////////////////////////
-
-#ifdef _WINDOWS
-long CALLBACK GPUopen(HWND hwndGPU) // GPU OPEN
-{
- hWGPU = hwndGPU; // store hwnd
-
- SetKeyHandler(); // sub-class window
-
- if(bChangeWinMode) ReadWinSizeConfig(); // alt+enter toggle?
- else // or first time startup?
- {
- ReadConfig(); // read registry
- InitFPS();
- }
-
- bIsFirstFrame = TRUE; // we have to init later
- bDoVSyncUpdate = TRUE;
-
- ulInitDisplay(); // setup direct draw
-
- if(iStopSaver)
- D_SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED|ES_CONTINUOUS);
-
-
- return 0;
-}
-
-#else
-
-long GPUopen(unsigned long * disp,char * CapText,char * CfgFile)
-{
- unsigned long d;
-
- pCaptionText=CapText;
-
-
- ReadConfig(); // read registry
-
- InitFPS();
-
- bIsFirstFrame = TRUE; // we have to init later
- bDoVSyncUpdate = TRUE;
-
- d=ulInitDisplay(); // setup x
-
- if(disp)
- *disp=d; // wanna x pointer? ok
-
- if(d) return 0;
- return -1;
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////
-// time to leave...
-////////////////////////////////////////////////////////////////////////
-
-long CALLBACK GPUclose() // GPU CLOSE
-{
-#ifdef _WINDOWS
- if(RECORD_RECORDING==TRUE) {RECORD_Stop();RECORD_RECORDING=FALSE;BuildDispMenu(0);}
-#endif
-
- ReleaseKeyHandler(); // de-subclass window
-
- CloseDisplay(); // shutdown direct draw
-
-#ifdef _WINDOWS
- if(iStopSaver)
- D_SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED);
-#endif
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// I shot the sheriff
-////////////////////////////////////////////////////////////////////////
-
-long CALLBACK GPUshutdown() // GPU SHUTDOWN
-{
- // screensaver: release the handle for kernel32.dll
- FreeKernel32();
-
- free(psxVSecure);
-
- return 0; // nothinh to do
-}
-
-////////////////////////////////////////////////////////////////////////
-// Update display (swap buffers)
-////////////////////////////////////////////////////////////////////////
-
-void updateDisplay(void) // UPDATE DISPLAY
-{
- if(PSXDisplay.Disabled) // disable?
- {
- DoClearFrontBuffer(); // -> clear frontbuffer
- return; // -> and bye
- }
-
- if(dwActFixes&32) // pc fps calculation fix
- {
- if(UseFrameLimit) PCFrameCap(); // -> brake
- if(UseFrameSkip || ulKeybits&KEY_SHOWFPS)
- PCcalcfps();
- }
-
- if(ulKeybits&KEY_SHOWFPS) // make fps display buf
- {
- sprintf(szDispBuf,"FPS %06.1f",fps_cur);
- }
-
- if(iFastFwd) // fastfwd ?
- {
- static int fpscount; UseFrameSkip=1;
-
- if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip
- if(fpscount%6) // -> skip 6/7 frames
- bSkipNextFrame = TRUE;
- else bSkipNextFrame = FALSE;
- fpscount++;
- if(fpscount >= (int)fFrameRateHz) fpscount = 0;
- return;
- }
-
- if(UseFrameSkip) // skip ?
- {
- if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip
- if(dwActFixes&0xa0) // -> pc fps calculation fix/old skipping fix
- {
- if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) // -> skip max one in a row
- {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;}
- else bSkipNextFrame = FALSE;
- }
- else FrameSkip();
- }
- else // no skip ?
- {
- DoBufferSwap(); // -> swap
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-// roughly emulated screen centering bits... not complete !!!
-////////////////////////////////////////////////////////////////////////
-
-void ChangeDispOffsetsX(void) // X CENTER
-{
- long lx,l;
-
- if(!PSXDisplay.Range.x1) return;
-
- l=PreviousPSXDisplay.DisplayMode.x;
-
- l*=(long)PSXDisplay.Range.x1;
- l/=2560;lx=l;l&=0xfffffff8;
-
- if(l==PreviousPSXDisplay.Range.y1) return; // abusing range.y1 for
- PreviousPSXDisplay.Range.y1=(short)l; // storing last x range and test
-
- if(lx>=PreviousPSXDisplay.DisplayMode.x)
- {
- PreviousPSXDisplay.Range.x1=
- (short)PreviousPSXDisplay.DisplayMode.x;
- PreviousPSXDisplay.Range.x0=0;
- }
- else
- {
- PreviousPSXDisplay.Range.x1=(short)l;
-
- PreviousPSXDisplay.Range.x0=
- (PSXDisplay.Range.x0-500)/8;
-
- if(PreviousPSXDisplay.Range.x0<0)
- PreviousPSXDisplay.Range.x0=0;
-
- if((PreviousPSXDisplay.Range.x0+lx)>
- PreviousPSXDisplay.DisplayMode.x)
- {
- PreviousPSXDisplay.Range.x0=
- (short)(PreviousPSXDisplay.DisplayMode.x-lx);
- PreviousPSXDisplay.Range.x0+=2; //???
-
- PreviousPSXDisplay.Range.x1+=(short)(lx-l);
-
-#ifndef _WINDOWS
- PreviousPSXDisplay.Range.x1-=2; // makes linux stretching easier
-#endif
- }
-
-#ifndef _WINDOWS
- // some linux alignment security
- PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0>>1;
- PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0<<1;
- PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1>>1;
- PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1<<1;
-#endif
-
- DoClearScreenBuffer();
- }
-
- bDoVSyncUpdate=TRUE;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void ChangeDispOffsetsY(void) // Y CENTER
-{
- int iT,iO=PreviousPSXDisplay.Range.y0;
- int iOldYOffset=PreviousPSXDisplay.DisplayModeNew.y;
-
-// new
-
- if((PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)>iGPUHeight)
- {
- int dy1=iGPUHeight-PreviousPSXDisplay.DisplayModeNew.x;
- int dy2=(PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)-iGPUHeight;
-
- if(dy1>=dy2)
- {
- PreviousPSXDisplay.DisplayModeNew.y=-dy2;
- }
- else
- {
- PSXDisplay.DisplayPosition.y=0;
- PreviousPSXDisplay.DisplayModeNew.y=-dy1;
- }
- }
- else PreviousPSXDisplay.DisplayModeNew.y=0;
-
-// eon
-
- if(PreviousPSXDisplay.DisplayModeNew.y!=iOldYOffset) // if old offset!=new offset: recalc height
- {
- PSXDisplay.Height = PSXDisplay.Range.y1 -
- PSXDisplay.Range.y0 +
- PreviousPSXDisplay.DisplayModeNew.y;
- PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double;
- }
-
-//
-
- if(PSXDisplay.PAL) iT=48; else iT=28;
-
- if(PSXDisplay.Range.y0>=iT)
- {
- PreviousPSXDisplay.Range.y0=
- (short)((PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double);
- if(PreviousPSXDisplay.Range.y0<0)
- PreviousPSXDisplay.Range.y0=0;
- PSXDisplay.DisplayModeNew.y+=
- PreviousPSXDisplay.Range.y0;
- }
- else
- PreviousPSXDisplay.Range.y0=0;
-
- if(iO!=PreviousPSXDisplay.Range.y0)
- {
- DoClearScreenBuffer();
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-// check if update needed
-////////////////////////////////////////////////////////////////////////
-
-void updateDisplayIfChanged(void) // UPDATE DISPLAY IF CHANGED
-{
- if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) &&
- (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x))
- {
- if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) &&
- (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) return;
- }
-
- PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos
-
- PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y;
- PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x;
- PreviousPSXDisplay.DisplayMode.x= // previous will hold
- min(640,PSXDisplay.DisplayMode.x); // max 640x512... that's
- PreviousPSXDisplay.DisplayMode.y= // the size of my
- min(512,PSXDisplay.DisplayMode.y); // back buffer surface
- PSXDisplay.Interlaced = PSXDisplay.InterlacedNew;
-
- PSXDisplay.DisplayEnd.x= // calc end of display
- 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 it
-
- if(UseFrameSkip) updateDisplay(); // stupid stuff when frame skipping enabled
-}
-
-////////////////////////////////////////////////////////////////////////
-
-#if defined(_WINDOWS)
-
-void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW
-{
- GPUclose();
- iWindowMode=!iWindowMode;
- GPUopen(hWGPU);
- bChangeWinMode=FALSE;
- bDoVSyncUpdate=TRUE;
-}
-
-#elif !defined (_MACGL)
-
-#include "draw.h"
-
-void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW
-{
- extern Display *display;
- extern Window window;
- extern int root_window_id;
- Screen *screen;
- XSizeHints hints;
- MotifWmHints mwmhints;
- Atom mwmatom;
-
- screen=DefaultScreenOfDisplay(display);
- iWindowMode=!iWindowMode;
-
- if(!iWindowMode) // fullscreen
- {
- mwmhints.flags=MWM_HINTS_DECORATIONS;
- mwmhints.functions=0;
- mwmhints.decorations=0;
- mwmhints.input_mode=0;
- mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0);
- XChangeProperty(display,window,mwmatom,mwmatom,32,
- PropModeReplace,(unsigned char *)&mwmhints,5);
-
- 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);
-
- {
- 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, root_window_id, 0,
- SubstructureRedirectMask | SubstructureNotifyMask, &xev);
- }
- } else {
- {
- 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] = 0;
- 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, root_window_id, 0,
- SubstructureRedirectMask | SubstructureNotifyMask, &xev);
- }
-
- mwmhints.flags=MWM_HINTS_DECORATIONS;
- mwmhints.functions=0;
- mwmhints.decorations=1;
- mwmhints.input_mode=0;
- mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0);
-
- //This shouldn't work on 64 bit longs, but it does...in fact, it breaks when I change all the mwmhints to int.
- //I don't pretend to understand it.
- XChangeProperty(display,window,mwmatom,mwmatom,32,
- PropModeReplace,(unsigned char *)&mwmhints,5);
-
- hints.flags=USPosition|USSize;
- hints.base_width = iResX;
- hints.base_height = iResY;
- XSetWMNormalHints(display,window,&hints);
-
- XResizeWindow(display,window,iResX,iResY);
-}
-
- DoClearScreenBuffer();
-
- bChangeWinMode=FALSE;
- bDoVSyncUpdate=TRUE;
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////
-// 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<<iPlayer);
-
- if(x<0) x=0;
- if(x>511) x=511;
- if(y<0) y=0;
- if(y>255) y=255;
-
- ptCursorPoint[iPlayer].x=x;
- ptCursorPoint[iPlayer].y=y;
-}
-
-////////////////////////////////////////////////////////////////////////
-// update lace is called evry VSync
-////////////////////////////////////////////////////////////////////////
-
-void CALLBACK GPUupdateLace(void) // VSYNC
-{
- //if(!(dwActFixes&1))
- //lGPUstatusRet^=0x80000000; // odd/even bit
-
- if(!(dwActFixes&32)) // std fps limitation?
- CheckFrameRate();
-
- if(PSXDisplay.Interlaced) // interlaced mode?
- {
- lGPUstatusRet^=0x80000000;
- if(bDoVSyncUpdate && PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0)
- {
- updateDisplay();
- }
- }
- else // non-interlaced?
- {
- if(dwActFixes&64) // lazy screen update fix
- {
- if(bDoLazyUpdate && !UseFrameSkip)
- updateDisplay();
- bDoLazyUpdate=FALSE;
- }
- else
- {
- if(bDoVSyncUpdate && !UseFrameSkip) // some primitives drawn?
- updateDisplay(); // -> update display
- }
- }
-
-#ifdef _WINDOWS
- if(RECORD_RECORDING)
- if(RECORD_WriteFrame()==FALSE)
- {RECORD_RECORDING=FALSE;RECORD_Stop();}
-#endif
-
-#ifndef _MACGL
- if(bChangeWinMode) ChangeWindowMode(); // toggle full - window mode
-#endif
-
- bDoVSyncUpdate=FALSE; // vsync done
-}
-
-////////////////////////////////////////////////////////////////////////
-// process read request from GPU status register
-////////////////////////////////////////////////////////////////////////
-
-
-uint32_t CALLBACK GPUreadStatus(void) // READ STATUS
-{
- if(dwActFixes&1)
- {
- static int iNumRead=0; // odd/even hack
- if((iNumRead++)==2)
- {
- iNumRead=0;
- lGPUstatusRet^=0x80000000; // interlaced bit toggle... we do it on every 3 read status... needed by some games (like ChronoCross) with old epsxe versions (1.5.2 and older)
- }
- }
-
- if(iFakePrimBusy) // 27.10.2007 - PETE : emulating some 'busy' while drawing... pfff
- {
- iFakePrimBusy--;
-
- if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims
- {
- GPUIsBusy;
- GPUIsNotReadyForCommands;
- }
- else
- {
- GPUIsIdle;
- GPUIsReadyForCommands;
- }
- }
- return lGPUstatusRet | (vBlank ? 0x80000000 : 0 );
-}
-
-////////////////////////////////////////////////////////////////////////
-// processes data send to GPU status register
-// these are always single packet commands.
-////////////////////////////////////////////////////////////////////////
-
-void CALLBACK GPUwriteStatus(uint32_t gdata) // WRITE STATUS
-{
- uint32_t lCommand=(gdata>>24)&0xff;
-
- ulStatusControl[lCommand]=gdata; // store command for freezing
-
- switch(lCommand)
- {
- //--------------------------------------------------//
- // reset gpu
- case 0x00:
- memset(lGPUInfoVals,0x00,16*sizeof(uint32_t));
- lGPUstatusRet=0x14802000;
- PSXDisplay.Disabled=1;
- DataWriteMode=DataReadMode=DR_NORMAL;
- PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0;
- drawX=drawY=0;drawW=drawH=0;
- sSetMask=0;lSetMask=0;bCheckMask=FALSE;
- 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)
- lGPUstatusRet|=GPUSTATUS_DISPLAYDISABLED;
- else lGPUstatusRet&=~GPUSTATUS_DISPLAYDISABLED;
- return;
-
- //--------------------------------------------------//
- // setting transfer mode
- case 0x04:
- gdata &= 0x03; // Only want the lower two bits
-
- DataWriteMode=DataReadMode=DR_NORMAL;
- if(gdata==0x02) DataWriteMode=DR_VRAMTRANSFER;
- if(gdata==0x03) DataReadMode =DR_VRAMTRANSFER;
- lGPUstatusRet&=~GPUSTATUS_DMABITS; // Clear the current settings of the DMA bits
- lGPUstatusRet|=(gdata << 29); // Set the DMA bits according to the received data
-
- return;
- //--------------------------------------------------//
- // setting display position
- case 0x05:
- {
- PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
- PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
-
-////////
-/*
- PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff);
- if (PSXDisplay.DisplayPosition.y & 0x200)
- PSXDisplay.DisplayPosition.y |= 0xfffffc00;
- if(PSXDisplay.DisplayPosition.y<0)
- {
- PreviousPSXDisplay.DisplayModeNew.y=PSXDisplay.DisplayPosition.y/PSXDisplay.Double;
- PSXDisplay.DisplayPosition.y=0;
- }
- else PreviousPSXDisplay.DisplayModeNew.y=0;
-*/
-
-// new
- if(iGPUHeight==1024)
- {
- if(dwGPUVersion==2)
- PSXDisplay.DisplayPosition.y = (short)((gdata>>12)&0x3ff);
- else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff);
- }
- else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x1ff);
-
- // store the same val in some helper var, we need it on later compares
- PreviousPSXDisplay.DisplayModeNew.x=PSXDisplay.DisplayPosition.y;
-
- if((PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)>iGPUHeight)
- {
- int dy1=iGPUHeight-PSXDisplay.DisplayPosition.y;
- int dy2=(PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)-iGPUHeight;
-
- if(dy1>=dy2)
- {
- PreviousPSXDisplay.DisplayModeNew.y=-dy2;
- }
- else
- {
- PSXDisplay.DisplayPosition.y=0;
- PreviousPSXDisplay.DisplayModeNew.y=-dy1;
- }
- }
- else PreviousPSXDisplay.DisplayModeNew.y=0;
-// eon
-
- PSXDisplay.DisplayPosition.x = (short)(gdata & 0x3ff);
- 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;
-
- bDoVSyncUpdate=TRUE;
-
- if (!(PSXDisplay.Interlaced)) // stupid frame skipping option
- {
- if(UseFrameSkip) updateDisplay();
- if(dwActFixes&64) bDoLazyUpdate=TRUE;
- }
- }return;
- //--------------------------------------------------//
- // setting width
- case 0x06:
-
- PSXDisplay.Range.x0=(short)(gdata & 0x7ff);
- PSXDisplay.Range.x1=(short)((gdata>>12) & 0xfff);
-
- PSXDisplay.Range.x1-=PSXDisplay.Range.x0;
-
- ChangeDispOffsetsX();
-
- return;
- //--------------------------------------------------//
- // setting height
- case 0x07:
- {
-
- PSXDisplay.Range.y0=(short)(gdata & 0x3ff);
- PSXDisplay.Range.y1=(short)((gdata>>10) & 0x3ff);
-
- PreviousPSXDisplay.Height = PSXDisplay.Height;
-
- 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 =
- sDispWidths[(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
-
- lGPUstatusRet&=~GPUSTATUS_WIDTHBITS; // Clear the width bits
- lGPUstatusRet|=
- (((gdata & 0x03) << 17) |
- ((gdata & 0x40) << 10)); // Set the width bits
-
- if(PSXDisplay.InterlacedNew)
- {
- if(!PSXDisplay.Interlaced)
- {
- PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x;
- PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y;
- }
- lGPUstatusRet|=GPUSTATUS_INTERLACED;
- }
- else lGPUstatusRet&=~GPUSTATUS_INTERLACED;
-
- if (PSXDisplay.PAL)
- lGPUstatusRet|=GPUSTATUS_PAL;
- else lGPUstatusRet&=~GPUSTATUS_PAL;
-
- if (PSXDisplay.Double==2)
- lGPUstatusRet|=GPUSTATUS_DOUBLEHEIGHT;
- else lGPUstatusRet&=~GPUSTATUS_DOUBLEHEIGHT;
-
- if (PSXDisplay.RGB24New)
- lGPUstatusRet|=GPUSTATUS_RGB24;
- else lGPUstatusRet&=~GPUSTATUS_RGB24;
-
- updateDisplayIfChanged();
-
- return;
- //--------------------------------------------------//
- // ask about GPU version and other stuff
- case 0x10:
-
- gdata&=0xff;
-
- switch(gdata)
- {
- case 0x02:
- lGPUdataRet=lGPUInfoVals[INFO_TW]; // tw infos
- return;
- case 0x03:
- lGPUdataRet=lGPUInfoVals[INFO_DRAWSTART]; // draw start
- return;
- case 0x04:
- lGPUdataRet=lGPUInfoVals[INFO_DRAWEND]; // draw end
- return;
- case 0x05:
- case 0x06:
- lGPUdataRet=lGPUInfoVals[INFO_DRAWOFF]; // draw offset
- return;
- case 0x07:
- if(dwGPUVersion==2)
- lGPUdataRet=0x01;
- else lGPUdataRet=0x02; // gpu type
- return;
- case 0x08:
- case 0x0F: // some bios addr?
- lGPUdataRet=0xBFC03720;
- return;
- }
- return;
- //--------------------------------------------------//
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-// vram read/write helpers, needed by LEWPY's optimized vram read/write :)
-////////////////////////////////////////////////////////////////////////
-
-static __inline void FinishedVRAMWrite(void)
-{
-/*
-// NEWX
- if(!PSXDisplay.Interlaced && UseFrameSkip) // stupid frame skipping
- {
- VRAMWrite.Width +=VRAMWrite.x;
- VRAMWrite.Height+=VRAMWrite.y;
- if(VRAMWrite.x<PSXDisplay.DisplayEnd.x &&
- VRAMWrite.Width >=PSXDisplay.DisplayPosition.x &&
- VRAMWrite.y<PSXDisplay.DisplayEnd.y &&
- VRAMWrite.Height>=PSXDisplay.DisplayPosition.y)
- updateDisplay();
- }
-*/
-
- // Set register to NORMAL operation
- DataWriteMode = DR_NORMAL;
- // Reset transfer values, to prevent mis-transfer of data
- VRAMWrite.x = 0;
- VRAMWrite.y = 0;
- VRAMWrite.Width = 0;
- VRAMWrite.Height = 0;
- VRAMWrite.ColsRemaining = 0;
- VRAMWrite.RowsRemaining = 0;
-}
-
-static __inline void FinishedVRAMRead(void)
-{
- // Set register to NORMAL operation
- DataReadMode = 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
- lGPUstatusRet&=~GPUSTATUS_READYFORVRAM;
-}
-
-////////////////////////////////////////////////////////////////////////
-// core read from vram
-////////////////////////////////////////////////////////////////////////
-
-void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize)
-{
- int i;
-
- if(DataReadMode!=DR_VRAMTRANSFER) return;
-
- GPUIsBusy;
-
- // adjust read ptr, if necessary
- while(VRAMRead.ImagePtr>=psxVuw_eom)
- VRAMRead.ImagePtr-=iGPUHeight*1024;
- while(VRAMRead.ImagePtr<psxVuw)
- VRAMRead.ImagePtr+=iGPUHeight*1024;
-
- for(i=0;i<iSize;i++)
- {
- // do 2 seperate 16bit reads for compatibility (wrap issues)
- if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0))
- {
- // lower 16 bit
- lGPUdataRet=(uint32_t)GETLE16(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)
- lGPUdataRet|=(uint32_t)GETLE16(VRAMRead.ImagePtr)<<16;
- PUTLE32(pMem, lGPUdataRet); pMem++;
-
- 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 lGPUdataRet;
-}
-
-////////////////////////////////////////////////////////////////////////
-// processes data send to GPU data register
-// extra table entries for fixing polyline troubles
-////////////////////////////////////////////////////////////////////////
-
-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, // GLINE
- 255,255,255,255,255,255,255,255,
- // 60
- 3,3,3,3,4,4,4,4,
- // 68
- 2,2,2,2,3,3,3,3, // 3=SPRITE1???
- // 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
-};
-
-void CALLBACK GPUwriteDataMem(uint32_t * pMem, int iSize)
-{
- unsigned char command;
- uint32_t gdata=0;
- int i=0;
- GPUIsBusy;
- GPUIsNotReadyForCommands;
-
-STARTVRAM:
-
- if(DataWriteMode==DR_VRAMTRANSFER)
- {
- BOOL bFinished=FALSE;
-
- // make sure we are in vram
- while(VRAMWrite.ImagePtr>=psxVuw_eom)
- VRAMWrite.ImagePtr-=iGPUHeight*1024;
- while(VRAMWrite.ImagePtr<psxVuw)
- VRAMWrite.ImagePtr+=iGPUHeight*1024;
-
- // now do the loop
- while(VRAMWrite.ColsRemaining>0)
- {
- while(VRAMWrite.RowsRemaining>0)
- {
- if(i>=iSize) {goto ENDVRAM;}
- i++;
-
- gdata=GETLE32(pMem); pMem++;
-
- PUTLE16(VRAMWrite.ImagePtr, (unsigned short)gdata); VRAMWrite.ImagePtr++;
- 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)GETLE16(VRAMWrite.ImagePtr))<<16);
- FinishedVRAMWrite();
- bDoVSyncUpdate=TRUE;
- goto ENDVRAM;
- }
- VRAMWrite.RowsRemaining = VRAMWrite.Width;
- VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
- }
-
- PUTLE16(VRAMWrite.ImagePtr, (unsigned short)(gdata>>16)); VRAMWrite.ImagePtr++;
- if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024;
- VRAMWrite.RowsRemaining --;
- }
-
- VRAMWrite.RowsRemaining = VRAMWrite.Width;
- VRAMWrite.ColsRemaining--;
- VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width;
- bFinished=TRUE;
- }
-
- FinishedVRAMWrite();
- if(bFinished) bDoVSyncUpdate=TRUE;
- }
-
-ENDVRAM:
-
- if(DataWriteMode==DR_NORMAL)
- {
- void (* *primFunc)(unsigned char *);
- if(bSkipNextFrame) primFunc=primTableSkip;
- else primFunc=primTableJ;
-
- for(;i<iSize;)
- {
- if(DataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM;
-
- gdata=GETLE32(pMem); pMem++; i++;
-
- if(gpuDataC == 0)
- {
- command = (unsigned char)((gdata>>24) & 0xff);
-
-//if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command);
-
- if(primTableCX[command])
- {
- gpuDataC = primTableCX[command];
- gpuCommand = command;
- PUTLE32(&gpuDataM[0], gdata);
- gpuDataP = 1;
- }
- else continue;
- }
- else
- {
- PUTLE32(&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&0x0400) // hack for emulating "gpu busy" in some games
- iFakePrimBusy=4;
- }
- }
- }
-
- lGPUdataRet=gdata;
-
- GPUIsReadyForCommands;
- GPUIsIdle;
-}
-
-////////////////////////////////////////////////////////////////////////
-
-void CALLBACK GPUwriteData(uint32_t gdata)
-{
- PUTLE32(&gdata, gdata);
- GPUwriteDataMem(&gdata,1);
-}
-
-////////////////////////////////////////////////////////////////////////
-// this functions will be removed soon (or 'soonish')... not really needed, but some emus want them
-////////////////////////////////////////////////////////////////////////
-
-void CALLBACK GPUsetMode(unsigned long gdata)
-{
-// Peops does nothing here...
-// DataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL;
-// DataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL;
-}
-
-long CALLBACK GPUgetMode(void)
-{
- long iT=0;
-
- if(DataWriteMode==DR_VRAMTRANSFER) iT|=0x1;
- if(DataReadMode ==DR_VRAMTRANSFER) iT|=0x2;
- return iT;
-}
-
-////////////////////////////////////////////////////////////////////////
-// call config dlg
-////////////////////////////////////////////////////////////////////////
-
-long CALLBACK GPUconfigure(void)
-{
-#ifdef _WINDOWS
- HWND hWP=GetActiveWindow();
-
- DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGSOFT),
- hWP,(DLGPROC)SoftDlgProc);
-#else
- SoftDlgProc();
-#endif
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// sets all kind of act fixes
-////////////////////////////////////////////////////////////////////////
-
-void SetFixes(void)
- {
-#ifdef _WINDOWS
- BOOL bOldPerformanceCounter=IsPerformanceCounter; // store curr timer mode
-
- if(dwActFixes&0x10) // check fix 0x10
- IsPerformanceCounter=FALSE;
- else SetFPSHandler();
-
- if(bOldPerformanceCounter!=IsPerformanceCounter) // we have change it?
- InitFPS(); // -> init fps again
-#endif
-
- if(dwActFixes&0x02) sDispWidths[4]=384;
- else sDispWidths[4]=368;
- }
-
-////////////////////////////////////////////////////////////////////////
-// process gpu commands
-////////////////////////////////////////////////////////////////////////
-
-unsigned long lUsedAddr[3];
-
-static __inline BOOL CheckForEndlessLoop(unsigned long laddr)
-{
- if(laddr==lUsedAddr[1]) return TRUE;
- if(laddr==lUsedAddr[2]) return TRUE;
-
- if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr;
- else lUsedAddr[2]=laddr;
- lUsedAddr[0]=laddr;
- return FALSE;
-}
-
-long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr)
-{
- uint32_t dmaMem;
- unsigned char * baseAddrB;
- short count;unsigned int DMACommandCounter = 0;
-
- GPUIsBusy;
-
- lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff;
-
- baseAddrB = (unsigned char*) baseAddrL;
-
- do
- {
- if(iGPUHeight==512) addr&=0x1FFFFC;
- if(DMACommandCounter++ > 2000000) break;
- if(CheckForEndlessLoop(addr)) break;
-
- count = baseAddrB[addr+3];
-
- dmaMem=addr+4;
-
- if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count);
-
- addr = GETLE32(&baseAddrL[addr>>2])&0xffffff;
- }
- while (addr != 0xffffff);
-
- GPUIsIdle;
-
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////
-// show about dlg
-////////////////////////////////////////////////////////////////////////
-
-#ifdef _WINDOWS
-BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch(uMsg)
- {
- case WM_COMMAND:
- {
- switch(LOWORD(wParam))
- {case IDOK: EndDialog(hW,TRUE);return TRUE;}
- }
- }
- return FALSE;
-}
-#endif
-
-void CALLBACK GPUabout(void) // ABOUT
-{
-#ifdef _WINDOWS
- HWND hWP=GetActiveWindow(); // to be sure
- DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT),
- hWP,(DLGPROC)AboutDlgProc);
-#else
- AboutDlgProc();
-#endif
-
- return;
-}
-
-////////////////////////////////////////////////////////////////////////
-// 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;
-}
-
-////////////////////////////////////////////////////////////////////////
-// Freeze
-////////////////////////////////////////////////////////////////////////
-
-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) // 2: info, which save slot is selected? (just for display)
- {
- long lSlotNum=*((long *)pF);
- if(lSlotNum<0) return 0;
- if(lSlotNum>8) return 0;
- lSelectedSlot=lSlotNum+1;
- BuildDispMenu(0);
- return 1;
- }
- //----------------------------------------------------//
- if(!pF) return 0; // some checks
- if(pF->ulFreezeVersion!=1) return 0;
-
- if(ulGetFreezeData==1) // 1: get data
- {
- pF->ulStatus=lGPUstatusRet;
- memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t));
- memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2);
-
- return 1;
- }
-
- if(ulGetFreezeData!=0) return 0; // 0: set data
-
- lGPUstatusRet=pF->ulStatus;
- memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t));
- memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2);
-
-// RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT
-
- GPUwriteStatus(ulStatusControl[0]);
- GPUwriteStatus(ulStatusControl[1]);
- GPUwriteStatus(ulStatusControl[2]);
- GPUwriteStatus(ulStatusControl[3]);
- GPUwriteStatus(ulStatusControl[8]); // try to repair things
- GPUwriteStatus(ulStatusControl[6]);
- GPUwriteStatus(ulStatusControl[7]);
- GPUwriteStatus(ulStatusControl[5]);
- GPUwriteStatus(ulStatusControl[4]);
-
- return 1;
-}
-
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////
-// SAVE STATE DISPLAY STUFF
-////////////////////////////////////////////////////////////////////////
-
-// font 0-9, 24x20 pixels, 1 byte = 4 dots
-// 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;} // black
- if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} // white
- if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} // red
- // transparent
-}
-
-////////////////////////////////////////////////////////////////////////
-// the main emu allocs 128x96x3 bytes, and passes a ptr
-// to it in pMem... the plugin has to fill it with
-// 8-8-8 bit BGR screen data (Win 24 bit BMP format
-// without header).
-// Beware: the func can be called at any time,
-// so you have to use the frontbuffer to get a fully
-// rendered picture
-
-#ifdef _WINDOWS
-
-void CALLBACK GPUgetScreenPic(unsigned char * pMem)
-{
- HRESULT ddrval;DDSURFACEDESC xddsd;unsigned char * pf;
- int x,y,c,v;RECT r;
- float XS,YS;
-
- memset(&xddsd, 0, sizeof(DDSURFACEDESC));
- xddsd.dwSize = sizeof(DDSURFACEDESC);
- xddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
- xddsd.dwWidth = iResX;
- xddsd.dwHeight = iResY;
-
- r.left=0; r.right =iResX;
- r.top=0; r.bottom=iResY;
-
- if(iWindowMode)
- {
- POINT Point={0,0};
- ClientToScreen(DX.hWnd,&Point);
- r.left+=Point.x;r.right+=Point.x;
- r.top+=Point.y;r.bottom+=Point.y;
- }
-
- XS=(float)iResX/128;
- YS=(float)iResY/96;
-
- ddrval=IDirectDrawSurface_Lock(DX.DDSPrimary,NULL, &xddsd, DDLOCK_WAIT|DDLOCK_READONLY, NULL);
-
- if(ddrval==DDERR_SURFACELOST) IDirectDrawSurface_Restore(DX.DDSPrimary);
-
- pf=pMem;
-
- if(ddrval==DD_OK)
- {
- unsigned char * ps=(unsigned char *)xddsd.lpSurface;
-
- if(iDesktopCol==16)
- {
- unsigned short sx;
- for(y=0;y<96;y++)
- {
- for(x=0;x<128;x++)
- {
- sx=*((unsigned short *)((ps)+
- r.top*xddsd.lPitch+
- (((int)((float)y*YS))*xddsd.lPitch)+
- r.left*2+
- ((int)((float)x*XS))*2));
- *(pf+0)=(sx&0x1f)<<3;
- *(pf+1)=(sx&0x7e0)>>3;
- *(pf+2)=(sx&0xf800)>>8;
- pf+=3;
- }
- }
- }
- else
- if(iDesktopCol==15)
- {
- unsigned short sx;
- for(y=0;y<96;y++)
- {
- for(x=0;x<128;x++)
- {
- sx=*((unsigned short *)((ps)+
- r.top*xddsd.lPitch+
- (((int)((float)y*YS))*xddsd.lPitch)+
- r.left*2+
- ((int)((float)x*XS))*2));
- *(pf+0)=(sx&0x1f)<<3;
- *(pf+1)=(sx&0x3e0)>>2;
- *(pf+2)=(sx&0x7c00)>>7;
- pf+=3;
- }
- }
- }
- else
- {
- unsigned long sx;
- for(y=0;y<96;y++)
- {
- for(x=0;x<128;x++)
- {
- sx=*((unsigned long *)((ps)+
- r.top*xddsd.lPitch+
- (((int)((float)y*YS))*xddsd.lPitch)+
- r.left*4+
- ((int)((float)x*XS))*4));
- *(pf+0)=(unsigned char)((sx&0xff));
- *(pf+1)=(unsigned char)((sx&0xff00)>>8);
- *(pf+2)=(unsigned char)((sx&0xff0000)>>16);
- pf+=3;
- }
- }
- }
- }
-
- IDirectDrawSurface_Unlock(DX.DDSPrimary,&xddsd);
-
- /////////////////////////////////////////////////////////////////////
- // generic number/border painter
-
- pf=pMem+(103*3); // offset to number rect
-
- for(y=0;y<20;y++) // loop the number rect pixel
- {
- for(x=0;x<6;x++)
- {
- c=cFont[lSelectedSlot][x+y*6]; // get 4 char dot infos at once (number depends on selected slot)
- 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; // next rect y line
- }
-
- pf=pMem; // ptr to first pos in 128x96 pic
- for(x=0;x<128;x++) // loop top/bottom line
- {
- *(pf+(95*128*3))=0x00;*pf++=0x00;
- *(pf+(95*128*3))=0x00;*pf++=0x00; // paint it red
- *(pf+(95*128*3))=0xff;*pf++=0xff;
- }
- pf=pMem; // ptr to first pos
- for(y=0;y<96;y++) // loop left/right line
- {
- *(pf+(127*3))=0x00;*pf++=0x00;
- *(pf+(127*3))=0x00;*pf++=0x00; // paint it red
- *(pf+(127*3))=0xff;*pf++=0xff;
- pf+=127*3; // offset to next line
- }
-}
-
-#else
-
-// LINUX version:
-
-extern char * Xpixels;
-
-void GPUgetScreenPic(unsigned char * pMem)
-{
-/*
- unsigned short c;unsigned char * pf;int x,y;
-
- float XS=(float)iResX/128;
- float YS=(float)iResY/96;
-
- pf=pMem;
- memset(pMem, 0, 128*96*3);
-
- if(Xpixels)
- {
- unsigned char * ps=(unsigned char *)Xpixels;
- {
- long lPitch=iResX<<2;
- uint32_t sx;
-
- for(y=0;y<96;y++)
- {
- for(x=0;x<128;x++)
- {
- sx=*((uint32_t *)((ps)+
- (((int)((float)y*YS))*lPitch)+
- ((int)((float)x*XS))*4));
- *(pf+0)=(sx&0xff);
- *(pf+1)=(sx&0xff00)>>8;
- *(pf+2)=(sx&0xff0000)>>16;
- pf+=3;
- }
- }
- }
- }
-
-
- /////////////////////////////////////////////////////////////////////
- // generic number/border painter
-
- pf=pMem+(103*3); // offset to number rect
-
- for(y=0;y<20;y++) // loop the number rect pixel
- {
- for(x=0;x<6;x++)
- {
- c=cFont[lSelectedSlot][x+y*6]; // get 4 char dot infos at once (number depends on selected slot)
- PaintPicDot(pf,(c&0xc0)>>6);pf+=3; // paint the dots into the rect
- PaintPicDot(pf,(c&0x30)>>4);pf+=3;
- PaintPicDot(pf,(c&0x0c)>>2);pf+=3;
- PaintPicDot(pf,(c&0x03)); pf+=3;
- }
- pf+=104*3; // next rect y line
- }
-
- pf=pMem; // ptr to first pos in 128x96 pic
- for(x=0;x<128;x++) // loop top/bottom line
- {
- *(pf+(95*128*3))=0x00;*pf++=0x00;
- *(pf+(95*128*3))=0x00;*pf++=0x00; // paint it red
- *(pf+(95*128*3))=0xff;*pf++=0xff;
- }
- pf=pMem; // ptr to first pos
- for(y=0;y<96;y++) // loop left/right line
- {
- *(pf+(127*3))=0x00;*pf++=0x00;
- *(pf+(127*3))=0x00;*pf++=0x00; // paint it red
- *(pf+(127*3))=0xff;*pf++=0xff;
- pf+=127*3; // offset to next line
- }
-*/
-}
-
-#endif
-
-////////////////////////////////////////////////////////////////////////
-// func will be called with 128x96x3 BGR data.
-// the plugin has to store the data and display
-// it in the upper right corner.
-// If the func is called with a NULL ptr, you can
-// release your picture data and stop displaying
-// the screen pic
-
-void CALLBACK GPUshowScreenPic(unsigned char * pMem)
-{
- DestroyPic(); // destroy old pic data
- if(pMem==0) return; // done
- CreatePic(pMem); // create new pic... don't free pMem or something like that... just read from it
-}
-
-void CALLBACK GPUsetfix(uint32_t dwFixBits)
-{
- dwEmuFixes=dwFixBits;
-}
-
-void CALLBACK GPUvBlank( int val )
-{
- vBlank = val;
-}
-
-void CALLBACK GPUvisualVibration(uint32_t iSmall, uint32_t iBig)
-{
- int iVibVal;
-
- if(PreviousPSXDisplay.DisplayMode.x) // calc min "shake pixel" from screen width
- iVibVal=max(1,iResX/PreviousPSXDisplay.DisplayMode.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));
-
- iRumbleTime=15; // let the rumble last 16 buffer swaps
-}
+/*************************************************************************** + gpu.c - description + ------------------- + begin : Sun Oct 28 2001 + copyright : (C) 2001 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. * + * * + ***************************************************************************/ + +#if !defined(_MACGL) && !defined(_WINDOWS) +#include "config.h" +#endif + +#define _IN_GPU + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "cfg.h" +#include "prim.h" +#include "stdint.h" +#include "psemu_plugin_defs.h" +#include "menu.h" +#include "key.h" +#include "fps.h" +#include "swap.h" + +#ifdef ENABLE_NLS +#include <libintl.h> +#include <locale.h> +#define _(x) gettext(x) +#define N_(x) (x) + +//If running under Mac OS X, use the Localizable.strings file instead. +#elif defined(_MACOSX) +#ifdef PCSXRCORE +extern char* Pcsxr_locale_text(char* toloc); +#define _(String) Pcsxr_locale_text(String) +#define N_(String) String +#else +#ifndef PCSXRPLUG +#warning please define the plug being built to use Mac OS X localization! +#define _(msgid) msgid +#define N_(msgid) msgid +#else +//Kludge to get the preprocessor to accept PCSXRPLUG as a variable. +#define PLUGLOC_x(x,y) x ## y +#define PLUGLOC_y(x,y) PLUGLOC_x(x,y) +#define PLUGLOC PLUGLOC_y(PCSXRPLUG,_locale_text) +extern const char* PLUGLOC(char* toloc); +#define _(String) PLUGLOC(String) +#define N_(String) String +#endif +#endif +#else +#define _(x) (x) +#define N_(x) (x) +#endif + +#ifdef _WINDOWS +#include "resource.h" +#include "record.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 = 17; // increase that with each version + +#if defined (_WINDOWS) +static char *libraryName = N_("Soft Driver"); +static char *libraryInfo = N_("P.E.Op.S. Soft Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"); +#elif defined (_MACGL) +static char *libraryName = N_("SoftGL Driver"); +static char *libraryInfo = N_("P.E.Op.S. SoftGL Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"); +#else +static char *libraryName = N_("XVideo Driver"); +static char *libraryInfo = N_("P.E.Op.S. Xvideo Driver V1.17\nCoded by Pete Bernert and the P.E.Op.S. team\n"); +#endif + +static char *PluginAuthor = N_("Pete Bernert and the P.E.Op.S. team"); + +//////////////////////////////////////////////////////////////////////// +// 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; +int32_t *psxVsl; + +//////////////////////////////////////////////////////////////////////// +// GPU globals +//////////////////////////////////////////////////////////////////////// + +static long lGPUdataRet; +long lGPUstatusRet; +char szDispBuf[64]; +char szMenuBuf[36]; +char szDebugText[512]; +uint32_t ulStatusControl[256]; + +static uint32_t gpuDataM[256]; +static unsigned char gpuCommand = 0; +static long gpuDataC = 0; +static long gpuDataP = 0; + +VRAMLoad_t VRAMWrite; +VRAMLoad_t VRAMRead; +DATAREGISTERMODES DataWriteMode; +DATAREGISTERMODES DataReadMode; + +BOOL bSkipNextFrame = FALSE; +DWORD dwLaceCnt=0; +int iColDepth; +int iWindowMode; +short sDispWidths[8] = {256,320,512,640,368,384,512,640}; +PSXDisplay_t PSXDisplay; +PSXDisplay_t PreviousPSXDisplay; +long lSelectedSlot=0; +BOOL bChangeWinMode=FALSE; +BOOL bDoLazyUpdate=FALSE; +uint32_t lGPUInfoVals[16]; +static int iFakePrimBusy=0; +uint32_t vBlank=0; +int iRumbleVal=0; +int iRumbleTime=0; + +#ifdef _WINDOWS + +//////////////////////////////////////////////////////////////////////// +// screensaver stuff: dynamically load kernel32.dll to avoid export dependeny +//////////////////////////////////////////////////////////////////////// + +int iStopSaver=0; +HINSTANCE kernel32LibHandle = NULL; + +// A stub function, that does nothing .... but it does "nothing" well :) +EXECUTION_STATE WINAPI STUB_SetThreadExecutionState(EXECUTION_STATE esFlags) +{ + return esFlags; +} + +// The dynamic version of the system call is prepended with a "D_" +EXECUTION_STATE (WINAPI *D_SetThreadExecutionState)(EXECUTION_STATE esFlags) = STUB_SetThreadExecutionState; + +BOOL LoadKernel32(void) +{ + // Get a handle to the kernel32.dll (which is actually already loaded) + kernel32LibHandle = LoadLibrary("kernel32.dll"); + + // If we've got a handle, then locate the entry point for the SetThreadExecutionState function + if (kernel32LibHandle != NULL) + { + if ((D_SetThreadExecutionState = (EXECUTION_STATE (WINAPI *)(EXECUTION_STATE))GetProcAddress (kernel32LibHandle, "SetThreadExecutionState")) == NULL) + D_SetThreadExecutionState = STUB_SetThreadExecutionState; + } + + return TRUE; +} + +BOOL FreeKernel32(void) +{ + // Release the handle to kernel32.dll + if (kernel32LibHandle != NULL) + FreeLibrary(kernel32LibHandle); + + // Set to stub function, to avoid nasty suprises if called :) + D_SetThreadExecutionState = STUB_SetThreadExecutionState; + + return TRUE; +} +#else + +// Linux: Stub the functions +BOOL LoadKernel32(void) +{ + return TRUE; +} + +BOOL FreeKernel32(void) +{ + return TRUE; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// some misc external display funcs +//////////////////////////////////////////////////////////////////////// + +#include <time.h> +time_t tStart; + +void CALLBACK GPUdisplayText(char * pText) // some debug func +{ + if(!pText) {szDebugText[0]=0;return;} + if(strlen(pText)>511) return; + time(&tStart); + strcpy(szDebugText,pText); +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUdisplayFlags(unsigned long dwFlags) // some info func +{ + dwCoreFlags=dwFlags; + BuildDispMenu(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 func +//////////////////////////////////////////////////////////////////////// + +char * pGetConfigInfos(int iCfg) +{ + 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\r\n",libraryName,version,revision,build); + strcat(pB,szTxt); + sprintf(szTxt,"Author: %s\r\n\r\n",PluginAuthor); + strcat(pB,szTxt); + //----------------------------------------------------// + if(iCfg && iWindowMode) + 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(iWindowMode && iCfg) + strcpy(szTxt,"Window mode\r\n"); + else + if(iWindowMode) + sprintf(szTxt,"Window mode - [%d Bit]\r\n",iDesktopCol); + else + sprintf(szTxt,"Fullscreen - [%d Bit]\r\n",iColDepth); + strcat(pB,szTxt); + + sprintf(szTxt,"Stretch mode: %d\r\n",iUseNoStretchBlt); + strcat(pB,szTxt); + sprintf(szTxt,"Dither mode: %d\r\n\r\n",iUseDither); + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Framerate:\r\n- FPS limit: %s\r\n",szO[UseFrameLimit]); + strcat(pB,szTxt); + sprintf(szTxt,"- Frame skipping: %s",szO[UseFrameSkip]); + strcat(pB,szTxt); + if(iFastFwd) strcat(pB," (fast forward)"); + strcat(pB,"\r\n"); + 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); + //----------------------------------------------------// +#if !defined (_MACGL) && !defined (_WINDOWS) + strcpy(szTxt,"Misc:\r\n- MaintainAspect: "); + if(iMaintainAspect == 0) strcat(szTxt,"disabled"); + else + if(iMaintainAspect == 1) strcat(szTxt,"enabled"); + strcat(szTxt,"\r\n"); + strcat(pB,szTxt); +#endif + sprintf(szTxt,"- Game fixes: %s [%08x]\r\n",szO[iUseFixes],dwCfgFixes); + strcat(pB,szTxt); + //----------------------------------------------------// + return pB; +} + +static void DoTextSnapShot(int iNum) +{ + FILE *txtfile; + char szTxt[256]; + char *pB; + +#ifdef _WINDOWS + sprintf(szTxt,"snap\\pcsxr%04d.txt",iNum); +#else + sprintf(szTxt,"%s/pcsxr%04d.txt",getenv("HOME"),iNum); +#endif + + if ((txtfile = fopen(szTxt, "wb")) == NULL) + return; + + pB = pGetConfigInfos(0); + if (pB) + { + fwrite(pB, strlen(pB), 1, txtfile); + free(pB); + } + fclose(txtfile); +} + +void CALLBACK GPUmakeSnapshot(void) +{ + FILE *bmpfile; + char filename[256]; + unsigned char header[0x36]; + long size, height; + unsigned char line[1024 * 3]; + short i, j; + unsigned char empty[2] = {0,0}; + unsigned short color; + unsigned long snapshotnr = 0; + unsigned char *pD; + + height = PreviousPSXDisplay.DisplayMode.y; + + size = height * PreviousPSXDisplay.Range.x1 * 3 + 0x38; + + // fill in proper values for BMP + + // hardcoded BMP header + memset(header, 0, 0x36); + header[0] = 'B'; + header[1] = 'M'; + header[2] = size & 0xff; + header[3] = (size >> 8) & 0xff; + header[4] = (size >> 16) & 0xff; + header[5] = (size >> 24) & 0xff; + header[0x0a] = 0x36; + header[0x0e] = 0x28; + header[0x12] = PreviousPSXDisplay.Range.x1 % 256; + header[0x13] = PreviousPSXDisplay.Range.x1 / 256; + header[0x16] = height % 256; + header[0x17] = height / 256; + header[0x1a] = 0x01; + header[0x1c] = 0x18; + header[0x26] = 0x12; + header[0x27] = 0x0B; + header[0x2A] = 0x12; + header[0x2B] = 0x0B; + + // increment snapshot value & try to get filename + do + { + snapshotnr++; +#ifdef _WINDOWS + sprintf(filename,"snap\\pcsxr%04ld.bmp",snapshotnr); +#else + sprintf(filename, "%s/pcsxr%04ld.bmp", getenv("HOME"), snapshotnr); +#endif + + bmpfile = fopen(filename,"rb"); + if (bmpfile == NULL) + break; + + fclose(bmpfile); + } + while(TRUE); + + // try opening new snapshot file + if ((bmpfile = fopen(filename,"wb")) == NULL) + return; + + fwrite(header, 0x36, 1, bmpfile); + for (i = height + PSXDisplay.DisplayPosition.y - 1; i >= PSXDisplay.DisplayPosition.y; i--) + { + pD = (unsigned char *)&psxVuw[i * 1024 + PSXDisplay.DisplayPosition.x]; + for (j = 0; j < PreviousPSXDisplay.Range.x1; j++) + { + if (PSXDisplay.RGB24) + { + uint32_t lu = *(uint32_t *)pD; + line[j * 3 + 2] = (unsigned char)RED(lu); + line[j * 3 + 1] = (unsigned char)GREEN(lu); + line[j * 3 + 0] = (unsigned char)BLUE(lu); + pD += 3; + } + else + { + color = GETLE16(pD); + line[j * 3 + 2] = (color << 3) & 0xf1; + line[j * 3 + 1] = (color >> 2) & 0xf1; + line[j * 3 + 0] = (color >> 7) & 0xf1; + pD += 2; + } + } + fwrite(line, PreviousPSXDisplay.Range.x1 * 3, 1, bmpfile); + } + fwrite(empty, 0x2, 1, bmpfile); + fclose(bmpfile); + + DoTextSnapShot(snapshotnr); +} + +//////////////////////////////////////////////////////////////////////// +// INIT, will be called after lib load... well, just do some var init... +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUinit() // GPU INIT +{ + memset(ulStatusControl,0,256*sizeof(uint32_t)); // init save state scontrol field + + szDebugText[0] = 0; // init debug text buffer + + psxVSecure = (unsigned char *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security + if (!psxVSecure) + return -1; + + //!!! ATTENTION !!! + psxVub=psxVSecure + 512 * 1024; // security offset into double sized psx vram! + + psxVsb=(signed char *)psxVub; // different ways of accessing PSX VRAM + psxVsw=(signed short *)psxVub; + psxVsl=(int32_t *)psxVub; + psxVuw=(unsigned short *)psxVub; + psxVul=(uint32_t *)psxVub; + + psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram + + memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024)); + memset(lGPUInfoVals,0x00,16*sizeof(uint32_t)); + + SetFPSHandler(); + + PSXDisplay.RGB24 = FALSE; // init some stuff + PSXDisplay.Interlaced = FALSE; + PSXDisplay.DrawOffset.x = 0; + PSXDisplay.DrawOffset.y = 0; + PSXDisplay.DisplayMode.x= 320; + PSXDisplay.DisplayMode.y= 240; + PreviousPSXDisplay.DisplayMode.x= 320; + PreviousPSXDisplay.DisplayMode.y= 240; + PSXDisplay.Disabled = FALSE; + PreviousPSXDisplay.Range.x0 =0; + PreviousPSXDisplay.Range.y0 =0; + PSXDisplay.Range.x0=0; + PSXDisplay.Range.x1=0; + PreviousPSXDisplay.DisplayModeNew.y=0; + PSXDisplay.Double = 1; + lGPUdataRet = 0x400; + + DataWriteMode = 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 = 0x14802000; + GPUIsIdle; + GPUIsReadyForCommands; + bDoVSyncUpdate = TRUE; + vBlank = 0; + + // Get a handle for kernel32.dll, and access the required export function + LoadKernel32(); + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// Here starts all... +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUopen(HWND hwndGPU) // GPU OPEN +{ + hWGPU = hwndGPU; // store hwnd + + SetKeyHandler(); // sub-class window + + if(bChangeWinMode) ReadWinSizeConfig(); // alt+enter toggle? + else // or first time startup? + { + ReadConfig(); // read registry + InitFPS(); + } + + bIsFirstFrame = TRUE; // we have to init later + bDoVSyncUpdate = TRUE; + + ulInitDisplay(); // setup direct draw + + if(iStopSaver) + D_SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED|ES_CONTINUOUS); + + + return 0; +} + +#else + +long GPUopen(unsigned long * disp,char * CapText,char * CfgFile) +{ + unsigned long d; + + pCaptionText=CapText; + + + ReadConfig(); // read registry + + InitFPS(); + + bIsFirstFrame = TRUE; // we have to init later + bDoVSyncUpdate = TRUE; + + d=ulInitDisplay(); // setup x + + if(disp) + *disp=d; // wanna x pointer? ok + + if(d) return 0; + return -1; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// time to leave... +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUclose() // GPU CLOSE +{ +#ifdef _WINDOWS + if(RECORD_RECORDING==TRUE) {RECORD_Stop();RECORD_RECORDING=FALSE;BuildDispMenu(0);} +#endif + + ReleaseKeyHandler(); // de-subclass window + + CloseDisplay(); // shutdown direct draw + +#ifdef _WINDOWS + if(iStopSaver) + D_SetThreadExecutionState(ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED); +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// I shot the sheriff +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUshutdown() // GPU SHUTDOWN +{ + // screensaver: release the handle for kernel32.dll + FreeKernel32(); + + free(psxVSecure); + + return 0; // nothinh to do +} + +//////////////////////////////////////////////////////////////////////// +// Update display (swap buffers) +//////////////////////////////////////////////////////////////////////// + +void updateDisplay(void) // UPDATE DISPLAY +{ + if(PSXDisplay.Disabled) // disable? + { + DoClearFrontBuffer(); // -> clear frontbuffer + return; // -> and bye + } + + if(dwActFixes&32) // pc fps calculation fix + { + if(UseFrameLimit) PCFrameCap(); // -> brake + if(UseFrameSkip || ulKeybits&KEY_SHOWFPS) + PCcalcfps(); + } + + if(ulKeybits&KEY_SHOWFPS) // make fps display buf + { + sprintf(szDispBuf,"FPS %06.1f",fps_cur); + } + + if(iFastFwd) // fastfwd ? + { + static int fpscount; UseFrameSkip=1; + + if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip + if(fpscount%6) // -> skip 6/7 frames + bSkipNextFrame = TRUE; + else bSkipNextFrame = FALSE; + fpscount++; + if(fpscount >= (int)fFrameRateHz) fpscount = 0; + return; + } + + if(UseFrameSkip) // skip ? + { + if(!bSkipNextFrame) DoBufferSwap(); // -> to skip or not to skip + if(dwActFixes&0xa0) // -> pc fps calculation fix/old skipping fix + { + if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) // -> skip max one in a row + {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} + else bSkipNextFrame = FALSE; + } + else FrameSkip(); + } + else // no skip ? + { + DoBufferSwap(); // -> swap + } +} + +//////////////////////////////////////////////////////////////////////// +// roughly emulated screen centering bits... not complete !!! +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsX(void) // X CENTER +{ + long lx,l; + + if(!PSXDisplay.Range.x1) return; + + l=PreviousPSXDisplay.DisplayMode.x; + + l*=(long)PSXDisplay.Range.x1; + l/=2560;lx=l;l&=0xfffffff8; + + if(l==PreviousPSXDisplay.Range.y1) return; // abusing range.y1 for + PreviousPSXDisplay.Range.y1=(short)l; // storing last x range and test + + if(lx>=PreviousPSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x1= + (short)PreviousPSXDisplay.DisplayMode.x; + PreviousPSXDisplay.Range.x0=0; + } + else + { + PreviousPSXDisplay.Range.x1=(short)l; + + PreviousPSXDisplay.Range.x0= + (PSXDisplay.Range.x0-500)/8; + + if(PreviousPSXDisplay.Range.x0<0) + PreviousPSXDisplay.Range.x0=0; + + if((PreviousPSXDisplay.Range.x0+lx)> + PreviousPSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x0= + (short)(PreviousPSXDisplay.DisplayMode.x-lx); + PreviousPSXDisplay.Range.x0+=2; //??? + + PreviousPSXDisplay.Range.x1+=(short)(lx-l); + +#ifndef _WINDOWS + PreviousPSXDisplay.Range.x1-=2; // makes linux stretching easier +#endif + } + +#ifndef _WINDOWS + // some linux alignment security + PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0>>1; + PreviousPSXDisplay.Range.x0=PreviousPSXDisplay.Range.x0<<1; + PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1>>1; + PreviousPSXDisplay.Range.x1=PreviousPSXDisplay.Range.x1<<1; +#endif + + DoClearScreenBuffer(); + } + + bDoVSyncUpdate=TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsY(void) // Y CENTER +{ + int iT,iO=PreviousPSXDisplay.Range.y0; + int iOldYOffset=PreviousPSXDisplay.DisplayModeNew.y; + +// new + + if((PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)>iGPUHeight) + { + int dy1=iGPUHeight-PreviousPSXDisplay.DisplayModeNew.x; + int dy2=(PreviousPSXDisplay.DisplayModeNew.x+PSXDisplay.DisplayModeNew.y)-iGPUHeight; + + if(dy1>=dy2) + { + PreviousPSXDisplay.DisplayModeNew.y=-dy2; + } + else + { + PSXDisplay.DisplayPosition.y=0; + PreviousPSXDisplay.DisplayModeNew.y=-dy1; + } + } + else PreviousPSXDisplay.DisplayModeNew.y=0; + +// eon + + if(PreviousPSXDisplay.DisplayModeNew.y!=iOldYOffset) // if old offset!=new offset: recalc height + { + PSXDisplay.Height = PSXDisplay.Range.y1 - + PSXDisplay.Range.y0 + + PreviousPSXDisplay.DisplayModeNew.y; + PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; + } + +// + + if(PSXDisplay.PAL) iT=48; else iT=28; + + if(PSXDisplay.Range.y0>=iT) + { + PreviousPSXDisplay.Range.y0= + (short)((PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double); + if(PreviousPSXDisplay.Range.y0<0) + PreviousPSXDisplay.Range.y0=0; + PSXDisplay.DisplayModeNew.y+= + PreviousPSXDisplay.Range.y0; + } + else + PreviousPSXDisplay.Range.y0=0; + + if(iO!=PreviousPSXDisplay.Range.y0) + { + DoClearScreenBuffer(); + } +} + +//////////////////////////////////////////////////////////////////////// +// check if update needed +//////////////////////////////////////////////////////////////////////// + +void updateDisplayIfChanged(void) // UPDATE DISPLAY IF CHANGED +{ + if ((PSXDisplay.DisplayMode.y == PSXDisplay.DisplayModeNew.y) && + (PSXDisplay.DisplayMode.x == PSXDisplay.DisplayModeNew.x)) + { + if((PSXDisplay.RGB24 == PSXDisplay.RGB24New) && + (PSXDisplay.Interlaced == PSXDisplay.InterlacedNew)) return; + } + + PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos + + PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; + PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; + PreviousPSXDisplay.DisplayMode.x= // previous will hold + min(640,PSXDisplay.DisplayMode.x); // max 640x512... that's + PreviousPSXDisplay.DisplayMode.y= // the size of my + min(512,PSXDisplay.DisplayMode.y); // back buffer surface + PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; + + PSXDisplay.DisplayEnd.x= // calc end of display + 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 it + + if(UseFrameSkip) updateDisplay(); // stupid stuff when frame skipping enabled +} + +//////////////////////////////////////////////////////////////////////// + +#if defined(_WINDOWS) + +void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW +{ + GPUclose(); + iWindowMode=!iWindowMode; + GPUopen(hWGPU); + bChangeWinMode=FALSE; + bDoVSyncUpdate=TRUE; +} + +#elif !defined (_MACGL) + +#include "draw.h" + +void ChangeWindowMode(void) // TOGGLE FULLSCREEN - WINDOW +{ + extern Display *display; + extern Window window; + extern int root_window_id; + Screen *screen; + XSizeHints hints; + MotifWmHints mwmhints; + Atom mwmatom; + + screen=DefaultScreenOfDisplay(display); + iWindowMode=!iWindowMode; + + if(!iWindowMode) // fullscreen + { + mwmhints.flags=MWM_HINTS_DECORATIONS; + mwmhints.functions=0; + mwmhints.decorations=0; + mwmhints.input_mode=0; + mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); + XChangeProperty(display,window,mwmatom,mwmatom,32, + PropModeReplace,(unsigned char *)&mwmhints,5); + + 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); + + { + 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, root_window_id, 0, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } + } else { + { + 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] = 0; + 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, root_window_id, 0, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); + } + + mwmhints.flags=MWM_HINTS_DECORATIONS; + mwmhints.functions=0; + mwmhints.decorations=1; + mwmhints.input_mode=0; + mwmatom=XInternAtom(display,"_MOTIF_WM_HINTS",0); + + //This shouldn't work on 64 bit longs, but it does...in fact, it breaks when I change all the mwmhints to int. + //I don't pretend to understand it. + XChangeProperty(display,window,mwmatom,mwmatom,32, + PropModeReplace,(unsigned char *)&mwmhints,5); + + hints.flags=USPosition|USSize; + hints.base_width = iResX; + hints.base_height = iResY; + XSetWMNormalHints(display,window,&hints); + + XResizeWindow(display,window,iResX,iResY); +} + + DoClearScreenBuffer(); + + bChangeWinMode=FALSE; + bDoVSyncUpdate=TRUE; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// 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<<iPlayer); + + if(x<0) x=0; + if(x>511) x=511; + if(y<0) y=0; + if(y>255) y=255; + + ptCursorPoint[iPlayer].x=x; + ptCursorPoint[iPlayer].y=y; +} + +//////////////////////////////////////////////////////////////////////// +// update lace is called evry VSync +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUupdateLace(void) // VSYNC +{ + //if(!(dwActFixes&1)) + //lGPUstatusRet^=0x80000000; // odd/even bit + + if(!(dwActFixes&32)) // std fps limitation? + CheckFrameRate(); + + if(PSXDisplay.Interlaced) // interlaced mode? + { + lGPUstatusRet^=0x80000000; + if(bDoVSyncUpdate && PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) + { + updateDisplay(); + } + } + else // non-interlaced? + { + if(dwActFixes&64) // lazy screen update fix + { + if(bDoLazyUpdate && !UseFrameSkip) + updateDisplay(); + bDoLazyUpdate=FALSE; + } + else + { + if(bDoVSyncUpdate && !UseFrameSkip) // some primitives drawn? + updateDisplay(); // -> update display + } + } + +#ifdef _WINDOWS + if(RECORD_RECORDING) + if(RECORD_WriteFrame()==FALSE) + {RECORD_RECORDING=FALSE;RECORD_Stop();} +#endif + +#ifndef _MACGL + if(bChangeWinMode) ChangeWindowMode(); // toggle full - window mode +#endif + + bDoVSyncUpdate=FALSE; // vsync done +} + +//////////////////////////////////////////////////////////////////////// +// process read request from GPU status register +//////////////////////////////////////////////////////////////////////// + + +uint32_t CALLBACK GPUreadStatus(void) // READ STATUS +{ + if(dwActFixes&1) + { + static int iNumRead=0; // odd/even hack + if((iNumRead++)==2) + { + iNumRead=0; + lGPUstatusRet^=0x80000000; // interlaced bit toggle... we do it on every 3 read status... needed by some games (like ChronoCross) with old epsxe versions (1.5.2 and older) + } + } + + if(iFakePrimBusy) // 27.10.2007 - PETE : emulating some 'busy' while drawing... pfff + { + iFakePrimBusy--; + + if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims + { + GPUIsBusy; + GPUIsNotReadyForCommands; + } + else + { + GPUIsIdle; + GPUIsReadyForCommands; + } + } + return lGPUstatusRet | (vBlank ? 0x80000000 : 0 ); +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU status register +// these are always single packet commands. +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteStatus(uint32_t gdata) // WRITE STATUS +{ + uint32_t lCommand=(gdata>>24)&0xff; + + ulStatusControl[lCommand]=gdata; // store command for freezing + + switch(lCommand) + { + //--------------------------------------------------// + // reset gpu + case 0x00: + memset(lGPUInfoVals,0x00,16*sizeof(uint32_t)); + lGPUstatusRet=0x14802000; + PSXDisplay.Disabled=1; + DataWriteMode=DataReadMode=DR_NORMAL; + PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; + drawX=drawY=0;drawW=drawH=0; + sSetMask=0;lSetMask=0;bCheckMask=FALSE; + 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) + lGPUstatusRet|=GPUSTATUS_DISPLAYDISABLED; + else lGPUstatusRet&=~GPUSTATUS_DISPLAYDISABLED; + return; + + //--------------------------------------------------// + // setting transfer mode + case 0x04: + gdata &= 0x03; // Only want the lower two bits + + DataWriteMode=DataReadMode=DR_NORMAL; + if(gdata==0x02) DataWriteMode=DR_VRAMTRANSFER; + if(gdata==0x03) DataReadMode =DR_VRAMTRANSFER; + lGPUstatusRet&=~GPUSTATUS_DMABITS; // Clear the current settings of the DMA bits + lGPUstatusRet|=(gdata << 29); // Set the DMA bits according to the received data + + return; + //--------------------------------------------------// + // setting display position + case 0x05: + { + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + +//////// +/* + PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff); + if (PSXDisplay.DisplayPosition.y & 0x200) + PSXDisplay.DisplayPosition.y |= 0xfffffc00; + if(PSXDisplay.DisplayPosition.y<0) + { + PreviousPSXDisplay.DisplayModeNew.y=PSXDisplay.DisplayPosition.y/PSXDisplay.Double; + PSXDisplay.DisplayPosition.y=0; + } + else PreviousPSXDisplay.DisplayModeNew.y=0; +*/ + +// new + if(iGPUHeight==1024) + { + if(dwGPUVersion==2) + PSXDisplay.DisplayPosition.y = (short)((gdata>>12)&0x3ff); + else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x3ff); + } + else PSXDisplay.DisplayPosition.y = (short)((gdata>>10)&0x1ff); + + // store the same val in some helper var, we need it on later compares + PreviousPSXDisplay.DisplayModeNew.x=PSXDisplay.DisplayPosition.y; + + if((PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)>iGPUHeight) + { + int dy1=iGPUHeight-PSXDisplay.DisplayPosition.y; + int dy2=(PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayMode.y)-iGPUHeight; + + if(dy1>=dy2) + { + PreviousPSXDisplay.DisplayModeNew.y=-dy2; + } + else + { + PSXDisplay.DisplayPosition.y=0; + PreviousPSXDisplay.DisplayModeNew.y=-dy1; + } + } + else PreviousPSXDisplay.DisplayModeNew.y=0; +// eon + + PSXDisplay.DisplayPosition.x = (short)(gdata & 0x3ff); + 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; + + bDoVSyncUpdate=TRUE; + + if (!(PSXDisplay.Interlaced)) // stupid frame skipping option + { + if(UseFrameSkip) updateDisplay(); + if(dwActFixes&64) bDoLazyUpdate=TRUE; + } + }return; + //--------------------------------------------------// + // setting width + case 0x06: + + PSXDisplay.Range.x0=(short)(gdata & 0x7ff); + PSXDisplay.Range.x1=(short)((gdata>>12) & 0xfff); + + PSXDisplay.Range.x1-=PSXDisplay.Range.x0; + + ChangeDispOffsetsX(); + + return; + //--------------------------------------------------// + // setting height + case 0x07: + { + + PSXDisplay.Range.y0=(short)(gdata & 0x3ff); + PSXDisplay.Range.y1=(short)((gdata>>10) & 0x3ff); + + PreviousPSXDisplay.Height = PSXDisplay.Height; + + 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 = + sDispWidths[(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 + + lGPUstatusRet&=~GPUSTATUS_WIDTHBITS; // Clear the width bits + lGPUstatusRet|= + (((gdata & 0x03) << 17) | + ((gdata & 0x40) << 10)); // Set the width bits + + if(PSXDisplay.InterlacedNew) + { + if(!PSXDisplay.Interlaced) + { + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + } + lGPUstatusRet|=GPUSTATUS_INTERLACED; + } + else lGPUstatusRet&=~GPUSTATUS_INTERLACED; + + if (PSXDisplay.PAL) + lGPUstatusRet|=GPUSTATUS_PAL; + else lGPUstatusRet&=~GPUSTATUS_PAL; + + if (PSXDisplay.Double==2) + lGPUstatusRet|=GPUSTATUS_DOUBLEHEIGHT; + else lGPUstatusRet&=~GPUSTATUS_DOUBLEHEIGHT; + + if (PSXDisplay.RGB24New) + lGPUstatusRet|=GPUSTATUS_RGB24; + else lGPUstatusRet&=~GPUSTATUS_RGB24; + + updateDisplayIfChanged(); + + return; + //--------------------------------------------------// + // ask about GPU version and other stuff + case 0x10: + + gdata&=0xff; + + switch(gdata) + { + case 0x02: + lGPUdataRet=lGPUInfoVals[INFO_TW]; // tw infos + return; + case 0x03: + lGPUdataRet=lGPUInfoVals[INFO_DRAWSTART]; // draw start + return; + case 0x04: + lGPUdataRet=lGPUInfoVals[INFO_DRAWEND]; // draw end + return; + case 0x05: + case 0x06: + lGPUdataRet=lGPUInfoVals[INFO_DRAWOFF]; // draw offset + return; + case 0x07: + if(dwGPUVersion==2) + lGPUdataRet=0x01; + else lGPUdataRet=0x02; // gpu type + return; + case 0x08: + case 0x0F: // some bios addr? + lGPUdataRet=0xBFC03720; + return; + } + return; + //--------------------------------------------------// + } +} + +//////////////////////////////////////////////////////////////////////// +// vram read/write helpers, needed by LEWPY's optimized vram read/write :) +//////////////////////////////////////////////////////////////////////// + +static __inline void FinishedVRAMWrite(void) +{ +/* +// NEWX + if(!PSXDisplay.Interlaced && UseFrameSkip) // stupid frame skipping + { + VRAMWrite.Width +=VRAMWrite.x; + VRAMWrite.Height+=VRAMWrite.y; + if(VRAMWrite.x<PSXDisplay.DisplayEnd.x && + VRAMWrite.Width >=PSXDisplay.DisplayPosition.x && + VRAMWrite.y<PSXDisplay.DisplayEnd.y && + VRAMWrite.Height>=PSXDisplay.DisplayPosition.y) + updateDisplay(); + } +*/ + + // Set register to NORMAL operation + DataWriteMode = DR_NORMAL; + // Reset transfer values, to prevent mis-transfer of data + VRAMWrite.x = 0; + VRAMWrite.y = 0; + VRAMWrite.Width = 0; + VRAMWrite.Height = 0; + VRAMWrite.ColsRemaining = 0; + VRAMWrite.RowsRemaining = 0; +} + +static __inline void FinishedVRAMRead(void) +{ + // Set register to NORMAL operation + DataReadMode = 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 + lGPUstatusRet&=~GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// core read from vram +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUreadDataMem(uint32_t * pMem, int iSize) +{ + int i; + + if(DataReadMode!=DR_VRAMTRANSFER) return; + + GPUIsBusy; + + // adjust read ptr, if necessary + while(VRAMRead.ImagePtr>=psxVuw_eom) + VRAMRead.ImagePtr-=iGPUHeight*1024; + while(VRAMRead.ImagePtr<psxVuw) + VRAMRead.ImagePtr+=iGPUHeight*1024; + + for(i=0;i<iSize;i++) + { + // do 2 seperate 16bit reads for compatibility (wrap issues) + if ((VRAMRead.ColsRemaining > 0) && (VRAMRead.RowsRemaining > 0)) + { + // lower 16 bit + lGPUdataRet=(uint32_t)GETLE16(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) + lGPUdataRet|=(uint32_t)GETLE16(VRAMRead.ImagePtr)<<16; + PUTLE32(pMem, lGPUdataRet); pMem++; + + 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 lGPUdataRet; +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU data register +// extra table entries for fixing polyline troubles +//////////////////////////////////////////////////////////////////////// + +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, // GLINE + 255,255,255,255,255,255,255,255, + // 60 + 3,3,3,3,4,4,4,4, + // 68 + 2,2,2,2,3,3,3,3, // 3=SPRITE1??? + // 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 +}; + +void CALLBACK GPUwriteDataMem(uint32_t * pMem, int iSize) +{ + unsigned char command; + uint32_t gdata=0; + int i=0; + GPUIsBusy; + GPUIsNotReadyForCommands; + +STARTVRAM: + + if(DataWriteMode==DR_VRAMTRANSFER) + { + BOOL bFinished=FALSE; + + // make sure we are in vram + while(VRAMWrite.ImagePtr>=psxVuw_eom) + VRAMWrite.ImagePtr-=iGPUHeight*1024; + while(VRAMWrite.ImagePtr<psxVuw) + VRAMWrite.ImagePtr+=iGPUHeight*1024; + + // now do the loop + while(VRAMWrite.ColsRemaining>0) + { + while(VRAMWrite.RowsRemaining>0) + { + if(i>=iSize) {goto ENDVRAM;} + i++; + + gdata=GETLE32(pMem); pMem++; + + PUTLE16(VRAMWrite.ImagePtr, (unsigned short)gdata); VRAMWrite.ImagePtr++; + 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)GETLE16(VRAMWrite.ImagePtr))<<16); + FinishedVRAMWrite(); + bDoVSyncUpdate=TRUE; + goto ENDVRAM; + } + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + PUTLE16(VRAMWrite.ImagePtr, (unsigned short)(gdata>>16)); VRAMWrite.ImagePtr++; + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + } + + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining--; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + bFinished=TRUE; + } + + FinishedVRAMWrite(); + if(bFinished) bDoVSyncUpdate=TRUE; + } + +ENDVRAM: + + if(DataWriteMode==DR_NORMAL) + { + void (* *primFunc)(unsigned char *); + if(bSkipNextFrame) primFunc=primTableSkip; + else primFunc=primTableJ; + + for(;i<iSize;) + { + if(DataWriteMode==DR_VRAMTRANSFER) goto STARTVRAM; + + gdata=GETLE32(pMem); pMem++; i++; + + if(gpuDataC == 0) + { + command = (unsigned char)((gdata>>24) & 0xff); + +//if(command>=0xb0 && command<0xc0) auxprintf("b0 %x!!!!!!!!!\n",command); + + if(primTableCX[command]) + { + gpuDataC = primTableCX[command]; + gpuCommand = command; + PUTLE32(&gpuDataM[0], gdata); + gpuDataP = 1; + } + else continue; + } + else + { + PUTLE32(&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&0x0400) // hack for emulating "gpu busy" in some games + iFakePrimBusy=4; + } + } + } + + lGPUdataRet=gdata; + + GPUIsReadyForCommands; + GPUIsIdle; +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUwriteData(uint32_t gdata) +{ + PUTLE32(&gdata, gdata); + GPUwriteDataMem(&gdata,1); +} + +//////////////////////////////////////////////////////////////////////// +// this functions will be removed soon (or 'soonish')... not really needed, but some emus want them +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetMode(unsigned long gdata) +{ +// Peops does nothing here... +// DataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL; +// DataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL; +} + +long CALLBACK GPUgetMode(void) +{ + long iT=0; + + if(DataWriteMode==DR_VRAMTRANSFER) iT|=0x1; + if(DataReadMode ==DR_VRAMTRANSFER) iT|=0x2; + return iT; +} + +//////////////////////////////////////////////////////////////////////// +// call config dlg +//////////////////////////////////////////////////////////////////////// + +long CALLBACK GPUconfigure(void) +{ +#ifdef _WINDOWS + HWND hWP=GetActiveWindow(); + + DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGSOFT), + hWP,(DLGPROC)SoftDlgProc); +#else + SoftDlgProc(); +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// sets all kind of act fixes +//////////////////////////////////////////////////////////////////////// + +void SetFixes(void) + { +#ifdef _WINDOWS + BOOL bOldPerformanceCounter=IsPerformanceCounter; // store curr timer mode + + if(dwActFixes&0x10) // check fix 0x10 + IsPerformanceCounter=FALSE; + else SetFPSHandler(); + + if(bOldPerformanceCounter!=IsPerformanceCounter) // we have change it? + InitFPS(); // -> init fps again +#endif + + if(dwActFixes&0x02) sDispWidths[4]=384; + else sDispWidths[4]=368; + } + +//////////////////////////////////////////////////////////////////////// +// process gpu commands +//////////////////////////////////////////////////////////////////////// + +unsigned long lUsedAddr[3]; + +static __inline BOOL CheckForEndlessLoop(unsigned long laddr) +{ + if(laddr==lUsedAddr[1]) return TRUE; + if(laddr==lUsedAddr[2]) return TRUE; + + if(laddr<lUsedAddr[0]) lUsedAddr[1]=laddr; + else lUsedAddr[2]=laddr; + lUsedAddr[0]=laddr; + return FALSE; +} + +long CALLBACK GPUdmaChain(uint32_t * baseAddrL, uint32_t addr) +{ + uint32_t dmaMem; + unsigned char * baseAddrB; + short count;unsigned int DMACommandCounter = 0; + + GPUIsBusy; + + lUsedAddr[0]=lUsedAddr[1]=lUsedAddr[2]=0xffffff; + + baseAddrB = (unsigned char*) baseAddrL; + + do + { + if(iGPUHeight==512) addr&=0x1FFFFC; + if(DMACommandCounter++ > 2000000) break; + if(CheckForEndlessLoop(addr)) break; + + count = baseAddrB[addr+3]; + + dmaMem=addr+4; + + if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); + + addr = GETLE32(&baseAddrL[addr>>2])&0xffffff; + } + while (addr != 0xffffff); + + GPUIsIdle; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// show about dlg +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +BOOL CALLBACK AboutDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_COMMAND: + { + switch(LOWORD(wParam)) + {case IDOK: EndDialog(hW,TRUE);return TRUE;} + } + } + return FALSE; +} +#endif + +void CALLBACK GPUabout(void) // ABOUT +{ +#ifdef _WINDOWS + HWND hWP=GetActiveWindow(); // to be sure + DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT), + hWP,(DLGPROC)AboutDlgProc); +#else + AboutDlgProc(); +#endif + + return; +} + +//////////////////////////////////////////////////////////////////////// +// 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; +} + +//////////////////////////////////////////////////////////////////////// +// Freeze +//////////////////////////////////////////////////////////////////////// + +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) // 2: info, which save slot is selected? (just for display) + { + long lSlotNum=*((long *)pF); + if(lSlotNum<0) return 0; + if(lSlotNum>8) return 0; + lSelectedSlot=lSlotNum+1; + BuildDispMenu(0); + return 1; + } + //----------------------------------------------------// + if(!pF) return 0; // some checks + if(pF->ulFreezeVersion!=1) return 0; + + if(ulGetFreezeData==1) // 1: get data + { + pF->ulStatus=lGPUstatusRet; + memcpy(pF->ulControl,ulStatusControl,256*sizeof(uint32_t)); + memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); + + return 1; + } + + if(ulGetFreezeData!=0) return 0; // 0: set data + + lGPUstatusRet=pF->ulStatus; + memcpy(ulStatusControl,pF->ulControl,256*sizeof(uint32_t)); + memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); + +// RESET TEXTURE STORE HERE, IF YOU USE SOMETHING LIKE THAT + + GPUwriteStatus(ulStatusControl[0]); + GPUwriteStatus(ulStatusControl[1]); + GPUwriteStatus(ulStatusControl[2]); + GPUwriteStatus(ulStatusControl[3]); + GPUwriteStatus(ulStatusControl[8]); // try to repair things + GPUwriteStatus(ulStatusControl[6]); + GPUwriteStatus(ulStatusControl[7]); + GPUwriteStatus(ulStatusControl[5]); + GPUwriteStatus(ulStatusControl[4]); + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// SAVE STATE DISPLAY STUFF +//////////////////////////////////////////////////////////////////////// + +// font 0-9, 24x20 pixels, 1 byte = 4 dots +// 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;} // black + if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} // white + if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} // red + // transparent +} + +//////////////////////////////////////////////////////////////////////// +// the main emu allocs 128x96x3 bytes, and passes a ptr +// to it in pMem... the plugin has to fill it with +// 8-8-8 bit BGR screen data (Win 24 bit BMP format +// without header). +// Beware: the func can be called at any time, +// so you have to use the frontbuffer to get a fully +// rendered picture + +#ifdef _WINDOWS + +void CALLBACK GPUgetScreenPic(unsigned char * pMem) +{ + HRESULT ddrval;DDSURFACEDESC xddsd;unsigned char * pf; + int x,y,c,v;RECT r; + float XS,YS; + + memset(&xddsd, 0, sizeof(DDSURFACEDESC)); + xddsd.dwSize = sizeof(DDSURFACEDESC); + xddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; + xddsd.dwWidth = iResX; + xddsd.dwHeight = iResY; + + r.left=0; r.right =iResX; + r.top=0; r.bottom=iResY; + + if(iWindowMode) + { + POINT Point={0,0}; + ClientToScreen(DX.hWnd,&Point); + r.left+=Point.x;r.right+=Point.x; + r.top+=Point.y;r.bottom+=Point.y; + } + + XS=(float)iResX/128; + YS=(float)iResY/96; + + ddrval=IDirectDrawSurface_Lock(DX.DDSPrimary,NULL, &xddsd, DDLOCK_WAIT|DDLOCK_READONLY, NULL); + + if(ddrval==DDERR_SURFACELOST) IDirectDrawSurface_Restore(DX.DDSPrimary); + + pf=pMem; + + if(ddrval==DD_OK) + { + unsigned char * ps=(unsigned char *)xddsd.lpSurface; + + if(iDesktopCol==16) + { + unsigned short sx; + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + sx=*((unsigned short *)((ps)+ + r.top*xddsd.lPitch+ + (((int)((float)y*YS))*xddsd.lPitch)+ + r.left*2+ + ((int)((float)x*XS))*2)); + *(pf+0)=(sx&0x1f)<<3; + *(pf+1)=(sx&0x7e0)>>3; + *(pf+2)=(sx&0xf800)>>8; + pf+=3; + } + } + } + else + if(iDesktopCol==15) + { + unsigned short sx; + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + sx=*((unsigned short *)((ps)+ + r.top*xddsd.lPitch+ + (((int)((float)y*YS))*xddsd.lPitch)+ + r.left*2+ + ((int)((float)x*XS))*2)); + *(pf+0)=(sx&0x1f)<<3; + *(pf+1)=(sx&0x3e0)>>2; + *(pf+2)=(sx&0x7c00)>>7; + pf+=3; + } + } + } + else + { + unsigned long sx; + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + sx=*((unsigned long *)((ps)+ + r.top*xddsd.lPitch+ + (((int)((float)y*YS))*xddsd.lPitch)+ + r.left*4+ + ((int)((float)x*XS))*4)); + *(pf+0)=(unsigned char)((sx&0xff)); + *(pf+1)=(unsigned char)((sx&0xff00)>>8); + *(pf+2)=(unsigned char)((sx&0xff0000)>>16); + pf+=3; + } + } + } + } + + IDirectDrawSurface_Unlock(DX.DDSPrimary,&xddsd); + + ///////////////////////////////////////////////////////////////////// + // generic number/border painter + + pf=pMem+(103*3); // offset to number rect + + for(y=0;y<20;y++) // loop the number rect pixel + { + for(x=0;x<6;x++) + { + c=cFont[lSelectedSlot][x+y*6]; // get 4 char dot infos at once (number depends on selected slot) + 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; // next rect y line + } + + pf=pMem; // ptr to first pos in 128x96 pic + for(x=0;x<128;x++) // loop top/bottom line + { + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0x00;*pf++=0x00; // paint it red + *(pf+(95*128*3))=0xff;*pf++=0xff; + } + pf=pMem; // ptr to first pos + for(y=0;y<96;y++) // loop left/right line + { + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0x00;*pf++=0x00; // paint it red + *(pf+(127*3))=0xff;*pf++=0xff; + pf+=127*3; // offset to next line + } +} + +#else + +// LINUX version: + +extern char * Xpixels; + +void GPUgetScreenPic(unsigned char * pMem) +{ +/* + unsigned short c;unsigned char * pf;int x,y; + + float XS=(float)iResX/128; + float YS=(float)iResY/96; + + pf=pMem; + memset(pMem, 0, 128*96*3); + + if(Xpixels) + { + unsigned char * ps=(unsigned char *)Xpixels; + { + long lPitch=iResX<<2; + uint32_t sx; + + for(y=0;y<96;y++) + { + for(x=0;x<128;x++) + { + sx=*((uint32_t *)((ps)+ + (((int)((float)y*YS))*lPitch)+ + ((int)((float)x*XS))*4)); + *(pf+0)=(sx&0xff); + *(pf+1)=(sx&0xff00)>>8; + *(pf+2)=(sx&0xff0000)>>16; + pf+=3; + } + } + } + } + + + ///////////////////////////////////////////////////////////////////// + // generic number/border painter + + pf=pMem+(103*3); // offset to number rect + + for(y=0;y<20;y++) // loop the number rect pixel + { + for(x=0;x<6;x++) + { + c=cFont[lSelectedSlot][x+y*6]; // get 4 char dot infos at once (number depends on selected slot) + PaintPicDot(pf,(c&0xc0)>>6);pf+=3; // paint the dots into the rect + PaintPicDot(pf,(c&0x30)>>4);pf+=3; + PaintPicDot(pf,(c&0x0c)>>2);pf+=3; + PaintPicDot(pf,(c&0x03)); pf+=3; + } + pf+=104*3; // next rect y line + } + + pf=pMem; // ptr to first pos in 128x96 pic + for(x=0;x<128;x++) // loop top/bottom line + { + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0x00;*pf++=0x00; // paint it red + *(pf+(95*128*3))=0xff;*pf++=0xff; + } + pf=pMem; // ptr to first pos + for(y=0;y<96;y++) // loop left/right line + { + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0x00;*pf++=0x00; // paint it red + *(pf+(127*3))=0xff;*pf++=0xff; + pf+=127*3; // offset to next line + } +*/ +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// func will be called with 128x96x3 BGR data. +// the plugin has to store the data and display +// it in the upper right corner. +// If the func is called with a NULL ptr, you can +// release your picture data and stop displaying +// the screen pic + +void CALLBACK GPUshowScreenPic(unsigned char * pMem) +{ + DestroyPic(); // destroy old pic data + if(pMem==0) return; // done + CreatePic(pMem); // create new pic... don't free pMem or something like that... just read from it +} + +void CALLBACK GPUsetfix(uint32_t dwFixBits) +{ + dwEmuFixes=dwFixBits; +} + +void CALLBACK GPUvBlank( int val ) +{ + vBlank = val; +} + +void CALLBACK GPUvisualVibration(uint32_t iSmall, uint32_t iBig) +{ + int iVibVal; + + if(PreviousPSXDisplay.DisplayMode.x) // calc min "shake pixel" from screen width + iVibVal=max(1,iResX/PreviousPSXDisplay.DisplayMode.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)); + + iRumbleTime=15; // let the rumble last 16 buffer swaps +} |
