Lets go ahead and bring the changes to zzogl-pg in the GregMiscellaneous branch into trunk.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3748 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
arcum42 2010-09-11 04:51:18 +00:00
parent da9c955135
commit a9281ecea0
12 changed files with 905 additions and 169 deletions

View File

@ -65,6 +65,7 @@ set(zzoglSources
ZZoglCreate.cpp
ZZoglCRTC.cpp
ZZoglFlush.cpp
ZZoglFlushHack.cpp
ZZoglSave.cpp
ZZoglShaders.cpp
ZZoglShoots.cpp
@ -154,9 +155,6 @@ target_link_libraries(${Output} ${OPENGL_LIBRARIES})
# link target with X11
target_link_libraries(${Output} ${X11_LIBRARIES})
# link target with X11 videomod
target_link_libraries(${Output} ${X11_Xxf86vm_LIB})
# User flags options
if(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}")

View File

@ -53,7 +53,8 @@ enum GAME_HACK_OPTIONS
GAME_PARTIALDEPTH = 0x04000000, // tries to save depth targets as much as possible across height changes
GAME_REGETHACK = 0x08000000, // some sort of weirdness in ReGet() code
GAME_GUSTHACK = 0x10000000, // Needed for Gustgames fast update.
GAME_NOLOGZ = 0x20000000 // Intended for linux -- not logarithmic Z.
GAME_NOLOGZ = 0x20000000, // Intended for linux -- not logarithmic Z.
GAME_AUTOSKIPDRAW = 0x40000000 // Remove blur effect on some games
};
#define USEALPHATESTING (!(conf.settings().no_alpha_test))

View File

@ -29,10 +29,6 @@
#undef CreateWindow // Undo Windows.h global namespace pollution
#ifdef GL_X11_WINDOW
#include <X11/extensions/xf86vmode.h>
#endif
class GLWindow
{
private:
@ -45,22 +41,23 @@ class GLWindow
Window glWindow;
XSetWindowAttributes attr;
// Original desktop video mode
XF86VidModeModeInfo deskMode;
bool CreateVisual();
void GetGLXVersion();
void GetGLXVidModeVersion();
void GetWindowSize();
void UpdateGrabKey();
void Force43Ratio();
#endif
bool fullScreen, doubleBuffered;
s32 x, y;
u32 width, height, depth;
public:
void SwapGLBuffers();
bool ReleaseContext();
#ifdef GL_X11_WINDOW
void ToggleFullscreen();
#endif
bool CreateWindow(void *pDisplay);
void CloseWindow();
bool DisplayWindow(int _width, int _height);
@ -68,6 +65,7 @@ class GLWindow
void ResizeCheck();
};
extern GLWindow GLWin;
#endif // GLWIN_H_INCLUDED

View File

