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,6 +109,7 @@ bool GLWindow::CreateWindow(void *pDisplay)
}
AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
GetWindowRect(GetDesktopWindow(), &rcdesktop);
GShwnd = CreateWindowEx(
@ -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);
}
hRC=NULL; // Set RC To NULL
MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
if (hDC && !ReleaseDC(GShwnd,hDC)) // Are We Able To Release The DC
hRC = NULL; // Set RC To NULL
}
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

@ -26,7 +26,7 @@ bool GLWindow::CreateWindow(void *pDisplay)
glDisplay = XOpenDisplay(0);
glScreen = DefaultScreen(glDisplay);
if ( pDisplay == NULL ) return false;
if (pDisplay == NULL) return false;
*(Display**)pDisplay = glDisplay;
@ -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,7 +65,8 @@ 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;
@ -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,7 +234,7 @@ 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;
}
@ -236,8 +249,10 @@ 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);
}
@ -245,7 +260,7 @@ void GLWindow::ResizeCheck()
{
XEvent event;
while(XCheckTypedEvent(glDisplay, ConfigureNotify, &event))
while (XCheckTypedEvent(glDisplay, ConfigureNotify, &event))
{
if ((event.xconfigure.width != width) || (event.xconfigure.height != height))
{
@ -253,6 +268,7 @@ void GLWindow::ResizeCheck()
width = event.xconfigure.width;
height = event.xconfigure.height;
}
if ((event.xconfigure.x != x) || (event.xconfigure.y != y))
{
x = event.xconfigure.x;

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
}
@ -99,14 +103,14 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
pathInfo *path = &gs.path[index];
#ifdef _WIN32
assert( g_hCurrentThread == GetCurrentThread() );
assert(g_hCurrentThread == GetCurrentThread());
#endif
#ifdef _DEBUG
gifTransferLog(index, pMem, size);
#endif
while(size > 0)
while (size > 0)
{
//LOG(_T("Transfer(%08x, %d) START\n"), pMem, size);
if (path->nloop == 0)
@ -123,7 +127,7 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
{
gs.q = 1.0f;
if(path->tag.PRE && (path->tag.FLG == GIF_FLG_PACKED))
if (path->tag.PRE && (path->tag.FLG == GIF_FLG_PACKED))
{
u32 tagprim = path->tag.PRIM;
GIFRegHandlerPRIM((u32*)&tagprim);
@ -132,7 +136,7 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
}
else
{
switch(path->mode)
switch (path->mode)
{
case GIF_FLG_PACKED:
{
@ -163,6 +167,7 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
break;
}
case GIF_FLG_REGLIST:
{
// Needs to be looked at.
@ -177,10 +182,9 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
pMem += 2;
size--;
}
while(path->StepReg() && (size > 0));
if(size & 1) pMem += 2;
while (path->StepReg() && (size > 0));
if (size & 1) pMem += 2;
size /= 2;
break;
}
@ -191,32 +195,38 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
int len = min(size, path->nloop);
//ZZLog::Error_Log("GIF_FLG_IMAGE(%d)=%d", gs.imageTransfer, len);
switch(gs.imageTransfer)
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);
@ -227,7 +237,7 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
if (index == 0)
{
if(path->tag.EOP && path->nloop == 0)
if (path->tag.EOP && path->nloop == 0)
{
break;
}
@ -238,7 +248,7 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
// 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,6 +293,7 @@ void CALLBACK GSgifTransfer3(u32 *pMem, u32 size)
_GSgifTransfer<2>(pMem, size);
}
#else
template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
@ -292,14 +303,14 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
pathInfo *path = &gs.path[index];
#ifdef _WIN32
assert( g_hCurrentThread == GetCurrentThread() );
assert(g_hCurrentThread == GetCurrentThread());
#endif
#ifdef _DEBUG
gifTransferLog(index, pMem, size);
#endif
while(size > 0)
while (size > 0)
{
//LOG(_T("Transfer(%08x, %d) START\n"), pMem, size);
if (path->nloop == 0)
@ -316,7 +327,7 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
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)
for (int i = 0; i < path->nreg; i += 4)
{
if (((path->regs >> i) & 0xf) == 11)
{
@ -328,12 +339,13 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
}
}
if(path->nloop == 0 )
if (path->nloop == 0)
{
if (index == 0)
{
// ffx hack
if( path->eop ) return;
if (path->eop) return;
continue;
}
@ -348,12 +360,14 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
}
}
switch(path->mode)
switch (path->mode)
{
case GIF_FLG_PACKED:
{
assert( path->nloop > 0 );
for(; size > 0; size--, pMem += 4)
assert(path->nloop > 0);
for (; size > 0; size--, pMem += 4)
{
int reg = (int)((path->regs >> path->regn) & 0xf);
@ -365,7 +379,7 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
{
path->regn = 0;
if( path->nloop-- <= 1 )
if (path->nloop-- <= 1)
{
size--;
pMem += 4;
@ -373,15 +387,17 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
}
}
}
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 );
assert(path->nloop > 0);
size *= 2;
for(; size > 0; pMem+= 2, size--)
for (; size > 0; pMem += 2, size--)
{
int reg = (int)((path->regs >> path->regn) & 0xf);
@ -392,7 +408,8 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
if (path->nreg == path->regn)
{
path->regn = 0;
if( path->nloop-- <= 1 )
if (path->nloop-- <= 1)
{
size--;
pMem += 2;
@ -401,30 +418,36 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
}
}
if( size & 1 ) pMem += 2;
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)
if (gs.imageTransfer >= 0 && gs.imageTransfer <= 1)
{
int process = min((int)size, path->nloop);
if( process > 0 )
if (process > 0)
{
if ( gs.imageTransfer )
if (gs.imageTransfer)
ZeroGS::TransferLocalHost(pMem, process);
else
ZeroGS::TransferHostLocal(pMem, process*4);
path->nloop -= process;
pMem += process*4;
pMem += process * 4;
size -= process;
assert( size == 0 || path->nloop == 0 );
assert(size == 0 || path->nloop == 0);
}
break;
}
else
@ -433,12 +456,13 @@ template<int index> void _GSgifTransfer(u32 *pMem, u32 size)
int process = min((int)size, path->nloop);
path->nloop -= process;
pMem += process*4;
pMem += process * 4;
size -= process;
}
break;
}
default: // GIF_IMAGE
ZZLog::GS_Log("*** WARNING **** Unexpected GIFTag flag.");
assert(0);
@ -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 ---------//
}
@ -215,7 +225,7 @@ void DisplayDialog()
if (!(conf.options & GSOPTION_LOADED)) LoadConfig();
/* Create the widgets */
dialog = gtk_dialog_new_with_buttons (
dialog = gtk_dialog_new_with_buttons(
"ZZOgl PG Config",
NULL, /* parent window*/
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
@ -226,8 +236,11 @@ void DisplayDialog()
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 ();
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");
@ -235,10 +248,11 @@ void DisplayDialog()
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_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();
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");
@ -249,38 +263,45 @@ void DisplayDialog()
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)");
snap_label = gtk_label_new ("Snapshot format:");
snap_box = gtk_combo_box_new_text ();
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);
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 ();
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);
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);
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);
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);
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,9 +319,7 @@ 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);
@ -311,10 +330,11 @@ void DisplayDialog()
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);
return_value = gtk_dialog_run(GTK_DIALOG(dialog));
if (return_value == GTK_RESPONSE_ACCEPT)
{
@ -329,15 +349,27 @@ void DisplayDialog()
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)))
@ -356,10 +388,11 @@ void DisplayDialog()
fake_options |= GSOPTION_TGASNAP;
conf.options = fake_options;
SaveConfig();
}
gtk_widget_destroy (dialog);
gtk_widget_destroy(dialog);
}
void CALLBACK GSconfigure()
@ -384,13 +417,16 @@ void SysMessage(const char *fmt, ...)
if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0;
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL,
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);
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

