zzogl-pg: Ran a bunch of the files through AStyle, so I don't find myself messing with the source code formatting so much.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2931 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
arcum42 2010-05-01 20:33:53 +00:00
parent 7e8c22b4f5
commit a6c4df49ea
23 changed files with 5863 additions and 3923 deletions

View File

@ -21,13 +21,15 @@
#ifdef GL_WIN32_WINDOW
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static int nWindowWidth = 0, nWindowHeight = 0;
switch( msg ) {
switch (msg)
{
case WM_DESTROY:
PostQuitMessage( 0 );
PostQuitMessage(0);
return 0;
case WM_KEYDOWN:
@ -39,24 +41,23 @@ LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
break;
case WM_ACTIVATE:
if( wParam != WA_INACTIVE ) {
if (wParam != WA_INACTIVE)
{
//ZZLog::Debug_Log("Restoring device.");
ZeroGS::Restore();
}
break;
case WM_SIZE:
nWindowWidth = lParam&0xffff;
nWindowHeight = lParam>>16;
nWindowWidth = lParam & 0xffff;
nWindowHeight = lParam >> 16;
ZeroGS::ChangeWindowSize(nWindowWidth, nWindowHeight);
break;
case WM_SIZING:
// if button is 0, then just released so can resize
if( GetSystemMetrics(SM_SWAPBUTTON) ? !GetAsyncKeyState(VK_RBUTTON) : !GetAsyncKeyState(VK_LBUTTON) ) {
if (GetSystemMetrics(SM_SWAPBUTTON) ? !GetAsyncKeyState(VK_RBUTTON) : !GetAsyncKeyState(VK_LBUTTON))
{
ZeroGS::SetChangeDeviceSize(nWindowWidth, nWindowHeight);
}
break;
@ -66,14 +67,16 @@ LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
break;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
return DefWindowProc(hWnd, msg, wParam, lParam);
}
bool GLWindow::CreateWindow(void *pDisplay)
{
RECT rc, rcdesktop;
rc.left = 0; rc.top = 0;
rc.right = conf.width; rc.bottom = conf.height;
rc.left = 0;
rc.top = 0;
rc.right = conf.width;
rc.bottom = conf.height;
WNDCLASSEX wc;
HINSTANCE hInstance = GetModuleHandle(NULL);
@ -92,9 +95,9 @@ bool GLWindow::CreateWindow(void *pDisplay)
wc.lpszMenuName = NULL;
wc.lpszClassName = "PS2EMU_ZEROGS";
RegisterClassEx( &wc );
RegisterClassEx(&wc);
if( conf.options & GSOPTION_FULLSCREEN)
if (conf.options & GSOPTION_FULLSCREEN)
{
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
@ -106,21 +109,22 @@ bool GLWindow::CreateWindow(void *pDisplay)
}
AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
GetWindowRect(GetDesktopWindow(), &rcdesktop);
GShwnd = CreateWindowEx(
dwExStyle,
"PS2EMU_ZEROGS",
"ZeroGS",
dwStyle,
(rcdesktop.right - (rc.right - rc.left)) / 2,
(rcdesktop.bottom - (rc.bottom - rc.top)) / 2,
rc.right - rc.left,
rc.bottom - rc.top,
NULL,
NULL,
hInstance,
NULL);
dwExStyle,
"PS2EMU_ZEROGS",
"ZeroGS",
dwStyle,
(rcdesktop.right - (rc.right - rc.left)) / 2,
(rcdesktop.bottom - (rc.bottom - rc.top)) / 2,
rc.right - rc.left,
rc.bottom - rc.top,
NULL,
NULL,
hInstance,
NULL);
if (GShwnd == NULL) return false;
@ -129,8 +133,10 @@ bool GLWindow::CreateWindow(void *pDisplay)
// set just in case
SetWindowLongPtr(GShwnd, GWLP_WNDPROC, (LPARAM)(WNDPROC)MsgProc);
ShowWindow( GShwnd, SW_SHOWDEFAULT );
UpdateWindow( GShwnd );
ShowWindow(GShwnd, SW_SHOWDEFAULT);
UpdateWindow(GShwnd);
SetFocus(GShwnd);
return (pDisplay != NULL);
@ -140,22 +146,23 @@ bool GLWindow::ReleaseWindow()
{
if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
if (!wglMakeCurrent(NULL, NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
hRC = NULL; // Set RC To NULL
}
if (hDC && !ReleaseDC(GShwnd,hDC)) // Are We Able To Release The DC
if (hDC && !ReleaseDC(GShwnd, hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
hDC = NULL; // Set DC To NULL
}
return true;
@ -163,7 +170,7 @@ bool GLWindow::ReleaseWindow()
void GLWindow::CloseWindow()
{
if( GShwnd != NULL )
if (GShwnd != NULL)
{
DestroyWindow(GShwnd);
GShwnd = NULL;
@ -179,55 +186,64 @@ bool GLWindow::DisplayWindow(int _width, int _height)
RECT rcdesktop;
GetWindowRect(GetDesktopWindow(), &rcdesktop);
if( conf.options & GSOPTION_FULLSCREEN) {
if (conf.options & GSOPTION_FULLSCREEN)
{
nBackbufferWidth = rcdesktop.right - rcdesktop.left;
nBackbufferHeight = rcdesktop.bottom - rcdesktop.top;
dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_POPUP;
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
ShowCursor(FALSE);
}
else {
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle=WS_OVERLAPPEDWINDOW;
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
}
RECT rc;
rc.left = 0; rc.top = 0;
rc.right = nBackbufferWidth; rc.bottom = nBackbufferHeight;
rc.left = 0;
rc.top = 0;
rc.right = nBackbufferWidth;
rc.bottom = nBackbufferHeight;
AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2;
int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2;
int X = (rcdesktop.right - rcdesktop.left) / 2 - (rc.right - rc.left) / 2;
int Y = (rcdesktop.bottom - rcdesktop.top) / 2 - (rc.bottom - rc.top) / 2;
SetWindowLong( GShwnd, GWL_STYLE, dwStyle );
SetWindowLong( GShwnd, GWL_EXSTYLE, dwExStyle );
SetWindowLong(GShwnd, GWL_STYLE, dwStyle);
SetWindowLong(GShwnd, GWL_EXSTYLE, dwExStyle);
SetWindowPos(GShwnd, HWND_TOP, X, Y, rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW);
SetWindowPos(GShwnd, HWND_TOP, X, Y, rc.right - rc.left, rc.bottom - rc.top, SWP_SHOWWINDOW);
if (conf.options & GSOPTION_FULLSCREEN) {
if (conf.options & GSOPTION_FULLSCREEN)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = nBackbufferWidth;
dmScreenSettings.dmPelsHeight = nBackbufferHeight;
dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
if (MessageBox(NULL, "The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?", "NeHe GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
conf.options &= ~GSOPTION_FULLSCREEN;
else
return false;
}
}
else {
else
{
// change to default resolution
ChangeDisplaySettings(NULL, 0);
}
PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
@ -249,32 +265,38 @@ bool GLWindow::DisplayWindow(int _width, int _height)
0, 0, 0 // Layer Masks Ignored
};
if (!(hDC=GetDC(GShwnd))) {
MessageBox(NULL,"(1) Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
if (!(hDC = GetDC(GShwnd)))
{
MessageBox(NULL, "(1) Can't Create A GL Device Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false;
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) {
MessageBox(NULL,"(2) Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd)))
{
MessageBox(NULL, "(2) Can't Find A Suitable PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false;
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) {
MessageBox(NULL,"(3) Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
if (!SetPixelFormat(hDC, PixelFormat, &pfd))
{
MessageBox(NULL, "(3) Can't Set The PixelFormat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false;
}
if (!(hRC=wglCreateContext(hDC))) {
MessageBox(NULL,"(4) Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
if (!(hRC = wglCreateContext(hDC)))
{
MessageBox(NULL, "(4) Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false;
}
if(!wglMakeCurrent(hDC,hRC)) {
MessageBox(NULL,"(5) Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
if (!wglMakeCurrent(hDC, hRC))
{
MessageBox(NULL, "(5) Can't Activate The GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
return false;
}
UpdateWindow(GShwnd);
return true;
}

View File

@ -23,14 +23,14 @@
bool GLWindow::CreateWindow(void *pDisplay)
{
glDisplay = XOpenDisplay(0);
glScreen = DefaultScreen(glDisplay);
glDisplay = XOpenDisplay(0);
glScreen = DefaultScreen(glDisplay);
if ( pDisplay == NULL ) return false;
if (pDisplay == NULL) return false;
*(Display**)pDisplay = glDisplay;
*(Display**)pDisplay = glDisplay;
return true;
return true;
}
bool GLWindow::ReleaseWindow()
@ -43,11 +43,12 @@ bool GLWindow::ReleaseWindow()
}
glXDestroyContext(glDisplay, context);
context = NULL;
}
/* switch back to original desktop resolution if we were in fullscreen */
if ( glDisplay != NULL )
if (glDisplay != NULL)
{
if (fullScreen)
{
@ -55,6 +56,7 @@ bool GLWindow::ReleaseWindow()
XF86VidModeSetViewPort(glDisplay, glScreen, 0, 0);
}
}
return true;
}
@ -63,8 +65,9 @@ void GLWindow::CloseWindow()
conf.x = x;
conf.y = y;
SaveConfig();
if ( glDisplay != NULL )
{
if (glDisplay != NULL)
{
XCloseDisplay(glDisplay);
glDisplay = NULL;
}
@ -91,7 +94,8 @@ bool GLWindow::DisplayWindow(int _width, int _height)
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_DEPTH_SIZE, 24,
None};
None
};
// attributes for a double buffered visual in RGBA format with at least
// 8 bits per color and a 24 bit depth buffer
@ -100,12 +104,14 @@ bool GLWindow::DisplayWindow(int _width, int _height)
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_DEPTH_SIZE, 24,
None };
None
};
GLWin.fullScreen = !!(conf.options & GSOPTION_FULLSCREEN);
/* get an appropriate visual */
vi = glXChooseVisual(glDisplay, glScreen, attrListDbl);
if (vi == NULL)
{
vi = glXChooseVisual(glDisplay, glScreen, attrListSgl);
@ -117,6 +123,7 @@ bool GLWindow::DisplayWindow(int _width, int _height)
doubleBuffered = true;
ZZLog::Error_Log("Got Doublebuffered Visual!");
}
if (vi == NULL)
{
ZZLog::Error_Log("Failed to get buffered Visual!");
@ -124,6 +131,7 @@ bool GLWindow::DisplayWindow(int _width, int _height)
}
glXQueryVersion(glDisplay, &glxMajorVersion, &glxMinorVersion);
ZZLog::Error_Log("glX-Version %d.%d", glxMajorVersion, glxMinorVersion);
/* create a GLX context */
@ -149,12 +157,13 @@ bool GLWindow::DisplayWindow(int _width, int _height)
ZZLog::Error_Log("XF86VidModeExtension-Version %d.%d.", vidModeMajorVersion, vidModeMinorVersion);
XF86VidModeGetAllModeLines(glDisplay, glScreen, &modeNum, &modes);
if( modeNum > 0 && modes != NULL )
if (modeNum > 0 && modes != NULL)
{
/* save desktop-resolution before switching modes */
deskMode = *modes[0];
/* look for mode with requested resolution */
for (i = 0; i < modeNum; i++)
{
if ((modes[i]->hdisplay == _width) && (modes[i]->vdisplay == _height))
@ -164,6 +173,7 @@ bool GLWindow::DisplayWindow(int _width, int _height)
}
XF86VidModeSwitchToMode(glDisplay, glScreen, modes[bestMode]);
XF86VidModeSetViewPort(glDisplay, glScreen, 0, 0);
dpyWidth = modes[bestMode]->hdisplay;
dpyHeight = modes[bestMode]->vdisplay;
@ -174,9 +184,9 @@ bool GLWindow::DisplayWindow(int _width, int _height)
attr.override_redirect = True;
attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen),
0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
&attr);
0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
&attr);
XWarpPointer(glDisplay, None, glWindow, 0, 0, 0, 0, 0, 0);
XMapRaised(glDisplay, glWindow);
XGrabKeyboard(glDisplay, glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
@ -185,9 +195,9 @@ bool GLWindow::DisplayWindow(int _width, int _height)
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)");
"\"XFree86-VidModeExtension\" extension is missing, add\n"
"Load \"extmod\"\n"
"to your X configuration file (under the Module Section)");
fullScreen = false;
}
}
@ -197,8 +207,8 @@ bool GLWindow::DisplayWindow(int _width, int _height)
// create a window in window mode
attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen),
0, 0, _width, _height, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &attr);
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
wmDelete = XInternAtom(glDisplay, "WM_DELETE_WINDOW", True);
@ -211,8 +221,11 @@ bool GLWindow::DisplayWindow(int _width, int _height)
// connect the glx-context to the window
glXMakeCurrent(glDisplay, glWindow, context);
XGetGeometry(glDisplay, glWindow, &winDummy, &x, &y, &width, &height, &borderDummy, &depth);
ZZLog::Error_Log("Depth %d", depth);
if (glXIsDirect(glDisplay, context))
ZZLog::Error_Log("You have Direct Rendering!");
else
@ -221,14 +234,14 @@ bool GLWindow::DisplayWindow(int _width, int _height)
// better for pad plugin key input (thc)
XSelectInput(glDisplay, glWindow, ExposureMask | KeyPressMask | KeyReleaseMask |
ButtonPressMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask |
FocusChangeMask );
FocusChangeMask);
return true;
}
void GLWindow::SwapGLBuffers()
{
glXSwapBuffers(glDisplay, glWindow);
glXSwapBuffers(glDisplay, glWindow);
}
void GLWindow::SetTitle(char *strtitle)
@ -236,29 +249,32 @@ void GLWindow::SetTitle(char *strtitle)
XTextProperty prop;
memset(&prop, 0, sizeof(prop));
char* ptitle = strtitle;
if( XStringListToTextProperty(&ptitle, 1, &prop) )
if (XStringListToTextProperty(&ptitle, 1, &prop))
XSetWMName(glDisplay, glWindow, &prop);
XFree(prop.value);
}
void GLWindow::ResizeCheck()
{
XEvent event;
XEvent event;
while(XCheckTypedEvent(glDisplay, 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;
}
if ((event.xconfigure.x != x) || (event.xconfigure.y != y))
{
x = event.xconfigure.x;
y = event.xconfigure.y;
}
}
while (XCheckTypedEvent(glDisplay, 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;
}
if ((event.xconfigure.x != x) || (event.xconfigure.y != y))
{
x = event.xconfigure.x;
y = event.xconfigure.y;
}
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -74,18 +74,22 @@ extern HANDLE g_hCurrentThread;
__forceinline void gifTransferLog(int index, u32 *pMem, u32 size)
{
#ifdef _DEBUG
if( conf.log /*& 0x20*/ )
if (conf.log /*& 0x20*/)
{
static int nSaveIndex = 0;
ZZLog::GS_Log("%d: p:%d %x", nSaveIndex++, index + 1, size);
int vals[4] = {0};
for(u32 i = 0; i < size; i++)
for (u32 i = 0; i < size; i++)
{
for(u32 j = 0; j < 4; ++j )
for (u32 j = 0; j < 4; ++j)
vals[j] ^= pMem[4*i+j];
}
ZZLog::GS_Log("%x %x %x %x", vals[0], vals[1], vals[2], vals[3]);
}
#endif
}
@ -94,151 +98,157 @@ extern int g_GSMultiThreaded;
template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
{
FUNCLOG
FUNCLOG
pathInfo *path = &gs.path[index];
pathInfo *path = &gs.path[index];
#ifdef _WIN32
assert( g_hCurrentThread == GetCurrentThread() );
assert(g_hCurrentThread == GetCurrentThread());
#endif
#ifdef _DEBUG
gifTransferLog(index, pMem, size);
gifTransferLog(index, pMem, size);
#endif
while(size > 0)
{
//LOG(_T("Transfer(%08x, %d) START\n"), pMem, size);
if (path->nloop == 0)
while (size > 0)
{
//LOG(_T("Transfer(%08x, %d) START\n"), pMem, size);
if (path->nloop == 0)
{
path->setTag(pMem);
pMem += 4;
size--;
if ((g_GameSettings & GAME_PATH3HACK) && (index == 2) && path->eop) nPath3Hack = 1;
// eeuser 7.2.2. GIFtag: "... when NLOOP is 0, the GIF does not output anything, and
// values other than the EOP field are disregarded."
if (path->nloop > 0)
{
path->setTag(pMem);
pMem += 4;
size--;
gs.q = 1.0f;
if ((g_GameSettings & GAME_PATH3HACK) && (index == 2) && path->eop) nPath3Hack = 1;
// eeuser 7.2.2. GIFtag: "... when NLOOP is 0, the GIF does not output anything, and
// values other than the EOP field are disregarded."
if (path->nloop > 0)
if (path->tag.PRE && (path->tag.FLG == GIF_FLG_PACKED))
{
gs.q = 1.0f;
if(path->tag.PRE && (path->tag.FLG == GIF_FLG_PACKED))
{
u32 tagprim = path->tag.PRIM;
GIFRegHandlerPRIM((u32*)&tagprim);
}
u32 tagprim = path->tag.PRIM;
GIFRegHandlerPRIM((u32*)&tagprim);
}
}
else
}
else
{
switch (path->mode)
{
switch(path->mode)
case GIF_FLG_PACKED:
{
case GIF_FLG_PACKED:
// Needs to be looked at.
// first try a shortcut for a very common case
/*if(path.adonly && size >= path.nloop)
{
// Needs to be looked at.
// first try a shortcut for a very common case
/*if(path.adonly && size >= path.nloop)
{
size -= path.nloop;
do
{
GIFPackedRegHandlerA_D(pMem);
mem += sizeof(GIFPackedReg);
}
while(--path.nloop > 0);*/
size -= path.nloop;
do
{
g_GIFPackedRegHandlers[path->GetReg()](pMem);
GIFPackedRegHandlerA_D(pMem);
pMem += 4;
size--;
mem += sizeof(GIFPackedReg);
}
while (path->StepReg() && (size > 0));
while(--path.nloop > 0);*/
break;
}
case GIF_FLG_REGLIST:
do
{
// Needs to be looked at.
//ZZLog::GS_Log("%8.8x%8.8x %d L", ((u32*)&gs.regs)[1], *(u32*)&gs.regs, path->tag.nreg/4);
g_GIFPackedRegHandlers[path->GetReg()](pMem);
size *= 2;
do
{
g_GIFRegHandlers[path->GetReg()](pMem);
pMem += 2;
size--;
}
while(path->StepReg() && (size > 0));
if(size & 1) pMem += 2;
size /= 2;
break;
pMem += 4;
size--;
}
while (path->StepReg() && (size > 0));
case GIF_FLG_IMAGE: // FROM_VFRAM
case GIF_FLG_IMAGE2: // Used in the DirectX version, so we'll use it here too.
{
int len = min(size, path->nloop);
//ZZLog::Error_Log("GIF_FLG_IMAGE(%d)=%d", gs.imageTransfer, len);
switch(gs.imageTransfer)
{
case 0:
ZeroGS::TransferHostLocal(pMem, len * 4);
break;
case 1:
ZeroGS::TransferLocalHost(pMem, len);
break;
case 2:
//Move();
//ZZLog::Error_Log("GIF_FLG_IMAGE MOVE");
break;
case 3:
//assert(0);
break;
default:
//assert(0);
break;
}
pMem += len * 4;
path->nloop -= len;
size -= len;
break;
}
default: // GIF_IMAGE
ZZLog::GS_Log("*** WARNING **** Unexpected GIFTag flag.");
assert(0);
path->nloop = 0;
break;
}
}
if (index == 0)
{
if(path->tag.EOP && path->nloop == 0)
{
break;
}
case GIF_FLG_REGLIST:
{
// Needs to be looked at.
//ZZLog::GS_Log("%8.8x%8.8x %d L", ((u32*)&gs.regs)[1], *(u32*)&gs.regs, path->tag.nreg/4);
size *= 2;
do
{
g_GIFRegHandlers[path->GetReg()](pMem);
pMem += 2;
size--;
}
while (path->StepReg() && (size > 0));
if (size & 1) pMem += 2;
size /= 2;
break;
}
case GIF_FLG_IMAGE: // FROM_VFRAM
case GIF_FLG_IMAGE2: // Used in the DirectX version, so we'll use it here too.
{
int len = min(size, path->nloop);
//ZZLog::Error_Log("GIF_FLG_IMAGE(%d)=%d", gs.imageTransfer, len);
switch (gs.imageTransfer)
{
case 0:
ZeroGS::TransferHostLocal(pMem, len * 4);
break;
case 1:
ZeroGS::TransferLocalHost(pMem, len);
break;
case 2:
//Move();
//ZZLog::Error_Log("GIF_FLG_IMAGE MOVE");
break;
case 3:
//assert(0);
break;
default:
//assert(0);
break;
}
pMem += len * 4;
path->nloop -= len;
size -= len;
break;
}
default: // GIF_IMAGE
ZZLog::GS_Log("*** WARNING **** Unexpected GIFTag flag.");
assert(0);
path->nloop = 0;
break;
}
}
}
if (index == 0)
{
if (path->tag.EOP && path->nloop == 0)
{
break;
}
}
}
// This is the case when not all data was readed from one try: VU1 has too much data.
// So we should redo reading from the start.
if (index == 0)
{
if(size == 0 && path->nloop > 0)
if (size == 0 && path->nloop > 0)
{
if (g_GSMultiThreaded)
{
@ -263,7 +273,7 @@ void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr)
count++;
#endif
_GSgifTransfer<0>((u32*)((u8*)pMem + addr), (0x4000 - addr)/16);
_GSgifTransfer<0>((u32*)((u8*)pMem + addr), (0x4000 - addr) / 16);
}
void CALLBACK GSgifTransfer2(u32 *pMem, u32 size)
@ -283,180 +293,194 @@ void CALLBACK GSgifTransfer3(u32 *pMem, u32 size)
_GSgifTransfer<2>(pMem, size);
}
#else
template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
{
FUNCLOG
FUNCLOG
pathInfo *path = &gs.path[index];
pathInfo *path = &gs.path[index];
#ifdef _WIN32
assert( g_hCurrentThread == GetCurrentThread() );
assert(g_hCurrentThread == GetCurrentThread());
#endif
#ifdef _DEBUG
gifTransferLog(index, pMem, size);
gifTransferLog(index, pMem, size);
#endif
while(size > 0)
{
//LOG(_T("Transfer(%08x, %d) START\n"), pMem, size);
if (path->nloop == 0)
{
path->setTag(pMem);
gs.q = 1;
pMem += 4;
size--;
while (size > 0)
{
//LOG(_T("Transfer(%08x, %d) START\n"), pMem, size);
if (path->nloop == 0)
{
path->setTag(pMem);
gs.q = 1;
pMem += 4;
size--;
if ((g_GameSettings & GAME_PATH3HACK) && (index == 2) && path->eop) nPath3Hack = 1;
if ((g_GameSettings & GAME_PATH3HACK) && (index == 2) && path->eop) nPath3Hack = 1;
if (index == 0)
{
if (path->mode == GIF_FLG_PACKED)
{
// check if 0xb is in any reg, if yes, exit (kh2)
for(int i = 0; i < path->nreg; i += 4)
{
if (((path->regs >> i) & 0xf) == 11)
{
ERROR_LOG_SPAM("Invalid unpack type\n");
path->nloop = 0;
return;
}
}
}
}
if (index == 0)
{
if (path->mode == GIF_FLG_PACKED)
{
// check if 0xb is in any reg, if yes, exit (kh2)
for (int i = 0; i < path->nreg; i += 4)
{
if (((path->regs >> i) & 0xf) == 11)
{
ERROR_LOG_SPAM("Invalid unpack type\n");
path->nloop = 0;
return;
}
}
}
}
if(path->nloop == 0 )
{
if (index == 0)
{
// ffx hack
if( path->eop ) return;
continue;
}
if (path->nloop == 0)
{
if (index == 0)
{
// ffx hack
if (path->eop) return;
/*if( !path->eop )
{
//ZZLog::Debug_Log("Continuing from eop.");
continue;
}*/
continue;
}
// Issue 174 fix!
continue;
}
}
/*if( !path->eop )
{
//ZZLog::Debug_Log("Continuing from eop.");
continue;
}*/
switch(path->mode)
{
case GIF_FLG_PACKED:
{
assert( path->nloop > 0 );
for(; size > 0; size--, pMem += 4)
{
int reg = (int)((path->regs >> path->regn) & 0xf);
// Issue 174 fix!
continue;
}
}
g_GIFPackedRegHandlers[reg](pMem);
switch (path->mode)
{
path->regn += 4;
case GIF_FLG_PACKED:
{
assert(path->nloop > 0);
if (path->nreg == path->regn)
{
path->regn = 0;
for (; size > 0; size--, pMem += 4)
{
int reg = (int)((path->regs >> path->regn) & 0xf);
if( path->nloop-- <= 1 )
{
size--;
pMem += 4;
break;
}
}
}
break;
}
case GIF_FLG_REGLIST:
{
//GS_LOG("%8.8x%8.8x %d L", ((u32*)&gs.regs)[1], *(u32*)&gs.regs, path->tag.nreg/4);
assert( path->nloop > 0 );
size *= 2;
g_GIFPackedRegHandlers[reg](pMem);
for(; size > 0; pMem+= 2, size--)
{
int reg = (int)((path->regs >> path->regn) & 0xf);
path->regn += 4;
g_GIFRegHandlers[reg](pMem);
if (path->nreg == path->regn)
{
path->regn = 0;
path->regn += 4;
if (path->nloop-- <= 1)
{
size--;
pMem += 4;
break;
}
}
}
if (path->nreg == path->regn)
{
path->regn = 0;
if( path->nloop-- <= 1 )
{
size--;
pMem += 2;
break;
}
}
}
break;
}
if( size & 1 ) pMem += 2;
size /= 2;
break;
}
case GIF_FLG_IMAGE: // FROM_VFRAM
case GIF_FLG_IMAGE2: // Used in the DirectX version, so we'll use it here too.
{
if(gs.imageTransfer >= 0 && gs.imageTransfer <= 1)
{
int process = min((int)size, path->nloop);
case GIF_FLG_REGLIST:
{
//GS_LOG("%8.8x%8.8x %d L", ((u32*)&gs.regs)[1], *(u32*)&gs.regs, path->tag.nreg/4);
assert(path->nloop > 0);
size *= 2;
if( process > 0 )
{
if ( gs.imageTransfer )
ZeroGS::TransferLocalHost(pMem, process);
else
ZeroGS::TransferHostLocal(pMem, process*4);
for (; size > 0; pMem += 2, size--)
{
int reg = (int)((path->regs >> path->regn) & 0xf);
path->nloop -= process;
pMem += process*4;
size -= process;
g_GIFRegHandlers[reg](pMem);
assert( size == 0 || path->nloop == 0 );
}
break;
}
else
{
// simulate
int process = min((int)size, path->nloop);
path->regn += 4;
path->nloop -= process;
pMem += process*4;
size -= process;
}
if (path->nreg == path->regn)
{
path->regn = 0;
break;
}
default: // GIF_IMAGE
ZZLog::GS_Log("*** WARNING **** Unexpected GIFTag flag.");
assert(0);
path->nloop = 0;
break;
}
if (path->nloop-- <= 1)
{
size--;
pMem += 2;
break;
}
}
}
if ((index == 0) && path->eop) return;
}
if (size & 1) pMem += 2;
// This is the case when not all data was readed from one try: VU1 has too much data.
// So we should redo reading from the start.
if ((index == 0) && size == 0 && path->nloop > 0)
{
ERROR_LOG_SPAMA("VU1 too much data, ignore if gfx are fine %d\n", path->nloop)
// TODO: this code is not working correctly. Anyway, ringing work only in single-threaded mode.
// _GSgifTransfer(&gs.path[0], (u32*)((u8*)pMem-0x4000), (0x4000)/16);
}
size /= 2;
break;
}
case GIF_FLG_IMAGE: // FROM_VFRAM
case GIF_FLG_IMAGE2: // Used in the DirectX version, so we'll use it here too.
{
if (gs.imageTransfer >= 0 && gs.imageTransfer <= 1)
{
int process = min((int)size, path->nloop);
if (process > 0)
{
if (gs.imageTransfer)
ZeroGS::TransferLocalHost(pMem, process);
else
ZeroGS::TransferHostLocal(pMem, process*4);
path->nloop -= process;
pMem += process * 4;
size -= process;
assert(size == 0 || path->nloop == 0);
}
break;
}
else
{
// simulate
int process = min((int)size, path->nloop);
path->nloop -= process;
pMem += process * 4;
size -= process;
}
break;
}
default: // GIF_IMAGE
ZZLog::GS_Log("*** WARNING **** Unexpected GIFTag flag.");
assert(0);
path->nloop = 0;
break;
}
if ((index == 0) && path->eop) return;
}
// This is the case when not all data was readed from one try: VU1 has too much data.
// So we should redo reading from the start.
if ((index == 0) && size == 0 && path->nloop > 0)
{
ERROR_LOG_SPAMA("VU1 too much data, ignore if gfx are fine %d\n", path->nloop)
// TODO: this code is not working correctly. Anyway, ringing work only in single-threaded mode.
// _GSgifTransfer(&gs.path[0], (u32*)((u8*)pMem-0x4000), (0x4000)/16);
}
}
void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr)
@ -476,11 +500,11 @@ void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr)
path->nloop = 0;
path->eop = 0;
_GSgifTransfer<0>((u32*)((u8*)pMem + addr), (0x4000 - addr)/16);
_GSgifTransfer<0>((u32*)((u8*)pMem + addr), (0x4000 - addr) / 16);
if (!path->eop && (path->nloop > 0))
{
assert( (addr&0xf) == 0 ); //BUG
assert((addr&0xf) == 0); //BUG
path->nloop = 0;
ZZLog::Error_Log("Transfer1 - 2.");
return;
@ -505,4 +529,5 @@ void CALLBACK GSgifTransfer3(u32 *pMem, u32 size)
nPath3Hack = 0;
_GSgifTransfer<2>(pMem, size);
}
#endif

View File

@ -26,8 +26,8 @@
void SaveConfig()
{
const std::string iniFile( s_strIniPath + "zzogl-pg.ini" );
FILE* f = fopen(iniFile.c_str(),"w");
const std::string iniFile(s_strIniPath + "zzogl-pg.ini");
FILE* f = fopen(iniFile.c_str(), "w");
if (f == NULL)
{
@ -36,6 +36,7 @@ void SaveConfig()
}
fprintf(f, "interlace = %hhx\n", conf.interlace);
fprintf(f, "mrtdepth = %hhx\n", conf.mrtdepth);
fprintf(f, "options = %x\n", conf.options); //u32
fprintf(f, "bilinear = %hhx\n", conf.bilinear);
@ -64,15 +65,18 @@ void LoadConfig()
conf.aa = 0;
conf.log = 1;
const std::string iniFile( s_strIniPath + "zzogl-pg.ini" );
const std::string iniFile(s_strIniPath + "zzogl-pg.ini");
FILE* f = fopen(iniFile.c_str(), "r");
if (f == NULL)
{
printf("failed to open %s\n", iniFile.c_str());
SaveConfig();//save and return
return;
}
err = fscanf(f, "interlace = %hhx\n", &conf.interlace);
err = fscanf(f, "mrtdepth = %hhx\n", &conf.mrtdepth);
err = fscanf(f, "options = %x\n", &conf.options);//u32
err = fscanf(f, "bilinear = %hhx\n", &conf.bilinear);
@ -86,23 +90,29 @@ void LoadConfig()
fclose(f);
// filter bad files
if ((conf.aa < 0) || (conf.aa > 4)) conf.aa = 0;
conf.isWideScreen = conf.options & GSOPTION_WIDESCREEN;
switch(conf.options & GSOPTION_WINDIMS)
switch (conf.options & GSOPTION_WINDIMS)
{
case GSOPTION_WIN640:
conf.width = 640;
conf.height = conf.isWideScreen ? 360 : 480;
break;
case GSOPTION_WIN800:
conf.width = 800;
conf.height = conf.isWideScreen ? 450 : 600;
break;
case GSOPTION_WIN1024:
conf.width = 1024;
conf.height = conf.isWideScreen ? 576 : 768;
break;
case GSOPTION_WIN1280:
conf.width = 1280;
conf.height = conf.isWideScreen ? 720 : 960;
@ -111,14 +121,16 @@ void LoadConfig()
// turn off all hacks by default
conf.options &= ~(GSOPTION_WIREFRAME | GSOPTION_CAPTUREAVI);
conf.options |= GSOPTION_LOADED;
if( conf.width <= 0 || conf.height <= 0 )
if (conf.width <= 0 || conf.height <= 0)
{
conf.width = 640;
conf.height = 480;
}
if( conf.x <= 0 || conf.y <= 0 )
if (conf.x <= 0 || conf.y <= 0)
{
conf.x = 0;
conf.y = 0;

View File

@ -35,37 +35,44 @@ void CALLBACK GSkeyEvent(keyEvent *ev)
//static bool bShift = false;
static bool bAlt = false;
switch(ev->evt) {
switch (ev->evt)
{
case KEYPRESS:
switch(ev->key) {
switch (ev->key)
{
case XK_F5:
case XK_F6:
case XK_F7:
case XK_F9:
THR_KeyEvent = ev->key ;
break;
case XK_Escape:
if (conf.options & GSOPTION_FULLSCREEN)
GSclose();
if (conf.options & GSOPTION_FULLSCREEN) GSclose();
break;
case XK_Shift_L:
case XK_Shift_R:
//bShift = true;
THR_bShift = true;
break;
case XK_Alt_L:
case XK_Alt_R:
bAlt = true;
break;
}
}
break;
case KEYRELEASE:
switch(ev->key) {
switch (ev->key)
{
case XK_Shift_L:
case XK_Shift_R:
//bShift = false;
THR_bShift = false;
break;
case XK_Alt_L:
case XK_Alt_R:
bAlt = false;
@ -91,7 +98,7 @@ void CreateGameHackTable(GtkWidget *treeview)
GtkTreeViewColumn *treecol;
//--------- Let's build a treeview for our advanced options! --------//
treestore = gtk_list_store_new(2,G_TYPE_BOOLEAN, G_TYPE_STRING);
treestore = gtk_list_store_new(2, G_TYPE_BOOLEAN, G_TYPE_STRING);
//setup columns in treeview
//COLUMN 0 is the checkboxes
@ -139,15 +146,16 @@ void CreateGameHackTable(GtkWidget *treeview)
add_map_entry(GAME_NOLOGZ, "20000000", "No logarithmic Z, could decrease number of Z-artefacts - 20000000");
add_map_entry(GAME_INTERLACE2X, "00000004", "Interlace 2X - 00000004\nFixes 2x bigger screen (Gradius 3).");
for(map<string, confOptsStruct>::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it)
for (map<string, confOptsStruct>::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it)
{
gtk_list_store_append(treestore, &treeiter);//new row
itval = (conf.gamesettings&it->second.value)?TRUE:FALSE;
itval = (conf.gamesettings & it->second.value) ? TRUE : FALSE;
snprintf(descbuf, 254, "%s", it->second.desc);
gtk_list_store_set(treestore, &treeiter, 0, itval, 1, descbuf, -1);
}
gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(treestore));//NB: store is cast as tree model.
g_object_unref(treestore);//allow model to be destroyed when the tree is destroyed.
//don't select/highlight rows
@ -166,17 +174,19 @@ void SaveGameHackTable(GtkWidget *treeview)
gtk_tree_model_get_iter_first(treemodel, &treeiter);
conf.gamesettings = 0;
for(map<string, confOptsStruct>::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it)
for (map<string, confOptsStruct>::iterator it = mapConfOpts.begin(); it != mapConfOpts.end(); ++it)
{
treeoptval = FALSE;
gtk_tree_model_get(treemodel, &treeiter, 0, &treeoptval, -1);
if(treeoptval) conf.gamesettings |= it->second.value;
if (treeoptval) conf.gamesettings |= it->second.value;
gtk_tree_model_iter_next(treemodel,&treeiter);
gtk_tree_model_iter_next(treemodel, &treeiter);
}
GSsetGameCRC(0, conf.gamesettings);
//---------- done getting advanced options ---------//
}
@ -193,94 +203,105 @@ void OnToggle_advopts(GtkCellRendererToggle *cell, gchar *path, gpointer user_da
void DisplayDialog()
{
int return_value;
int return_value;
GtkWidget *dialog;
GtkWidget *main_frame, *main_box;
GtkWidget *dialog;
GtkWidget *main_frame, *main_box;
GtkWidget *option_frame, *option_box;
GtkWidget *log_check;
GtkWidget *int_label, *int_box;
GtkWidget *bilinear_check, *bilinear_label;
GtkWidget *aa_label, *aa_box;
GtkWidget *wireframe_check, *avi_check;
GtkWidget *snap_label, *snap_box;
GtkWidget *size_label, *size_box;
GtkWidget *fullscreen_check, *widescreen_check;
GtkWidget *option_frame, *option_box;
GtkWidget *log_check;
GtkWidget *int_label, *int_box;
GtkWidget *bilinear_check, *bilinear_label;
GtkWidget *aa_label, *aa_box;
GtkWidget *wireframe_check, *avi_check;
GtkWidget *snap_label, *snap_box;
GtkWidget *size_label, *size_box;
GtkWidget *fullscreen_check, *widescreen_check;
GtkWidget *advanced_frame, *advanced_box;
GtkWidget *advanced_scroll;
GtkWidget *tree;
GtkWidget *advanced_frame, *advanced_box;
GtkWidget *advanced_scroll;
GtkWidget *tree;
if (!(conf.options & GSOPTION_LOADED)) LoadConfig();
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons (
"ZZOgl PG Config",
NULL, /* parent window*/
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
NULL);
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons(
"ZZOgl PG Config",
NULL, /* parent window*/
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
GTK_STOCK_CANCEL,
GTK_RESPONSE_REJECT,
GTK_STOCK_OK,
GTK_RESPONSE_ACCEPT,
NULL);
log_check = gtk_check_button_new_with_label("Logging (For Debugging):");
int_label = gtk_label_new ("Interlacing: (F5 to toggle)");
int_box = gtk_combo_box_new_text ();
gtk_combo_box_append_text(GTK_COMBO_BOX(int_box), "No Interlacing");
gtk_combo_box_append_text(GTK_COMBO_BOX(int_box), "Interlace 0");
gtk_combo_box_append_text(GTK_COMBO_BOX(int_box), "Interlace 1");
gtk_combo_box_set_active(GTK_COMBO_BOX(int_box), conf.interlace);
log_check = gtk_check_button_new_with_label("Logging (For Debugging):");
int_label = gtk_label_new("Interlacing: (F5 to toggle)");
int_box = gtk_combo_box_new_text();
gtk_combo_box_append_text(GTK_COMBO_BOX(int_box), "No Interlacing");
gtk_combo_box_append_text(GTK_COMBO_BOX(int_box), "Interlace 0");
gtk_combo_box_append_text(GTK_COMBO_BOX(int_box), "Interlace 1");
gtk_combo_box_set_active(GTK_COMBO_BOX(int_box), conf.interlace);
bilinear_check = gtk_check_button_new_with_label("Bilinear Filtering (Shift + F5)");
bilinear_label = gtk_label_new ("Best quality is off. Turn on for speed.");
bilinear_check = gtk_check_button_new_with_label("Bilinear Filtering (Shift + F5)");
bilinear_label = gtk_label_new("Best quality is off. Turn on for speed.");
aa_label = gtk_label_new ("Anti-Aliasing for Higher Quality(F6)");
aa_box = gtk_combo_box_new_text ();
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "1X - No Anti-Aliasing");
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "2X - Anti-Aliasing x 2");
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "4X - Anti-Aliasing x 4");
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "8X - Anti-Aliasing x 8");
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "16X - Anti-Aliasing x 16");
gtk_combo_box_set_active(GTK_COMBO_BOX(aa_box), conf.aa);
aa_label = gtk_label_new("Anti-Aliasing for Higher Quality(F6)");
aa_box = gtk_combo_box_new_text();
wireframe_check = gtk_check_button_new_with_label("Wireframe Rendering(Shift + F6)");
avi_check = gtk_check_button_new_with_label("Capture Avi (as zerogs.avi)(F7)");
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "1X - No Anti-Aliasing");
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "2X - Anti-Aliasing x 2");
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "4X - Anti-Aliasing x 4");
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "8X - Anti-Aliasing x 8");
gtk_combo_box_append_text(GTK_COMBO_BOX(aa_box), "16X - Anti-Aliasing x 16");
gtk_combo_box_set_active(GTK_COMBO_BOX(aa_box), conf.aa);
snap_label = gtk_label_new ("Snapshot format:");
snap_box = gtk_combo_box_new_text ();
gtk_combo_box_append_text(GTK_COMBO_BOX(snap_box), "JPEG");
gtk_combo_box_append_text(GTK_COMBO_BOX(snap_box), "TIFF");
gtk_combo_box_set_active(GTK_COMBO_BOX(snap_box), conf.options&GSOPTION_TGASNAP);
wireframe_check = gtk_check_button_new_with_label("Wireframe Rendering(Shift + F6)");
avi_check = gtk_check_button_new_with_label("Capture Avi (as zerogs.avi)(F7)");
fullscreen_check = gtk_check_button_new_with_label("Fullscreen (Alt + Enter)");
snap_label = gtk_label_new("Snapshot format:");
snap_box = gtk_combo_box_new_text();
gtk_combo_box_append_text(GTK_COMBO_BOX(snap_box), "JPEG");
gtk_combo_box_append_text(GTK_COMBO_BOX(snap_box), "TIFF");
gtk_combo_box_set_active(GTK_COMBO_BOX(snap_box), conf.options & GSOPTION_TGASNAP);
fullscreen_check = gtk_check_button_new_with_label("Fullscreen (Alt + Enter)");
widescreen_check = gtk_check_button_new_with_label("Widescreen");
size_label = gtk_label_new ("Default Window Size: (no speed impact)");
size_box = gtk_combo_box_new_text ();
gtk_combo_box_append_text(GTK_COMBO_BOX(size_box), "640x480");
gtk_combo_box_append_text(GTK_COMBO_BOX(size_box), "800x600");
gtk_combo_box_append_text(GTK_COMBO_BOX(size_box), "1024x768");
gtk_combo_box_append_text(GTK_COMBO_BOX(size_box), "1280x960");
gtk_combo_box_set_active(GTK_COMBO_BOX(size_box), (conf.options&GSOPTION_WINDIMS)>>4);
size_label = gtk_label_new("Default Window Size: (no speed impact)");
main_box = gtk_hbox_new(false, 5);
main_frame = gtk_frame_new ("ZZOgl PG Config");
gtk_container_add (GTK_CONTAINER(main_frame), main_box);
size_box = gtk_combo_box_new_text();
option_box = gtk_vbox_new(false, 5);
option_frame = gtk_frame_new ("");
gtk_container_add (GTK_CONTAINER(option_frame), option_box);
gtk_combo_box_append_text(GTK_COMBO_BOX(size_box), "640x480");
gtk_combo_box_append_text(GTK_COMBO_BOX(size_box), "800x600");
gtk_combo_box_append_text(GTK_COMBO_BOX(size_box), "1024x768");
gtk_combo_box_append_text(GTK_COMBO_BOX(size_box), "1280x960");
advanced_box = gtk_vbox_new(false, 5);
advanced_frame = gtk_frame_new ("Advanced Settings:");
gtk_container_add (GTK_CONTAINER(advanced_frame), advanced_box);
gtk_combo_box_set_active(GTK_COMBO_BOX(size_box), (conf.options&GSOPTION_WINDIMS) >> 4);
main_box = gtk_hbox_new(false, 5);
main_frame = gtk_frame_new("ZZOgl PG Config");
gtk_container_add(GTK_CONTAINER(main_frame), main_box);
option_box = gtk_vbox_new(false, 5);
option_frame = gtk_frame_new("");
gtk_container_add(GTK_CONTAINER(option_frame), option_box);
advanced_box = gtk_vbox_new(false, 5);
advanced_frame = gtk_frame_new("Advanced Settings:");
gtk_container_add(GTK_CONTAINER(advanced_frame), advanced_box);
tree = gtk_tree_view_new();
CreateGameHackTable(tree);
advanced_scroll = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(advanced_scroll), tree);
gtk_box_pack_start(GTK_BOX(option_box), log_check, false, false, 2);
@ -298,68 +319,80 @@ void DisplayDialog()
gtk_box_pack_start(GTK_BOX(option_box), widescreen_check, false, false, 2);
gtk_box_pack_start(GTK_BOX(option_box), size_label, false, false, 2);
gtk_box_pack_start(GTK_BOX(option_box), size_box, false, false, 2);
gtk_box_pack_start(GTK_BOX(advanced_box), advanced_scroll, true, true, 2);
gtk_box_pack_start(GTK_BOX(main_box), option_frame, false, false, 2);
gtk_box_pack_start(GTK_BOX(main_box), advanced_frame, true, true, 2);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(log_check), conf.log);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bilinear_check), conf.bilinear);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wireframe_check), (conf.options & GSOPTION_WIREFRAME));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(avi_check), (conf.options & GSOPTION_CAPTUREAVI));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fullscreen_check), (conf.options & GSOPTION_FULLSCREEN));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widescreen_check), (conf.options & GSOPTION_WIDESCREEN));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(log_check), conf.log);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bilinear_check), conf.bilinear);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wireframe_check), (conf.options & GSOPTION_WIREFRAME));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(avi_check), (conf.options & GSOPTION_CAPTUREAVI));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fullscreen_check), (conf.options & GSOPTION_FULLSCREEN));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widescreen_check), (conf.options & GSOPTION_WIDESCREEN));
gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), main_frame);
gtk_widget_show_all (dialog);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), main_frame);
return_value = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_show_all(dialog);
if (return_value == GTK_RESPONSE_ACCEPT)
{
int fake_options = 0;
SaveGameHackTable(tree);
return_value = gtk_dialog_run(GTK_DIALOG(dialog));
if (gtk_combo_box_get_active(GTK_COMBO_BOX(int_box)) != -1)
if (return_value == GTK_RESPONSE_ACCEPT)
{
int fake_options = 0;
SaveGameHackTable(tree);
if (gtk_combo_box_get_active(GTK_COMBO_BOX(int_box)) != -1)
conf.interlace = gtk_combo_box_get_active(GTK_COMBO_BOX(int_box));
if (gtk_combo_box_get_active(GTK_COMBO_BOX(aa_box)) != -1)
if (gtk_combo_box_get_active(GTK_COMBO_BOX(aa_box)) != -1)
conf.aa = gtk_combo_box_get_active(GTK_COMBO_BOX(aa_box));
conf.negaa = 0;
switch(gtk_combo_box_get_active(GTK_COMBO_BOX(size_box)))
switch (gtk_combo_box_get_active(GTK_COMBO_BOX(size_box)))
{
case 0: fake_options |= GSOPTION_WIN640; break;
case 1: fake_options |= GSOPTION_WIN800; break;
case 2: fake_options |= GSOPTION_WIN1024; break;
case 3: fake_options |= GSOPTION_WIN1280; break;
case 0:
fake_options |= GSOPTION_WIN640;
break;
case 1:
fake_options |= GSOPTION_WIN800;
break;
case 2:
fake_options |= GSOPTION_WIN1024;
break;
case 3:
fake_options |= GSOPTION_WIN1280;
break;
}
conf.log = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(log_check));
conf.bilinear = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(bilinear_check));
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wireframe_check)))
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wireframe_check)))
fake_options |= GSOPTION_WIREFRAME;
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(avi_check)))
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(avi_check)))
fake_options |= GSOPTION_CAPTUREAVI;
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fullscreen_check)))
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fullscreen_check)))
fake_options |= GSOPTION_FULLSCREEN;
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widescreen_check)))
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widescreen_check)))
fake_options |= GSOPTION_WIDESCREEN;
if (gtk_combo_box_get_active(GTK_COMBO_BOX(snap_box)) == 1)
if (gtk_combo_box_get_active(GTK_COMBO_BOX(snap_box)) == 1)
fake_options |= GSOPTION_TGASNAP;
conf.options = fake_options;
SaveConfig();
}
gtk_widget_destroy (dialog);
SaveConfig();
}
gtk_widget_destroy(dialog);
}
void CALLBACK GSconfigure()
@ -374,23 +407,26 @@ void CALLBACK GSconfigure()
void SysMessage(const char *fmt, ...)
{
va_list list;
char msg[512];
va_list list;
char msg[512];
va_start(list, fmt);
vsprintf(msg, fmt, list);
va_end(list);
va_start(list, fmt);
vsprintf(msg, fmt, list);
va_end(list);
if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0;
if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0;
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"%s", msg);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
GtkWidget *dialog;
dialog = gtk_message_dialog_new(NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"%s", msg);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
void CALLBACK GSabout()
@ -411,7 +447,9 @@ void *SysLoadLibrary(char *lib)
void *SysLoadSym(void *lib, char *sym)
{
void *ret = dlsym(lib, sym);
if (ret == NULL) printf("null: %s\n", sym);
return dlsym(lib, sym);
}