@ -24,9 +24,14 @@
#ifdef GL_X11_WINDOW
#include <X11/Xlib.h>
#include <stdlib.h>
bool GLWindow::CreateWindow(void *pDisplay)
{
// init support of multi thread
if (!XInitThreads())
ZZLog::Error_Log("Failed to init the xlib concurent threads");
glDisplay = XOpenDisplay(0);
glScreen = DefaultScreen(glDisplay);
@ -39,42 +44,37 @@ bool GLWindow::CreateWindow(void *pDisplay)
bool GLWindow::ReleaseContext()
{
if (context && (glDisplay != NULL))
{
if (!glXMakeCurrent(glDisplay, None, NULL))
bool status = true;
if (!glDisplay) return status;
// free the context
if (context)
{
if (!glXMakeCurrent(glDisplay, None, NULL)) {
ZZLog::Error_Log("Could not release drawing context.");
status = false;
}
glXDestroyContext(glDisplay, context);
context = NULL;
}
return true;
// free the visual
if (vi) {
XFree(vi);
vi = NULL;
}
return status;
}
void GLWindow::CloseWindow()
{
conf.x = x;
conf.y = y;
SaveConfig();
if (!glDisplay) return;
/* switch back to original desktop resolution if we were in fullscreen */
if (glDisplay != NULL)
{
if (fullScreen)
{
XF86VidModeSwitchToMode(glDisplay, glScreen, &deskMode);
XF86VidModeSetViewPort(glDisplay, glScreen, 0, 0);
}
}
if (glDisplay != NULL)
{
XCloseDisplay(glDisplay);
glDisplay = NULL;
}
}
bool GLWindow::CreateVisual()
@ -123,11 +123,21 @@ bool GLWindow::CreateVisual()
void GLWindow::GetWindowSize()
{
if (!glDisplay or !glWindow) return;
unsigned int borderDummy;
Window winDummy;
s32 xDummy;
s32 yDummy;
XGetGeometry(glDisplay, glWindow, &winDummy, &x, &y, &width, &height, &borderDummy, &depth);
ZZLog::Error_Log("Depth %d", depth);
XLockDisplay(glDisplay);
XGetGeometry(glDisplay, glWindow, &winDummy, &xDummy, &yDummy, &width, &height, &borderDummy, &depth);
XUnlockDisplay(glDisplay);
// update the gl buffer size
ZeroGS::ChangeWindowSize(width, height);
ZZLog::Error_Log("Resolution %dx%d. Depth %d bpp. Position (%d,%d)", width, height, depth, conf.x, conf.y);
}
void GLWindow::GetGLXVersion()
@ -139,123 +149,148 @@ void GLWindow::GetGLXVersion()
ZZLog::Error_Log("glX-Version %d.%d", glxMajorVersion, glxMinorVersion);
}
void GLWindow::GetGLXVidModeVersion()
void GLWindow::UpdateGrabKey()
{
int vidModeMajorVersion, vidModeMinorVersion;
// Do not stole the key in debug mode. It is not breakpoint friendly...
#ifndef _DEBUG
XLockDisplay(glDisplay);
if (fullScreen) {
XGrabPointer(glDisplay, glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, glWindow, None, CurrentTime);
XGrabKeyboard(glDisplay, glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
} else {
XUngrabPointer(glDisplay, CurrentTime);
XUngrabKeyboard(glDisplay, CurrentTime);
}
XUnlockDisplay(glDisplay);
#endif
}
XF86VidModeQueryVersion(glDisplay, &vidModeMajorVersion, &vidModeMinorVersion);
void GLWindow::Force43Ratio()
{
// avoid black border in fullscreen
if (fullScreen && conf.isWideScreen) {
conf.width = width;
conf.height = height;
}
if(!fullScreen && !conf.isWideScreen) {
// Compute the width based on height
s32 new_width = (4*height)/3;
// do not bother to resize for 5 pixels. Avoid a loop
// due to round value
if ( abs(new_width - width) > 5) {
width = new_width;
conf.width = new_width;
// resize the window
XLockDisplay(glDisplay);
XResizeWindow(glDisplay, glWindow, new_width, height);
XSync(glDisplay, False);
XUnlockDisplay(glDisplay);
}
}
}
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2
void GLWindow::ToggleFullscreen()
{
if (!glDisplay or !glWindow) return;
Force43Ratio();
u32 mask = SubstructureRedirectMask | SubstructureNotifyMask;
// Setup a new event structure
XClientMessageEvent cme;
cme.type = ClientMessage;
cme.send_event = True;
cme.display = glDisplay;
cme.window = glWindow;
cme.message_type = XInternAtom(glDisplay, "_NET_WM_STATE", False);
cme.format = 32;
// Note: can not use _NET_WM_STATE_TOGGLE because the WM can change the fullscreen state
// and screw up the fullscreen variable... The test on fulscreen restore a sane configuration
cme.data.l[0] = fullScreen ? _NET_WM_STATE_REMOVE : _NET_WM_STATE_ADD;
cme.data.l[1] = (u32)XInternAtom(glDisplay, "_NET_WM_STATE_FULLSCREEN", False);
cme.data.l[2] = 0;
cme.data.l[3] = 0;
// send the event
XLockDisplay(glDisplay);
if (!XSendEvent(glDisplay, RootWindow(glDisplay, vi->screen), False, mask, (XEvent*)(&cme)))
ZZLog::Error_Log("Failed to send event: toggle fullscreen");
else {
fullScreen = (!fullScreen);
conf.setFullscreen(fullScreen);
}
XUnlockDisplay(glDisplay);
// Apply the change
XSync(glDisplay, False);
// update info structure
GetWindowSize();
UpdateGrabKey();
// avoid black border in widescreen fullscreen
if (fullScreen && conf.isWideScreen) {
conf.width = width;
conf.height = height;
}
// Hide the cursor in the right bottom corner
if(fullScreen)
XWarpPointer(glDisplay, None, glWindow, 0, 0, 0, 0, width, height);
ZZLog::Error_Log("XF86VidModeExtension-Version %d.%d.", vidModeMajorVersion, vidModeMinorVersion);
}
bool GLWindow::DisplayWindow(int _width, int _height)
{
Colormap cmap;
x = conf.x;
y = conf.y;
fullScreen = (conf.fullscreen());
if (!CreateVisual()) return false;
/* create a GLX context */
context = glXCreateContext(glDisplay, vi, NULL, GL_TRUE);
/* create a color map */
cmap = XCreateColormap(glDisplay, RootWindow(glDisplay, vi->screen),
attr.colormap = XCreateColormap(glDisplay, RootWindow(glDisplay, vi->screen),
vi->visual, AllocNone);
attr.colormap = cmap;
attr.border_pixel = 0;
attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask |
StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask |
EnterWindowMask | LeaveWindowMask | FocusChangeMask ;
GetGLXVersion();
if (fullScreen)
{
int dpyWidth, dpyHeight;
int modeNum = 0, bestMode = 0;
XF86VidModeModeInfo **modes = NULL;
GetGLXVidModeVersion();
XF86VidModeGetAllModeLines(glDisplay, glScreen, &modeNum, &modes);
if (modeNum > 0 && modes != NULL)
{
/* save desktop-resolution before switching modes */
deskMode = *modes[0];
/* look for mode with requested resolution */
for (int i = 0; i < modeNum; i++)
{
if ((modes[i]->hdisplay == _width) && (modes[i]->vdisplay == _height))
{
bestMode = i;
}
}
XF86VidModeSwitchToMode(glDisplay, glScreen, modes[bestMode]);
XF86VidModeSetViewPort(glDisplay, glScreen, 0, 0);
dpyWidth = modes[bestMode]->hdisplay;
dpyHeight = modes[bestMode]->vdisplay;
ZZLog::Error_Log("Resolution %dx%d.", dpyWidth, dpyHeight);
XFree(modes);
/* create a fullscreen window */
attr.override_redirect = True;
// Create a window at the last position/size
glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen),
0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
conf.x , conf.y , _width, _height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask,
&attr);
XWarpPointer(glDisplay, None, glWindow, 0, 0, 0, 0, 0, 0);
XMapRaised(glDisplay, glWindow);
XGrabKeyboard(glDisplay, glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(glDisplay, glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, glWindow, None, CurrentTime);
}
else
{
ZZLog::Error_Log("Failed to start fullscreen. If you received the \n"
"\"XFree86-VidModeExtension\" extension is missing, add\n"
"Load \"extmod\"\n"
"to your X configuration file (under the Module Section)");
fullScreen = false;
}
}
if (!fullScreen)
{
// create a window in window mode
glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen),
0, 0, _width, _height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &attr);
// only set window title and handle wm_delete_events if in windowed mode
Atom wmDelete;
wmDelete = XInternAtom(glDisplay, "WM_DELETE_WINDOW", True);
/* Allow to kill properly the window */
Atom wmDelete = XInternAtom(glDisplay, "WM_DELETE_WINDOW", True);
XSetWMProtocols(glDisplay, glWindow, &wmDelete, 1);
XSetStandardProperties(glDisplay, glWindow, "ZZOgl-PG", "ZZOgl-PG", None, NULL, 0, NULL);
// Set icon name
XSetIconName(glDisplay, glWindow, "ZZogl-pg");
// Draw the window
XMapRaised(glDisplay, glWindow);
XMoveWindow(glDisplay, glWindow, x, y);
}
XSync(glDisplay, false);
// connect the glx-context to the window
glXMakeCurrent(glDisplay, glWindow, context);
GetWindowSize();
if (glXIsDirect(glDisplay, context))
ZZLog::Error_Log("You have Direct Rendering!");
else
ZZLog::Error_Log("No Direct Rendering possible!");
// better for pad plugin key input (thc)
XSelectInput(glDisplay, glWindow, ExposureMask | KeyPressMask | KeyReleaseMask |
ButtonPressMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask |
FocusChangeMask);
// Always start in window mode
fullScreen = 0;
GetWindowSize();
return true;
}
@ -267,40 +302,49 @@ void GLWindow::SwapGLBuffers()
void GLWindow::SetTitle(char *strtitle)
{
if (!conf.fullscreen())
{
if (!glDisplay or !glWindow) return;
if (fullScreen) return;
XTextProperty prop;
memset(&prop, 0, sizeof(prop));
char* ptitle = strtitle;
if (XStringListToTextProperty(&ptitle, 1, &prop))
char* ptitle = strtitle;
if (XStringListToTextProperty(&ptitle, 1, &prop)) {
XLockDisplay(glDisplay);
XSetWMName(glDisplay, glWindow, &prop);
XUnlockDisplay(glDisplay);
}
XFree(prop.value);
}
}
void GLWindow::ResizeCheck()
{
XEvent event;
if (!glDisplay or !glWindow) return;
while (XCheckTypedEvent(glDisplay, ConfigureNotify, &event))
XLockDisplay(glDisplay);
while (XCheckTypedWindowEvent(glDisplay, glWindow, ConfigureNotify, &event))
{
if ((event.xconfigure.width != width) || (event.xconfigure.height != height))
{
ZeroGS::ChangeWindowSize(event.xconfigure.width, event.xconfigure.height);
width = event.xconfigure.width;
height = event.xconfigure.height;
Force43Ratio();
ZeroGS::ChangeWindowSize(width, height);
}
if ((event.xconfigure.x != x) || (event.xconfigure.y != y))
if (!fullScreen) {
if ((event.xconfigure.x != conf.x) || (event.xconfigure.y != conf.y))
{
// Fixme; x&y occassionally gives values near the top left corner rather then the real values,
// causing the window to change positions when adjusting ZZOgl's settings.
x = event.xconfigure.x;
y = event.xconfigure.y;
conf.x = event.xconfigure.x;
conf.y = event.xconfigure.y;
}
}
}
XUnlockDisplay(glDisplay);
}
#endif