@ -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,17 +116,17 @@ 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;
u8 *temp = pstart + fun.gp(tempj, tempY, gs.dstbuf.bw) * data.blockbits / 8;
swizzle(temp, (u8*)pbuf, TransPitch(pitch, data.transfersize), 0xffffffff);
}
@ -130,25 +134,27 @@ static __forceinline const T* TransferAligningToBlocks(TransferData data, Transf
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,21 +18,24 @@
#include "GS.h"
u32 g_blockTable32[4][8] = {
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] = {
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] = {
u32 g_blockTable16[8][4] =
{
{ 0, 2, 8, 10 },
{ 1, 3, 9, 11 },
{ 4, 6, 12, 14 },
@ -43,7 +46,8 @@ u32 g_blockTable16[8][4] = {
{ 21, 23, 29, 31 }
};
u32 g_blockTable16S[8][4] = {
u32 g_blockTable16S[8][4] =
{
{ 0, 2, 16, 18 },
{ 1, 3, 17, 19 },
{ 8, 10, 24, 26 },
@ -54,7 +58,8 @@ u32 g_blockTable16S[8][4] = {
{ 13, 15, 29, 31 }
};
u32 g_blockTable16Z[8][4] = {
u32 g_blockTable16Z[8][4] =
{
{ 24, 26, 16, 18 },
{ 25, 27, 17, 19 },
{ 28, 30, 20, 22 },
@ -65,7 +70,8 @@ u32 g_blockTable16Z[8][4] = {
{ 13, 15, 5, 7 }
};
u32 g_blockTable16SZ[8][4] = {
u32 g_blockTable16SZ[8][4] =
{
{ 24, 26, 8, 10 },
{ 25, 27, 9, 11 },
{ 16, 18, 0, 2 },
@ -76,14 +82,16 @@ u32 g_blockTable16SZ[8][4] = {
{ 21, 23, 5, 7 }
};
u32 g_blockTable8[4][8] = {
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] = {
u32 g_blockTable4[8][4] =
{
{ 0, 2, 8, 10 },
{ 1, 3, 9, 11 },
{ 4, 6, 12, 14 },
@ -94,7 +102,8 @@ u32 g_blockTable4[8][4] = {
{ 21, 23, 29, 31 }
};
u32 g_columnTable32[8][8] = {
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 },
@ -105,7 +114,8 @@ u32 g_columnTable32[8][8] = {
{ 50, 51, 54, 55, 58, 59, 62, 63 },
};
u32 g_columnTable16[8][16] = {
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,
@ -124,7 +134,8 @@ u32 g_columnTable16[8][16] = {
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,
@ -159,7 +170,8 @@ u32 g_columnTable8[16][16] = {
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,

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)
@ -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]);
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.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 &&
int psm = (0x30 | ((data[0] >> 24) & 0xf));
if (zbuf.zbp == (data[0] & 0x1ff) * 32 &&
zbuf.psm == psm &&
zbuf.zmsk == (data[1] & 0x1) ) {
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,37 +944,41 @@ 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 &&
int psm = (0x30 | ((data[0] >> 24) & 0xf));
if (zbuf.zbp == (data[0] & 0x1ff) * 32 &&
zbuf.psm == psm &&
zbuf.zmsk == (data[1] & 0x1) ) {
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.dstbufnew.bp = ((data[1]) & 0x3fff); // * 64;
gs.dstbufnew.bw = ((data[1] >> 16) & 0x3f) * 64;
gs.dstbufnew.psm = (data[1] >> 24) & 0x3f;
@ -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,30 +80,36 @@ 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
inline u32 CreateInterlaceTex(int width)
{
if (width == s_nInterlaceTexWidth && s_ptexInterlace != 0) return s_ptexInterlace;
SAFE_RELEASE_TEX(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);
@ -111,9 +117,11 @@ namespace ZeroGS {
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,16 +844,21 @@ 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;
@ -762,49 +870,55 @@ inline void AfterRendererAutoresetTargets() {
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);
// 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);
}
}
#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);
}
}
#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,29 +250,33 @@ 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");
@ -269,11 +286,15 @@ inline void ZeroGS::CreateOtherCheck() {
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,7 +260,8 @@ 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 ) {
@ -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;
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);
@ -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;
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,7 +218,8 @@ 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) {
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)
@ -257,33 +272,38 @@ struct TGA_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) {
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,6 +431,7 @@ WriteUnaligned:
movdqa [ecx+16], xmm2
movdqa [ecx+48], xmm3
End:
}
#else
@ -495,7 +499,7 @@ End:
"movdqa [edx+48], xmm3\n"
"jmp WriteCLUT_T16_I4_CSM1_End\n"
"WriteUnaligned:\n"
"WriteUnaligned:\n"
// %edx is offset by 2
"sub edx, 2\n"
@ -538,12 +542,14 @@ End:
"movdqa [edx+16], xmm2\n"
"movdqa [edx+48], xmm3\n"
"WriteCLUT_T16_I4_CSM1_End:\n"
"WriteCLUT_T16_I4_CSM1_End:\n"
".att_syntax\n"
: [s_clut16mask]"=m"(s_clut16mask), [s_clut16mask2]"=m"(s_clut16mask2)
: [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
@ -741,7 +762,8 @@ Z16Loop:
"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)
".att_syntax\n" : "=r"(src), "=r"(dst), "=r"(iters) : "0"(src), "1"(dst), "2"(iters)
);
#endif // _MSC_VER
}

View File

@ -42,9 +42,10 @@
//----------------------- Defines
//-------------------------- Typedefs
typedef void (APIENTRYP _PFNSWAPINTERVAL) (int);
typedef void (APIENTRYP _PFNSWAPINTERVAL)(int);
//-------------------------- Extern variables
using namespace ZeroGS;
extern u32 g_nGenVars, g_nTexVars, g_nAlphaVars, g_nResolve;
@ -54,8 +55,8 @@ extern int g_nFrame, g_nRealFrame;
//-------------------------- Variables
#ifdef _WIN32
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HDC hDC = NULL; // Private GDI Device Context
HGLRC hRC = NULL; // Permanent Rendering Context
#endif
bool g_bIsLost = 0; // ZZ
@ -115,78 +116,90 @@ u8* g_pbyGSClut = NULL; // ZZ
namespace ZeroGS
{
Vector g_vdepth, vlogz;
Vector g_vdepth, vlogz;
// = Vector( 255.0 /256.0f, 255.0/65536.0f, 255.0f/(65535.0f*256.0f), 1.0f/(65536.0f*65536.0f));
// Vector g_vdepth = Vector( 65536.0f*65536.0f, 256.0f*65536.0f, 65536.0f, 256.0f);
extern CRangeManager s_RangeMngr; // manages overwritten memory
GLenum GetRenderTargetFormat() { return GetRenderFormat()==RFT_byte8?4:g_internalRGBAFloat16Fmt; }
extern CRangeManager s_RangeMngr; // manages overwritten memory
GLenum GetRenderTargetFormat() { return GetRenderFormat() == RFT_byte8 ? 4 : g_internalRGBAFloat16Fmt; }
// returns the first and last addresses aligned to a page that cover
void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw);
// returns the first and last addresses aligned to a page that cover
void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw);
// bool LoadEffects();
// bool LoadExtraEffects();
// FRAGMENTSHADER* LoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed);
int s_nNewWidth = -1, s_nNewHeight = -1;
void ChangeDeviceSize(int nNewWidth, int nNewHeight);
int s_nNewWidth = -1, s_nNewHeight = -1;
void ChangeDeviceSize(int nNewWidth, int nNewHeight);
void ProcessMessages();
void RenderCustom(float fAlpha); // intro anim
void ProcessMessages();
void RenderCustom(float fAlpha); // intro anim
struct MESSAGE
{
struct MESSAGE
{
MESSAGE() {}
MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; }
char str[255];
u32 dwTimeStamp;
};
static list<MESSAGE> listMsgs;
///////////////////////
// Method Prototypes //
///////////////////////
void KickPoint();
void KickLine();
void KickTriangle();
void KickTriangleFan();
void KickSprite();
void KickDummy();
void ResolveInRange(int start, int end);
void ExtWrite();
void ResetRenderTarget(int index)
{
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_RECTANGLE_NV, 0, 0);
}
DrawFn drawfn[8] = { KickDummy, KickDummy, KickDummy, KickDummy,
KickDummy, KickDummy, KickDummy, KickDummy
};
static list<MESSAGE> listMsgs;
///////////////////////
// Method Prototypes //
///////////////////////
void KickPoint();
void KickLine();
void KickTriangle();
void KickTriangleFan();
void KickSprite();
void KickDummy();
void ResolveInRange(int start, int end);
void ExtWrite();
void ResetRenderTarget(int index) {
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+index, GL_TEXTURE_RECTANGLE_NV, 0, 0 );
}
DrawFn drawfn[8] = { KickDummy, KickDummy, KickDummy, KickDummy,
KickDummy, KickDummy, KickDummy, KickDummy };
}; // end namespace
// does one time only initializing/destruction
class ZeroGSInit
{
public:
ZeroGSInit() {
public:
ZeroGSInit()
{
const u32 mem_size = 0x00400000 + 0x10000; // leave some room for out of range accesses (saves on the checks)
// clear
g_pbyGSMemory = (u8*)_aligned_malloc(0x00410000, 1024); // leave some room for out of range accesses (saves on the checks)
memset(g_pbyGSMemory, 0, 0x00410000);
g_pbyGSMemory = (u8*)_aligned_malloc(mem_size, 1024);
memset(g_pbyGSMemory, 0, mem_size);
g_pbyGSClut = (u8*)_aligned_malloc(256*8, 1024); // need 512 alignment!
g_pbyGSClut = (u8*)_aligned_malloc(256 * 8, 1024); // need 512 alignment!
memset(g_pbyGSClut, 0, 256*8);
memset(&GLWin, 0, sizeof(GLWin));
}
~ZeroGSInit() {
_aligned_free(g_pbyGSMemory); g_pbyGSMemory = NULL;
_aligned_free(g_pbyGSClut); g_pbyGSClut = NULL;
~ZeroGSInit()
{
_aligned_free(g_pbyGSMemory);
g_pbyGSMemory = NULL;
_aligned_free(g_pbyGSClut);
g_pbyGSClut = NULL;
}
};
@ -203,41 +216,52 @@ void ZeroGS::HandleGLError()
GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
// if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort
if( error != 0 ) {
if (error != 0)
{
int w, h;
GLint fmt;
glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt);
glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w);
glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &h);
switch(error)
switch (error)
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
ZZLog::Error_Log("Error! missing a required image/buffer attachment!");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
ZZLog::Error_Log("Error! has no images/buffers attached!");
break;
// case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
// ZZLog::Error_Log("Error! has an image/buffer attached in multiple locations!");
// break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
ZZLog::Error_Log("Error! has mismatched image/buffer dimensions!");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
ZZLog::Error_Log("Error! colorbuffer attachments have different types!");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
ZZLog::Error_Log("Error! trying to draw to non-attached color buffer!");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
ZZLog::Error_Log("Error! trying to read from a non-attached color buffer!");
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
ZZLog::Error_Log("Error! format is not supported by current graphics card/driver!");
break;
default:
ZZLog::Error_Log("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT() for %s!");
break;
@ -251,7 +275,8 @@ void ZeroGS::GSStateReset()
FUNCLOG
icurctx = -1;
for(int i = 0; i < 2; ++i) {
for (int i = 0; i < 2; ++i)
{
vb[i].Destroy();
memset(&vb[i], 0, sizeof(ZeroGS::VB));
@ -264,6 +289,7 @@ void ZeroGS::GSStateReset()
}
s_RangeMngr.Clear();
g_MemTargs.Destroy();
s_RTs.Destroy();
s_DepthRTs.Destroy();
@ -276,7 +302,8 @@ void ZeroGS::GSStateReset()
void ZeroGS::AddMessage(const char* pstr, u32 ms)
{
FUNCLOG
listMsgs.push_back(MESSAGE(pstr, timeGetTime()+ms));
listMsgs.push_back(MESSAGE(pstr, timeGetTime() + ms));
ZZLog::Log("%s\n", pstr);
}
void ZeroGS::DrawText(const char* pstr, int left, int top, u32 color)
@ -285,9 +312,12 @@ void ZeroGS::DrawText(const char* pstr, int left, int top, u32 color)
cgGLDisableProfile(cgvProf);
cgGLDisableProfile(cgfProf);
glColor3f(((color>>16)&0xff)/255.0f, ((color>>8)&0xff)/255.0f, (color&0xff)/255.0f);
Vector v;
v.SetColor(color);
glColor3f(v.z, v.y, v.x);
//glColor3f(((color >> 16) & 0xff) / 255.0f, ((color >> 8) & 0xff)/ 255.0f, (color & 0xff) / 255.0f);
font_p->printString(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight,0);
font_p->printString(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight, 0);
cgGLEnableProfile(cgvProf);
cgGLEnableProfile(cgfProf);
}
@ -295,10 +325,11 @@ void ZeroGS::DrawText(const char* pstr, int left, int top, u32 color)
void ZeroGS::ChangeWindowSize(int nNewWidth, int nNewHeight)
{
FUNCLOG
nBackbufferWidth = nNewWidth > 16 ? nNewWidth : 16;
nBackbufferHeight = nNewHeight > 16 ? nNewHeight : 16;
nBackbufferWidth = max(nNewWidth, 16);
nBackbufferHeight = max(nNewHeight, 16);
if( !(conf.options & GSOPTION_FULLSCREEN) ) {
if (!(conf.options & GSOPTION_FULLSCREEN))
{
conf.width = nNewWidth;
conf.height = nNewHeight;
//SaveConfig();
@ -311,7 +342,8 @@ void ZeroGS::SetChangeDeviceSize(int nNewWidth, int nNewHeight)
s_nNewWidth = nNewWidth;
s_nNewHeight = nNewHeight;
if( !(conf.options & GSOPTION_FULLSCREEN) ) {
if (!(conf.options & GSOPTION_FULLSCREEN))
{
conf.width = nNewWidth;
conf.height = nNewHeight;
//SaveConfig();
@ -352,26 +384,30 @@ void ZeroGS::ChangeDeviceSize(int nNewWidth, int nNewHeight)
//int oldscreen = s_nFullscreen;
int oldwidth = nBackbufferWidth, oldheight = nBackbufferHeight;
if (!Create(nNewWidth&~7, nNewHeight&~7))
{
ZZLog::Error_Log("Failed to recreate, changing to old device.");
if ( Create(oldwidth, oldheight))
if (Create(oldwidth, oldheight))
{
SysMessage("Failed to create device, exiting...");
exit(0);
}
}
for(int i = 0; i < 2; ++i) {
for (int i = 0; i < 2; ++i)
{
vb[i].bNeedFrameCheck = vb[i].bNeedZCheck = 1;
vb[i].CheckFrame(0);
}
assert( vb[0].pBufferData != NULL && vb[1].pBufferData != NULL );
assert(vb[0].pBufferData != NULL && vb[1].pBufferData != NULL);
}
void ZeroGS::SetNegAA(int mode) {
void ZeroGS::SetNegAA(int mode)
{
FUNCLOG
// need to flush all targets
s_RTs.ResolveAll();
@ -380,17 +416,25 @@ void ZeroGS::SetNegAA(int mode) {
s_DepthRTs.Destroy();
s_AAz = s_AAw = 0; // This is code for x0, x2, x4, x8 and x16 anti-aliasing.
if (mode > 0)
{
s_AAz = (mode+1) / 2; // ( 1, 0 ) ; ( 1, 1 ) -- it's used as binary shift, so x << s_AAz, y << s_AAw
s_AAz = (mode + 1) / 2; // ( 1, 0 ) ; ( 1, 1 ) -- it's used as binary shift, so x << s_AAz, y << s_AAw
s_AAw = mode / 2;
}
memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts));
s_nLastResolveReset = 0;
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;
}
void ZeroGS::SetAA(int mode)
@ -405,32 +449,40 @@ void ZeroGS::SetAA(int mode)
s_DepthRTs.Destroy();
s_AAx = s_AAy = 0; // This is code for x0, x2, x4, x8 and x16 anti-aliasing.
if (mode > 0)
{
s_AAx = (mode+1) / 2; // ( 1, 0 ) ; ( 1, 1 ) ; ( 2, 1 ) ; ( 2, 2 ) -- it's used as binary shift, so x >> s_AAx, y >> s_AAy
s_AAx = (mode + 1) / 2; // ( 1, 0 ) ; ( 1, 1 ) ; ( 2, 1 ) ; ( 2, 2 ) -- it's used as binary shift, so x >> s_AAx, y >> s_AAy
s_AAy = mode / 2;
}
memset(s_nResolveCounts, 0, sizeof(s_nResolveCounts));
s_nLastResolveReset = 0;
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;
f = mode > 0 ? 2.0f : 1.0f;
glPointSize(f);
}
void ZeroGS::Prim(){
void ZeroGS::Prim()
{
FUNCLOG
if( g_bIsLost )
return;
if (g_bIsLost) return;
VB& curvb = vb[prim->ctxt];
if( curvb.CheckPrim() ){
Flush(prim->ctxt);
}
if (curvb.CheckPrim()) Flush(prim->ctxt);
curvb.curprim._val = prim->_val;
// flush the other pipe if sharing the same buffer
@ -446,16 +498,19 @@ void ZeroGS::Prim(){
void ZeroGS::ProcessMessages()
{
FUNCLOG
if( listMsgs.size() > 0 ) {
if (listMsgs.size() > 0)
{
int left = 25, top = 15;
list<MESSAGE>::iterator it = listMsgs.begin();
while( it != listMsgs.end() ) {
DrawText(it->str, left+1, top+1, 0xff000000);
while (it != listMsgs.end())
{
DrawText(it->str, left + 1, top + 1, 0xff000000);
DrawText(it->str, left, top, 0xffffff30);
top += 15;
if( (int)(it->dwTimeStamp - timeGetTime()) < 0 )
if ((int)(it->dwTimeStamp - timeGetTime()) < 0)
it = listMsgs.erase(it);
else ++it;
}
@ -468,7 +523,7 @@ void ZeroGS::RenderCustom(float fAlpha)
GL_REPORT_ERROR();
fAlpha = 1;
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
DisableAllgl() ;
SetShaderCaller("RenderCustom");
@ -476,10 +531,10 @@ void ZeroGS::RenderCustom(float fAlpha)
glViewport(0, 0, nBackbufferWidth, nBackbufferHeight);
// play custom animation
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);
// tex coords
Vector v = Vector(1/32767.0f, 1/32767.0f, 0, 0);
Vector v = Vector(1 / 32767.0f, 1 / 32767.0f, 0, 0);
ZZcgSetParameter4fv(pvsBitBlt.sBitBltPos, v, "g_fBitBltPos");
v.x = (float)nLogoWidth;
v.y = (float)nLogoHeight;
@ -488,21 +543,22 @@ void ZeroGS::RenderCustom(float fAlpha)
v.x = v.y = v.z = v.w = fAlpha;
ZZcgSetParameter4fv(ppsBaseTexture.sOneColor, v, "g_fOneColor");
if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (conf.options & GSOPTION_WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// inside vhDCb[0]'s target area, so render that region only
cgGLSetTextureParameter(ppsBaseTexture.sFinal, ptexLogo);
cgGLEnableTextureParameter(ppsBaseTexture.sFinal);
glBindBuffer(GL_ARRAY_BUFFER, vboRect);
SET_STREAM();
SETVERTEXSHADER(pvsBitBlt.prog);
SETPIXELSHADER(ppsBaseTexture.prog);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// restore
if( conf.options & GSOPTION_WIREFRAME ) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (conf.options & GSOPTION_WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
ProcessMessages();
@ -515,20 +571,24 @@ void ZeroGS::RenderCustom(float fAlpha)
vb[1].bSyncVars = 0;
GL_REPORT_ERROR();
GLint status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
assert( status == GL_FRAMEBUFFER_COMPLETE_EXT || status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT );
assert(status == GL_FRAMEBUFFER_COMPLETE_EXT || status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT);
}
void ZeroGS::Restore()
{
FUNCLOG
if( !g_bIsLost )
return;
if (!g_bIsLost) return;
//if( SUCCEEDED(pd3dDevice->Reset(&d3dpp)) ) {
g_bIsLost = 0;
// handle lost states
ZeroGS::ChangeDeviceSize(nBackbufferWidth, nBackbufferHeight);
//}
}
@ -539,16 +599,16 @@ void ZeroGS::Restore()
__forceinline void MOVZ(VertexGPU *p, u32 gsz, const VB& curvb)
{
p->z = (curvb.zprimmask==0xffff) ? min((u32)0xffff, gsz) : gsz;
p->z = (curvb.zprimmask == 0xffff) ? min((u32)0xffff, gsz) : gsz;
}
__forceinline void MOVFOG(VertexGPU *p, Vertex gsf)
{
p->f = ((s16)(gsf).f<<7)|0x7f;
p->f = ((s16)(gsf).f << 7) | 0x7f;
}
int Values[100]={0,};
int Values[100] = {0, };
__forceinline void SET_VERTEX(VertexGPU *p, int Index, const VB& curvb)
{
int index = Index;
@ -564,23 +624,26 @@ __forceinline void SET_VERTEX(VertexGPU *p, int Index, const VB& curvb)
#endif
p->f = ((s16)gs.gsvertex[index].f<<7)|0x7f;
p->f = ((s16)gs.gsvertex[index].f << 7) | 0x7f;
MOVZ(p, gs.gsvertex[index].z, curvb);
p->rgba = prim->iip ? gs.gsvertex[index].rgba : gs.rgba;
// This code is somehow incorrect
// if ((gs.texa.aem) && ((p->rgba & 0xffffff ) == 0))
// p->rgba = 0;
if (g_GameSettings & GAME_TEXAHACK) {
u32 B = (( p->rgba & 0xfe000000 ) >> 1) +
if (g_GameSettings & GAME_TEXAHACK)
{
u32 B = ((p->rgba & 0xfe000000) >> 1) +
(0x01000000 * curvb.fba.fba) ;
p->rgba = ( p->rgba & 0xffffff ) + B;
p->rgba = (p->rgba & 0xffffff) + B;
}
if (prim->tme )
if (prim->tme)
{
if( prim->fst )
if (prim->fst)
{
p->s = (float)gs.gsvertex[index].u * fiTexWidth[prim->ctxt];
p->t = (float)gs.gsvertex[index].v * fiTexHeight[prim->ctxt];
@ -599,7 +662,7 @@ static __forceinline void OUTPUT_VERT(VertexGPU vert, u32 id)
{
#ifdef WRITE_PRIM_LOGS
ZZLog::Prim_Log("%c%d(%d): xyzf=(%4d,%4d,0x%x,%3d), rgba=0x%8.8x, stq = (%2.5f,%2.5f,%2.5f)\n",
id==0?'*':' ', id, prim->prim, vert.x/8, vert.y/8, vert.z, vert.f/128,
id == 0 ? '*' : ' ', id, prim->prim, vert.x / 8, vert.y / 8, vert.z, vert.f / 128,
vert.rgba, Clamp(vert.s, -10, 10), Clamp(vert.t, -10, 10), Clamp(vert.q, -10, 10));
#endif
}
@ -607,22 +670,23 @@ static __forceinline void OUTPUT_VERT(VertexGPU vert, u32 id)
void ZeroGS::KickPoint()
{
FUNCLOG
assert( gs.primC >= 1 );
assert(gs.primC >= 1);
VB& curvb = vb[prim->ctxt];
if (curvb.bNeedTexCheck) curvb.FlushTexData();
if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
{
assert( vb[prim->ctxt].nCount == 0 );
assert(vb[prim->ctxt].nCount == 0);
Flush(!prim->ctxt);
}
curvb.NotifyWrite(1);
int last = (gs.primIndex+2)%ARRAY_SIZE(gs.gsvertex);
int last = (gs.primIndex + 2) % ARRAY_SIZE(gs.gsvertex);
VertexGPU* p = curvb.pBufferData+curvb.nCount;
VertexGPU* p = curvb.pBufferData + curvb.nCount;
SET_VERTEX(&p[0], last, curvb);
curvb.nCount++;
@ -632,23 +696,23 @@ void ZeroGS::KickPoint()
void ZeroGS::KickLine()
{
FUNCLOG
assert( gs.primC >= 2 );
assert(gs.primC >= 2);
VB& curvb = vb[prim->ctxt];
if( curvb.bNeedTexCheck )
curvb.FlushTexData();
if( vb[!prim->ctxt].nCount > 0 && vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp )
if (curvb.bNeedTexCheck) curvb.FlushTexData();
if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
{
assert( vb[prim->ctxt].nCount == 0 );
assert(vb[prim->ctxt].nCount == 0);
Flush(!prim->ctxt);
}
curvb.NotifyWrite(2);
int next = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex);
int last = (gs.primIndex+2)%ARRAY_SIZE(gs.gsvertex);
int next = (gs.primIndex + 1) % ARRAY_SIZE(gs.gsvertex);
int last = (gs.primIndex + 2) % ARRAY_SIZE(gs.gsvertex);
VertexGPU* p = curvb.pBufferData+curvb.nCount;
VertexGPU* p = curvb.pBufferData + curvb.nCount;
SET_VERTEX(&p[0], next, curvb);
SET_VERTEX(&p[1], last, curvb);
@ -661,19 +725,20 @@ void ZeroGS::KickLine()
void ZeroGS::KickTriangle()
{
FUNCLOG
assert( gs.primC >= 3 );
assert(gs.primC >= 3);
VB& curvb = vb[prim->ctxt];
if (curvb.bNeedTexCheck) curvb.FlushTexData();
if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
{
assert( vb[prim->ctxt].nCount == 0 );
assert(vb[prim->ctxt].nCount == 0);
Flush(!prim->ctxt);
}
curvb.NotifyWrite(3);
VertexGPU* p = curvb.pBufferData+curvb.nCount;
VertexGPU* p = curvb.pBufferData + curvb.nCount;
SET_VERTEX(&p[0], 0, curvb);
SET_VERTEX(&p[1], 1, curvb);
SET_VERTEX(&p[2], 2, curvb);
@ -688,19 +753,20 @@ void ZeroGS::KickTriangle()
void ZeroGS::KickTriangleFan()
{
FUNCLOG
assert( gs.primC >= 3 );
assert(gs.primC >= 3);
VB& curvb = vb[prim->ctxt];
if (curvb.bNeedTexCheck) curvb.FlushTexData();
if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
{
assert( vb[prim->ctxt].nCount == 0 );
assert(vb[prim->ctxt].nCount == 0);
Flush(!prim->ctxt);
}
curvb.NotifyWrite(3);
VertexGPU* p = curvb.pBufferData+curvb.nCount;
VertexGPU* p = curvb.pBufferData + curvb.nCount;
SET_VERTEX(&p[0], 0, curvb);
SET_VERTEX(&p[1], 1, curvb);
SET_VERTEX(&p[2], 2, curvb);
@ -708,8 +774,8 @@ void ZeroGS::KickTriangleFan()
curvb.nCount += 3;
// add 1 to skip the first vertex
if (gs.primIndex == gs.nTriFanVert)
gs.primIndex = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex);
if (gs.primIndex == gs.nTriFanVert) gs.primIndex = (gs.primIndex + 1) % ARRAY_SIZE(gs.gsvertex);
OUTPUT_VERT(p[0], 0);
OUTPUT_VERT(p[1], 1);
@ -726,34 +792,36 @@ __forceinline void SetKickVertex(VertexGPU *p, Vertex v, int next, const VB& cur
void ZeroGS::KickSprite()
{
FUNCLOG
assert( gs.primC >= 2 );
assert(gs.primC >= 2);
VB& curvb = vb[prim->ctxt];
if (curvb.bNeedTexCheck) curvb.FlushTexData();
if ((vb[!prim->ctxt].nCount > 0) && (vb[prim->ctxt].gsfb.fbp == vb[!prim->ctxt].gsfb.fbp))
{
assert( vb[prim->ctxt].nCount == 0 );
assert(vb[prim->ctxt].nCount == 0);
Flush(!prim->ctxt);
}
curvb.NotifyWrite(6);
int next = (gs.primIndex+1)%ARRAY_SIZE(gs.gsvertex);
int last = (gs.primIndex+2)%ARRAY_SIZE(gs.gsvertex);
int next = (gs.primIndex + 1) % ARRAY_SIZE(gs.gsvertex);
int last = (gs.primIndex + 2) % ARRAY_SIZE(gs.gsvertex);
// sprite is too small and AA shows lines (tek4)
if ( s_AAx )
if (s_AAx)
{
gs.gsvertex[last].x += 4;
if( s_AAy ) gs.gsvertex[last].y += 4;
if (s_AAy) gs.gsvertex[last].y += 4;
}
// might be bad sprite (KH dialog text)
//if( gs.gsvertex[next].x == gs.gsvertex[last].x || gs.gsvertex[next].y == gs.gsvertex[last].y )
//return;
VertexGPU* p = curvb.pBufferData+curvb.nCount;
VertexGPU* p = curvb.pBufferData + curvb.nCount;
SetKickVertex(&p[0], gs.gsvertex[last], next, curvb);
SetKickVertex(&p[3], gs.gsvertex[last], next, curvb);
@ -765,6 +833,7 @@ void ZeroGS::KickSprite()
p[2].x = p[1].x;
SetKickVertex(&p[5], gs.gsvertex[last], last, curvb);
p[5].s = p[0].s;
p[5].x = p[0].x;
@ -798,11 +867,13 @@ void ZeroGS::SetFogColor(u32 fog)
Vector v;
// set it immediately
v.x = (gs.fogcol&0xff)/255.0f;
v.y = ((gs.fogcol>>8)&0xff)/255.0f;
v.z = ((gs.fogcol>>16)&0xff)/255.0f;
// v.x = (gs.fogcol & 0xff) / 255.0f;
// v.y = ((gs.fogcol >> 8) & 0xff) / 255.0f;
// v.z = ((gs.fogcol >> 16) & 0xff) / 255.0f;
v.SetColor(gs.fogcol);
ZZcgSetParameter4fv(g_fparamFogColor, v, "g_fParamFogColor");
}
// }
}
@ -862,7 +933,8 @@ bool IsDirty(u32 highdword, u32 psm, int cld, int cbp)
// do a fast test with MMX
#ifdef _MSC_VER
int storeebx;
__asm {
__asm
{
mov storeebx, ebx
mov edx, dst
mov ecx, src
@ -910,12 +982,14 @@ Continue:
test ebx, 0x10
jz AddEcx
sub ecx, 448 // go back and down one column,
AddEcx:
add ecx, 256 // go to the right block
jne Continue1
add ecx, 256 // skip whole block
Continue1:
add edx, 64
sub ebx, 16
@ -930,7 +1004,7 @@ Return:
// do a fast test with MMX
__asm__(
".intel_syntax\n"
"Start:\n"
"Start:\n"
"movq %%mm0, [%%ecx]\n"
"movq %%mm1, [%%ecx+8]\n"
"pcmpeqd %%mm0, [%%edx]\n"
@ -961,27 +1035,28 @@ Return:
"movb $1, %0\n"
".intel_syntax\n"
"jmp Return\n"
"Continue:\n"
"Continue:\n"
"cmp %%ebx, 16\n"
"jle Return\n"
"test %%ebx, 0x10\n"
"jz AddEcx\n"
"sub %%edx, 448\n" // go back and down one column
"AddEcx:\n"
"AddEcx:\n"
"add %%edx, 256\n" // go to the right block
"cmp %%ebx, 0x90\n"
"jne Continue1\n"
"add %%edx, 256\n" // skip whole block
"Continue1:\n"
"Continue1:\n"
"add %%ecx, 64\n"
"sub %%ebx, 16\n"
"jmp Start\n"
"Return:\n"
"Return:\n"
"emms\n"
".att_syntax\n" : "=m"(bRet) : "c"(dst), "d"(src), "b"(entries) : "eax", "memory");
#endif // _WIN32
return bRet;
return bRet;
}
// cld state:
@ -1001,19 +1076,36 @@ bool ZeroGS::CheckChangeInClut(u32 highdword, u32 psm)
// processing the CLUT after tex0/2 are written
//ZZLog::Error_Log("high == 0x%x; cld == %d", highdword, cld);
switch(cld) {
case 0: return false;
case 1: break;
case 2: break;
case 3: break;
case 4: if (gs.cbp[0] == cbp) return false; break;
case 5: if (gs.cbp[1] == cbp) return false; break;
switch (cld)
{
case 0:
return false;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
if (gs.cbp[0] == cbp) return false;
break;
case 5:
if (gs.cbp[1] == cbp) return false;
break;
//case 4: return gs.cbp[0] != cbp;
//case 5: return gs.cbp[1] != cbp;
// default: load
default: break;
default:
break;
}
return IsDirty(highdword, psm, cld, cbp);
@ -1023,26 +1115,40 @@ void ZeroGS::texClutWrite(int ctx)
{
FUNCLOG
s_bTexFlush = 0;
if (g_bIsLost) return;
tex0Info& tex0 = vb[ctx].tex0;
assert( PSMT_ISCLUT(tex0.psm) );
assert(PSMT_ISCLUT(tex0.psm));
// processing the CLUT after tex0/2 are written
switch(tex0.cld)
switch (tex0.cld)
{
case 0: return;
case 1: break; // tex0.cld is usually 1.
case 2: gs.cbp[0] = tex0.cbp; break;
case 3: gs.cbp[1] = tex0.cbp; break;
case 0:
return;
case 1:
break; // tex0.cld is usually 1.
case 2:
gs.cbp[0] = tex0.cbp;
break;
case 3:
gs.cbp[1] = tex0.cbp;
break;
case 4:
if (gs.cbp[0] == tex0.cbp) return;
gs.cbp[0] = tex0.cbp;
break;
case 5:
if (gs.cbp[1] == tex0.cbp) return;
gs.cbp[1] = tex0.cbp;
break;
default: //ZZLog::Debug_Log("cld isn't 0-5!");
break;
}
@ -1057,10 +1163,11 @@ void ZeroGS::texClutWrite(int ctx)
{
// 16bit psm
// eggomania uses non16bit textures for csm2
case PSMCT16:
{
u16* src = (u16*)g_pbyGSMemory + tex0.cbp*128;
u16 *dst = (u16*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0));
u16* src = (u16*)g_pbyGSMemory + tex0.cbp * 128;
u16 *dst = (u16*)(g_pbyGSClut + 32 * (tex0.csa & 15) + (tex0.csa >= 16 ? 2 : 0));
for (int i = 0; i < entries; ++i)
{
@ -1068,15 +1175,16 @@ void ZeroGS::texClutWrite(int ctx)
dst += 2;
// check for wrapping
if (((u32)(uptr)dst & 0x3ff) == 0) dst = (u16*)(g_pbyGSClut+2);
if (((u32)(uptr)dst & 0x3ff) == 0) dst = (u16*)(g_pbyGSClut + 2);
}
break;
}
case PSMCT16S:
{
u16* src = (u16*)g_pbyGSMemory + tex0.cbp*128;
u16 *dst = (u16*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0));
u16* src = (u16*)g_pbyGSMemory + tex0.cbp * 128;
u16 *dst = (u16*)(g_pbyGSClut + 32 * (tex0.csa & 15) + (tex0.csa >= 16 ? 2 : 0));
for (int i = 0; i < entries; ++i)
{
@ -1084,7 +1192,8 @@ void ZeroGS::texClutWrite(int ctx)
dst += 2;
// check for wrapping
if (((u32)(uptr)dst & 0x3ff) == 0) dst = (u16*)(g_pbyGSClut+2);
if (((u32)(uptr)dst & 0x3ff) == 0) dst = (u16*)(g_pbyGSClut + 2);
}
break;
}
@ -1092,14 +1201,15 @@ void ZeroGS::texClutWrite(int ctx)
case PSMCT32:
case PSMCT24:
{
u32* src = (u32*)g_pbyGSMemory + tex0.cbp*64;
u32 *dst = (u32*)(g_pbyGSClut+64*tex0.csa);
u32* src = (u32*)g_pbyGSMemory + tex0.cbp * 64;
u32 *dst = (u32*)(g_pbyGSClut + 64 * tex0.csa);
// check if address exceeds src
if( src+getPixelAddress32_0(gs.clut.cou+entries-1, gs.clut.cov, gs.clut.cbw) >= (u32*)g_pbyGSMemory + 0x00100000 )
if (src + getPixelAddress32_0(gs.clut.cou + entries - 1, gs.clut.cov, gs.clut.cbw) >= (u32*)g_pbyGSMemory + 0x00100000)
ZZLog::Error_Log("texClutWrite out of bounds.");
else
for(int i = 0; i < entries; ++i)
for (int i = 0; i < entries; ++i)
{
*dst = src[getPixelAddress32_0(gs.clut.cou+i, gs.clut.cov, gs.clut.cbw)];
dst++;
@ -1120,19 +1230,18 @@ void ZeroGS::texClutWrite(int ctx)
{
case PSMCT24:
case PSMCT32:
if( entries == 16 )
WriteCLUT_T32_I4_CSM1((u32*)(g_pbyGSMemory + tex0.cbp*256), (u32*)(g_pbyGSClut+64*tex0.csa));
if (entries == 16)
WriteCLUT_T32_I4_CSM1((u32*)(g_pbyGSMemory + tex0.cbp*256), (u32*)(g_pbyGSClut + 64*tex0.csa));
else
WriteCLUT_T32_I8_CSM1((u32*)(g_pbyGSMemory + tex0.cbp*256), (u32*)(g_pbyGSClut+64*tex0.csa));
WriteCLUT_T32_I8_CSM1((u32*)(g_pbyGSMemory + tex0.cbp*256), (u32*)(g_pbyGSClut + 64*tex0.csa));
break;
default:
if( entries == 16 )
WriteCLUT_T16_I4_CSM1((u32*)(g_pbyGSMemory + 256 * tex0.cbp), (u32*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0)));
if (entries == 16)
WriteCLUT_T16_I4_CSM1((u32*)(g_pbyGSMemory + 256 * tex0.cbp), (u32*)(g_pbyGSClut + 32*(tex0.csa&15) + (tex0.csa >= 16 ? 2 : 0)));
else // sse2 for 256 is more complicated, so use regular
WriteCLUT_T16_I8_CSM1_c((u32*)(g_pbyGSMemory + 256 * tex0.cbp), (u32*)(g_pbyGSClut+32*(tex0.csa&15)+(tex0.csa>=16?2:0)));
WriteCLUT_T16_I8_CSM1_c((u32*)(g_pbyGSMemory + 256 * tex0.cbp), (u32*)(g_pbyGSClut + 32*(tex0.csa&15) + (tex0.csa >= 16 ? 2 : 0)));
break;
}
}
}

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,11 +74,17 @@ 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) {
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;
@ -81,11 +92,11 @@ int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompr
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,22 +104,27 @@ int inf(char *src, char *dst, int bytes_to_decompress, int maximum_after_decompr
void zerr(int ret)
{
fputs("zpipe: ", stderr);
switch (ret) {
switch (ret)
{
case Z_ERRNO:
if (ferror(stdin))
fputs("error reading stdin\n", stderr);
if (ferror(stdout))
fputs("error writing stdout\n", stderr);
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);
}