View File

@ -57,8 +57,8 @@ static __forceinline const T* AlignOnBlockBoundry(TransferData data, TransferFun
{
/* hack */
int testwidth = (int)nSize -
(gs.imageEndY - gs.imageY) * (gs.imageEndX - gs.trxpos.dx)
+ (gs.imageX - gs.trxpos.dx);
(gs.imageEndY - gs.imageY) * (gs.imageEndX - gs.trxpos.dx)
+ (gs.imageX - gs.trxpos.dx);
if ((testwidth <= data.widthlimit) && (testwidth >= -data.widthlimit))
{
@ -67,17 +67,19 @@ static __forceinline const T* AlignOnBlockBoundry(TransferData data, TransferFun
//ZZLog::Error_Log("Bad texture: testwidth = %d; data.widthlimit = %d", testwidth, data.widthlimit);
gs.imageTransfer = -1;
}
bCanAlign = false;
}
/* first align on block boundary */
if ( MOD_POW2(gs.imageY, data.blockheight) || !bCanAlign )
if (MOD_POW2(gs.imageY, data.blockheight) || !bCanAlign)
{
u32 transwidth;
if( !bCanAlign )
if (!bCanAlign)
endY = gs.imageEndY; /* transfer the whole image */
else
assert( endY < gs.imageEndY); /* part of alignment condition */
assert(endY < gs.imageEndY); /* part of alignment condition */
if (((gs.imageEndX - gs.trxpos.dx) % data.widthlimit) || ((gs.imageEndX - gs.imageX) % data.widthlimit))
{
@ -90,10 +92,12 @@ static __forceinline const T* AlignOnBlockBoundry(TransferData data, TransferFun
}
pbuf = TransmitHostLocalY<T>(data, fun.wp, transwidth, endY, pbuf);
if (pbuf == NULL) return NULL;
if( nSize == 0 || tempY == gs.imageEndY ) return NULL;
if (nSize == 0 || tempY == gs.imageEndY) return NULL;
}
return pbuf;
}
@ -112,43 +116,45 @@ static __forceinline const T* TransferAligningToBlocks(TransferData data, Transf
/* on top of checking whether pbuf is aligned, make sure that the width is at least aligned to its limits (due to bugs in pcsx2) */
bAligned = !((uptr)pbuf & 0xf) && (TransPitch(pitch, data.transfersize) & 0xf) == 0;
if ( bAligned || ((DSTPSM==PSMCT24) || (DSTPSM==PSMT8H) || (DSTPSM==PSMT4HH) || (DSTPSM==PSMT4HL)))
if (bAligned || ((DSTPSM == PSMCT24) || (DSTPSM == PSMT8H) || (DSTPSM == PSMT4HH) || (DSTPSM == PSMT4HL)))
swizzle = (fun.Swizzle);
else
swizzle = (fun.Swizzle_u);
//Transfer aligning to blocks.
for(; tempY < alignedPt.y && nSize >= area; tempY += data.blockheight, nSize -= area)
for (; tempY < alignedPt.y && nSize >= area; tempY += data.blockheight, nSize -= area)
{
for(int tempj = gs.trxpos.dx; tempj < alignedPt.x; tempj += data.blockwidth, pbuf += TransPitch(data.blockwidth, data.transfersize)/TSize)
for (int tempj = gs.trxpos.dx; tempj < alignedPt.x; tempj += data.blockwidth, pbuf += TransPitch(data.blockwidth, data.transfersize) / TSize)
{
u8 *temp = pstart + fun.gp(tempj, tempY, gs.dstbuf.bw) * data.blockbits/8;
swizzle(temp, (u8*)pbuf, TransPitch(pitch, data.transfersize), 0xffffffff);
u8 *temp = pstart + fun.gp(tempj, tempY, gs.dstbuf.bw) * data.blockbits / 8;
swizzle(temp, (u8*)pbuf, TransPitch(pitch, data.transfersize), 0xffffffff);
}
/* transfer the rest */
if (alignedPt.x < gs.imageEndX)
{
pbuf = TransmitHostLocalX<T>(data, fun.wp, data.widthlimit, data.blockheight, alignedPt.x, pbuf);
if (pbuf == NULL) return NULL;
pbuf -= TransPitch((alignedPt.x - gs.trxpos.dx), data.transfersize)/TSize;
pbuf -= TransPitch((alignedPt.x - gs.trxpos.dx), data.transfersize) / TSize;
}
else
{
pbuf += (data.blockheight - 1)* TransPitch(pitch, data.transfersize)/TSize;
pbuf += (data.blockheight - 1) * TransPitch(pitch, data.transfersize) / TSize;
}
tempX = gs.trxpos.dx;
}
return pbuf;
}
static __forceinline int FinishTransfer(TransferData data, int nLeftOver)
{
if( tempY >= gs.imageEndY )
if (tempY >= gs.imageEndY)
{
assert( gs.imageTransfer == -1 || tempY == gs.imageEndY );
assert(gs.imageTransfer == -1 || tempY == gs.imageEndY);
gs.imageTransfer = -1;
/*int start, end;
ZeroGS::GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
@ -161,22 +167,23 @@ static __forceinline int FinishTransfer(TransferData data, int nLeftOver)
gs.imageX = tempX;
}
return (nSize * TransPitch(2, data.transfersize) + nLeftOver)/2;
return (nSize * TransPitch(2, data.transfersize) + nLeftOver) / 2;
}
template <class T>
static __forceinline int RealTransfer(TransferData data, TransferFuncts fun, const void* pbyMem, u32 nQWordSize)
{
assert( gs.imageTransfer == 0 );
assert(gs.imageTransfer == 0);
pstart = g_pbyGSMemory + gs.dstbuf.bp*256;
pstart = g_pbyGSMemory + gs.dstbuf.bp * 256;
const T* pbuf = (const T*)pbyMem;
const int tp2 = TransPitch(2, data.transfersize);
int nLeftOver = (nQWordSize*4*2)%tp2;
tempY = gs.imageY; tempX = gs.imageX;
int nLeftOver = (nQWordSize * 4 * 2) % tp2;
tempY = gs.imageY;
tempX = gs.imageX;
Point alignedPt;
nSize = (nQWordSize*4*2)/tp2;
nSize = (nQWordSize * 4 * 2) / tp2;
nSize = min(nSize, gs.imageWnew * gs.imageHnew);
int endY = ROUND_UPPOW2(gs.imageY, data.blockheight);
@ -184,17 +191,21 @@ static __forceinline int RealTransfer(TransferData data, TransferFuncts fun, con
alignedPt.x = ROUND_DOWNPOW2(gs.imageEndX, data.blockwidth);
pbuf = AlignOnBlockBoundry<T>(data, fun, alignedPt, endY, pbuf);
if (pbuf == NULL) return FinishTransfer(data, nLeftOver);
pbuf = TransferAligningToBlocks<T>(data, fun, alignedPt, pbuf);
if (pbuf == NULL) return FinishTransfer(data, nLeftOver);
if (TransPitch(nSize, data.transfersize)/4 > 0)
if (TransPitch(nSize, data.transfersize) / 4 > 0)
{
pbuf = TransmitHostLocalY<T>(data, fun.wp, data.widthlimit, gs.imageEndY, pbuf);
if (pbuf == NULL) return FinishTransfer(data, nLeftOver);
/* sometimes wrong sizes are sent (tekken tag) */
assert( gs.imageTransfer == -1 || TransPitch(nSize, data.transfersize)/4 <= 2 );
assert(gs.imageTransfer == -1 || TransPitch(nSize, data.transfersize) / 4 <= 2);
}
return FinishTransfer(data, nLeftOver);
@ -203,7 +214,7 @@ static __forceinline int RealTransfer(TransferData data, TransferFuncts fun, con
//DEFINE_TRANSFERLOCAL(32, u32, 2, 32, 8, 8, _, SwizzleBlock32);
int TransferHostLocal32(const void* pbyMem, u32 nQWordSize)
{
TransferData data(2,32,8,8,32, PSM_);
TransferData data(2, 32, 8, 8, 32, PSM_);
TransferFuncts fun(writePixel32_0, getPixelAddress32_0, SwizzleBlock32, SwizzleBlock32u);
return RealTransfer<u32>(data, fun, pbyMem, nQWordSize);
@ -212,7 +223,7 @@ int TransferHostLocal32(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(32Z, u32, 2, 32, 8, 8, _, SwizzleBlock32);
int TransferHostLocal32Z(const void* pbyMem, u32 nQWordSize)
{
TransferData data(2,32,8,8,32, PSM_);
TransferData data(2, 32, 8, 8, 32, PSM_);
TransferFuncts fun(writePixel32Z_0, getPixelAddress32Z_0, SwizzleBlock32, SwizzleBlock32u);
return RealTransfer<u32>(data, fun, pbyMem, nQWordSize);
@ -221,7 +232,7 @@ int TransferHostLocal32Z(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(24, u8, 8, 32, 8, 8, _24, SwizzleBlock24);
int TransferHostLocal24(const void* pbyMem, u32 nQWordSize)
{
TransferData data(8,32,8,8,24, PSM_24_);
TransferData data(8, 32, 8, 8, 24, PSM_24_);
TransferFuncts fun(writePixel24_0, getPixelAddress24_0, SwizzleBlock24, SwizzleBlock24u);
return RealTransfer<u8>(data, fun, pbyMem, nQWordSize);
@ -230,7 +241,7 @@ int TransferHostLocal24(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(24Z, u8, 8, 32, 8, 8, _24, SwizzleBlock24);
int TransferHostLocal24Z(const void* pbyMem, u32 nQWordSize)
{
TransferData data(8,32,8,8,24, PSM_24_);
TransferData data(8, 32, 8, 8, 24, PSM_24_);
TransferFuncts fun(writePixel24Z_0, getPixelAddress24Z_0, SwizzleBlock24, SwizzleBlock24u);
return RealTransfer<u8>(data, fun, pbyMem, nQWordSize);
@ -239,7 +250,7 @@ int TransferHostLocal24Z(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(16, u16, 4, 16, 16, 8, _, SwizzleBlock16);
int TransferHostLocal16(const void* pbyMem, u32 nQWordSize)
{
TransferData data(4,16,16,8,16, PSM_);
TransferData data(4, 16, 16, 8, 16, PSM_);
TransferFuncts fun(writePixel16_0, getPixelAddress16_0, SwizzleBlock16, SwizzleBlock16u);
return RealTransfer<u16>(data, fun, pbyMem, nQWordSize);
@ -248,7 +259,7 @@ int TransferHostLocal16(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(16S, u16, 4, 16, 16, 8, _, SwizzleBlock16);
int TransferHostLocal16S(const void* pbyMem, u32 nQWordSize)
{
TransferData data(4,16,16,8,16, PSM_);
TransferData data(4, 16, 16, 8, 16, PSM_);
TransferFuncts fun(writePixel16S_0, getPixelAddress16S_0, SwizzleBlock16, SwizzleBlock16u);
return RealTransfer<u16>(data, fun, pbyMem, nQWordSize);
@ -257,7 +268,7 @@ int TransferHostLocal16S(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(16Z, u16, 4, 16, 16, 8, _, SwizzleBlock16);
int TransferHostLocal16Z(const void* pbyMem, u32 nQWordSize)
{
TransferData data(4,16,16,8,16, PSM_);
TransferData data(4, 16, 16, 8, 16, PSM_);
TransferFuncts fun(writePixel16Z_0, getPixelAddress16Z_0, SwizzleBlock16, SwizzleBlock16u);
return RealTransfer<u16>(data, fun, pbyMem, nQWordSize);
@ -266,7 +277,7 @@ int TransferHostLocal16Z(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(16SZ, u16, 4, 16, 16, 8, _, SwizzleBlock16);
int TransferHostLocal16SZ(const void* pbyMem, u32 nQWordSize)
{
TransferData data(4,16,16,8,16, PSM_);
TransferData data(4, 16, 16, 8, 16, PSM_);
TransferFuncts fun(writePixel16SZ_0, getPixelAddress16SZ_0, SwizzleBlock16, SwizzleBlock16u);
return RealTransfer<u16>(data, fun, pbyMem, nQWordSize);
@ -275,7 +286,7 @@ int TransferHostLocal16SZ(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(8, u8, 4, 8, 16, 16, _, SwizzleBlock8);
int TransferHostLocal8(const void* pbyMem, u32 nQWordSize)
{
TransferData data(4,8,16,16,8, PSM_);
TransferData data(4, 8, 16, 16, 8, PSM_);
TransferFuncts fun(writePixel8_0, getPixelAddress8_0, SwizzleBlock8, SwizzleBlock8u);
return RealTransfer<u8>(data, fun, pbyMem, nQWordSize);
@ -284,7 +295,7 @@ int TransferHostLocal8(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(4, u8, 8, 4, 32, 16, _4, SwizzleBlock4);
int TransferHostLocal4(const void* pbyMem, u32 nQWordSize)
{
TransferData data(8,4,32,16,4, PSM_4_);
TransferData data(8, 4, 32, 16, 4, PSM_4_);
TransferFuncts fun(writePixel4_0, getPixelAddress4_0, SwizzleBlock4, SwizzleBlock4u);
return RealTransfer<u8>(data, fun, pbyMem, nQWordSize);
@ -293,7 +304,7 @@ int TransferHostLocal4(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(8H, u8, 4, 32, 8, 8, _, SwizzleBlock8H);
int TransferHostLocal8H(const void* pbyMem, u32 nQWordSize)
{
TransferData data(4,32,8,8,8, PSM_);
TransferData data(4, 32, 8, 8, 8, PSM_);
TransferFuncts fun(writePixel8H_0, getPixelAddress8H_0, SwizzleBlock8H, SwizzleBlock8Hu);
return RealTransfer<u8>(data, fun, pbyMem, nQWordSize);
@ -302,7 +313,7 @@ int TransferHostLocal8H(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(4HL, u8, 8, 32, 8, 8, _4, SwizzleBlock4HL);
int TransferHostLocal4HL(const void* pbyMem, u32 nQWordSize)
{
TransferData data(8,32,8,8,4, PSM_4_);
TransferData data(8, 32, 8, 8, 4, PSM_4_);
TransferFuncts fun(writePixel4HL_0, getPixelAddress4HL_0, SwizzleBlock4HL, SwizzleBlock4HLu);
return RealTransfer<u8>(data, fun, pbyMem, nQWordSize);
@ -311,7 +322,7 @@ int TransferHostLocal4HL(const void* pbyMem, u32 nQWordSize)
//DEFINE_TRANSFERLOCAL(4HH, u8, 8, 32, 8, 8, _4, SwizzleBlock4HH);
int TransferHostLocal4HH(const void* pbyMem, u32 nQWordSize)
{
TransferData data(8,32,8,8,4, PSM_4_);
TransferData data(8, 32, 8, 8, 4, PSM_4_);
TransferFuncts fun(writePixel4HH_0, getPixelAddress4HH_0, SwizzleBlock4HH, SwizzleBlock4HHu);
return RealTransfer<u8>(data, fun, pbyMem, nQWordSize);
@ -387,19 +398,25 @@ void BLOCK::FillBlocks(vector<char>& vBlockData, vector<char>& vBilinearData, in
{
FUNCLOG
vBlockData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * (floatfmt ? 4 : 2));
if( floatfmt )
if (floatfmt)
vBilinearData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * sizeof(Vector));
int i, j;
BLOCK b;
float* psrcf = NULL;
u16* psrcw = NULL;
Vector* psrcv = NULL;
memset(m_Blocks, 0, sizeof(m_Blocks));
// 32
FILL_BLOCK(64, 32, 0, 0, 1, 32, 32);
m_Blocks[PSMCT32] = b;
// 24 (same as 32 except write/readPixel are different)
@ -427,8 +444,8 @@ void BLOCK::FillBlocks(vector<char>& vBlockData, vector<char>& vBilinearData, in
m_Blocks[PSMT4HL].readPixel_0 = readPixel4HL_0;
m_Blocks[PSMT4HL].TransferHostLocal = TransferHostLocal4HL;
m_Blocks[PSMT4HL].TransferLocalHost = TransferLocalHost4HL;
m_Blocks[PSMT4HH] = b;
m_Blocks[PSMT4HH].writePixel = writePixel4HH;
m_Blocks[PSMT4HH].writePixel_0 = writePixel4HH_0;
m_Blocks[PSMT4HH].readPixel = readPixel4HH;

View File

@ -32,30 +32,37 @@ __forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock16_sse2(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock8_sse2(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock4_sse2(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock32u_sse2(dst, src, pitch, WriteMask);
}
__forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock16u_sse2(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock8u_sse2(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock4u_sse2(dst, src, pitch/*, WriteMask*/);
}
#else
__forceinline void SwizzleBlock32(u8 *dst, u8 *src, int pitch, u32 WriteMask)
@ -67,26 +74,32 @@ __forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock16_c(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock8_c(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock4_c(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock32_c(dst, src, pitch, WriteMask);
}
__forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock16_c(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock8_c(dst, src, pitch/*, WriteMask*/);
}
__forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
SwizzleBlock4_c(dst, src, pitch/*, WriteMask*/);
@ -96,16 +109,16 @@ __forceinline void __fastcall SwizzleBlock32_c(u8* dst, u8* src, int srcpitch, u
{
u32* d = &g_columnTable32[0][0];
if(WriteMask == 0xffffffff)
if (WriteMask == 0xffffffff)
{
for(int j = 0; j < 8; j++, d += 8, src += srcpitch)
for(int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++, d += 8, src += srcpitch)
for (int i = 0; i < 8; i++)
((u32*)dst)[d[i]] = ((u32*)src)[i];
}
else
{
for(int j = 0; j < 8; j++, d += 8, src += srcpitch)
for(int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++, d += 8, src += srcpitch)
for (int i = 0; i < 8; i++)
((u32*)dst)[d[i]] = (((u32*)dst)[d[i]] & ~WriteMask) | (((u32*)src)[i] & WriteMask);
}
}
@ -115,16 +128,16 @@ __forceinline void __fastcall SwizzleBlock24_c(u8* dst, u8* src, int srcpitch, u
{
u32* d = &g_columnTable32[0][0];
if(WriteMask == 0x00ffffff)
if (WriteMask == 0x00ffffff)
{
for(int j = 0; j < 8; j++, d += 8, src += srcpitch)
for(int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++, d += 8, src += srcpitch)
for (int i = 0; i < 8; i++)
((u32*)dst)[d[i]] = ((u32*)src)[i];
}
else
{
for(int j = 0; j < 8; j++, d += 8, src += srcpitch)
for(int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++, d += 8, src += srcpitch)
for (int i = 0; i < 8; i++)
((u32*)dst)[d[i]] = (((u32*)dst)[d[i]] & ~WriteMask) | (((u32*)src)[i] & WriteMask);
}
}
@ -133,8 +146,8 @@ __forceinline void __fastcall SwizzleBlock16_c(u8* dst, u8* src, int srcpitch, u
{
u32* d = &g_columnTable16[0][0];
for(int j = 0; j < 8; j++, d += 16, src += srcpitch)
for(int i = 0; i < 16; i++)
for (int j = 0; j < 8; j++, d += 16, src += srcpitch)
for (int i = 0; i < 16; i++)
((u16*)dst)[d[i]] = ((u16*)src)[i];
}
@ -142,8 +155,8 @@ __forceinline void __fastcall SwizzleBlock8_c(u8* dst, u8* src, int srcpitch, u3
{
u32* d = &g_columnTable8[0][0];
for(int j = 0; j < 16; j++, d += 16, src += srcpitch)
for(int i = 0; i < 16; i++)
for (int j = 0; j < 16; j++, d += 16, src += srcpitch)
for (int i = 0; i < 16; i++)
dst[d[i]] = src[i];
}
@ -151,41 +164,45 @@ __forceinline void __fastcall SwizzleBlock4_c(u8* dst, u8* src, int srcpitch, u3
{
u32* d = &g_columnTable4[0][0];
for(int j = 0; j < 16; j++, d += 32, src += srcpitch)
for (int j = 0; j < 16; j++, d += 32, src += srcpitch)
{
for(int i = 0; i < 32; i++)
for (int i = 0; i < 32; i++)
{
u32 addr = d[i];
u8 c = (src[i>>1] >> ((i&1) << 2)) & 0x0f;
u32 shift = (addr&1) << 2;
u8 c = (src[i>>1] >> ((i & 1) << 2)) & 0x0f;
u32 shift = (addr & 1) << 2;
dst[addr >> 1] = (dst[addr >> 1] & (0xf0 >> shift)) | (c << shift);
}
}
}
#endif
__forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch, u32 WriteMask)
{
u8* pnewsrc = src;
u32* pblock = tempblock;
for(int by = 0; by < 7; ++by, pblock += 8, pnewsrc += pitch-24)
for (int by = 0; by < 7; ++by, pblock += 8, pnewsrc += pitch - 24)
{
for(int bx = 0; bx < 8; ++bx, pnewsrc += 3)
for (int bx = 0; bx < 8; ++bx, pnewsrc += 3)
{
pblock[bx] = *(u32*)pnewsrc;
}
}
for(int bx = 0; bx < 7; ++bx, pnewsrc += 3)
for (int bx = 0; bx < 7; ++bx, pnewsrc += 3)
{
/* might be 1 byte out of bounds of GS memory */
pblock[bx] = *(u32*)pnewsrc;
}
/* do 3 bytes for the last copy */
*((u8*)pblock+28) = pnewsrc[0];
*((u8*)pblock+29) = pnewsrc[1];
*((u8*)pblock+30) = pnewsrc[2];
*((u8*)pblock + 28) = pnewsrc[0];
*((u8*)pblock + 29) = pnewsrc[1];
*((u8*)pblock + 30) = pnewsrc[2];
SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0x00ffffff);
}
@ -194,19 +211,20 @@ __forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch, u32 WriteMask)
u8* pnewsrc = src;
u32* pblock = tempblock;
for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch)
for (int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch)
{
u32 u = *(u32*)pnewsrc;
pblock[0] = u<<24;
pblock[1] = u<<16;
pblock[2] = u<<8;
pblock[0] = u << 24;
pblock[1] = u << 16;
pblock[2] = u << 8;
pblock[3] = u;
u = *(u32*)(pnewsrc+4);
pblock[4] = u<<24;
pblock[5] = u<<16;
pblock[6] = u<<8;
u = *(u32*)(pnewsrc + 4);
pblock[4] = u << 24;
pblock[5] = u << 16;
pblock[6] = u << 8;
pblock[7] = u;
}
SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0xff000000);
}
@ -215,18 +233,19 @@ __forceinline void SwizzleBlock4HH(u8 *dst, u8 *src, int pitch, u32 WriteMask)
u8* pnewsrc = src;
u32* pblock = tempblock;
for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch)
for (int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch)
{
u32 u = *(u32*)pnewsrc;
pblock[0] = u<<28;
pblock[1] = u<<24;
pblock[2] = u<<20;
pblock[3] = u<<16;
pblock[4] = u<<12;
pblock[5] = u<<8;
pblock[6] = u<<4;
pblock[0] = u << 28;
pblock[1] = u << 24;
pblock[2] = u << 20;
pblock[3] = u << 16;
pblock[4] = u << 12;
pblock[5] = u << 8;
pblock[6] = u << 4;
pblock[7] = u;
}
SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0xf0000000);
}
@ -235,17 +254,18 @@ __forceinline void SwizzleBlock4HL(u8 *dst, u8 *src, int pitch, u32 WriteMask)
u8* pnewsrc = src;
u32* pblock = tempblock;
for(int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch)
for (int by = 0; by < 8; ++by, pblock += 8, pnewsrc += pitch)
{
u32 u = *(u32*)pnewsrc;
pblock[0] = u<<24;
pblock[1] = u<<20;
pblock[2] = u<<16;
pblock[3] = u<<12;
pblock[4] = u<<8;
pblock[5] = u<<4;
pblock[0] = u << 24;
pblock[1] = u << 20;
pblock[2] = u << 16;
pblock[3] = u << 12;
pblock[4] = u << 8;
pblock[5] = u << 4;
pblock[6] = u;
pblock[7] = u>>4;
pblock[7] = u >> 4;
}
SwizzleBlock32((u8*)dst, (u8*)tempblock, 32, 0x0f000000);
}

View File

@ -18,212 +18,224 @@
#include "GS.h"
u32 g_blockTable32[4][8] = {
{ 0, 1, 4, 5, 16, 17, 20, 21},
{ 2, 3, 6, 7, 18, 19, 22, 23},
{ 8, 9, 12, 13, 24, 25, 28, 29},
{ 10, 11, 14, 15, 26, 27, 30, 31}
u32 g_blockTable32[4][8] =
{
{ 0, 1, 4, 5, 16, 17, 20, 21},
{ 2, 3, 6, 7, 18, 19, 22, 23},
{ 8, 9, 12, 13, 24, 25, 28, 29},
{ 10, 11, 14, 15, 26, 27, 30, 31}
};
u32 g_blockTable32Z[4][8] = {
{ 24, 25, 28, 29, 8, 9, 12, 13},
{ 26, 27, 30, 31, 10, 11, 14, 15},
{ 16, 17, 20, 21, 0, 1, 4, 5},
{ 18, 19, 22, 23, 2, 3, 6, 7}
u32 g_blockTable32Z[4][8] =
{
{ 24, 25, 28, 29, 8, 9, 12, 13},
{ 26, 27, 30, 31, 10, 11, 14, 15},
{ 16, 17, 20, 21, 0, 1, 4, 5},
{ 18, 19, 22, 23, 2, 3, 6, 7}
};
u32 g_blockTable16[8][4] = {
{ 0, 2, 8, 10 },
{ 1, 3, 9, 11 },
{ 4, 6, 12, 14 },
{ 5, 7, 13, 15 },
{ 16, 18, 24, 26 },
{ 17, 19, 25, 27 },
{ 20, 22, 28, 30 },
{ 21, 23, 29, 31 }
u32 g_blockTable16[8][4] =
{
{ 0, 2, 8, 10 },
{ 1, 3, 9, 11 },
{ 4, 6, 12, 14 },
{ 5, 7, 13, 15 },
{ 16, 18, 24, 26 },
{ 17, 19, 25, 27 },
{ 20, 22, 28, 30 },
{ 21, 23, 29, 31 }
};
u32 g_blockTable16S[8][4] = {
{ 0, 2, 16, 18 },
{ 1, 3, 17, 19 },
{ 8, 10, 24, 26 },
{ 9, 11, 25, 27 },
{ 4, 6, 20, 22 },
{ 5, 7, 21, 23 },
{ 12, 14, 28, 30 },
{ 13, 15, 29, 31 }
u32 g_blockTable16S[8][4] =
{
{ 0, 2, 16, 18 },
{ 1, 3, 17, 19 },
{ 8, 10, 24, 26 },
{ 9, 11, 25, 27 },
{ 4, 6, 20, 22 },
{ 5, 7, 21, 23 },
{ 12, 14, 28, 30 },
{ 13, 15, 29, 31 }
};
u32 g_blockTable16Z[8][4] = {
{ 24, 26, 16, 18 },
{ 25, 27, 17, 19 },
{ 28, 30, 20, 22 },
{ 29, 31, 21, 23 },
{ 8, 10, 0, 2 },
{ 9, 11, 1, 3 },
{ 12, 14, 4, 6 },
{ 13, 15, 5, 7 }
u32 g_blockTable16Z[8][4] =
{
{ 24, 26, 16, 18 },
{ 25, 27, 17, 19 },
{ 28, 30, 20, 22 },
{ 29, 31, 21, 23 },
{ 8, 10, 0, 2 },
{ 9, 11, 1, 3 },
{ 12, 14, 4, 6 },
{ 13, 15, 5, 7 }
};
u32 g_blockTable16SZ[8][4] = {
{ 24, 26, 8, 10 },
{ 25, 27, 9, 11 },
{ 16, 18, 0, 2 },
{ 17, 19, 1, 3 },
{ 28, 30, 12, 14 },
{ 29, 31, 13, 15 },
{ 20, 22, 4, 6 },
{ 21, 23, 5, 7 }
u32 g_blockTable16SZ[8][4] =
{
{ 24, 26, 8, 10 },
{ 25, 27, 9, 11 },
{ 16, 18, 0, 2 },
{ 17, 19, 1, 3 },
{ 28, 30, 12, 14 },
{ 29, 31, 13, 15 },
{ 20, 22, 4, 6 },
{ 21, 23, 5, 7 }
};
u32 g_blockTable8[4][8] = {
{ 0, 1, 4, 5, 16, 17, 20, 21},
{ 2, 3, 6, 7, 18, 19, 22, 23},
{ 8, 9, 12, 13, 24, 25, 28, 29},
{ 10, 11, 14, 15, 26, 27, 30, 31}
u32 g_blockTable8[4][8] =
{
{ 0, 1, 4, 5, 16, 17, 20, 21},
{ 2, 3, 6, 7, 18, 19, 22, 23},
{ 8, 9, 12, 13, 24, 25, 28, 29},
{ 10, 11, 14, 15, 26, 27, 30, 31}
};
u32 g_blockTable4[8][4] = {
{ 0, 2, 8, 10 },
{ 1, 3, 9, 11 },
{ 4, 6, 12, 14 },
{ 5, 7, 13, 15 },
{ 16, 18, 24, 26 },
{ 17, 19, 25, 27 },
{ 20, 22, 28, 30 },
{ 21, 23, 29, 31 }
u32 g_blockTable4[8][4] =
{
{ 0, 2, 8, 10 },
{ 1, 3, 9, 11 },
{ 4, 6, 12, 14 },
{ 5, 7, 13, 15 },
{ 16, 18, 24, 26 },
{ 17, 19, 25, 27 },
{ 20, 22, 28, 30 },
{ 21, 23, 29, 31 }
};
u32 g_columnTable32[8][8] = {
{ 0, 1, 4, 5, 8, 9, 12, 13 },
{ 2, 3, 6, 7, 10, 11, 14, 15 },
{ 16, 17, 20, 21, 24, 25, 28, 29 },
{ 18, 19, 22, 23, 26, 27, 30, 31 },
{ 32, 33, 36, 37, 40, 41, 44, 45 },
{ 34, 35, 38, 39, 42, 43, 46, 47 },
{ 48, 49, 52, 53, 56, 57, 60, 61 },
{ 50, 51, 54, 55, 58, 59, 62, 63 },
u32 g_columnTable32[8][8] =
{
{ 0, 1, 4, 5, 8, 9, 12, 13 },
{ 2, 3, 6, 7, 10, 11, 14, 15 },
{ 16, 17, 20, 21, 24, 25, 28, 29 },
{ 18, 19, 22, 23, 26, 27, 30, 31 },
{ 32, 33, 36, 37, 40, 41, 44, 45 },
{ 34, 35, 38, 39, 42, 43, 46, 47 },
{ 48, 49, 52, 53, 56, 57, 60, 61 },
{ 50, 51, 54, 55, 58, 59, 62, 63 },
};
u32 g_columnTable16[8][16] = {
{ 0, 2, 8, 10, 16, 18, 24, 26,
1, 3, 9, 11, 17, 19, 25, 27 },
{ 4, 6, 12, 14, 20, 22, 28, 30,
5, 7, 13, 15, 21, 23, 29, 31 },
{ 32, 34, 40, 42, 48, 50, 56, 58,
33, 35, 41, 43, 49, 51, 57, 59 },
{ 36, 38, 44, 46, 52, 54, 60, 62,
37, 39, 45, 47, 53, 55, 61, 63 },
{ 64, 66, 72, 74, 80, 82, 88, 90,
65, 67, 73, 75, 81, 83, 89, 91 },
{ 68, 70, 76, 78, 84, 86, 92, 94,
69, 71, 77, 79, 85, 87, 93, 95 },
{ 96, 98, 104, 106, 112, 114, 120, 122,
97, 99, 105, 107, 113, 115, 121, 123 },
{ 100, 102, 108, 110, 116, 118, 124, 126,
101, 103, 109, 111, 117, 119, 125, 127 },
u32 g_columnTable16[8][16] =
{
{ 0, 2, 8, 10, 16, 18, 24, 26,
1, 3, 9, 11, 17, 19, 25, 27 },
{ 4, 6, 12, 14, 20, 22, 28, 30,
5, 7, 13, 15, 21, 23, 29, 31 },
{ 32, 34, 40, 42, 48, 50, 56, 58,
33, 35, 41, 43, 49, 51, 57, 59 },
{ 36, 38, 44, 46, 52, 54, 60, 62,
37, 39, 45, 47, 53, 55, 61, 63 },
{ 64, 66, 72, 74, 80, 82, 88, 90,
65, 67, 73, 75, 81, 83, 89, 91 },
{ 68, 70, 76, 78, 84, 86, 92, 94,
69, 71, 77, 79, 85, 87, 93, 95 },
{ 96, 98, 104, 106, 112, 114, 120, 122,
97, 99, 105, 107, 113, 115, 121, 123 },
{ 100, 102, 108, 110, 116, 118, 124, 126,
101, 103, 109, 111, 117, 119, 125, 127 },
};
u32 g_columnTable8[16][16] = {
u32 g_columnTable8[16][16] =
{
{ 0, 4, 16, 20, 32, 36, 48, 52, // column 0
2, 6, 18, 22, 34, 38, 50, 54 },
{ 8, 12, 24, 28, 40, 44, 56, 60,
10, 14, 26, 30, 42, 46, 58, 62 },
{ 33, 37, 49, 53, 1, 5, 17, 21,
35, 39, 51, 55, 3, 7, 19, 23 },
{ 41, 45, 57, 61, 9, 13, 25, 29,
43, 47, 59, 63, 11, 15, 27, 31 },
2, 6, 18, 22, 34, 38, 50, 54 },
{ 8, 12, 24, 28, 40, 44, 56, 60,
10, 14, 26, 30, 42, 46, 58, 62 },
{ 33, 37, 49, 53, 1, 5, 17, 21,
35, 39, 51, 55, 3, 7, 19, 23 },
{ 41, 45, 57, 61, 9, 13, 25, 29,
43, 47, 59, 63, 11, 15, 27, 31 },
{ 96, 100, 112, 116, 64, 68, 80, 84, // column 1
98, 102, 114, 118, 66, 70, 82, 86 },
{ 104, 108, 120, 124, 72, 76, 88, 92,
106, 110, 122, 126, 74, 78, 90, 94 },
{ 65, 69, 81, 85, 97, 101, 113, 117,
67, 71, 83, 87, 99, 103, 115, 119 },
{ 73, 77, 89, 93, 105, 109, 121, 125,
75, 79, 91, 95, 107, 111, 123, 127 },
98, 102, 114, 118, 66, 70, 82, 86 },
{ 104, 108, 120, 124, 72, 76, 88, 92,
106, 110, 122, 126, 74, 78, 90, 94 },
{ 65, 69, 81, 85, 97, 101, 113, 117,
67, 71, 83, 87, 99, 103, 115, 119 },
{ 73, 77, 89, 93, 105, 109, 121, 125,
75, 79, 91, 95, 107, 111, 123, 127 },
{ 128, 132, 144, 148, 160, 164, 176, 180, // column 2
130, 134, 146, 150, 162, 166, 178, 182 },
{ 136, 140, 152, 156, 168, 172, 184, 188,
138, 142, 154, 158, 170, 174, 186, 190 },
{ 161, 165, 177, 181, 129, 133, 145, 149,
163, 167, 179, 183, 131, 135, 147, 151 },
{ 169, 173, 185, 189, 137, 141, 153, 157,
171, 175, 187, 191, 139, 143, 155, 159 },
130, 134, 146, 150, 162, 166, 178, 182 },
{ 136, 140, 152, 156, 168, 172, 184, 188,
138, 142, 154, 158, 170, 174, 186, 190 },
{ 161, 165, 177, 181, 129, 133, 145, 149,
163, 167, 179, 183, 131, 135, 147, 151 },
{ 169, 173, 185, 189, 137, 141, 153, 157,
171, 175, 187, 191, 139, 143, 155, 159 },
{ 224, 228, 240, 244, 192, 196, 208, 212, // column 3
226, 230, 242, 246, 194, 198, 210, 214 },
{ 232, 236, 248, 252, 200, 204, 216, 220,
234, 238, 250, 254, 202, 206, 218, 222 },
{ 193, 197, 209, 213, 225, 229, 241, 245,
195, 199, 211, 215, 227, 231, 243, 247 },
{ 201, 205, 217, 221, 233, 237, 249, 253,
203, 207, 219, 223, 235, 239, 251, 255 },
226, 230, 242, 246, 194, 198, 210, 214 },
{ 232, 236, 248, 252, 200, 204, 216, 220,
234, 238, 250, 254, 202, 206, 218, 222 },
{ 193, 197, 209, 213, 225, 229, 241, 245,
195, 199, 211, 215, 227, 231, 243, 247 },
{ 201, 205, 217, 221, 233, 237, 249, 253,
203, 207, 219, 223, 235, 239, 251, 255 },
};
u32 g_columnTable4[16][32] = {
u32 g_columnTable4[16][32] =
{
{ 0, 8, 32, 40, 64, 72, 96, 104, // column 0
2, 10, 34, 42, 66, 74, 98, 106,
4, 12, 36, 44, 68, 76, 100, 108,
6, 14, 38, 46, 70, 78, 102, 110 },
{ 16, 24, 48, 56, 80, 88, 112, 120,
18, 26, 50, 58, 82, 90, 114, 122,
20, 28, 52, 60, 84, 92, 116, 124,
22, 30, 54, 62, 86, 94, 118, 126 },
{ 65, 73, 97, 105, 1, 9, 33, 41,
67, 75, 99, 107, 3, 11, 35, 43,
69, 77, 101, 109, 5, 13, 37, 45,
71, 79, 103, 111, 7, 15, 39, 47 },
{ 81, 89, 113, 121, 17, 25, 49, 57,
83, 91, 115, 123, 19, 27, 51, 59,
85, 93, 117, 125, 21, 29, 53, 61,
87, 95, 119, 127, 23, 31, 55, 63 },
2, 10, 34, 42, 66, 74, 98, 106,
4, 12, 36, 44, 68, 76, 100, 108,
6, 14, 38, 46, 70, 78, 102, 110 },
{ 16, 24, 48, 56, 80, 88, 112, 120,
18, 26, 50, 58, 82, 90, 114, 122,
20, 28, 52, 60, 84, 92, 116, 124,
22, 30, 54, 62, 86, 94, 118, 126 },
{ 65, 73, 97, 105, 1, 9, 33, 41,
67, 75, 99, 107, 3, 11, 35, 43,
69, 77, 101, 109, 5, 13, 37, 45,
71, 79, 103, 111, 7, 15, 39, 47 },
{ 81, 89, 113, 121, 17, 25, 49, 57,
83, 91, 115, 123, 19, 27, 51, 59,
85, 93, 117, 125, 21, 29, 53, 61,
87, 95, 119, 127, 23, 31, 55, 63 },
{ 192, 200, 224, 232, 128, 136, 160, 168, // column 1
194, 202, 226, 234, 130, 138, 162, 170,
196, 204, 228, 236, 132, 140, 164, 172,
198, 206, 230, 238, 134, 142, 166, 174 },
{ 208, 216, 240, 248, 144, 152, 176, 184,
210, 218, 242, 250, 146, 154, 178, 186,
212, 220, 244, 252, 148, 156, 180, 188,
214, 222, 246, 254, 150, 158, 182, 190 },
{ 129, 137, 161, 169, 193, 201, 225, 233,
131, 139, 163, 171, 195, 203, 227, 235,
133, 141, 165, 173, 197, 205, 229, 237,
135, 143, 167, 175, 199, 207, 231, 239 },
{ 145, 153, 177, 185, 209, 217, 241, 249,
147, 155, 179, 187, 211, 219, 243, 251,
149, 157, 181, 189, 213, 221, 245, 253,
151, 159, 183, 191, 215, 223, 247, 255 },
194, 202, 226, 234, 130, 138, 162, 170,
196, 204, 228, 236, 132, 140, 164, 172,
198, 206, 230, 238, 134, 142, 166, 174 },
{ 208, 216, 240, 248, 144, 152, 176, 184,
210, 218, 242, 250, 146, 154, 178, 186,
212, 220, 244, 252, 148, 156, 180, 188,
214, 222, 246, 254, 150, 158, 182, 190 },
{ 129, 137, 161, 169, 193, 201, 225, 233,
131, 139, 163, 171, 195, 203, 227, 235,
133, 141, 165, 173, 197, 205, 229, 237,
135, 143, 167, 175, 199, 207, 231, 239 },
{ 145, 153, 177, 185, 209, 217, 241, 249,
147, 155, 179, 187, 211, 219, 243, 251,
149, 157, 181, 189, 213, 221, 245, 253,
151, 159, 183, 191, 215, 223, 247, 255 },
{ 256, 264, 288, 296, 320, 328, 352, 360, // column 2
258, 266, 290, 298, 322, 330, 354, 362,
260, 268, 292, 300, 324, 332, 356, 364,
262, 270, 294, 302, 326, 334, 358, 366 },
{ 272, 280, 304, 312, 336, 344, 368, 376,
274, 282, 306, 314, 338, 346, 370, 378,
276, 284, 308, 316, 340, 348, 372, 380,
278, 286, 310, 318, 342, 350, 374, 382 },
{ 321, 329, 353, 361, 257, 265, 289, 297,
323, 331, 355, 363, 259, 267, 291, 299,
325, 333, 357, 365, 261, 269, 293, 301,
327, 335, 359, 367, 263, 271, 295, 303 },
{ 337, 345, 369, 377, 273, 281, 305, 313,
339, 347, 371, 379, 275, 283, 307, 315,
341, 349, 373, 381, 277, 285, 309, 317,
343, 351, 375, 383, 279, 287, 311, 319 },
258, 266, 290, 298, 322, 330, 354, 362,
260, 268, 292, 300, 324, 332, 356, 364,
262, 270, 294, 302, 326, 334, 358, 366 },
{ 272, 280, 304, 312, 336, 344, 368, 376,
274, 282, 306, 314, 338, 346, 370, 378,
276, 284, 308, 316, 340, 348, 372, 380,
278, 286, 310, 318, 342, 350, 374, 382 },
{ 321, 329, 353, 361, 257, 265, 289, 297,
323, 331, 355, 363, 259, 267, 291, 299,
325, 333, 357, 365, 261, 269, 293, 301,
327, 335, 359, 367, 263, 271, 295, 303 },
{ 337, 345, 369, 377, 273, 281, 305, 313,
339, 347, 371, 379, 275, 283, 307, 315,
341, 349, 373, 381, 277, 285, 309, 317,
343, 351, 375, 383, 279, 287, 311, 319 },
{ 448, 456, 480, 488, 384, 392, 416, 424, // column 3
450, 458, 482, 490, 386, 394, 418, 426,
452, 460, 484, 492, 388, 396, 420, 428,
454, 462, 486, 494, 390, 398, 422, 430 },
{ 464, 472, 496, 504, 400, 408, 432, 440,
466, 474, 498, 506, 402, 410, 434, 442,
468, 476, 500, 508, 404, 412, 436, 444,
470, 478, 502, 510, 406, 414, 438, 446 },
{ 385, 393, 417, 425, 449, 457, 481, 489,
387, 395, 419, 427, 451, 459, 483, 491,
389, 397, 421, 429, 453, 461, 485, 493,
391, 399, 423, 431, 455, 463, 487, 495 },
{ 401, 409, 433, 441, 465, 473, 497, 505,
403, 411, 435, 443, 467, 475, 499, 507,
405, 413, 437, 445, 469, 477, 501, 509,
407, 415, 439, 447, 471, 479, 503, 511 },
450, 458, 482, 490, 386, 394, 418, 426,
452, 460, 484, 492, 388, 396, 420, 428,
454, 462, 486, 494, 390, 398, 422, 430 },
{ 464, 472, 496, 504, 400, 408, 432, 440,
466, 474, 498, 506, 402, 410, 434, 442,
468, 476, 500, 508, 404, 412, 436, 444,
470, 478, 502, 510, 406, 414, 438, 446 },
{ 385, 393, 417, 425, 449, 457, 481, 489,
387, 395, 419, 427, 451, 459, 483, 491,
389, 397, 421, 429, 453, 461, 485, 493,
391, 399, 423, 431, 455, 463, 487, 495 },
{ 401, 409, 433, 441, 465, 473, 497, 505,
403, 411, 435, 443, 467, 475, 499, 507,
405, 413, 437, 445, 469, 477, 501, 509,
407, 415, 439, 447, 471, 479, 503, 511 },
};
u32 g_pageTable32[32][64];

View File

@ -36,20 +36,23 @@ const u32 g_primsub[8] = { 1, 2, 1, 3, 1, 1, 2, 0 };
#pragma warning(disable:4244)
#endif
GIFRegHandler g_GIFPackedRegHandlers[16] = {
GIFRegHandler g_GIFPackedRegHandlers[16] =
{
GIFRegHandlerPRIM, GIFPackedRegHandlerRGBA, GIFPackedRegHandlerSTQ, GIFPackedRegHandlerUV,
GIFPackedRegHandlerXYZF2, GIFPackedRegHandlerXYZ2, GIFRegHandlerTEX0_1, GIFRegHandlerTEX0_2,
GIFRegHandlerCLAMP_1, GIFRegHandlerCLAMP_2, GIFPackedRegHandlerFOG, GIFPackedRegHandlerNull,
GIFRegHandlerXYZF3, GIFRegHandlerXYZ3, GIFPackedRegHandlerA_D, GIFPackedRegHandlerNOP };
GIFRegHandlerXYZF3, GIFRegHandlerXYZ3, GIFPackedRegHandlerA_D, GIFPackedRegHandlerNOP
};
GIFRegHandler g_GIFRegHandlers[] = {
GIFRegHandler g_GIFRegHandlers[] =
{
GIFRegHandlerPRIM, GIFRegHandlerRGBAQ, GIFRegHandlerST, GIFRegHandlerUV,
GIFRegHandlerXYZF2, GIFRegHandlerXYZ2, GIFRegHandlerTEX0_1, GIFRegHandlerTEX0_2,
GIFRegHandlerCLAMP_1, GIFRegHandlerCLAMP_2, GIFRegHandlerFOG, GIFRegHandlerNull,
GIFRegHandlerXYZF3, GIFRegHandlerXYZ3, GIFRegHandlerNOP, GIFRegHandlerNOP,
GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull,
GIFRegHandlerTEX1_1, GIFRegHandlerTEX1_2, GIFRegHandlerTEX2_1, GIFRegHandlerTEX2_2,
GIFRegHandlerXYOFFSET_1,GIFRegHandlerXYOFFSET_2,GIFRegHandlerPRMODECONT,GIFRegHandlerPRMODE,
GIFRegHandlerXYOFFSET_1, GIFRegHandlerXYOFFSET_2, GIFRegHandlerPRMODECONT, GIFRegHandlerPRMODE,
GIFRegHandlerTEXCLUT, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull,
GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerSCANMSK, GIFRegHandlerNull,
GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull,
@ -67,23 +70,25 @@ GIFRegHandler g_GIFRegHandlers[] = {
GIFRegHandlerHWREG, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull,
GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull,
GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull, GIFRegHandlerNull,
GIFRegHandlerSIGNAL, GIFRegHandlerFINISH, GIFRegHandlerLABEL, GIFRegHandlerNull };
GIFRegHandlerSIGNAL, GIFRegHandlerFINISH, GIFRegHandlerLABEL, GIFRegHandlerNull
};
C_ASSERT(sizeof(g_GIFRegHandlers)/sizeof(g_GIFRegHandlers[0]) == 100 );
C_ASSERT(sizeof(g_GIFRegHandlers) / sizeof(g_GIFRegHandlers[0]) == 100);
// values for keeping track of changes
u32 s_uTex1Data[2][2] = {{0,}};
u32 s_uClampData[2] = {0,};
u32 s_uTex1Data[2][2] = {{0, }};
u32 s_uClampData[2] = {0, };
u32 results[65535] = {0,};
u32 results[65535] = {0, };
// return true if triangle SHOULD be painted.
inline bool NoHighlights(int i) {
inline bool NoHighlights(int i)
{
// This is hack-code, I still in search of correct reason, why some triangles should not be drawn.
// I'd have thought we could just test prim->_val and ZeroGS::vb[i].zbuf.psm directly...
int resultA = prim->iip + ((prim->tme) << 1) + ((prim->fge) << 2) + ((prim->abe) << 3) + ((prim->aa1) << 4) + ((prim->fst) << 5) + ((prim->ctxt) << 6) + ((prim->fix)<< 7) +
((ZeroGS::vb[i].zbuf.psm ) << 8);
int resultA = prim->iip + ((prim->tme) << 1) + ((prim->fge) << 2) + ((prim->abe) << 3) + ((prim->aa1) << 4) + ((prim->fst) << 5) + ((prim->ctxt) << 6) + ((prim->fix) << 7) +
((ZeroGS::vb[i].zbuf.psm) << 8);
// if ( results[resultA] == 0 ) {
// results[resultA] = 1;
// ZZLog::Error_Log("%x = %d %d %d %d %d %d %d %d psm: %x", resultA, prim->iip, (prim->tme), (prim->fge), (prim->abe) , (prim->aa1) ,(prim->fst), (prim->ctxt), (prim->fix), ZeroGS::vb[i].zbuf.psm) ;
@ -92,7 +97,7 @@ inline bool NoHighlights(int i) {
const pixTest curtest = ZeroGS::vb[i].test;
// Again, couldn't we just test curtest._val?
int result = curtest.ate + ((curtest.atst) << 1) +((curtest.afail) << 4) + ((curtest.date) << 6) + ((curtest.datm) << 7) + ((curtest.zte) << 8) + ((curtest.ztst)<< 9);
int result = curtest.ate + ((curtest.atst) << 1) + ((curtest.afail) << 4) + ((curtest.date) << 6) + ((curtest.datm) << 7) + ((curtest.zte) << 8) + ((curtest.ztst) << 9);
// if (resultA == 0xb)
// if ( results[result] == 0) {
// results[result] = 1;
@ -102,6 +107,7 @@ inline bool NoHighlights(int i) {
// if (result == 0x50b && ZeroGS::vb[i].zbuf.zmsk ) return false; //ATF
// if psm is 16S or 24, tme, abe, & fst are true, the rest are false, result is 0x302 or 0x700, and there is a mask.
if ((resultA == 0x3a2a || resultA == 0x312a) && (result == 0x302 || result == 0x700) && (ZeroGS::vb[i].zbuf.zmsk)) return false; // Silent Hill:SM and Front Mission 5, result != 0x300
// if psm is 24, abe is true, tme doesn't matter, the rest are false, result is 0x54c or 0x50c and there is a mask.
@ -109,12 +115,14 @@ inline bool NoHighlights(int i) {
// if psm is 24, abe & tme are true, the rest are false, and no result.
if ((resultA == 0x310a) && (result == 0x0)) return false; // Radiata Stories
// if psm is 16S, tme, abe, fst, and ctxt are true, the rest are false, result is 0x330 or 0x500, and there is a mask.
if (resultA == 0x3a6a && (result == 0x300 || result == 0x500)&& ZeroGS::vb[i].zbuf.zmsk) return false; // Okami, result != 0x30d
if (resultA == 0x3a6a && (result == 0x300 || result == 0x500) && ZeroGS::vb[i].zbuf.zmsk) return false; // Okami, result != 0x30d
// if ((resultA == 0x300b) && (result == 0x300) && ZeroGS::vb[i].zbuf.zmsk) return false; // ATF, but no Melty Blood
// Old code
return (!(g_GameSettings&GAME_XENOSPECHACK) || !ZeroGS::vb[i].zbuf.zmsk || prim->iip ) ;
return (!(g_GameSettings&GAME_XENOSPECHACK) || !ZeroGS::vb[i].zbuf.zmsk || prim->iip) ;
}
void __fastcall GIFPackedRegHandlerNull(u32* data)
@ -127,9 +135,9 @@ void __fastcall GIFPackedRegHandlerRGBA(u32* data)
{
FUNCLOG
gs.rgba = (data[0] & 0xff) |
((data[1] & 0xff) << 8) |
((data[2] & 0xff) << 16) |
((data[3] & 0xff) << 24);
((data[1] & 0xff) << 8) |
((data[2] & 0xff) << 16) |
((data[3] & 0xff) << 24);
gs.vertexregs.rgba = gs.rgba;
gs.vertexregs.q = gs.q;
}
@ -137,8 +145,8 @@ void __fastcall GIFPackedRegHandlerRGBA(u32* data)
void __fastcall GIFPackedRegHandlerSTQ(u32* data)
{
FUNCLOG
*(u32*)&gs.vertexregs.s = data[0]&0xffffff00;
*(u32*)&gs.vertexregs.t = data[1]&0xffffff00;
*(u32*)&gs.vertexregs.s = data[0] & 0xffffff00;
*(u32*)&gs.vertexregs.t = data[1] & 0xffffff00;
*(u32*)&gs.q = data[2];
}
@ -152,10 +160,11 @@ void __fastcall GIFPackedRegHandlerUV(u32* data)
void __forceinline KICK_VERTEX2()
{
FUNCLOG
if (++gs.primC >= (int)g_primmult[prim->prim])
{
if ( NoHighlights(prim->ctxt) )
(*ZeroGS::drawfn[prim->prim])();
if (NoHighlights(prim->ctxt)) (*ZeroGS::drawfn[prim->prim])();
gs.primC -= g_primsub[prim->prim];
}
}
@ -163,14 +172,16 @@ void __forceinline KICK_VERTEX2()
void __forceinline KICK_VERTEX3()
{
FUNCLOG
if (++gs.primC >= (int)g_primmult[prim->prim])
{
gs.primC -= g_primsub[prim->prim];
if (prim->prim == 5)
{
/* tri fans need special processing */
if (gs.nTriFanVert == gs.primIndex)
gs.primIndex = (gs.primIndex+1)%ArraySize(gs.gsvertex);
gs.primIndex = (gs.primIndex + 1) % ArraySize(gs.gsvertex);
}
}
}
@ -183,12 +194,14 @@ void __fastcall GIFPackedRegHandlerXYZF2(u32* data)
gs.vertexregs.z = (data[2] >> 4) & 0xffffff;
gs.vertexregs.f = (data[3] >> 4) & 0xff;
gs.gsvertex[gs.primIndex] = gs.vertexregs;
gs.primIndex = (gs.primIndex+1)%ArraySize(gs.gsvertex);
gs.primIndex = (gs.primIndex + 1) % ArraySize(gs.gsvertex);
if( data[3] & 0x8000 ) {
if (data[3] & 0x8000)
{
KICK_VERTEX3();
}
else {
else
{
KICK_VERTEX2();
}
}
@ -200,12 +213,14 @@ void __fastcall GIFPackedRegHandlerXYZ2(u32* data)
gs.vertexregs.y = (data[1] >> 0) & 0xffff;
gs.vertexregs.z = data[2];
gs.gsvertex[gs.primIndex] = gs.vertexregs;
gs.primIndex = (gs.primIndex+1)%ArraySize(gs.gsvertex);
gs.primIndex = (gs.primIndex + 1) % ArraySize(gs.gsvertex);
if( data[3] & 0x8000 ) {
if (data[3] & 0x8000)
{
KICK_VERTEX3();
}
else {
else
{
KICK_VERTEX2();
}
}
@ -213,20 +228,22 @@ void __fastcall GIFPackedRegHandlerXYZ2(u32* data)
void __fastcall GIFPackedRegHandlerFOG(u32* data)
{
FUNCLOG
gs.vertexregs.f = (data[3]&0xff0)>>4;
gs.vertexregs.f = (data[3] & 0xff0) >> 4;
}
void __fastcall GIFPackedRegHandlerA_D(u32* data)
{
FUNCLOG
if((data[2] & 0xff) < 100)
if ((data[2] & 0xff) < 100)
g_GIFRegHandlers[data[2] & 0xff](data);
else
GIFRegHandlerNull(data);
}
void __fastcall GIFPackedRegHandlerNOP(u32* data)
{FUNCLOG
{
FUNCLOG
}
extern int g_PrevBitwiseTexX, g_PrevBitwiseTexY;
@ -236,17 +253,19 @@ void tex0Write(int i, u32 *data)
FUNCLOG
u32 psm = ZZOglGet_psm_TexBitsFix(data[0]);
if ( m_Blocks[psm].bpp == 0 )
if (m_Blocks[psm].bpp == 0)
{
// kh and others
return;
}
ZeroGS::vb[i].uNextTex0Data[0] = data[0];
ZeroGS::vb[i].uNextTex0Data[1] = data[1];
ZeroGS::vb[i].bNeedTexCheck = 1;
// don't update unless necessary
if (PSMT_ISCLUT(psm))
{
if (ZeroGS::CheckChangeInClut(data[1], psm))
@ -254,6 +273,7 @@ void tex0Write(int i, u32 *data)
// loading clut, so flush whole texture
ZeroGS::vb[i].FlushTexData();
}
// check if csa is the same!! (ffx bisaid island, grass)
else if ((data[1] & 0x1f780000) != (ZeroGS::vb[i].uCurTex0Data[1] & 0x1f780000))
{
@ -262,11 +282,12 @@ void tex0Write(int i, u32 *data)
}
}
void tex2Write(int i, u32 *data) {
void tex2Write(int i, u32 *data)
{
FUNCLOG
tex0Info& tex0 = ZeroGS::vb[i].tex0;
if( ZeroGS::vb[i].bNeedTexCheck )
if (ZeroGS::vb[i].bNeedTexCheck)
ZeroGS::vb[i].FlushTexData();
u32 psm = ZZOglGet_psm_TexBitsFix(data[0]);
@ -275,43 +296,48 @@ void tex2Write(int i, u32 *data) {
// don't update unless necessary
// if( ZZOglGet_psm_TexBitsFix(*s_uTex0Data) == ZZOglGet_psm_TexBitsFix(data[0]) ) { // psm is the same
if (ZZOglAllExceptClutIsSame(s_uTex0Data, data)) {
if (!PSMT_ISCLUT(psm))
return;
if (ZZOglAllExceptClutIsSame(s_uTex0Data, data))
{
if (!PSMT_ISCLUT(psm)) return;
// have to write the CLUT again if changed
if (ZZOglClutMinusCLDunchanged(s_uTex0Data, data)) {
if (ZZOglClutMinusCLDunchanged(s_uTex0Data, data))
{
tex0.cld = ZZOglGet_cld_TexBits(data[1]);
if (tex0.cld != 0) {
if (tex0.cld != 0)
{
ZeroGS::texClutWrite(i);
// invalidate to make sure target didn't change!
ZeroGS::vb[i].bVarsTexSync = FALSE;
}
return;
}
}
ZeroGS::Flush(i);
ZeroGS::vb[i].bVarsTexSync = FALSE;
ZeroGS::vb[i].bTexConstsSync = FALSE;
s_uTex0Data[0] = (s_uTex0Data[0]&~0x03f00000)|(psm<<20);
s_uTex0Data[1] = (s_uTex0Data[1]&0x1f)|(data[1]&~0x1f);
s_uTex0Data[0] = (s_uTex0Data[0] & ~0x03f00000) | (psm << 20);
s_uTex0Data[1] = (s_uTex0Data[1] & 0x1f) | (data[1] & ~0x1f);
tex0.psm = ZZOglGet_psm_TexBitsFix(data[0]);
tex0.psm = ZZOglGet_psm_TexBitsFix(data[0]);
if( PSMT_ISCLUT(tex0.psm) )
ZeroGS::CluttingForFlushedTex(&tex0, data[1], i);
if (PSMT_ISCLUT(tex0.psm)) ZeroGS::CluttingForFlushedTex(&tex0, data[1], i);
}
__forceinline void frameWrite(int i, u32 *data) {
__forceinline void frameWrite(int i, u32 *data)
{
FUNCLOG
frameInfo& gsfb = ZeroGS::vb[i].gsfb;
if ((gsfb.fbp == ZZOglGet_fbp_FrameBitsMult(data[0])) &&
(gsfb.fbw == ZZOglGet_fbw_FrameBitsMult(data[0])) &&
(gsfb.psm == ZZOglGet_psm_FrameBits(data[0])) &&
(gsfb.fbm == ZZOglGet_fbm_FrameBits(data[0])) )
(gsfb.fbw == ZZOglGet_fbw_FrameBitsMult(data[0])) &&
(gsfb.psm == ZZOglGet_psm_FrameBits(data[0])) &&
(gsfb.fbm == ZZOglGet_fbm_FrameBits(data[0])))
{
return;
}
@ -322,7 +348,7 @@ __forceinline void frameWrite(int i, u32 *data) {
gsfb.fbp = ZZOglGet_fbp_FrameBitsMult(data[0]);
gsfb.fbw = ZZOglGet_fbw_FrameBitsMult(data[0]);
gsfb.psm = ZZOglGet_psm_FrameBits(data[0]);
gsfb.fbm = ZZOglGet_fbm_FrameBitsFix(data[0],data[1]);
gsfb.fbm = ZZOglGet_fbm_FrameBitsFix(data[0], data[1]);
gsfb.fbh = ZZOglGet_fbh_FrameBitsCalc(data[0]);
// gsfb.fbhCalc = gsfb.fbh;
@ -334,10 +360,10 @@ __forceinline void testWrite(int i, u32 *data)
FUNCLOG
pixTest* test = &ZeroGS::vb[i].test;
if( (*(u32*)test & 0x0007ffff) == (data[0] & 0x0007ffff) )
return;
if ((*(u32*)test & 0x0007ffff) == (data[0] & 0x0007ffff)) return;
ZeroGS::Flush(i);
*(u32*)test = data[0];
// test.ate = (data[0] ) & 0x1;
@ -355,16 +381,17 @@ __forceinline void clampWrite(int i, u32 *data)
FUNCLOG
clampInfo& clamp = ZeroGS::vb[i].clamp;
if ((s_uClampData[i] != data[0]) || (((clamp.minv>>8) | (clamp.maxv<<2)) != (data[1]&0x0fff))) {
if ((s_uClampData[i] != data[0]) || (((clamp.minv >> 8) | (clamp.maxv << 2)) != (data[1]&0x0fff)))
{
ZeroGS::Flush(i);
s_uClampData[i] = data[0];
clamp.wms = (data[0] ) & 0x3;
clamp.wms = (data[0]) & 0x3;
clamp.wmt = (data[0] >> 2) & 0x3;
clamp.minu = (data[0] >> 4) & 0x3ff;
clamp.maxu = (data[0] >> 14) & 0x3ff;
clamp.minv =((data[0] >> 24) & 0xff) | ((data[1] & 0x3) << 8);
clamp.minv = ((data[0] >> 24) & 0xff) | ((data[1] & 0x3) << 8);
clamp.maxv = (data[1] >> 2) & 0x3ff;
ZeroGS::vb[i].bTexConstsSync = FALSE;
@ -375,6 +402,7 @@ void __fastcall GIFRegHandlerNull(u32* data)
{
FUNCLOG
#ifdef _DEBUG
if ((((uptr)&data[2])&0xffff) == 0) return;
// 0x7f happens on a lot of games
@ -382,23 +410,26 @@ void __fastcall GIFRegHandlerNull(u32* data)
{
ZZLog::Debug_Log("Unexpected reg handler %x %x %x.", data[0], data[1], data[2]);
}
#endif
}
void __fastcall GIFRegHandlerPRIM(u32 *data)
{
FUNCLOG
if (data[0] & ~0x3ff)
{
//ZZLog::Warn_Log("Warning: unknown bits in prim %8.8lx_%8.8lx", data[1], data[0]);
}
gs.nTriFanVert = gs.primIndex;
gs.primC = 0;
prim->prim = (data[0]) & 0x7;
gs._prim[0].prim = (data[0]) & 0x7;
gs._prim[1].prim = (data[0]) & 0x7;
gs._prim[1]._val = (data[0]>>3)&0xff;
gs._prim[1]._val = (data[0] >> 3) & 0xff;
ZeroGS::Prim();
}
@ -414,8 +445,8 @@ void __fastcall GIFRegHandlerRGBAQ(u32* data)
void __fastcall GIFRegHandlerST(u32* data)
{
FUNCLOG
*(u32*)&gs.vertexregs.s = data[0]&0xffffff00;
*(u32*)&gs.vertexregs.t = data[1]&0xffffff00;
*(u32*)&gs.vertexregs.s = data[0] & 0xffffff00;
*(u32*)&gs.vertexregs.t = data[1] & 0xffffff00;
//*(u32*)&gs.q = data[2];
}
@ -434,7 +465,7 @@ void __fastcall GIFRegHandlerXYZF2(u32* data)
gs.vertexregs.z = data[1] & 0xffffff;
gs.vertexregs.f = data[1] >> 24;
gs.gsvertex[gs.primIndex] = gs.vertexregs;
gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex);
gs.primIndex = (gs.primIndex + 1) % ARRAY_SIZE(gs.gsvertex);
KICK_VERTEX2();
}
@ -446,7 +477,7 @@ void __fastcall GIFRegHandlerXYZ2(u32* data)
gs.vertexregs.y = (data[0] >> (16)) & 0xffff;
gs.vertexregs.z = data[1];
gs.gsvertex[gs.primIndex] = gs.vertexregs;
gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex);
gs.primIndex = (gs.primIndex + 1) % ARRAY_SIZE(gs.gsvertex);
KICK_VERTEX2();
}
@ -454,36 +485,36 @@ void __fastcall GIFRegHandlerXYZ2(u32* data)
void __fastcall GIFRegHandlerTEX0_1(u32* data)
{
FUNCLOG
if( !NoHighlights(0)) {
return;
}
if (!NoHighlights(0)) return;
tex0Write(0, data);
}
void __fastcall GIFRegHandlerTEX0_2(u32* data)
{
FUNCLOG
if( !NoHighlights(1) ) {
return;
}
if (!NoHighlights(1)) return;
tex0Write(1, data);
}
void __fastcall GIFRegHandlerCLAMP_1(u32* data)
{
FUNCLOG
if( !NoHighlights(0) ) {
return;
}
if (!NoHighlights(0)) return;
clampWrite(0, data);
}
void __fastcall GIFRegHandlerCLAMP_2(u32* data)
{
FUNCLOG
if( !NoHighlights(1) ) {
return;
}
if (!NoHighlights(1)) return;
clampWrite(1, data);
}
@ -491,7 +522,7 @@ void __fastcall GIFRegHandlerFOG(u32* data)
{
FUNCLOG
//gs.gsvertex[gs.primIndex].f = (data[1] >> 24); // shift to upper bits
gs.vertexregs.f = data[1]>>24;
gs.vertexregs.f = data[1] >> 24;
}
void __fastcall GIFRegHandlerXYZF3(u32* data)
@ -502,7 +533,7 @@ void __fastcall GIFRegHandlerXYZF3(u32* data)
gs.vertexregs.z = data[1] & 0xffffff;
gs.vertexregs.f = data[1] >> 24;
gs.gsvertex[gs.primIndex] = gs.vertexregs;
gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex);
gs.primIndex = (gs.primIndex + 1) % ARRAY_SIZE(gs.gsvertex);
KICK_VERTEX3();
}
@ -514,7 +545,7 @@ void __fastcall GIFRegHandlerXYZ3(u32* data)
gs.vertexregs.y = (data[0] >> (16)) & 0xffff;
gs.vertexregs.z = data[1];
gs.gsvertex[gs.primIndex] = gs.vertexregs;
gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex);
gs.primIndex = (gs.primIndex + 1) % ARRAY_SIZE(gs.gsvertex);
KICK_VERTEX3();
}
@ -529,11 +560,14 @@ void tex1Write(int i, u32* data)
FUNCLOG
tex1Info& tex1 = ZeroGS::vb[i].tex1;
if( conf.bilinear == 1 && (tex1.mmag != ((data[0] >> 5) & 0x1) || tex1.mmin != ((data[0] >> 6) & 0x7)) ) {
if (conf.bilinear == 1 && (tex1.mmag != ((data[0] >> 5) & 0x1) || tex1.mmin != ((data[0] >> 6) & 0x7)))
{
ZeroGS::Flush(i);
ZeroGS::vb[i].bVarsTexSync = FALSE;
}
tex1.lcm = (data[0] ) & 0x1;
tex1.lcm = (data[0]) & 0x1;
tex1.mxl = (data[0] >> 2) & 0x7;
tex1.mmag = (data[0] >> 5) & 0x1;
tex1.mmin = (data[0] >> 6) & 0x7;
@ -546,9 +580,7 @@ void __fastcall GIFRegHandlerTEX1_1(u32* data)
{
FUNCLOG
if( !NoHighlights(0)) {
return;
}
if (!NoHighlights(0)) return;
tex1Write(0, data);
}
@ -556,8 +588,8 @@ void __fastcall GIFRegHandlerTEX1_1(u32* data)
void __fastcall GIFRegHandlerTEX1_2(u32* data)
{
FUNCLOG
if( !NoHighlights(1) )
return;
if (!NoHighlights(1)) return;
tex1Write(1, data);
}
@ -611,7 +643,7 @@ void __fastcall GIFRegHandlerPRMODECONT(u32* data)
void __fastcall GIFRegHandlerPRMODE(u32* data)
{
FUNCLOG
gs._prim[0]._val = (data[0]>>3)&0xff;
gs._prim[0]._val = (data[0] >> 3) & 0xff;
if (gs.prac == 0)
ZeroGS::Prim();
@ -620,11 +652,11 @@ void __fastcall GIFRegHandlerPRMODE(u32* data)
void __fastcall GIFRegHandlerTEXCLUT(u32* data)
{
FUNCLOG
if( ZeroGS::vb[0].bNeedTexCheck )
ZeroGS::vb[0].FlushTexData();
if( ZeroGS::vb[1].bNeedTexCheck )
ZeroGS::vb[1].FlushTexData();
gs.clut.cbw = ((data[0] ) & 0x3f) * 64;
if (ZeroGS::vb[0].bNeedTexCheck) ZeroGS::vb[0].FlushTexData();
if (ZeroGS::vb[1].bNeedTexCheck) ZeroGS::vb[1].FlushTexData();
gs.clut.cbw = ((data[0]) & 0x3f) * 64;
gs.clut.cou = ((data[0] >> 6) & 0x3f) * 16;
gs.clut.cov = (data[0] >> 12) & 0x3ff;
}
@ -644,7 +676,7 @@ void __fastcall GIFRegHandlerMIPTBP1_1(u32* data)
{
FUNCLOG
miptbpInfo& miptbp0 = ZeroGS::vb[0].miptbp0;
miptbp0.tbp[0] = (data[0] ) & 0x3fff;
miptbp0.tbp[0] = (data[0]) & 0x3fff;
miptbp0.tbw[0] = (data[0] >> 14) & 0x3f;
miptbp0.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12);
miptbp0.tbw[1] = (data[1] >> 2) & 0x3f;
@ -656,7 +688,7 @@ void __fastcall GIFRegHandlerMIPTBP1_2(u32* data)
{
FUNCLOG
miptbpInfo& miptbp0 = ZeroGS::vb[1].miptbp0;
miptbp0.tbp[0] = (data[0] ) & 0x3fff;
miptbp0.tbp[0] = (data[0]) & 0x3fff;
miptbp0.tbw[0] = (data[0] >> 14) & 0x3f;
miptbp0.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12);
miptbp0.tbw[1] = (data[1] >> 2) & 0x3f;
@ -668,7 +700,7 @@ void __fastcall GIFRegHandlerMIPTBP2_1(u32* data)
{
FUNCLOG
miptbpInfo& miptbp1 = ZeroGS::vb[0].miptbp1;
miptbp1.tbp[0] = (data[0] ) & 0x3fff;
miptbp1.tbp[0] = (data[0]) & 0x3fff;
miptbp1.tbw[0] = (data[0] >> 14) & 0x3f;
miptbp1.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12);
miptbp1.tbw[1] = (data[1] >> 2) & 0x3f;
@ -680,7 +712,7 @@ void __fastcall GIFRegHandlerMIPTBP2_2(u32* data)
{
FUNCLOG
miptbpInfo& miptbp1 = ZeroGS::vb[1].miptbp1;
miptbp1.tbp[0] = (data[0] ) & 0x3fff;
miptbp1.tbp[0] = (data[0]) & 0x3fff;
miptbp1.tbw[0] = (data[0] >> 14) & 0x3f;
miptbp1.tbp[1] = ((data[0] >> 20) & 0xfff) | ((data[1] & 0x3) << 12);
miptbp1.tbw[1] = (data[1] >> 2) & 0x3f;
@ -696,12 +728,13 @@ void __fastcall GIFRegHandlerTEXA(u32* data)
newinfo.ta[0] = data[0] & 0xff;
newinfo.ta[1] = data[1] & 0xff;
if( *(u32*)&newinfo != *(u32*)&gs.texa ) {
if (*(u32*)&newinfo != *(u32*)&gs.texa)
{
ZeroGS::Flush(0);
ZeroGS::Flush(1);
*(u32*)&gs.texa = *(u32*)&newinfo;
gs.texa.fta[0] = newinfo.ta[0]/255.0f;
gs.texa.fta[1] = newinfo.ta[1]/255.0f;
*(u32*)&gs.texa = *(u32*) & newinfo;
gs.texa.fta[0] = newinfo.ta[0] / 255.0f;
gs.texa.fta[1] = newinfo.ta[1] / 255.0f;
ZeroGS::vb[0].bTexConstsSync = FALSE;
ZeroGS::vb[1].bTexConstsSync = FALSE;
@ -727,13 +760,14 @@ void __fastcall GIFRegHandlerSCISSOR_1(u32* data)
Rect2 newscissor;
newscissor.x0 = ((data[0] ) & 0x7ff) << 3;
newscissor.x0 = ((data[0]) & 0x7ff) << 3;
newscissor.x1 = ((data[0] >> 16) & 0x7ff) << 3;
newscissor.y0 = ((data[1] ) & 0x7ff) << 3;
newscissor.y0 = ((data[1]) & 0x7ff) << 3;
newscissor.y1 = ((data[1] >> 16) & 0x7ff) << 3;
if( newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 ||
newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0 ) {
if (newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 ||
newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0)
{
ZeroGS::Flush(0);
scissor = newscissor;
@ -749,13 +783,14 @@ void __fastcall GIFRegHandlerSCISSOR_2(u32* data)
Rect2 newscissor;
newscissor.x0 = ((data[0] ) & 0x7ff) << 3;
newscissor.x0 = ((data[0]) & 0x7ff) << 3;
newscissor.x1 = ((data[0] >> 16) & 0x7ff) << 3;
newscissor.y0 = ((data[1] ) & 0x7ff) << 3;
newscissor.y0 = ((data[1]) & 0x7ff) << 3;
newscissor.y1 = ((data[1] >> 16) & 0x7ff) << 3;
if( newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 ||
newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0 ) {
if (newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 ||
newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0)
{
ZeroGS::Flush(1);
scissor = newscissor;
@ -770,17 +805,18 @@ void __fastcall GIFRegHandlerALPHA_1(u32* data)
FUNCLOG
alphaInfo newalpha;
newalpha.abcd = *(u8*)data;
newalpha.fix = *(u8*)(data+1);
newalpha.fix = *(u8*)(data + 1);
if( *(u16*)&newalpha != *(u16*)&ZeroGS::vb[0].alpha ) {
if (*(u16*)&newalpha != *(u16*)&ZeroGS::vb[0].alpha)
{
ZeroGS::Flush(0);
if( newalpha.a == 3 ) newalpha.a = 0;
if( newalpha.b == 3 ) newalpha.b = 0;
if( newalpha.c == 3 ) newalpha.c = 0;
if( newalpha.d == 3 ) newalpha.d = 0;
if (newalpha.a == 3) newalpha.a = 0;
if (newalpha.b == 3) newalpha.b = 0;
if (newalpha.c == 3) newalpha.c = 0;
if (newalpha.d == 3) newalpha.d = 0;
*(u16*)&ZeroGS::vb[0].alpha = *(u16*)&newalpha;
*(u16*)&ZeroGS::vb[0].alpha = *(u16*) & newalpha;
}
}
@ -789,17 +825,18 @@ void __fastcall GIFRegHandlerALPHA_2(u32* data)
FUNCLOG
alphaInfo newalpha;
newalpha.abcd = *(u8*)data;
newalpha.fix = *(u8*)(data+1);
newalpha.fix = *(u8*)(data + 1);
if( *(u16*)&newalpha != *(u16*)&ZeroGS::vb[1].alpha ) {
if (*(u16*)&newalpha != *(u16*)&ZeroGS::vb[1].alpha)
{
ZeroGS::Flush(1);
if( newalpha.a == 3 ) newalpha.a = 0;
if( newalpha.b == 3 ) newalpha.b = 0;
if( newalpha.c == 3 ) newalpha.c = 0;
if( newalpha.d == 3 ) newalpha.d = 0;
if (newalpha.a == 3) newalpha.a = 0;
if (newalpha.b == 3) newalpha.b = 0;
if (newalpha.c == 3) newalpha.c = 0;
if (newalpha.d == 3) newalpha.d = 0;
*(u16*)&ZeroGS::vb[1].alpha = *(u16*)&newalpha;
*(u16*)&ZeroGS::vb[1].alpha = *(u16*) & newalpha;
}
}
@ -876,26 +913,28 @@ void __fastcall GIFRegHandlerZBUF_1(u32* data)
FUNCLOG
zbufInfo& zbuf = ZeroGS::vb[0].zbuf;
int psm = (0x30|((data[0] >> 24) & 0xf));
if( zbuf.zbp == (data[0] & 0x1ff) * 32 &&
zbuf.psm == psm &&
zbuf.zmsk == (data[1] & 0x1) ) {
int psm = (0x30 | ((data[0] >> 24) & 0xf));
if (zbuf.zbp == (data[0] & 0x1ff) * 32 &&
zbuf.psm == psm &&
zbuf.zmsk == (data[1] & 0x1))
{
return;
}
// error detection
if( m_Blocks[psm].bpp == 0 )
return;
if (m_Blocks[psm].bpp == 0) return;
ZeroGS::Flush(0);
ZeroGS::Flush(1);
zbuf.zbp = (data[0] & 0x1ff) * 32;
zbuf.psm = 0x30|((data[0] >> 24) & 0xf);
zbuf.psm = 0x30 | ((data[0] >> 24) & 0xf);
zbuf.zmsk = data[1] & 0x1;
ZeroGS::vb[0].zprimmask = 0xffffffff;
if( zbuf.psm > 0x31 ) ZeroGS::vb[0].zprimmask = 0xffff;
if (zbuf.psm > 0x31) ZeroGS::vb[0].zprimmask = 0xffff;
ZeroGS::vb[0].bNeedZCheck = 1;
}
@ -905,39 +944,43 @@ void __fastcall GIFRegHandlerZBUF_2(u32* data)
FUNCLOG
zbufInfo& zbuf = ZeroGS::vb[1].zbuf;
int psm = (0x30|((data[0] >> 24) & 0xf));
if( zbuf.zbp == (data[0] & 0x1ff) * 32 &&
zbuf.psm == psm &&
zbuf.zmsk == (data[1] & 0x1) ) {
int psm = (0x30 | ((data[0] >> 24) & 0xf));
if (zbuf.zbp == (data[0] & 0x1ff) * 32 &&
zbuf.psm == psm &&
zbuf.zmsk == (data[1] & 0x1))
{
return;
}
// error detection
if( m_Blocks[psm].bpp == 0 )
if (m_Blocks[psm].bpp == 0)
return;
ZeroGS::Flush(0);
ZeroGS::Flush(1);
zbuf.zbp = (data[0] & 0x1ff) * 32;
zbuf.psm = 0x30|((data[0] >> 24) & 0xf);
zbuf.psm = 0x30 | ((data[0] >> 24) & 0xf);
zbuf.zmsk = data[1] & 0x1;
ZeroGS::vb[1].bNeedZCheck = 1;
ZeroGS::vb[1].zprimmask = 0xffffffff;
if( zbuf.psm > 0x31 ) ZeroGS::vb[1].zprimmask = 0xffff;
if (zbuf.psm > 0x31) ZeroGS::vb[1].zprimmask = 0xffff;
}
void __fastcall GIFRegHandlerBITBLTBUF(u32* data)
{
FUNCLOG
gs.srcbufnew.bp = ((data[0] ) & 0x3fff);// * 64;
gs.srcbufnew.bp = ((data[0]) & 0x3fff); // * 64;
gs.srcbufnew.bw = ((data[0] >> 16) & 0x3f) * 64;
gs.srcbufnew.psm = (data[0] >> 24) & 0x3f;
gs.dstbufnew.bp = ((data[1] ) & 0x3fff);// * 64;
gs.srcbufnew.psm = (data[0] >> 24) & 0x3f;
gs.dstbufnew.bp = ((data[1]) & 0x3fff); // * 64;
gs.dstbufnew.bw = ((data[1] >> 16) & 0x3f) * 64;
gs.dstbufnew.psm = (data[1] >> 24) & 0x3f;
gs.dstbufnew.psm = (data[1] >> 24) & 0x3f;
if (gs.dstbufnew.bw == 0) gs.dstbufnew.bw = 64;
}
@ -945,9 +988,9 @@ void __fastcall GIFRegHandlerBITBLTBUF(u32* data)
void __fastcall GIFRegHandlerTRXPOS(u32* data)
{
FUNCLOG
gs.trxposnew.sx = (data[0] ) & 0x7ff;
gs.trxposnew.sx = (data[0]) & 0x7ff;
gs.trxposnew.sy = (data[0] >> 16) & 0x7ff;
gs.trxposnew.dx = (data[1] ) & 0x7ff;
gs.trxposnew.dx = (data[1]) & 0x7ff;
gs.trxposnew.dy = (data[1] >> 16) & 0x7ff;
gs.trxposnew.dir = (data[1] >> 27) & 0x3;
}
@ -955,42 +998,48 @@ void __fastcall GIFRegHandlerTRXPOS(u32* data)
void __fastcall GIFRegHandlerTRXREG(u32* data)
{
FUNCLOG
gs.imageWtemp = data[0]&0xfff;
gs.imageHtemp = data[1]&0xfff;
gs.imageWtemp = data[0] & 0xfff;
gs.imageHtemp = data[1] & 0xfff;
}
void __fastcall GIFRegHandlerTRXDIR(u32* data)
{
FUNCLOG
// terminate any previous transfers
switch( gs.imageTransfer ) {
switch (gs.imageTransfer)
{
case 0: // host->loc
gs.imageTransfer = -1;
break;
case 1: // loc->host
ZeroGS::TerminateLocalHost();
break;
}
gs.srcbuf = gs.srcbufnew;
gs.dstbuf = gs.dstbufnew;
gs.trxpos = gs.trxposnew;
gs.imageTransfer = data[0] & 0x3;
gs.imageWnew = gs.imageWtemp;
gs.imageHnew = gs.imageHtemp;
if( gs.imageWnew > 0 && gs.imageHnew > 0 ) {
switch(gs.imageTransfer) {
if (gs.imageWnew > 0 && gs.imageHnew > 0)
{
switch (gs.imageTransfer)
{
case 0: // host->loc
ZeroGS::InitTransferHostLocal();
break;
case 1: // loc->host
ZeroGS::InitTransferLocalHost();
break;
case 2:
case 2:
ZeroGS::TransferLocalLocal();
break;
@ -998,10 +1047,12 @@ void __fastcall GIFRegHandlerTRXDIR(u32* data)
gs.imageTransfer = -1;
break;
default: assert(0);
default:
assert(0);
}
}
else {
else
{
#if defined(ZEROGS_DEVBUILD)
ZZLog::Warn_Log("Dummy transfer.");
#endif
@ -1012,10 +1063,13 @@ void __fastcall GIFRegHandlerTRXDIR(u32* data)
void __fastcall GIFRegHandlerHWREG(u32* data)
{
FUNCLOG
if( gs.imageTransfer == 0 ) {
if (gs.imageTransfer == 0)
{
ZeroGS::TransferHostLocal(data, 2);
}
else {
else
{
#if defined(ZEROGS_DEVBUILD)
ZZLog::Error_Log("ZeroGS: HWREG!? %8.8x_%8.8x", data[0], data[1]);
//assert(0);
@ -1028,31 +1082,34 @@ extern int g_GSMultiThreaded;
void __fastcall GIFRegHandlerSIGNAL(u32* data)
{
FUNCLOG
if(!g_GSMultiThreaded) {
SIGLBLID->SIGID = (SIGLBLID->SIGID&~data[1])|(data[0]&data[1]);
if (!g_GSMultiThreaded)
{
SIGLBLID->SIGID = (SIGLBLID->SIGID & ~data[1]) | (data[0] & data[1]);
// if (gs.CSRw & 0x1) CSR->SIGNAL = 1;
// if (!IMR->SIGMSK && GSirq)
// GSirq();
if (gs.CSRw & 0x1) {
if (gs.CSRw & 0x1)
{
CSR->SIGNAL = 1;
//gs.CSRw &= ~1;
}
if (!IMR->SIGMSK && GSirq)
GSirq();
if (!IMR->SIGMSK && GSirq) GSirq();
}
}
void __fastcall GIFRegHandlerFINISH(u32* data)
{
FUNCLOG
if(!g_GSMultiThreaded) {
if (gs.CSRw & 0x2)
CSR->FINISH = 1;
if (!IMR->FINISHMSK && GSirq)
GSirq();
if (!g_GSMultiThreaded)
{
if (gs.CSRw & 0x2) CSR->FINISH = 1;
if (!IMR->FINISHMSK && GSirq) GSirq();
// if( gs.CSRw & 2 ) {
// //gs.CSRw &= ~2;
@ -1070,7 +1127,9 @@ void __fastcall GIFRegHandlerFINISH(u32* data)
void __fastcall GIFRegHandlerLABEL(u32* data)
{
FUNCLOG
if(!g_GSMultiThreaded) {
SIGLBLID->LBLID = (SIGLBLID->LBLID&~data[1])|(data[0]&data[1]);
if (!g_GSMultiThreaded)
{
SIGLBLID->LBLID = (SIGLBLID->LBLID & ~data[1]) | (data[0] & data[1]);
}
}

View File

@ -80,40 +80,48 @@ extern vector<u32> s_vecTempTextures; // temporary textures, released at the
//------------------ Namespace
namespace ZeroGS {
extern int s_nNewWidth, s_nNewHeight;
namespace ZeroGS
{
extern int s_nNewWidth, s_nNewHeight;
extern CRangeManager s_RangeMngr; // manages overwritten memory
extern void FlushTransferRanges(const tex0Info* ptex);
extern void ProcessMessages();
void AdjustTransToAspect(Vector& v);
extern CRangeManager s_RangeMngr; // manages overwritten memory
extern void FlushTransferRanges(const tex0Info* ptex);
extern void ProcessMessages();
void AdjustTransToAspect(Vector& v);
// Interlace texture is lazy 1*(height) array of 1 and 0.
// It height (it named s_nInterlaceTexWidth here) hanging we must redone
// the texture.
// FIXME: If this function would spammed to often, we could use
// width < s_nInterlaceTexWidth as correct for old texture
static int s_nInterlaceTexWidth = 0; // width of texture
inline u32 CreateInterlaceTex(int width) {
if (width == s_nInterlaceTexWidth && s_ptexInterlace != 0)
return s_ptexInterlace;
// Interlace texture is lazy 1*(height) array of 1 and 0.
// If its height (named s_nInterlaceTexWidth here) is hanging we must redo
// the texture.
// FIXME: If this function were spammed too often, we could use
// width < s_nInterlaceTexWidth as correct for old texture
static int s_nInterlaceTexWidth = 0; // width of texture
SAFE_RELEASE_TEX(s_ptexInterlace);
s_nInterlaceTexWidth = width;
inline u32 CreateInterlaceTex(int width)
{
if (width == s_nInterlaceTexWidth && s_ptexInterlace != 0) return s_ptexInterlace;
vector<u32> data(width);
for (int i = 0; i < width; ++i)
data[i] = (i & 1) ? 0xffffffff : 0;
SAFE_RELEASE_TEX(s_ptexInterlace);
glGenTextures(1, &s_ptexInterlace);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ptexInterlace);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, width, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GL_REPORT_ERRORD();
return s_ptexInterlace;
s_nInterlaceTexWidth = width;
vector<u32> data(width);
for (int i = 0; i < width; ++i)
{
data[i] = (i & 1) ? 0xffffffff : 0;
}
glGenTextures(1, &s_ptexInterlace);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ptexInterlace);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, width, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GL_REPORT_ERRORD();
return s_ptexInterlace;
}
}
//------------------ Code
// Adjusts vertex shader BitBltPos vector v to preserve aspect ratio. It used to emulate 4:3 or 16:9.
@ -132,19 +140,20 @@ void ZeroGS::AdjustTransToAspect(Vector& v)
v.w *= f;
// scanlines mess up when not aligned right
v.y += (1-(float)modf(v.y*(float)nBackbufferHeight*0.5f+0.05f, &temp))*2.0f/(float)nBackbufferHeight;
v.w += (1-(float)modf(v.w*(float)nBackbufferHeight*0.5f+0.05f, &temp))*2.0f/(float)nBackbufferHeight;
v.y += (1 - (float)modf(v.y * (float)nBackbufferHeight * 0.5f + 0.05f, &temp)) * 2.0f / (float)nBackbufferHeight;
v.w += (1 - (float)modf(v.w * (float)nBackbufferHeight * 0.5f + 0.05f, &temp)) * 2.0f / (float)nBackbufferHeight;
}
else
{
// limited by height
f = ((float)nBackbufferHeight / (float)conf.height) / ((float)nBackbufferWidth / (float)conf.width);
f -= (float)modf(f*nBackbufferWidth, &temp)/(float)nBackbufferWidth;
f -= (float)modf(f * nBackbufferWidth, &temp) / (float)nBackbufferWidth;
v.x *= f;
v.z *= f;
}
v *= 1/32767.0f;
v *= 1 / 32767.0f;
}
// Helper for skip frames.
@ -174,51 +183,67 @@ inline bool FrameSkippingHelper()
g_nFramesSkipped++;
ShouldSkip = true;
}
g_nFrameRender--;
}
#if defined _DEBUG
if (timeGetTime() - TimeLastSkip > 15000 && ShouldSkip) {
if (timeGetTime() - TimeLastSkip > 15000 && ShouldSkip)
{
ZZLog::Debug_Log("ZZogl Skipped frames.");
TimeLastSkip = timeGetTime();
}
#endif
return ShouldSkip;
}
// helper function for save frame in picture.
inline void FrameSavingHelper() {
if( g_bSaveFrame ) {
if( vb[0].prndr != NULL ) {
inline void FrameSavingHelper()
{
if (g_bSaveFrame)
{
if (vb[0].prndr != NULL)
{
SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, vb[0].prndr->ptex, RW(vb[0].prndr->fbw), RH(vb[0].prndr->fbh));
}
if( vb[1].prndr != NULL && vb[0].prndr != vb[1].prndr ) {
if (vb[1].prndr != NULL && vb[0].prndr != vb[1].prndr)
{
SaveTexture("frame2.tga", GL_TEXTURE_RECTANGLE_NV, vb[1].prndr->ptex, RW(vb[1].prndr->fbw), RH(vb[1].prndr->fbh));
}
#ifdef _WIN32
else DeleteFile("frame2.tga");
else
{
DeleteFile("frame2.tga");
}
#endif
}
g_SaveFrameNum = 0;
g_bSaveFlushedFrame = 1;
}
// Function populated tex0Info[2] array
inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo) {
for(int i = 0; i < 2; ++i) {
inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo)
{
for (int i = 0; i < 2; ++i)
{
if( !(*(u32*)(PMODE) & (1<<i)) ) {
if (!(*(u32*)(PMODE) & (1 << i)))
{
dispinfo[i].tw = 0;
dispinfo[i].th = 0;
continue;
}
GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1;
GSRegDISPLAY* pd = i ? DISPLAY2 : DISPLAY1;
int magh = pd->MAGH+1;
int magv = pd->MAGV+1;
int magh = pd->MAGH + 1;
int magv = pd->MAGV + 1;
dispinfo[i].tbp0 = pfb->FBP << 5;
dispinfo[i].tbw = pfb->FBW << 6;
@ -228,7 +253,9 @@ inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo) {
// hack!!
// 2 * dispinfo[i].tw / dispinfo[i].th <= 1, metal slug 4
if( bInterlace && 2 * dispinfo[i].tw / dispinfo[i].th <= 1 && !(g_GameSettings&GAME_INTERLACE2X) ) {
if (bInterlace && 2 * dispinfo[i].tw / dispinfo[i].th <= 1 && !(g_GameSettings&GAME_INTERLACE2X))
{
dispinfo[i].th >>= 1;
}
}
@ -236,7 +263,8 @@ inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo) {
// Something should be done before Renderer the picture.
inline void RenderStartHelper(u32 bInterlace){
inline void RenderStartHelper(u32 bInterlace)
{
// Crashes Final Fantasy X at startup if uncommented. --arcum42
//#ifdef !defined(ZEROGS_DEVBUILD)
// if(g_nRealFrame < 80 ) {
@ -261,36 +289,39 @@ inline void RenderStartHelper(u32 bInterlace){
FrameSavingHelper();
if( s_RangeMngr.ranges.size() > 0 )
if (s_RangeMngr.ranges.size() > 0)
FlushTransferRanges(NULL);
SetShaderCaller("RenderStartHelper");
// reset fba after every frame
vb[0].fba.fba = 0;
vb[1].fba.fba = 0;
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
glViewport(0, 0, nBackbufferWidth, nBackbufferHeight);
// if interlace, only clear every other vsync
if(!bInterlace )
if (!bInterlace)
{
//u32 color = COLOR_ARGB(0, BGCOLOR->R, BGCOLOR->G, BGCOLOR->B);
glClear(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
SETVERTEXSHADER(pvsBitBlt.prog);
glBindBuffer(GL_ARRAY_BUFFER, vboRect);
SET_STREAM();
GL_REPORT_ERRORD();
if( conf.options & GSOPTION_WIREFRAME )
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (conf.options & GSOPTION_WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
DisableAllgl() ;
GL_REPORT_ERRORD();
if( bInterlace ) g_PrevBitwiseTexX = -1; // reset since will be using
if (bInterlace) g_PrevBitwiseTexX = -1; // reset since will be using
}
// It is setting for intrelace texture multiplied vector;
@ -298,95 +329,116 @@ inline void RenderStartHelper(u32 bInterlace){
// on image y coord. So it we write valpha.z * F + valpha.w + 0.5 it would be swicthig odd
// and even strings at each frame
// valpha.x and y used for image blending.
inline Vector RenderGetForClip(u32 bInterlace, int interlace, int psm, FRAGMENTSHADER* prog){
inline Vector RenderGetForClip(u32 bInterlace, int interlace, int psm, FRAGMENTSHADER* prog)
{
SetShaderCaller("RenderGetForClip");
Vector valpha;
// first render the current render targets, then from ptexMem
if( psm == 1 ) {
if (psm == 1)
{
valpha.x = 1;
valpha.y = 0;
}
else {
else
{
valpha.x = 0;
valpha.y = 1;
}
if (bInterlace) {
if( interlace == (conf.interlace&1) ) {
if (bInterlace)
{
if (interlace == (conf.interlace&1))
{
// pass if odd
valpha.z = 1.0f;
valpha.w = -0.4999f;
}
else {
else
{
// pass if even
valpha.z = -1.0f;
valpha.w = 0.5001f;
}
}
else {
else
{
// always pass interlace test
valpha.z = 0;
valpha.w = 1;
}
ZZcgSetParameter4fv(prog->sOneColor, valpha, "g_fOneColor");
return valpha;
}
// Put interlaced texture in use for shader prog.
// Note: if frame interlaced it's th is halved, so we should x2 it.
inline void RenderCreateInterlaceTex(u32 bInterlace, int th, FRAGMENTSHADER* prog) {
inline void RenderCreateInterlaceTex(u32 bInterlace, int th, FRAGMENTSHADER* prog)
{
if (!bInterlace)
return;
int interlacetex = CreateInterlaceTex(2*th);
int interlacetex = CreateInterlaceTex(2 * th);
cgGLSetTextureParameter(prog->sInterlace, interlacetex);
cgGLEnableTextureParameter(prog->sInterlace);
}
// Well, do blending setup prior to second pass of half-frame drawing
inline void RenderSetupBlending() {
inline void RenderSetupBlending()
{
// setup right blending
glEnable(GL_BLEND);
zgsBlendEquationSeparateEXT(GL_FUNC_ADD, GL_FUNC_ADD);
if (PMODE->MMOD) {
glBlendColorEXT(PMODE->ALP*(1/255.0f), PMODE->ALP*(1/255.0f), PMODE->ALP*(1/255.0f), 0.5f);
if (PMODE->MMOD)
{
glBlendColorEXT(PMODE->ALP*(1 / 255.0f), PMODE->ALP*(1 / 255.0f), PMODE->ALP*(1 / 255.0f), 0.5f);
s_srcrgb = GL_CONSTANT_COLOR_EXT;
s_dstrgb = GL_ONE_MINUS_CONSTANT_COLOR_EXT;
}
else {
else
{
s_srcrgb = GL_SRC_ALPHA;
s_dstrgb = GL_ONE_MINUS_SRC_ALPHA;
}
s_srcalpha = PMODE->AMOD ? GL_ZERO : GL_ONE;
s_dstalpha = PMODE->AMOD? GL_ONE : GL_ZERO;
s_dstalpha = PMODE->AMOD ? GL_ONE : GL_ZERO;
zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha);
}
// each frame could be drawed in two stages, so blending should be different for them
inline void RenderSetupStencil(int i) {
glStencilMask(1<<i);
s_stencilmask = 1<<i;
inline void RenderSetupStencil(int i)
{
glStencilMask(1 << i);
s_stencilmask = 1 << i;
GL_STENCILFUNC_SET();
}
// do stencil check for each found target i -- texturig stage
inline void RenderUpdateStencil(int i, bool* bUsingStencil) {
if( !(*bUsingStencil) ) {
inline void RenderUpdateStencil(int i, bool* bUsingStencil)
{
if (!(*bUsingStencil))
{
glClear(GL_STENCIL_BUFFER_BIT);
}
*bUsingStencil = 1;
glEnable(GL_STENCIL_TEST);
GL_STENCILFUNC(GL_NOTEQUAL, 3, 1<<i);
GL_STENCILFUNC(GL_NOTEQUAL, 3, 1 << i);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(1<<i);
glStencilMask(1 << i);
}
// CRTC24 could not be rendered
inline void RenderCRTC24helper(u32 bInterlace, int interlace, int psm) {
inline void RenderCRTC24helper(u32 bInterlace, int interlace, int psm)
{
ZZLog::Error_Log("ZZogl: CRTC24!!! I'm trying to show something.");
SetShaderCaller("RenderCRTC24helper");
// assume that data is already in ptexMem (do Resolve?)
@ -406,43 +458,51 @@ inline int RenderGetBpp(int psm)
ZZLog::Debug_Log("ZZogl: 16S target.");
}
if (PSMT_ISHALF(psm))
return 2;
return 4;
}
// We want to draw ptarg on screen, that could be disaligned to viewport.
// So we do aligning it by height.
inline int RenderGetOffsets(int* dby, int* movy, tex0Info& texframe, CRenderTarget* ptarg, int bpp) {
*dby += (256/bpp)*(texframe.tbp0 - ptarg->fbp)/texframe.tbw;
if( *dby < 0 ) {
inline int RenderGetOffsets(int* dby, int* movy, tex0Info& texframe, CRenderTarget* ptarg, int bpp)
{
*dby += (256 / bpp) * (texframe.tbp0 - ptarg->fbp) / texframe.tbw;
if (*dby < 0)
{
*movy = -*dby;
*dby = 0;
}
return min(ptarg->fbh - *dby, texframe.th - *movy);
}
// BltBit shader calculate vertex (4 coord's pixel) position at the viewport.
inline Vector RenderSetTargetBitPos(int dh, int th, int movy, bool isInterlace) {
inline Vector RenderSetTargetBitPos(int dh, int th, int movy, bool isInterlace)
{
SetShaderCaller("RenderSetTargetBitPos");
Vector v;
// dest rect
v.x = 1;
v.y = dh/(float)th;
v.y = dh / (float)th;
v.z = 0;
v.w = 1-v.y;
v.w = 1 - v.y;
if( movy > 0 )
v.w -= movy/(float)th;
if (movy > 0) v.w -= movy / (float)th;
AdjustTransToAspect(v);
if (isInterlace) {
if (isInterlace)
{
// move down by 1 pixel
v.w += 1.0f / (float)dh ;
}
ZZcgSetParameter4fv(pvsBitBlt.sBitBltPos, v, "g_fBitBltPos");
return v;
}
@ -450,62 +510,73 @@ inline Vector RenderSetTargetBitPos(int dh, int th, int movy, bool isInterlace)
// For example use tw / X and tw / X magnify the vieport.
// Interlaced output is little out of VB, it could be see as evil blinking line on top
// and bottom, so we try to remove it
inline Vector RenderSetTargetBitTex(float th, float tw, float dh, float dw, bool isInterlace) {
inline Vector RenderSetTargetBitTex(float th, float tw, float dh, float dw, bool isInterlace)
{
SetShaderCaller("RenderSetTargetBitTex");
Vector v;
v = Vector(th, tw, dh, dw);
// Incorrect Aspect ratio on interlaced frames
if (isInterlace)
{
v.y -= 1.0f/conf.height;
v.w += 1.0f/conf.height;
v.y -= 1.0f / conf.height;
v.w += 1.0f / conf.height;
}
ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, v, "g_fBitBltTex");
return v;
}
// Translator for POSITION coordinats (-1.0:+1.0f at x axis, +1.0f:-1.0y at y) into target frame ones
// We don't need x coordinate, bvecause interlacing is y-axis only.
inline Vector RenderSetTargetBitTrans(int th) {
inline Vector RenderSetTargetBitTrans(int th)
{
SetShaderCaller("RenderSetTargetBitTrans");
Vector v = Vector( float(th), -float(th), float(th), float(th));
Vector v = Vector(float(th), -float(th), float(th), float(th));
ZZcgSetParameter4fv(pvsBitBlt.fBitBltTrans, v, "g_fBitBltTrans");
return v;
}
// use g_fInvTexDims to store inverse texture dims
// Seems, that Targ shader does not use it
inline Vector RenderSetTargetInvTex(int bInterlace, int tw, int th, FRAGMENTSHADER* prog) {
inline Vector RenderSetTargetInvTex(int bInterlace, int tw, int th, FRAGMENTSHADER* prog)
{
SetShaderCaller("RenderSetTargetInvTex");
Vector v = Vector(0, 0, 0, 0);
if (prog->sInvTexDims) {
if (prog->sInvTexDims)
{
v.x = 1.0f / (float)tw;
v.y = 1.0f / (float)th;
v.z = (float)0.0;
v.w = -0.5f / (float)th;
ZZcgSetParameter4fv(prog->sInvTexDims, v, "g_fInvTexDims");
}
return v;
}
// Metal Slug 5 hack (as was written). If tarhet tbp not equal to framed fbp, than we look for better possibility,
// Note, than after true result iterator it could not be use.
inline bool RenderLookForABetterTarget(int fbp, int tbp, list<CRenderTarget*>& listTargs, list<CRenderTarget*>::iterator& it) {
inline bool RenderLookForABetterTarget(int fbp, int tbp, list<CRenderTarget*>& listTargs, list<CRenderTarget*>::iterator& it)
{
if (fbp == tbp)
return false;
// look for a better target (metal slug 5)
list<CRenderTarget*>::iterator itbetter;
for(itbetter = listTargs.begin(); itbetter != listTargs.end(); ++itbetter ) {
if( (*itbetter)->fbp == tbp )
break;
for (itbetter = listTargs.begin(); itbetter != listTargs.end(); ++itbetter)
{
if ((*itbetter)->fbp == tbp) break;
}
if( itbetter != listTargs.end() ) {
if (itbetter != listTargs.end())
{
it = listTargs.erase(it);
return true;
}
@ -514,7 +585,8 @@ inline bool RenderLookForABetterTarget(int fbp, int tbp, list<CRenderTarget*>& l
}
// First try to draw frame from targets. It's
inline bool RenderCheckForTargets(tex0Info& texframe, list<CRenderTarget*>& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace) {
inline bool RenderCheckForTargets(tex0Info& texframe, list<CRenderTarget*>& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace)
{
// get the start and end addresses of the buffer
int bpp = RenderGetBpp(texframe.psm);
GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1;
@ -525,30 +597,33 @@ inline bool RenderCheckForTargets(tex0Info& texframe, list<CRenderTarget*>& list
// We need share list of targets beetween functions
s_RTs.GetTargs(start, end, listTargs);
for(list<CRenderTarget*>::iterator it = listTargs.begin(); it != listTargs.end(); ) {
for (list<CRenderTarget*>::iterator it = listTargs.begin(); it != listTargs.end();)
{
CRenderTarget* ptarg = *it;
if( ptarg->fbw == texframe.tbw && !(ptarg->status&CRenderTarget::TS_NeedUpdate) && ((256/bpp)*(texframe.tbp0-ptarg->fbp))%texframe.tbw == 0 ) {
if (RenderLookForABetterTarget(ptarg->fbp, texframe.tbp0, listTargs, it))
continue;
if (ptarg->fbw == texframe.tbw && !(ptarg->status&CRenderTarget::TS_NeedUpdate) && ((256 / bpp)*(texframe.tbp0 - ptarg->fbp)) % texframe.tbw == 0)
{
if (RenderLookForABetterTarget(ptarg->fbp, texframe.tbp0, listTargs, it)) continue;
if( g_bSaveFinalFrame )
SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptarg->ptex, RW(ptarg->fbw), RH(ptarg->fbh));
if (g_bSaveFinalFrame) SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptarg->ptex, RW(ptarg->fbw), RH(ptarg->fbh));
// determine the rectangle to render
int dby = pfb->DBY;
int movy = 0;
int dh = RenderGetOffsets(&dby, &movy, texframe, ptarg, bpp);
if( dh >= 64 ) {
if (dh >= 64)
{
if( ptarg->fbh - dby < texframe.th - movy && !(*bUsingStencil) )
if (ptarg->fbh - dby < texframe.th - movy && !(*bUsingStencil))
RenderUpdateStencil(i, bUsingStencil);
SetShaderCaller("RenderCheckForTargets");
// Texture
Vector v = RenderSetTargetBitTex((float)RW(texframe.tw), (float)RH(dh), (float)RW(pfb->DBX), (float)RH(dby), INTERLACE_COUNT );
Vector v = RenderSetTargetBitTex((float)RW(texframe.tw), (float)RH(dh), (float)RW(pfb->DBX), (float)RH(dby), INTERLACE_COUNT);
// dest rect
v = RenderSetTargetBitPos(dh, texframe.th, movy, INTERLACE_COUNT);
v = RenderSetTargetBitTrans(ptarg->fbh);
@ -559,37 +634,45 @@ inline bool RenderCheckForTargets(tex0Info& texframe, list<CRenderTarget*>& list
// inside vb[0]'s target area, so render that region only
cgGLSetTextureParameter(ppsCRTCTarg[bInterlace].sFinal, ptarg->ptex);
cgGLEnableTextureParameter(ppsCRTCTarg[bInterlace].sFinal);
RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTCTarg[bInterlace]);
SETPIXELSHADER(ppsCRTCTarg[bInterlace].prog);
GL_REPORT_ERRORD();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if( abs(dh - (int)texframe.th) <= 1 )
return true;
if (abs(dh - (int)texframe.th) <= 1) return true;
if( abs(dh - (int)ptarg->fbh) <= 1 ) {
if (abs(dh - (int)ptarg->fbh) <= 1)
{
it = listTargs.erase(it);
continue;
}
}
}
++it;
}
return false;
}
// The same of the previous, but from memory
inline void RenderCheckForMemory(tex0Info& texframe, list<CRenderTarget*>& listTargs, int interlace, int bInterlace) {
// The same as the previous, but from memory.
// If you ever wondered why a picture from a minute ago suddenly flashes on the screen (say, in Mana Khemia),
// this is the function that does it.
inline void RenderCheckForMemory(tex0Info& texframe, list<CRenderTarget*>& listTargs, int interlace, int bInterlace)
{
for(list<CRenderTarget*>::iterator it = listTargs.begin(); it != listTargs.end(); ++it)
for (list<CRenderTarget*>::iterator it = listTargs.begin(); it != listTargs.end(); ++it)
{
(*it)->Resolve();
}
// context has to be 0
CMemoryTarget* pmemtarg = g_MemTargs.GetMemoryTarget(texframe, 1);
if ((pmemtarg == NULL) || (bInterlace >= 2))
ZZLog::Error_Log("CRCR Check for memory shader fault.");
@ -599,56 +682,62 @@ inline void RenderCheckForMemory(tex0Info& texframe, list<CRenderTarget*>& listT
cgGLSetTextureParameter(ppsCRTC[bInterlace].sMemory, pmemtarg->ptex->tex);
cgGLEnableTextureParameter(ppsCRTC[bInterlace].sMemory);
if( g_bSaveFinalFrame )
SaveTex(&texframe, g_bSaveFinalFrame - 1 > 0);
if (g_bSaveFinalFrame) SaveTex(&texframe, g_bSaveFinalFrame - 1 > 0);
// finally render from the memory (note that the stencil buffer will keep previous regions)
Vector v = RenderSetTargetBitPos(1, 1, 0, INTERLACE_COUNT);
// Fixme: Why this if here?
if( g_bCRTCBilinear )
ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, Vector(texframe.tw,texframe.th,-0.5f,-0.5f), "g_fBitBltTex");
// Fixme: Why is this here?
// We should probably call RenderSetTargetBitTex instead.
if (g_bCRTCBilinear)
ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, Vector(texframe.tw, texframe.th, -0.5f, -0.5f), "g_fBitBltTex");
else
ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, Vector(1,1,-0.5f/(float)texframe.tw,-0.5f/(float)texframe.th), "g_fBitBltTex");
ZZcgSetParameter4fv(pvsBitBlt.sBitBltTex, Vector(1, 1, -0.5f / (float)texframe.tw, -0.5f / (float)texframe.th), "g_fBitBltTex");
v = RenderSetTargetBitTrans(texframe.th);
v = RenderSetTargetInvTex(bInterlace, texframe.tw, texframe.th, &ppsCRTC[bInterlace]);
Vector valpha = RenderGetForClip(bInterlace, interlace, texframe.psm, &ppsCRTC[bInterlace]);
RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTC[bInterlace]);
SETPIXELSHADER(ppsCRTC[bInterlace].prog);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
// Put FPS counter on scren (not in window title)
inline void AfterRenderDisplayFPS() {
inline void AfterRenderDisplayFPS()
{
char str[64];
int left = 10, top = 15;
sprintf(str, "%.1f fps", fFPS);
DrawText(str, left+1, top+1, 0xff000000);
DrawText(str, left + 1, top + 1, 0xff000000);
DrawText(str, left, top, 0xffc0ffff);
}
// Swaping buffers, so we could use another windows
inline void AfterRenderSwapBuffers() {
if (glGetError() != GL_NO_ERROR)
ZZLog::Debug_Log("glError before swap!");
// Swapping buffers, so we could use another windows
inline void AfterRenderSwapBuffers()
{
if (glGetError() != GL_NO_ERROR) ZZLog::Debug_Log("glError before swap!");
GLWin.SwapGLBuffers();
}
// SnapeShoot helper
inline void AfterRenderMadeSnapshoot() {
inline void AfterRenderMadeSnapshoot()
{
char str[64];
int left = 200, top = 15;
sprintf(str, "ZeroGS %d.%d.%d - %.1f fps %s", zgsrevision, zgsbuild, zgsminor, fFPS, s_frameskipping?" - frameskipping":"");
sprintf(str, "ZeroGS %d.%d.%d - %.1f fps %s", zgsrevision, zgsbuild, zgsminor, fFPS, s_frameskipping ? " - frameskipping" : "");
DrawText(str, left+1, top+1, 0xff000000);
DrawText(str, left + 1, top + 1, 0xff000000);
DrawText(str, left, top, 0xffc0ffff);
if( SaveRenderTarget(strSnapshot != ""?strSnapshot.c_str():"temp.jpg", nBackbufferWidth, -nBackbufferHeight, 0)) {//(conf.options&GSOPTION_TGASNAP)?0:1) ) {
if (SaveRenderTarget(strSnapshot != "" ? strSnapshot.c_str() : "temp.jpg", nBackbufferWidth, -nBackbufferHeight, 0)) //(conf.options&GSOPTION_TGASNAP)?0:1) ) {
{
char str[255];
sprintf(str, "saved %s\n", strSnapshot.c_str());
AddMessage(str, 500);
@ -656,71 +745,83 @@ inline void AfterRenderMadeSnapshoot() {
}
// If needed reset
inline void AfterRendererResizeWindow() {
inline void AfterRendererResizeWindow()
{
Reset();
ChangeDeviceSize(s_nNewWidth, s_nNewHeight);
s_nNewWidth = s_nNewHeight = -1;
}
// Put new values on statistic variable
inline void AfterRenderCountStatistics() {
if( s_nWriteDepthCount > 0 ) {
assert( conf.mrtdepth );
if( --s_nWriteDepthCount <= 0 ) {
inline void AfterRenderCountStatistics()
{
if (s_nWriteDepthCount > 0)
{
assert(conf.mrtdepth);
if (--s_nWriteDepthCount <= 0)
{
s_bWriteDepth = FALSE;
}
}
if( s_nWriteDestAlphaTest > 0 ) {
if( --s_nWriteDestAlphaTest <= 0 ) {
if (s_nWriteDestAlphaTest > 0)
{
if (--s_nWriteDestAlphaTest <= 0)
{
s_bDestAlphaTest = FALSE;
}
}
if( g_nDepthUsed > 0 ) --g_nDepthUsed;
if (g_nDepthUsed > 0) --g_nDepthUsed;
s_ClutResolve = 0;
g_nDepthUpdateCount = 0;
}
// This all could be easily forefeit
inline void AfterRendererUnimportantJob() {
inline void AfterRendererUnimportantJob()
{
ProcessMessages();
if( g_bDisplayFPS )
AfterRenderDisplayFPS();
if (g_bDisplayFPS) AfterRenderDisplayFPS();
AfterRenderSwapBuffers();
if( conf.options & GSOPTION_WIREFRAME ) {
if (conf.options & GSOPTION_WIREFRAME)
{
// clear all targets
s_nWireframeCount = 1;
}
if( g_bMakeSnapshot ) {
if (g_bMakeSnapshot)
{
AfterRenderMadeSnapshoot();
g_bMakeSnapshot = 0;
}
if( s_avicapturing )
if (s_avicapturing)
CaptureFrame();
AfterRenderCountStatistics();
if( s_nNewWidth >= 0 && s_nNewHeight >= 0 && !g_bIsLost )
if (s_nNewWidth >= 0 && s_nNewHeight >= 0 && !g_bIsLost)
AfterRendererResizeWindow();
maxmin = 608;
}
// Swich Frabuffers
inline void AfterRendererSwitchBackToTextures() {
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer );
inline void AfterRendererSwitchBackToTextures()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer);
g_MemTargs.DestroyCleared();
if( s_vecTempTextures.size() > 0 )
if (s_vecTempTextures.size() > 0)
glDeleteTextures((GLsizei)s_vecTempTextures.size(), &s_vecTempTextures[0]);
s_vecTempTextures.clear();
if (EXTWRITE->WRITE & 1)
@ -730,10 +831,12 @@ inline void AfterRendererSwitchBackToTextures() {
EXTWRITE->WRITE = 0;
}
if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (conf.options & GSOPTION_WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glEnable(GL_SCISSOR_TEST);
if( icurctx >= 0 ) {
if (icurctx >= 0)
{
vb[icurctx].bVarsSetTarg = FALSE;
vb[icurctx].bVarsTexSync = FALSE;
vb[0].bVarsTexSync = FALSE;
@ -741,70 +844,81 @@ inline void AfterRendererSwitchBackToTextures() {
}
// Reset Targets Helper, for hack.
inline void AfterRendererAutoresetTargets() {
if( g_GameSettings & GAME_AUTORESET ) {
inline void AfterRendererAutoresetTargets()
{
if (g_GameSettings & GAME_AUTORESET)
{
s_nResolveCounts[s_nCurResolveIndex] = s_nResolved;
s_nCurResolveIndex = (s_nCurResolveIndex+1)%ARRAY_SIZE(s_nResolveCounts);
s_nCurResolveIndex = (s_nCurResolveIndex + 1) % ARRAY_SIZE(s_nResolveCounts);
int total = 0;
for(int i = 0; i < ARRAY_SIZE(s_nResolveCounts); ++i) total += s_nResolveCounts[i];
if( total / ARRAY_SIZE(s_nResolveCounts) > 3 ) {
if( s_nLastResolveReset > (int)(fFPS * 8) ) {
for (int i = 0; i < ARRAY_SIZE(s_nResolveCounts); ++i) total += s_nResolveCounts[i];
if (total / ARRAY_SIZE(s_nResolveCounts) > 3)
{
if (s_nLastResolveReset > (int)(fFPS * 8))
{
// reset
ZZLog::Error_Log("Video memory reset.");
s_nLastResolveReset = 0;
memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts));
s_RTs.ResolveAll();
return;
return;
s_RTs.Destroy();
s_DepthRTs.ResolveAll();
s_DepthRTs.Destroy();
vb[0].prndr = NULL; vb[0].pdepth = NULL; vb[0].bNeedFrameCheck = 1; vb[0].bNeedZCheck = 1;
vb[1].prndr = NULL; vb[1].pdepth = NULL; vb[1].bNeedFrameCheck = 1; vb[1].bNeedZCheck = 1;
vb[0].prndr = NULL;
vb[0].pdepth = NULL;
vb[0].bNeedFrameCheck = 1;
vb[0].bNeedZCheck = 1;
vb[1].prndr = NULL;
vb[1].pdepth = NULL;
vb[1].bNeedFrameCheck = 1;
vb[1].bNeedZCheck = 1;
}
}
s_nLastResolveReset++;
}
if( s_nResolved > 8 ) s_nResolved = 2;
else if( s_nResolved > 0 ) --s_nResolved;
if (s_nResolved > 8)
s_nResolved = 2;
else if (s_nResolved > 0)
--s_nResolved;
}
int count = 0;
// The main renderer function
void ZeroGS::RenderCRTC(int interlace)
{
if( g_bIsLost ) return;
if (g_bIsLost) return;
if (FrameSkippingHelper()) return;
u32 bInterlace = SMODE2->INT && SMODE2->FFMD && (conf.interlace < 2);
RenderStartHelper(bInterlace);
bool bUsingStencil = 0;
RenderStartHelper(bInterlace);
bool bUsingStencil = 0;
tex0Info dispinfo[2];
FrameObtainDispinfo(bInterlace, dispinfo);
FrameObtainDispinfo(bInterlace, dispinfo);
// start from the last circuit
for(int i = !PMODE->SLBG; i >= 0; --i) {
for (int i = !PMODE->SLBG; i >= 0; --i)
{
tex0Info& texframe = dispinfo[i];
if( texframe.th <= 1 )
continue;
if (SMODE2->INT && SMODE2->FFMD)
texframe.th >>= 1;
if (texframe.th <= 1) continue;
if (SMODE2->INT && SMODE2->FFMD) texframe.th >>= 1;
if (i == 0) RenderSetupBlending();
if (bUsingStencil) RenderSetupStencil(i);
if( i == 0 )
RenderSetupBlending();
if( bUsingStencil )
RenderSetupStencil(i);
if( texframe.psm == 0x12 ) {
if (texframe.psm == 0x12)
{
RenderCRTC24helper(bInterlace, interlace, texframe.psm);
continue;
}
@ -813,7 +927,7 @@ void ZeroGS::RenderCRTC(int interlace)
list<CRenderTarget*> listTargs;
// if we could not draw image from target's do it from memory
if ( !RenderCheckForTargets(texframe, listTargs, i, &bUsingStencil, interlace, bInterlace) )
if (!RenderCheckForTargets(texframe, listTargs, i, &bUsingStencil, interlace, bInterlace))
RenderCheckForMemory(texframe, listTargs, interlace, bInterlace);
}

View File

@ -79,59 +79,60 @@
#define VB_NUMBUFFERS 512
// ----------------- Types
typedef void (APIENTRYP _PFNSWAPINTERVAL) (int);
typedef void (APIENTRYP _PFNSWAPINTERVAL)(int);
map<string, GLbyte> mapGLExtensions;
namespace ZeroGS{
RenderFormatType g_RenderFormatType = RFT_float16;
namespace ZeroGS
{
RenderFormatType g_RenderFormatType = RFT_float16;
extern void KickPoint();
extern void KickLine();
extern void KickTriangle();
extern void KickTriangleFan();
extern void KickSprite();
extern void KickDummy();
extern bool LoadEffects();
extern bool LoadExtraEffects();
extern FRAGMENTSHADER* LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed);
VERTEXSHADER pvsBitBlt;
extern void KickPoint();
extern void KickLine();
extern void KickTriangle();
extern void KickTriangleFan();
extern void KickSprite();
extern void KickDummy();
extern bool LoadEffects();
extern bool LoadExtraEffects();
extern FRAGMENTSHADER* LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed);
VERTEXSHADER pvsBitBlt;
GLuint vboRect = 0;
vector<GLuint> g_vboBuffers; // VBOs for all drawing commands
int g_nCurVBOIndex = 0;
GLuint vboRect = 0;
vector<GLuint> g_vboBuffers; // VBOs for all drawing commands
int g_nCurVBOIndex = 0;
inline bool CreateImportantCheck();
inline void CreateOtherCheck();
inline bool CreateOpenShadersFile();
inline bool CreateImportantCheck();
inline void CreateOtherCheck();
inline bool CreateOpenShadersFile();
}
//------------------ Dummies
#ifdef _WIN32
void __stdcall glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4)
void __stdcall glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4)
#else
void APIENTRY glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4)
void APIENTRY glBlendFuncSeparateDummy(GLenum e1, GLenum e2, GLenum e3, GLenum e4)
#endif
{
glBlendFunc(e1, e2);
}
{
glBlendFunc(e1, e2);
}
#ifdef _WIN32
void __stdcall glBlendEquationSeparateDummy(GLenum e1, GLenum e2)
void __stdcall glBlendEquationSeparateDummy(GLenum e1, GLenum e2)
#else
void APIENTRY glBlendEquationSeparateDummy(GLenum e1, GLenum e2)
void APIENTRY glBlendEquationSeparateDummy(GLenum e1, GLenum e2)
#endif
{
glBlendEquation(e1);
}
{
glBlendEquation(e1);
}
#ifdef _WIN32
extern HINSTANCE hInst;
void (__stdcall *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL;
void (__stdcall *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL;
extern HINSTANCE hInst;
void (__stdcall *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL;
void (__stdcall *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL;
#else
void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL;
void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL;
void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum) = NULL;
void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL;
#endif
//------------------ variables
@ -144,8 +145,8 @@ CGprogram pvs[16] = {NULL};
// String's for shader file in developer mode
#ifdef DEVBUILD
char* EFFECT_NAME="";
char* EFFECT_DIR="";
char* EFFECT_NAME = "";
char* EFFECT_DIR = "";
#endif
/////////////////////
@ -183,52 +184,64 @@ BOOL g_bSaveFlushedFrame = 0;
//------------------ Code
bool ZeroGS::IsGLExt( const char* szTargetExtension )
bool ZeroGS::IsGLExt(const char* szTargetExtension)
{
return mapGLExtensions.find(string(szTargetExtension)) != mapGLExtensions.end();
}
inline bool
ZeroGS::Create_Window(int _width, int _height) {
ZeroGS::Create_Window(int _width, int _height)
{
nBackbufferWidth = _width;
nBackbufferHeight = _height;
fiRendWidth = 1.0f / nBackbufferWidth;
fiRendHeight = 1.0f / nBackbufferHeight;
if (!GLWin.DisplayWindow(_width, _height)) return false;
s_nFullscreen = (conf.options & GSOPTION_FULLSCREEN) ? 1 : 0;
conf.mrtdepth = 0; // for now
return true;
}
// Function asks about different OGL extensions, that are required to setup accordingly. Return false if checks failed
inline bool ZeroGS::CreateImportantCheck() {
inline bool ZeroGS::CreateImportantCheck()
{
bool bSuccess = true;
#ifndef _WIN32
int const glew_ok = glewInit();
if( glew_ok != GLEW_OK ) {
if (glew_ok != GLEW_OK)
{
ZZLog::Error_Log("glewInit() is not ok!");
bSuccess = false;
}
#endif
if( !IsGLExt("GL_EXT_framebuffer_object") ) {
if (!IsGLExt("GL_EXT_framebuffer_object"))
{
ZZLog::Error_Log("*********\nZZogl: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nZZogl: *********");
bSuccess = false;
}
if( !IsGLExt("GL_EXT_secondary_color") ) {
if (!IsGLExt("GL_EXT_secondary_color"))
{
ZZLog::Error_Log("*********\nZZogl: OGL WARNING: Need GL_EXT_secondary_color\nZZogl: *********");
bSuccess = false;
}
// load the effect & find the best profiles (if any)
if( cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE ) {
if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE)
{
ZZLog::Error_Log("arbvp1 not supported.");
bSuccess = false;
}
if( cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE ) {
if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE)
{
ZZLog::Error_Log("arbfp1 not supported.");
bSuccess = false;
}
@ -237,43 +250,51 @@ inline bool ZeroGS::CreateImportantCheck() {
}
// This is a check for less important open gl extensions.
inline void ZeroGS::CreateOtherCheck() {
if( !IsGLExt("GL_EXT_blend_equation_separate") || glBlendEquationSeparateEXT == NULL ) {
inline void ZeroGS::CreateOtherCheck()
{
if (!IsGLExt("GL_EXT_blend_equation_separate") || glBlendEquationSeparateEXT == NULL)
{
ZZLog::Error_Log("*********\nZZogl: OGL WARNING: Need GL_EXT_blend_equation_separate\nZZogl: *********");
zgsBlendEquationSeparateEXT = glBlendEquationSeparateDummy;
}
else
zgsBlendEquationSeparateEXT = glBlendEquationSeparateEXT;
if( !IsGLExt("GL_EXT_blend_func_separate") || glBlendFuncSeparateEXT == NULL ) {
if (!IsGLExt("GL_EXT_blend_func_separate") || glBlendFuncSeparateEXT == NULL)
{
ZZLog::Error_Log("*********\nZZogl: OGL WARNING: Need GL_EXT_blend_func_separate\nZZogl: *********");
zgsBlendFuncSeparateEXT = glBlendFuncSeparateDummy;
}
else
zgsBlendFuncSeparateEXT = glBlendFuncSeparateEXT;
if( !IsGLExt("GL_ARB_draw_buffers") && !IsGLExt("GL_ATI_draw_buffers") ) {
if (!IsGLExt("GL_ARB_draw_buffers") && !IsGLExt("GL_ATI_draw_buffers"))
{
ZZLog::Error_Log("*********\nZZogl: OGL WARNING: multiple render targets not supported, some effects might look bad\nZZogl: *********");
conf.mrtdepth = 0;
}
if( IsGLExt("GL_ARB_draw_buffers") )
if (IsGLExt("GL_ARB_draw_buffers"))
glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffers");
else if( IsGLExt("GL_ATI_draw_buffers") )
else if (IsGLExt("GL_ATI_draw_buffers"))
glDrawBuffers = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress("glDrawBuffersATI");
if (!IsGLExt("GL_ARB_multitexture"))
if (!IsGLExt("GL_ARB_multitexture"))
ZZLog::Error_Log("No multitexturing.");
else
ZZLog::Error_Log("Using multitexturing.");
GLint Max_Texture_Size_NV = 0;
GLint Max_Texture_Size_2d = 0;
glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, &Max_Texture_Size_NV);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Max_Texture_Size_2d);
ZZLog::Error_Log("Maximum texture size is %d for Tex_2d and %d for Tex_NV.", Max_Texture_Size_2d, Max_Texture_Size_NV);
if (Max_Texture_Size_NV < 1024)
ZZLog::Error_Log("Could not properly make bitmasks, so some textures will be missed.");
@ -291,44 +312,56 @@ inline void ZeroGS::CreateOtherCheck() {
g_RenderFormatType = RFT_byte8;
#ifdef _WIN32
if( IsGLExt("WGL_EXT_swap_control") || IsGLExt("EXT_swap_control") )
if (IsGLExt("WGL_EXT_swap_control") || IsGLExt("EXT_swap_control"))
wglSwapIntervalEXT(0);
#else
if( IsGLExt("GLX_SGI_swap_control") ) {
if (IsGLExt("GLX_SGI_swap_control"))
{
_PFNSWAPINTERVAL swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapInterval");
if( !swapinterval )
if (!swapinterval)
swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapIntervalSGI");
if( !swapinterval )
if (!swapinterval)
swapinterval = (_PFNSWAPINTERVAL)wglGetProcAddress("glXSwapIntervalEXT");
if( swapinterval )
if (swapinterval)
swapinterval(0);
else
ZZLog::Error_Log("No support for SwapInterval (framerate clamped to monitor refresh rate),");
}
#endif
}
// open shader file according to build target
inline bool ZeroGS::CreateOpenShadersFile() {
inline bool ZeroGS::CreateOpenShadersFile()
{
#ifndef DEVBUILD
# ifdef _WIN32
HRSRC hShaderSrc = FindResource(hInst, MAKEINTRESOURCE(IDR_SHADERS), RT_RCDATA);
assert( hShaderSrc != NULL );
assert(hShaderSrc != NULL);
HGLOBAL hShaderGlob = LoadResource(hInst, hShaderSrc);
assert( hShaderGlob != NULL );
assert(hShaderGlob != NULL);
s_lpShaderResources = (u8*)LockResource(hShaderGlob);
# else // not _WIN32
FILE* fres = fopen("ps2hw.dat", "rb");
if( fres == NULL ) {
if (fres == NULL)
{
fres = fopen("plugins/ps2hw.dat", "rb");
if( fres == NULL ) {
if (fres == NULL)
{
ZZLog::Error_Log("Cannot find ps2hw.dat in working directory. Exiting.");
return false;
}
}
fseek(fres, 0, SEEK_END);
size_t s = ftell(fres);
s_lpShaderResources = new u8[s+1];
fseek(fres, 0, SEEK_SET);
@ -345,33 +378,40 @@ inline bool ZeroGS::CreateOpenShadersFile() {
strcpy(tempstr, "/plugins/");
sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr);
FILE* f = fopen(EFFECT_NAME, "r");
if( f == NULL ) {
if (f == NULL)
{
strcpy(tempstr, "../../plugins/zzogl-pg/opengl/");
sprintf(EFFECT_NAME, "%sps2hw.fx", tempstr);
f = fopen(EFFECT_NAME, "r");
if( f == NULL ) {
if (f == NULL)
{
ZZLog::Error_Log("Failed to find %s, try compiling a non-devbuild.", EFFECT_NAME);
return false;
}
}
fclose(f);
sprintf(EFFECT_DIR, "%s/%s", curwd, tempstr);
sprintf(EFFECT_NAME, "%sps2hw.fx", EFFECT_DIR);
#endif
#endif
#endif // !defined(ZEROGS_DEVBUILD)
return true;
}
// Read all extensions name and fill mapGLExtensions
inline bool CreateFillExtensionsMap(){
inline bool CreateFillExtensionsMap()
{
// fill the opengl extension map
const char* ptoken = (const char*)glGetString( GL_EXTENSIONS );
if( ptoken == NULL ) return false;
const char* ptoken = (const char*)glGetString(GL_EXTENSIONS);
if (ptoken == NULL) return false;
int prevlog = conf.log;
conf.log = 1;
ZZLog::GS_Log("Supported OpenGL Extensions:\n%s\n", ptoken); // write to the log file
@ -391,20 +431,25 @@ inline bool CreateFillExtensionsMap(){
const char* pend = NULL;
while(ptoken != NULL ) {
while (ptoken != NULL)
{
pend = strchr(ptoken, ' ');
if( pend != NULL ) {
if (pend != NULL)
{
mapGLExtensions[string(ptoken, pend-ptoken)];
}
else {
else
{
mapGLExtensions[string(ptoken)];
break;
}
ptoken = pend;
while(*ptoken == ' ') ++ptoken;
while (*ptoken == ' ') ++ptoken;
}
return true;
}
@ -431,15 +476,16 @@ bool ZeroGS::Create(int _width, int _height)
// check the max texture width and height
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &g_MaxTexWidth);
g_MaxTexHeight = g_MaxTexWidth/4;
GPU_TEXWIDTH = g_MaxTexWidth/8;
g_MaxTexHeight = g_MaxTexWidth / 4;
GPU_TEXWIDTH = g_MaxTexWidth / 8;
g_fiGPU_TEXWIDTH = 1.0f / GPU_TEXWIDTH;
if (!CreateOpenShadersFile())
return false;
if (!CreateOpenShadersFile()) return false;
GL_REPORT_ERROR();
if( err != GL_NO_ERROR ) bSuccess = false;
if (err != GL_NO_ERROR) bSuccess = false;
s_srcrgb = s_dstrgb = s_srcalpha = s_dstalpha = GL_ONE;
@ -461,28 +507,31 @@ bool ZeroGS::Create(int _width, int _height)
GL_LOADFN(glGetFramebufferAttachmentParameterivEXT);
GL_LOADFN(glGenerateMipmapEXT);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GL_REPORT_ERROR();
if( err != GL_NO_ERROR ) bSuccess = false;
glGenFramebuffersEXT( 1, &s_uFramebuffer);
if( s_uFramebuffer == 0 ) {
if (err != GL_NO_ERROR) bSuccess = false;
glGenFramebuffersEXT(1, &s_uFramebuffer);
if (s_uFramebuffer == 0)
{
ZZLog::Error_Log("Failed to create the renderbuffer.");
}
assert( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT );
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer );
assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT);
if( glDrawBuffers != NULL )
glDrawBuffers(1, s_drawbuffers);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer);
if (glDrawBuffers != NULL) glDrawBuffers(1, s_drawbuffers);
GL_REPORT_ERROR();
if( err != GL_NO_ERROR ) bSuccess = false;
if (err != GL_NO_ERROR) bSuccess = false;
font_p = new RasterFont();
GL_REPORT_ERROR();
if( err != GL_NO_ERROR ) bSuccess = false;
if (err != GL_NO_ERROR) bSuccess = false;
// init draw fns
drawfn[0] = KickPoint;
@ -495,64 +544,76 @@ bool ZeroGS::Create(int _width, int _height)
drawfn[7] = KickDummy;
SetAA(conf.aa);
GSsetGameCRC(g_LastCRC, g_GameSettings);
GL_STENCILFUNC(GL_ALWAYS, 0, 0);
//g_GameSettings |= 0;//GAME_VSSHACK|GAME_FULL16BITRES|GAME_NODEPTHRESOLVE|GAME_FASTUPDATE;
//s_bWriteDepth = TRUE;
GL_BLEND_ALL(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
glViewport(0,0,nBackbufferWidth,nBackbufferHeight); // Reset The Current Viewport
glViewport(0, 0, nBackbufferWidth, nBackbufferHeight); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glGenTextures(1, &ptexLogo);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptexLogo);
#ifdef _WIN32
HRSRC hBitmapSrc = FindResource(hInst, MAKEINTRESOURCE(IDB_ZEROGSLOGO), RT_BITMAP);
assert( hBitmapSrc != NULL );
assert(hBitmapSrc != NULL);
HGLOBAL hBitmapGlob = LoadResource(hInst, hBitmapSrc);
assert( hBitmapGlob != NULL );
assert(hBitmapGlob != NULL);
PBITMAPINFO pinfo = (PBITMAPINFO)LockResource(hBitmapGlob);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, pinfo->bmiHeader.biWidth, pinfo->bmiHeader.biHeight, 0, pinfo->bmiHeader.biBitCount==32?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, (u8*)pinfo+pinfo->bmiHeader.biSize);
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, pinfo->bmiHeader.biWidth, pinfo->bmiHeader.biHeight, 0, pinfo->bmiHeader.biBitCount == 32 ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, (u8*)pinfo + pinfo->bmiHeader.biSize);
nLogoWidth = pinfo->bmiHeader.biWidth;
nLogoHeight = pinfo->bmiHeader.biHeight;
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
#else
#endif
GL_REPORT_ERROR();
g_nCurVBOIndex = 0;
g_vboBuffers.resize(VB_NUMBUFFERS);
glGenBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]);
for(i = 0; i < (int)g_vboBuffers.size(); ++i) {
for (i = 0; i < (int)g_vboBuffers.size(); ++i)
{
glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[i]);
glBufferData(GL_ARRAY_BUFFER, 0x100*sizeof(VertexGPU), NULL, GL_STREAM_DRAW);
}
GL_REPORT_ERROR();
if( err != GL_NO_ERROR ) bSuccess = false;
if (err != GL_NO_ERROR) bSuccess = false;
// create the blocks texture
g_fBlockMult = 1;
vector<char> vBlockData, vBilinearData;
BLOCK::FillBlocks(vBlockData, vBilinearData, 1);
glGenTextures(1, &ptexBlocks);
@ -564,7 +625,8 @@ bool ZeroGS::Create(int _width, int _height)
glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_ALPHA, GL_FLOAT, &vBlockData[0]);
if( glGetError() != GL_NO_ERROR ) {
if (glGetError() != GL_NO_ERROR)
{
// try different internal format
g_internalFloatFmt = GL_FLOAT_R32_NV;
glTexImage2D(GL_TEXTURE_2D, 0, g_internalFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RED, GL_FLOAT, &vBlockData[0]);
@ -575,26 +637,31 @@ bool ZeroGS::Create(int _width, int _height)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
if( glGetError() != GL_NO_ERROR ) {
if (glGetError() != GL_NO_ERROR)
{
// error, resort to 16bit
g_fBlockMult = 65535.0f*(float)g_fiGPU_TEXWIDTH / 32.0f;
g_fBlockMult = 65535.0f * (float)g_fiGPU_TEXWIDTH / 32.0f;
BLOCK::FillBlocks(vBlockData, vBilinearData, 0);
glTexImage2D(GL_TEXTURE_2D, 0, 2, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_R, GL_UNSIGNED_SHORT, &vBlockData[0]);
if( glGetError() != GL_NO_ERROR ) {
if (glGetError() != GL_NO_ERROR)
{
ZZLog::Error_Log("Could not fill blocks.");
return false;
}
ZZLog::Error_Log("Using non-bilinear fill.");
}
else {
else
{
// fill in the bilinear blocks
glGenTextures(1, &ptexBilinearBlocks);
glBindTexture(GL_TEXTURE_2D, ptexBilinearBlocks);
glTexImage2D(GL_TEXTURE_2D, 0, g_internalRGBAFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RGBA, GL_FLOAT, &vBilinearData[0]);
if( glGetError() != GL_NO_ERROR ) {
if (glGetError() != GL_NO_ERROR)
{
g_internalRGBAFloatFmt = GL_FLOAT_RGBA32_NV;
g_internalRGBAFloat16Fmt = GL_FLOAT_RGBA16_NV;
glTexImage2D(GL_TEXTURE_2D, 0, g_internalRGBAFloatFmt, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, 0, GL_RGBA, GL_FLOAT, &vBilinearData[0]);
@ -603,7 +670,8 @@ bool ZeroGS::Create(int _width, int _height)
}
else
{
ZZLog::Error_Log("Fill bilinear blocks failed!");
// No, they failed on the first clause of the if statement, not the second.
//ZZLog::Error_Log("Fill bilinear blocks failed!");
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -613,9 +681,10 @@ bool ZeroGS::Create(int _width, int _height)
}
float fpri = 1;
glPrioritizeTextures(1, &ptexBlocks, &fpri);
if( ptexBilinearBlocks != 0 )
glPrioritizeTextures(1, &ptexBilinearBlocks, &fpri);
if (ptexBilinearBlocks != 0) glPrioritizeTextures(1, &ptexBilinearBlocks, &fpri);
GL_REPORT_ERROR();
@ -624,11 +693,37 @@ bool ZeroGS::Create(int _width, int _height)
glBindBuffer(GL_ARRAY_BUFFER, vboRect);
vector<VertexGPU> verts(4);
VertexGPU* pvert = &verts[0];
pvert->x = -0x7fff; pvert->y = 0x7fff; pvert->z = 0; pvert->s = 0; pvert->t = 0; pvert++;
pvert->x = 0x7fff; pvert->y = 0x7fff; pvert->z = 0; pvert->s = 1; pvert->t = 0; pvert++;
pvert->x = -0x7fff; pvert->y = -0x7fff; pvert->z = 0; pvert->s = 0; pvert->t = 1; pvert++;
pvert->x = 0x7fff; pvert->y = -0x7fff; pvert->z = 0; pvert->s = 1; pvert->t = 1; pvert++;
pvert->x = -0x7fff;
pvert->y = 0x7fff;
pvert->z = 0;
pvert->s = 0;
pvert->t = 0;
pvert++;
pvert->x = 0x7fff;
pvert->y = 0x7fff;
pvert->z = 0;
pvert->s = 1;
pvert->t = 0;
pvert++;
pvert->x = -0x7fff;
pvert->y = -0x7fff;
pvert->z = 0;
pvert->s = 0;
pvert->t = 1;
pvert++;
pvert->x = 0x7fff;
pvert->y = -0x7fff;
pvert->z = 0;
pvert->s = 1;
pvert->t = 1;
pvert++;
glBufferDataARB(GL_ARRAY_BUFFER, 4*sizeof(VertexGPU), &verts[0], GL_STATIC_DRAW);
// setup the default vertex declaration
@ -649,33 +744,45 @@ bool ZeroGS::Create(int _width, int _height)
glBindTexture(GL_TEXTURE_2D, ptexConv16to32);
vector<u32> conv16to32data(256*256);
for(i = 0; i < 256*256; ++i) {
for (i = 0; i < 256*256; ++i)
{
u32 tempcol = RGBA16to32(i);
// have to flip r and b
conv16to32data[i] = (tempcol&0xff00ff00)|((tempcol&0xff)<<16)|((tempcol&0xff0000)>>16);
conv16to32data[i] = (tempcol & 0xff00ff00) | ((tempcol & 0xff) << 16) | ((tempcol & 0xff0000) >> 16);
}
glTexImage2D(GL_TEXTURE_2D, 0, 4, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, &conv16to32data[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
GL_REPORT_ERROR();
if( err != GL_NO_ERROR ) bSuccess = false;
if (err != GL_NO_ERROR) bSuccess = false;
vector<u32> conv32to16data(32*32*32);
glGenTextures(1, &ptexConv32to16);
glBindTexture(GL_TEXTURE_3D, ptexConv32to16);
u32* dst = &conv32to16data[0];
for(i = 0; i < 32; ++i) {
for(int j = 0; j < 32; ++j) {
for(int k = 0; k < 32; ++k) {
u32 col = (i<<10)|(j<<5)|k;
*dst++ = ((col&0xff)<<16)|(col&0xff00);
for (i = 0; i < 32; ++i)
{
for (int j = 0; j < 32; ++j)
{
for (int k = 0; k < 32; ++k)
{
u32 col = (i << 10) | (j << 5) | k;
*dst++ = ((col & 0xff) << 16) | (col & 0xff00);
}
}
}
glTexImage3D(GL_TEXTURE_3D, 0, 4, 32, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, &conv32to16data[0]);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -683,18 +790,22 @@ bool ZeroGS::Create(int _width, int _height)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP);
GL_REPORT_ERROR();
if( err != GL_NO_ERROR ) bSuccess = false;
if (err != GL_NO_ERROR) bSuccess = false;
g_cgcontext = cgCreateContext();
cgvProf = CG_PROFILE_ARBVP1;
cgfProf = CG_PROFILE_ARBFP1;
cgGLEnableProfile(cgvProf);
cgGLEnableProfile(cgfProf);
cgGLSetOptimalOptions(cgvProf);
cgGLSetOptimalOptions(cgfProf);
cgGLSetManageTextureParameters(g_cgcontext, CG_FALSE);
//cgSetAutoCompile(g_cgcontext, CG_COMPILE_IMMEDIATE);
g_fparamFogColor = cgCreateParameter(g_cgcontext, CG_FLOAT4);
@ -702,6 +813,7 @@ bool ZeroGS::Create(int _width, int _height)
g_vparamPosXY[1] = cgCreateParameter(g_cgcontext, CG_FLOAT4);
ZZLog::Error_Log("Creating effects.");
B_G(LoadEffects(), return false);
g_bDisplayMsg = 0;
@ -709,41 +821,54 @@ bool ZeroGS::Create(int _width, int _height)
// create a sample shader
clampInfo temp;
memset(&temp, 0, sizeof(temp));
temp.wms = 3; temp.wmt = 3;
temp.wms = 3;
temp.wmt = 3;
g_nPixelShaderVer = 0;//SHADER_ACCURATE;
// test
bool bFailed;
FRAGMENTSHADER* pfrag = LoadShadeEffect(0, 1, 1, 1, 1, temp, 0, &bFailed);
if( bFailed || pfrag == NULL ) {
g_nPixelShaderVer = SHADER_ACCURATE|SHADER_REDUCED;
if (bFailed || pfrag == NULL)
{
g_nPixelShaderVer = SHADER_ACCURATE | SHADER_REDUCED;
pfrag = LoadShadeEffect(0, 0, 1, 1, 0, temp, 0, &bFailed);
if( pfrag != NULL )
if (pfrag != NULL)
cgGLLoadProgram(pfrag->prog);
if( bFailed || pfrag == NULL || cgGetError() != CG_NO_ERROR ) {
if (bFailed || pfrag == NULL || cgGetError() != CG_NO_ERROR)
{
g_nPixelShaderVer = SHADER_REDUCED;
ZZLog::Error_Log("Basic shader test failed.");
}
}
g_bDisplayMsg = 1;
if( g_nPixelShaderVer & SHADER_REDUCED )
conf.bilinear = 0;
if (g_nPixelShaderVer & SHADER_REDUCED) conf.bilinear = 0;
ZZLog::Error_Log("Creating extra effects.");
B_G(LoadExtraEffects(), return false);
ZZLog::Error_Log("Using %s shaders.", g_pShaders[g_nPixelShaderVer]);
GL_REPORT_ERROR();
if( err != GL_NO_ERROR ) bSuccess = false;
if (err != GL_NO_ERROR) bSuccess = false;
glDisable(GL_STENCIL_TEST);
glEnable(GL_SCISSOR_TEST);
GL_BLEND_ALPHA(GL_ONE, GL_ZERO);
glBlendColorEXT(0, 0, 0, 0.5f);
glDisable(GL_CULL_FACE);
@ -751,20 +876,27 @@ bool ZeroGS::Create(int _width, int _height)
// points
// This was changed in SetAA - should we be changing it back?
glPointSize(1.0f);
g_nDepthBias = 0;
glEnable(GL_POLYGON_OFFSET_FILL);
glEnable(GL_POLYGON_OFFSET_LINE);
glPolygonOffset(0, 1);
vb[0].Init(VB_BUFFERSIZE);
vb[1].Init(VB_BUFFERSIZE);
g_bSaveFlushedFrame = 1;
g_vsprog = g_psprog = 0;
if (glGetError() == GL_NO_ERROR)
{
return bSuccess;
else {
}
else
{
ZZLog::Error_Log("In final init!");
return false;
}
@ -772,7 +904,8 @@ bool ZeroGS::Create(int _width, int _height)
void ZeroGS::Destroy(BOOL bD3D)
{
if( s_aviinit ) {
if (s_aviinit)
{
StopCapture();
Stop_Avi();
ZZLog::Error_Log("zerogs.avi stopped.");
@ -780,6 +913,7 @@ void ZeroGS::Destroy(BOOL bD3D)
}
g_MemTargs.Destroy();
s_RTs.Destroy();
s_DepthRTs.Destroy();
s_BitwiseTextures.Destroy();
@ -793,28 +927,40 @@ void ZeroGS::Destroy(BOOL bD3D)
vb[0].Destroy();
vb[1].Destroy();
if( g_vboBuffers.size() > 0 ) {
if (g_vboBuffers.size() > 0)
{
glDeleteBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]);
g_vboBuffers.clear();
}
g_nCurVBOIndex = 0;
for(int i = 0; i < ARRAY_SIZE(pvs); ++i) {
for (int i = 0; i < ARRAY_SIZE(pvs); ++i)
{
SAFE_RELEASE_PROG(pvs[i]);
}
for(int i = 0; i < ARRAY_SIZE(ppsRegular); ++i) {
for (int i = 0; i < ARRAY_SIZE(ppsRegular); ++i)
{
SAFE_RELEASE_PROG(ppsRegular[i].prog);
}
for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) {
for (int i = 0; i < ARRAY_SIZE(ppsTexture); ++i)
{
SAFE_RELEASE_PROG(ppsTexture[i].prog);
}
SAFE_RELEASE_PROG(pvsBitBlt.prog);
SAFE_RELEASE_PROG(ppsBitBlt[0].prog); SAFE_RELEASE_PROG(ppsBitBlt[1].prog);
SAFE_RELEASE_PROG(ppsBitBlt[0].prog);
SAFE_RELEASE_PROG(ppsBitBlt[1].prog);
SAFE_RELEASE_PROG(ppsBitBltDepth.prog);
SAFE_RELEASE_PROG(ppsCRTCTarg[0].prog); SAFE_RELEASE_PROG(ppsCRTCTarg[1].prog);
SAFE_RELEASE_PROG(ppsCRTC[0].prog); SAFE_RELEASE_PROG(ppsCRTC[1].prog);
SAFE_RELEASE_PROG(ppsCRTC24[0].prog); SAFE_RELEASE_PROG(ppsCRTC24[1].prog);
SAFE_RELEASE_PROG(ppsCRTCTarg[0].prog);
SAFE_RELEASE_PROG(ppsCRTCTarg[1].prog);
SAFE_RELEASE_PROG(ppsCRTC[0].prog);
SAFE_RELEASE_PROG(ppsCRTC[1].prog);
SAFE_RELEASE_PROG(ppsCRTC24[0].prog);
SAFE_RELEASE_PROG(ppsCRTC24[1].prog);
SAFE_RELEASE_PROG(ppsOne.prog);
SAFE_DELETE(font_p);

File diff suppressed because it is too large Load Diff

View File

@ -46,31 +46,38 @@ extern u32 s_uTex1Data[2][2], s_uClampData[2];
int ZeroGS::Save(s8* pbydata)
{
if( pbydata == NULL )
if (pbydata == NULL)
return 40 + 0x00400000 + sizeof(gs) + 2*VBSAVELIMIT + 2*sizeof(frameInfo) + 4 + 256*4;
s_RTs.ResolveAll();
s_DepthRTs.ResolveAll();
strcpy((char*)pbydata, libraryNameX);
*(u32*)(pbydata+16) = ZEROGS_SAVEVER;
pbydata += 32;
*(int*)pbydata = icurctx; pbydata += 4;
*(int*)pbydata = VBSAVELIMIT; pbydata += 4;
*(u32*)(pbydata + 16) = ZEROGS_SAVEVER;
pbydata += 32;
*(int*)pbydata = icurctx;
pbydata += 4;
*(int*)pbydata = VBSAVELIMIT;
pbydata += 4;
memcpy(pbydata, g_pbyGSMemory, 0x00400000);
pbydata += 0x00400000;
memcpy(pbydata, g_pbyGSClut, 256*4);
pbydata += 256*4;
pbydata += 256 * 4;
*(int*)pbydata = sizeof(gs);
pbydata += 4;
memcpy(pbydata, &gs, sizeof(gs));
pbydata += sizeof(gs);
for(int i = 0; i < 2; ++i) {
for (int i = 0; i < 2; ++i)
{
memcpy(pbydata, &vb[i], VBSAVELIMIT);
pbydata += VBSAVELIMIT;
}
@ -86,10 +93,10 @@ bool ZeroGS::Load(s8* pbydata)
g_nCurVBOIndex = 0;
// first 32 bytes are the id
u32 savever = *(u32*)(pbydata+16);
if( strncmp((char*)pbydata, libraryNameX, 6) == 0 && (savever == ZEROGS_SAVEVER || savever == 0xaa000004) ) {
u32 savever = *(u32*)(pbydata + 16);
if (strncmp((char*)pbydata, libraryNameX, 6) == 0 && (savever == ZEROGS_SAVEVER || savever == 0xaa000004))
{
g_MemTargs.Destroy();
GSStateReset();
@ -99,25 +106,31 @@ bool ZeroGS::Load(s8* pbydata)
pbydata += 4;
u32 savelimit = VBSAVELIMIT;
savelimit = *(u32*)pbydata; pbydata += 4;
savelimit = *(u32*)pbydata;
pbydata += 4;
memcpy(g_pbyGSMemory, pbydata, 0x00400000);
pbydata += 0x00400000;
memcpy(g_pbyGSClut, pbydata, 256*4);
pbydata += 256*4;
pbydata += 256 * 4;
memset(&gs, 0, sizeof(gs));
int savedgssize;
if( savever == 0xaa000004 )
if (savever == 0xaa000004)
{
savedgssize = 0x1d0;
else {
}
else
{
savedgssize = *(int*)pbydata;
pbydata += 4;
}
memcpy(&gs, pbydata, savedgssize);
pbydata += savedgssize;
prim = &gs._prim[gs.prac];
@ -131,17 +144,19 @@ bool ZeroGS::Load(s8* pbydata)
pbydata += savelimit;
vb[1].pBufferData = NULL;
for(int i = 0; i < 2; ++i) {
for (int i = 0; i < 2; ++i)
{
vb[i].Init(VB_BUFFERSIZE);
vb[i].bNeedZCheck = vb[i].bNeedFrameCheck = 1;
vb[i].bSyncVars = 0; vb[i].bNeedTexCheck = 1;
vb[i].bSyncVars = 0;
vb[i].bNeedTexCheck = 1;
memset(vb[i].uCurTex0Data, 0, sizeof(vb[i].uCurTex0Data));
}
icurctx = -1;
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); // switch to the backbuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer); // switch to the backbuffer
SetFogColor(gs.fogcol);
GL_REPORT_ERRORD();

View File

@ -30,9 +30,11 @@ using namespace ZeroGS;
//------------------ Constants
// ----------------- Global Variables
namespace ZeroGS {
FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne;
FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16;
namespace ZeroGS
{
FRAGMENTSHADER ppsBitBlt[2], ppsBitBltDepth, ppsOne;
FRAGMENTSHADER ppsBaseTexture, ppsConvert16to32, ppsConvert32to16;
}
// Debug variable, store name of the function that call the shader.
@ -46,8 +48,8 @@ void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
{
ZZLog::Error_Log("%s->%s: %s", ShaderCallerName, ShaderHandleName, cgGetErrorString(err));
const char* listing = cgGetLastListing(g_cgcontext);
if (listing != NULL)
ZZLog::Debug_Log(" Last listing: %s", listing);
if (listing != NULL) ZZLog::Debug_Log(" Last listing: %s", listing);
}
// This is a helper of cgGLSetParameter4fv, made for debugging purposes.
@ -82,14 +84,24 @@ void SetupFragmentProgramParameters(FRAGMENTSHADER* pf, int context, int type)
pf->set_texture(ptexBlocks, "g_sBlocks");
// cg parameter usage is wrong, so do it manually
switch(type)
switch (type)
{
case 3: pf->set_texture(ptexConv16to32, "g_sConv16to32"); break;
case 4: pf->set_texture(ptexConv32to16, "g_sConv32to16"); break;
default: pf->set_texture(ptexBilinearBlocks, "g_sBilinearBlocks"); break;
case 3:
pf->set_texture(ptexConv16to32, "g_sConv16to32");
break;
case 4:
pf->set_texture(ptexConv32to16, "g_sConv32to16");
break;
default:
pf->set_texture(ptexBilinearBlocks, "g_sBilinearBlocks");
break;
}
pf->set_texture(pf->sMemory, "g_sMemory");
pf->set_texture(pf->sFinal, "g_sSrcFinal");
pf->set_texture(pf->sBitwiseANDX, "g_sBitwiseANDX");
pf->set_texture(pf->sBitwiseANDY, "g_sBitwiseANDY");
@ -97,11 +109,11 @@ void SetupFragmentProgramParameters(FRAGMENTSHADER* pf, int context, int type)
pf->set_texture(pf->sInterlace, "g_sInterlace");
// set global shader constants
pf->set_shader_const(Vector(0.5f, (g_GameSettings&GAME_EXACTCOLOR)?0.9f/256.0f:0.5f/256.0f, 0,1/255.0f), "g_fExactColor");
pf->set_shader_const(Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f ), "g_fBilinear");
pf->set_shader_const(Vector(1.0f/256.0f, 1.0004f, 1, 0.5f), "g_fZBias");
pf->set_shader_const(Vector(0,1, 0.001f, 0.5f), "g_fc0");
pf->set_shader_const(Vector(1/1024.0f, 0.2f/1024.0f, 1/128.0f, 1/512.0f), "g_fMult");
pf->set_shader_const(Vector(0.5f, (g_GameSettings&GAME_EXACTCOLOR) ? 0.9f / 256.0f : 0.5f / 256.0f, 0, 1 / 255.0f), "g_fExactColor");
pf->set_shader_const(Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f), "g_fBilinear");
pf->set_shader_const(Vector(1.0f / 256.0f, 1.0004f, 1, 0.5f), "g_fZBias");
pf->set_shader_const(Vector(0, 1, 0.001f, 0.5f), "g_fc0");
pf->set_shader_const(Vector(1 / 1024.0f, 0.2f / 1024.0f, 1 / 128.0f, 1 / 512.0f), "g_fMult");
}
void SetupVertexProgramParameters(CGprogram prog, int context)
@ -109,50 +121,62 @@ void SetupVertexProgramParameters(CGprogram prog, int context)
CGparameter p;
p = cgGetNamedParameter(prog, "g_fPosXY");
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE)
cgConnectParameter(g_vparamPosXY[context], p);
// Set Z-test, log or no log;
if (g_GameSettings&GAME_NOLOGZ)
{
g_vdepth = Vector( 255.0 /256.0f, 255.0/65536.0f, 255.0f/(65535.0f*256.0f), 1.0f/(65536.0f*65536.0f));
vlogz = Vector( 1.0f, 0.0f, 0.0f, 0.0f);
g_vdepth = Vector(255.0 / 256.0f, 255.0 / 65536.0f, 255.0f / (65535.0f * 256.0f), 1.0f / (65536.0f * 65536.0f));
vlogz = Vector(1.0f, 0.0f, 0.0f, 0.0f);
}
else
{
g_vdepth = Vector( 256.0f*65536.0f, 65536.0f, 256.0f, 65536.0f*65536.0f);
vlogz = Vector( 0.0f, 1.0f, 0.0f, 0.0f);
g_vdepth = Vector(256.0f * 65536.0f, 65536.0f, 256.0f, 65536.0f * 65536.0f);
vlogz = Vector(0.0f, 1.0f, 0.0f, 0.0f);
}
p = cgGetNamedParameter(prog, "g_fZ");
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) {
if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE)
{
cgGLSetParameter4fv(p, g_vdepth);
p = cgGetNamedParameter(prog, "g_fZMin"); // Switch to flat-z when needed
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE ) {
if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE)
{
//ZZLog::Error_Log("Use flat-z");
cgGLSetParameter4fv(p, vlogz);
}
else
{
ZZLog::Error_Log("Shader file version is outdated! Only log-Z is possible.");
}
}
Vector vnorm = Vector(g_filog32, 0, 0,0);
Vector vnorm = Vector(g_filog32, 0, 0, 0);
p = cgGetNamedParameter(prog, "g_fZNorm");
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE)
cgGLSetParameter4fv(p, vnorm);
p = cgGetNamedParameter(prog, "g_fBilinear");
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
cgGLSetParameter4fv(p, Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f ));
if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE)
cgGLSetParameter4fv(p, Vector(-0.2f, -0.65f, 0.9f, 1.0f / 32767.0f));
p = cgGetNamedParameter(prog, "g_fZBias");
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
cgGLSetParameter4fv(p, Vector(1.0f/256.0f, 1.0004f, 1, 0.5f));
if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE)
cgGLSetParameter4fv(p, Vector(1.0f / 256.0f, 1.0004f, 1, 0.5f));
p = cgGetNamedParameter(prog, "g_fc0");
if( p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE )
cgGLSetParameter4fv(p, Vector(0,1, 0.001f, 0.5f));
if (p != NULL && cgIsParameterUsed(p, prog) == CG_TRUE)
cgGLSetParameter4fv(p, Vector(0, 1, 0.001f, 0.5f));
}
#ifndef DEVBUILD
@ -190,34 +214,39 @@ void SetupVertexProgramParameters(CGprogram prog, int context)
bool ZeroGS::LoadEffects()
{
assert( s_lpShaderResources != NULL );
assert(s_lpShaderResources != NULL);
// process the header
u32 num = *(u32*)s_lpShaderResources;
int compressed_size = *(int*)(s_lpShaderResources+4);
int real_size = *(int*)(s_lpShaderResources+8);
int compressed_size = *(int*)(s_lpShaderResources + 4);
int real_size = *(int*)(s_lpShaderResources + 8);
int out;
char* pbuffer = (char*)malloc(real_size);
inf((char*)s_lpShaderResources+12, &pbuffer[0], compressed_size, real_size, &out);
inf((char*)s_lpShaderResources + 12, &pbuffer[0], compressed_size, real_size, &out);
assert(out == real_size);
s_lpShaderResources = (u8*)pbuffer;
SHADERHEADER* header = (SHADERHEADER*)s_lpShaderResources;
mapShaderResources.clear();
while(num-- > 0 ) {
while (num-- > 0)
{
mapShaderResources[header->index] = header;
++header;
}
// clear the textures
for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) {
for (int i = 0; i < ARRAY_SIZE(ppsTexture); ++i)
{
SAFE_RELEASE_PROG(ppsTexture[i].prog);
ppsTexture[i].prog = NULL;
}
#ifndef _DEBUG
memset(ppsTexture, 0, sizeof(ppsTexture));
#endif
return true;
@ -231,12 +260,13 @@ bool ZeroGS::LoadExtraEffects()
const int vsshaders[4] = { SH_REGULARVS, SH_TEXTUREVS, SH_REGULARFOGVS, SH_TEXTUREFOGVS };
for(int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
LOAD_VS(vsshaders[i], pvs[2*i]);
LOAD_VS((vsshaders[i] | SH_CONTEXT1), pvs[2*i+1]);
//if( conf.mrtdepth ) {
LOAD_VS((vsshaders[i] | SH_WRITEDEPTH), pvs[2*i+8]);
LOAD_VS((vsshaders[i] | SH_WRITEDEPTH | SH_CONTEXT1), pvs[2*i+8+1]);
LOAD_VS((vsshaders[i] | SH_WRITEDEPTH), pvs[2*i+8]);
LOAD_VS((vsshaders[i] | SH_WRITEDEPTH | SH_CONTEXT1), pvs[2*i+8+1]);
// }
// else {
// pvs[2*i+8] = pvs[2*i+8+1] = NULL;
@ -244,6 +274,7 @@ bool ZeroGS::LoadExtraEffects()
}
LOAD_VS(SH_BITBLTVS, pvsBitBlt.prog);
pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos");
pvsBitBlt.sBitBltTex = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTex");
pvsBitBlt.fBitBltTrans = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltTrans");
@ -251,38 +282,50 @@ bool ZeroGS::LoadExtraEffects()
LOAD_PS(SH_REGULARPS, ppsRegular[0]);
LOAD_PS(SH_REGULARFOGPS, ppsRegular[1]);
if( conf.mrtdepth ) {
if (conf.mrtdepth)
{
LOAD_PS(SH_REGULARPS, ppsRegular[2]);
if( !bLoadSuccess )
if (!bLoadSuccess)
conf.mrtdepth = 0;
LOAD_PS(SH_REGULARFOGPS, ppsRegular[3]);
if( !bLoadSuccess )
if (!bLoadSuccess)
conf.mrtdepth = 0;
}
LOAD_PS(SH_BITBLTPS, ppsBitBlt[0]);
LOAD_PS(SH_BITBLTAAPS, ppsBitBlt[1]);
if( !bLoadSuccess ) {
if (!bLoadSuccess)
{
ZZLog::Error_Log("Failed to load BitBltAAPS, using BitBltPS.");
LOAD_PS(SH_BITBLTPS, ppsBitBlt[1]);
}
LOAD_PS(SH_BITBLTDEPTHPS, ppsBitBltDepth);
LOAD_PS(SH_CRTCTARGPS, ppsCRTCTarg[0]);
LOAD_PS(SH_CRTCTARGINTERPS, ppsCRTCTarg[1]);
g_bCRTCBilinear = TRUE;
LOAD_PS(SH_CRTCPS, ppsCRTC[0]);
if( !bLoadSuccess ) {
if (!bLoadSuccess)
{
// switch to simpler
g_bCRTCBilinear = FALSE;
LOAD_PS(SH_CRTC_NEARESTPS, ppsCRTC[0]);
LOAD_PS(SH_CRTCINTER_NEARESTPS, ppsCRTC[0]);
}
else {
else
{
LOAD_PS(SH_CRTCINTERPS, ppsCRTC[1]);
}
if( !bLoadSuccess )
if (!bLoadSuccess)
ZZLog::Error_Log("Failed to create CRTC shaders.");
LOAD_PS(SH_CRTC24PS, ppsCRTC24[0]);
@ -298,62 +341,85 @@ bool ZeroGS::LoadExtraEffects()
FRAGMENTSHADER* ZeroGS::LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed)
{
int texwrap;
assert( texfilter < NUM_FILTERS );
assert(texfilter < NUM_FILTERS);
if(g_nPixelShaderVer&SHADER_REDUCED)
texfilter = 0;
assert(!(g_nPixelShaderVer&SHADER_REDUCED) || !exactcolor);
if (g_nPixelShaderVer & SHADER_REDUCED) texfilter = 0;
if( clamp.wms == clamp.wmt ) {
switch( clamp.wms ) {
case 0: texwrap = TEXWRAP_REPEAT; break;
case 1: texwrap = TEXWRAP_CLAMP; break;
case 2: texwrap = TEXWRAP_CLAMP; break;
default: texwrap = TEXWRAP_REGION_REPEAT; break;
assert(!(g_nPixelShaderVer & SHADER_REDUCED) || !exactcolor);
if (clamp.wms == clamp.wmt)
{
switch (clamp.wms)
{
case 0:
texwrap = TEXWRAP_REPEAT;
break;
case 1:
texwrap = TEXWRAP_CLAMP;
break;
case 2:
texwrap = TEXWRAP_CLAMP;
break;
default:
texwrap = TEXWRAP_REGION_REPEAT;
break;
}
}
else if( clamp.wms==3||clamp.wmt==3)
else if (clamp.wms == 3 || clamp.wmt == 3)
texwrap = TEXWRAP_REGION_REPEAT;
else
texwrap = TEXWRAP_REPEAT_CLAMP;
int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0);
assert( index < ARRAY_SIZE(ppsTexture) );
FRAGMENTSHADER* pf = ppsTexture+index;
assert(index < ARRAY_SIZE(ppsTexture));
if( pbFailed != NULL ) *pbFailed = false;
FRAGMENTSHADER* pf = ppsTexture + index;
if( pf->prog != NULL )
return pf;
if (pbFailed != NULL) *pbFailed = false;
if( (g_nPixelShaderVer & SHADER_ACCURATE) && mapShaderResources.find(index+NUM_SHADERS*SHADER_ACCURATE) != mapShaderResources.end() )
index += NUM_SHADERS*SHADER_ACCURATE;
if (pf->prog != NULL) return pf;
if ((g_nPixelShaderVer & SHADER_ACCURATE) && mapShaderResources.find(index + NUM_SHADERS*SHADER_ACCURATE) != mapShaderResources.end())
index += NUM_SHADERS * SHADER_ACCURATE;
assert(mapShaderResources.find(index) != mapShaderResources.end());
assert( mapShaderResources.find(index) != mapShaderResources.end() );
SHADERHEADER* header = mapShaderResources[index];
if( header == NULL )
ZZLog::Error_Log("%d %d", index, g_nPixelShaderVer);
assert( header != NULL );
if (header == NULL) ZZLog::Error_Log("%d %d", index, g_nPixelShaderVer);
assert(header != NULL);
//ZZLog::Debug_Log("Shader:\n%s.", (char*)(s_lpShaderResources + (header)->offset));
pf->prog = cgCreateProgram(g_cgcontext, CG_OBJECT, (char*)(s_lpShaderResources + (header)->offset), cgfProf, NULL, NULL);
if( pf->prog != NULL && cgIsProgram(pf->prog) && cgGetError() == CG_NO_ERROR ) {
if (pf->prog != NULL && cgIsProgram(pf->prog) && cgGetError() == CG_NO_ERROR)
{
SetupFragmentProgramParameters(pf, context, type);
cgGLLoadProgram(pf->prog);
if( cgGetError() != CG_NO_ERROR ) {
if (cgGetError() != CG_NO_ERROR)
{
// cgGLLoadProgram(pf->prog);
// if( cgGetError() != CG_NO_ERROR ) {
ZZLog::Error_Log("Failed to load shader %d,%d,%d,%d.", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
if( pbFailed != NULL ) *pbFailed = true;
return pf;
ZZLog::Error_Log("Failed to load shader %d,%d,%d,%d.", type, fog, texfilter, 4*clamp.wms + clamp.wmt);
if (pbFailed != NULL) *pbFailed = true;
return pf;
// }
}
return pf;
}
ZZLog::Error_Log("Failed to create shader %d,%d,%d,%d", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
if( pbFailed != NULL ) *pbFailed = true;
ZZLog::Error_Log("Failed to create shader %d,%d,%d,%d", type, fog, texfilter, 4*clamp.wms + clamp.wmt);
if (pbFailed != NULL) *pbFailed = true;
return NULL;
}
@ -396,12 +462,14 @@ FRAGMENTSHADER* ZeroGS::LoadShadeEffect(int type, int texfilter, int fog, int te
bool ZeroGS::LoadEffects()
{
// clear the textures
for(int i = 0; i < ARRAY_SIZE(ppsTexture); ++i) {
for (int i = 0; i < ARRAY_SIZE(ppsTexture); ++i)
{
SAFE_RELEASE_PROG(ppsTexture[i].prog);
}
#ifndef _DEBUG
memset(ppsTexture, 0, sizeof(ppsTexture));
#endif
return true;
@ -418,7 +486,8 @@ bool ZeroGS::LoadExtraEffects()
const char* pvsshaders[4] = { "RegularVS", "TextureVS", "RegularFogVS", "TextureFogVS" };
for(int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
args[0] = context0;
args[1] = NULL;
LOAD_VS(pvsshaders[i], pvs[2*i], cgvProf);
@ -426,11 +495,11 @@ bool ZeroGS::LoadExtraEffects()
LOAD_VS(pvsshaders[i], pvs[2*i+1], cgvProf);
//if( conf.mrtdepth ) {
args[0] = context0;
args[1] = write_depth;
LOAD_VS(pvsshaders[i], pvs[2*i+8], cgvProf);
args[0] = context1;
LOAD_VS(pvsshaders[i], pvs[2*i+8+1], cgvProf);
args[0] = context0;
args[1] = write_depth;
LOAD_VS(pvsshaders[i], pvs[2*i+8], cgvProf);
args[0] = context1;
LOAD_VS(pvsshaders[i], pvs[2*i+8+1], cgvProf);
// }
// else {
// pvs[2*i+8] = pvs[2*i+8+1] = NULL;
@ -438,6 +507,7 @@ bool ZeroGS::LoadExtraEffects()
}
args[0] = context0;
args[1] = NULL;
LOAD_VS("BitBltVS", pvsBitBlt.prog, cgvProf);
pvsBitBlt.sBitBltPos = cgGetNamedParameter(pvsBitBlt.prog, "g_fBitBltPos");
@ -447,20 +517,24 @@ bool ZeroGS::LoadExtraEffects()
LOAD_PS("RegularPS", ppsRegular[0], cgfProf);
LOAD_PS("RegularFogPS", ppsRegular[1], cgfProf);
if( conf.mrtdepth ) {
if (conf.mrtdepth)
{
args[0] = context0;
args[1] = write_depth;
LOAD_PS("RegularPS", ppsRegular[2], cgfProf);
if( !bLoadSuccess )
conf.mrtdepth = 0;
if (!bLoadSuccess) conf.mrtdepth = 0;
LOAD_PS("RegularFogPS", ppsRegular[3], cgfProf);
if( !bLoadSuccess )
conf.mrtdepth = 0;
if (!bLoadSuccess) conf.mrtdepth = 0;
}
LOAD_PS("BitBltPS", ppsBitBlt[0], cgfProf);
LOAD_PS("BitBltAAPS", ppsBitBlt[1], cgfProf);
if( !bLoadSuccess ) {
if (!bLoadSuccess)
{
ZZLog::Error_Log("Failed to load BitBltAAPS, using BitBltPS.");
LOAD_PS("BitBltPS", ppsBitBlt[1], cgfProf);
}
@ -471,19 +545,23 @@ bool ZeroGS::LoadExtraEffects()
g_bCRTCBilinear = TRUE;
LOAD_PS("CRTCPS", ppsCRTC[0], cgfProf);
if( !bLoadSuccess ) {
if (!bLoadSuccess)
{
// switch to simpler
g_bCRTCBilinear = FALSE;
LOAD_PS("CRTCPS_Nearest", ppsCRTC[0], cgfProf);
LOAD_PS("CRTCInterPS_Nearest", ppsCRTC[0], cgfProf);
}
else {
else
{
LOAD_PS("CRTCInterPS", ppsCRTC[1], cgfProf);
}
if (!bLoadSuccess) ZZLog::Error_Log("Failed to create CRTC shaders.");
LOAD_PS("CRTC24PS", ppsCRTC24[0], cgfProf); LOAD_PS("CRTC24InterPS", ppsCRTC24[1], cgfProf);
LOAD_PS("CRTC24PS", ppsCRTC24[0], cgfProf);
LOAD_PS("CRTC24InterPS", ppsCRTC24[1], cgfProf);
LOAD_PS("ZeroPS", ppsOne, cgfProf);
LOAD_PS("BaseTexturePS", ppsBaseTexture, cgfProf);
LOAD_PS("Convert16to32PS", ppsConvert16to32, cgfProf);
@ -501,57 +579,77 @@ FRAGMENTSHADER* ZeroGS::LoadShadeEffect(int type, int texfilter, int fog, int te
{
int texwrap;
assert( texfilter < NUM_FILTERS );
assert(texfilter < NUM_FILTERS);
//assert( g_nPixelShaderVer == SHADER_30 );
if( clamp.wms == clamp.wmt ) {
switch( clamp.wms ) {
case 0: texwrap = TEXWRAP_REPEAT; break;
case 1: texwrap = TEXWRAP_CLAMP; break;
case 2: texwrap = TEXWRAP_CLAMP; break;
if (clamp.wms == clamp.wmt)
{
switch (clamp.wms)
{
case 0:
texwrap = TEXWRAP_REPEAT;
break;
case 1:
texwrap = TEXWRAP_CLAMP;
break;
case 2:
texwrap = TEXWRAP_CLAMP;
break;
default:
texwrap = TEXWRAP_REGION_REPEAT; break;
texwrap = TEXWRAP_REGION_REPEAT;
break;
}
}
else if( clamp.wms==3||clamp.wmt==3)
else if (clamp.wms == 3 || clamp.wmt == 3)
texwrap = TEXWRAP_REGION_REPEAT;
else
texwrap = TEXWRAP_REPEAT_CLAMP;
int index = GET_SHADER_INDEX(type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, context, 0);
if( pbFailed != NULL ) *pbFailed = false;
if (pbFailed != NULL) *pbFailed = false;
FRAGMENTSHADER* pf = ppsTexture+index;
FRAGMENTSHADER* pf = ppsTexture + index;
if( pf->prog != NULL )
return pf;
if (pf->prog != NULL) return pf;
pf->prog = LoadShaderFromType(EFFECT_DIR, EFFECT_NAME, type, texfilter, texwrap, fog, s_bWriteDepth, testaem, exactcolor, g_nPixelShaderVer, context);
if( pf->prog != NULL ) {
if (pf->prog != NULL)
{
#ifdef _DEBUG
char str[255];
sprintf(str, "Texture%s%d_%sPS", fog?"Fog":"", texfilter, g_pTexTypes[type]);
sprintf(str, "Texture%s%d_%sPS", fog ? "Fog" : "", texfilter, g_pTexTypes[type]);
pf->filename = str;
#endif
SetupFragmentProgramParameters(pf, context, type);
cgGLLoadProgram(pf->prog);
if( cgGetError() != CG_NO_ERROR ) {
if (cgGetError() != CG_NO_ERROR)
{
// try again
// cgGLLoadProgram(pf->prog);
// if( cgGetError() != CG_NO_ERROR ) {
ZZLog::Error_Log("Failed to load shader %d,%d,%d,%d.", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
if( pbFailed != NULL ) *pbFailed = true;
//assert(0);
// NULL makes things crash
return pf;
ZZLog::Error_Log("Failed to load shader %d,%d,%d,%d.", type, fog, texfilter, 4*clamp.wms + clamp.wmt);
if (pbFailed != NULL) *pbFailed = true;
//assert(0);
// NULL makes things crash
return pf;
// }
}
return pf;
}
ZZLog::Error_Log("Failed to create shader %d,%d,%d,%d.", type, fog, texfilter, 4*clamp.wms+clamp.wmt);
if( pbFailed != NULL ) *pbFailed = true;
ZZLog::Error_Log("Failed to create shader %d,%d,%d,%d.", type, fog, texfilter, 4*clamp.wms + clamp.wmt);
if (pbFailed != NULL) *pbFailed = true;
return NULL;
}

View File

@ -32,7 +32,8 @@
#include "Mem.h"
extern "C" {
extern "C"
{
#ifdef _WIN32
# define XMD_H
# undef FAR
@ -59,64 +60,65 @@ int s_aviinit = 0;
//------------------ Code
// Set variables need to made a snapshoot when it's possible
void
ZeroGS::SaveSnapshot(const char* filename)
void ZeroGS::SaveSnapshot(const char* filename)
{
g_bMakeSnapshot = 1;
strSnapshot = filename;
}
// Save curent renderer in jpeg or TGA format
bool
ZeroGS::SaveRenderTarget(const char* filename, int width, int height, int jpeg)
bool ZeroGS::SaveRenderTarget(const char* filename, int width, int height, int jpeg)
{
bool bflip = height < 0;
height = abs(height);
vector<u32> data(width*height);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
if (glGetError() != GL_NO_ERROR)
return false;
if (bflip) {
if (glGetError() != GL_NO_ERROR) return false;
if (bflip)
{
// swap scanlines
vector<u32> scanline(width);
for (int i = 0; i < height/2; ++i) {
for (int i = 0; i < height / 2; ++i)
{
memcpy(&scanline[0], &data[i * width], width * 4);
memcpy(&data[i * width], &data[(height - i - 1) * width], width * 4);
memcpy(&data[(height - i - 1) * width], &scanline[0], width * 4);
}
}
if (jpeg)
return SaveJPEG(filename, width, height, &data[0], 70);
if (jpeg) return SaveJPEG(filename, width, height, &data[0], 70);
return SaveTGA(filename, width, height, &data[0]);
}
// Save selected texture as TGA
bool
ZeroGS::SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height)
bool ZeroGS::SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height)
{
vector<u32> data(width*height);
glBindTexture(textarget, tex);
glGetTexImage(textarget, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
if (glGetError() != GL_NO_ERROR)
return false;
if (glGetError() != GL_NO_ERROR) return false;
return SaveTGA(filename, width, height, &data[0]);
}
// save image as JPEG
bool
ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const void* pdata, int quality)
bool ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const void* pdata, int quality)
{
u8* image_buffer = new u8[image_width * image_height * 3];
u8* psrc = (u8*)pdata;
// input data is rgba format, so convert to rgb
u8* p = image_buffer;
for(int i = 0; i < image_height; ++i) {
for(int j = 0; j < image_width; ++j) {
for (int i = 0; i < image_height; ++i)
{
for (int j = 0; j < image_width; ++j)
{
p[0] = psrc[0];
p[1] = psrc[1];
p[2] = psrc[2];
@ -131,7 +133,9 @@ ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const
* compression/decompression processes, in existence at once. We refer
* to any one struct (and its associated working data) as a "JPEG object".
*/
struct jpeg_compress_struct cinfo;
/* This struct represents a JPEG error handler. It is declared separately
* because applications often want to supply a specialized error handler
* (see the second half of this file for an example). But here we just
@ -140,10 +144,14 @@ ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
struct jpeg_error_mgr jerr;
/* More stuff */
FILE * outfile; /* target file */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
/* Step 1: allocate and initialize JPEG compression object */
@ -154,6 +162,7 @@ ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const
* address which we place into the link field in cinfo.
*/
cinfo.err = jpeg_std_error(&jerr);
/* Now we can initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
@ -165,10 +174,12 @@ ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
* requires it in order to write binary files.
*/
if ((outfile = fopen(filename, "wb")) == NULL) {
if ((outfile = fopen(filename, "wb")) == NULL)
{
fprintf(stderr, "can't open %s\n", filename);
exit(1);
}
jpeg_stdio_dest(&cinfo, outfile);
/* Step 3: set parameters for compression */
@ -207,8 +218,9 @@ ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const
*/
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
while (cinfo.next_scanline < cinfo.image_height) {
/* jpeg_write_scanlines expects an array of pointers to scanlines.
while (cinfo.next_scanline < cinfo.image_height)
{
/* jpeg_write_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could pass
* more than one scanline at a time if that's more convenient.
*/
@ -219,6 +231,7 @@ ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
/* After finish_compress, we can close the output file. */
fclose(outfile);
@ -228,6 +241,7 @@ ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const
jpeg_destroy_compress(&cinfo);
delete image_buffer;
/* And we're done! */
return true;
}
@ -237,6 +251,7 @@ ZeroGS::SaveJPEG(const char* filename, int image_width, int image_height, const
#endif
// This is the defenition of TGA header. We need it to function bellow
struct TGA_HEADER
{
u8 identsize; // size of ID field that follows 18 u8 header (0 usually)
@ -254,36 +269,41 @@ struct TGA_HEADER
u8 bits; // image bits per pixel 8,16,24,32
u8 descriptor; // image descriptor bits (vh flip bits)
// pixel data follows header
// pixel data follows header
#if defined(_MSC_VER)
};
# pragma pack(pop)
# else
} __attribute__((packed));
}
__attribute__((packed));
#endif
// Save image as TGA
bool
ZeroGS::SaveTGA(const char* filename, int width, int height, void* pdata)
bool ZeroGS::SaveTGA(const char* filename, int width, int height, void* pdata)
{
int err = 0;
TGA_HEADER hdr;
FILE* f = fopen(filename, "wb");
if (f == NULL)
return false;
assert( sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18 );
if (f == NULL) return false;
assert(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18);
memset(&hdr, 0, sizeof(hdr));
hdr.imagetype = 2;
hdr.bits = 32;
hdr.width = width;
hdr.height = height;
hdr.descriptor |= 8|(1<<5); // 8bit alpha, flip vertical
hdr.descriptor |= 8 | (1 << 5); // 8bit alpha, flip vertical
err = fwrite(&hdr, sizeof(hdr), 1, f);
err = fwrite(pdata, width * height * 4, 1, f);
fclose(f);
return true;
}
@ -291,8 +311,8 @@ ZeroGS::SaveTGA(const char* filename, int width, int height, void* pdata)
// AVI start -- set needed glabal variables
void ZeroGS::StartCapture()
{
if( !s_aviinit ) {
if (!s_aviinit)
{
#ifdef _WIN32
START_AVI("zerogs.avi");
#else // linux
@ -300,7 +320,8 @@ void ZeroGS::StartCapture()
#endif
s_aviinit = 1;
}
else {
else
{
ZZLog::Error_Log("Continuing from previous capture.");
}
@ -317,10 +338,11 @@ void ZeroGS::StopCapture()
// Does not work on linux
void ZeroGS::CaptureFrame()
{
assert( s_avicapturing && s_aviinit );
assert(s_avicapturing && s_aviinit);
vector<u32> data(nBackbufferWidth*nBackbufferHeight);
glReadPixels(0, 0, nBackbufferWidth, nBackbufferHeight, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
if (glGetError() != GL_NO_ERROR) return;
#ifdef _WIN32
@ -328,12 +350,14 @@ void ZeroGS::CaptureFrame()
bool bSuccess = ADD_FRAME_FROM_DIB_TO_AVI("AAAA", fps, nBackbufferWidth, nBackbufferHeight, 32, &data[0]);
if( !bSuccess ) {
if (!bSuccess)
{
s_avicapturing = 0;
STOP_AVI();
ZeroGS::AddMessage("Failed to create avi");
return;
}
#else // linux
//TODO
#endif // _WIN32
@ -351,10 +375,10 @@ ZeroGS::SaveTex(tex0Info* ptex, int usevid)
CMemoryTarget* pmemtarg = NULL;
if (usevid) {
if (usevid)
{
pmemtarg = g_MemTargs.GetMemoryTarget(*ptex, 0);
assert( pmemtarg != NULL );
assert(pmemtarg != NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, pmemtarg->ptex->tex);
srcdata.resize(pmemtarg->realheight * GPU_TEXWIDTH * pmemtarg->widthmult * 4 * 8); // max of 8 cannels
@ -371,11 +395,15 @@ ZeroGS::SaveTex(tex0Info* ptex, int usevid)
psrc = &srcdata[0] - offset;
}
for (int i = 0; i < ptex->th; ++i) {
for (int j = 0; j < ptex->tw; ++j) {
for (int i = 0; i < ptex->th; ++i)
{
for (int j = 0; j < ptex->tw; ++j)
{
u32 u = 0;
u32 addr;
switch (ptex->psm) {
u32 addr;
switch (ptex->psm)
{
case PSMCT32:
addr = getPixelAddress32(j, i, ptex->tbp0, ptex->tbw);
if (addr * 4 < 0x00400000)
@ -383,6 +411,7 @@ ZeroGS::SaveTex(tex0Info* ptex, int usevid)
else
u = 0;
break;
case PSMCT24:
addr = getPixelAddress24(j, i, ptex->tbp0, ptex->tbw);
if (addr * 4 < 0x00400000)
@ -390,135 +419,174 @@ ZeroGS::SaveTex(tex0Info* ptex, int usevid)
else
u = 0;
break;
case PSMCT16:
addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw);
if (addr * 2 < 0x00400000) {
if (addr * 2 < 0x00400000)
{
u = readPixel16(psrc, j, i, ptex->tbp0, ptex->tbw);
u = RGBA16to32(u);
}
else
{
u = 0;
}
break;
case PSMCT16S:
addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw);
if (addr * 2 < 0x00400000) {
if (addr * 2 < 0x00400000)
{
u = readPixel16S(psrc, j, i, ptex->tbp0, ptex->tbw);
u = RGBA16to32(u);
}
else u = 0;
else
{
u = 0;
}
break;
case PSMT8:
addr = getPixelAddress8(j, i, ptex->tbp0, ptex->tbw);
if (addr < 0x00400000) {
if (usevid) {
if (addr < 0x00400000)
{
if (usevid)
{
if (PSMT_IS32BIT(ptex->cpsm))
u = *(u32*)(psrc+4*addr);
u = *(u32*)(psrc + 4 * addr);
else
u = RGBA16to32(*(u16*)(psrc+2*addr));
u = RGBA16to32(*(u16*)(psrc + 2 * addr));
}
else
{
u = readPixel8(psrc, j, i, ptex->tbp0, ptex->tbw);
}
}
else
{
u = 0;
}
break;
case PSMT4:
addr = getPixelAddress4(j, i, ptex->tbp0, ptex->tbw);
if( addr < 2*0x00400000 ) {
if( usevid ) {
if (addr < 2*0x00400000)
{
if (usevid)
{
if (PSMT_IS32BIT(ptex->cpsm))
u = *(u32*)(psrc+4*addr);
u = *(u32*)(psrc + 4 * addr);
else
u = RGBA16to32(*(u16*)(psrc+2*addr));
u = RGBA16to32(*(u16*)(psrc + 2 * addr));
}
else
{
u = readPixel4(psrc, j, i, ptex->tbp0, ptex->tbw);
}
}
else u = 0;
else
{
u = 0;
}
break;
case PSMT8H:
addr = getPixelAddress8H(j, i, ptex->tbp0, ptex->tbw);
if( 4*addr < 0x00400000 ) {
if( usevid ) {
if (4*addr < 0x00400000)
{
if (usevid)
{
if (PSMT_IS32BIT(ptex->cpsm))
u = *(u32*)(psrc+4*addr);
u = *(u32*)(psrc + 4 * addr);
else
u = RGBA16to32(*(u16*)(psrc+2*addr));
u = RGBA16to32(*(u16*)(psrc + 2 * addr));
}
else
{
u = readPixel8H(psrc, j, i, ptex->tbp0, ptex->tbw);
}
}
else
{
u = 0;
}
else u = 0;
break;
case PSMT4HL:
addr = getPixelAddress4HL(j, i, ptex->tbp0, ptex->tbw);
if( 4*addr < 0x00400000 ) {
if( usevid ) {
if (4*addr < 0x00400000)
{
if (usevid)
{
if (PSMT_IS32BIT(ptex->cpsm))
u = *(u32*)(psrc+4*addr);
u = *(u32*)(psrc + 4 * addr);
else
u = RGBA16to32(*(u16*)(psrc+2*addr));
u = RGBA16to32(*(u16*)(psrc + 2 * addr));
}
else
{
u = readPixel4HL(psrc, j, i, ptex->tbp0, ptex->tbw);
}
}
else
{
u = 0;
}
else u = 0;
break;
case PSMT4HH:
addr = getPixelAddress4HH(j, i, ptex->tbp0, ptex->tbw);
if( 4*addr < 0x00400000 ) {
if( usevid ) {
if (4*addr < 0x00400000)
{
if (usevid)
{
if (PSMT_IS32BIT(ptex->cpsm))
u = *(u32*)(psrc+4*addr);
u = *(u32*)(psrc + 4 * addr);
else
u = RGBA16to32(*(u16*)(psrc+2*addr));
u = RGBA16to32(*(u16*)(psrc + 2 * addr));
}
else
{
u = readPixel4HH(psrc, j, i, ptex->tbp0, ptex->tbw);
}
}
else
{
u = 0;
}
else u = 0;
break;
case PSMT32Z:
addr = getPixelAddress32Z(j, i, ptex->tbp0, ptex->tbw);
if( 4*addr < 0x00400000 )
if (4*addr < 0x00400000)
u = readPixel32Z(psrc, j, i, ptex->tbp0, ptex->tbw);
else u = 0;
else
u = 0;
break;
case PSMT24Z:
addr = getPixelAddress24Z(j, i, ptex->tbp0, ptex->tbw);
if( 4*addr < 0x00400000 )
if (4*addr < 0x00400000)
u = readPixel24Z(psrc, j, i, ptex->tbp0, ptex->tbw);
else u = 0;
else
u = 0;
break;
case PSMT16Z:
addr = getPixelAddress16Z(j, i, ptex->tbp0, ptex->tbw);
if( 2*addr < 0x00400000 )
if (2*addr < 0x00400000)
u = readPixel16Z(psrc, j, i, ptex->tbp0, ptex->tbw);
else u = 0;
else
u = 0;
break;
case PSMT16SZ:
addr = getPixelAddress16SZ(j, i, ptex->tbp0, ptex->tbw);
if( 2*addr < 0x00400000 )
if (2*addr < 0x00400000)
u = readPixel16SZ(psrc, j, i, ptex->tbp0, ptex->tbw);
else u = 0;
else
u = 0;
break;
default:
@ -530,29 +598,30 @@ ZeroGS::SaveTex(tex0Info* ptex, int usevid)
}
char Name[TGA_FILE_NAME_MAX_LENGTH];
snprintf( Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber );
snprintf(Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber);
SaveTGA(Name, ptex->tw, ptex->th, &data[0]);
}
// Do the save texture and return file name of it
// Do not forget to call free(), other wise there would be memory leak!
char*
ZeroGS::NamedSaveTex(tex0Info* ptex, int usevid){
char* ZeroGS::NamedSaveTex(tex0Info* ptex, int usevid)
{
SaveTex(ptex, usevid);
char* Name = (char*)malloc(TGA_FILE_NAME_MAX_LENGTH);
snprintf( Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber );
snprintf(Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber);
TexNumber++;
if (TexNumber > MAX_NUMBER_SAVED_TGA)
TexNumber = 0;
if (TexNumber > MAX_NUMBER_SAVED_TGA) TexNumber = 0;
return Name;
}
// Special function, wich is safe to call from any other file, without aviutils problems.
void
ZeroGS::Stop_Avi(){
// Special function, which is safe to call from any other file, without aviutils problems.
void ZeroGS::Stop_Avi()
{
#ifdef _WIN32
STOP_AVI();
#else

View File

@ -52,104 +52,123 @@ ZeroGS::VB::~VB()
void ZeroGS::VB::Destroy()
{
_aligned_free(pBufferData); pBufferData = NULL; nNumVertices = 0;
_aligned_free(pBufferData);
pBufferData = NULL;
nNumVertices = 0;
prndr = NULL;
pdepth = NULL;
}
int ConstraintReson;
int ConstraintReason;
// Return number of 64-pixels block, that guaranted could be hold in memory
// from gsfb.fbp and tbp (textrure pase), zbuf.zbp (Z-buffer), frame.fbp
// (previous frame).
inline int
ZeroGS::VB::FindMinimalMemoryConstrain(int tbp, int maxpos) {
inline int ZeroGS::VB::FindMinimalMemoryConstrain(int tbp, int maxpos)
{
int MinConstraint = maxpos;
// make sure texture is far away from tbp
{
int Constraint = tbp - gsfb.fbp;
if ((0 < Constraint) && (Constraint < MinConstraint)) {
if ((0 < Constraint) && (Constraint < MinConstraint))
{
MinConstraint = Constraint;
ConstraintReson = 1;
ConstraintReason = 1;
}
}
// offroad uses 0x80 fbp which messes up targets
// special case when double buffering (hamsterball)
// Suikoden 3 require e00 have this issue too. P3 - 0x1000.
if (prndr != NULL) {
if (prndr != NULL)
{
int Constraint = frame.fbp - gsfb.fbp;
if ((0x0 < Constraint) && (Constraint < MinConstraint)) {
if ((0x0 < Constraint) && (Constraint < MinConstraint))
{
MinConstraint = Constraint;
ConstraintReson = 2;
ConstraintReason = 2;
}
}
// old caching method
// zmsk necessary for KH movie
if (!zbuf.zmsk){
if (!zbuf.zmsk)
{
int Constraint = zbuf.zbp - gsfb.fbp;
if ((0 < Constraint) && (Constraint < MinConstraint)) {
if ((0 < Constraint) && (Constraint < MinConstraint))
{
MinConstraint = Constraint;
ConstraintReson = 3;
ConstraintReason = 3;
}
}
// In 16Bit mode in one Word freame stored 2 pixels
if (PSMT_ISHALF(gsfb.psm))
MinConstraint *= 2;
// In 16Bit mode in one Word frame stored 2 pixels
if (PSMT_ISHALF(gsfb.psm)) MinConstraint *= 2;
return MinConstraint ;
}
// Return number of 64 pizel words that could be placed in Z-Buffer
// If no Z-buffer present return old constraint
inline int
ZeroGS::VB::FindZbufferMemoryConstrain(int tbp, int maxpos) {
inline int ZeroGS::VB::FindZbufferMemoryConstrain(int tbp, int maxpos)
{
int MinConstraint = maxpos;
// Check tbp / zbuffer constraint
if (!zbuf.zmsk) {
int Constraint = (tbp - zbuf.zbp) * (PSMT_ISHALF(zbuf.psm) ? 2 : 1 );
if ((0 < Constraint) && (Constraint < MinConstraint)) {
if (!zbuf.zmsk)
{
int Constraint = (tbp - zbuf.zbp) * (PSMT_ISHALF(zbuf.psm) ? 2 : 1);
if ((0 < Constraint) && (Constraint < MinConstraint))
{
MinConstraint = Constraint;
ConstraintReson = 4;
ConstraintReason = 4;
}
}
return MinConstraint;
}
// Return heights limiter form scissor. .
inline int
GetScissorY(int y) {
// Return heights limiter from scissor...
inline int GetScissorY(int y)
{
int fbh = (y >> MINMAX_SHIFT) + 1;
if ( fbh > 2 && ( fbh & 1 ) ) fbh -= 1;
if (fbh > 2 && (fbh & 1)) fbh -= 1;
return fbh;
}
//There is several reason to limit a height of frame: maximum buffer size, calculated size
//There is several reasons to limit a height of frame: maximum buffer size, calculated size
//from fbw and fbh and scissoring.
inline int
ZeroGS::VB::FindMinimalHeightConstrain(int maxpos) {
inline int ZeroGS::VB::FindMinimalHeightConstrain(int maxpos)
{
int MinConstraint = maxpos;
if (maxmin < MinConstraint) {
if (maxmin < MinConstraint)
{
MinConstraint = maxmin;
ConstraintReson = 5;
ConstraintReason = 5;
}
if (gsfb.fbh < MinConstraint) {
if (gsfb.fbh < MinConstraint)
{
MinConstraint = gsfb.fbh;
ConstraintReson = 6;
ConstraintReason = 6;
}
int ScissorConstraint = GetScissorY(scissor.y1) ;
if (ScissorConstraint < MinConstraint) {
if (ScissorConstraint < MinConstraint)
{
MinConstraint = ScissorConstraint;
ConstraintReson = 7;
ConstraintReason = 7;
}
return MinConstraint;
@ -157,32 +176,36 @@ ZeroGS::VB::FindMinimalHeightConstrain(int maxpos) {
// 32 bit frames have additional constraints to frame
// maxpos was maximum length of frame at normal constraints
inline void
ZeroGS::VB::CheckFrame32bitRes(int maxpos)
inline void ZeroGS::VB::CheckFrame32bitRes(int maxpos)
{
int fbh = frame.fbh;
if ( frame.fbh >= 512 ) {
if (frame.fbh >= 512)
{
// neopets hack
maxmin = min(maxmin, frame.fbh);
frame.fbh = maxmin;
ConstraintReson = 8;
ConstraintReason = 8;
}
// ffxii hack to stop resolving
if( frame.fbp >= 0x3000 && fbh >= 0x1a0 ) {
if (frame.fbp >= 0x3000 && fbh >= 0x1a0)
{
int endfbp = frame.fbp + frame.fbw * fbh / (PSMT_ISHALF(gsfb.psm) ? 128 : 64);
// see if there is a previous render target in the way, reduce
for (CRenderTargetMngr::MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew) {
if ( itnew->second->fbp > frame.fbp && endfbp > itnew->second->fbp ) {
for (CRenderTargetMngr::MAPTARGETS::iterator itnew = s_RTs.mapTargets.begin(); itnew != s_RTs.mapTargets.end(); ++itnew)
{
if (itnew->second->fbp > frame.fbp && endfbp > itnew->second->fbp)
{
endfbp = itnew->second->fbp;
}
}
frame.fbh = (endfbp - frame.fbp) * ( PSMT_ISHALF(gsfb.psm) ? 128: 64 ) / frame.fbw;
if (frame.fbh < fbh)
ConstraintReson = 9;
frame.fbh = (endfbp - frame.fbp) * (PSMT_ISHALF(gsfb.psm) ? 128 : 64) / frame.fbw;
if (frame.fbh < fbh) ConstraintReason = 9;
}
}
@ -192,30 +215,33 @@ ZeroGS::VB::CheckFrame32bitRes(int maxpos)
// 4Mb memory in 64 bit (4 bytes) words.
// |------------------------|---------------------|----------|----------|---------------------|
// 0 gsfb.fbp zbuff.zpb tbp frame.fbp 2^20/64
inline int
ZeroGS::VB::CheckFrameAddConstraints(int tbp)
inline int ZeroGS::VB::CheckFrameAddConstraints(int tbp)
{
if ( gsfb.fbw <= 0 ) {
if (gsfb.fbw <= 0)
{
ERROR_LOG_SPAM("render target null, no constraints. Ignoring\n");
return -1;
}
// Memory region after fbp
int maxmemorypos = 0x4000 - gsfb.fbp;
ConstraintReson = 0;
ConstraintReason = 0;
maxmemorypos = FindMinimalMemoryConstrain(tbp, maxmemorypos);
maxmemorypos = FindZbufferMemoryConstrain(tbp, maxmemorypos);
int maxpos = 64 * maxmemorypos ;
maxpos /= gsfb.fbw;
//? atelier iris crashes without it
if( maxpos > 256 )
maxpos &= ~0x1f;
if (maxpos > 256) maxpos &= ~0x1f;
#ifdef DEVBUILD
int noscissorpos = maxpos;
int ConstrainR1 = ConstraintReson;
int ConstrainR1 = ConstraintReason;
#endif
maxpos = FindMinimalHeightConstrain(maxpos);
@ -223,12 +249,13 @@ ZeroGS::VB::CheckFrameAddConstraints(int tbp)
frame = gsfb;
frame.fbh = maxpos;
if( !PSMT_ISHALF(frame.psm) || !(g_GameSettings&GAME_FULL16BITRES) )
CheckFrame32bitRes( maxpos ) ;
if (!PSMT_ISHALF(frame.psm) || !(g_GameSettings&GAME_FULL16BITRES))
CheckFrame32bitRes(maxpos);
#ifdef DEVBUILD
if (frame.fbh == 0xe2)
ZZLog::Error_Log ("Const: %x %x %d| %x %d %x %x", frame.fbh, frame.fbw, ConstraintReson, noscissorpos, ConstrainR1, tbp, frame.fbp);
ZZLog::Error_Log("Const: %x %x %d| %x %d %x %x", frame.fbh, frame.fbw, ConstraintReason, noscissorpos, ConstrainR1, tbp, frame.fbp);
#endif
// Fixme: Reserved psm for framebuffers
@ -237,11 +264,9 @@ ZeroGS::VB::CheckFrameAddConstraints(int tbp)
return 0 ;
}
// Check if after resising new depth target is need to be used.
// it return 2 if new deapth target used. bool Chose is used to proprely check
// renderer target status
inline int
ZeroGS::VB::CheckFrameResolveDepth(int tbp)
// Check if after resizing new depth target is needed to be used.
// it returns 2 if a new depth target is used.
inline int ZeroGS::VB::CheckFrameResolveDepth(int tbp)
{
int result = 0 ;
CDepthTarget* pprevdepth = pdepth;
@ -250,13 +275,13 @@ ZeroGS::VB::CheckFrameResolveDepth(int tbp)
// just z changed
frameInfo f = CreateFrame(zbuf.zbp, prndr->fbw, prndr->fbh, zbuf.psm, (zbuf.psm == 0x31) ? 0xff000000 : 0);
CDepthTarget* pnewdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer|CRenderTargetMngr::TO_StrictHeight|
(zbuf.zmsk?CRenderTargetMngr::TO_Virtual:0), get_maxheight(zbuf.zbp, gsfb.fbw, 0));
CDepthTarget* pnewdepth = (CDepthTarget*)s_DepthRTs.GetTarg(f, CRenderTargetMngr::TO_DepthBuffer | CRenderTargetMngr::TO_StrictHeight |
(zbuf.zmsk ? CRenderTargetMngr::TO_Virtual : 0), get_maxheight(zbuf.zbp, gsfb.fbw, 0));
assert( pnewdepth != NULL && prndr != NULL );
assert( pnewdepth->fbh == prndr->fbh );
assert(pnewdepth != NULL && prndr != NULL);
assert(pnewdepth->fbh == prndr->fbh);
if( (pprevdepth != pnewdepth) || (pprevdepth != NULL && (pprevdepth->status & CRenderTarget::TS_NeedUpdate)) )
if ((pprevdepth != pnewdepth) || (pprevdepth != NULL && (pprevdepth->status & CRenderTarget::TS_NeedUpdate)))
result = 2;
pdepth = pnewdepth;
@ -264,11 +289,11 @@ ZeroGS::VB::CheckFrameResolveDepth(int tbp)
return result ;
}
// Check if after resings new render target is need to be used. Also perform deptaget check
// Return 1 if only render target is changed and 3 -- if both.
inline int
ZeroGS::VB::CheckFrameResolveRender(int tbp) {
int result = 0 ;
// Check if after resizing, a new render target is needed to be used. Also perform deptarget check.
// Returns 1 if only 1 render target is changed and 3 -- if both.
inline int ZeroGS::VB::CheckFrameResolveRender(int tbp)
{
int result = 0;
CRenderTarget* pprevrndr = prndr;
prndr = NULL;
@ -277,98 +302,115 @@ ZeroGS::VB::CheckFrameResolveRender(int tbp) {
// Set renderes to NULL to prevent Flushing.
CRenderTarget* pnewtarg = s_RTs.GetTarg(frame, 0, maxmin);
assert( pnewtarg != NULL );
assert(pnewtarg != NULL);
// pnewtarg->fbh >= 0x1c0 needed for ffx
if( (pnewtarg->fbh >= 0x1c0) && pnewtarg->fbh > frame.fbh && zbuf.zbp < tbp && !zbuf.zmsk ) {
if ((pnewtarg->fbh >= 0x1c0) && pnewtarg->fbh > frame.fbh && zbuf.zbp < tbp && !zbuf.zmsk)
{
// check if zbuf is in the way of the texture (suikoden5)
int maxallowedfbh = (tbp-zbuf.zbp)*(PSMT_ISHALF(zbuf.psm)?128:64) / gsfb.fbw;
int maxallowedfbh = (tbp - zbuf.zbp) * (PSMT_ISHALF(zbuf.psm) ? 128 : 64) / gsfb.fbw;
if (PSMT_ISHALF(gsfb.psm)) maxallowedfbh *= 2;
if (pnewtarg->fbh > maxallowedfbh + 32) { // +32 needed for ffx2
if (pnewtarg->fbh > maxallowedfbh + 32) // +32 needed for ffx2
{
// destroy and recreate
s_RTs.DestroyAllTargs(0, 0x100, pnewtarg->fbw);
pnewtarg = s_RTs.GetTarg(frame, 0, maxmin);
assert( pnewtarg != NULL );
assert(pnewtarg != NULL);
}
}
ZZLog::Prim_Log("frame_%d: fbp=0x%x fbw=%d fbh=%d(%d) psm=0x%x fbm=0x%x\n", ictx, gsfb.fbp, gsfb.fbw, gsfb.fbh, pnewtarg->fbh, gsfb.psm, gsfb.fbm);
if( (pprevrndr != pnewtarg) || (pprevrndr != NULL && (pprevrndr->status & CRenderTarget::TS_NeedUpdate)) )
if ((pprevrndr != pnewtarg) || (pprevrndr != NULL && (pprevrndr->status & CRenderTarget::TS_NeedUpdate)))
result = 1;
prndr = pnewtarg;
pdepth = pprevdepth ;
result |= CheckFrameResolveDepth(tbp) ;
return result ;
}
// After frame resetting it is possible that 16 to 32 or 32 to 16 (color bits) conversion should be made.
inline void
ZeroGS::VB::CheckFrame16vs32Convesion()
// After frame resetting, it is possible that 16 to 32 or 32 to 16 (color bits) conversion should be made.
inline void ZeroGS::VB::CheckFrame16vs32Convesion()
{
if( prndr->status & CRenderTarget::TS_NeedConvert32) {
if( pdepth->pdepth != 0 )
pdepth->SetDepthStencilSurface();
if (prndr->status & CRenderTarget::TS_NeedConvert32)
{
if (pdepth->pdepth != 0) pdepth->SetDepthStencilSurface();
prndr->fbh *= 2;
prndr->ConvertTo32();
prndr->status &= ~CRenderTarget::TS_NeedConvert32;
}
else if( prndr->status & CRenderTarget::TS_NeedConvert16 ) {
if( pdepth->pdepth != 0 )
pdepth->SetDepthStencilSurface();
else if (prndr->status & CRenderTarget::TS_NeedConvert16)
{
if (pdepth->pdepth != 0) pdepth->SetDepthStencilSurface();
prndr->fbh /= 2;
prndr->ConvertTo16();
prndr->status &= ~CRenderTarget::TS_NeedConvert16;
}
}
// a lot of times, target is too big and overwrites the texture using,
// if tbp != 0, use it to bound
// A lot of times, the target is too big and overwrites the texture.
// If tbp != 0, use it to bound.
void ZeroGS::VB::CheckFrame(int tbp)
{
static int bChanged;
if( bNeedZCheck ) {
if (bNeedZCheck)
{
ZZLog::Prim_Log("zbuf_%d: zbp=0x%x psm=0x%x, zmsk=%d\n", ictx, zbuf.zbp, zbuf.psm, zbuf.zmsk);
//zbuf = *zb;
}
if( m_Blocks[gsfb.psm].bpp == 0 ) {
if (m_Blocks[gsfb.psm].bpp == 0)
{
ZZLog::Error_Log("CheckFrame invalid bpp %d.", gsfb.psm);
return;
}
bChanged = 0;
if( bNeedFrameCheck ) {
if (bNeedFrameCheck)
{
// important to set before calling GetTarg
bNeedFrameCheck = 0;
bNeedZCheck = 0;
if ( CheckFrameAddConstraints(tbp) == -1 ) return ;
if ( ( prndr != NULL ) && ( prndr->psm != gsfb.psm ) ) {
if (CheckFrameAddConstraints(tbp) == -1) return ;
if ((prndr != NULL) && (prndr->psm != gsfb.psm))
{
// behavior for dest alpha varies
ResetAlphaVariables();
}
}
bChanged = CheckFrameResolveRender(tbp);
bChanged = CheckFrameResolveRender(tbp) ;
CheckFrame16vs32Convesion();
}
else if (bNeedZCheck) {
else if (bNeedZCheck)
{
bNeedZCheck = 0;
if (prndr != NULL && gsfb.fbw > 0 )
if (prndr != NULL && gsfb.fbw > 0)
CheckFrameResolveDepth(tbp);
}
if( prndr != NULL ) SetContextTarget(ictx);
if (prndr != NULL) SetContextTarget(ictx);
}
// This is the case, most easy to perform, when nothinh was changed
inline void ZeroGS::VB::FlushTexUnchangedClutDontUpdate() {
if (ZZOglGet_cld_TexBits(uNextTex0Data[1])) {
inline void ZeroGS::VB::FlushTexUnchangedClutDontUpdate()
{
if (ZZOglGet_cld_TexBits(uNextTex0Data[1]))
{
ZeroGS::texClutWrite(ictx);
// invalidate to make sure target didn't change!
bVarsTexSync = FALSE;
@ -377,7 +419,8 @@ inline void ZeroGS::VB::FlushTexUnchangedClutDontUpdate() {
// The second of easy branch. We does not change storage model, so we don't need to
// update anything except texture itself
inline void ZeroGS::VB::FlushTexClutDontUpdate() {
inline void ZeroGS::VB::FlushTexClutDontUpdate()
{
if (!ZZOglClutStorageUnchanged(uCurTex0Data, uNextTex0Data))
ZeroGS::Flush(ictx);
@ -388,12 +431,14 @@ inline void ZeroGS::VB::FlushTexClutDontUpdate() {
tex0.cpsm = ZZOglGet_cpsm_TexBits(uNextTex0Data[1]);
ZeroGS::texClutWrite(ictx);
bVarsTexSync = FALSE;
}
// Set texture variables after big change
inline void ZeroGS::VB::FlushTexSetNewVars(u32 psm) {
inline void ZeroGS::VB::FlushTexSetNewVars(u32 psm)
{
tex0.tbp0 = ZZOglGet_tbp0_TexBits(uNextTex0Data[0]);
tex0.tbw = ZZOglGet_tbw_TexBitsMult(uNextTex0Data[0]);
tex0.psm = psm;
@ -403,34 +448,37 @@ inline void ZeroGS::VB::FlushTexSetNewVars(u32 psm) {
tex0.tcc = ZZOglGet_tcc_TexBits(uNextTex0Data[1]);
tex0.tfx = ZZOglGet_tfx_TexBits(uNextTex0Data[1]);
ZeroGS::fiTexWidth[ictx] = (1/16.0f)/ tex0.tw;
ZeroGS::fiTexHeight[ictx] = (1/16.0f) / tex0.th;
ZeroGS::fiTexWidth[ictx] = (1 / 16.0f) / tex0.tw;
ZeroGS::fiTexHeight[ictx] = (1 / 16.0f) / tex0.th;
}
// Flush == draw on screen
// This function made VB state consistant before real Flush.
void ZeroGS::VB::FlushTexData()
{
assert( bNeedTexCheck );
assert(bNeedTexCheck);
bNeedTexCheck = 0;
u32 psm = ZZOglGet_psm_TexBitsFix(uNextTex0Data[0]);
// don't update unless necessary
if (ZZOglAllExceptClutIsSame(uCurTex0Data, uNextTex0Data)) {
if (ZZOglAllExceptClutIsSame(uCurTex0Data, uNextTex0Data))
{
// Don't need to do anything if there is no clutting and VB tex data was not changed
if( !PSMT_ISCLUT(psm) )
return ;
if (!PSMT_ISCLUT(psm)) return ;
// have to write the CLUT again if only CLD was changed
if( ZZOglClutMinusCLDunchanged(uCurTex0Data, uNextTex0Data) ) {
if (ZZOglClutMinusCLDunchanged(uCurTex0Data, uNextTex0Data))
{
FlushTexUnchangedClutDontUpdate();
return;
}
// Cld bit is 0 means that clut buffer stay unchanged
if( ZZOglGet_cld_TexBits(uNextTex0Data[1]) == 0 ) {
if (ZZOglGet_cld_TexBits(uNextTex0Data[1]) == 0)
{
FlushTexClutDontUpdate();
return;
}
@ -438,6 +486,7 @@ void ZeroGS::VB::FlushTexData()
// Made the full update
ZeroGS::Flush(ictx);
bVarsTexSync = FALSE;
bTexConstsSync = FALSE;
@ -446,8 +495,5 @@ void ZeroGS::VB::FlushTexData()
FlushTexSetNewVars(psm);
if( PSMT_ISCLUT(psm) )
ZeroGS::CluttingForFlushedTex(&tex0, uNextTex0Data[1], ictx ) ;
if (PSMT_ISCLUT(psm)) ZeroGS::CluttingForFlushedTex(&tex0, uNextTex0Data[1], ictx) ;
}

View File

@ -1,4 +1,3 @@
#ifdef _WIN32
#include <windows.h>
#endif
@ -9,7 +8,8 @@
#include "rasterfont.h"
// globals
GLubyte rasters[][13] = {
GLubyte rasters[][13] =
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
@ -113,9 +113,11 @@ RasterFont::RasterFont()
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// create the raster font
fontOffset = glGenLists (128);
for (int i = 32; i < 127; i++) {
glNewList(i+fontOffset, GL_COMPILE);
fontOffset = glGenLists(128);
for (int i = 32; i < 127; i++)
{
glNewList(i + fontOffset, GL_COMPILE);
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i-32]);
glEndList();
}
@ -131,16 +133,16 @@ void RasterFont::printString(const char *s, double x, double y, double z)
// go to the right spot
glRasterPos3d(x, y, z);
glPushAttrib (GL_LIST_BIT);
glPushAttrib(GL_LIST_BIT);
glListBase(fontOffset);
glCallLists(strlen(s), GL_UNSIGNED_BYTE, (GLubyte *) s);
glPopAttrib ();
glPopAttrib();
}
void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
{
int length = strlen(s);
int x = int(screen_width/2.0 - (length/2.0)*char_width);
int x = int(screen_width / 2.0 - (length / 2.0) * char_width);
printString(s, x, y, z);
}

File diff suppressed because it is too large Load Diff

View File

@ -193,8 +193,8 @@ void __fastcall Frame16SwizzleBlock16Z##type##c(u16* dst, Vector_16F* src, int s
} \
_FrameSwizzleBlock(_, src[j], src[j], 0);
_FrameSwizzleBlock(A2_, (src[2*j]+src[2*j+1])>>1, src[2*j], 0);
_FrameSwizzleBlock(A4_, (src[2*j]+src[2*j+1]+src[2*j+srcpitch]+src[2*j+srcpitch+1])>>2, src[2*j], 1);
_FrameSwizzleBlock(A2_, (src[2*j] + src[2*j+1]) >> 1, src[2*j], 0);
_FrameSwizzleBlock(A4_, (src[2*j] + src[2*j+1] + src[2*j+srcpitch] + src[2*j+srcpitch+1]) >> 2, src[2*j], 1);
#ifdef ZEROGS_SSE2
@ -266,9 +266,9 @@ extern "C" void __fastcall WriteCLUT_T32_I8_CSM1_sse2(u32* vm, u32* clut)
__m128i* src = (__m128i*)vm;
__m128i* dst = (__m128i*)clut;
for(int j = 0; j < 64; j += 32, src += 32, dst += 32)
for (int j = 0; j < 64; j += 32, src += 32, dst += 32)
{
for(int i = 0; i < 16; i += 4)
for (int i = 0; i < 16; i += 4)
{
__m128i r0 = _mm_load_si128(&src[i+0]);
__m128i r1 = _mm_load_si128(&src[i+1]);
@ -310,16 +310,19 @@ extern "C" void __fastcall WriteCLUT_T32_I4_CSM1_sse2(u32* vm, u32* clut)
}
extern "C" {
PCSX2_ALIGNED16(int s_clut16mask2[4]) = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff };
PCSX2_ALIGNED16(int s_clut16mask[8]) = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000,
0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff};
extern "C"
{
PCSX2_ALIGNED16(int s_clut16mask2[4]) = { 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff };
PCSX2_ALIGNED16(int s_clut16mask[8]) = { 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000,
0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff
};
}
extern "C" void __fastcall WriteCLUT_T16_I4_CSM1_sse2(u32* vm, u32* clut)
{
#if defined(_MSC_VER)
__asm {
__asm
{
mov eax, vm
mov ecx, clut
movdqa xmm0, qword ptr [eax]
@ -428,122 +431,125 @@ WriteUnaligned:
movdqa [ecx+16], xmm2
movdqa [ecx+48], xmm3
End:
}
#else
__asm__(".intel_syntax noprefix\n"
"movdqa xmm0, xmmword ptr [ecx]\n"
"movdqa xmm1, xmmword ptr [ecx+16]\n"
"movdqa xmm2, xmmword ptr [ecx+32]\n"
"movdqa xmm3, xmmword ptr [ecx+48]\n"
"movdqa xmm0, xmmword ptr [ecx]\n"
"movdqa xmm1, xmmword ptr [ecx+16]\n"
"movdqa xmm2, xmmword ptr [ecx+32]\n"
"movdqa xmm3, xmmword ptr [ecx+48]\n"
// rearrange
"pshuflw xmm0, xmm0, 0x88\n"
"pshufhw xmm0, xmm0, 0x88\n"
"pshuflw xmm1, xmm1, 0x88\n"
"pshufhw xmm1, xmm1, 0x88\n"
"pshuflw xmm2, xmm2, 0x88\n"
"pshufhw xmm2, xmm2, 0x88\n"
"pshuflw xmm3, xmm3, 0x88\n"
"pshufhw xmm3, xmm3, 0x88\n"
// rearrange
"pshuflw xmm0, xmm0, 0x88\n"
"pshufhw xmm0, xmm0, 0x88\n"
"pshuflw xmm1, xmm1, 0x88\n"
"pshufhw xmm1, xmm1, 0x88\n"
"pshuflw xmm2, xmm2, 0x88\n"
"pshufhw xmm2, xmm2, 0x88\n"
"pshuflw xmm3, xmm3, 0x88\n"
"pshufhw xmm3, xmm3, 0x88\n"
"shufps xmm0, xmm1, 0x88\n"
"shufps xmm2, xmm3, 0x88\n"
"shufps xmm0, xmm1, 0x88\n"
"shufps xmm2, xmm3, 0x88\n"
"pshufd xmm0, xmm0, 0xd8\n"
"pshufd xmm2, xmm2, 0xd8\n"
"pshufd xmm0, xmm0, 0xd8\n"
"pshufd xmm2, xmm2, 0xd8\n"
"pxor xmm6, xmm6\n"
"pxor xmm6, xmm6\n"
"test edx, 15\n"
"jnz WriteUnaligned\n"
"test edx, 15\n"
"jnz WriteUnaligned\n"
"movdqa xmm7, [%[s_clut16mask]]\n" // saves upper 16 bits
"movdqa xmm7, [%[s_clut16mask]]\n" // saves upper 16 bits
// have to save interlaced with the old data
"movdqa xmm4, [edx]\n"
"movdqa xmm5, [edx+32]\n"
"movhlps xmm1, xmm0\n"
"movlhps xmm0, xmm2\n"// lower 8 colors
// have to save interlaced with the old data
"movdqa xmm4, [edx]\n"
"movdqa xmm5, [edx+32]\n"
"movhlps xmm1, xmm0\n"
"movlhps xmm0, xmm2\n"// lower 8 colors
"pand xmm4, xmm7\n"
"pand xmm5, xmm7\n"
"pand xmm4, xmm7\n"
"pand xmm5, xmm7\n"
"shufps xmm1, xmm2, 0xe4\n" // upper 8 colors
"movdqa xmm2, xmm0\n"
"movdqa xmm3, xmm1\n"
"shufps xmm1, xmm2, 0xe4\n" // upper 8 colors
"movdqa xmm2, xmm0\n"
"movdqa xmm3, xmm1\n"
"punpcklwd xmm0, xmm6\n"
"punpcklwd xmm1, xmm6\n"
"por xmm0, xmm4\n"
"por xmm1, xmm5\n"
"punpcklwd xmm0, xmm6\n"
"punpcklwd xmm1, xmm6\n"
"por xmm0, xmm4\n"
"por xmm1, xmm5\n"
"punpckhwd xmm2, xmm6\n"
"punpckhwd xmm3, xmm6\n"
"punpckhwd xmm2, xmm6\n"
"punpckhwd xmm3, xmm6\n"
"movdqa [edx], xmm0\n"
"movdqa [edx+32], xmm1\n"
"movdqa [edx], xmm0\n"
"movdqa [edx+32], xmm1\n"
"movdqa xmm5, xmm7\n"
"pand xmm7, [edx+16]\n"
"pand xmm5, [edx+48]\n"
"movdqa xmm5, xmm7\n"
"pand xmm7, [edx+16]\n"
"pand xmm5, [edx+48]\n"
"por xmm2, xmm7\n"
"por xmm3, xmm5\n"
"por xmm2, xmm7\n"
"por xmm3, xmm5\n"
"movdqa [edx+16], xmm2\n"
"movdqa [edx+48], xmm3\n"
"jmp WriteCLUT_T16_I4_CSM1_End\n"
"movdqa [edx+16], xmm2\n"
"movdqa [edx+48], xmm3\n"
"jmp WriteCLUT_T16_I4_CSM1_End\n"
"WriteUnaligned:\n"
// %edx is offset by 2
"sub edx, 2\n"
"WriteUnaligned:\n"
// %edx is offset by 2
"sub edx, 2\n"
"movdqa xmm7, [%[s_clut16mask2]]\n" // saves lower 16 bits
"movdqa xmm7, [%[s_clut16mask2]]\n" // saves lower 16 bits
// have to save interlaced with the old data
"movdqa xmm4, [edx]\n"
"movdqa xmm5, [edx+32]\n"
"movhlps xmm1, xmm0\n"
"movlhps xmm0, xmm2\n" // lower 8 colors
// have to save interlaced with the old data
"movdqa xmm4, [edx]\n"
"movdqa xmm5, [edx+32]\n"
"movhlps xmm1, xmm0\n"
"movlhps xmm0, xmm2\n" // lower 8 colors
"pand xmm4, xmm7\n"
"pand xmm5, xmm7\n"
"pand xmm4, xmm7\n"
"pand xmm5, xmm7\n"
"shufps xmm1, xmm2, 0xe4\n" // upper 8 colors
"movdqa xmm2, xmm0\n"
"movdqa xmm3, xmm1\n"
"shufps xmm1, xmm2, 0xe4\n" // upper 8 colors
"movdqa xmm2, xmm0\n"
"movdqa xmm3, xmm1\n"
"punpcklwd xmm0, xmm6\n"
"punpcklwd xmm1, xmm6\n"
"pslld xmm0, 16\n"
"pslld xmm1, 16\n"
"por xmm0, xmm4\n"
"por xmm1, xmm5\n"
"punpcklwd xmm0, xmm6\n"
"punpcklwd xmm1, xmm6\n"
"pslld xmm0, 16\n"
"pslld xmm1, 16\n"
"por xmm0, xmm4\n"
"por xmm1, xmm5\n"
"punpckhwd xmm2, xmm6\n"
"punpckhwd xmm3, xmm6\n"
"pslld xmm2, 16\n"
"pslld xmm3, 16\n"
"punpckhwd xmm2, xmm6\n"
"punpckhwd xmm3, xmm6\n"
"pslld xmm2, 16\n"
"pslld xmm3, 16\n"
"movdqa [edx], xmm0\n"
"movdqa [edx+32], xmm1\n"
"movdqa [edx], xmm0\n"
"movdqa [edx+32], xmm1\n"
"movdqa xmm5, xmm7\n"
"pand xmm7, [edx+16]\n"
"pand xmm5, [edx+48]\n"
"movdqa xmm5, xmm7\n"
"pand xmm7, [edx+16]\n"
"pand xmm5, [edx+48]\n"
"por xmm2, xmm7\n"
"por xmm3, xmm5\n"
"por xmm2, xmm7\n"
"por xmm3, xmm5\n"
"movdqa [edx+16], xmm2\n"
"movdqa [edx+48], xmm3\n"
"WriteCLUT_T16_I4_CSM1_End:\n"
".att_syntax\n"
: [s_clut16mask]"=m"(s_clut16mask), [s_clut16mask2]"=m"(s_clut16mask2)
);
"movdqa [edx+16], xmm2\n"
"movdqa [edx+48], xmm3\n"
"WriteCLUT_T16_I4_CSM1_End:\n"
".att_syntax\n"
: [s_clut16mask]"=m"(s_clut16mask), [s_clut16mask2]"=m"(s_clut16mask2)
);
#endif // _MSC_VER
}
#endif // ZEROGS_SSE2
void __fastcall WriteCLUT_T16_I8_CSM1_c(u32* _vm, u32* _clut)
@ -559,27 +565,31 @@ void __fastcall WriteCLUT_T16_I8_CSM1_c(u32* _vm, u32* _clut)
u16* vm = (u16*)_vm;
u16* clut = (u16*)_clut;
int left = ((u32)(uptr)clut&2) ? 512 : 512-(((u32)(uptr)clut)&0x3ff)/2;
int left = ((u32)(uptr)clut & 2) ? 512 : 512 - (((u32)(uptr)clut) & 0x3ff) / 2;
for(int j = 0; j < 8; j++, vm += 32, clut += 64, left -= 32)
for (int j = 0; j < 8; j++, vm += 32, clut += 64, left -= 32)
{
if(left == 32) {
assert( left == 32 );
for(int i = 0; i < 16; i++)
if (left == 32)
{
assert(left == 32);
for (int i = 0; i < 16; i++)
clut[2*i] = vm[map[i]];
clut = (u16*)((uptr)clut & ~0x3ff) + 1;
for(int i = 16; i < 32; i++)
for (int i = 16; i < 32; i++)
clut[2*i] = vm[map[i]];
}
else {
if( left == 0 ) {
else
{
if (left == 0)
{
clut = (u16*)((uptr)clut & ~0x3ff) + 1;
left = -1;
}
for(int i = 0; i < 32; i++)
for (int i = 0; i < 32; i++)
clut[2*i] = vm[map[i]];
}
}
@ -590,8 +600,9 @@ void __fastcall WriteCLUT_T32_I8_CSM1_c(u32* vm, u32* clut)
u64* src = (u64*)vm;
u64* dst = (u64*)clut;
for(int j = 0; j < 2; j++, src += 32) {
for(int i = 0; i < 4; i++, dst+=16, src+=8)
for (int j = 0; j < 2; j++, src += 32)
{
for (int i = 0; i < 4; i++, dst += 16, src += 8)
{
dst[0] = src[0];
dst[1] = src[2];
@ -619,14 +630,22 @@ void __fastcall WriteCLUT_T16_I4_CSM1_c(u32* _vm, u32* _clut)
u16* dst = (u16*)_clut;
u16* src = (u16*)_vm;
dst[0] = src[0]; dst[2] = src[2];
dst[4] = src[8]; dst[6] = src[10];
dst[8] = src[16]; dst[10] = src[18];
dst[12] = src[24]; dst[14] = src[26];
dst[16] = src[4]; dst[18] = src[6];
dst[20] = src[12]; dst[22] = src[14];
dst[24] = src[20]; dst[26] = src[22];
dst[28] = src[28]; dst[30] = src[30];
dst[0] = src[0];
dst[2] = src[2];
dst[4] = src[8];
dst[6] = src[10];
dst[8] = src[16];
dst[10] = src[18];
dst[12] = src[24];
dst[14] = src[26];
dst[16] = src[4];
dst[18] = src[6];
dst[20] = src[12];
dst[22] = src[14];
dst[24] = src[20];
dst[26] = src[22];
dst[28] = src[28];
dst[30] = src[30];
}
void __fastcall WriteCLUT_T32_I4_CSM1_c(u32* vm, u32* clut)
@ -644,10 +663,12 @@ void __fastcall WriteCLUT_T32_I4_CSM1_c(u32* vm, u32* clut)
dst[7] = src[7];
}
void SSE2_UnswizzleZ16Target( u16* dst, u16* src, int iters ) {
void SSE2_UnswizzleZ16Target(u16* dst, u16* src, int iters)
{
#if defined(_MSC_VER)
__asm {
__asm
{
mov edx, iters
pxor xmm7, xmm7
mov eax, dst
@ -698,51 +719,52 @@ Z16Loop:
#else // _MSC_VER
__asm__(".intel_syntax\n"
"pxor %%xmm7, %%xmm7\n"
"pxor %%xmm7, %%xmm7\n"
"Z16Loop:\n"
// unpack 64 bytes at a time
"movdqa %%xmm0, [%0]\n"
"movdqa %%xmm2, [%0+16]\n"
"movdqa %%xmm4, [%0+32]\n"
"movdqa %%xmm6, [%0+48]\n"
"Z16Loop:\n"
// unpack 64 bytes at a time
"movdqa %%xmm0, [%0]\n"
"movdqa %%xmm2, [%0+16]\n"
"movdqa %%xmm4, [%0+32]\n"
"movdqa %%xmm6, [%0+48]\n"
"movdqa %%xmm1, %%xmm0\n"
"movdqa %%xmm3, %%xmm2\n"
"movdqa %%xmm5, %%xmm4\n"
"movdqa %%xmm1, %%xmm0\n"
"movdqa %%xmm3, %%xmm2\n"
"movdqa %%xmm5, %%xmm4\n"
"punpcklwd %%xmm0, %%xmm7\n"
"punpckhwd %%xmm1, %%xmm7\n"
"punpcklwd %%xmm2, %%xmm7\n"
"punpckhwd %%xmm3, %%xmm7\n"
"punpcklwd %%xmm0, %%xmm7\n"
"punpckhwd %%xmm1, %%xmm7\n"
"punpcklwd %%xmm2, %%xmm7\n"
"punpckhwd %%xmm3, %%xmm7\n"
// start saving
"movdqa [%1], %%xmm0\n"
"movdqa [%1+16], %%xmm1\n"
// start saving
"movdqa [%1], %%xmm0\n"
"movdqa [%1+16], %%xmm1\n"
"punpcklwd %%xmm4, %%xmm7\n"
"punpckhwd %%xmm5, %%xmm7\n"
"punpcklwd %%xmm4, %%xmm7\n"
"punpckhwd %%xmm5, %%xmm7\n"
"movdqa [%1+32], %%xmm2\n"
"movdqa [%1+48], %%xmm3\n"
"movdqa [%1+32], %%xmm2\n"
"movdqa [%1+48], %%xmm3\n"
"movdqa %%xmm0, %%xmm6\n"
"punpcklwd %%xmm6, %%xmm7\n"
"movdqa %%xmm0, %%xmm6\n"
"punpcklwd %%xmm6, %%xmm7\n"
"movdqa [%1+64], %%xmm4\n"
"movdqa [%1+80], %%xmm5\n"
"movdqa [%1+64], %%xmm4\n"
"movdqa [%1+80], %%xmm5\n"
"punpckhwd %%xmm0, %%xmm7\n"
"punpckhwd %%xmm0, %%xmm7\n"
"movdqa [%1+96], %%xmm6\n"
"movdqa [%1+112], %%xmm0\n"
"movdqa [%1+96], %%xmm6\n"
"movdqa [%1+112], %%xmm0\n"
"add %0, 64\n"
"add %1, 128\n"
"sub %2, 1\n"
"jne Z16Loop\n"
".att_syntax\n" : "=r"(src), "=r"(dst), "=r"(iters) : "0"(src), "1"(dst), "2"(iters)
);
"add %0, 64\n"
"add %1, 128\n"
"sub %2, 1\n"
"jne Z16Loop\n"
".att_syntax\n" : "=r"(src), "=r"(dst), "=r"(iters) : "0"(src), "1"(dst), "2"(iters)
);
#endif // _MSC_VER
}

File diff suppressed because it is too large Load Diff

View File

@ -59,6 +59,12 @@ public:
inline void Set3(const float* pvals) { x = pvals[0]; y = pvals[1]; z = pvals[2]; }
inline void Set4(const float* pvals) { x = pvals[0]; y = pvals[1]; z = pvals[2]; w = pvals[3]; }
inline void SetColor(u32 color)
{
x = (color & 0xff) / 255.0f;
y = ((color >> 8) & 0xff) / 255.0f;
z = ((color >> 16) & 0xff) / 255.0f;
}
// 3 dim cross product, w is not touched
/// this = this x v

View File

@ -25,23 +25,28 @@ int def(char *src, char *dst, int bytes_to_compress, int *bytes_after_compressed
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION) ;
if (ret != Z_OK)
return ret;
/* compress */
strm.avail_in = bytes_to_compress ;
strm.avail_out = bytes_to_compress ;
strm.next_in = (Bytef *)src ;
strm.next_out = (Bytef *)dst ;
ret = deflate(&strm, Z_FINISH) ;
have = bytes_to_compress - strm.avail_out ;
*bytes_after_compressed = have ;
assert(ret == Z_STREAM_END); /* stream will be complete */
/* clean up and return */
(void)deflateEnd(&strm);
return Z_OK;
}
@ -59,8 +64,8 @@ int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompr
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK)
return ret;
if (ret != Z_OK) return ret;
/* decompress */
strm.avail_in = bytes_to_decompress ;
@ -69,23 +74,29 @@ int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompr
strm.avail_out = maximum_after_decompress ;
ret = inflate(&strm, Z_NO_FLUSH) ;
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
switch (ret)
{
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
assert(strm.avail_in == 0); /* all input will be used */
if( outbytes != NULL )
*outbytes = strm.total_out;
if (outbytes != NULL) *outbytes = strm.total_out;
/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
@ -93,23 +104,28 @@ int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompr
void zerr(int ret)
{
fputs("zpipe: ", stderr);
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
fputs("error reading stdin\n", stderr);
if (ferror(stdout))
fputs("error writing stdout\n", stderr);
break;
case Z_STREAM_ERROR:
fputs("invalid compression level\n", stderr);
break;
case Z_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);
break;
case Z_MEM_ERROR:
fputs("out of memory\n", stderr);
break;
case Z_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
switch (ret)
{
case Z_ERRNO:
if (ferror(stdin)) fputs("error reading stdin\n", stderr);
if (ferror(stdout)) fputs("error writing stdout\n", stderr);
break;
case Z_STREAM_ERROR:
fputs("invalid compression level\n", stderr);
break;
case Z_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);
break;
case Z_MEM_ERROR:
fputs("out of memory\n", stderr);
break;
case Z_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
}
}