View File

@ -100,19 +100,19 @@ extern GSconf conf;
// PSM types == Texture Storage Format
enum PSM_value
{
PSMCT32 = 0, // 000000
PSMCT24 = 1, // 000001
PSMCT16 = 2, // 000010
PSMCT16S = 10, // 001010
PSMT8 = 19, // 010011
PSMT4 = 20, // 010100
PSMT8H = 27, // 011011
PSMT4HL = 36, // 100100
PSMT4HH = 44, // 101100
PSMT32Z = 48, // 110000
PSMT24Z = 49, // 110001
PSMT16Z = 50, // 110010
PSMT16SZ = 58, // 111010
PSMCT32 = 0, // 00 0000
PSMCT24 = 1, // 00 0001
PSMCT16 = 2, // 00 0010
PSMCT16S = 10, // 00 1010
PSMT8 = 19, // 01 0011
PSMT4 = 20, // 01 0100
PSMT8H = 27, // 01 1011
PSMT4HL = 36, // 10 0100
PSMT4HH = 44, // 10 1100
PSMT32Z = 48, // 11 0000
PSMT24Z = 49, // 11 0001
PSMT16Z = 50, // 11 0010
PSMT16SZ = 58, // 11 1010
};
// Check target bit mode. PSMCT32 and 32Z return 0, 24 and 24Z - 1
@ -168,6 +168,25 @@ inline bool PSMT_IS16Z(int psm) {return ((psm & 0x32) == 0x32);}
// I'll have to look closer at it, because it'd seem like it'd return true for 24 bits.
inline bool PSMT_IS32BIT(int psm) {return !!(psm <= 1);}
// This function updates the 6th and 5th bit of psm
// 00 or 11 -> 00 ; 01 -> 10 ; 10 -> 01
inline int Switch_Top_Bytes (int X) {
if ( ( X & 0x30 ) == 0 )
return X;
else
return (X ^ 0x30);
}
// Some storage formats could share the same memory block (2 textures in 1 format). This include following combinations:
// PSMT24(24Z) with either 8H, 4HL, 4HH and PSMT4HL with PSMT4HH.
// We use slightly different versions of this function on comparison with GSDX, Storage format XOR 0x30 made Z-textures
// similar to normal ones and change higher bits on short (8 and 4 bits) textures.
inline bool PSMT_HAS_SHARED_BITS (int fpsm, int tpsm) {
int SUM = Switch_Top_Bytes(fpsm) + Switch_Top_Bytes(tpsm) ;
return (SUM == 0x15 || SUM == 0x1D || SUM == 0x2C || SUM == 0x30);
}
//----------------------- Data from registers -----------------------
typedef union

View File

@ -37,6 +37,7 @@ using namespace std;
#include "zerogs.h"
#include "targets.h"
#include "ZeroGSShaders/zerogsshaders.h"
#include "ZZoglFlushHack.h"
#ifdef _MSC_VER
#pragma warning(disable:4244)
@ -49,6 +50,8 @@ GSconf conf;
int ppf, g_GSMultiThreaded, CurrentSavestate = 0;
int g_LastCRC = 0, g_TransferredToGPU = 0, s_frameskipping = 0;
int g_SkipFlushFrame = 0;
GetSkipCount GetSkipCount_Handler = 0;
int UPDATE_FRAMES = 16, g_nFrame = 0, g_nRealFrame = 0;
float fFPS = 0;
@ -157,6 +160,7 @@ void ReportHacks(gameHacks hacks)
if (hacks.reget) ZZLog::WriteLn("Reget hack enabled.");
if (hacks.gust) ZZLog::WriteLn("Gust hack enabled.");
if (hacks.no_logz) ZZLog::WriteLn("'No logz' hack enabled.");
if (hacks.automatic_skip_draw) ZZLog::WriteLn("'Automatic skip draw' hack enabled.");
}
void ListHacks()
@ -176,6 +180,54 @@ void ListHacks()
void CALLBACK GSsetGameCRC(int crc, int options)
{
// build a list of function pointer for GetSkipCount (SkipDraw)
static GetSkipCount GSC_list[NUMBER_OF_TITLES];
static bool inited = false;
if (!inited)
{
inited = true;
memset(GSC_list, 0, sizeof(GSC_list));
// for(int i = 0; i < NUMBER_OF_TITLES; i++)
// {
// GSC_list[i] = GSC_Null;
// }
GSC_list[Okami] = GSC_Okami;
GSC_list[MetalGearSolid3] = GSC_MetalGearSolid3;
GSC_list[DBZBT2] = GSC_DBZBT2;
GSC_list[DBZBT3] = GSC_DBZBT3;
GSC_list[SFEX3] = GSC_SFEX3;
GSC_list[Bully] = GSC_Bully;
GSC_list[BullyCC] = GSC_BullyCC;
GSC_list[SoTC] = GSC_SoTC;
GSC_list[OnePieceGrandAdventure] = GSC_OnePieceGrandAdventure;
GSC_list[OnePieceGrandBattle] = GSC_OnePieceGrandBattle;
GSC_list[ICO] = GSC_ICO;
GSC_list[GT4] = GSC_GT4;
//FIXME GSC_list[WildArms4] = GSC_WildArms4;
GSC_list[WildArms5] = GSC_WildArms5;
GSC_list[Manhunt2] = GSC_Manhunt2;
GSC_list[CrashBandicootWoC] = GSC_CrashBandicootWoC;
GSC_list[ResidentEvil4] = GSC_ResidentEvil4;
GSC_list[Spartan] = GSC_Spartan;
GSC_list[AceCombat4] = GSC_AceCombat4;
GSC_list[Drakengard2] = GSC_Drakengard2;
GSC_list[Tekken5] = GSC_Tekken5;
GSC_list[IkkiTousen] = GSC_IkkiTousen;
GSC_list[GodOfWar] = GSC_GodOfWar;
GSC_list[GodOfWar2] = GSC_GodOfWar2;
GSC_list[GiTS] = GSC_GiTS;
GSC_list[Onimusha3] = GSC_Onimusha3;
GSC_list[TalesOfAbyss] = GSC_TalesOfAbyss;
GSC_list[SonicUnleashed] = GSC_SonicUnleashed;
GSC_list[Genji] = GSC_Genji;
GSC_list[StarOcean3] = GSC_StarOcean3;
GSC_list[ValkyrieProfile2] = GSC_ValkyrieProfile2;
GSC_list[RadiataStories] = GSC_RadiataStories;
}
// TEXDESTROY_THRESH starts out at 16.
VALIDATE_THRESH = 8;
conf.mrtdepth = (conf.settings().disable_mrt_depth != 0);
@ -211,6 +263,9 @@ void CALLBACK GSsetGameCRC(int crc, int options)
ZZLog::WriteLn("Setting TEXDESTROY_THRESH to %d", TEXDESTROY_THRESH);
}
// FIXME need to check SkipDraw is positive (enabled by users)
GetSkipCount_Handler = GSC_list[crc_game_list[i].title];
conf.def_hacks._u32 |= crc_game_list[i].flags;
ListHacks();
return;
@ -491,6 +546,7 @@ void CALLBACK GSvsync(int interlace)
g_nAlphaVars = 0;
g_nResolve = 0;
g_nFramesSkipped = 0;
g_SkipFlushFrame = 0;
}
#if defined(ZEROGS_DEVBUILD)

View File

@ -16,6 +16,7 @@
<Compiler>
<Add option="-Wall" />
<Add option="-g" />
<Add option="-DZEROGS_DEVBUILD" />
<Add option="-D_DEBUG" />
</Compiler>
<Linker>
@ -150,6 +151,8 @@
<Unit filename="../../ZZoglCRTC.h" />
<Unit filename="../../ZZoglCreate.cpp" />
<Unit filename="../../ZZoglFlush.cpp" />
<Unit filename="../../ZZoglFlushHack.cpp" />
<Unit filename="../../ZZoglFlushHack.h" />
<Unit filename="../../ZZoglSave.cpp" />
<Unit filename="../../ZZoglShaders.cpp" />
<Unit filename="../../ZZoglShoots.cpp" />

View File

@ -173,7 +173,7 @@ typedef union
u32 reget : 1; // some sort of weirdness in ReGet() code
u32 gust : 1; // Needed for Gustgames fast update.
u32 no_logz : 1; // Intended for linux -- not logarithmic Z.
u32 reserved1 :1;
u32 automatic_skip_draw :1; // allow debug of the automatic skip draw option
u32 reserved2 :1;
};
u32 _u32;
@ -209,6 +209,7 @@ typedef struct
int width, height; // View target size, has no impact towards speed
int x, y; // Lets try for a persistant window position.
bool isWideScreen; // Widescreen support
u32 SkipDraw;
u32 log;
void incAA() { aa++; if (aa > 4) aa = 0; }
@ -271,8 +272,8 @@ typedef struct
break;
default:
width = 640;
height = 480;
width = 800;
height = 600;
break;
}
}

View File

@ -25,6 +25,7 @@
#include "Mem.h"
#include "zerogs.h"
#include "targets.h"
#include "ZZoglFlushHack.h"
using namespace ZeroGS;
@ -375,7 +376,7 @@ inline void FlushUpdateEffect()
// Check, maybe we cold skip flush
inline bool IsFlushNoNeed(VB& curvb, const pixTest& curtest)
{
if (curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0))
if (curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0) || IsBadFrame(curvb))
{
curvb.nCount = 0;
return true;

View File

@ -0,0 +1,531 @@
/* ZZ Open GL graphics plugin
* Copyright (c)2010 gregory.hainaut@gmail.com, zeydlitz@gmail.com
* Based on GSdx Copyright (C) 2007-2009 Gabest
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* This file is a collection of hack for removing the blur effect on some games
* The blur renders very badly on high screen flat panel.
*
* To avoid severals combo-box, the hack detects the game based on crc
*/
#include "ZZoglFlushHack.h"
inline bool GABEST_HAS_SHARED_BITS (int fbp, int fpsm, int tbp, int tpsm)
{
if ( !PSMT_HAS_SHARED_BITS (fpsm, tpsm) )
return ((fbp ^ tbp) == 0);
else
return false;
}
// GSC_... function has been imported from GSdx
void GSC_Okami(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x00e00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT32)
skip = 1000;
}
else
{
if(fi.TME && fi.FBP == 0x00e00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03800 && fi.TPSM == PSMT4)
skip = 0;
}
}
void GSC_MetalGearSolid3(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x02000 && fi.FPSM == PSMCT32 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01000) && fi.TPSM == PSMCT24)
skip = 1000; // 76, 79
else if(fi.TME && fi.FBP == 0x02800 && fi.FPSM == PSMCT24 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01000) && fi.TPSM == PSMCT32)
skip = 1000; // 69
}
else
{
if(!fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01000) && fi.FPSM == PSMCT32)
skip = 0;
}
}
void GSC_DBZBT2(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && /*fi.FBP == 0x00000 && fi.FPSM == PSMCT16 &&*/ fi.TBP0 == 0x02000 && fi.TPSM == PSMT16Z)
skip = 27;
else if(!fi.TME && fi.FBP == 0x03000 && fi.FPSM == PSMCT16)
skip = 10;
}
}
void GSC_DBZBT3(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x01c00 && fi.FPSM == PSMCT32 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00e00) && fi.TPSM == PSMT8H)
skip = 24; // blur
else if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && fi.FPSM == PSMCT32 && fi.TPSM == PSMT8H)
skip = 28; // outline
}
}
void GSC_SFEX3(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x00500 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00f00 && fi.TPSM == PSMCT16)
skip = 2; // blur
}
}
void GSC_Bully(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
// Test is useless !
// if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01180) && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01180) && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.FPSM == fi.TPSM)
// return; // allowed
if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01180) && fi.FPSM == PSMCT16S && fi.TBP0 == 0x02300 && fi.TPSM == PSMT16SZ)
skip = 6;
}
else
{
if(!fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01180) && fi.FPSM == PSMCT32)
skip = 0;
}
}
void GSC_BullyCC(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
// Test is useless !
// if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01180) && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01180) && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.FPSM == fi.TPSM)
// return; // allowed
if(!fi.TME && fi.FBP == 0x02800 && fi.FPSM == PSMCT24)
skip = 9;
}
}
void GSC_SoTC(const GSFrameInfo& fi, int& skip)
{
// Not needed anymore? What did it fix anyway? (rama)
/*if(skip == 0)
{
if(fi.TME && fi.FBP == 0x02b80 && fi.FPSM == PSMCT24 && fi.TBP0 == 0x01e80 && fi.TPSM == PSMCT24)
skip = 9;
else if(fi.TME && fi.FBP == 0x01c00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03800 && fi.TPSM == PSMCT32)
skip = 8;
else if(fi.TME && fi.FBP == 0x01e80 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03880 && fi.TPSM == PSMCT32)
skip = 8;
}*/
}
void GSC_OnePieceGrandAdventure(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x02d00 && fi.FPSM == PSMCT16 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00e00 || fi.TBP0 == 0x00f00) && fi.TPSM == PSMCT16)
skip = 4;
}
}
void GSC_OnePieceGrandBattle(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x02d00 && fi.FPSM == PSMCT16 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00f00) && fi.TPSM == PSMCT16)
skip = 4;
}
}
void GSC_ICO(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x00800 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03d00 && fi.TPSM == PSMCT32)
skip = 3;
else if(fi.TME && fi.FBP == 0x00800 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x02800 && fi.TPSM == PSMT8H)
skip = 1;
}
else
{
if(fi.TME && fi.TBP0 == 0x00800 && fi.TPSM == PSMCT32)
skip = 0;
}
}
void GSC_GT4(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && (fi.FBP == 0x03440 || fi.FBP >= 0x03e00) && fi.FPSM == PSMCT32 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01400) && fi.TPSM == PSMT8)
skip = 880;
else if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x01400) && fi.FPSM == PSMCT24 && fi.TBP0 >= 0x03420 && fi.TPSM == PSMT8)
{
// TODO: removes gfx from where it is not supposed to (garage)
// skip = 58;
}
}
}
void GSC_WildArms4(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x03100 && fi.FPSM == PSMT32Z && fi.TBP0 == 0x01c00 && fi.TPSM == PSMT32Z)
skip = 100;
}
else
{
if(fi.TME && fi.FBP == 0x00e00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x02a00 && fi.TPSM == PSMCT32)
skip = 1;
}
}
void GSC_WildArms5(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x03100 && fi.FPSM == PSMT32Z && fi.TBP0 == 0x01c00 && fi.TPSM == PSMT32Z)
skip = 100;
}
else
{
if(fi.TME && fi.FBP == 0x00e00 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x02a00 && fi.TPSM == PSMCT32)
skip = 1;
}
}
void GSC_Manhunt2(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x03c20 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x01400 && fi.TPSM == PSMT8)
skip = 640;
}
}
void GSC_CrashBandicootWoC(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
// Test is useless !
// if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00a00) && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00a00) && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.FPSM == fi.TPSM)
// return false; // allowed
if(fi.TME && fi.FBP == 0x02200 && fi.FPSM == PSMT24Z && fi.TBP0 == 0x01400 && fi.TPSM == PSMT24Z)
skip = 41;
}
else
{
if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00a00) && fi.FPSM == PSMCT32 && fi.TBP0 == 0x03c00 && fi.TPSM == PSMCT32)
skip = 0;
else if(!fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00a00))
skip = 0;
}
}
void GSC_ResidentEvil4(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x03100 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x01c00 && fi.TPSM == PSMT24Z)
skip = 176;
}
}
void GSC_Spartan(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x02000 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT32)
skip = 107;
}
}
void GSC_AceCombat4(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x02a00 && fi.FPSM == PSMT24Z && fi.TBP0 == 0x01600 && fi.TPSM == PSMT24Z)
skip = 71; // clouds (z, 16-bit)
else if(fi.TME && fi.FBP == 0x02900 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT24)
skip = 28; // blur
}
}
void GSC_Drakengard2(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x026c0 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00a00 && fi.TPSM == PSMCT32)
skip = 64;
}
}
void GSC_Tekken5(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x02ea0 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT32)
skip = 95;
}
}
void GSC_IkkiTousen(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x00a80 && fi.FPSM == PSMT24Z && fi.TBP0 == 0x01180 && fi.TPSM == PSMT24Z)
skip = 1000; // shadow (result is broken without depth copy, also includes 16 bit)
else if(fi.TME && fi.FBP == 0x00700 && fi.FPSM == PSMT24Z && fi.TBP0 == 0x01180 && fi.TPSM == PSMT24Z)
skip = 11; // blur
}
else if(skip > 7)
{
if(fi.TME && fi.FBP == 0x00700 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00700 && fi.TPSM == PSMCT16)
skip = 7; // the last steps of shadow drawing
}
}
void GSC_GodOfWar(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x00000 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT16)
{
// skip = 30; //GSdx
skip = 4; // 23 or 4 need more testing
}
else if(fi.TME && fi.FBP == 0x00000 && fi.FPSM == PSMCT32 && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT32 && fi.FBMSK == 0xff000000)
skip = 1; // blur
else if(fi.FBP == 0x00000 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT8
&& ((fi.TZTST == 2 && fi.FBMSK == 0x00FFFFFF) || (fi.TZTST == 1 && fi.FBMSK == 0x00FFFFFF) || (fi.TZTST == 3 && fi.FBMSK == 0xFF000000)))
skip = 1; // wall of fog
}
}
void GSC_GodOfWar2(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME)
{
if((fi.FBP == 0x00100 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00100 && fi.TPSM == PSMCT16) // ntsc
|| (fi.FBP == 0x02100 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x02100 && fi.TPSM == PSMCT16)) // pal
skip = 29; // shadows
if(fi.FBP == 0x00100 && fi.FPSM == PSMCT32 && (fi.TBP0 & 0x03000) == 0x03000
&& (fi.TPSM == PSMT8 || fi.TPSM == PSMT4)
&& ((fi.TZTST == 2 && fi.FBMSK == 0x00FFFFFF) || (fi.TZTST == 1 && fi.FBMSK == 0x00FFFFFF) || (fi.TZTST == 3 && fi.FBMSK == 0xFF000000)))
skip = 1; // wall of fog
}
}
}
void GSC_GiTS(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x01400 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x02e40 && fi.TPSM == PSMCT16)
skip = 1315;
}
}
void GSC_Onimusha3(const GSFrameInfo& fi, int& skip)
{
if(fi.TME /*&& (fi.FBP == 0x00000 || fi.FBP == 0x00700)*/ && (fi.TBP0 == 0x01180 || fi.TBP0 == 0x00e00 || fi.TBP0 == 0x01000 || fi.TBP0 == 0x01200) && (fi.TPSM == PSMCT32 || fi.TPSM == PSMCT24))
skip = 1;
}
void GSC_TalesOfAbyss(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && fi.TBP0 == 0x01c00 && fi.TPSM == PSMT8) // copies the z buffer to the alpha channel of the fb
skip = 1000;
else if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && (fi.TBP0 == 0x03560 || fi.TBP0 == 0x038e0) && fi.TPSM == PSMCT32)
skip = 1;
}
else
{
if(fi.TME && fi.TPSM != PSMT8)
skip = 0;
}
}
void GSC_SonicUnleashed(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x02200 && fi.FPSM == PSMCT16S && fi.TBP0 == 0x00000 && fi.TPSM == PSMCT16)
skip = 1000; // shadow
}
else
{
if(fi.TME && fi.FBP == 0x00000 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x02200 && fi.TPSM == PSMCT16S)
skip = 2;
}
}
void GSC_Genji(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x01500 && fi.FPSM == PSMCT16 && fi.TBP0 == 0x00e00 && fi.TPSM == PSMT16Z)
skip = 6; //
}
}
void GSC_StarOcean3(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH)
skip = 1000; //
}
else
{
if(!(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH))
skip = 0;
}
}
void GSC_ValkyrieProfile2(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH)
skip = 1000; //
}
else
{
if(!(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH))
skip = 0;
}
}
void GSC_RadiataStories(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH)
skip = 1000; // Shadows
else if (fi.TME && fi.FBP == fi.TBP0 && (fi.TBP0 == 0x3700 || fi.TBP0 == 0x3400) && fi.TZTST == 1)
skip = 1; // Start manu issue;
}
else
{
if(!(fi.TME && fi.FBP == fi.TBP0 && fi.FPSM == PSMCT32 && fi.TPSM == PSMT4HH))
skip = 0;
}
}
bool GSC_HauntingGround(const GSFrameInfo& fi, int& skip)
{
// Note GSdx seems to use invert somewhere FBMSK. So values were inverted
if(skip == 0)
{
if(fi.TME && fi.FPSM == fi.TPSM && fi.TPSM == PSMCT16S && fi.FBMSK == ~(0x03FFF))
skip = 1;
else if(fi.TME && fi.FBP == 0x3000 && fi.TBP0 == 0x3380)
skip = 1; // bloom
else if(fi.TME && fi.FBP == fi.TBP0 && fi.TBP0 == 0x3000 && fi.FBMSK == ~(0xFFFFFF) &&
GABEST_HAS_SHARED_BITS(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM))
skip = 1;
}
return true;
}
// Record skipped frame to allow better analysis
// #define FRAME_RECORDING_ON 1
#ifdef FRAME_RECORDING_ON
static const u32 MAX_FRAMES = 500;
static GSFrameInfo FrameAppear[MAX_FRAMES];
static u32 Rec_Numbers = 0;
void RecordNewFrames(ZeroGS::VB& curvb, GSFrameInfo fi) {
if (Rec_Numbers >= MAX_FRAMES)
return;
u32 i;
bool was_recorded = false;
for (i = 0; i < Rec_Numbers; i++ ) {
if (FrameAppear[i].FBP == fi.FBP && FrameAppear[i].FPSM == fi.FPSM
&& FrameAppear[i].TBP0 == fi.TBP0 && FrameAppear[i].TPSM == fi.TPSM) {
was_recorded = true;
break;
}
}
if (!was_recorded) {
FrameAppear[Rec_Numbers] = fi;
Rec_Numbers++;
ZZLog::Print( "New frame %d, skip %d | fpb: %x fpsm: %d fpmsk: %x tme: %x tbp0: %x tpsm: %d tztst: %x | bits %d\n", \
Rec_Numbers, g_SkipFlushFrame, fi.FBP, fi.FPSM, fi.FBMSK, fi.TME, fi.TBP0, fi.TPSM, fi.TZTST, GABEST_HAS_SHARED_BITS(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM) );
// Dump a nice picture of the frame
char filename[255];
sprintf(filename, "SkipFlushFrame_%d__%d.tga", g_SkipFlushFrame, Rec_Numbers);
ZeroGS::SaveRenderTarget(filename, curvb.prndr->fbw, curvb.prndr->fbh, 0);
}
}
#endif
__forceinline bool IsBadFrame(ZeroGS::VB& curvb)
{
GSFrameInfo fi;
// Keep GSdx naming convention to ease sharing code
fi.FBP = curvb.frame.fbp;
fi.FPSM = curvb.frame.psm;
fi.FBMSK = ~curvb.frame.fbm;
fi.TME = curvb.curprim.tme;
fi.TBP0 = curvb.tex0.tbp0;
fi.TPSM = curvb.tex0.psm;
fi.TZTST = curvb.test.ztst;
if (GetSkipCount_Handler && conf.settings().automatic_skip_draw)
GetSkipCount_Handler(fi, g_SkipFlushFrame);
if(g_SkipFlushFrame == 0 && (conf.SkipDraw > 0))
{
if(fi.TME)
{
// depth textures (bully, mgs3s1 intro, Front Mission 5)
// Or General, often problematic post processing
if (PSMT_ISZTEX(fi.TPSM) || (GABEST_HAS_SHARED_BITS(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM)))
g_SkipFlushFrame = conf.SkipDraw;
}
}
if(g_SkipFlushFrame > 0)
{
#ifdef FRAME_RECORDING_ON
RecordNewFrames(curvb, fi);
#endif
g_SkipFlushFrame--;
return true;
}
return false;
}

View File

@ -0,0 +1,83 @@
/* ZZ Open GL graphics plugin
* Copyright (c)2010 gregory.hainaut@gmail.com
* Based on GSdx Copyright (C) 2007-2009 Gabest
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* This file is a collection of hack for removing the blur effect on some games
* The blur renders very badly on high screen flat panel.
*
* To avoid severals combo-box, the hack detects the game based on crc
*/
#ifndef ZZOGL_FLUSH_HACK_H_INCLUDED
#define ZZOGL_FLUSH_HACK_H_INCLUDED
#include "GS.h"
#include "zerogs.h"
extern int g_SkipFlushFrame;
struct GSFrameInfo
{
u32 FBP;
u32 FPSM;
u32 FBMSK;
u32 TBP0;
u32 TPSM;
u32 TZTST;
bool TME;
};
typedef void (*GetSkipCount)(const GSFrameInfo& fi, int& skip);
extern GetSkipCount GetSkipCount_Handler;
void GSC_Okami(const GSFrameInfo& fi, int& skip);
void GSC_MetalGearSolid3(const GSFrameInfo& fi, int& skip);
void GSC_DBZBT2(const GSFrameInfo& fi, int& skip);
void GSC_DBZBT3(const GSFrameInfo& fi, int& skip);
void GSC_SFEX3(const GSFrameInfo& fi, int& skip);
void GSC_Bully(const GSFrameInfo& fi, int& skip);
void GSC_BullyCC(const GSFrameInfo& fi, int& skip);
void GSC_SoTC(const GSFrameInfo& fi, int& skip);
void GSC_OnePieceGrandAdventure(const GSFrameInfo& fi, int& skip);
void GSC_OnePieceGrandBattle(const GSFrameInfo& fi, int& skip);
void GSC_ICO(const GSFrameInfo& fi, int& skip);
void GSC_GT4(const GSFrameInfo& fi, int& skip);
void GSC_WildArms4(const GSFrameInfo& fi, int& skip);
void GSC_WildArms5(const GSFrameInfo& fi, int& skip);
void GSC_Manhunt2(const GSFrameInfo& fi, int& skip);
void GSC_CrashBandicootWoC(const GSFrameInfo& fi, int& skip);
void GSC_ResidentEvil4(const GSFrameInfo& fi, int& skip);
void GSC_Spartan(const GSFrameInfo& fi, int& skip);
void GSC_AceCombat4(const GSFrameInfo& fi, int& skip);
void GSC_Drakengard2(const GSFrameInfo& fi, int& skip);
void GSC_Tekken5(const GSFrameInfo& fi, int& skip);
void GSC_IkkiTousen(const GSFrameInfo& fi, int& skip);
void GSC_GodOfWar(const GSFrameInfo& fi, int& skip);
void GSC_GodOfWar2(const GSFrameInfo& fi, int& skip);
void GSC_GiTS(const GSFrameInfo& fi, int& skip);
void GSC_Onimusha3(const GSFrameInfo& fi, int& skip);
void GSC_TalesOfAbyss(const GSFrameInfo& fi, int& skip);
void GSC_SonicUnleashed(const GSFrameInfo& fi, int& skip);
void GSC_Genji(const GSFrameInfo& fi, int& skip);
void GSC_StarOcean3(const GSFrameInfo& fi, int& skip);
void GSC_ValkyrieProfile2(const GSFrameInfo& fi, int& skip);
void GSC_RadiataStories(const GSFrameInfo& fi, int& skip);
extern bool IsBadFrame(ZeroGS::VB& curvb);
#endif

View File

@ -420,6 +420,7 @@ union
CMemoryTarget* pmemtarg; // the current mem target set
CRenderTarget* prndr;
CDepthTarget* pdepth;
};
// Return, if tcc, aem or psm mode told us, than Alpha test should be used