diff --git a/cmake/BuildParameters.cmake b/cmake/BuildParameters.cmake
index 542af6712f..52e33e63a1 100644
--- a/cmake/BuildParameters.cmake
+++ b/cmake/BuildParameters.cmake
@@ -8,6 +8,7 @@
# Use soundtouch internal lib: -DFORCE_INTERNAL_SOUNDTOUCH=TRUE
# Use zlib internal lib: -DFORCE_INTERNAL_ZLIB=TRUE
# Use sdl1.3 internal lib: -DFORCE_INTERNAL_SDL=TRUE # Not supported yet
+# Use GLSL API(else NVIDIA_CG): -DGLSL_API=TRUE
### GCC optimization options
# control C flags : -DUSER_CMAKE_C_FLAGS="cflags"
@@ -183,3 +184,10 @@ if(PACKAGE_MODE)
# Compile all source codes with these 2 defines
add_definitions(-DPLUGIN_DIR_COMPILATION=${PLUGIN_DIR} -DGAMEINDEX_DIR_COMPILATION=${GAMEINDEX_DIR})
endif(PACKAGE_MODE)
+
+#-------------------------------------------------------------------------------
+# Select nvidia cg shader api by default
+#-------------------------------------------------------------------------------
+if(NOT DEFINED FORCE_INTERNAL_SOUNDTOUCH)
+ set(GLSL_API FALSE)
+endif(NOT DEFINED FORCE_INTERNAL_SOUNDTOUCH)
diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake
index 6c776f100d..da39519c89 100644
--- a/cmake/SearchForStuff.cmake
+++ b/cmake/SearchForStuff.cmake
@@ -53,7 +53,9 @@ if(NOT FORCE_INTERNAL_ZLIB)
endif(NOT FORCE_INTERNAL_ZLIB)
## Use pcsx2 package to find module
-include(FindCg)
+if(NOT GLSL_API)
+ include(FindCg)
+endif(NOT GLSL_API)
include(FindGlew)
include(FindLibc)
include(FindPortAudio)
diff --git a/cmake/SelectPcsx2Plugins.cmake b/cmake/SelectPcsx2Plugins.cmake
index 88bb76597e..4796a5344b 100644
--- a/cmake/SelectPcsx2Plugins.cmake
+++ b/cmake/SelectPcsx2Plugins.cmake
@@ -6,11 +6,15 @@ set(msg_dep_pcsx2 "check these libraries -> wxWidgets (>=2.8.10), gtk2 (>=
set(msg_dep_cdvdiso "check these libraries -> bzip2 (>=1.0.5), gtk2 (>=2.16)")
set(msg_dep_zerogs "check these libraries -> glew (>=1.5), opengl, X11, nvidia-cg-toolkit (>=2.1)")
set(msg_dep_gsdx "check these libraries -> opengl, X11, pcsx2 SDL")
-set(msg_dep_zzogl "check these libraries -> glew (>=1.5), jpeg (>=6.2), opengl, X11, nvidia-cg-toolkit (>=2.1), pcsx2 common libs")
set(msg_dep_onepad "check these libraries -> sdl (>=1.2)")
set(msg_dep_zeropad "check these libraries -> sdl (>=1.2)")
set(msg_dep_spu2x "check these libraries -> soundtouch (>=1.5), alsa, portaudio (>=1.9), pcsx2 common libs")
set(msg_dep_zerospu2 "check these libraries -> soundtouch (>=1.5), alsa")
+if(GLSP_API)
+ set(msg_dep_zzogl "check these libraries -> glew (>=1.5), jpeg (>=6.2), opengl, X11, pcsx2 common libs")
+else(GLSP_API)
+ set(msg_dep_zzogl "check these libraries -> glew (>=1.5), jpeg (>=6.2), opengl, X11, nvidia-cg-toolkit (>=2.1), pcsx2 common libs")
+endif(GLSP_API)
#-------------------------------------------------------------------------------
# Pcsx2 core & common libs
@@ -153,17 +157,17 @@ endif(GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND CG_FOUND)
# requires: -GLEW
# -OpenGL
# -X11
-# -CG
+# -CG (only with cg build
# -JPEG
# -common_libs
#---------------------------------------
-if(GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND CG_FOUND AND JPEG_FOUND AND common_libs)
+if((GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND JPEG_FOUND AND common_libs) AND (CG_FOUND OR GLSL_API))
set(zzogl TRUE)
-else(GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND CG_FOUND AND JPEG_FOUND AND common_libs)
+else((GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND JPEG_FOUND AND common_libs) AND (CG_FOUND OR GLSL_API))
set(zzogl FALSE)
message(STATUS "Skip build of zzogl: miss some dependencies")
message(STATUS "${msg_dep_zzogl}")
-endif(GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND CG_FOUND AND JPEG_FOUND AND common_libs)
+endif((GLEW_FOUND AND OPENGL_FOUND AND X11_FOUND AND JPEG_FOUND AND common_libs) AND (CG_FOUND OR GLSL_API))
#---------------------------------------
#---------------------------------------
diff --git a/pcsx2-codeblocks.workspace b/pcsx2-codeblocks.workspace
index c5d3652b6f..9390014171 100644
--- a/pcsx2-codeblocks.workspace
+++ b/pcsx2-codeblocks.workspace
@@ -27,7 +27,7 @@
-
+
diff --git a/plugins/zzogl-pg/opengl/CMakeLists.txt b/plugins/zzogl-pg/opengl/CMakeLists.txt
index c8bed7a170..5c40f84e65 100644
--- a/plugins/zzogl-pg/opengl/CMakeLists.txt
+++ b/plugins/zzogl-pg/opengl/CMakeLists.txt
@@ -45,6 +45,14 @@ if(CMAKE_BUILD_TYPE STREQUAL Release)
add_definitions(${CommonFlags} ${OptimizationFlags} -W)
endif(CMAKE_BUILD_TYPE STREQUAL Release)
+# Select the shader API
+if(GLSL_API)
+ add_definitions(-DGLSL_API)
+else(GLSL_API)
+ add_definitions(-DNVIDIA_CG_API)
+endif(GLSL_API)
+
+
# zzogl sources
set(zzoglSources
GifTransfer.cpp
@@ -54,17 +62,17 @@ set(zzoglSources
GSmain.cpp
HostMemory.cpp
Mem.cpp
- # memcpy_amd.cpp
Mem_Swizzle.cpp
Mem_Tables.cpp
Profile.cpp
rasterfont.cpp
- NewRegs.cpp
Regs.cpp
targets.cpp
- x86.cpp
zerogs.cpp
zpipe.cpp
+ ZZDepthTargets.cpp
+ ZZMemoryTargets.cpp
+ ZZRenderTargets.cpp
ZZClut.cpp
ZZHacks.cpp
ZZKeyboard.cpp
@@ -74,8 +82,10 @@ set(zzoglSources
ZZoglCRTC.cpp
ZZoglFlush.cpp
ZZoglFlushHack.cpp
+ ZZoglMem.cpp
ZZoglSave.cpp
ZZoglShaders.cpp
+ ZZoglShadersGLSL.cpp
ZZoglShoots.cpp
ZZoglVB.cpp
)
@@ -94,7 +104,6 @@ set(zzoglHeaders
Mem_Transmit.h
Profile.h
rasterfont.h
- NewRegs.h
Regs.h
targets.h
Util.h
@@ -102,21 +111,19 @@ set(zzoglHeaders
zerogs.h
zpipe.h
ZZClut.h
+ ZZoglFlush.h
ZZGl.h
ZZHacks.h
ZZoglDrawing.h
ZZLog.h
ZZoglCRTC.h
ZZoglMath.h
+ ZZoglMem.h
ZZoglShaders.h
ZZoglShoots.h
ZZoglVB.h
)
-# zzogl S sources
-set(zzoglSSources
- x86-32.S)
-
# zzogl shader sources
set(zzoglShaderSources
ctx0/ps2hw_ctx.fx
@@ -131,9 +138,6 @@ set(zzoglLinuxSources
set(zzoglLinuxHeaders
Linux/Linux.h)
-# change language of .S-files to c++
-set_source_files_properties(${zzoglSSources} PROPERTIES LANGUAGE CXX)
-
# add additional include directories
include_directories(.
Linux)
@@ -142,7 +146,6 @@ include_directories(.
add_library(${Output} SHARED
${zzoglSources}
${zzoglHeaders}
- ${zzoglSSources}
${zzoglShaderSources}
${zzoglLinuxSources}
${zzoglLinuxHeaders})
@@ -154,7 +157,9 @@ set_target_properties(${Output} PROPERTIES COMPILE_DEFINITIONS USE_GSOPEN2)
target_link_libraries(${Output} Utilities)
# link target with Cg
-target_link_libraries(${Output} ${CG_LIBRARIES})
+if(NOT GLSP_API)
+ target_link_libraries(${Output} ${CG_LIBRARIES})
+endif(NOT GLSP_API)
# link target with glew
target_link_libraries(${Output} ${GLEW_LIBRARY})
@@ -183,10 +188,18 @@ endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
if(PACKAGE_MODE)
install(TARGETS ${Output} DESTINATION ${PLUGIN_DIR})
- install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${PLUGIN_DIR})
+ if(GLSL_API)
+ install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.glsl DESTINATION ${PLUGIN_DIR})
+ else(GLSL_API)
+ install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${PLUGIN_DIR})
+ endif(GLSL_API)
else(PACKAGE_MODE)
install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
- install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
+ if(GLSL_API)
+ install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
+ else(GLSL_API)
+ install(FILES ${PROJECT_SOURCE_DIR}/plugins/zzogl-pg/opengl/ps2hw.dat DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins)
+ endif(GLSL_API)
endif(PACKAGE_MODE)
################################### Replay Loader
diff --git a/plugins/zzogl-pg/opengl/GLWinX11.cpp b/plugins/zzogl-pg/opengl/GLWinX11.cpp
index 0730acc214..764cb9dfc3 100644
--- a/plugins/zzogl-pg/opengl/GLWinX11.cpp
+++ b/plugins/zzogl-pg/opengl/GLWinX11.cpp
@@ -198,13 +198,24 @@ void GLWindow::CreateContextGL()
GLXFBConfig *framebuffer_config = glXChooseFBConfig(glDisplay, DefaultScreen(glDisplay), NULL, &fbcount);
if (!framebuffer_config or !fbcount) return;
+#if 1
// At least create a 3.0 context with compatibility profile
int attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
+ // GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0
};
+#else
+ // Create a 3.2 core context without compatibility profile
+ int attribs[] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
+ GLX_CONTEXT_MINOR_VERSION_ARB, 2,
+ GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ 0
+ };
+#endif
GLXContext context_temp = glXCreateContextAttribsARB(glDisplay, framebuffer_config[0], NULL, true, attribs);
if (context_temp) {
ZZLog::Error_Log("Create a 3.0 opengl context");
diff --git a/plugins/zzogl-pg/opengl/GS.h b/plugins/zzogl-pg/opengl/GS.h
index 8bded3f4cc..04052bda1f 100644
--- a/plugins/zzogl-pg/opengl/GS.h
+++ b/plugins/zzogl-pg/opengl/GS.h
@@ -21,7 +21,7 @@
#define __GS_H__
-#define USE_OLD_REGS
+#define ZZNORMAL_MEMORY
#include "Util.h"
#include "GifTransfer.h"
@@ -39,6 +39,8 @@ extern float fFPS;
extern int g_LastCRC;
+#define VB_NUMBUFFERS 512 // number of vbo buffer allocated
+
struct Vector_16F
{
u16 x, y, z, w;
@@ -132,21 +134,22 @@ extern GSconf conf;
// PSM values
// PSM types == Texture Storage Format
-enum PSM_value
-{
- PSMCT32 = 0, // 00 0000
- PSMCT24 = 1, // 00 0001
- PSMCT16 = 2, // 00 0010
- PSMCT16S = 10, // 00 1010
- PSMT8 = 19, // 01 0011
- PSMT4 = 20, // 01 0100
- PSMT8H = 27, // 01 1011
- PSMT4HL = 36, // 10 0100
- PSMT4HH = 44, // 10 1100
- PSMT32Z = 48, // 11 0000
- PSMT24Z = 49, // 11 0001
- PSMT16Z = 50, // 11 0010
- PSMT16SZ = 58, // 11 1010
+enum PSM_value{
+ PSMCT32 = 0, // 000000
+ PSMCT24 = 1, // 000001
+ PSMCT16 = 2, // 000010
+ PSMCT16S = 10, // 001010
+ PSMT8 = 19, // 010011
+ PSMT4 = 20, // 010100
+ PSMT8H = 27, // 011011
+ PSMT4HL = 36, // 100100
+ PSMT4HH = 44, // 101100
+ PSMT32Z = 48, // 110000
+ PSMT24Z = 49, // 110001
+ PSMT16Z = 50, // 110010
+ PSMT16SZ = 58, // 111010
+
+ PSMT_BAD_PSM = 63 // for every unknown psm.
};
// Check target bit mode. PSMCT32 and 32Z return 0, 24 and 24Z - 1
@@ -461,7 +464,6 @@ typedef struct
{
u16 aem;
u8 ta[2];
- float fta[2];
} texaInfo;
typedef struct
@@ -503,6 +505,14 @@ typedef struct
int fba;
} fbaInfo;
+enum transfer_types
+{
+ XFER_HOST_TO_LOCAL = 0,
+ XFER_LOCAL_TO_HOST = 1,
+ XFER_LOCAL_TO_LOCAL = 2,
+ XFER_DEACTIVATED = 3
+};
+
typedef struct
{
Vertex gsvertex[4]; // circular buffer that contains the vertex
@@ -537,15 +547,20 @@ typedef struct
texaInfo texa;
trxposInfo trxpos, trxposnew;
- int imageWtemp, imageHtemp;
-
int imageTransfer;
- int imageWnew, imageHnew, imageX, imageY, imageEndX, imageEndY;
+ bool transferring;
+
+ Point image, imageEnd;
+ Size imageNew, imageTemp;
pathInfo path[4];
GIFRegDIMX dimx;
GSMemory mem;
GSClut clut_buffer;
+
+ // Subject to change.
+ int vsync, interlace;
+
int primNext(int inc = 1)
{
// Note: ArraySize(gsvertex) == 2^n => modulo is replaced by an and instruction
@@ -615,7 +630,7 @@ static __forceinline u32 RGBA16to32(u16 c)
(((c) & 0x8000) ? 0xff000000 : 0);
}
-#if 0
+#ifndef ZZNORMAL_MEMORY
// converts float16 [0,1] to BYTE [0,255] (assumes value is in range, otherwise will take lower 8bits)
// f is a u16
static __forceinline u16 Float16ToBYTE(u16 f)
@@ -984,4 +999,39 @@ inline void CluttingForFlushedTex(tex0Info* tex0, u32 Data, int ictx)
#define CPSM_CSA_BITMASK 0x1f780000
#define CPSM_CSA_NOTMASK 0xe0870000
+// I'll find a good place for these later.
+
+extern PSM_value PSM_value_Table[64];
+extern bool allowed_psm[256]; // in ZZoglMem.cpp.cpp
+inline void FillAlowedPsnTable() {
+
+ allowed_psm[PSMCT32] = true;
+ allowed_psm[PSMCT24] = true;
+ allowed_psm[PSMCT16] = true;
+ allowed_psm[PSMCT16S] = true;
+ allowed_psm[PSMT8] = true;
+ allowed_psm[PSMT4] = true;
+ allowed_psm[PSMT8H] = true;
+ allowed_psm[PSMT4HH] = true;
+ allowed_psm[PSMT4HL] = true;
+ allowed_psm[PSMT32Z] = true;
+ allowed_psm[PSMT24Z] = true;
+ allowed_psm[PSMT16Z] = true;
+ allowed_psm[PSMT16SZ] = true;
+
+ PSM_value_Table[PSMCT32] = PSMCT32;
+ PSM_value_Table[PSMCT24] = PSMCT24;
+ PSM_value_Table[PSMCT16] = PSMCT16;
+ PSM_value_Table[PSMCT16S] = PSMCT16S;
+ PSM_value_Table[PSMT8] = PSMT8;
+ PSM_value_Table[PSMT4] = PSMT4;
+ PSM_value_Table[PSMT8H] = PSMT8H;
+ PSM_value_Table[PSMT4HH] = PSMT4HH;
+ PSM_value_Table[PSMT4HL] = PSMT4HL;
+ PSM_value_Table[PSMT32Z] = PSMT32Z;
+ PSM_value_Table[PSMT24Z] = PSMT24Z;
+ PSM_value_Table[PSMT16Z] = PSMT16Z;
+ PSM_value_Table[PSMT16SZ] = PSMT16SZ;
+};
+
#endif
diff --git a/plugins/zzogl-pg/opengl/GSmain.cpp b/plugins/zzogl-pg/opengl/GSmain.cpp
index af8a59173e..f92417edab 100644
--- a/plugins/zzogl-pg/opengl/GSmain.cpp
+++ b/plugins/zzogl-pg/opengl/GSmain.cpp
@@ -22,6 +22,7 @@
#include "Profile.h"
#include "GLWin.h"
#include "ZZoglFlushHack.h"
+#include "ZZoglShaders.h"
using namespace std;
@@ -82,7 +83,7 @@ extern int ZZSave(s8* pbydata);
extern bool ZZLoad(s8* pbydata);
// switches the render target to the real target, flushes the current render targets and renders the real image
-extern void RenderCRTC(int interlace);
+extern void RenderCRTC();
#if defined(_WIN32) && defined(_DEBUG)
HANDLE g_hCurrentThread = NULL;
@@ -91,37 +92,37 @@ HANDLE g_hCurrentThread = NULL;
extern int VALIDATE_THRESH;
extern u32 TEXDESTROY_THRESH;
-u32 CALLBACK PS2EgetLibType()
+EXPORT_C_(u32) PS2EgetLibType()
{
return PS2E_LT_GS;
}
-char* CALLBACK PS2EgetLibName()
+EXPORT_C_(char*) PS2EgetLibName()
{
return libraryName;
}
-u32 CALLBACK PS2EgetLibVersion2(u32 type)
+EXPORT_C_(u32) PS2EgetLibVersion2(u32 type)
{
return (zgsversion << 16) | (zgsrevision << 8) | zgsbuild | (zgsminor << 24);
}
-void CALLBACK GSsetBaseMem(void* pmem)
+EXPORT_C_(void) GSsetBaseMem(void* pmem)
{
g_pBasePS2Mem = (u8*)pmem;
}
-void CALLBACK GSsetSettingsDir(const char* dir)
+EXPORT_C_(void) GSsetSettingsDir(const char* dir)
{
s_strIniPath = (dir == NULL) ? wxString(L"inis") : wxString(dir, wxConvFile);
}
-void CALLBACK GSsetLogDir(const char* dir)
+EXPORT_C_(void) GSsetLogDir(const char* dir)
{
ZZLog::SetDir(dir);
}
-void CALLBACK GSsetGameCRC(int crc, int options)
+EXPORT_C_(void) GSsetGameCRC(int crc, int options)
{
// build a list of function pointer for GetSkipCount (SkipDraw)
static GetSkipCount GSC_list[NUMBER_OF_TITLES];
@@ -217,7 +218,7 @@ void CALLBACK GSsetGameCRC(int crc, int options)
ListHacks();
}
-void CALLBACK GSsetFrameSkip(int frameskip)
+EXPORT_C_(void) GSsetFrameSkip(int frameskip)
{
FUNCLOG
s_frameskipping |= frameskip;
@@ -232,7 +233,7 @@ void CALLBACK GSsetFrameSkip(int frameskip)
}
}
-void CALLBACK GSreset()
+EXPORT_C_(void) GSreset()
{
FUNCLOG
@@ -242,11 +243,11 @@ void CALLBACK GSreset()
gs.prac = 1;
prim = &gs._prim[0];
- gs.imageTransfer = -1;
+ gs.transferring = false;
gs.q = 1;
}
-void CALLBACK GSgifSoftReset(u32 mask)
+EXPORT_C_(void) GSgifSoftReset(u32 mask)
{
FUNCLOG
@@ -254,11 +255,11 @@ void CALLBACK GSgifSoftReset(u32 mask)
if (mask & 2) memset(&gs.path[1], 0, sizeof(gs.path[1]));
if (mask & 4) memset(&gs.path[2], 0, sizeof(gs.path[2]));
- gs.imageTransfer = -1;
+ gs.transferring = false;
gs.q = 1;
}
-s32 CALLBACK GSinit()
+EXPORT_C_(s32) GSinit()
{
FUNCLOG
@@ -281,7 +282,7 @@ __forceinline void InitMisc()
ResetRegs();
}
-s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread)
+EXPORT_C_(s32) GSopen(void *pDsp, char *Title, int multithread)
{
FUNCLOG
@@ -337,32 +338,34 @@ EXPORT_C_(s32) GSopen2( void* pDsp, u32 flags )
}
#endif
-void CALLBACK GSshutdown()
+EXPORT_C_(void) GSshutdown()
{
FUNCLOG
ZZLog::Close();
}
-void CALLBACK GSclose()
+EXPORT_C_(void) GSclose()
{
FUNCLOG
ZZDestroy();
GLWin.CloseWindow();
+ // Free alocated memory. We could close plugin without closing pcsx2, so we SHOULD free all allocated resources
+ ZZshExitCleaning();
SaveStateFile = NULL;
SaveStateExists = true; // default value
g_LastCRC = 0;
}
-void CALLBACK GSirqCallback(void (*callback)())
+EXPORT_C_(void) GSirqCallback(void (*callback)())
{
FUNCLOG
GSirq = callback;
}
-void CALLBACK GSwriteCSR(u32 write)
+EXPORT_C_(void) GSwriteCSR(u32 write)
{
FUNCLOG
@@ -373,7 +376,7 @@ void CALLBACK GSwriteCSR(u32 write)
#define access _access
#endif
-void CALLBACK GSchangeSaveState(int newstate, const char* filename)
+EXPORT_C_(void) GSchangeSaveState(int newstate, const char* filename)
{
FUNCLOG
@@ -428,7 +431,7 @@ static bool get_snapshot_filename(char *filename, char* path, const char* extens
return true;
}
-void CALLBACK GSmakeSnapshot(char *path)
+EXPORT_C_(void) GSmakeSnapshot(char *path)
{
FUNCLOG
@@ -474,7 +477,16 @@ static __forceinline void SetGSTitle()
GLWin.SetTitle(strtitle);
}
-void CALLBACK GSvsync(int interlace)
+// This isn't implemented for some reason? Adding a field for it for the moment, till I get a chance to look closer.
+EXPORT_C_(void) GSsetVsync(int enabled)
+{
+ FUNCLOG
+
+ ZZLog::Debug_Log("Setting VSync to 0x%x.", enabled);
+ gs.vsync = enabled;
+}
+
+EXPORT_C_(void) GSvsync(int current_interlace)
{
FUNCLOG
@@ -506,8 +518,9 @@ void CALLBACK GSvsync(int interlace)
g_nRealFrame++;
- // !interlace? Hmmm... Fixme.
- RenderCRTC(!interlace);
+ // The value passed seems to either be 0 or 0x2000, and we want 0 or 1. Perhaps !! would be better...
+ gs.interlace = !current_interlace;
+ RenderCRTC();
GLWin.ProcessEvents();
@@ -559,7 +572,7 @@ void CALLBACK GSvsync(int interlace)
}
-void CALLBACK GSreadFIFO(u64 *pMem)
+EXPORT_C_(void) GSreadFIFO(u64 *pMem)
{
FUNCLOG
@@ -571,7 +584,7 @@ void CALLBACK GSreadFIFO(u64 *pMem)
TransferLocalHost((u32*)pMem, 1);
}
-void CALLBACK GSreadFIFO2(u64 *pMem, int qwc)
+EXPORT_C_(void) GSreadFIFO2(u64 *pMem, int qwc)
{
FUNCLOG
@@ -583,7 +596,7 @@ void CALLBACK GSreadFIFO2(u64 *pMem, int qwc)
TransferLocalHost((u32*)pMem, qwc);
}
-int CALLBACK GSsetupRecording(int start, void* pData)
+EXPORT_C_(int) GSsetupRecording(int start, void* pData)
{
FUNCLOG
@@ -595,7 +608,7 @@ int CALLBACK GSsetupRecording(int start, void* pData)
return 1;
}
-s32 CALLBACK GSfreeze(int mode, freezeData *data)
+EXPORT_C_(s32) GSfreeze(int mode, freezeData *data)
{
FUNCLOG
diff --git a/plugins/zzogl-pg/opengl/GifTransfer.cpp b/plugins/zzogl-pg/opengl/GifTransfer.cpp
index f8be40629b..7c42c9a48e 100644
--- a/plugins/zzogl-pg/opengl/GifTransfer.cpp
+++ b/plugins/zzogl-pg/opengl/GifTransfer.cpp
@@ -27,7 +27,7 @@ static int path1_count = 0;
static int nPath3Hack = 0;
-void CALLBACK GSgetLastTag(u64* ptag)
+EXPORT_C_(void) GSgetLastTag(u64* ptag)
{
FUNCLOG
@@ -165,32 +165,36 @@ template void _GSgifTransfer(const u32 *pMem, u32 size)
{
int len = min(size, path->nloop);
//ZZLog::Error_Log("GIF_FLG_IMAGE(%d)=%d", gs.imageTransfer, len);
-
- switch (gs.imageTransfer)
+
+ if (gs.transferring)
{
- case 0:
- TransferHostLocal(pMem, len * 4);
- break;
+ switch (gs.imageTransfer)
+ {
+ case XFER_HOST_TO_LOCAL:
+ TransferHostLocal(pMem, len * 4);
+ break;
- case 1:
- // This can't happen; downloads can not be started or performed as part of
- // a GIFtag operation. They're an entirely separate process that can only be
- // done through the ReverseFIFO transfer (aka ReadFIFO). --air
- assert(0);
- //TransferLocalHost(pMem, len);
- break;
+ case XFER_LOCAL_TO_HOST:
+ // This can't happen; downloads can not be started or performed as part of
+ // a GIFtag operation. They're an entirely separate process that can only be
+ // done through the ReverseFIFO transfer (aka ReadFIFO). --air
+ assert(0);
+ //TransferLocalHost(pMem, len);
+ break;
- case 2:
- //TransferLocalLocal();
- break;
+ case XFER_LOCAL_TO_LOCAL:
+ //TransferLocalLocal();
+ break;
- case 3:
- //assert(0);
- break;
+ case XFER_DEACTIVATED:
+ //assert(0);
+ break;
- default:
- //assert(0);
- break;
+ default:
+ //assert(0);
+ break;
+ }
+
}
pMem += len * 4;
@@ -236,7 +240,7 @@ template void _GSgifTransfer(const u32 *pMem, u32 size)
}
}
-void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr)
+EXPORT_C_(void) GSgifTransfer1(u32 *pMem, u32 addr)
{
FUNCLOG
@@ -250,7 +254,7 @@ void CALLBACK GSgifTransfer1(u32 *pMem, u32 addr)
_GSgifTransfer<0>((u32*)((u8*)pMem + addr), (0x4000 - addr) / 16);
}
-void CALLBACK GSgifTransfer2(u32 *pMem, u32 size)
+EXPORT_C_(void) GSgifTransfer2(u32 *pMem, u32 size)
{
FUNCLOG
@@ -259,7 +263,7 @@ void CALLBACK GSgifTransfer2(u32 *pMem, u32 size)
_GSgifTransfer<1>(const_cast(pMem), size);
}
-void CALLBACK GSgifTransfer3(u32 *pMem, u32 size)
+EXPORT_C_(void) GSgifTransfer3(u32 *pMem, u32 size)
{
FUNCLOG
@@ -268,7 +272,7 @@ void CALLBACK GSgifTransfer3(u32 *pMem, u32 size)
_GSgifTransfer<2>(const_cast(pMem), size);
}
-void CALLBACK GSgifTransfer(const u32 *pMem, u32 size)
+EXPORT_C_(void) GSgifTransfer(const u32 *pMem, u32 size)
{
FUNCLOG
diff --git a/plugins/zzogl-pg/opengl/HostMemory.cpp b/plugins/zzogl-pg/opengl/HostMemory.cpp
index 9b762e9437..78d6100730 100644
--- a/plugins/zzogl-pg/opengl/HostMemory.cpp
+++ b/plugins/zzogl-pg/opengl/HostMemory.cpp
@@ -18,8 +18,6 @@
*/
#include "GS.h"
-#include
-#include
#include
#include "Mem.h"
@@ -117,14 +115,14 @@ void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h
if (PSMT_ISZTEX(psm))
{
- // Somehow, I doubt this code is right. I'll have to look into it. For the moment, I'm keeping it the
- // way it was. --arcum42
-
+ // This still needs an eye kept on it.
const BLOCK& b = m_Blocks[psm];
-
- bw = (bw + b.width - 1) / b.width;
- start = bp * 256 + ((y / b.height) * bw + (x / b.width)) * 0x2000;
- end = bp * 256 + (((y + h - 1) / b.height) * bw + (x + w + b.width - 1) / b.width) * 0x2000;
+ const int x2 = x + w + b.width - 1;
+ const int y2 = y + h - 1;
+ bw = bw / b.width;
+
+ start = (bp + ((y / b.height) * bw + (x / b.width)) * 0x20) * 0x100;
+ end = (bp + ((y2 / b.height) * bw + (x2 / b.width)) * 0x20) * 0x100;
return;
}
@@ -139,46 +137,101 @@ void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h
}
else
{
- // This is what it used to do, which doesn't seem right.
- // Keeping it for reference, in case removing it breaks anything.
+ start /= 2;
+ end /= 2;
+ }
+}
+
+// Same as GetRectMemAddress, except that we know x & y are zero, so it's simplified a bit.
+void GetRectMemAddressZero(int& start, int& end, int psm, int w, int h, int bp, int bw)
+{
+ FUNCLOG
+ u32 bits = 0;
+
+ if (m_Blocks[psm].bpp == 0)
+ {
+ ZZLog::Error_Log("ZeroGS: Bad psm 0x%x.", psm);
+ start = 0;
+ end = MEMORY_END;
+ return;
+ }
+
+ if (PSMT_ISZTEX(psm))
+ {
+ // This still needs an eye kept on it.
+ const BLOCK& b = m_Blocks[psm];
+ const int x2 = w + b.width - 1;
+ const int y2 = h - 1;
+ bw = bw / b.width;
+
+ start = bp * 0x100;
+ end = (bp + ((y2 / b.height) * bw + (x2 / b.width)) * 0x20) * 0x100;
+ return;
+ }
- //int newx = ((x + w - 1 + 31) & ~31) - 1;
- //int newy = ((y + h - 1 + 15) & ~15) - 1;
- //start = getPixelAddress4(x, y, bp, bw) / 2;
- //end = (getPixelAddress4(max(newx, x), max(newy, y), bp, bw) + 2) / 2;
+ bits = PSMT_BITS_NUM(psm);
+ start = getPixelFun[psm](0, 0, bp, bw);
+ end = getPixelFun[psm](w - 1, h - 1, bp, bw) + 1;
+ if (bits > 0)
+ {
+ start *= bits;
+ end *= bits;
+ }
+ else
+ {
start /= 2;
end /= 2;
}
}
+
+void GetRectMemAddress(int& start, int& end, int psm, Point p, Size s, int bp, int bw)
+{
+ GetRectMemAddress(start, end, psm, p.x, p.y, s.w, s.h, bp, bw);
+}
+
+void GetRectMemAddress(int& start, int& end, int psm, int x, int y, Size s, int bp, int bw)
+{
+ GetRectMemAddress(start, end, psm, x, y, s.w, s.h, bp, bw);
+}
+
+void GetRectMemAddressZero(int& start, int& end, int psm, Size s, int bp, int bw)
+{
+ GetRectMemAddressZero(start, end, psm, s.w, s.h, bp, bw);
+}
+
void InitTransferHostLocal()
{
FUNCLOG
#if defined(_DEBUG)
// Xenosaga 1.
- if (gs.trxpos.dx + gs.imageWnew > gs.dstbuf.bw)
- ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0X%x)", gs.trxpos.dx + gs.imageWnew, gs.dstbuf.bw);
+ if (gs.trxpos.dx + gs.imageNew.w > gs.dstbuf.bw)
+ ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0X%x)", gs.trxpos.dx + gs.imageNew.w, gs.dstbuf.bw);
#endif
//bool bHasFlushed = false;
- gs.imageX = gs.trxpos.dx;
- gs.imageY = gs.trxpos.dy;
+ gs.image.x = gs.trxpos.dx;
+ gs.image.y = gs.trxpos.dy;
- gs.imageEndX = gs.imageX + gs.imageWnew;
- gs.imageEndY = gs.imageY + gs.imageHnew;
+ gs.imageEnd.x = gs.image.x + gs.imageNew.w;
+ gs.imageEnd.y = gs.image.y + gs.imageNew.h;
- assert(gs.imageEndX < 2048 && gs.imageEndY < 2048);
+ assert(gs.imageEnd.x < 2048 && gs.imageEnd.y < 2048);
// This needs to be looked in to, since psm should *not* be 63.
// hack! viewful joe
- if (gs.dstbuf.psm == 63) gs.dstbuf.psm = 0;
+ if (gs.dstbuf.psm == 63)
+ {
+ ZZLog::WriteLn("gs.dstbuf.psm set to 0!");
+ gs.dstbuf.psm = 0;
+ }
int start, end;
- GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
+ GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageNew, gs.dstbuf.bp, gs.dstbuf.bw);
if (end > MEMORY_END)
{
@@ -189,7 +242,7 @@ void InitTransferHostLocal()
// MEMORY_END is 0x400000...
ZZLog::Warn_Log("Init host local out of bounds! (end == 0x%x)", end);
- //gs.imageTransfer = -1;
+ //gs.transferring = false;
end = MEMORY_END;
}
@@ -198,17 +251,18 @@ void InitTransferHostLocal()
if (vb[0].nCount > 0) Flush(0);
if (vb[1].nCount > 0) Flush(1);
- //ZZLog::Prim_Log("trans: bp:%x x:%x y:%x w:%x h:%x\n", gs.dstbuf.bp, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew);
+ //ZZLog::Prim_Log("trans: bp:%x x:%x y:%x w:%x h:%x\n", gs.dstbuf.bp, gs.trxpos.dx, gs.trxpos.dy, gs.imageNew.w, gs.imageNew.h);
}
void TransferHostLocal(const void* pbyMem, u32 nQWordSize)
{
FUNCLOG
- int start, end;
-
- GetRectMemAddress(start, end, gs.dstbuf.psm, gs.imageX, gs.imageY, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
+ int start = -1, end = -1;
+ GetRectMemAddress(start, end, gs.dstbuf.psm, gs.image, gs.imageNew, gs.dstbuf.bp, gs.dstbuf.bw);
+
+ if ((start == -1) || (end == -1)) ZZLog::WriteLn("start == %d, end == %d", start, end);
assert(start < gs_imageEnd);
end = gs_imageEnd;
@@ -272,8 +326,8 @@ void TransferHostLocal(const void* pbyMem, u32 nQWordSize)
{
tex0Info t;
t.tbp0 = gs.dstbuf.bp;
- t.tw = gs.imageWnew;
- t.th = gs.imageHnew;
+ t.tw = gs.imageNew.w;
+ t.th = gs.imageNew.h;
t.tbw = gs.dstbuf.bw;
t.psm = gs.dstbuf.psm;
SaveTex(&t, 0);
@@ -285,24 +339,24 @@ void TransferHostLocal(const void* pbyMem, u32 nQWordSize)
void InitTransferLocalHost()
{
FUNCLOG
- assert(gs.trxpos.sx + gs.imageWnew <= 2048 && gs.trxpos.sy + gs.imageHnew <= 2048);
+ assert(gs.trxpos.sx + gs.imageNew.w <= 2048 && gs.trxpos.sy + gs.imageNew.h <= 2048);
#if defined(_DEBUG)
- if (gs.trxpos.sx + gs.imageWnew > gs.srcbuf.bw)
- ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0x%x)", gs.trxpos.sx + gs.imageWnew, gs.srcbuf.bw);
+ if (gs.trxpos.sx + gs.imageNew.w > gs.srcbuf.bw)
+ ZZLog::Debug_Log("Transfer error, width exceeded. (0x%x > 0x%x)", gs.trxpos.sx + gs.imageNew.w, gs.srcbuf.bw);
#endif
- gs.imageX = gs.trxpos.sx;
- gs.imageY = gs.trxpos.sy;
+ gs.image.x = gs.trxpos.sx;
+ gs.image.y = gs.trxpos.sy;
- gs.imageEndX = gs.imageX + gs.imageWnew;
- gs.imageEndY = gs.imageY + gs.imageHnew;
+ gs.imageEnd.x = gs.image.x + gs.imageNew.w;
+ gs.imageEnd.y = gs.image.y + gs.imageNew.h;
s_vTransferCache.resize(0);
int start, end;
- GetRectMemAddress(start, end, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw);
+ GetRectMemAddress(start, end, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageNew, gs.srcbuf.bp, gs.srcbuf.bw);
ResolveInRange(start, end);
}
@@ -316,16 +370,16 @@ void TransferLocalHost(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *pstart)
T* pbuf = (T*)pbyMem;
u32 nSize = nQWordSize * 16 / sizeof(T);
- for (; i < gs.imageEndY; ++i)
+ for (; i < gs.imageEnd.y; ++i)
{
- for (; j < gs.imageEndX && nSize > 0; ++j, --nSize)
+ for (; j < gs.imageEnd.x && nSize > 0; ++j, --nSize)
{
*pbuf++ = rp(pstart, j % 2048, i % 2048, gs.srcbuf.bw);
}
- if (j >= gs.imageEndX)
+ if (j >= gs.imageEnd.x)
{
- assert(j == gs.imageEndX);
+ assert(j == gs.imageEnd.x);
j = gs.trxpos.sx;
}
else
@@ -344,9 +398,9 @@ void TransferLocalHost_24(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *psta
u8* pbuf = (u8*)pbyMem;
u32 nSize = nQWordSize * 16 / 3;
- for (; i < gs.imageEndY; ++i)
+ for (; i < gs.imageEnd.y; ++i)
{
- for (; j < gs.imageEndX && nSize > 0; ++j, --nSize)
+ for (; j < gs.imageEnd.x && nSize > 0; ++j, --nSize)
{
u32 p = rp(pstart, j % 2048, i % 2048, gs.srcbuf.bw);
pbuf[0] = (u8)p;
@@ -355,9 +409,9 @@ void TransferLocalHost_24(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *psta
pbuf += 3;
}
- if (j >= gs.imageEndX)
+ if (j >= gs.imageEnd.x)
{
- assert(j == gs.imageEndX);
+ assert(j == gs.imageEnd.x);
j = gs.trxpos.sx;
}
else
@@ -372,34 +426,34 @@ void TransferLocalHost_24(void* pbyMem, u32 nQWordSize, int& x, int& y, u8 *psta
void TransferLocalHost(void* pbyMem, u32 nQWordSize)
{
FUNCLOG
- assert(gs.imageTransfer == 1);
+ assert(gs.imageTransfer == XFER_LOCAL_TO_HOST);
u8* pstart = g_pbyGSMemory + 256 * gs.srcbuf.bp;
switch(PSMT_BITMODE(gs.srcbuf.psm))
{
- case 0:
- TransferLocalHost(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart);
- break;
- case 1:
- TransferLocalHost_24(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart);
- break;
- case 2:
- TransferLocalHost(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart);
- break;
- case 3:
- TransferLocalHost(pbyMem, nQWordSize, gs.imageY, gs.imageX, pstart);
- break;
- default:
- assert(0);
- break;
+ case 0:
+ TransferLocalHost(pbyMem, nQWordSize, gs.image.y, gs.image.x, pstart);
+ break;
+ case 1:
+ TransferLocalHost_24(pbyMem, nQWordSize, gs.image.y, gs.image.x, pstart);
+ break;
+ case 2:
+ TransferLocalHost(pbyMem, nQWordSize, gs.image.y, gs.image.x, pstart);
+ break;
+ case 3:
+ TransferLocalHost(pbyMem, nQWordSize, gs.image.y, gs.image.x, pstart);
+ break;
+ default:
+ assert(0);
+ break;
}
- if (gs.imageY >= gs.imageEndY)
+ if (gs.image.y >= gs.imageEnd.y)
{
- ZZLog::Error_Log("gs.imageY >= gs.imageEndY!");
- assert(gs.imageY == gs.imageEndY);
- gs.imageTransfer = -1;
+ ZZLog::Error_Log("gs.image.y >= gs.imageEnd.y!");
+ assert(gs.image.y == gs.imageEnd.y);
+ gs.transferring = false;
}
}
@@ -411,11 +465,11 @@ __forceinline void _TransferLocalLocal()
u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp * 256;
u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp * 256;
u32 widthlimit = 4;
- u32 maxX = gs.trxpos.sx + gs.imageWnew;
- u32 maxY = gs.trxpos.sy + gs.imageHnew;
+ u32 maxX = gs.trxpos.sx + gs.imageNew.w;
+ u32 maxY = gs.trxpos.sy + gs.imageNew.h;
if (PSMT_BITMODE(gs.srcbuf.psm) == 0) widthlimit = 2;
- if ((gs.imageWnew & widthlimit) != 0) return;
+ if ((gs.imageNew.w & widthlimit) != 0) return;
for(u32 i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; i++, i2++)
{
@@ -447,10 +501,10 @@ __forceinline void _TransferLocalLocal_4()
_getPixelAddress_0 gdp = getPixelFun_0[gs.dstbuf.psm];
u8* pSrcBuf = g_pbyGSMemory + gs.srcbuf.bp * 256;
u8* pDstBuf = g_pbyGSMemory + gs.dstbuf.bp * 256;
- u32 maxX = gs.trxpos.sx + gs.imageWnew;
- u32 maxY = gs.trxpos.sy + gs.imageHnew;
+ u32 maxX = gs.trxpos.sx + gs.imageNew.w;
+ u32 maxY = gs.trxpos.sy + gs.imageNew.h;
- assert((gs.imageWnew % 8) == 0);
+ assert((gs.imageNew.w % 8) == 0);
for(u32 i = gs.trxpos.sy, i2 = gs.trxpos.dy; i < maxY; ++i, ++i2)
{
@@ -498,21 +552,21 @@ void TransferLocalLocal()
FUNCLOG
//ZZLog::Error_Log("I'z in your code, transferring your memory...");
- assert(gs.imageTransfer == 2);
- assert(gs.trxpos.sx + gs.imageWnew < 2048 && gs.trxpos.sy + gs.imageHnew < 2048);
- assert(gs.trxpos.dx + gs.imageWnew < 2048 && gs.trxpos.dy + gs.imageHnew < 2048);
+ assert(gs.imageTransfer == XFER_LOCAL_TO_LOCAL);
+ assert(gs.trxpos.sx + gs.imageNew.w < 2048 && gs.trxpos.sy + gs.imageNew.h < 2048);
+ assert(gs.trxpos.dx + gs.imageNew.w < 2048 && gs.trxpos.dy + gs.imageNew.h < 2048);
assert((gs.srcbuf.psm&0x7) == (gs.dstbuf.psm&0x7));
- if (gs.trxpos.sx + gs.imageWnew > gs.srcbuf.bw)
- ZZLog::Debug_Log("Transfer error, src width exceeded.(0x%x > 0x%x)", gs.trxpos.sx + gs.imageWnew, gs.srcbuf.bw);
+ if (gs.trxpos.sx + gs.imageNew.w > gs.srcbuf.bw)
+ ZZLog::Debug_Log("Transfer error, src width exceeded.(0x%x > 0x%x)", gs.trxpos.sx + gs.imageNew.w, gs.srcbuf.bw);
- if (gs.trxpos.dx + gs.imageWnew > gs.dstbuf.bw)
- ZZLog::Debug_Log("Transfer error, dst width exceeded.(0x%x > 0x%x)", gs.trxpos.dx + gs.imageWnew, gs.dstbuf.bw);
+ if (gs.trxpos.dx + gs.imageNew.w > gs.dstbuf.bw)
+ ZZLog::Debug_Log("Transfer error, dst width exceeded.(0x%x > 0x%x)", gs.trxpos.dx + gs.imageNew.w, gs.dstbuf.bw);
int srcstart, srcend, dststart, dstend;
- GetRectMemAddress(srcstart, srcend, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageWnew, gs.imageHnew, gs.srcbuf.bp, gs.srcbuf.bw);
- GetRectMemAddress(dststart, dstend, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
+ GetRectMemAddress(srcstart, srcend, gs.srcbuf.psm, gs.trxpos.sx, gs.trxpos.sy, gs.imageNew, gs.srcbuf.bp, gs.srcbuf.bw);
+ GetRectMemAddress(dststart, dstend, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageNew, gs.dstbuf.bp, gs.dstbuf.bw);
// resolve the targs
ResolveInRange(srcstart, srcend);
@@ -547,15 +601,15 @@ void TransferLocalLocal()
{
tex0Info t;
t.tbp0 = gs.dstbuf.bp;
- t.tw = gs.imageWnew;
- t.th = gs.imageHnew;
+ t.tw = gs.imageNew.w;
+ t.th = gs.imageNew.h;
t.tbw = gs.dstbuf.bw;
t.psm = gs.dstbuf.psm;
SaveTex(&t, 0);
t.tbp0 = gs.srcbuf.bp;
- t.tw = gs.imageWnew;
- t.th = gs.imageHnew;
+ t.tw = gs.imageNew.w;
+ t.th = gs.imageNew.h;
t.tbw = gs.srcbuf.bw;
t.psm = gs.srcbuf.psm;
SaveTex(&t, 0);
@@ -563,16 +617,4 @@ void TransferLocalLocal()
#endif
}
-
-__forceinline void TerminateLocalHost()
-{
- FUNCLOG
- //ZZLog::Error_Log("Terminate Local Host!");
-}
-
-__forceinline void TerminateHostLocal()
-{
- FUNCLOG
- gs.imageTransfer = -1;
-}
diff --git a/plugins/zzogl-pg/opengl/HostMemory.h b/plugins/zzogl-pg/opengl/HostMemory.h
index e9217685d1..a49fe1eb81 100644
--- a/plugins/zzogl-pg/opengl/HostMemory.h
+++ b/plugins/zzogl-pg/opengl/HostMemory.h
@@ -96,7 +96,10 @@ inline u8* _MemoryAddress(int x)
}
extern void GetRectMemAddress(int& start, int& end, int psm, int x, int y, int w, int h, int bp, int bw);
-
+extern void GetRectMemAddress(int& start, int& end, int psm, Point p, Size s, int bp, int bw);
+extern void GetRectMemAddress(int& start, int& end, int psm, int x, int y, Size s, int bp, int bw);
+extern void GetRectMemAddressZero(int& start, int& end, int psm, int w, int h, int bp, int bw);
+extern void GetRectMemAddressZero(int& start, int& end, int psm, Size s, int bp, int bw);
// called when trxdir is accessed. If host is involved, transfers memory to temp buffer byTransferBuf.
// Otherwise performs the transfer. TODO: Perhaps divide the transfers into chunks?
@@ -108,7 +111,4 @@ extern void TransferLocalHost(void* pbyMem, u32 nQWordSize);
extern void TransferLocalLocal();
-extern void TerminateLocalHost();
-extern void TerminateHostLocal();
-
#endif // HOSTMEMORY_H_INCLUDED
diff --git a/plugins/zzogl-pg/opengl/Linux/Linux.cpp b/plugins/zzogl-pg/opengl/Linux/Linux.cpp
index 3d5609f95f..4cf6ee9577 100644
--- a/plugins/zzogl-pg/opengl/Linux/Linux.cpp
+++ b/plugins/zzogl-pg/opengl/Linux/Linux.cpp
@@ -35,7 +35,7 @@ extern bool THR_bCtrl;
static map mapConfOpts;
static gameHacks tempHacks;
-void CALLBACK GSkeyEvent(keyEvent *ev)
+EXPORT_C_(void) GSkeyEvent(keyEvent *ev)
{
static bool bAlt = false;
@@ -450,7 +450,7 @@ void DisplayDialog()
gtk_widget_destroy(dialog);
}
-void CALLBACK GSconfigure()
+EXPORT_C_(void) GSconfigure()
{
char strcurdir[256];
getcwd(strcurdir, 256);
@@ -484,12 +484,12 @@ void SysMessage(const char *fmt, ...)
gtk_widget_destroy(dialog);
}
-void CALLBACK GSabout()
+EXPORT_C_(void) GSabout()
{
SysMessage("ZZOgl PG: by Zeydlitz (PG version worked on by arcum42, gregory, and the pcsx2 development team). Based off of ZeroGS, by zerofrog.");
}
-s32 CALLBACK GStest()
+EXPORT_C_(s32) GStest()
{
return 0;
}
diff --git a/plugins/zzogl-pg/opengl/Linux/zzogl-pg/zzogl-pg.cbp b/plugins/zzogl-pg/opengl/Linux/zzogl-pg/zzogl-pg.cbp
index b9bf0a2d48..33f009d059 100644
--- a/plugins/zzogl-pg/opengl/Linux/zzogl-pg/zzogl-pg.cbp
+++ b/plugins/zzogl-pg/opengl/Linux/zzogl-pg/zzogl-pg.cbp
@@ -16,11 +16,14 @@
+
+
+
@@ -33,12 +36,15 @@
+
+
+
@@ -50,10 +56,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -68,8 +133,6 @@
-
-
@@ -96,10 +159,10 @@
-
+
@@ -121,8 +184,6 @@
-
-
@@ -147,24 +208,29 @@
+
+
+
+
+
diff --git a/plugins/zzogl-pg/opengl/Mem.cpp b/plugins/zzogl-pg/opengl/Mem.cpp
index 2bbfd8470a..88b5b752d3 100644
--- a/plugins/zzogl-pg/opengl/Mem.cpp
+++ b/plugins/zzogl-pg/opengl/Mem.cpp
@@ -25,9 +25,11 @@
#include "Mem_Transmit.h"
#include "Mem_Swizzle.h"
#ifdef ZEROGS_SSE2
-#include
+#include
#endif
+#ifdef ZZNORMAL_MEMORY
+
BLOCK m_Blocks[0x40]; // do so blocks are indexable
PCSX2_ALIGNED16(u32 tempblock[64]);
@@ -53,41 +55,41 @@ u8* pstart;
template
static __forceinline const T* AlignOnBlockBoundry(TransferData data, TransferFuncts fun, Point alignedPt, int& endY, const T* pbuf)
{
- bool bCanAlign = ((MOD_POW2(gs.trxpos.dx, data.blockwidth) == 0) && (gs.imageX == gs.trxpos.dx) &&
+ bool bCanAlign = ((MOD_POW2(gs.trxpos.dx, data.blockwidth) == 0) && (gs.image.x == gs.trxpos.dx) &&
(alignedPt.y > endY) && (alignedPt.x > gs.trxpos.dx));
- if ((gs.imageEndX - gs.trxpos.dx) % data.widthlimit)
+ if ((gs.imageEnd.x - gs.trxpos.dx) % data.widthlimit)
{
/* hack */
int testwidth = (int)nSize -
- (gs.imageEndY - gs.imageY) * (gs.imageEndX - gs.trxpos.dx)
- + (gs.imageX - gs.trxpos.dx);
+ (gs.imageEnd.y - gs.image.y) * (gs.imageEnd.x - gs.trxpos.dx)
+ + (gs.image.x - gs.trxpos.dx);
if ((testwidth <= data.widthlimit) && (testwidth >= -data.widthlimit))
{
/* don't transfer */
- /*ZZLog::Debug_Log("Bad texture %s: %d %d %d", #psm, gs.trxpos.dx, gs.imageEndX, nQWordSize);*/
+ /*ZZLog::Debug_Log("Bad texture %s: %d %d %d", #psm, gs.trxpos.dx, gs.imageEnd.x, nQWordSize);*/
//ZZLog::Error_Log("Bad texture: testwidth = %d; data.widthlimit = %d", testwidth, data.widthlimit);
- gs.imageTransfer = -1;
+ gs.transferring = false;
}
bCanAlign = false;
}
/* first align on block boundary */
- if (MOD_POW2(gs.imageY, data.blockheight) || !bCanAlign)
+ if (MOD_POW2(gs.image.y, data.blockheight) || !bCanAlign)
{
u32 transwidth;
if (!bCanAlign)
- endY = gs.imageEndY; /* transfer the whole image */
+ endY = gs.imageEnd.y; /* transfer the whole image */
else
- assert(endY < gs.imageEndY); /* part of alignment condition */
+ assert(endY < gs.imageEnd.y); /* part of alignment condition */
- if (((gs.imageEndX - gs.trxpos.dx) % data.widthlimit) || ((gs.imageEndX - gs.imageX) % data.widthlimit))
+ if (((gs.imageEnd.x - gs.trxpos.dx) % data.widthlimit) || ((gs.imageEnd.x - gs.image.x) % data.widthlimit))
{
/* transmit with a width of 1 */
- transwidth = (1 + (DSTPSM == PSMT4));
+ transwidth = (1 + (gs.dstbuf.psm == PSMT4));
}
else
{
@@ -98,7 +100,7 @@ static __forceinline const T* AlignOnBlockBoundry(TransferData data, TransferFun
if (pbuf == NULL) return NULL;
- if (nSize == 0 || tempY == gs.imageEndY) return NULL;
+ if (nSize == 0 || tempY == gs.imageEnd.y) return NULL;
}
return pbuf;
@@ -112,14 +114,14 @@ static __forceinline const T* TransferAligningToBlocks(TransferData data, Transf
_SwizzleBlock swizzle;
/* can align! */
- pitch = gs.imageEndX - gs.trxpos.dx;
+ pitch = gs.imageEnd.x - gs.trxpos.dx;
area = pitch * data.blockheight;
- fracX = gs.imageEndX - alignedPt.x;
+ fracX = gs.imageEnd.x - alignedPt.x;
/* 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 || ((gs.dstbuf.psm == PSMCT24) || (gs.dstbuf.psm == PSMT8H) || (gs.dstbuf.psm == PSMT4HH) || (gs.dstbuf.psm == PSMT4HL)))
swizzle = (fun.Swizzle);
else
swizzle = (fun.Swizzle_u);
@@ -140,7 +142,7 @@ static __forceinline const T* TransferAligningToBlocks(TransferData data, Transf
#endif
/* transfer the rest */
- if (alignedPt.x < gs.imageEndX)
+ if (alignedPt.x < gs.imageEnd.x)
{
pbuf = TransmitHostLocalX(data.psm, fun.wp, data.widthlimit, data.blockheight, alignedPt.x, pbuf);
@@ -161,19 +163,19 @@ static __forceinline const T* TransferAligningToBlocks(TransferData data, Transf
static __forceinline int FinishTransfer(TransferData data, int nLeftOver)
{
- if (tempY >= gs.imageEndY)
+ if (tempY >= gs.imageEnd.y)
{
- assert(gs.imageTransfer == -1 || tempY == gs.imageEndY);
- gs.imageTransfer = -1;
+ assert( gs.transferring == false || tempY == gs.imageEnd.y);
+ gs.transferring = false;
/*int start, end;
- GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageWnew, gs.imageHnew, gs.dstbuf.bp, gs.dstbuf.bw);
+ GetRectMemAddress(start, end, gs.dstbuf.psm, gs.trxpos.dx, gs.trxpos.dy, gs.imageNew, gs.dstbuf.bp, gs.dstbuf.bw);
g_MemTargs.ClearRange(start, end);*/
}
else
{
/* update new params */
- gs.imageY = tempY;
- gs.imageX = tempX;
+ gs.image.y = tempY;
+ gs.image.x = tempX;
}
return (nSize * TransPitch(2, data.transfersize) + nLeftOver) / 2;
@@ -182,23 +184,23 @@ static __forceinline int FinishTransfer(TransferData data, int nLeftOver)
template
static __forceinline int RealTransfer(u32 psm, const void* pbyMem, u32 nQWordSize)
{
- assert(gs.imageTransfer == 0);
+ assert(gs.imageTransfer == XFER_HOST_TO_LOCAL);
TransferData data = tData[psm];
TransferFuncts fun(psm);
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;
+ tempY = gs.image.y;
+ tempX = gs.image.x;
Point alignedPt;
nSize = (nQWordSize * 4 * 2) / tp2;
- nSize = min(nSize, gs.imageWnew * gs.imageHnew);
+ nSize = min(nSize, gs.imageNew.w * gs.imageNew.h);
- int endY = ROUND_UPPOW2(gs.imageY, data.blockheight);
- alignedPt.y = ROUND_DOWNPOW2(gs.imageEndY, data.blockheight);
- alignedPt.x = ROUND_DOWNPOW2(gs.imageEndX, data.blockwidth);
+ int endY = ROUND_UPPOW2(gs.image.y, data.blockheight);
+ alignedPt.y = ROUND_DOWNPOW2(gs.imageEnd.y, data.blockheight);
+ alignedPt.x = ROUND_DOWNPOW2(gs.imageEnd.x, data.blockwidth);
pbuf = AlignOnBlockBoundry(data, fun, alignedPt, endY, pbuf);
@@ -210,12 +212,12 @@ static __forceinline int RealTransfer(u32 psm, const void* pbyMem, u32 nQWordSiz
if (TransPitch(nSize, data.transfersize) / 4 > 0)
{
- pbuf = TransmitHostLocalY(psm, fun.wp, data.widthlimit, gs.imageEndY, pbuf);
+ pbuf = TransmitHostLocalY(psm, fun.wp, data.widthlimit, gs.imageEnd.y, 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.transferring == false || TransPitch(nSize, data.transfersize) / 4 <= 2);
}
return FinishTransfer(data, nLeftOver);
@@ -382,3 +384,5 @@ void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, in
m_Blocks[PSMT4] = b;
m_Blocks[PSMT4].SetFun(PSMT4);
}
+
+#endif
diff --git a/plugins/zzogl-pg/opengl/Mem.h b/plugins/zzogl-pg/opengl/Mem.h
index f4fdb21116..ad8986c39e 100644
--- a/plugins/zzogl-pg/opengl/Mem.h
+++ b/plugins/zzogl-pg/opengl/Mem.h
@@ -32,7 +32,13 @@ static __forceinline int MOD_POW2(int val, int base) { return ((val)&(base - 1))
const int BLOCK_TEXWIDTH = 128;
const int BLOCK_TEXHEIGHT = 512;
-extern PCSX2_ALIGNED16(u32 tempblock[64]);
+// PSM is u6 value, so we MUST guarantee, that we don't crush on incorrect psm.
+#define MAX_PSM 64
+#define TABLE_WIDTH 8
+
+#ifndef ZZNORMAL_MEMORY
+#include "ZZoglMem.h"
+#endif
typedef u32(*_getPixelAddress)(int x, int y, u32 bp, u32 bw);
typedef u32(*_getPixelAddress_0)(int x, int y, u32 bw);
@@ -54,6 +60,7 @@ extern _SwizzleBlock swizzleBlockUnFun[64];
extern _TransferHostLocal TransferHostLocalFun[64];
extern _TransferLocalHost TransferLocalHostFun[64];
+
// Both of the following structs should probably be local class variables or in a namespace,
// but this works for the moment.
@@ -68,6 +75,9 @@ struct TransferData
u32 psm;
};
+#ifdef ZZNORMAL_MEMORY
+extern PCSX2_ALIGNED16(u32 tempblock[64]);
+
struct TransferFuncts
{
_writePixel_0 wp;
@@ -500,6 +510,8 @@ static __forceinline u32 readPixel16SZ_0(const void* pmem, int x, int y, u32 bw)
///////////////
+#endif
+
extern int TransferHostLocal32(const void* pbyMem, u32 nQWordSize);
extern int TransferHostLocal32Z(const void* pbyMem, u32 nQWordSize);
extern int TransferHostLocal24(const void* pbyMem, u32 nQWordSize);
diff --git a/plugins/zzogl-pg/opengl/Mem_Swizzle.cpp b/plugins/zzogl-pg/opengl/Mem_Swizzle.cpp
index 4f49dfde7e..d69d684365 100644
--- a/plugins/zzogl-pg/opengl/Mem_Swizzle.cpp
+++ b/plugins/zzogl-pg/opengl/Mem_Swizzle.cpp
@@ -21,15 +21,11 @@
#include "Mem.h"
#include "Mem_Swizzle.h"
#ifdef ZEROGS_SSE2
-#include
+#include
#endif
// WARNING a sfence instruction must be call after SwizzleBlock sse2 function
-// Current port of the ASM function to intrinsic
-#define INTRINSIC_PORT_16
-#define INTRINSIC_PORT_8
-#define INTRINSIC_PORT_4
#ifdef ZEROGS_SSE2
static const __aligned16 u32 mask_24b_H[4] = {0xFF000000, 0x0000FFFF, 0xFF000000, 0x0000FFFF};
static const __aligned16 u32 mask_24b_L[4] = {0x00FFFFFF, 0x00000000, 0x00FFFFFF, 0x00000000};
@@ -501,29 +497,17 @@ __forceinline void SwizzleBlock24(u8 *dst, u8 *src, int pitch)
__forceinline void SwizzleBlock16(u8 *dst, u8 *src, int pitch)
{
-#ifdef INTRINSIC_PORT_16
SwizzleBlock16_sse2_I(dst, src, pitch);
-#else
- SwizzleBlock16_sse2(dst, src, pitch);
-#endif
}
__forceinline void SwizzleBlock8(u8 *dst, u8 *src, int pitch)
{
-#ifdef INTRINSIC_PORT_8
SwizzleBlock8_sse2_I(dst, src, pitch);
-#else
- SwizzleBlock8_sse2(dst, src, pitch);
-#endif
}
__forceinline void SwizzleBlock4(u8 *dst, u8 *src, int pitch)
{
-#ifdef INTRINSIC_PORT_4
SwizzleBlock4_sse2_I(dst, src, pitch);
-#else
- SwizzleBlock4_sse2(dst, src, pitch);
-#endif
}
__forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch)
@@ -533,29 +517,17 @@ __forceinline void SwizzleBlock32u(u8 *dst, u8 *src, int pitch)
__forceinline void SwizzleBlock16u(u8 *dst, u8 *src, int pitch)
{
-#ifdef INTRINSIC_PORT_16
SwizzleBlock16_sse2_I(dst, src, pitch);
-#else
- SwizzleBlock16u_sse2(dst, src, pitch);
-#endif
}
__forceinline void SwizzleBlock8u(u8 *dst, u8 *src, int pitch)
{
-#ifdef INTRINSIC_PORT_8
SwizzleBlock8_sse2_I(dst, src, pitch);
-#else
- SwizzleBlock8u_sse2(dst, src, pitch);
-#endif
}
__forceinline void SwizzleBlock4u(u8 *dst, u8 *src, int pitch)
{
-#ifdef INTRINSIC_PORT_4
SwizzleBlock4_sse2_I(dst, src, pitch);
-#else
- SwizzleBlock4u_sse2(dst, src, pitch);
-#endif
}
__forceinline void SwizzleBlock8H(u8 *dst, u8 *src, int pitch)
diff --git a/plugins/zzogl-pg/opengl/Mem_Tables.cpp b/plugins/zzogl-pg/opengl/Mem_Tables.cpp
index 8db1b5c67c..93e9c66efc 100644
--- a/plugins/zzogl-pg/opengl/Mem_Tables.cpp
+++ b/plugins/zzogl-pg/opengl/Mem_Tables.cpp
@@ -250,6 +250,92 @@ u32 g_pageTable16SZ[64][64];
u32 g_pageTable8[64][128];
u32 g_pageTable4[128][128];
+
+//maximum PSM is 58, so our arrays have 58 + 1 = 59 elements
+
+// This table is used for fasr access to memory storage data. Field meaning is following:
+// 0 -- the number (1 << [psm][0]) is number of pixels per storage format. It's 0 if stored 1 pixel, 1 for 2 pixels (16-bit), 2 for 4 pixels (PSMT8) and 3 for 8 (PSMT4)
+// 5 -- is 3 - [psm][0]. Just for speed
+// 3, 4 -- size-1 of pageTable for psm. It used to clump x, y otside boundaries.
+// 1, 2 -- the number (1 << [psm][1]) and (1 << [psm[2]]) is also size of pageTable. So [psm][3] = (1 << [psm][1]) - 1
+// Also note, that [psm][1] = 5 + ([psm][0] + 1) / 2, and [psm][2] = 6 + [psm][0] / 2.
+// 6 -- pixel mask, (1 << [psm][5]) - 1, if be used to word, it leave only bytes for pixel formay
+// 7 -- starting position of data in word, PSMT8H, 4HL, 4HH are stored data not from the begining.
+u32 ZZ_DT[MAX_PSM][TABLE_WIDTH] = {
+ {0, 5, 6, 31, 63, 3, 0xffffffff, 0}, // 0 PSMCT32
+ {0, 5, 6, 31, 63, 3, 0x00ffffff, 0}, // 1 PSMCT24
+ {1, 6, 6, 63, 63, 2, 0x0000ffff, 0}, // 2 PSMCT16
+ {0, }, // 3
+ {0, }, // 4
+ {0, }, // 5
+ {0, }, // 6
+ {0, }, // 7
+ {0, }, // 8
+ {0, }, // 9
+ {1, 6, 6, 63, 63, 2, 0x0000ffff, 0}, // 10 PSMCT16S
+ {0, }, // 11
+ {0, }, // 12
+ {0, }, // 13
+ {0, }, // 14
+ {0, }, // 15
+ {0, }, // 16
+ {0, }, // 17
+ {0, }, // 18
+ {2, 6, 7, 63, 127, 1, 0x000000ff, 0}, // 19 PSMT8
+ {3, 7, 7, 127, 127, 0, 0x0000000f, 0}, // 20 PSMT4
+ {0, }, // 21
+ {0, }, // 22
+ {0, }, // 23
+ {0, }, // 24
+ {0, }, // 25
+ {0, }, // 26
+ {0, 5, 6, 31, 63, 3, 0x000000ff, 24}, // 27 PSMT8H
+ {0, }, // 28
+ {0, }, // 29
+ {0, }, // 30
+ {0, }, // 31
+ {0, }, // 32
+ {0, }, // 33
+ {0, }, // 34
+ {0, }, // 35
+ {0, 5, 6, 31, 63, 3, 0x0000000f, 24}, // 36 PSMT4HL
+ {0, }, // 37
+ {0, }, // 38
+ {0, }, // 39
+ {0, }, // 40
+ {0, }, // 41
+ {0, }, // 42
+ {0, }, // 43
+ {0, 5, 6, 31, 63, 3, 0x0000000f, 28}, // 44 PSMT4HH
+ {0, }, // 45
+ {0, }, // 46
+ {0, }, // 47
+ {0, 5, 6, 31, 63, 3, 0xffffffff, 0}, // 48 PSMCT32Z
+ {0, 5, 6, 31, 63, 3, 0x00ffffff, 0}, // 49 PSMCT24Z
+ {1, 6, 6, 63, 63, 2, 0x0000ffff, 0}, // 50 PSMCT16Z
+ {0, }, // 51
+ {0, }, // 52
+ {0, }, // 53
+ {0, }, // 54
+ {0, }, // 55
+ {0, }, // 56
+ {0, }, // 57
+ {1, 6, 6, 63, 63, 2, 0x0000ffff, 0}, // 58 PSMCT16SZ
+ {0, }, // 59
+ {0, }, // 60
+ {0, }, // 61
+ {0, }, // 62
+ {0, }, // 63
+};
+
+
+//maxium PSM is 58, so our arrays have 58 + 1 = 59 elements
+u32** g_pageTable[MAX_PSM] = {NULL,};
+u32** g_blockTable[MAX_PSM] = {NULL, };
+u32** g_columnTable[MAX_PSM] = {NULL, };
+u32 g_pageTable2[MAX_PSM][127][127] = {0, };
+u32** g_pageTableNew[MAX_PSM] = {NULL,};
+
/* PSM reference array
{ 32, 24, 16, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, 16S, NULL, NULL, NULL, NULL, NULL,
diff --git a/plugins/zzogl-pg/opengl/Mem_Transmit.h b/plugins/zzogl-pg/opengl/Mem_Transmit.h
index 0e228360b7..7a33f5bb1e 100644
--- a/plugins/zzogl-pg/opengl/Mem_Transmit.h
+++ b/plugins/zzogl-pg/opengl/Mem_Transmit.h
@@ -23,7 +23,6 @@
#include "GS.h"
#include "Mem.h"
-#define DSTPSM gs.dstbuf.psm
extern int tempX, tempY;
extern int pitch, area, fracX;
extern int nSize;
@@ -37,13 +36,13 @@ static __forceinline const T *TransmitHostLocalY_(_writePixel_0 wp, s32 widthlim
{
assert((nSize % widthlimit) == 0 && widthlimit <= 4);
- if ((gs.imageEndX - gs.trxpos.dx) % widthlimit)
+ if ((gs.imageEnd.x - gs.trxpos.dx) % widthlimit)
{
- // ZZLog::GS_Log("Bad Transmission! %d %d, psm: %d", gs.trxpos.dx, gs.imageEndX, DSTPSM);
+ // ZZLog::GS_Log("Bad Transmission! %d %d, psm: %d", gs.trxpos.dx, gs.imageEnd.x, gs.dstbuf.psm);
for (; tempY < endY; ++tempY)
{
- for (; tempX < gs.imageEndX && nSize > 0; tempX += 1, nSize -= 1, buf += 1)
+ for (; tempX < gs.imageEnd.x && nSize > 0; tempX += 1, nSize -= 1, buf += 1)
{
/* write as many pixel at one time as possible */
wp(pstart, tempX % 2048, tempY % 2048, buf[0], gs.dstbuf.bw);
@@ -53,7 +52,7 @@ static __forceinline const T *TransmitHostLocalY_(_writePixel_0 wp, s32 widthlim
for (; tempY < endY; ++tempY)
{
- for (; tempX < gs.imageEndX && nSize > 0; tempX += widthlimit, nSize -= widthlimit, buf += widthlimit)
+ for (; tempX < gs.imageEnd.x && nSize > 0; tempX += widthlimit, nSize -= widthlimit, buf += widthlimit)
{
/* write as many pixel at one time as possible */
@@ -77,14 +76,14 @@ static __forceinline const T *TransmitHostLocalY_(_writePixel_0 wp, s32 widthlim
}
}
- if (tempX >= gs.imageEndX)
+ if (tempX >= gs.imageEnd.x)
{
- assert(tempX == gs.imageEndX);
+ assert(tempX == gs.imageEnd.x);
tempX = gs.trxpos.dx;
}
else
{
- assert(gs.imageTransfer == -1 || nSize*sizeof(T) / 4 == 0);
+ assert(gs.transferring == false || nSize*sizeof(T) / 4 == 0);
return NULL;
}
}
@@ -96,24 +95,24 @@ static __forceinline const T *TransmitHostLocalY_(_writePixel_0 wp, s32 widthlim
template
static __forceinline const T *TransmitHostLocalY_24(_writePixel_0 wp, s32 widthlimit, int endY, const T *buf)
{
- if (widthlimit != 8 || ((gs.imageEndX - gs.trxpos.dx) % widthlimit))
+ if (widthlimit != 8 || ((gs.imageEnd.x - gs.trxpos.dx) % widthlimit))
{
- //ZZLog::GS_Log("Bad Transmission! %d %d, psm: %d", gs.trxpos.dx, gs.imageEndX, DSTPSM);
+ //ZZLog::GS_Log("Bad Transmission! %d %d, psm: %d", gs.trxpos.dx, gs.imageEnd.x, gs.dstbuf.psm);
for (; tempY < endY; ++tempY)
{
- for (; tempX < gs.imageEndX && nSize > 0; tempX += 1, nSize -= 1, buf += 3)
+ for (; tempX < gs.imageEnd.x && nSize > 0; tempX += 1, nSize -= 1, buf += 3)
{
wp(pstart, tempX % 2048, tempY % 2048, *(u32*)(buf), gs.dstbuf.bw);
}
- if (tempX >= gs.imageEndX)
+ if (tempX >= gs.imageEnd.x)
{
- assert(gs.imageTransfer == -1 || tempX == gs.imageEndX);
+ assert(gs.transferring == false || tempX == gs.imageEnd.x);
tempX = gs.trxpos.dx;
}
else
{
- assert(gs.imageTransfer == -1 || nSize == 0);
+ assert(gs.transferring == false || nSize == 0);
return NULL;
}
}
@@ -124,7 +123,7 @@ static __forceinline const T *TransmitHostLocalY_24(_writePixel_0 wp, s32 widthl
for (; tempY < endY; ++tempY)
{
- for (; tempX < gs.imageEndX && nSize > 0; tempX += widthlimit, nSize -= widthlimit, buf += 3 * widthlimit)
+ for (; tempX < gs.imageEnd.x && nSize > 0; tempX += widthlimit, nSize -= widthlimit, buf += 3 * widthlimit)
{
if (nSize < widthlimit) return NULL;
@@ -140,9 +139,9 @@ static __forceinline const T *TransmitHostLocalY_24(_writePixel_0 wp, s32 widthl
wp(pstart, (tempX + 7) % 2048, tempY % 2048, *(u32*)(buf + 21), gs.dstbuf.bw);
}
- if (tempX >= gs.imageEndX)
+ if (tempX >= gs.imageEnd.x)
{
- assert(gs.imageTransfer == -1 || tempX == gs.imageEndX);
+ assert(gs.transferring == false || tempX == gs.imageEnd.x);
tempX = gs.trxpos.dx;
}
else
@@ -155,7 +154,7 @@ static __forceinline const T *TransmitHostLocalY_24(_writePixel_0 wp, s32 widthl
nSize = 0;
}
- assert(gs.imageTransfer == -1 || nSize == 0);
+ assert(gs.transferring == false || nSize == 0);
return NULL;
}
@@ -171,7 +170,7 @@ static __forceinline const T *TransmitHostLocalY_4(_writePixel_0 wp, s32 widthli
{
for (; tempY < endY; ++tempY)
{
- for (; tempX < gs.imageEndX && nSize > 0; tempX += widthlimit, nSize -= widthlimit)
+ for (; tempX < gs.imageEnd.x && nSize > 0; tempX += widthlimit, nSize -= widthlimit)
{
/* write as many pixel at one time as possible */
wp(pstart, tempX % 2048, tempY % 2048, *buf&0x0f, gs.dstbuf.bw);
@@ -200,13 +199,13 @@ static __forceinline const T *TransmitHostLocalY_4(_writePixel_0 wp, s32 widthli
}
}
- if (tempX >= gs.imageEndX)
+ if (tempX >= gs.imageEnd.x)
{
tempX = gs.trxpos.dx;
}
else
{
- assert(gs.imageTransfer == -1 || (nSize / 32) == 0);
+ assert(gs.transferring == false || (nSize / 32) == 0);
return NULL;
}
}
@@ -238,7 +237,7 @@ static __forceinline const T *TransmitHostLocalX_(_writePixel_0 wp, u32 widthlim
{
for (u32 tempi = 0; tempi < blockheight; ++tempi)
{
- for (tempX = startX; tempX < gs.imageEndX; tempX++, buf++)
+ for (tempX = startX; tempX < gs.imageEnd.x; tempX++, buf++)
{
wp(pstart, tempX % 2048, (tempY + tempi) % 2048, buf[0], gs.dstbuf.bw);
}
@@ -255,7 +254,7 @@ static __forceinline const T *TransmitHostLocalX_24(_writePixel_0 wp, u32 widthl
{
for (u32 tempi = 0; tempi < blockheight; ++tempi)
{
- for (tempX = startX; tempX < gs.imageEndX; tempX++, buf += 3)
+ for (tempX = startX; tempX < gs.imageEnd.x; tempX++, buf += 3)
{
wp(pstart, tempX % 2048, (tempY + tempi) % 2048, *(u32*)buf, gs.dstbuf.bw);
}
@@ -272,7 +271,7 @@ static __forceinline const T *TransmitHostLocalX_4(_writePixel_0 wp, u32 widthli
{
for (u32 tempi = 0; tempi < blockheight; ++tempi)
{
- for (tempX = startX; tempX < gs.imageEndX; tempX += 2, buf++)
+ for (tempX = startX; tempX < gs.imageEnd.x; tempX += 2, buf++)
{
wp(pstart, tempX % 2048, (tempY + tempi) % 2048, buf[0]&0x0f, gs.dstbuf.bw);
wp(pstart, (tempX + 1) % 2048, (tempY + tempi) % 2048, buf[0] >> 4, gs.dstbuf.bw);
diff --git a/plugins/zzogl-pg/opengl/NewRegs.cpp b/plugins/zzogl-pg/opengl/NewRegs.cpp
deleted file mode 100644
index d9ff6cd7f4..0000000000
--- a/plugins/zzogl-pg/opengl/NewRegs.cpp
+++ /dev/null
@@ -1,1144 +0,0 @@
-/* ZZ Open GL graphics plugin
- * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
- * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "GS.h"
-#include "Mem.h"
-#include "NewRegs.h"
-#include "PS2Etypes.h"
-
-#include "targets.h"
-
-#ifdef USE_OLD_REGS
-#include "Regs.h"
-#else
-#include "ZZoglVB.h"
-#include "ZZoglDrawing.h"
-
-#ifdef _MSC_VER
-#pragma warning(disable:4244)
-#endif
-
-GIFRegHandler g_GIFPackedRegHandlers[16];
-GIFRegHandler g_GIFRegHandlers[256];
-GIFRegHandler g_GIFTempRegHandlers[16] = {0};
-
-// values for keeping track of changes
-u32 s_uTex1Data[2][2] = {{0, }};
-u32 s_uClampData[2] = {0, };
-
-//u32 results[65535] = {0, };
-
-void __gifCall GIFPackedRegHandlerNull(const u32* data)
-{
- FUNCLOG
- ZZLog::Debug_Log("Unexpected packed reg handler %8.8lx_%8.8lx %x.", data[0], data[1], data[2]);
-}
-
-// All these just call their non-packed equivalent.
-void __gifCall GIFPackedRegHandlerPRIM(const u32* data) { GIFRegHandlerPRIM(data); }
-
-template
-void __gifCall GIFPackedRegHandlerTEX0(const u32* data)
-{
- GIFRegHandlerTEX0(data);
-}
-
-template
-void __gifCall GIFPackedRegHandlerCLAMP(const u32* data)
-{
- GIFRegHandlerCLAMP(data);
-}
-
-void __gifCall GIFPackedRegHandlerTEX0_1(const u32* data) { GIFRegHandlerTEX0<0>(data); }
-void __gifCall GIFPackedRegHandlerTEX0_2(const u32* data) { GIFRegHandlerTEX0<1>(data); }
-void __gifCall GIFPackedRegHandlerCLAMP_1(const u32* data) { GIFRegHandlerCLAMP<0>(data); }
-void __gifCall GIFPackedRegHandlerCLAMP_2(const u32* data) { GIFRegHandlerCLAMP<1>(data); }
-void __gifCall GIFPackedRegHandlerXYZF3(const u32* data) { GIFRegHandlerXYZF3(data); }
-void __gifCall GIFPackedRegHandlerXYZ3(const u32* data) { GIFRegHandlerXYZ3(data); }
-
-void __gifCall GIFPackedRegHandlerRGBA(const u32* data)
-{
- FUNCLOG
-
- GIFPackedRGBA* r = (GIFPackedRGBA*)(data);
- gs.rgba = (r->R | (r->G << 8) | (r->B << 16) | (r->A << 24));
- gs.vertexregs.rgba = gs.rgba;
- gs.vertexregs.q = gs.q;
-
- ZZLog::Greg_Log("Packed RGBA: 0x%x", gs.rgba);
-}
-
-void __gifCall GIFPackedRegHandlerSTQ(const u32* data)
-{
- FUNCLOG
- GIFPackedSTQ* r = (GIFPackedSTQ*)(data);
- gs.vertexregs.s = r->S;
- gs.vertexregs.t = r->T;
- gs.q = r->Q;
- ZZLog::Greg_Log("Packed STQ: 0x%x, 0x%x, %f", r->S, r->T, r->Q);
-}
-
-void __gifCall GIFPackedRegHandlerUV(const u32* data)
-{
- FUNCLOG
- GIFPackedUV* r = (GIFPackedUV*)(data);
- gs.vertexregs.u = r->U;
- gs.vertexregs.v = r->V;
- ZZLog::Greg_Log("Packed UV: 0x%x, 0x%x", r->U, r->V);
-}
-
-void __gifCall GIFPackedRegHandlerXYZF2(const u32* data)
-{
- FUNCLOG
- GIFPackedXYZF2* r = (GIFPackedXYZF2*)(data);
- gs.add_vertex(r->X, r->Y,r->Z, r->F);
-
- // Fix Vertexes up later.
- ZZKick->KickVertex(!!(r->ADC));
- ZZLog::Greg_Log("Packed XYZF2: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F);
-}
-
-void __gifCall GIFPackedRegHandlerXYZ2(const u32* data)
-{
- FUNCLOG
- GIFPackedXYZ2* r = (GIFPackedXYZ2*)(data);
- gs.add_vertex(r->X, r->Y,r->Z);
-
- // Fix Vertexes up later.
- ZZKick->KickVertex(!!(r->ADC));
- ZZLog::Greg_Log("Packed XYZ2: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z);
-}
-
-void __gifCall GIFPackedRegHandlerFOG(const u32* data)
-{
- FUNCLOG
- GIFPackedFOG* r = (GIFPackedFOG*)(data);
- gs.vertexregs.f = r->F;
- ZZLog::Greg_Log("Packed FOG: 0x%x", r->F);
-}
-
-void __gifCall GIFPackedRegHandlerA_D(const u32* data)
-{
- FUNCLOG
- GIFPackedA_D* r = (GIFPackedA_D*)(data);
-
- g_GIFRegHandlers[r->ADDR](data);
- ZZLog::Greg_Log("Packed A_D: 0x%x", r->ADDR);
-}
-
-void __gifCall GIFPackedRegHandlerNOP(const u32* data)
-{
- FUNCLOG
-}
-
-void __gifCall GIFRegHandlerNull(const u32* data)
-{
- FUNCLOG
-#ifdef _DEBUG
-
- if ((((uptr)&data[2])&0xffff) == 0) return;
-
- // 0x7f happens on a lot of games
- if (data[2] != 0x7f && (data[0] || data[1]))
- {
- ZZLog::Debug_Log("Unexpected reg handler %x %x %x.", data[0], data[1], data[2]);
- }
-
-#endif
-}
-
-void __gifCall GIFRegHandlerRGBAQ(const u32* data)
-{
- FUNCLOG
- GIFRegRGBAQ* r = (GIFRegRGBAQ*)(data);
- gs.rgba = (r->R | (r->G << 8) | (r->B << 16) | (r->A << 24));
- gs.vertexregs.rgba = gs.rgba;
- gs.vertexregs.q = r->Q;
- ZZLog::Greg_Log("RGBAQ: 0x%x, 0x%x, 0x%x, %f", r->R, r->G, r->B, r->A, r->Q);
-}
-
-void __gifCall GIFRegHandlerST(const u32* data)
-{
- FUNCLOG
- GIFRegST* r = (GIFRegST*)(data);
- gs.vertexregs.s = r->S;
- gs.vertexregs.t = r->T;
- ZZLog::Greg_Log("ST: 0x%x, 0x%x", r->S, r->T);
-}
-
-void __gifCall GIFRegHandlerUV(const u32* data)
-{
- // Baroque breaks if u&v are 16 bits instead of 14.
- FUNCLOG
- GIFRegUV* r = (GIFRegUV*)(data);
- gs.vertexregs.u = r->U;
- gs.vertexregs.v = r->V;
- ZZLog::Greg_Log("UV: 0x%x, 0x%x", r->U, r->V);
-}
-
-void __gifCall GIFRegHandlerXYZF2(const u32* data)
-{
- FUNCLOG
- GIFRegXYZF* r = (GIFRegXYZF*)(data);
- gs.add_vertex(r->X, r->Y,r->Z, r->F);
-
- ZZKick->KickVertex(false);
- ZZLog::Greg_Log("XYZF2: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F);
-}
-
-void __gifCall GIFRegHandlerXYZ2(const u32* data)
-{
- FUNCLOG
- GIFRegXYZ* r = (GIFRegXYZ*)(data);
- gs.add_vertex(r->X, r->Y,r->Z);
-
- ZZKick->KickVertex(false);
- ZZLog::Greg_Log("XYZF2: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z);
-}
-
-template
-void __gifCall GIFRegHandlerTEX0(const u32* data)
-{
- // Used on Mana Khemias opening dialog.
- FUNCLOG
-
- GIFRegTEX0* r = (GIFRegTEX0*)(data);
- u32 psm = ZZOglGet_psm_TexBitsFix(data[0]);
-
- ZZLog::Greg_Log("TEX0_%d: 0x%x", i, data);
-
- // Worry about this later.
- if (!NoHighlights(i)) return;
-
- if (m_Blocks[psm].bpp == 0)
- {
- // kh and others
- return;
- }
-
- // Order is important.
- vb[i].uNextTex0Data[0] = r->ai32[0];
- vb[i].uNextTex0Data[1] = r->ai32[1];
- vb[i].bNeedTexCheck = 1;
-
- // don't update unless necessary
- if (PSMT_ISCLUT(psm))
- {
- if (CheckChangeInClut(data[1], psm))
- {
- // loading clut, so flush whole texture
- vb[i].FlushTexData();
- }
- else if (r->CSA != (vb[i].uCurTex0.CSA))
- {
- // check if csa is the same!! (ffx bisaid island, grass)
- Flush(i); // flush any previous entries
- }
- }
-}
-
-template
-void __gifCall GIFRegHandlerCLAMP(const u32* data)
-{
- FUNCLOG
- clampInfo& clamp = vb[i].clamp;
- GIFRegCLAMP* r = (GIFRegCLAMP*)(data);
-
- // Worry about this later.
- if (!NoHighlights(i)) return;
-
- if ((s_uClampData[i] != data[0]) || (((clamp.minv >> 8) | (clamp.maxv << 2)) != (data[1]&0x0fff)))
- {
- Flush(i);
-
- vb[i].bTexConstsSync = false;
- }
-
- s_uClampData[i] = data[0];
-
- clamp.wms = r->WMS;
- clamp.wmt = r->WMT;
- clamp.minu = r->MINU;
- clamp.maxu = r->MAXU;
- clamp.minv = r->MINV;
- clamp.maxv = r->MAXV;
- ZZLog::Greg_Log("CLAMP_%d: 0x%x", i, data);
-}
-
-void __gifCall GIFRegHandlerFOG(const u32* data)
-{
- FUNCLOG
- GIFRegFOG* r = (GIFRegFOG*)(data);
- gs.vertexregs.f = r->F;
- ZZLog::Greg_Log("FOG: 0x%x", r->F);
-}
-
-void __gifCall GIFRegHandlerXYZF3(const u32* data)
-{
- FUNCLOG
- GIFRegXYZF* r = (GIFRegXYZF*)(data);
- gs.add_vertex(r->X, r->Y,r->Z, r->F);
-
- ZZKick->KickVertex(true);
- ZZLog::Greg_Log("XYZF3: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F);
-}
-
-void __gifCall GIFRegHandlerXYZ3(const u32* data)
-{
- FUNCLOG
- GIFRegXYZ* r = (GIFRegXYZ*)(data);
- gs.add_vertex(r->X, r->Y,r->Z);
-
- ZZKick->KickVertex(true);
- ZZLog::Greg_Log("XYZ3: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z);
-}
-
-void __gifCall GIFRegHandlerNOP(const u32* data)
-{
- FUNCLOG
-}
-
-template
-void __fastcall GIFRegHandlerTEX1(const u32* data)
-{
- FUNCLOG
- GIFRegTEX1* r = (GIFRegTEX1*)(data);
- tex1Info& tex1 = vb[i].tex1;
-
- // Worry about this later.
- if (!NoHighlights(i)) return;
-
- if (conf.bilinear == 1 && (tex1.mmag != r->MMAG || tex1.mmin != r->MMIN))
- {
- Flush(i);
- vb[i].bVarsTexSync = false;
- }
-
- tex1.lcm = r->LCM;
-
- tex1.mxl = r->MXL;
- tex1.mmag = r->MMAG;
- tex1.mmin = r->MMIN;
- tex1.mtba = r->MTBA;
- tex1.l = r->L;
- tex1.k = r->K;
- ZZLog::Greg_Log("TEX1_%d: 0x%x", i, data);
-}
-
-template
-void __gifCall GIFRegHandlerTEX2(const u32* data)
-{
- FUNCLOG
- tex0Info& tex0 = vb[i].tex0;
-
- vb[i].FlushTexData();
-
- u32 psm = ZZOglGet_psm_TexBitsFix(data[0]);
-
- u32* s_uTex0Data = vb[i].uCurTex0Data;
-
- // 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;
-
- // have to write the CLUT again if changed
- if (ZZOglClutMinusCLDunchanged(s_uTex0Data, data))
- {
- tex0.cld = ZZOglGet_cld_TexBits(data[1]);
-
- if (tex0.cld != 0)
- {
- texClutWrite(i);
- // invalidate to make sure target didn't change!
- vb[i].bVarsTexSync = false;
- }
-
- return;
- }
- }
-
- Flush(i);
-
- vb[i].bVarsTexSync = false;
- vb[i].bTexConstsSync = false;
-
- 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)) CluttingForFlushedTex(&tex0, data[1], i);
- ZZLog::Greg_Log("TEX2_%d: 0x%x", i, data);
-}
-
-template
-void __gifCall GIFRegHandlerXYOFFSET(const u32* data)
-{
- FUNCLOG
- // Affects that Mana Khemia opening dialog (when i == 0).
- GIFRegXYOFFSET* r = (GIFRegXYOFFSET*)(data);
- vb[i].offset.x = r->OFX;
- vb[i].offset.y = r->OFY;
- ZZLog::Greg_Log("XYOFFSET_%d: 0x%x, 0x%x", i, r->OFX, r->OFY);
-}
-
-// Fill out the vertex queue(prim) and the attributes.
-void __gifCall GIFRegHandlerPRIM(const u32 *data)
-{
- FUNCLOG
- GIFRegPRIM* r = (GIFRegPRIM*)(data);
-
- //if (data[0] & ~0x3ff)
- //{
- //ZZLog::Warn_Log("Warning: unknown bits in prim %8.8lx_%8.8lx", data[1], data[0]);
- //}
-
- gs.primC = 0;
- prim->prim = r->PRIM;
- gs._prim[0].prim = r->PRIM;
- gs._prim[1].prim = r->PRIM;
- gs._prim[1]._val = (data[0] >> 3) & 0xff; // Setting the next 8 flags after prim at once.
-
- gs.new_tri_fan = !(r->PRIM ^ PRIM_TRIANGLE_FAN);
- ZZKick->DirtyValidPrevPrim();
-
- Prim();
- ZZLog::Greg_Log("PRIM");
-}
-
-// Fill out an alternate set of attributes.
-void __gifCall GIFRegHandlerPRMODE(const u32* data)
-{
- FUNCLOG
- //GIFRegPRMODE* r = (GIFRegPRMODE*)(data);
- // Re-examine all code dealing with PRIMs in a bit.
- gs._prim[0]._val = (data[0] >> 3) & 0xff;
-
- if (gs.prac == 0) Prim();
- ZZLog::Greg_Log("PRMODE");
-}
-
-// Switch between the primary set of attributes (gs._prim[1]) and the secondary (gs._prim[0]).
-void __gifCall GIFRegHandlerPRMODECONT(const u32* data)
-{
- FUNCLOG
- // Turns all the text into colored blocks on the initial Mana Khemia dialog if not run.
- GIFRegPRMODECONT* r = (GIFRegPRMODECONT*)(data);
- gs.prac = r->AC;
- prim = &gs._prim[gs.prac];
-
- Prim();
- ZZLog::Greg_Log("PRMODECONT");
-}
-
-void __gifCall GIFRegHandlerTEXCLUT(const u32* data)
-{
- FUNCLOG
- // Affects background coloration of initial Mana Khemia dialog.
- GIFRegTEXCLUT* r = (GIFRegTEXCLUT*)(data);
-
- vb[0].FlushTexData();
- vb[1].FlushTexData();
-
- // Fixme.
- gs.clut.cbw = r->CBW << 6;
- gs.clut.cou = r->COU << 4;
- gs.clut.cov = r->COV;
- ZZLog::Greg_Log("TEXCLUT: CBW:0x%x, COU:0x%x, COV:0x%x",r->CBW, r->COU, r->COV);
-}
-
-void __gifCall GIFRegHandlerSCANMSK(const u32* data)
-{
- FUNCLOG
- GIFRegSCANMSK* r = (GIFRegSCANMSK*)(data);
-
- if(r->MSK != gs.smask)
- {
- FlushBoth();
-// ResolveC(&vb[0]);
-// ResolveZ(&vb[0]);
- }
-
- gs.smask = r->MSK;
- ZZLog::Greg_Log("SCANMSK: 0x%x",r->MSK);
-}
-
-template
-void __gifCall GIFRegHandlerMIPTBP1(const u32* data)
-{
- FUNCLOG
- GIFRegMIPTBP1* r = (GIFRegMIPTBP1*)(data);
- /*if(PRIM->CTXT == i && r != miptbp0)
- {
- Flush();
- }*/
-
- miptbpInfo& miptbp0 = vb[i].miptbp0;
- miptbp0.tbp[0] = r->TBP1;
- miptbp0.tbw[0] = r->TBW1;
- miptbp0.tbp[1] = r->TBP2;
- miptbp0.tbw[1] = r->TBW2;
- miptbp0.tbp[2] = r->TBP3;
- miptbp0.tbw[2] = r->TBW3;
- ZZLog::Greg_Log("MIPTBP1_%d: TBP/TBW: (0x%x, 0x%x), (0x%x, 0x%x), (0x%x, 0x%x)", i, r->TBP1, r->TBW1, r->TBP2, r->TBW2, r->TBP3, r->TBW3);
-}
-
-template
-void __gifCall GIFRegHandlerMIPTBP2(const u32* data)
-{
- FUNCLOG
- GIFRegMIPTBP2* r = (GIFRegMIPTBP2*)(data);
- // Yep.
-
- miptbpInfo& miptbp1 = vb[i].miptbp1;
- miptbp1.tbp[0] = r->TBP4;
- miptbp1.tbw[0] = r->TBW4;
- miptbp1.tbp[1] = r->TBP5;
- miptbp1.tbw[1] = r->TBW5;
- miptbp1.tbp[2] = r->TBP6;
- miptbp1.tbw[2] = r->TBW6;
- ZZLog::Greg_Log("MIPTBP2_%d: TBP/TBW: (0x%x, 0x%x), (0x%x, 0x%x), (0x%x, 0x%x)", i, r->TBP4, r->TBW4, r->TBP5, r->TBW5, r->TBP6, r->TBW6);
-}
-
-void __gifCall GIFRegHandlerTEXA(const u32* data)
-{
- FUNCLOG
- // Background of initial Mana Khemia dialog.
- GIFRegTEXA* r = (GIFRegTEXA*)(data);
-
- if ((r->AEM != gs.texa.aem) || (r->TA0 != gs.texa.ta[0]) || (r->TA1 != gs.texa.ta[1]))
- {
- FlushBoth();
-
- vb[0].bTexConstsSync = false;
- vb[1].bTexConstsSync = false;
- }
-
- gs.texa.aem = r->AEM;
- gs.texa.ta[0] = r->TA0;
- gs.texa.ta[1] = r->TA1;
- gs.texa.fta[0] = r->TA0 / 255.0f;
- gs.texa.fta[1] = r->TA1 / 255.0f;
- ZZLog::Greg_Log("TEXA: AEM:0x%x, TA0:0x%x, TA1:0x%x", r->AEM, r->TA0, r->TA1);
-}
-
-void __gifCall GIFRegHandlerFOGCOL(const u32* data)
-{
- FUNCLOG
- GIFRegFOGCOL* r = (GIFRegFOGCOL*)(data);
-
- if (gs.fogcol != r->ai32[0])
- {
- FlushBoth();
- }
-
- SetFogColor(r);
- gs.fogcol = r->ai32[0];
- ZZLog::Greg_Log("FOGCOL: 0x%x", r->ai32[0]);
-}
-
-void __gifCall GIFRegHandlerTEXFLUSH(const u32* data)
-{
- FUNCLOG
- // GSdx doesn't even do anything here.
- SetTexFlush();
- ZZLog::Greg_Log("TEXFLUSH");
-}
-
-template
-void __gifCall GIFRegHandlerSCISSOR(const u32* data)
-{
- FUNCLOG
- GIFRegSCISSOR* r = (GIFRegSCISSOR*)(data);
- Rect2& scissor = vb[i].scissor;
-
- Rect2 newscissor;
-
- // << 3?
- newscissor.x0 = r->SCAX0 << 3;
- newscissor.x1 = r->SCAX1 << 3;
- newscissor.y0 = r->SCAY0 << 3;
- newscissor.y1 = r->SCAY1 << 3;
-
- if (newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 ||
- newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0)
- {
- Flush(i);
-
- // flush everything
- vb[i].bNeedFrameCheck = 1;
- }
-
- scissor = newscissor;
-
- //Hmm...
- /*
- if(PRIM->CTXT == i && r->SCISSOR != m_env.CTXT[i].SCISSOR)
- {
- Flush();
- }
-
- m_env.CTXT[i].SCISSOR = (GSVector4i)r->SCISSOR;
-
- m_env.CTXT[i].UpdateScissor();*/
- ZZLog::Greg_Log("SCISSOR%d", i);
-}
-
-template
-void __gifCall GIFRegHandlerALPHA(const u32* data)
-{
- FUNCLOG
- // Mana Khemia Opening Dialog (when i = 0).
- GIFRegALPHA* r = (GIFRegALPHA*)(data);
- alphaInfo newalpha;
-
- newalpha.a = r->A;
- newalpha.b = r->B;
- newalpha.c = r->C;
- newalpha.d = r->D;
- newalpha.fix = r->FIX;
-
- 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.abcd != vb[i].alpha.abcd) || (newalpha.fix != vb[i].alpha.fix))
- {
- Flush(i);
- }
-
- vb[i].alpha = newalpha;
- ZZLog::Greg_Log("ALPHA%d: A:0x%x B:0x%x C:0x%x D:0x%x FIX:0x%x ", i, r->A, r->B, r->C, r->D, r->FIX);
-}
-
-void __gifCall GIFRegHandlerDIMX(const u32* data)
-{
- FUNCLOG
-
- GIFRegDIMX* r = (GIFRegDIMX*)(data);
- // Not even handled? Fixme.
- bool update = false;
-
- if (r->i64 != gs.dimx.i64)
- {
- FlushBoth();
-
- update = true;
- }
-
- gs.dimx.i64 = r->i64;
-
- if (update)
- {
- //gs.UpdateDIMX();
- }
- ZZLog::Greg_Log("DIMX");
-}
-
-void __gifCall GIFRegHandlerDTHE(const u32* data)
-{
- FUNCLOG
- GIFRegDTHE* r = (GIFRegDTHE*)(data);
-
- if (r->DTHE != gs.dthe)
- {
- FlushBoth();
- }
-
- gs.dthe = r->DTHE;
- ZZLog::Greg_Log("DTHE: 0x%x ", r->DTHE);
-}
-
-void __gifCall GIFRegHandlerCOLCLAMP(const u32* data)
-{
- FUNCLOG
- GIFRegCOLCLAMP* r = (GIFRegCOLCLAMP*)(data);
-
- if (r->CLAMP != gs.colclamp)
- {
- FlushBoth();
- }
-
- gs.colclamp = r->CLAMP;
- ZZLog::Greg_Log("COLCLAMP: 0x%x ", r->CLAMP);
-}
-
-template
-void __gifCall GIFRegHandlerTEST(const u32* data)
-{
- FUNCLOG
- pixTest* test = &vb[i].test;
- GIFRegTEST* r = (GIFRegTEST*)(data);
-
- if (test->_val != r->ai32[0])
- {
- Flush(i);
- }
-
- test->_val = r->ai32[0];
- ZZLog::Greg_Log("TEST%d", i);
-}
-
-void __gifCall GIFRegHandlerPABE(const u32* data)
-{
- FUNCLOG
- GIFRegPABE* r = (GIFRegPABE*)(data);
-
- if (gs.pabe != r->PABE)
- {
- FlushBoth();
-// SetAlphaChanged(0, GPUREG_PABE);
-// SetAlphaChanged(1, GPUREG_PABE);
- }
-
- gs.pabe = r->PABE;
- ZZLog::Greg_Log("PABE: 0x%x ", r->PABE);
-}
-
-template
-void __gifCall GIFRegHandlerFBA(const u32* data)
-{
- FUNCLOG
- GIFRegFBA* r = (GIFRegFBA*)(data);
-
- if (r->FBA != vb[i].fba.fba)
- {
- FlushBoth();
- }
-
- vb[i].fba.fba = r->FBA;
- ZZLog::Greg_Log("FBA%d: 0x%x ", i, r->FBA);
-}
-
-template
-void __gifCall GIFRegHandlerFRAME(const u32* data)
-{
- FUNCLOG
- // Affects opening dialogs, movie, and menu on Mana Khemia.
-
- GIFRegFRAME* r = (GIFRegFRAME*)(data);
- frameInfo& gsfb = vb[i].gsfb;
-
- int fbw = r->FBW * 64;
- int fbp = r->FBP * 32;
- int fbh = 0;
-
- if (gs.dthe != 0)
- {
- // Dither here.
- //ZZLog::Error_Log("frameWrite: Dither!");
- }
-
- if ((gsfb.fbp == fbp) &&
- (gsfb.fbw == fbw) &&
- (gsfb.psm == r->PSM) &&
- (gsfb.fbm == ZZOglGet_fbm_FrameBitsFix(data[0], data[1])))
- {
- return;
- }
-
- FlushBoth();
- if (r->FBW > 0) fbh = ZZOgl_fbh_Calc(r->FBP, r->FBW, r->PSM);
-
- gsfb.fbp = fbp;
- gsfb.fbw = fbw;
- gsfb.psm = r->PSM;
- gsfb.fbh = fbh;
- gsfb.fbm = ZZOglGet_fbm_FrameBitsFix(data[0], data[1]);
-
-
- vb[i].bNeedFrameCheck = 1;
- ZZLog::Greg_Log("FRAME_%d", i);
-}
-
-template
-void __gifCall GIFRegHandlerZBUF(const u32* data)
-{
- FUNCLOG
- // I'll wait a bit on this one.
- GIFRegZBUF* r = (GIFRegZBUF*)(data);
- ZZLog::Greg_Log("ZBUF_1");
-
- zbufInfo& zbuf = vb[i].zbuf;
- int psm = (0x30 | r->PSM);
- int zbp = r->ZBP * 32;
-
- if (zbuf.zbp == zbp &&
- zbuf.psm == psm &&
- zbuf.zmsk == r->ZMSK)
- {
- return;
- }
-
- // error detection
- if (m_Blocks[psm].bpp == 0) return;
-
- FlushBoth();
-
- zbuf.zbp = zbp;
- zbuf.psm = psm;
- zbuf.zmsk = r->ZMSK;
-
- vb[i].zprimmask = 0xffffffff;
-
- if (zbuf.psm > 0x31) vb[i].zprimmask = 0xffff;
-
- vb[i].bNeedZCheck = 1;
-}
-
-void __gifCall GIFRegHandlerBITBLTBUF(const u32* data)
-{
- FUNCLOG
- // Required for *all* graphics. (Checked on Mana Khemia)
-
- GIFRegBITBLTBUF* r = (GIFRegBITBLTBUF*)(data);
- // Wonder why the shift?
- gs.srcbufnew.bp = r->SBP; // * 64;
- gs.srcbufnew.bw = r->SBW << 6;
- gs.srcbufnew.psm = r->SPSM;
- gs.dstbufnew.bp = r->DBP; // * 64;
- gs.dstbufnew.bw = r->DBW << 6;
- gs.dstbufnew.psm = r->DPSM;
-
- if (gs.dstbufnew.bw == 0) gs.dstbufnew.bw = 64;
- // GSdx does this:
-
- /*if((gs.srcbufnew.bw & 1) && (gs.srcbufnew.psm == PSM_PSMT8 || gs.srcbufnew.psm == PSM_PSMT4))
- {
- gs.srcbufnew.bw &= ~1;
- }
-
- if((gs.dstbufnew.bw & 1) && (gs.dstbufnew.psm == PSM_PSMT8 || gs.dstbufnew.psm == PSM_PSMT4))
- {
- gs.dstbufnew.bw &= ~1; // namcoXcapcom: 5, 11, refered to as 4, 10 in TEX0.TBW later
- }*/
- ZZLog::Greg_Log("BITBLTBUF");
-}
-
-void __gifCall GIFRegHandlerTRXPOS(const u32* data)
-{
- // Affects Mana Khemia opening background.
- FUNCLOG
- GIFRegTRXPOS* r = (GIFRegTRXPOS*)(data);
-
- gs.trxposnew.sx = r->SSAX;
- gs.trxposnew.sy = r->SSAY;
- gs.trxposnew.dx = r->DSAX;
- gs.trxposnew.dy = r->DSAY;
- gs.trxposnew.dirx = r->DIRX;
- gs.trxposnew.diry = r->DIRY;
- ZZLog::Greg_Log("TRXPOS: SSA:(0x%x/0x%x) DSA:(0x%x/0x%x) DIR:(0x%x/0x%x)", r->SSAX, r->SSAY, r->DSAX, r->DSAY, r->DIRX, r->DIRY);
-}
-
-void __gifCall GIFRegHandlerTRXREG(const u32* data)
-{
- FUNCLOG
- GIFRegTRXREG* r = (GIFRegTRXREG*)(data);
- gs.imageWtemp = r->RRW;
- gs.imageHtemp = r->RRH;
- ZZLog::Greg_Log("TRXREG: RRW: 0x%x, RRH: 0x%x", r->RRW, r->RRH);
-}
-
-void __gifCall GIFRegHandlerTRXDIR(const u32* data)
-{
- FUNCLOG
- GIFRegTRXDIR* r = (GIFRegTRXDIR*)(data);
- // Oh dear...
-
- // terminate any previous transfers
-
- switch (gs.imageTransfer)
- {
- case 0: // host->loc
- TerminateHostLocal();
- break;
-
- case 1: // loc->host
- TerminateLocalHost();
- break;
- }
-
- gs.srcbuf = gs.srcbufnew;
- gs.dstbuf = gs.dstbufnew;
- gs.trxpos = gs.trxposnew;
-
- gs.imageTransfer = r->XDIR;
- gs.imageWnew = gs.imageWtemp;
- gs.imageHnew = gs.imageHtemp;
-
- if (gs.imageWnew > 0 && gs.imageHnew > 0)
- {
- switch (gs.imageTransfer)
- {
- case 0: // host->loc
- InitTransferHostLocal();
- break;
-
- case 1: // loc->host
- InitTransferLocalHost();
- break;
-
- case 2:
- TransferLocalLocal();
- break;
-
- case 3:
- gs.imageTransfer = -1;
- break;
-
- default:
- assert(0);
- }
- }
- else
- {
-#if defined(ZEROGS_DEVBUILD)
- ZZLog::Warn_Log("Dummy transfer.");
-#endif
- gs.imageTransfer = -1;
- }
- ZZLog::Greg_Log("TRXDIR");
-}
-
-void __gifCall GIFRegHandlerHWREG(const u32* data)
-{
- FUNCLOG
-
- if (gs.imageTransfer == 0)
- {
- TransferHostLocal(data, 2);
- }
- else
- {
-#if defined(ZEROGS_DEVBUILD)
- ZZLog::Error_Log("ZeroGS: HWREG!? %8.8x_%8.8x", data[0], data[1]);
- //assert(0);
-#endif
- }
- ZZLog::Greg_Log("HWREG");
-}
-
-extern int g_GSMultiThreaded;
-
-void __gifCall GIFRegHandlerSIGNAL(const u32* data)
-{
- FUNCLOG
-
- 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();
- }
-}
-
-void __gifCall GIFRegHandlerFINISH(const u32* data)
-{
- FUNCLOG
-
- if (!g_GSMultiThreaded)
- {
- if (gs.CSRw & 0x2) CSR->FINISH = 1;
-
- if (!IMR->FINISHMSK && GSirq) GSirq();
- }
-}
-
-void __gifCall GIFRegHandlerLABEL(const u32* data)
-{
- FUNCLOG
-
- if (!g_GSMultiThreaded)
- {
- SIGLBLID->LBLID = (SIGLBLID->LBLID & ~data[1]) | (data[0] & data[1]);
- }
-}
-
-
-void SetMultithreaded()
-{
- // Some older versions of PCSX2 didn't properly set the irq callback to NULL
- // in multithreaded mode (possibly because ZeroGS itself would assert in such
- // cases), and didn't bind them to a dummy callback either. PCSX2 handles all
- // IRQs internally when multithreaded anyway -- so let's ignore them here:
-
- if (g_GSMultiThreaded)
- {
- g_GIFRegHandlers[GIF_A_D_REG_SIGNAL] = &GIFRegHandlerNull;
- g_GIFRegHandlers[GIF_A_D_REG_FINISH] = &GIFRegHandlerNull;
- g_GIFRegHandlers[GIF_A_D_REG_LABEL] = &GIFRegHandlerNull;
- }
- else
- {
- g_GIFRegHandlers[GIF_A_D_REG_SIGNAL] = &GIFRegHandlerSIGNAL;
- g_GIFRegHandlers[GIF_A_D_REG_FINISH] = &GIFRegHandlerFINISH;
- g_GIFRegHandlers[GIF_A_D_REG_LABEL] = &GIFRegHandlerLABEL;
- }
-}
-
-void ResetRegs()
-{
- for (int i = 0; i < 16; i++)
- {
- g_GIFPackedRegHandlers[i] = &GIFPackedRegHandlerNull;
- }
-
- g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerPRIM;
- g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerRGBA;
- g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerSTQ;
- g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerUV;
- g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerXYZF2;
- g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerXYZ2;
- g_GIFPackedRegHandlers[GIF_REG_TEX0_1] = &GIFPackedRegHandlerTEX0<0>;
- g_GIFPackedRegHandlers[GIF_REG_TEX0_2] = &GIFPackedRegHandlerTEX0<1>;
- g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerCLAMP<0>;
- g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerCLAMP<1>;
- g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerFOG;
- g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerXYZF3;
- g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerXYZ3;
- g_GIFPackedRegHandlers[GIF_REG_A_D] = &GIFPackedRegHandlerA_D;
- g_GIFPackedRegHandlers[GIF_REG_NOP] = &GIFPackedRegHandlerNOP;
-
- for (int i = 0; i < 256; i++)
- {
- g_GIFRegHandlers[i] = &GIFPackedRegHandlerNull;
- }
-
- g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerPRIM;
- g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerRGBAQ;
- g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerST;
- g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerUV;
- g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerXYZF2;
- g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerXYZ2;
- g_GIFRegHandlers[GIF_A_D_REG_TEX0_1] = &GIFRegHandlerTEX0<0>;
- g_GIFRegHandlers[GIF_A_D_REG_TEX0_2] = &GIFRegHandlerTEX0<1>;
- g_GIFRegHandlers[GIF_A_D_REG_CLAMP_1] = &GIFRegHandlerCLAMP<0>;
- g_GIFRegHandlers[GIF_A_D_REG_CLAMP_2] = &GIFRegHandlerCLAMP<1>;
- g_GIFRegHandlers[GIF_A_D_REG_FOG] = &GIFRegHandlerFOG;
- g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerXYZF3;
- g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerXYZ3;
- g_GIFRegHandlers[GIF_A_D_REG_NOP] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_TEX1_1] = &GIFRegHandlerTEX1<0>;
- g_GIFRegHandlers[GIF_A_D_REG_TEX1_2] = &GIFRegHandlerTEX1<1>;
- g_GIFRegHandlers[GIF_A_D_REG_TEX2_1] = &GIFRegHandlerTEX2<0>;
- g_GIFRegHandlers[GIF_A_D_REG_TEX2_2] = &GIFRegHandlerTEX2<1>;
- g_GIFRegHandlers[GIF_A_D_REG_XYOFFSET_1] = &GIFRegHandlerXYOFFSET<0>;
- g_GIFRegHandlers[GIF_A_D_REG_XYOFFSET_2] = &GIFRegHandlerXYOFFSET<1>;
- g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerPRMODECONT;
- g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerPRMODE;
- g_GIFRegHandlers[GIF_A_D_REG_TEXCLUT] = &GIFRegHandlerTEXCLUT;
- g_GIFRegHandlers[GIF_A_D_REG_SCANMSK] = &GIFRegHandlerSCANMSK;
- g_GIFRegHandlers[GIF_A_D_REG_MIPTBP1_1] = &GIFRegHandlerMIPTBP1<0>;
- g_GIFRegHandlers[GIF_A_D_REG_MIPTBP1_2] = &GIFRegHandlerMIPTBP1<1>;
- g_GIFRegHandlers[GIF_A_D_REG_MIPTBP2_1] = &GIFRegHandlerMIPTBP2<0>;
- g_GIFRegHandlers[GIF_A_D_REG_MIPTBP2_2] = &GIFRegHandlerMIPTBP2<1>;
- g_GIFRegHandlers[GIF_A_D_REG_TEXA] = &GIFRegHandlerTEXA;
- g_GIFRegHandlers[GIF_A_D_REG_FOGCOL] = &GIFRegHandlerFOGCOL;
- g_GIFRegHandlers[GIF_A_D_REG_TEXFLUSH] = &GIFRegHandlerTEXFLUSH;
- g_GIFRegHandlers[GIF_A_D_REG_SCISSOR_1] = &GIFRegHandlerSCISSOR<0>;
- g_GIFRegHandlers[GIF_A_D_REG_SCISSOR_2] = &GIFRegHandlerSCISSOR<1>;
- g_GIFRegHandlers[GIF_A_D_REG_ALPHA_1] = &GIFRegHandlerALPHA<0>;
- g_GIFRegHandlers[GIF_A_D_REG_ALPHA_2] = &GIFRegHandlerALPHA<1>;
- g_GIFRegHandlers[GIF_A_D_REG_DIMX] = &GIFRegHandlerDIMX;
- g_GIFRegHandlers[GIF_A_D_REG_DTHE] = &GIFRegHandlerDTHE;
- g_GIFRegHandlers[GIF_A_D_REG_COLCLAMP] = &GIFRegHandlerCOLCLAMP;
- g_GIFRegHandlers[GIF_A_D_REG_TEST_1] = &GIFRegHandlerTEST<0>;
- g_GIFRegHandlers[GIF_A_D_REG_TEST_2] = &GIFRegHandlerTEST<1>;
- g_GIFRegHandlers[GIF_A_D_REG_PABE] = &GIFRegHandlerPABE;
- g_GIFRegHandlers[GIF_A_D_REG_FBA_1] = &GIFRegHandlerFBA<0>;
- g_GIFRegHandlers[GIF_A_D_REG_FBA_2] = &GIFRegHandlerFBA<1>;
- g_GIFRegHandlers[GIF_A_D_REG_FRAME_1] = &GIFRegHandlerFRAME<0>;
- g_GIFRegHandlers[GIF_A_D_REG_FRAME_2] = &GIFRegHandlerFRAME<1>;
- g_GIFRegHandlers[GIF_A_D_REG_ZBUF_1] = &GIFRegHandlerZBUF<0>;
- g_GIFRegHandlers[GIF_A_D_REG_ZBUF_2] = &GIFRegHandlerZBUF<1>;
- g_GIFRegHandlers[GIF_A_D_REG_BITBLTBUF] = &GIFRegHandlerBITBLTBUF;
- g_GIFRegHandlers[GIF_A_D_REG_TRXPOS] = &GIFRegHandlerTRXPOS;
- g_GIFRegHandlers[GIF_A_D_REG_TRXREG] = &GIFRegHandlerTRXREG;
- g_GIFRegHandlers[GIF_A_D_REG_TRXDIR] = &GIFRegHandlerTRXDIR;
- g_GIFRegHandlers[GIF_A_D_REG_HWREG] = &GIFRegHandlerHWREG;
- SetMultithreaded();
-}
-
-void WriteTempRegs()
-{
- memcpy(g_GIFTempRegHandlers, g_GIFPackedRegHandlers, sizeof(g_GIFTempRegHandlers));
-}
-
-void SetFrameSkip(bool skip)
-{
- if (skip)
- {
- g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerNOP;
- g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerNOP;
-
- g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerNOP;
- g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerNOP;
- }
- else
- {
- g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerPRIM;
- g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerRGBA;
- g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerSTQ;
- g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerUV;
- g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerXYZF2;
- g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerXYZ2;
- g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerCLAMP<0>;
- g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerCLAMP<1>;
- g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerFOG;
- g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerXYZF3;
- g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerXYZ3;
-
- g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerPRIM;
- g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerRGBAQ;
- g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerST;
- g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerUV;
- g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerXYZF2;
- g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerXYZ2;
- g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerXYZF3;
- g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerXYZ3;
- g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerPRMODECONT;
- g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerPRMODE;
- }
-}
-#endif
diff --git a/plugins/zzogl-pg/opengl/NewRegs.h b/plugins/zzogl-pg/opengl/NewRegs.h
deleted file mode 100644
index b915ef1b7b..0000000000
--- a/plugins/zzogl-pg/opengl/NewRegs.h
+++ /dev/null
@@ -1,973 +0,0 @@
-/* ZZ Open GL graphics plugin
- * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
- * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifndef NEWREGS_H_INCLUDED
-#define NEWREGS_H_INCLUDED
-
-#ifdef USE_OLD_REGS
-#include "Regs.h"
-#else
-
-enum GIF_REG
-{
- GIF_REG_PRIM = 0x00,
- GIF_REG_RGBA = 0x01,
- GIF_REG_STQ = 0x02,
- GIF_REG_UV = 0x03,
- GIF_REG_XYZF2 = 0x04,
- GIF_REG_XYZ2 = 0x05,
- GIF_REG_TEX0_1 = 0x06,
- GIF_REG_TEX0_2 = 0x07,
- GIF_REG_CLAMP_1 = 0x08,
- GIF_REG_CLAMP_2 = 0x09,
- GIF_REG_FOG = 0x0a,
- GIF_REG_XYZF3 = 0x0c,
- GIF_REG_XYZ3 = 0x0d,
- GIF_REG_A_D = 0x0e,
- GIF_REG_NOP = 0x0f,
-};
-
-enum GIF_A_D_REG
-{
- GIF_A_D_REG_PRIM = 0x00,
- GIF_A_D_REG_RGBAQ = 0x01,
- GIF_A_D_REG_ST = 0x02,
- GIF_A_D_REG_UV = 0x03,
- GIF_A_D_REG_XYZF2 = 0x04,
- GIF_A_D_REG_XYZ2 = 0x05,
- GIF_A_D_REG_TEX0_1 = 0x06,
- GIF_A_D_REG_TEX0_2 = 0x07,
- GIF_A_D_REG_CLAMP_1 = 0x08,
- GIF_A_D_REG_CLAMP_2 = 0x09,
- GIF_A_D_REG_FOG = 0x0a,
- GIF_A_D_REG_XYZF3 = 0x0c,
- GIF_A_D_REG_XYZ3 = 0x0d,
- GIF_A_D_REG_NOP = 0x0f,
- GIF_A_D_REG_TEX1_1 = 0x14,
- GIF_A_D_REG_TEX1_2 = 0x15,
- GIF_A_D_REG_TEX2_1 = 0x16,
- GIF_A_D_REG_TEX2_2 = 0x17,
- GIF_A_D_REG_XYOFFSET_1 = 0x18,
- GIF_A_D_REG_XYOFFSET_2 = 0x19,
- GIF_A_D_REG_PRMODECONT = 0x1a,
- GIF_A_D_REG_PRMODE = 0x1b,
- GIF_A_D_REG_TEXCLUT = 0x1c,
- GIF_A_D_REG_SCANMSK = 0x22,
- GIF_A_D_REG_MIPTBP1_1 = 0x34,
- GIF_A_D_REG_MIPTBP1_2 = 0x35,
- GIF_A_D_REG_MIPTBP2_1 = 0x36,
- GIF_A_D_REG_MIPTBP2_2 = 0x37,
- GIF_A_D_REG_TEXA = 0x3b,
- GIF_A_D_REG_FOGCOL = 0x3d,
- GIF_A_D_REG_TEXFLUSH = 0x3f,
- GIF_A_D_REG_SCISSOR_1 = 0x40,
- GIF_A_D_REG_SCISSOR_2 = 0x41,
- GIF_A_D_REG_ALPHA_1 = 0x42,
- GIF_A_D_REG_ALPHA_2 = 0x43,
- GIF_A_D_REG_DIMX = 0x44,
- GIF_A_D_REG_DTHE = 0x45,
- GIF_A_D_REG_COLCLAMP = 0x46,
- GIF_A_D_REG_TEST_1 = 0x47,
- GIF_A_D_REG_TEST_2 = 0x48,
- GIF_A_D_REG_PABE = 0x49,
- GIF_A_D_REG_FBA_1 = 0x4a,
- GIF_A_D_REG_FBA_2 = 0x4b,
- GIF_A_D_REG_FRAME_1 = 0x4c,
- GIF_A_D_REG_FRAME_2 = 0x4d,
- GIF_A_D_REG_ZBUF_1 = 0x4e,
- GIF_A_D_REG_ZBUF_2 = 0x4f,
- GIF_A_D_REG_BITBLTBUF = 0x50,
- GIF_A_D_REG_TRXPOS = 0x51,
- GIF_A_D_REG_TRXREG = 0x52,
- GIF_A_D_REG_TRXDIR = 0x53,
- GIF_A_D_REG_HWREG = 0x54,
- GIF_A_D_REG_SIGNAL = 0x60,
- GIF_A_D_REG_FINISH = 0x61,
- GIF_A_D_REG_LABEL = 0x62,
-};
-// In case we want to change to/from __fastcall for GIF register handlers:
-#define __gifCall __fastcall
-
-typedef void __gifCall FnType_GIFRegHandler(const u32* data);
-typedef FnType_GIFRegHandler* GIFRegHandler;
-
-extern FnType_GIFRegHandler GIFPackedRegHandlerNull;
-extern FnType_GIFRegHandler GIFPackedRegHandlerRGBA;
-extern FnType_GIFRegHandler GIFPackedRegHandlerSTQ;
-extern FnType_GIFRegHandler GIFPackedRegHandlerUV;
-extern FnType_GIFRegHandler GIFPackedRegHandlerXYZF2;
-extern FnType_GIFRegHandler GIFPackedRegHandlerXYZ2;
-extern FnType_GIFRegHandler GIFPackedRegHandlerFOG;
-extern FnType_GIFRegHandler GIFPackedRegHandlerA_D;
-extern FnType_GIFRegHandler GIFPackedRegHandlerNOP;
-
-// These are unimplemented, and fall back on the non-packed versions.
-extern FnType_GIFRegHandler GIFPackedRegHandlerPRIM;
-
-template
-extern FnType_GIFRegHandler GIFPackedRegHandlerTEX0;
-
-template
-extern FnType_GIFRegHandler GIFPackedRegHandlerCLAMP;
-
-extern FnType_GIFRegHandler GIFPackedRegHandlerXYZF3;
-extern FnType_GIFRegHandler GIFPackedRegHandlerXYZ3;
-
-extern FnType_GIFRegHandler GIFRegHandlerNull;
-extern FnType_GIFRegHandler GIFRegHandlerPRIM;
-extern FnType_GIFRegHandler GIFRegHandlerRGBAQ;
-extern FnType_GIFRegHandler GIFRegHandlerST;
-extern FnType_GIFRegHandler GIFRegHandlerUV;
-extern FnType_GIFRegHandler GIFRegHandlerXYZF2;
-extern FnType_GIFRegHandler GIFRegHandlerXYZ2;
-
-template
-extern FnType_GIFRegHandler GIFRegHandlerTEX0;
-
-template
-extern FnType_GIFRegHandler GIFRegHandlerCLAMP;
-
-extern FnType_GIFRegHandler GIFRegHandlerFOG;
-extern FnType_GIFRegHandler GIFRegHandlerXYZF3;
-extern FnType_GIFRegHandler GIFRegHandlerXYZ3;
-extern FnType_GIFRegHandler GIFRegHandlerNOP;
-
-template
-extern FnType_GIFRegHandler GIFRegHandlerTEX1;
-
-template
-extern FnType_GIFRegHandler GIFRegHandlerTEX2;
-
-template
-extern FnType_GIFRegHandler GIFRegHandlerXYOFFSET;
-
-extern FnType_GIFRegHandler GIFRegHandlerPRMODECONT;
-extern FnType_GIFRegHandler GIFRegHandlerPRMODE;
-extern FnType_GIFRegHandler GIFRegHandlerTEXCLUT;
-extern FnType_GIFRegHandler GIFRegHandlerSCANMSK;
-template
-extern FnType_GIFRegHandler GIFRegHandlerMIPTBP1;
-template
-extern FnType_GIFRegHandler GIFRegHandlerMIPTBP2;
-extern FnType_GIFRegHandler GIFRegHandlerTEXA;
-extern FnType_GIFRegHandler GIFRegHandlerFOGCOL;
-extern FnType_GIFRegHandler GIFRegHandlerTEXFLUSH;
-
-template
-extern FnType_GIFRegHandler GIFRegHandlerSCISSOR;
-template
-extern FnType_GIFRegHandler GIFRegHandlerALPHA;
-
-extern FnType_GIFRegHandler GIFRegHandlerDIMX;
-extern FnType_GIFRegHandler GIFRegHandlerDTHE;
-extern FnType_GIFRegHandler GIFRegHandlerCOLCLAMP;
-template
-extern FnType_GIFRegHandler GIFRegHandlerTEST;
-extern FnType_GIFRegHandler GIFRegHandlerPABE;
-template
-extern FnType_GIFRegHandler GIFRegHandlerFBA;
-template
-extern FnType_GIFRegHandler GIFRegHandlerFRAME;
-template
-extern FnType_GIFRegHandler GIFRegHandlerZBUF;
-extern FnType_GIFRegHandler GIFRegHandlerBITBLTBUF;
-extern FnType_GIFRegHandler GIFRegHandlerTRXPOS;
-extern FnType_GIFRegHandler GIFRegHandlerTRXREG;
-extern FnType_GIFRegHandler GIFRegHandlerTRXDIR;
-extern FnType_GIFRegHandler GIFRegHandlerHWREG;
-extern FnType_GIFRegHandler GIFRegHandlerSIGNAL;
-extern FnType_GIFRegHandler GIFRegHandlerFINISH;
-extern FnType_GIFRegHandler GIFRegHandlerLABEL;
-
-// GifReg & GifPackedReg structs from GSdx, slightly modified
-
-enum GS_ATST
-{
- ATST_NEVER = 0,
- ATST_ALWAYS = 1,
- ATST_LESS = 2,
- ATST_LEQUAL = 3,
- ATST_EQUAL = 4,
- ATST_GEQUAL = 5,
- ATST_GREATER = 6,
- ATST_NOTEQUAL = 7,
-};
-
-enum GS_AFAIL
-{
- AFAIL_KEEP = 0,
- AFAIL_FB_ONLY = 1,
- AFAIL_ZB_ONLY = 2,
- AFAIL_RGB_ONLY = 3,
-};
-
-// GIFReg
-
-REG64_(GIFReg, ALPHA)
- u32 A:2;
- u32 B:2;
- u32 C:2;
- u32 D:2;
- u32 _PAD1:24;
- u32 FIX:8;
- u32 _PAD2:24;
-REG_END2
- // opaque => output will be Cs/As
- __forceinline bool IsOpaque() const {return (A == B || C == 2 && FIX == 0) && D == 0 || (A == 0 && B == D && C == 2 && FIX == 0x80);}
- __forceinline bool IsOpaque(int amin, int amax) const {return (A == B || amax == 0) && D == 0 || A == 0 && B == D && amin == 0x80 && amax == 0x80;}
-REG_END2
-
-REG64_(GIFReg, BITBLTBUF)
- u32 SBP:14;
- u32 _PAD1:2;
- u32 SBW:6;
- u32 _PAD2:2;
- u32 SPSM:6;
- u32 _PAD3:2;
- u32 DBP:14;
- u32 _PAD4:2;
- u32 DBW:6;
- u32 _PAD5:2;
- u32 DPSM:6;
- u32 _PAD6:2;
-REG_END
-
-REG64_(GIFReg, CLAMP)
-union
-{
- struct
- {
- u32 WMS:2;
- u32 WMT:2;
- u32 MINU:10;
- u32 MAXU:10;
- u32 _PAD1:8;
- u32 _PAD2:2;
- u32 MAXV:10;
- u32 _PAD3:20;
- };
-
- struct
- {
- u64 _PAD4:24;
- u64 MINV:10;
- u64 _PAD5:30;
- };
-};
-REG_END
-
-REG64_(GIFReg, COLCLAMP)
- u32 CLAMP:1;
- u32 _PAD1:31;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, DIMX)
- s32 DM00:3;
- s32 _PAD00:1;
- s32 DM01:3;
- s32 _PAD01:1;
- s32 DM02:3;
- s32 _PAD02:1;
- s32 DM03:3;
- s32 _PAD03:1;
- s32 DM10:3;
- s32 _PAD10:1;
- s32 DM11:3;
- s32 _PAD11:1;
- s32 DM12:3;
- s32 _PAD12:1;
- s32 DM13:3;
- s32 _PAD13:1;
- s32 DM20:3;
- s32 _PAD20:1;
- s32 DM21:3;
- s32 _PAD21:1;
- s32 DM22:3;
- s32 _PAD22:1;
- s32 DM23:3;
- s32 _PAD23:1;
- s32 DM30:3;
- s32 _PAD30:1;
- s32 DM31:3;
- s32 _PAD31:1;
- s32 DM32:3;
- s32 _PAD32:1;
- s32 DM33:3;
- s32 _PAD33:1;
-REG_END
-
-REG64_(GIFReg, DTHE)
- u32 DTHE:1;
- u32 _PAD1:31;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, FBA)
- u32 FBA:1;
- u32 _PAD1:31;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, FINISH)
- u32 _PAD1:32;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, FOG)
- u32 _PAD1:32;
- u32 _PAD2:24;
- u32 F:8;
-REG_END
-
-REG64_(GIFReg, FOGCOL)
- u32 FCR:8;
- u32 FCG:8;
- u32 FCB:8;
- u32 _PAD1:8;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, FRAME)
- u32 FBP:9;
- u32 _PAD1:7;
- u32 FBW:6;
- u32 _PAD2:2;
- u32 PSM:6;
- u32 _PAD3:2;
- u32 FBMSK:32;
-REG_END2
- u32 Block() const {return FBP << 5;}
-REG_END2
-
-REG64_(GIFReg, HWREG)
- u32 DATA_LOWER:32;
- u32 DATA_UPPER:32;
-REG_END
-
-REG64_(GIFReg, LABEL)
- u32 ID:32;
- u32 IDMSK:32;
-REG_END
-
-REG64_(GIFReg, MIPTBP1)
- u64 TBP1:14;
- u64 TBW1:6;
- u64 TBP2:14;
- u64 TBW2:6;
- u64 TBP3:14;
- u64 TBW3:6;
- u64 _PAD:4;
-REG_END
-
-REG64_(GIFReg, MIPTBP2)
- u64 TBP4:14;
- u64 TBW4:6;
- u64 TBP5:14;
- u64 TBW5:6;
- u64 TBP6:14;
- u64 TBW6:6;
- u64 _PAD:4;
-REG_END
-
-REG64_(GIFReg, NOP)
- u32 _PAD1:32;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, PABE)
- u32 PABE:1;
- u32 _PAD1:31;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, PRIM)
- u32 PRIM:3;
- u32 IIP:1;
- u32 TME:1;
- u32 FGE:1;
- u32 ABE:1;
- u32 AA1:1;
- u32 FST:1;
- u32 CTXT:1;
- u32 FIX:1;
- u32 _PAD1:21;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, PRMODE)
- u32 _PRIM:3;
- u32 IIP:1;
- u32 TME:1;
- u32 FGE:1;
- u32 ABE:1;
- u32 AA1:1;
- u32 FST:1;
- u32 CTXT:1;
- u32 FIX:1;
- u32 _PAD2:21;
- u32 _PAD3:32;
-REG_END
-
-REG64_(GIFReg, PRMODECONT)
- u32 AC:1;
- u32 _PAD1:31;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, RGBAQ)
- u32 R:8;
- u32 G:8;
- u32 B:8;
- u32 A:8;
- float Q;
-REG_END
-
-REG64_(GIFReg, SCANMSK)
- u32 MSK:2;
- u32 _PAD1:30;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, SCISSOR)
- u32 SCAX0:11;
- u32 _PAD1:5;
- u32 SCAX1:11;
- u32 _PAD2:5;
- u32 SCAY0:11;
- u32 _PAD3:5;
- u32 SCAY1:11;
- u32 _PAD4:5;
-REG_END
-
-REG64_(GIFReg, SIGNAL)
- u32 ID:32;
- u32 IDMSK:32;
-REG_END
-
-REG64_(GIFReg, ST)
- float S;
- float T;
-REG_END
-
-REG64_(GIFReg, TEST)
- u32 ATE:1;
- u32 ATST:3;
- u32 AREF:8;
- u32 AFAIL:2;
- u32 DATE:1;
- u32 DATM:1;
- u32 ZTE:1;
- u32 ZTST:2;
- u32 _PAD1:13;
- u32 _PAD2:32;
-REG_END2
- __forceinline bool DoFirstPass() {return !ATE || ATST != ATST_NEVER;} // not all pixels fail automatically
- __forceinline bool DoSecondPass() {return ATE && ATST != ATST_ALWAYS && AFAIL != AFAIL_KEEP;} // pixels may fail, write fb/z
- __forceinline bool NoSecondPass() {return ATE && ATST != ATST_ALWAYS && AFAIL == AFAIL_KEEP;} // pixels may fail, no output
-REG_END2
-
-REG64_(GIFReg, TEX0)
-union
-{
- struct
- {
- u32 TBP0:14;
- u32 TBW:6;
- u32 PSM:6;
- u32 TW:4;
- u32 _PAD1:2;
- u32 _PAD2:2;
- u32 TCC:1;
- u32 TFX:2;
- u32 CBP:14;
- u32 CPSM:4;
- u32 CSM:1;
- u32 CSA:5;
- u32 CLD:3;
- };
-
- struct
- {
- u64 _PAD3:30;
- u64 TH:4;
- u64 _PAD4:30;
- };
-};
-REG_END2
- __forceinline bool IsRepeating() {return (u32)((u32)1 << TW) > (u32)(TBW << (u32)6);}
-REG_END2
-
-REG64_(GIFReg, TEX1)
- u32 LCM:1;
- u32 _PAD1:1;
- u32 MXL:3;
- u32 MMAG:1;
- u32 MMIN:3;
- u32 MTBA:1;
- u32 _PAD2:9;
- u32 L:2;
- u32 _PAD3:11;
- s32 K:12; // 1:7:4
- u32 _PAD4:20;
-REG_END2
- bool IsMinLinear() const {return (MMIN == 1) || (MMIN & 4);}
- bool IsMagLinear() const {return MMAG;}
-REG_END2
-
-REG64_(GIFReg, TEX2)
- u32 _PAD1:20;
- u32 PSM:6;
- u32 _PAD2:6;
- u32 _PAD3:5;
- u32 CBP:14;
- u32 CPSM:4;
- u32 CSM:1;
- u32 CSA:5;
- u32 CLD:3;
-REG_END
-
-REG64_(GIFReg, TEXA)
- u32 TA0:8;
- u32 _PAD1:7;
- u32 AEM:1;
- u32 _PAD2:16;
- u32 TA1:8;
- u32 _PAD3:24;
-REG_END
-
-REG64_(GIFReg, TEXCLUT)
- u32 CBW:6;
- u32 COU:6;
- u32 COV:10;
- u32 _PAD1:10;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, TEXFLUSH)
- u32 _PAD1:32;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, TRXDIR)
- u32 XDIR:2;
- u32 _PAD1:30;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GIFReg, TRXPOS)
- u32 SSAX:11;
- u32 _PAD1:5;
- u32 SSAY:11;
- u32 _PAD2:5;
- u32 DSAX:11;
- u32 _PAD3:5;
- u32 DSAY:11;
- u32 DIRY:1;
- u32 DIRX:1;
- u32 _PAD4:3;
-REG_END
-
-REG64_(GIFReg, TRXREG)
- u32 RRW:12;
- u32 _PAD1:20;
- u32 RRH:12;
- u32 _PAD2:20;
-REG_END
-
-REG64_(GIFReg, UV)
- u32 U:14;
- u32 _PAD1:2;
- u32 V:14;
- u32 _PAD2:2;
- u32 _PAD3:32;
-REG_END
-
-REG64_(GIFReg, XYOFFSET)
- u32 OFX:16;
- u32 _PAD1:16;
- u32 OFY:16;
- u32 _PAD2:16;
-REG_END
-
-REG64_(GIFReg, XYZ)
- u32 X:16;
- u32 Y:16;
- u32 Z:32;
-REG_END
-
-REG64_(GIFReg, XYZF)
- u32 X:16;
- u32 Y:16;
- u32 Z:24;
- u32 F:8;
-REG_END
-
-REG64_(GIFReg, ZBUF)
- u32 ZBP:9;
- u32 _PAD1:15;
- // u32 PSM:4;
- // u32 _PAD2:4;
- u32 PSM:6;
- u32 _PAD2:2;
- u32 ZMSK:1;
- u32 _PAD3:31;
-REG_END2
- u32 Block() const {return ZBP << 5;}
-REG_END2
-
-REG64_SET(GIFReg)
- GIFRegALPHA ALPHA;
- GIFRegBITBLTBUF BITBLTBUF;
- GIFRegCLAMP CLAMP;
- GIFRegCOLCLAMP COLCLAMP;
- GIFRegDIMX DIMX;
- GIFRegDTHE DTHE;
- GIFRegFBA FBA;
- GIFRegFINISH FINISH;
- GIFRegFOG FOG;
- GIFRegFOGCOL FOGCOL;
- GIFRegFRAME FRAME;
- GIFRegHWREG HWREG;
- GIFRegLABEL LABEL;
- GIFRegMIPTBP1 MIPTBP1;
- GIFRegMIPTBP2 MIPTBP2;
- GIFRegNOP NOP;
- GIFRegPABE PABE;
- GIFRegPRIM PRIM;
- GIFRegPRMODE PRMODE;
- GIFRegPRMODECONT PRMODECONT;
- GIFRegRGBAQ RGBAQ;
- GIFRegSCANMSK SCANMSK;
- GIFRegSCISSOR SCISSOR;
- GIFRegSIGNAL SIGNAL;
- GIFRegST ST;
- GIFRegTEST TEST;
- GIFRegTEX0 TEX0;
- GIFRegTEX1 TEX1;
- GIFRegTEX2 TEX2;
- GIFRegTEXA TEXA;
- GIFRegTEXCLUT TEXCLUT;
- GIFRegTEXFLUSH TEXFLUSH;
- GIFRegTRXDIR TRXDIR;
- GIFRegTRXPOS TRXPOS;
- GIFRegTRXREG TRXREG;
- GIFRegUV UV;
- GIFRegXYOFFSET XYOFFSET;
- GIFRegXYZ XYZ;
- GIFRegXYZF XYZF;
- GIFRegZBUF ZBUF;
-REG_SET_END
-
-// GIFPacked
-
-REG128_(GIFPacked, PRIM)
- u32 PRIM:11;
- u32 _PAD1:21;
- u32 _PAD2:32;
- u32 _PAD3:32;
- u32 _PAD4:32;
-REG_END
-
-REG128_(GIFPacked, RGBA)
- u32 R:8;
- u32 _PAD1:24;
- u32 G:8;
- u32 _PAD2:24;
- u32 B:8;
- u32 _PAD3:24;
- u32 A:8;
- u32 _PAD4:24;
-REG_END
-
-REG128_(GIFPacked, STQ)
- float S;
- float T;
- float Q;
- u32 _PAD1:32;
-REG_END
-
-REG128_(GIFPacked, UV)
- u32 U:14;
- u32 _PAD1:18;
- u32 V:14;
- u32 _PAD2:18;
- u32 _PAD3:32;
- u32 _PAD4:32;
-REG_END
-
-REG128_(GIFPacked, XYZF2)
- u32 X:16;
- u32 _PAD1:16;
- u32 Y:16;
- u32 _PAD2:16;
- u32 _PAD3:4;
- u32 Z:24;
- u32 _PAD4:4;
- u32 _PAD5:4;
- u32 F:8;
- u32 _PAD6:3;
- u32 ADC:1;
- u32 _PAD7:16;
-REG_END
-
-REG128_(GIFPacked, XYZ2)
- u32 X:16;
- u32 _PAD1:16;
- u32 Y:16;
- u32 _PAD2:16;
- u32 Z:32;
- u32 _PAD3:15;
- u32 ADC:1;
- u32 _PAD4:16;
-REG_END
-
-REG128_(GIFPacked, FOG)
- u32 _PAD1:32;
- u32 _PAD2:32;
- u32 _PAD3:32;
- u32 _PAD4:4;
- u32 F:8;
- u32 _PAD5:20;
-REG_END
-
-REG128_(GIFPacked, A_D)
- u64 DATA:64;
- u32 ADDR:8; // enum GIF_A_D_REG
- u32 _PAD1:24;
- u32 _PAD2:32;
-REG_END
-
-REG128_(GIFPacked, NOP)
- u32 _PAD1:32;
- u32 _PAD2:32;
- u32 _PAD3:32;
- u32 _PAD4:32;
-REG_END
-
-REG128_SET(GIFPackedReg)
- GIFReg r;
- GIFPackedPRIM PRIM;
- GIFPackedRGBA RGBA;
- GIFPackedSTQ STQ;
- GIFPackedUV UV;
- GIFPackedXYZF2 XYZF2;
- GIFPackedXYZ2 XYZ2;
- GIFPackedFOG FOG;
- GIFPackedA_D A_D;
- GIFPackedNOP NOP;
-REG_SET_END
-
-REG64_(GSReg, BGCOLOR)
- u32 R:8;
- u32 G:8;
- u32 B:8;
- u32 _PAD1:8;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GSReg, BUSDIR)
- u32 DIR:1;
- u32 _PAD1:31;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GSReg, CSR)
- u32 SIGNAL:1;
- u32 FINISH:1;
- u32 HSINT:1;
- u32 VSINT:1;
- u32 EDWINT:1;
- u32 ZERO1:1;
- u32 ZERO2:1;
- u32 _PAD1:1;
- u32 FLUSH:1;
- u32 RESET:1;
- u32 _PAD2:2;
- u32 NFIELD:1;
- u32 FIELD:1;
- u32 FIFO:2;
- u32 REV:8;
- u32 ID:8;
- u32 _PAD3:32;
-REG_END
-
-REG64_(GSReg, DISPFB) // (-1/2)
- u32 FBP:9;
- u32 FBW:6;
- u32 PSM:5;
- u32 _PAD:12;
- u32 DBX:11;
- u32 DBY:11;
- u32 _PAD2:10;
-REG_END
-
-REG64_(GSReg, DISPLAY) // (-1/2)
- u32 DX:12;
- u32 DY:11;
- u32 MAGH:4;
- u32 MAGV:2;
- u32 _PAD:3;
- u32 DW:12;
- u32 DH:11;
- u32 _PAD2:9;
-REG_END
-
-REG64_(GSReg, EXTBUF)
- u32 EXBP:14;
- u32 EXBW:6;
- u32 FBIN:2;
- u32 WFFMD:1;
- u32 EMODA:2;
- u32 EMODC:2;
- u32 _PAD1:5;
- u32 WDX:11;
- u32 WDY:11;
- u32 _PAD2:10;
-REG_END
-
-REG64_(GSReg, EXTDATA)
- u32 SX:12;
- u32 SY:11;
- u32 SMPH:4;
- u32 SMPV:2;
- u32 _PAD1:3;
- u32 WW:12;
- u32 WH:11;
- u32 _PAD2:9;
-REG_END
-
-REG64_(GSReg, EXTWRITE)
- u32 WRITE;
- u32 _PAD2:32;
-REG_END
-
-REG64_(GSReg, IMR)
- u32 _PAD1:8;
- u32 SIGMSK:1;
- u32 FINISHMSK:1;
- u32 HSMSK:1;
- u32 VSMSK:1;
- u32 EDWMSK:1;
- u32 _PAD2:19;
- u32 _PAD3:32;
-REG_END
-
-REG64_(GSReg, PMODE)
- u32 EN1:1;
- u32 EN2:1;
- u32 CRTMD:3;
- u32 MMOD:1;
- u32 AMOD:1;
- u32 SLBG:1;
- u32 ALP:8;
- u32 _PAD:16;
- u32 _PAD1:32;
-REG_END
-
-REG64_(GSReg, SIGLBLID)
- u32 SIGID:32;
- u32 LBLID:32;
-REG_END
-
-REG64_(GSReg, SMODE1)
- u32 RC:3;
- u32 LC:7;
- u32 T1248:2;
- u32 SLCK:1;
- u32 CMOD:2;
- u32 EX:1;
- u32 PRST:1;
- u32 SINT:1;
- u32 XPCK:1;
- u32 PCK2:2;
- u32 SPML:4;
- u32 GCONT:1;
- u32 PHS:1;
- u32 PVS:1;
- u32 PEHS:1;
- u32 PEVS:1;
- u32 CLKSEL:2;
- u32 NVCK:1;
- u32 SLCK2:1;
- u32 VCKSEL:2;
- u32 VHP:1;
- u32 _PAD1:27;
-REG_END
-
-REG64_(GSReg, SMODE2)
- u32 INT:1;
- u32 FFMD:1;
- u32 DPMS:2;
- u32 _PAD2:28;
- u32 _PAD3:32;
-REG_END
-
-REG64_(GSReg, SIGBLID)
- u32 SIGID;
- u32 LBLID;
-REG_END
-
-#define PMODE ((GSRegPMODE*)(g_pBasePS2Mem+0x0000))
-#define SMODE1 ((GSRegSMODE1*)(g_pBasePS2Mem+0x0010))
-#define SMODE2 ((GSRegSMODE2*)(g_pBasePS2Mem+0x0020))
-// SRFSH
-#define SYNCH1 ((GSRegSYNCH1*)(g_pBasePS2Mem+0x0040))
-#define SYNCH2 ((GSRegSYNCH2*)(g_pBasePS2Mem+0x0050))
-#define SYNCV ((GSRegSYNCV*)(g_pBasePS2Mem+0x0060))
-#define DISPFB1 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0070))
-#define DISPLAY1 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x0080))
-#define DISPFB2 ((GSRegDISPFB*)(g_pBasePS2Mem+0x0090))
-#define DISPLAY2 ((GSRegDISPLAY*)(g_pBasePS2Mem+0x00a0))
-#define EXTBUF ((GSRegEXTBUF*)(g_pBasePS2Mem+0x00b0))
-#define EXTDATA ((GSRegEXTDATA*)(g_pBasePS2Mem+0x00c0))
-#define EXTWRITE ((GSRegEXTWRITE*)(g_pBasePS2Mem+0x00d0))
-#define BGCOLOR ((GSRegBGCOLOR*)(g_pBasePS2Mem+0x00e0))
-#define CSR ((GSRegCSR*)(g_pBasePS2Mem+0x1000))
-#define IMR ((GSRegIMR*)(g_pBasePS2Mem+0x1010))
-#define BUSDIR ((GSRegBUSDIR*)(g_pBasePS2Mem+0x1040))
-#define SIGLBLID ((GSRegSIGBLID*)(g_pBasePS2Mem+0x1080))
-
-//
-// sps2tags.h
-//
-#define GET_GIF_REG(tag, reg) \
- (((tag).ai32[2 + ((reg) >> 3)] >> (((reg) & 7) << 2)) & 0xf)
-
-#define GET_GSFPS (((SMODE1->CMOD&1) ? 50 : 60) / (SMODE2->INT ? 1 : 2))
-
-extern void WriteTempRegs();
-extern void SetFrameSkip(bool skip);
-extern void ResetRegs();
-
-extern void SetTexFlush();
-extern void SetFogColor(u32 fog);
-extern void SetFogColor(GIFRegFOGCOL* fog);
-extern bool CheckChangeInClut(u32 highdword, u32 psm); // returns true if clut will change after this tex0 op
-
-// flush current vertices, call before setting new registers (the main render method)
-void Flush(int context);
-void FlushBoth();
-
-// called on a primitive switch
-void Prim();
-
-#endif
-
-#endif // NEWREGS_H_INCLUDED
diff --git a/plugins/zzogl-pg/opengl/Regs.cpp b/plugins/zzogl-pg/opengl/Regs.cpp
index a033e7a641..9df70fd612 100644
--- a/plugins/zzogl-pg/opengl/Regs.cpp
+++ b/plugins/zzogl-pg/opengl/Regs.cpp
@@ -26,7 +26,6 @@
#include "ZZoglVB.h"
#include "ZZoglDrawing.h"
-#ifdef USE_OLD_REGS
#ifdef _MSC_VER
#pragma warning(disable:4244)
@@ -157,6 +156,9 @@ void __gifCall GIFPackedRegHandlerFOG(const u32* data)
void __gifCall GIFPackedRegHandlerA_D(const u32* data)
{
FUNCLOG
+// GIFPackedA_D* r = (GIFPackedA_D*)(data);
+//
+// g_GIFRegHandlers[r->ADDR](data);
if ((data[2] & 0xff) < 100)
g_GIFRegHandlers[data[2] & 0xff](data);
@@ -188,21 +190,20 @@ void __gifCall GIFRegHandlerNull(const u32* data)
void __gifCall GIFRegHandlerPRIM(const u32 *data)
{
FUNCLOG
+ GIFRegPRIM* r = (GIFRegPRIM*)(data);
//if (data[0] & ~0x3ff)
//{
//ZZLog::Warn_Log("Warning: unknown bits in prim %8.8lx_%8.8lx", data[1], data[0]);
//}
-
-
+
gs.primC = 0;
- u16 prim_type = (data[0]) & 0x7;
- prim->prim = prim_type;
- gs._prim[0].prim = prim_type;
- gs._prim[1].prim = prim_type;
- gs._prim[1]._val = (data[0] >> 3) & 0xff;
+ prim->prim = r->PRIM;
+ gs._prim[0].prim = r->PRIM;
+ gs._prim[1].prim = r->PRIM;
+ gs._prim[1]._val = (data[0] >> 3) & 0xff; // Setting the next 8 flags after prim at once.
- gs.new_tri_fan = !(prim_type ^ PRIM_TRIANGLE_FAN);
+ gs.new_tri_fan = !(r->PRIM ^ PRIM_TRIANGLE_FAN);
ZZKick->DirtyValidPrevPrim();
Prim();
@@ -211,6 +212,10 @@ void __gifCall GIFRegHandlerPRIM(const u32 *data)
void __gifCall GIFRegHandlerRGBAQ(const u32* data)
{
FUNCLOG
+// GIFRegRGBAQ* r = (GIFRegRGBAQ*)(data);
+// gs.rgba = (r->R | (r->G << 8) | (r->B << 16) | (r->A << 24));
+// gs.vertexregs.rgba = gs.rgba;
+// gs.vertexregs.q = r->Q;
gs.rgba = data[0];
gs.vertexregs.rgba = data[0];
*(u32*)&gs.vertexregs.q = data[1];
@@ -219,6 +224,9 @@ void __gifCall GIFRegHandlerRGBAQ(const u32* data)
void __gifCall GIFRegHandlerST(const u32* data)
{
FUNCLOG
+// GIFRegST* r = (GIFRegST*)(data);
+// gs.vertexregs.s = r->S;
+// gs.vertexregs.t = r->T;
*(u32*)&gs.vertexregs.s = data[0] & 0xffffff00;
*(u32*)&gs.vertexregs.t = data[1] & 0xffffff00;
//*(u32*)&gs.q = data[2];
@@ -445,7 +453,10 @@ void __gifCall GIFRegHandlerXYOFFSET(const u32* data)
void __gifCall GIFRegHandlerPRMODECONT(const u32* data)
{
FUNCLOG
- gs.prac = data[0] & 0x1;
+ // Turns all the text into colored blocks on the initial Mana Khemia dialog if not run.
+ GIFRegPRMODECONT* r = (GIFRegPRMODECONT*)(data);
+// gs.prac = data[0] & 0x1;
+ gs.prac = r->AC;
prim = &gs._prim[gs.prac];
Prim();
@@ -468,6 +479,7 @@ void __gifCall GIFRegHandlerTEXCLUT(const u32* data)
vb[0].FlushTexData();
vb[1].FlushTexData();
+ //Fixme
gs.clut.cbw = r->CBW << 6;
gs.clut.cou = r->COU << 4;
gs.clut.cov = r->COV;
@@ -477,9 +489,6 @@ void __gifCall GIFRegHandlerSCANMSK(const u32* data)
{
FUNCLOG
GIFRegSCANMSK* r = (GIFRegSCANMSK*)(data);
-// FlushBoth();
-// ResolveC(&vb[0]);
-// ResolveZ(&vb[0]);
gs.smask = r->MSK;
REG_LOG("Scanmsk == %d", gs.smask);
@@ -534,23 +543,20 @@ void __gifCall GIFRegHandlerMIPTBP2(const u32* data)
void __gifCall GIFRegHandlerTEXA(const u32* data)
{
FUNCLOG
- texaInfo newinfo;
- newinfo.aem = (data[0] >> 15) & 0x1;
- newinfo.ta[0] = data[0] & 0xff;
- newinfo.ta[1] = data[1] & 0xff;
-
- if (*(u32*)&newinfo != *(u32*)&gs.texa)
+ // Background of initial Mana Khemia dialog.
+ GIFRegTEXA* r = (GIFRegTEXA*)(data);
+
+ if ((r->AEM != gs.texa.aem) || (r->TA0 != gs.texa.ta[0]) || (r->TA1 != gs.texa.ta[1]))
{
FlushBoth();
-
- *(u32*)&gs.texa = *(u32*) & newinfo;
-
- gs.texa.fta[0] = newinfo.ta[0] / 255.0f;
- gs.texa.fta[1] = newinfo.ta[1] / 255.0f;
vb[0].bTexConstsSync = false;
vb[1].bTexConstsSync = false;
}
+
+ gs.texa.aem = r->AEM;
+ gs.texa.ta[0] = r->TA0;
+ gs.texa.ta[1] = r->TA1;
}
void __gifCall GIFRegHandlerFOGCOL(const u32* data)
@@ -564,6 +570,7 @@ void __gifCall GIFRegHandlerFOGCOL(const u32* data)
void __gifCall GIFRegHandlerTEXFLUSH(const u32* data)
{
FUNCLOG
+ // Not actually handled by GSDX.
SetTexFlush();
}
@@ -597,6 +604,12 @@ void __gifCall GIFRegHandlerALPHA(const u32* data)
{
FUNCLOG
alphaInfo newalpha;
+// newalpha.a = r->A;
+// newalpha.b = r->B;
+// newalpha.c = r->C;
+// newalpha.d = r->D;
+// newalpha.fix = r->FIX;
+
newalpha.abcd = *(u8*)data;
newalpha.fix = *(u8*)(data + 1);
@@ -610,9 +623,11 @@ void __gifCall GIFRegHandlerALPHA(const u32* data)
if (newalpha.d == 3) newalpha.d = 0;
*(u16*)&vb[ctxt].alpha = *(u16*) & newalpha;
+// vb[i].alpha = newalpha;
}
}
+// DIMX & DTHE are both for dithering, and not currently implemented.
void __gifCall GIFRegHandlerDIMX(const u32* data)
{
FUNCLOG
@@ -647,14 +662,18 @@ template
void __gifCall GIFRegHandlerTEST(const u32* data)
{
FUNCLOG
+// GIFRegTEST* r = (GIFRegTEST*)(data);
pixTest* test = &vb[ctxt].test;
- if ((*(u32*)test & 0x0007ffff) == (data[0] & 0x0007ffff)) return;
+ //if (test->_val != r->ai32[0])
+ if ((*(u32*)test & 0x0007ffff) != (data[0] & 0x0007ffff))
+ {
+ Flush(ctxt);
- Flush(ctxt);
-
- *(u32*)test = data[0];
+ *(u32*)test = data[0];
+ //test->_val = r->ai32[0];
+ }
// test.ate = (data[0] ) & 0x1;
// test.atst = (data[0] >> 1) & 0x7;
@@ -688,6 +707,48 @@ void __gifCall GIFRegHandlerFBA(const u32* data)
vb[ctxt].fba.fba = r->FBA;
}
+/*
+template
+void __gifCall GIFRegHandlerFRAME(const u32* data)
+{
+ FUNCLOG
+ // Affects opening dialogs, movie, and menu on Mana Khemia.
+
+ GIFRegFRAME* r = (GIFRegFRAME*)(data);
+ frameInfo& gsfb = vb[i].gsfb;
+
+ int fbw = r->FBW * 64;
+ int fbp = r->FBP * 32;
+ int fbh = 0;
+
+ if (gs.dthe != 0)
+ {
+ // Dither here.
+ //ZZLog::Error_Log("frameWrite: Dither!");
+ }
+
+ if ((gsfb.fbp == fbp) &&
+ (gsfb.fbw == fbw) &&
+ (gsfb.psm == r->PSM) &&
+ (gsfb.fbm == ZZOglGet_fbm_FrameBitsFix(data[0], data[1])))
+ {
+ return;
+ }
+
+ FlushBoth();
+ if (r->FBW > 0) fbh = ZZOgl_fbh_Calc(r->FBP, r->FBW, r->PSM);
+
+ gsfb.fbp = fbp;
+ gsfb.fbw = fbw;
+ gsfb.psm = r->PSM;
+ gsfb.fbh = fbh;
+ gsfb.fbm = ZZOglGet_fbm_FrameBitsFix(data[0], data[1]);
+
+
+ vb[i].bNeedFrameCheck = 1;
+ ZZLog::Greg_Log("FRAME_%d", i);
+}*/
+
template
void __gifCall GIFRegHandlerFRAME(const u32* data)
{
@@ -715,6 +776,41 @@ void __gifCall GIFRegHandlerFRAME(const u32* data)
vb[ctxt].bNeedFrameCheck = 1;
}
+/*
+template
+void __gifCall GIFRegHandlerZBUF(const u32* data)
+{
+ FUNCLOG
+ // I'll wait a bit on this one.
+ GIFRegZBUF* r = (GIFRegZBUF*)(data);
+ ZZLog::Greg_Log("ZBUF_1");
+
+ zbufInfo& zbuf = vb[i].zbuf;
+ int psm = (0x30 | r->PSM);
+ int zbp = r->ZBP * 32;
+
+ if (zbuf.zbp == zbp &&
+ zbuf.psm == psm &&
+ zbuf.zmsk == r->ZMSK)
+ {
+ return;
+ }
+
+ // error detection
+ if (m_Blocks[psm].bpp == 0) return;
+
+ FlushBoth();
+
+ zbuf.zbp = zbp;
+ zbuf.psm = psm;
+ zbuf.zmsk = r->ZMSK;
+
+ vb[i].zprimmask = 0xffffffff;
+
+ if (zbuf.psm > 0x31) vb[i].zprimmask = 0xffff;
+
+ vb[i].bNeedZCheck = 1;
+}*/
template
void __gifCall GIFRegHandlerZBUF(const u32* data)
{
@@ -758,6 +854,17 @@ void __gifCall GIFRegHandlerBITBLTBUF(const u32* data)
gs.dstbufnew.psm = r->DPSM;
if (gs.dstbufnew.bw == 0) gs.dstbufnew.bw = 64;
+ // GSdx does this:
+
+ /*if((gs.srcbufnew.bw & 1) && (gs.srcbufnew.psm == PSM_PSMT8 || gs.srcbufnew.psm == PSM_PSMT4))
+ {
+ gs.srcbufnew.bw &= ~1;
+ }
+
+ if((gs.dstbufnew.bw & 1) && (gs.dstbufnew.psm == PSM_PSMT8 || gs.dstbufnew.psm == PSM_PSMT4))
+ {
+ gs.dstbufnew.bw &= ~1; // namcoXcapcom: 5, 11, refered to as 4, 10 in TEX0.TBW later
+ }*/
}
void __gifCall GIFRegHandlerTRXPOS(const u32* data)
@@ -777,53 +884,44 @@ void __gifCall GIFRegHandlerTRXREG(const u32* data)
{
FUNCLOG
GIFRegTRXREG* r = (GIFRegTRXREG*)(data);
- gs.imageWtemp = r->RRW;
- gs.imageHtemp = r->RRH;
+ gs.imageTemp.w = r->RRW;
+ gs.imageTemp.h = r->RRH;
}
void __gifCall GIFRegHandlerTRXDIR(const u32* data)
{
FUNCLOG
- // terminate any previous transfers
-
- switch (gs.imageTransfer)
- {
-
- case 0: // host->loc
- TerminateHostLocal();
- break;
-
- case 1: // loc->host
- TerminateLocalHost();
- break;
- }
+ GIFRegTRXDIR* r = (GIFRegTRXDIR*)(data);
gs.srcbuf = gs.srcbufnew;
-
gs.dstbuf = gs.dstbufnew;
+
+ gs.imageNew.w = gs.imageTemp.w;
+ gs.imageNew.h = gs.imageTemp.h;
+
gs.trxpos = gs.trxposnew;
- gs.imageTransfer = data[0] & 0x3;
- gs.imageWnew = gs.imageWtemp;
- gs.imageHnew = gs.imageHtemp;
+ gs.imageTransfer = r->XDIR;
+ gs.transferring = true;
- if (gs.imageWnew > 0 && gs.imageHnew > 0)
+ if (gs.imageNew.w > 0 && gs.imageNew.h > 0)
{
switch (gs.imageTransfer)
{
- case 0: // host->loc
+ case XFER_HOST_TO_LOCAL: // host->loc
InitTransferHostLocal();
break;
- case 1: // loc->host
+ case XFER_LOCAL_TO_HOST: // loc->host
InitTransferLocalHost();
break;
- case 2:
+ case XFER_LOCAL_TO_LOCAL:
TransferLocalLocal();
break;
- case 3:
- gs.imageTransfer = -1;
+ case XFER_DEACTIVATED:
+ ZZLog::WriteLn("Image Transfer = 3?");
+ gs.transferring = false;
break;
default:
@@ -833,9 +931,9 @@ void __gifCall GIFRegHandlerTRXDIR(const u32* data)
else
{
#if defined(ZEROGS_DEVBUILD)
- ZZLog::Warn_Log("Dummy transfer.");
+ //ZZLog::Warn_Log("Dummy transfer.");
#endif
- gs.imageTransfer = -1;
+ gs.transferring = false;
}
}
@@ -843,7 +941,7 @@ void __gifCall GIFRegHandlerHWREG(const u32* data)
{
FUNCLOG
- if (gs.imageTransfer == 0)
+ if (gs.transferring && gs.imageTransfer == XFER_HOST_TO_LOCAL)
{
TransferHostLocal(data, 2);
}
@@ -866,14 +964,9 @@ void __gifCall GIFRegHandlerSIGNAL(const u32* data)
{
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)
{
CSR->SIGNAL = 1;
- //gs.CSRw &= ~1;
}
if (!IMR->SIGMSK && GSirq) GSirq();
@@ -889,17 +982,6 @@ void __gifCall GIFRegHandlerFINISH(const u32* data)
if (gs.CSRw & 0x2) CSR->FINISH = 1;
if (!IMR->FINISHMSK && GSirq) GSirq();
-
-// if( gs.CSRw & 2 ) {
-// //gs.CSRw &= ~2;
-// //CSR->FINISH = 0;
-//
-//
-// }
-// CSR->FINISH = 1;
-//
-// if( !IMR->FINISHMSK && GSirq )
-// GSirq();
}
}
@@ -913,7 +995,6 @@ void __gifCall GIFRegHandlerLABEL(const u32* data)
}
}
-
void SetMultithreaded()
{
// Some older versions of PCSX2 didn't properly set the irq callback to NULL
@@ -1077,4 +1158,3 @@ void SetFrameSkip(bool skip)
}
}
-#endif
diff --git a/plugins/zzogl-pg/opengl/Regs.h b/plugins/zzogl-pg/opengl/Regs.h
index 59608d3967..ba196473b9 100644
--- a/plugins/zzogl-pg/opengl/Regs.h
+++ b/plugins/zzogl-pg/opengl/Regs.h
@@ -20,9 +20,6 @@
#ifndef __GSREGS_H__
#define __GSREGS_H__
-
-#ifdef USE_OLD_REGS
-
enum GIF_REG
{
GIF_REG_PRIM = 0x00,
@@ -193,7 +190,7 @@ enum GS_ATST
ATST_EQUAL = 4,
ATST_GEQUAL = 5,
ATST_GREATER = 6,
- ATST_NOTEQUAL = 7,
+ ATST_NOTEQUAL = 7
};
enum GS_AFAIL
@@ -201,9 +198,24 @@ enum GS_AFAIL
AFAIL_KEEP = 0,
AFAIL_FB_ONLY = 1,
AFAIL_ZB_ONLY = 2,
- AFAIL_RGB_ONLY = 3,
+ AFAIL_RGB_ONLY = 3
+};
+
+enum GS_TFX
+{
+ TFX_MODULATE = 0,
+ TFX_DECAL = 1,
+ TFX_HIGHLIGHT = 2,
+ TFX_HIGHLIGHT2 = 3
};
+enum GS_CLAMP
+{
+ CLAMP_REPEAT = 0,
+ CLAMP_CLAMP = 1,
+ CLAMP_REGION_CLAMP = 2,
+ CLAMP_REGION_REPEAT = 3
+};
// GIFReg
REG64_(GIFReg, ALPHA)
@@ -763,7 +775,8 @@ REG128_SET(GIFPackedReg)
GIFPackedNOP NOP;
REG_SET_END
-
+// This register stores the background color. Theoretically it'd get blended with the image in some cases, but we don't appear to be
+// using it. See PMODE->SLBG. GSDx *is* using it.
REG64_(GSReg, BGCOLOR)
u32 R:8;
u32 G:8;
@@ -772,12 +785,15 @@ REG64_(GSReg, BGCOLOR)
u32 _PAD2:32;
REG_END
+// This register switches the direction of Fifo. 0 - Host -> Local; 1 - Local -> Host. Fifo is supposed to be empty at the time.
+// Unchecked by GSdx or ZZOgl.
REG64_(GSReg, BUSDIR)
u32 DIR:1;
u32 _PAD1:31;
u32 _PAD2:32;
REG_END
+// Mostly looks handled by pcsx2.
REG64_(GSReg, CSR)
u32 SIGNAL:1;
u32 FINISH:1;
@@ -798,6 +814,12 @@ REG64_(GSReg, CSR)
u32 _PAD3:32;
REG_END
+// Settings for whichever circuit we're using. (Again, see PMODE.)
+// -- FBP - Frame Buffer Pointer. address / 2048.
+// -- FBW - Frame Buffer Width. width / 64.
+// -- PSM - psm, but 5 bit. 0 - PSMCT32; 1 - PSMCT24; 2 - PSMCT16; 10 - PSMCT16S; 18 - PS-GPU24?
+// -- DBX - Upper left x coords of rectangle.
+// -- DBY - Upper left y coords of rectangle.
REG64_(GSReg, DISPFB) // (-1/2)
u32 FBP:9;
u32 FBW:6;
@@ -808,6 +830,14 @@ REG64_(GSReg, DISPFB) // (-1/2)
u32 _PAD2:10;
REG_END
+// Settings for whichever display we're using.
+// -- DX - X position in the display area.
+// -- DY - Y position in the display area.
+// -- MAGH - Horizontal Magnification; x1 - x16.
+// -- MAGV - Vertical Magnification; x1 - x16.
+// -- DW - Display Area Width - 1.
+// -- DH - Display Area Height - 1.
+
REG64_(GSReg, DISPLAY) // (-1/2)
u32 DX:12;
u32 DY:11;
@@ -819,6 +849,16 @@ REG64_(GSReg, DISPLAY) // (-1/2)
u32 _PAD2:9;
REG_END
+// This register has settings for the frame buffer when writing back. These next three registers are unused in ZZOgl & GSDx.
+// -- EXBP - Base pointer of the buffer / 64.
+// -- EXBW - Width of the buffer / 64.
+// -- FBIN - Whether we use OUT1 or OUT2. 0 - 1; 1 - 2.
+// -- WFFMD - Interlace Mode; 0 - Field; 1 - Frame.
+// -- EMODA - When processing an input alpha value; 0 - write it as is; 1 Convert from RGB to luminence value Y. 2 - Same as 1, only /2. 3 - 0.
+// -- EMODC - When processing an input color value; 0 - write it as is; 1 Convert from RGB to luminence value Y. 2 - Convert to YCbCr. 3 - Write Alpha to RGB.
+// -- WDX - X coords.
+// -- WDY - Y coords.
+
REG64_(GSReg, EXTBUF)
u32 EXBP:14;
u32 EXBW:6;
@@ -832,6 +872,14 @@ REG64_(GSReg, EXTBUF)
u32 _PAD2:10;
REG_END
+// Sets where you read when the write above is performed.
+// -- SX - X coords.
+// -- SX - Y coords.
+// -- SMPH - Horiz Sampling rate.
+// -- SMPV - Vert Sampling rate.
+// -- WW - Rect Width - 1
+// -- WH - Rect Height - 1
+
REG64_(GSReg, EXTDATA)
u32 SX:12;
u32 SY:11;
@@ -843,11 +891,13 @@ REG64_(GSReg, EXTDATA)
u32 _PAD2:9;
REG_END
+// Starts or stops the aforementioned write.
REG64_(GSReg, EXTWRITE)
u32 WRITE;
u32 _PAD2:32;
REG_END
+// Pcsx2 handles this.
REG64_(GSReg, IMR)
u32 _PAD1:8;
u32 SIGMSK:1;
@@ -859,6 +909,16 @@ REG64_(GSReg, IMR)
u32 _PAD3:32;
REG_END
+// The fields of PMODE are:
+// -- EN1 - Read Circuit 1; 0 - off, 1 - on.
+// -- EN2 - Read Circuit 2; 0 - off, 1 - on.
+// -- CRTMD - Always 1.
+// -- MMOD - For Alpha blending, the selection is: 0 - The Alpha value of circuit 1, 1 - The ALP register value.
+// -- AMOD - The OUT1 Alpha value selection: 0 - Read circuit 1, 1 - Read Circuit 2.
+// -- SLBG - The Alpha blending type: 0 - blended with the output of Read circuit 1, 1 - blended with the background color.
+// -- ALP - The fixed Alpha value.
+//
+
REG64_(GSReg, PMODE)
u32 EN1:1;
u32 EN2:1;
@@ -871,11 +931,13 @@ REG64_(GSReg, PMODE)
u32 _PAD1:32;
REG_END
+// Pcsx2 handles this.
REG64_(GSReg, SIGLBLID)
u32 SIGID:32;
u32 LBLID:32;
REG_END
+// Not sure about this one...
REG64_(GSReg, SMODE1)
u32 RC:3;
u32 LC:7;
@@ -901,6 +963,11 @@ REG64_(GSReg, SMODE1)
u32 _PAD1:27;
REG_END
+// The fields of SMODE2 are:
+// -- INT - 0 for non-interlaced; 1 for interlaced.
+// -- FFMD - 0 for field mode (read every other line); 1 for frame mode (read every line)
+// -- DPMS - VESA DPMS mode setting; 0 - on, 1 - standby, 2 - suspend, 3 - off.
+//
REG64_(GSReg, SMODE2)
u32 INT:1;
u32 FFMD:1;
@@ -914,6 +981,8 @@ REG64_(GSReg, SIGBLID)
u32 LBLID;
REG_END
+extern u8* g_pBasePS2Mem;
+
#define PMODE ((GSRegPMODE*)(g_pBasePS2Mem+0x0000))
#define SMODE1 ((GSRegSMODE1*)(g_pBasePS2Mem+0x0010))
#define SMODE2 ((GSRegSMODE2*)(g_pBasePS2Mem+0x0020))
@@ -942,6 +1011,21 @@ REG_END
#define GET_GSFPS (((SMODE1->CMOD&1) ? 50 : 60) / (SMODE2->INT ? 1 : 2))
+static __forceinline GSRegDISPLAY* Display_Reg(int circuit)
+{
+ return (circuit) ? DISPLAY2 : DISPLAY1;
+}
+
+static __forceinline GSRegDISPFB* Dispfb_Reg(int circuit)
+{
+ return (circuit) ? DISPFB2 : DISPFB1;
+}
+
+static __forceinline bool Circuit_Enabled(int circuit)
+{
+ return (circuit) ? PMODE->EN2 : PMODE->EN1;
+}
+
extern void WriteTempRegs();
extern void SetFrameSkip(bool skip);
extern void ResetRegs();
@@ -958,7 +1042,4 @@ void FlushBoth();
// called on a primitive switch
void Prim();
-#else
-#include "NewRegs.h"
-#endif
#endif
diff --git a/plugins/zzogl-pg/opengl/Util.h b/plugins/zzogl-pg/opengl/Util.h
index 99c98d80a4..c269d737a1 100644
--- a/plugins/zzogl-pg/opengl/Util.h
+++ b/plugins/zzogl-pg/opengl/Util.h
@@ -58,10 +58,12 @@
#include "CRC.h"
#include "ZZLog.h"
+#ifdef _WIN32
// need C definitions -- no mangling please!
extern "C" u32 CALLBACK PS2EgetLibType(void);
extern "C" u32 CALLBACK PS2EgetLibVersion2(u32 type);
extern "C" char* CALLBACK PS2EgetLibName(void);
+#endif
#include "ZZoglMath.h"
#include "Profile.h"
diff --git a/plugins/zzogl-pg/opengl/ZZClut.cpp b/plugins/zzogl-pg/opengl/ZZClut.cpp
index 3ac380c90b..dae5b846cb 100644
--- a/plugins/zzogl-pg/opengl/ZZClut.cpp
+++ b/plugins/zzogl-pg/opengl/ZZClut.cpp
@@ -22,7 +22,7 @@
#include "Util.h"
#if defined(ZEROGS_SSE2)
-#include
+#include
#endif
// Local Clut buffer:
diff --git a/plugins/zzogl-pg/opengl/ZZDepthTargets.cpp b/plugins/zzogl-pg/opengl/ZZDepthTargets.cpp
new file mode 100644
index 0000000000..a46a6a1043
--- /dev/null
+++ b/plugins/zzogl-pg/opengl/ZZDepthTargets.cpp
@@ -0,0 +1,314 @@
+/* ZZ Open GL graphics plugin
+ * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
+ * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+#include
+
+#include "GS.h"
+#include "Mem.h"
+#include "x86.h"
+#include "targets.h"
+#include "ZZoglShaders.h"
+#include "ZZClut.h"
+#include "ZZoglVB.h"
+
+#ifdef ZEROGS_SSE2
+#include
+#endif
+
+extern bool g_bUpdateStencil;
+
+void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm, bool mode);
+void SetWriteDepth();
+bool IsWriteDepth();
+bool IsWriteDestAlphaTest();
+
+const float g_filog32 = 0.999f / (32.0f * logf(2.0f));
+
+CDepthTarget::CDepthTarget() : CRenderTarget(), pdepth(0), pstencil(0), icount(0) {}
+
+CDepthTarget::~CDepthTarget()
+{
+ FUNCLOG
+
+ Destroy();
+}
+
+bool CDepthTarget::Create(const frameInfo& frame)
+{
+ FUNCLOG
+
+ if (!CRenderTarget::Create(frame)) return false;
+
+ GL_REPORT_ERROR();
+
+ glGenRenderbuffersEXT(1, &pdepth);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pdepth);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, RW(fbw), RH(fbh));
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+ // try a separate depth and stencil buffer
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pdepth);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, RW(fbw), RH(fbh));
+
+ if (g_bUpdateStencil)
+ {
+ glGenRenderbuffersEXT(1, &pstencil);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pstencil);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, RW(fbw), RH(fbh));
+
+ if (glGetError() != GL_NO_ERROR)
+ {
+ ZZLog::Error_Log("Failed to create depth buffer %dx%d.", RW(fbw), RH(fbh));
+ return false;
+ }
+ }
+ else
+ {
+ pstencil = 0;
+ }
+ }
+ else
+ {
+ pstencil = pdepth;
+ }
+
+ status = TS_NeedUpdate;
+
+ return true;
+}
+
+void CDepthTarget::Destroy()
+{
+ FUNCLOG
+
+ if (status) // In this case Framebuffer extension is off-use and lead to segfault
+ {
+ ResetRenderTarget(1);
+ FB::Attach(GL_DEPTH_ATTACHMENT_EXT);
+ FB::Attach(GL_STENCIL_ATTACHMENT_EXT);
+ GL_REPORT_ERRORD();
+
+ if (pstencil != 0)
+ {
+ if (pstencil != pdepth) glDeleteRenderbuffersEXT(1, &pstencil);
+ pstencil = 0;
+ }
+
+ if (pdepth != 0)
+ {
+ glDeleteRenderbuffersEXT(1, &pdepth);
+ pdepth = 0;
+ }
+
+ GL_REPORT_ERRORD();
+ }
+
+ CRenderTarget::Destroy();
+}
+
+
+extern int g_nDepthUsed; // > 0 if depth is used
+
+void CDepthTarget::Resolve()
+{
+ FUNCLOG
+
+ if (g_nDepthUsed > 0 && conf.mrtdepth && !(status & TS_Virtual) && IsWriteDepth() && !(conf.settings().no_depth_resolve))
+ CRenderTarget::Resolve();
+ else
+ {
+ // flush if necessary
+ FlushIfNecesary(this);
+
+ if (!(status & TS_Virtual)) status |= TS_Resolved;
+ }
+
+ if (!(status&TS_Virtual))
+ {
+ SetWriteDepth();
+ }
+}
+
+void CDepthTarget::Resolve(int startrange, int endrange)
+{
+ FUNCLOG
+
+ if (g_nDepthUsed > 0 && conf.mrtdepth && !(status&TS_Virtual) && IsWriteDepth())
+ {
+ CRenderTarget::Resolve(startrange, endrange);
+ }
+ else
+ {
+ // flush if necessary
+ FlushIfNecesary(this) ;
+
+ if (!(status & TS_Virtual))
+ status |= TS_Resolved;
+ }
+
+ if (!(status&TS_Virtual))
+ {
+ SetWriteDepth();
+ }
+}
+
+void CDepthTarget::Update(int context, CRenderTarget* prndr)
+{
+ FUNCLOG
+
+ assert(!(status & TS_Virtual));
+
+ // align the rect to the nearest page
+ // note that fbp is always aligned on page boundaries
+ tex0Info texframe;
+ texframe.tbp0 = fbp;
+ texframe.tbw = fbw;
+ texframe.tw = fbw;
+ texframe.th = fbh;
+ texframe.psm = psm;
+ // FIXME some field are not initialized...
+ // in particular the clut related one
+ assert(!PSMT_ISCLUT(psm));
+
+ DisableAllgl();
+
+ VB& curvb = vb[context];
+
+ if (curvb.test.zte == 0) return;
+
+ SetShaderCaller("CDepthTarget::Update");
+
+ glEnable(GL_DEPTH_TEST);
+
+ glDepthMask(!curvb.zbuf.zmsk);
+
+ static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER };
+
+ glDepthFunc(g_dwZCmp[curvb.test.ztst]);
+
+ // write color and zero out stencil buf, always 0 context!
+ SetTexVariablesInt(0, 0, texframe, false, &ppsBitBltDepth, 1);
+ ZZshGLSetTextureParameter(ppsBitBltDepth.prog, ppsBitBltDepth.sMemory, vb[0].pmemtarg->ptex->tex, "BitBltDepth");
+
+ float4 v = DefaultBitBltPos();
+
+ v = DefaultBitBltTex();
+
+ v.x = 1;
+ v.y = 2;
+ v.z = PSMT_IS16Z(psm) ? 1.0f : 0.0f;
+ v.w = g_filog32;
+ ZZshSetParameter4fv(ppsBitBltDepth.prog, ppsBitBltDepth.sOneColor, v, "g_fOneColor");
+
+ float4 vdepth = g_vdepth;
+
+ if (psm == PSMT24Z)
+ {
+ vdepth.w = 0;
+ }
+ else if (psm != PSMT32Z)
+ {
+ vdepth.z = vdepth.w = 0;
+ }
+
+ assert(ppsBitBltDepth.sBitBltZ != 0);
+
+ ZZshSetParameter4fv(ppsBitBltDepth.prog, ppsBitBltDepth.sBitBltZ, (vdepth*(255.0f / 256.0f)), "g_fBitBltZ");
+
+ assert(pdepth != 0);
+ //GLint w1 = 0;
+ //GLint h1 = 0;
+
+ FB::Attach2D(0, ptex);
+ //glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w1);
+ //glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &h1);
+ SetDepthStencilSurface();
+
+ FB::Attach2D(1);
+
+ GLenum buffer = GL_COLOR_ATTACHMENT0_EXT;
+
+ //ZZLog::Error_Log("CDepthTarget::Update: w1 = 0x%x; h1 = 0x%x", w1, h1);
+ DrawBuffers(&buffer);
+
+ SetViewport();
+
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vboRect);
+
+ SET_STREAM();
+ ZZshSetVertexShader(pvsBitBlt.prog);
+ ZZshSetPixelShader(ppsBitBltDepth.prog);
+
+ DrawTriangleArray();
+
+ status = TS_Resolved;
+
+ if (!IsWriteDepth())
+ {
+ ResetRenderTarget(1);
+ }
+
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ glEnable(GL_SCISSOR_TEST);
+
+#ifdef _DEBUG
+ if (g_bSaveZUpdate)
+ {
+ SaveTex(&texframe, 1);
+ SaveTexture("frame1.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh));
+ }
+#endif
+}
+
+void CDepthTarget::SetDepthStencilSurface()
+{
+ FUNCLOG
+ FB::Attach(GL_DEPTH_ATTACHMENT_EXT, pdepth);
+
+ if (pstencil)
+ {
+ // there's a bug with attaching stencil and depth buffers
+ FB::Attach(GL_STENCIL_ATTACHMENT_EXT, pstencil);
+
+ if (icount++ < 8) // not going to fail if succeeded 4 times
+ {
+ GL_REPORT_ERRORD();
+
+ if (FB::State() != GL_FRAMEBUFFER_COMPLETE_EXT)
+ {
+ FB::Attach(GL_STENCIL_ATTACHMENT_EXT);
+
+ if (pstencil != pdepth) glDeleteRenderbuffersEXT(1, &pstencil);
+
+ pstencil = 0;
+ g_bUpdateStencil = 0;
+ }
+ }
+ }
+ else
+ {
+ FB::Attach(GL_STENCIL_ATTACHMENT_EXT);
+ }
+}
+
diff --git a/plugins/zzogl-pg/opengl/ZZGl.h b/plugins/zzogl-pg/opengl/ZZGl.h
index c2979b7185..5db66e56f1 100644
--- a/plugins/zzogl-pg/opengl/ZZGl.h
+++ b/plugins/zzogl-pg/opengl/ZZGl.h
@@ -47,8 +47,11 @@ inline void* wglGetProcAddress(const char* x)
#endif
+#include "Mem.h"
+
extern u32 s_stencilfunc, s_stencilref, s_stencilmask;
-// Defines
+extern GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT
+extern GLenum s_rgbeq, s_alphaeq;
#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils
# define GL_DEPTH_STENCIL_EXT 0x84F9
@@ -57,28 +60,50 @@ extern u32 s_stencilfunc, s_stencilref, s_stencilmask;
# define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
#endif
-#define GL_STENCILFUNC(func, ref, mask) { \
- s_stencilfunc = func; \
- s_stencilref = ref; \
- s_stencilmask = mask; \
- glStencilFunc(func, ref, mask); \
+#ifdef _WIN32
+#define GL_LOADFN(name) { \
+ if( (*(void**)&name = (void*)wglGetProcAddress(#name)) == NULL ) { \
+ ZZLog::Error_Log("Failed to find %s, exiting.", #name); \
+ } \
+}
+#else
+// let GLEW take care of it
+#define GL_LOADFN(name)
+#endif
+
+static __forceinline void GL_STENCILFUNC(GLenum func, GLint ref, GLuint mask)
+{
+ s_stencilfunc = func;
+ s_stencilref = ref;
+ s_stencilmask = mask;
+ glStencilFunc(func, ref, mask);
}
-#define GL_STENCILFUNC_SET() glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask)
-
+static __forceinline void GL_STENCILFUNC_SET()
+{
+ glStencilFunc(s_stencilfunc, s_stencilref, s_stencilmask);
+}
// sets the data stream
-#define SET_STREAM() { \
- glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)8); \
- glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12); \
- glTexCoordPointer(3, GL_FLOAT, sizeof(VertexGPU), (void*)16); \
- glVertexPointer(4, GL_SHORT, sizeof(VertexGPU), (void*)0); \
+static __forceinline void SET_STREAM()
+{
+ glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)8);
+ glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, sizeof(VertexGPU), (void*)12);
+ glTexCoordPointer(3, GL_FLOAT, sizeof(VertexGPU), (void*)16);
+ glVertexPointer(4, GL_SHORT, sizeof(VertexGPU), (void*)0);
}
-
// global alpha blending settings
extern GLenum g_internalRGBAFloat16Fmt;
+//static __forceinline void SAFE_RELEASE_TEX(u32& x)
+//{
+// if (x != 0)
+// {
+// glDeleteTextures(1, &x);
+// x = 0;
+// }
+//}
#define SAFE_RELEASE_TEX(x) { if( (x) != 0 ) { glDeleteTextures(1, &(x)); x = 0; } }
// inline for an extremely often used sequence
@@ -104,12 +129,192 @@ extern void (APIENTRY *zgsBlendEquationSeparateEXT)(GLenum, GLenum);
extern void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum);
#endif
+static __forceinline void DrawTriangleArray()
+{
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ GL_REPORT_ERRORD();
+}
-// ------------------------ Types -------------------------
+static __forceinline void DrawBuffers(GLenum *buffer)
+{
+ if (glDrawBuffers != NULL)
+ {
+ glDrawBuffers(1, buffer);
+ }
-/////////////////////
-// graphics resources
-extern GLenum s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha; // set by zgsBlendFuncSeparateEXT
+ GL_REPORT_ERRORD();
+}
+
+
+namespace FB
+{
+ extern u32 buf;
+
+ static __forceinline void Create()
+ {
+ glGenFramebuffersEXT(1, &buf);
+ }
+
+ static __forceinline void Bind()
+ {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buf);
+ }
+
+ static __forceinline void Unbind()
+ {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ }
+
+ static __forceinline GLenum State()
+ {
+ return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ }
+
+ static __forceinline void Attach2D(int attach, int id = 0)
+ {
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + attach, GL_TEXTURE_RECTANGLE_NV, id, 0);
+ GL_REPORT_ERRORD();
+ }
+
+ static __forceinline void Attach(GLenum rend, GLuint id = 0)
+ {
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, rend, GL_RENDERBUFFER_EXT, id);
+ }
+};
+
+static __forceinline void ResetRenderTarget(int index)
+{
+ FB::Attach2D(index);
+}
+
+static __forceinline void TextureImage(GLenum tex_type, GLint iFormat, GLint width, GLint height, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ glTexImage2D(tex_type, 0, iFormat, width, height, 0, format, type, pixels);
+}
+
+static __forceinline void Texture2D(GLint iFormat, GLint width, GLint height, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ TextureImage(GL_TEXTURE_2D, iFormat, width, height, format, type, pixels);
+}
+
+static __forceinline void Texture2D(GLint iFormat, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ TextureImage(GL_TEXTURE_2D, iFormat, BLOCK_TEXWIDTH, BLOCK_TEXHEIGHT, format, type, pixels);
+}
+
+static __forceinline void TextureRect(GLint iFormat, GLint width, GLint height, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ TextureImage(GL_TEXTURE_RECTANGLE_NV, iFormat, width, height, format, type, pixels);
+}
+
+static __forceinline void TextureRect2(GLint iFormat, GLint width, GLint height, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ TextureImage(GL_TEXTURE_RECTANGLE, iFormat, width, height, format, type, pixels);
+}
+
+static __forceinline void Texture3D(GLint iFormat, GLint width, GLint height, GLint depth, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ glTexImage3D(GL_TEXTURE_3D, 0, iFormat, width, height, depth, 0, format, type, pixels);
+}
+
+static __forceinline void setTex2DFilters(GLint type)
+{
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, type);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, type);
+}
+
+static __forceinline void setTex2DWrap(GLint type)
+{
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, type);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, type);
+}
+
+static __forceinline void setTex3DFilters(GLint type)
+{
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, type);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, type);
+}
+
+static __forceinline void setTex3DWrap(GLint type)
+{
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, type);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, type);
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, type);
+}
+
+static __forceinline void setRectFilters(GLint type)
+{
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, type);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, type);
+}
+
+static __forceinline void setRectWrap(GLint type)
+{
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, type);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, type);
+}
+
+static __forceinline void setRectWrap2(GLint type)
+{
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, type);
+ glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, type);
+}
+
+static __forceinline void GL_BLEND_SET()
+{
+ zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha);
+}
+
+static __forceinline void GL_BLEND_RGB(GLenum src, GLenum dst)
+{
+ s_srcrgb = src;
+ s_dstrgb = dst;
+ GL_BLEND_SET();
+}
+
+static __forceinline void GL_BLEND_ALPHA(GLenum src, GLenum dst)
+{
+ s_srcalpha = src;
+ s_dstalpha = dst;
+ GL_BLEND_SET();
+}
+
+static __forceinline void GL_BLEND_ALL(GLenum srcrgb, GLenum dstrgb, GLenum srcalpha, GLenum dstalpha)
+{
+ s_srcrgb = srcrgb;
+ s_dstrgb = dstrgb;
+ s_srcalpha = srcalpha;
+ s_dstalpha = dstalpha;
+ GL_BLEND_SET();
+}
+
+static __forceinline void GL_ZTEST(bool enable)
+{
+ if (enable)
+ glEnable(GL_DEPTH_TEST);
+ else
+ glDisable(GL_DEPTH_TEST);
+}
+
+static __forceinline void GL_ALPHATEST(bool enable)
+{
+ if (enable)
+ glEnable(GL_ALPHA_TEST);
+ else
+ glDisable(GL_ALPHA_TEST);
+}
+
+static __forceinline void GL_BLENDEQ_RGB(GLenum eq)
+{
+ s_rgbeq = eq;
+ zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq);
+}
+
+static __forceinline void GL_BLENDEQ_ALPHA(GLenum eq)
+{
+ s_alphaeq = eq;
+ zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq);
+}
// GL prototypes
extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
diff --git a/plugins/zzogl-pg/opengl/ZZLog.cpp b/plugins/zzogl-pg/opengl/ZZLog.cpp
index 668a0d6dbd..f3ddae5104 100644
--- a/plugins/zzogl-pg/opengl/ZZLog.cpp
+++ b/plugins/zzogl-pg/opengl/ZZLog.cpp
@@ -27,7 +27,7 @@ extern GSconf conf;
using namespace std;
static list listMsgs;
-
+const char* logging_prefix = "ZZOgl-PG";
void ProcessMessages()
{
FUNCLOG
@@ -130,12 +130,14 @@ void _Log(const char *str)
void _WriteToConsole(const char *str)
{
- fprintf(stderr,"ZZogl-PG: %s", str);
+ fprintf(stderr,"%s: ", logging_prefix);
+ fprintf(stderr,"%s", str);
}
void _Print(const char *str)
{
- fprintf(stderr,"ZZogl-PG: %s", str);
+ fprintf(stderr,"%s: ", logging_prefix);
+ fprintf(stderr,"%s", str);
if (IsLogging()) fprintf(gsLog, str);
}
@@ -169,7 +171,7 @@ void WriteToConsole(const char *fmt, ...)
va_start(list, fmt);
- fprintf(stderr, "ZZogl-PG: ");
+ fprintf(stderr, "%s: ", logging_prefix);
vfprintf(stderr, fmt, list);
va_end(list);
}
@@ -182,7 +184,7 @@ void Print(const char *fmt, ...)
if (IsLogging()) vfprintf(gsLog, fmt, list);
- fprintf(stderr, "ZZogl-PG: ");
+ fprintf(stderr, "%s: ", logging_prefix);
vfprintf(stderr, fmt, list);
va_end(list);
@@ -197,7 +199,7 @@ void WriteLn(const char *fmt, ...)
if (IsLogging()) vfprintf(gsLog, fmt, list);
- fprintf(stderr, "ZZogl-PG: ");
+ fprintf(stderr, "%s: ", logging_prefix);
vfprintf(stderr, fmt, list);
va_end(list);
fprintf(stderr,"\n");
@@ -237,7 +239,7 @@ void Prim_Log(const char *fmt, ...)
{
if (IsLogging()) vfprintf(gsLog, fmt, list);
- fprintf(stderr, "ZZogl-PG(PRIM): ");
+ fprintf(stderr, "%s(PRIM): ", logging_prefix);
vfprintf(stderr, fmt, list);
vprintf(fmt, list);
@@ -262,7 +264,7 @@ void GS_Log(const char *fmt, ...)
fprintf(gsLog, "\n");
}
- fprintf(stderr, "ZZogl-PG: ");
+ fprintf(stderr, "%s: ", logging_prefix);
vfprintf(stderr, fmt, list);
fprintf(stderr, "\n");
@@ -283,7 +285,7 @@ void Warn_Log(const char *fmt, ...)
fprintf(gsLog, "\n");
}
- fprintf(stderr, "ZZogl-PG: ");
+ fprintf(stderr, "%s(Warning): ", logging_prefix);
vfprintf(stderr, fmt, list);
fprintf(stderr, "\n");
@@ -304,7 +306,7 @@ void Dev_Log(const char *fmt, ...)
fprintf(gsLog, "\n");
}
- fprintf(stderr, "ZZogl-PG: ");
+ fprintf(stderr, "%s: ", logging_prefix);
vfprintf(stderr, fmt, list);
fprintf(stderr, "\n");
@@ -325,7 +327,7 @@ void Debug_Log(const char *fmt, ...)
fprintf(gsLog, "\n");
}
- fprintf(stderr, "ZZogl-PG: ");
+ fprintf(stderr, "%s: ", logging_prefix);
vfprintf(stderr, fmt, list);
fprintf(stderr, "\n");
@@ -345,7 +347,7 @@ void Error_Log(const char *fmt, ...)
fprintf(gsLog, "\n");
}
- fprintf(stderr, "ZZogl-PG: ");
+ fprintf(stderr, "%s: ", logging_prefix);
vfprintf(stderr, fmt, list);
fprintf(stderr, "\n");
diff --git a/plugins/zzogl-pg/opengl/ZZMemoryTargets.cpp b/plugins/zzogl-pg/opengl/ZZMemoryTargets.cpp
new file mode 100644
index 0000000000..9125d0ee32
--- /dev/null
+++ b/plugins/zzogl-pg/opengl/ZZMemoryTargets.cpp
@@ -0,0 +1,620 @@
+/* ZZ Open GL graphics plugin
+ * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
+ * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+#include
+
+#include "GS.h"
+#include "Mem.h"
+#include "targets.h"
+#include "ZZClut.h"
+
+#ifdef ZEROGS_SSE2
+#include
+#endif
+
+extern int g_TransferredToGPU;
+
+extern int VALIDATE_THRESH;
+extern u32 TEXDESTROY_THRESH;
+#define FORCE_TEXDESTROY_THRESH (3) // destroy texture after FORCE_TEXDESTROY_THRESH frames
+
+void CMemoryTargetMngr::Destroy()
+{
+ FUNCLOG
+ listTargets.clear();
+ listClearedTargets.clear();
+}
+
+bool CMemoryTarget::ValidateTex(const tex0Info& tex0, int starttex, int endtex, bool bDeleteBadTex)
+{
+ FUNCLOG
+
+ if (clearmaxy == 0) return true;
+
+ int checkstarty = max(starttex, clearminy);
+ int checkendy = min(endtex, clearmaxy);
+
+ if (checkstarty >= checkendy) return true;
+
+ if (validatecount++ > VALIDATE_THRESH)
+ {
+ height = 0;
+ return false;
+ }
+
+ // lock and compare
+ assert(ptex != NULL && ptex->memptr != NULL);
+
+ int result = memcmp_mmx(ptex->memptr + MemorySize(checkstarty-realy), MemoryAddress(checkstarty), MemorySize(checkendy-checkstarty));
+
+ if (result == 0)
+ {
+ clearmaxy = 0;
+ return true;
+ }
+
+ if (!bDeleteBadTex) return false;
+
+ // delete clearminy, clearmaxy range (not the checkstarty, checkendy range)
+ //int newstarty = 0;
+ if (clearminy <= starty)
+ {
+ if (clearmaxy < starty + height)
+ {
+ // preserve end
+ height = starty + height - clearmaxy;
+ starty = clearmaxy;
+ assert(height > 0);
+ }
+ else
+ {
+ // destroy
+ height = 0;
+ }
+ }
+ else
+ {
+ // beginning can be preserved
+ height = clearminy - starty;
+ }
+
+ clearmaxy = 0;
+
+ assert((starty >= realy) && ((starty + height) <= (realy + realheight)));
+
+ return false;
+}
+
+#define TARGET_THRESH 0x500
+
+extern int g_MaxTexWidth, g_MaxTexHeight; // Maximum height & width of supported texture.
+
+//#define SORT_TARGETS
+inline list::iterator CMemoryTargetMngr::DestroyTargetIter(list::iterator& it)
+{
+ // find the target and destroy
+ list::iterator itprev = it;
+ ++it;
+ listClearedTargets.splice(listClearedTargets.end(), listTargets, itprev);
+
+ if (listClearedTargets.size() > TEXDESTROY_THRESH)
+ {
+ listClearedTargets.pop_front();
+ }
+
+ return it;
+}
+
+// Compare target to current texture info
+// Not same format -> 1
+// Same format, not same data (clut only) -> 2
+// identical -> 0
+int CMemoryTargetMngr::CompareTarget(list::iterator& it, const tex0Info& tex0, int clutsize)
+{
+ if (PSMT_ISCLUT(it->psm) != PSMT_ISCLUT(tex0.psm))
+ return 1;
+
+ if (PSMT_ISCLUT(tex0.psm)) {
+ if (it->psm != tex0.psm || it->cpsm != tex0.cpsm || it->clutsize != clutsize)
+ return 1;
+
+ if (PSMT_IS32BIT(tex0.cpsm)) {
+ if (Cmp_ClutBuffer_SavedClut((u32*)&it->clut[0], tex0.csa, clutsize))
+ return 2;
+ } else {
+ if (Cmp_ClutBuffer_SavedClut((u16*)&it->clut[0], tex0.csa, clutsize))
+ return 2;
+ }
+
+ } else {
+ if (PSMT_IS16BIT(tex0.psm) != PSMT_IS16BIT(it->psm))
+ return 1;
+ }
+
+ return 0;
+}
+
+void CMemoryTargetMngr::GetClutVariables(int& clutsize, const tex0Info& tex0)
+{
+ clutsize = 0;
+
+ if (PSMT_ISCLUT(tex0.psm))
+ {
+ int entries = PSMT_IS8CLUT(tex0.psm) ? 256 : 16;
+
+ if (PSMT_IS32BIT(tex0.cpsm))
+ clutsize = min(entries, 256 - tex0.csa * 16) * 4;
+ else
+ clutsize = min(entries, 512 - tex0.csa * 16) * 2;
+ }
+}
+
+void CMemoryTargetMngr::GetMemAddress(int& start, int& end, const tex0Info& tex0)
+{
+ int nbStart, nbEnd;
+ GetRectMemAddressZero(nbStart, nbEnd, tex0.psm, tex0.tw, tex0.th, tex0.tbp0, tex0.tbw);
+ assert(nbStart < nbEnd);
+ nbEnd = min(nbEnd, MEMORY_END);
+
+ start = nbStart / (4 * GPU_TEXWIDTH);
+ end = (nbEnd + GPU_TEXWIDTH * 4 - 1) / (4 * GPU_TEXWIDTH);
+ assert(start < end);
+
+}
+
+CMemoryTarget* CMemoryTargetMngr::SearchExistTarget(int start, int end, int clutsize, const tex0Info& tex0, int forcevalidate)
+{
+ for (list::iterator it = listTargets.begin(); it != listTargets.end();)
+ {
+
+ if (it->starty <= start && it->starty + it->height >= end)
+ {
+
+ int res = CompareTarget(it, tex0, clutsize);
+
+ if (res == 1)
+ {
+ if (it->validatecount++ > VALIDATE_THRESH)
+ {
+ it = DestroyTargetIter(it);
+
+ if (listTargets.size() == 0) break;
+ }
+ else
+ ++it;
+
+ continue;
+ }
+ else if (res == 2)
+ {
+ ++it;
+ continue;
+ }
+
+ if (forcevalidate) //&& listTargets.size() < TARGET_THRESH ) {
+ {
+ // do more validation checking. delete if not been used for a while
+
+ if (!it->ValidateTex(tex0, start, end, curstamp > it->usedstamp + FORCE_TEXDESTROY_THRESH))
+ {
+
+ if (it->height <= 0)
+ {
+ it = DestroyTargetIter(it);
+
+ if (listTargets.size() == 0) break;
+ }
+ else
+ ++it;
+
+ continue;
+ }
+ }
+
+ it->usedstamp = curstamp;
+
+ it->validatecount = 0;
+
+ return &(*it);
+ }
+
+#ifdef SORT_TARGETS
+ else if (it->starty >= end) break;
+
+#endif
+
+ ++it;
+ }
+
+ return NULL;
+}
+
+CMemoryTarget* CMemoryTargetMngr::ClearedTargetsSearch(int fmt, int widthmult, int channels, int height)
+{
+ CMemoryTarget* targ = NULL;
+
+ if (listClearedTargets.size() > 0)
+ {
+ list::iterator itbest = listClearedTargets.begin();
+
+ while (itbest != listClearedTargets.end())
+ {
+ if ((height == itbest->realheight) && (itbest->fmt == fmt) && (itbest->widthmult == widthmult) && (itbest->channels == channels))
+ {
+ // check channels
+ if (PIXELS_PER_WORD(itbest->psm) == channels) break;
+ }
+
+ ++itbest;
+ }
+
+ if (itbest != listClearedTargets.end())
+ {
+ listTargets.splice(listTargets.end(), listClearedTargets, itbest);
+ targ = &listTargets.back();
+ targ->validatecount = 0;
+ }
+ else
+ {
+ // create a new
+ listTargets.push_back(CMemoryTarget());
+ targ = &listTargets.back();
+ }
+ }
+ else
+ {
+ listTargets.push_back(CMemoryTarget());
+ targ = &listTargets.back();
+ }
+
+ return targ;
+}
+
+CMemoryTarget* CMemoryTargetMngr::GetMemoryTarget(const tex0Info& tex0, int forcevalidate)
+{
+ FUNCLOG
+ int start, end, clutsize;
+
+ GetClutVariables(clutsize, tex0);
+ GetMemAddress(start, end, tex0);
+
+ CMemoryTarget* it = SearchExistTarget(start, end, clutsize, tex0, forcevalidate);
+
+ if (it != NULL) return it;
+
+ // couldn't find so create
+ CMemoryTarget* targ;
+
+ u32 fmt;
+ u32 internal_fmt;
+ if (PSMT_ISHALF_STORAGE(tex0)) {
+ // RGBA_5551 storage format
+ fmt = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+ internal_fmt = GL_RGB5_A1;
+ } else {
+ // RGBA_8888 storage format
+ fmt = GL_UNSIGNED_BYTE;
+ internal_fmt = GL_RGBA;
+ }
+
+ int widthmult = 1, channels = 1;
+
+ // If our texture is too big and could not be placed in 1 GPU texture. Pretty rare in modern cards.
+ if ((g_MaxTexHeight < 4096) && (end - start > g_MaxTexHeight))
+ {
+ // In this rare case we made a texture of half height and place it on the screen.
+ ZZLog::Debug_Log("Making a half height texture (start - end == 0x%x)", (end-start));
+ widthmult = 2;
+ }
+
+ channels = PIXELS_PER_WORD(tex0.psm);
+
+ targ = ClearedTargetsSearch(fmt, widthmult, channels, end - start);
+
+ if (targ->ptex != NULL)
+ {
+ assert(end - start <= targ->realheight && targ->fmt == fmt && targ->widthmult == widthmult);
+
+ // good enough, so init
+ targ->realy = targ->starty = start;
+ targ->usedstamp = curstamp;
+ targ->psm = tex0.psm;
+ targ->cpsm = tex0.cpsm;
+ targ->height = end - start;
+ } else {
+ // not initialized yet
+ targ->fmt = fmt;
+ targ->realy = targ->starty = start;
+ targ->realheight = targ->height = end - start;
+ targ->usedstamp = curstamp;
+ targ->psm = tex0.psm;
+ targ->cpsm = tex0.cpsm;
+ targ->widthmult = widthmult;
+ targ->channels = channels;
+ targ->texH = (targ->realheight + widthmult - 1)/widthmult;
+ targ->texW = GPU_TEXWIDTH * widthmult * channels;
+
+ // alloc the mem
+ targ->ptex = new CMemoryTarget::TEXTURE();
+ targ->ptex->ref = 1;
+ }
+
+#if defined(ZEROGS_DEVBUILD)
+ g_TransferredToGPU += MemorySize(channels * targ->height);
+#endif
+
+ // fill with data
+ if (targ->ptex->memptr == NULL)
+ {
+ targ->ptex->memptr = (u8*)_aligned_malloc(MemorySize(targ->realheight), 16);
+ assert(targ->ptex->ref > 0);
+ }
+
+ memcpy_amd(targ->ptex->memptr, MemoryAddress(targ->realy), MemorySize(targ->height));
+
+ __aligned16 u8* ptexdata = NULL;
+ bool has_data = false;
+
+ if (PSMT_ISCLUT(tex0.psm))
+ {
+ assert(clutsize > 0);
+
+ // Local clut parameter
+ targ->cpsm = tex0.cpsm;
+
+ // Allocate a local clut array
+ targ->clutsize = clutsize;
+ if(targ->clut == NULL)
+ targ->clut = (u8*)_aligned_malloc(clutsize, 16);
+ else {
+ // In case it could occured
+ // realloc would be better but you need to get it from libutilies first
+ // _aligned_realloc is brought in from ScopedAlloc.h now. --arcum42
+ _aligned_free(targ->clut);
+ targ->clut = (u8*)_aligned_malloc(clutsize, 16);
+ }
+
+ // texture parameter
+ ptexdata = (u8*)_aligned_malloc(CLUT_PIXEL_SIZE(tex0.cpsm) * targ->texH * targ->texW, 16);
+ has_data = true;
+
+ u8* psrc = (u8*)(MemoryAddress(targ->realy));
+
+ // Fill a local clut then build the real texture
+ if (PSMT_IS32BIT(tex0.cpsm))
+ {
+ ClutBuffer_to_Array((u32*)targ->clut, tex0.csa, clutsize);
+ Build_Clut_Texture(tex0.psm, targ->height, (u32*)targ->clut, psrc, (u32*)ptexdata);
+ }
+ else
+ {
+ ClutBuffer_to_Array((u16*)targ->clut, tex0.csa, clutsize);
+ Build_Clut_Texture(tex0.psm, targ->height, (u16*)targ->clut, psrc, (u16*)ptexdata);
+ }
+
+ assert(targ->clutsize > 0);
+ }
+ else if (tex0.psm == PSMT16Z || tex0.psm == PSMT16SZ)
+ {
+ ptexdata = (u8*)_aligned_malloc(4 * targ->texH * targ->texW, 16);
+ has_data = true;
+
+ // needs to be 8 bit, use xmm for unpacking
+ u16* dst = (u16*)ptexdata;
+ u16* src = (u16*)(MemoryAddress(targ->realy));
+
+#ifdef ZEROGS_SSE2
+ assert(((u32)(uptr)dst) % 16 == 0);
+
+ __m128i zero_128 = _mm_setzero_si128();
+ // NOTE: future performance improvement
+ // SSE4.1 support uncacheable load 128bits. Maybe it can
+ // avoid some cache pollution
+ // NOTE2: I create multiple _n variable to mimic the previous ASM behavior
+ // but I'm not sure there are real gains.
+ for (int i = targ->height * GPU_TEXWIDTH/16 ; i > 0 ; --i)
+ {
+ // Convert 16 bits pixels to 32bits (zero extended)
+ // Batch 64 bytes (32 pixels) at once.
+ __m128i pixels_1 = _mm_load_si128((__m128i*)src);
+ __m128i pixels_2 = _mm_load_si128((__m128i*)(src+8));
+ __m128i pixels_3 = _mm_load_si128((__m128i*)(src+16));
+ __m128i pixels_4 = _mm_load_si128((__m128i*)(src+24));
+
+ __m128i pix_low_1 = _mm_unpacklo_epi16(pixels_1, zero_128);
+ __m128i pix_high_1 = _mm_unpackhi_epi16(pixels_1, zero_128);
+ __m128i pix_low_2 = _mm_unpacklo_epi16(pixels_2, zero_128);
+ __m128i pix_high_2 = _mm_unpackhi_epi16(pixels_2, zero_128);
+
+ // Note: bypass cache
+ _mm_stream_si128((__m128i*)dst, pix_low_1);
+ _mm_stream_si128((__m128i*)(dst+8), pix_high_1);
+ _mm_stream_si128((__m128i*)(dst+16), pix_low_2);
+ _mm_stream_si128((__m128i*)(dst+24), pix_high_2);
+
+ __m128i pix_low_3 = _mm_unpacklo_epi16(pixels_3, zero_128);
+ __m128i pix_high_3 = _mm_unpackhi_epi16(pixels_3, zero_128);
+ __m128i pix_low_4 = _mm_unpacklo_epi16(pixels_4, zero_128);
+ __m128i pix_high_4 = _mm_unpackhi_epi16(pixels_4, zero_128);
+
+ // Note: bypass cache
+ _mm_stream_si128((__m128i*)(dst+32), pix_low_3);
+ _mm_stream_si128((__m128i*)(dst+40), pix_high_3);
+ _mm_stream_si128((__m128i*)(dst+48), pix_low_4);
+ _mm_stream_si128((__m128i*)(dst+56), pix_high_4);
+
+ src += 32;
+ dst += 64;
+ }
+ // It is advise to use a fence instruction after non temporal move (mm_stream) instruction...
+ // store fence insures that previous store are finish before execute new one.
+ _mm_sfence();
+#else // ZEROGS_SSE2
+
+ for (int i = 0; i < targ->height; ++i)
+ {
+ for (int j = 0; j < GPU_TEXWIDTH; ++j)
+ {
+ dst[0] = src[0];
+ dst[1] = 0;
+ dst[2] = src[1];
+ dst[3] = 0;
+ dst += 4;
+ src += 2;
+ }
+ }
+
+#endif // ZEROGS_SSE2
+ }
+ else
+ {
+ ptexdata = targ->ptex->memptr;
+ // We really don't want to deallocate memptr. As a reminder...
+ has_data = false;
+ }
+
+ // create the texture
+ GL_REPORT_ERRORD();
+
+ assert(ptexdata != NULL);
+
+ if (targ->ptex->tex == 0) glGenTextures(1, &targ->ptex->tex);
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, targ->ptex->tex);
+
+ TextureRect(internal_fmt, targ->texW, targ->texH, GL_RGBA, fmt, ptexdata);
+
+ while (glGetError() != GL_NO_ERROR)
+ {
+ // release resources until can create
+ if (listClearedTargets.size() > 0)
+ {
+ listClearedTargets.pop_front();
+ }
+ else
+ {
+ if (listTargets.size() == 0)
+ {
+ ZZLog::Error_Log("Failed to create %dx%x texture.", targ->texW, targ->texH);
+ channels = 1;
+ if (has_data) _aligned_free(ptexdata);
+ return NULL;
+ }
+
+ DestroyOldest();
+ }
+
+ TextureRect(internal_fmt, targ->texW, targ->texH, GL_RGBA, fmt, ptexdata);
+ }
+
+ setRectWrap(GL_CLAMP);
+ if (has_data) _aligned_free(ptexdata);
+
+ assert(tex0.psm != 0xd);
+
+ return targ;
+}
+
+void CMemoryTargetMngr::ClearRange(int nbStartY, int nbEndY)
+{
+ FUNCLOG
+ int starty = nbStartY / (4 * GPU_TEXWIDTH);
+ int endy = (nbEndY + 4 * GPU_TEXWIDTH - 1) / (4 * GPU_TEXWIDTH);
+
+ for (list::iterator it = listTargets.begin(); it != listTargets.end();)
+ {
+
+ if (it->starty < endy && (it->starty + it->height) > starty)
+ {
+
+ // intersects, reduce valid texture mem (or totally delete texture)
+ // there are 4 cases
+ int miny = max(it->starty, starty);
+ int maxy = min(it->starty + it->height, endy);
+ assert(miny < maxy);
+
+ if (it->clearmaxy == 0)
+ {
+ it->clearminy = miny;
+ it->clearmaxy = maxy;
+ }
+ else
+ {
+ if (it->clearminy > miny) it->clearminy = miny;
+ if (it->clearmaxy < maxy) it->clearmaxy = maxy;
+ }
+ }
+
+ ++it;
+ }
+}
+
+void CMemoryTargetMngr::DestroyCleared()
+{
+ FUNCLOG
+
+ for (list::iterator it = listClearedTargets.begin(); it != listClearedTargets.end();)
+ {
+ if (it->usedstamp < curstamp - (FORCE_TEXDESTROY_THRESH -1))
+ {
+ it = listClearedTargets.erase(it);
+ continue;
+ }
+
+ ++it;
+ }
+
+ if ((curstamp % FORCE_TEXDESTROY_THRESH) == 0)
+ {
+ // purge old targets every FORCE_TEXDESTROY_THRESH frames
+ for (list::iterator it = listTargets.begin(); it != listTargets.end();)
+ {
+ if (it->usedstamp < curstamp - FORCE_TEXDESTROY_THRESH)
+ {
+ it = listTargets.erase(it);
+ continue;
+ }
+
+ ++it;
+ }
+ }
+
+ ++curstamp;
+}
+
+void CMemoryTargetMngr::DestroyOldest()
+{
+ FUNCLOG
+
+ if (listTargets.size() == 0)
+ return;
+
+ list::iterator it, itbest;
+
+ it = itbest = listTargets.begin();
+
+ while (it != listTargets.end())
+ {
+ if (it->usedstamp < itbest->usedstamp) itbest = it;
+ ++it;
+ }
+
+ listTargets.erase(itbest);
+}
diff --git a/plugins/zzogl-pg/opengl/ZZRenderTargets.cpp b/plugins/zzogl-pg/opengl/ZZRenderTargets.cpp
new file mode 100644
index 0000000000..7b8ee82ee3
--- /dev/null
+++ b/plugins/zzogl-pg/opengl/ZZRenderTargets.cpp
@@ -0,0 +1,1325 @@
+/* ZZ Open GL graphics plugin
+ * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
+ * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+#include
+
+#include "GS.h"
+#include "Mem.h"
+#include "x86.h"
+#include "targets.h"
+#include "ZZoglShaders.h"
+#include "ZZClut.h"
+#include "ZZoglVB.h"
+
+#ifdef ZEROGS_SSE2
+#include
+#endif
+
+extern int g_TransferredToGPU;
+extern int s_nResolved;
+
+void _Resolve(const void* psrc, int fbp, int fbw, int fbh, int psm, u32 fbm, bool mode);
+void SetWriteDepth();
+bool IsWriteDepth();
+bool IsWriteDestAlphaTest();
+
+
+
+// Draw 4 triangles from binded array using only stencil buffer
+inline void FillOnlyStencilBuffer()
+{
+ if (IsWriteDestAlphaTest() && !(conf.settings().no_stencil))
+ {
+ glColorMask(0, 0, 0, 0);
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GEQUAL, 1.0f);
+
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ glStencilFunc(GL_ALWAYS, 1, 0xff);
+
+ DrawTriangleArray();
+ glColorMask(1, 1, 1, 1);
+ }
+}
+
+inline void BindToSample(u32 *p_ptr)
+{
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, *p_ptr);
+ setRectFilters(GL_NEAREST);
+}
+
+// Made an empty texture and bind it to $ptr_p
+// returns false if creating texture was unsuccessful
+// fbh and fdb should be properly shifted before calling this!
+// We should ignore framebuffer trouble here, as we put textures of different sizes to it.
+inline bool CRenderTarget::InitialiseDefaultTexture(u32 *ptr_p, int fbw, int fbh)
+{
+ glGenTextures(1, ptr_p);
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, *ptr_p);
+
+ // initialize to default
+ TextureRect(GL_RGBA, fbw, fbh, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ setRectWrap(GL_CLAMP);
+ setRectFilters(GL_LINEAR);
+
+ GLenum Error = glGetError();
+ return ((Error == GL_NO_ERROR) || (Error == GL_INVALID_FRAMEBUFFER_OPERATION_EXT));
+}
+
+// used for transformation from vertex position in GS window.coords (I hope)
+// to view coordinates (in range 0, 1).
+float4 CRenderTarget::DefaultBitBltPos()
+{
+ float4 v = float4(1, -1, 0.5f / (float)RW(fbw), 0.5f / (float)RH(fbh));
+ v *= 1.0f / 32767.0f;
+ ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltPos, v, "g_sBitBltPos");
+ return v;
+}
+
+// Used to transform texture coordinates from GS (when 0,0 is upper left) to
+// OpenGL (0,0 - lower left).
+float4 CRenderTarget::DefaultBitBltTex()
+{
+ // I really sure that -0.5 is correct, because OpenGL have no half-offset
+ // issue, DirectX known for.
+ float4 v = float4(1, -1, 0.5f / (float)RW(fbw), -0.5f / (float)RH(fbh));
+ ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_sBitBltTex");
+ return v;
+}
+
+
+////////////////////
+// Render Targets //
+////////////////////
+CRenderTarget::CRenderTarget() : ptex(0), ptexFeedback(0), psys(NULL)
+{
+ FUNCLOG
+ nUpdateTarg = 0;
+}
+
+CRenderTarget::~CRenderTarget()
+{
+ FUNCLOG
+ Destroy();
+}
+
+bool CRenderTarget::Create(const frameInfo& frame)
+{
+ FUNCLOG
+ Resolve();
+ Destroy();
+ created = 123;
+
+ lastused = timeGetTime();
+ fbp = frame.fbp;
+ fbw = frame.fbw;
+ fbh = frame.fbh;
+ psm = (u8)frame.psm;
+ fbm = frame.fbm;
+
+ vposxy.x = 2.0f * (1.0f / 8.0f) / (float)fbw;
+ vposxy.y = 2.0f * (1.0f / 8.0f) / (float)fbh;
+ vposxy.z = -1.0f - 0.5f / (float)fbw;
+ vposxy.w = -1.0f + 0.5f / (float)fbh;
+ status = 0;
+
+ if (fbw > 0 && fbh > 0)
+ {
+ GetRectMemAddressZero(start, end, psm, fbw, fbh, fbp, fbw);
+ psys = _aligned_malloc(Tex_Memory_Size(fbw, fbh), 16);
+
+ GL_REPORT_ERRORD();
+
+ if (!InitialiseDefaultTexture(&ptex, RW(fbw), RH(fbh)))
+ {
+ Destroy();
+ return false;
+ }
+
+ status = TS_NeedUpdate;
+ }
+ else
+ {
+ start = end = 0;
+ }
+
+ return true;
+}
+
+void CRenderTarget::Destroy()
+{
+ FUNCLOG
+ created = 1;
+ _aligned_free(psys);
+ psys = NULL;
+ SAFE_RELEASE_TEX(ptex);
+ SAFE_RELEASE_TEX(ptexFeedback);
+}
+
+void CRenderTarget::SetTarget(int fbplocal, const Rect2& scissor, int context)
+{
+ FUNCLOG
+ int dy = 0;
+
+ if (fbplocal != fbp)
+ {
+ float4 v;
+
+ // will be rendering to a subregion
+ u32 bpp = PSMT_ISHALF(psm) ? 2 : 4;
+ assert(((256 / bpp)*(fbplocal - fbp)) % fbw == 0);
+ assert(fbplocal >= fbp);
+
+ dy = ((256 / bpp) * (fbplocal - fbp)) / fbw;
+
+ v.x = vposxy.x;
+ v.y = vposxy.y;
+ v.z = vposxy.z;
+ v.w = vposxy.w - dy * 2.0f / (float)fbh;
+ ZZshSetParameter4fv(g_vparamPosXY[context], v, "g_fPosXY");
+ }
+ else
+ {
+ ZZshSetParameter4fv(g_vparamPosXY[context], vposxy, "g_fPosXY");
+ }
+
+ // set render states
+ // Bleh. I *really* need to fix this. << 3 when setting the scissors, then >> 3 when using them... --Arcum42
+ scissorrect.x = scissor.x0 >> 3;
+ scissorrect.y = (scissor.y0 >> 3) + dy;
+ scissorrect.w = (scissor.x1 >> 3) + 1;
+ scissorrect.h = (scissor.y1 >> 3) + 1 + dy;
+
+ scissorrect.w = min(scissorrect.w, fbw) - scissorrect.x;
+ scissorrect.h = min(scissorrect.h, fbh) - scissorrect.y;
+
+ scissorrect.x = RW(scissorrect.x);
+ scissorrect.y = RH(scissorrect.y);
+ scissorrect.w = RW(scissorrect.w);
+ scissorrect.h = RH(scissorrect.h);
+}
+
+void CRenderTarget::SetViewport()
+{
+ FUNCLOG
+ glViewport(0, 0, RW(fbw), RH(fbh));
+}
+
+inline bool NotResolveHelper()
+{
+ return ((s_nResolved > 8 && (2 * s_nResolved > fFPS - 10)) || (conf.settings().no_target_resolve));
+}
+
+void CRenderTarget::Resolve()
+{
+ FUNCLOG
+
+ if (ptex != 0 && !(status&TS_Resolved) && !(status&TS_NeedUpdate))
+ {
+ // flush if necessary
+ FlushIfNecesary(this) ;
+
+ if ((IsDepth() && !IsWriteDepth()) || NotResolveHelper())
+ {
+ // don't resolve if depths aren't used
+ status = TS_Resolved;
+ return;
+ }
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex);
+
+ GL_REPORT_ERRORD();
+ // This code extremely slow on DC1.
+// _aligned_free(psys);
+// psys = _aligned_malloc( Tex_Memory_Size ( fbw, fbh ), 16 );
+
+ glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, psys);
+
+ GL_REPORT_ERRORD();
+
+#if defined(ZEROGS_DEVBUILD)
+
+ if (g_bSaveResolved)
+ {
+ SaveTexture("resolved.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh));
+ g_bSaveResolved = 0;
+ }
+
+#endif
+ _Resolve(psys, fbp, fbw, fbh, psm, fbm, true);
+
+ status = TS_Resolved;
+ }
+}
+
+void CRenderTarget::Resolve(int startrange, int endrange)
+{
+ FUNCLOG
+
+ assert(startrange < end && endrange > start); // make sure it at least intersects
+
+ if (ptex != 0 && !(status&TS_Resolved) && !(status&TS_NeedUpdate))
+ {
+ // flush if necessary
+ FlushIfNecesary(this) ;
+
+#if defined(ZEROGS_DEVBUILD)
+ if (g_bSaveResolved)
+ {
+ SaveTexture("resolved.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh));
+ g_bSaveResolved = 0;
+ }
+#endif
+ if (conf.settings().no_target_resolve)
+ {
+ status = TS_Resolved;
+ return;
+ }
+
+ int blockheight = PSMT_ISHALF(psm) ? 64 : 32;
+ int resolvefbp = fbp, resolveheight = fbh;
+ int scanlinewidth = 0x2000 * (fbw >> 6);
+
+ // in no way should data be overwritten!, instead resolve less
+
+ if (endrange < end)
+ {
+ // round down to nearest block and scanline
+ resolveheight = ((endrange - start) / (0x2000 * (fbw >> 6))) * blockheight;
+
+ if (resolveheight <= 32)
+ {
+ status = TS_Resolved;
+ return;
+ }
+ }
+ else if (startrange > start)
+ {
+ // round up to nearest block and scanline
+ resolvefbp = startrange + scanlinewidth - 1;
+ resolvefbp -= resolvefbp % scanlinewidth;
+
+ resolveheight = fbh - ((resolvefbp - fbp) * blockheight / scanlinewidth);
+
+ if (resolveheight <= 64) // this is a total hack, but kh doesn't resolve now
+ {
+ status = TS_Resolved;
+ return;
+ }
+
+ resolvefbp >>= 8;
+ }
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex);
+
+ glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, GL_UNSIGNED_BYTE, psys);
+ GL_REPORT_ERRORD();
+
+ u8* pbits = (u8*)psys;
+
+ if (fbp != resolvefbp) pbits += ((resolvefbp - fbp) * 256 / scanlinewidth) * blockheight * Pitch(fbw);
+
+ _Resolve(pbits, resolvefbp, fbw, resolveheight, psm, fbm, true);
+
+ status = TS_Resolved;
+ }
+}
+
+void CRenderTarget::Update(int context, CRenderTarget* pdepth)
+{
+ FUNCLOG
+
+ DisableAllgl();
+
+ glBindBuffer(GL_ARRAY_BUFFER, vboRect);
+ SET_STREAM();
+
+ // assume depth already set
+ //pd3dDevice->SetDepthStencilSurface(psurfDepth);
+ ResetRenderTarget(1);
+ SetRenderTarget(0);
+ assert(pdepth != NULL);
+ ((CDepthTarget*)pdepth)->SetDepthStencilSurface();
+
+ SetShaderCaller("CRenderTarget::Update");
+ float4 v = DefaultBitBltPos();
+
+ CRenderTargetMngr::MAPTARGETS::iterator ittarg;
+
+ if (nUpdateTarg)
+ {
+ ittarg = s_RTs.mapTargets.find(nUpdateTarg);
+
+ if (ittarg == s_RTs.mapTargets.end())
+ {
+ ittarg = s_DepthRTs.mapTargets.find(nUpdateTarg);
+
+ if (ittarg == s_DepthRTs.mapTargets.end())
+ nUpdateTarg = 0;
+ else if (ittarg->second == this)
+ {
+ ZZLog::Debug_Log("Updating self.");
+ nUpdateTarg = 0;
+ }
+ }
+ else if (ittarg->second == this)
+ {
+ ZZLog::Debug_Log("Updating self.");
+ nUpdateTarg = 0;
+ }
+ }
+
+ SetViewport();
+
+ if (nUpdateTarg)
+ {
+ ZZshGLSetTextureParameter(ppsBaseTexture.prog, ppsBaseTexture.sFinal, ittarg->second->ptex, "BaseTexture.final");
+
+ //assert( ittarg->second->fbw == fbw );
+ int offset = (fbp - ittarg->second->fbp) * 64 / fbw;
+
+ if (PSMT_ISHALF(psm)) // 16 bit
+ offset *= 2;
+
+ v.x = (float)RW(fbw);
+ v.y = (float)RH(fbh);
+ v.z = 0.25f;
+ v.w = (float)RH(offset) + 0.25f;
+
+ ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_fBitBltTex");
+
+// v = DefaultBitBltTex(); Maybe?
+ ZZshDefaultOneColor ( ppsBaseTexture );
+
+ ZZshSetPixelShader(ppsBaseTexture.prog);
+
+ nUpdateTarg = 0;
+ }
+ else
+ {
+ u32 bit_idx = (AA.x == 0) ? 0 : 1;
+
+ // align the rect to the nearest page
+ // note that fbp is always aligned on page boundaries
+ tex0Info texframe;
+ texframe.tbp0 = fbp;
+ texframe.tbw = fbw;
+ texframe.tw = fbw;
+ texframe.th = fbh;
+ texframe.psm = psm;
+ // FIXME some field are not initialized...
+ // in particular the clut related one
+ assert(!PSMT_ISCLUT(psm));
+
+ // write color and zero out stencil buf, always 0 context!
+ // force bilinear if using AA
+ // Fix in r133 -- FFX movies and Gust backgrounds!
+ //SetTexVariablesInt(0, 0*(AA.x || AA.y) ? 2 : 0, texframe, false, &ppsBitBlt[!!s_AAx], 1);
+ SetTexVariablesInt(0, 0, texframe, false, &ppsBitBlt[bit_idx], 1);
+ ZZshGLSetTextureParameter(ppsBitBlt[bit_idx].prog, ppsBitBlt[bit_idx].sMemory, vb[0].pmemtarg->ptex->tex, "BitBlt.memory");
+
+ v = float4(1, 1, 0.0f, 0.0f);
+ ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "g_fBitBltTex");
+
+ v.x = 1;
+ v.y = 2;
+ ZZshSetParameter4fv(ppsBitBlt[bit_idx].prog, ppsBitBlt[bit_idx].sOneColor, v, "g_fOneColor");
+
+ assert(ptex != 0);
+
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ if (IsWriteDestAlphaTest())
+ {
+ glEnable(GL_STENCIL_TEST);
+ glStencilFunc(GL_ALWAYS, 0, 0xff);
+ glStencilMask(0xff);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
+ }
+
+ // render with an AA shader if possible (bilinearly interpolates data)
+ //cgGLLoadProgram(ppsBitBlt[bit_idx].prog);
+ ZZshSetPixelShader(ppsBitBlt[bit_idx].prog);
+ }
+
+ ZZshSetVertexShader(pvsBitBlt.prog);
+
+ DrawTriangleArray();
+
+ // fill stencil buf only
+ FillOnlyStencilBuffer();
+ glEnable(GL_SCISSOR_TEST);
+
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ if (conf.mrtdepth && pdepth != NULL && IsWriteDepth()) pdepth->SetRenderTarget(1);
+
+ status = TS_Resolved;
+
+ // reset since settings changed
+ vb[0].bVarsTexSync = 0;
+
+// ResetAlphaVariables();
+}
+
+void CRenderTarget::ConvertTo32()
+{
+ FUNCLOG
+
+ u32 ptexConv;
+// ZZLog::Error_Log("Convert to 32, report if something missing.");
+ // create new target
+
+ if (! InitialiseDefaultTexture(&ptexConv, RW(fbw), RH(fbh) / 2))
+ {
+ ZZLog::Error_Log("Failed to create target for ConvertTo32 %dx%d.", RW(fbw), RH(fbh) / 2);
+ return;
+ }
+
+ DisableAllgl();
+
+ SetShaderCaller("CRenderTarget::ConvertTo32");
+
+ // tex coords, test ffx bikanel island when changing these
+ float4 v = DefaultBitBltPos();
+ v = DefaultBitBltTex();
+
+ v.x = (float)RW(16);
+ v.y = (float)RH(16);
+ v.z = -(float)RW(fbw);
+ v.w = (float)RH(8);
+ ZZshSetParameter4fv(ppsConvert16to32.prog, ppsConvert16to32.fTexOffset, v, "g_fTexOffset");
+
+ v.x = (float)RW(8);
+ v.y = 0;
+ v.z = 0;
+ v.w = 0.25f;
+ ZZshSetParameter4fv(ppsConvert16to32.prog, ppsConvert16to32.fPageOffset, v, "g_fPageOffset");
+
+ v.x = (float)RW(2 * fbw);
+ v.y = (float)RH(fbh);
+ v.z = 0;
+ v.w = 0.0001f * (float)RH(fbh);
+ ZZshSetParameter4fv(ppsConvert16to32.prog, ppsConvert16to32.fTexDims, v, "g_fTexDims");
+
+// v.x = 0;
+// ZZshSetParameter4fv(ppsConvert16to32.fTexBlock, v, "g_fTexBlock");
+
+ glBindBuffer(GL_ARRAY_BUFFER, vboRect);
+ SET_STREAM();
+
+ // assume depth already set !?
+ FB::Attach2D(0, ptexConv);
+ ResetRenderTarget(1);
+
+ BindToSample(&ptex);
+ ZZshGLSetTextureParameter(ppsConvert16to32.prog, ppsConvert16to32.sFinal, ptex, "Convert 16 to 32.Final");
+
+ fbh /= 2; // have 16 bit surfaces are usually 2x higher
+ SetViewport();
+
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ // render with an AA shader if possible (bilinearly interpolates data)
+ ZZshSetVertexShader(pvsBitBlt.prog);
+ ZZshSetPixelShader(ppsConvert16to32.prog);
+ DrawTriangleArray();
+
+#ifdef _DEBUG
+ if (g_bSaveZUpdate)
+ {
+ // buggy
+ SaveTexture("tex1.tga", GL_TEXTURE_RECTANGLE_NV, ptex, RW(fbw), RH(fbh)*2);
+ SaveTexture("tex3.tga", GL_TEXTURE_RECTANGLE_NV, ptexConv, RW(fbw), RH(fbh));
+ }
+
+#endif
+
+ vposxy.y = -2.0f * (32767.0f / 8.0f) / (float)fbh;
+ vposxy.w = 1 + 0.5f / fbh;
+
+ // restore
+ SAFE_RELEASE_TEX(ptex);
+ SAFE_RELEASE_TEX(ptexFeedback);
+
+ ptex = ptexConv;
+
+ // no need to free psys since the render target is getting shrunk
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ // reset textures
+ BindToSample(&ptex);
+
+ glEnable(GL_SCISSOR_TEST);
+
+ status = TS_Resolved;
+
+ // TODO, reset depth?
+ if (icurctx >= 0)
+ {
+ // reset since settings changed
+ vb[icurctx].bVarsTexSync = 0;
+ vb[icurctx].bVarsSetTarg = 0;
+ }
+
+ vb[0].bVarsTexSync = 0;
+}
+
+void CRenderTarget::ConvertTo16()
+{
+ FUNCLOG
+
+ u32 ptexConv;
+
+// ZZLog::Error_Log("Convert to 16, report if something missing.");
+ // create new target
+
+ if (! InitialiseDefaultTexture(&ptexConv, RW(fbw), RH(fbh)*2))
+ {
+ ZZLog::Error_Log("Failed to create target for ConvertTo16 %dx%d.", RW(fbw), RH(fbh)*2);
+ return;
+ }
+
+ DisableAllgl();
+
+ SetShaderCaller("CRenderTarget::ConvertTo16");
+
+ // tex coords, test ffx bikanel island when changing these
+ float4 v = DefaultBitBltPos();
+ v = DefaultBitBltTex();
+
+ v.x = 16.0f / (float)fbw;
+ v.y = 8.0f / (float)fbh;
+ v.z = 0.5f * v.x;
+ v.w = 0.5f * v.y;
+ ZZshSetParameter4fv(ppsConvert32to16.prog, ppsConvert32to16.fTexOffset, v, "g_fTexOffset");
+
+ v.x = 256.0f / 255.0f;
+ v.y = 256.0f / 255.0f;
+ v.z = 0.05f / 256.0f;
+ v.w = -0.001f / 256.0f;
+ ZZshSetParameter4fv(ppsConvert32to16.prog, ppsConvert32to16.fPageOffset, v, "g_fPageOffset");
+
+ v.x = (float)RW(fbw);
+ v.y = (float)RH(2 * fbh);
+ v.z = 0;
+ v.w = -0.1f / RH(fbh);
+ ZZshSetParameter4fv(ppsConvert32to16.prog, ppsConvert32to16.fTexDims, v, "g_fTexDims");
+
+ glBindBuffer(GL_ARRAY_BUFFER, vboRect);
+ SET_STREAM();
+
+ // assume depth already set !?
+ FB::Attach2D(0, ptexConv);
+ ResetRenderTarget(1);
+ GL_REPORT_ERRORD();
+
+ BindToSample(&ptex);
+
+ ZZshGLSetTextureParameter(ppsConvert32to16.prog, ppsConvert32to16.sFinal, ptex, "Convert 32 to 16");
+
+// fbh *= 2; // have 16 bit surfaces are usually 2x higher
+
+ SetViewport();
+
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ // render with an AA shader if possible (bilinearly interpolates data)
+ ZZshSetVertexShader(pvsBitBlt.prog);
+ ZZshSetPixelShader(ppsConvert32to16.prog);
+ DrawTriangleArray();
+
+#ifdef _DEBUG
+ //g_bSaveZUpdate = 1;
+ if (g_bSaveZUpdate)
+ {
+ SaveTexture("tex1.tga", GL_TEXTURE_RECTANGLE_NV, ptexConv, RW(fbw), RH(fbh));
+ }
+
+#endif
+
+ vposxy.y = -2.0f * (32767.0f / 8.0f) / (float)fbh;
+ vposxy.w = 1 + 0.5f / fbh;
+
+ // restore
+ SAFE_RELEASE_TEX(ptex);
+ SAFE_RELEASE_TEX(ptexFeedback);
+
+ ptex = ptexConv;
+
+ _aligned_free(psys);
+
+ psys = _aligned_malloc(Tex_Memory_Size(fbw, fbh), 16);
+
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ // reset textures
+ BindToSample(&ptex) ;
+
+ glEnable(GL_SCISSOR_TEST);
+
+ status = TS_Resolved;
+
+ // TODO, reset depth?
+ if (icurctx >= 0)
+ {
+ // reset since settings changed
+ vb[icurctx].bVarsTexSync = 0;
+ vb[icurctx].bVarsSetTarg = 0;
+ }
+
+ vb[0].bVarsTexSync = 0;
+}
+
+void CRenderTarget::_CreateFeedback()
+{
+ FUNCLOG
+
+ if (ptexFeedback == 0)
+ {
+ // create
+ if (! InitialiseDefaultTexture(&ptexFeedback, RW(fbw), RH(fbh)))
+ {
+ ZZLog::Error_Log("Failed to create feedback %dx%d.", RW(fbw), RH(fbh));
+ return;
+ }
+ }
+
+ DisableAllgl();
+
+ SetShaderCaller("CRenderTarget::_CreateFeedback");
+
+ // assume depth already set
+ ResetRenderTarget(1);
+
+ // tex coords, test ffx bikanel island when changing these
+ /* float4 v = DefaultBitBltPos();
+ v = float4 ((float)(RW(fbw+4)), (float)(RH(fbh+4)), +0.25f, -0.25f);
+ ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "BitBltTex");*/
+
+ // tex coords, test ffx bikanel island when changing these
+
+// float4 v = float4(1, -1, 0.5f / (fbw << AA.x), 0.5f / (fbh << AA.y));
+// v *= 1/32767.0f;
+// cgGLSetParameter4fv(pvsBitBlt.sBitBltPos, v);
+ float4 v = DefaultBitBltPos();
+
+ v.x = (float)(RW(fbw));
+ v.y = (float)(RH(fbh));
+ v.z = 0.0f;
+ v.w = 0.0f;
+ ZZshSetParameter4fv(pvsBitBlt.prog, pvsBitBlt.sBitBltTex, v, "BitBlt.Feedback");
+ ZZshDefaultOneColor(ppsBaseTexture);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vboRect);
+ SET_STREAM();
+
+ FB::Attach2D(0, ptexFeedback);
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, ptex);
+ GL_REPORT_ERRORD();
+
+ ZZshGLSetTextureParameter(ppsBaseTexture.prog, ppsBaseTexture.sFinal, ptex, "BaseTexture.Feedback");
+
+ SetViewport();
+
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ // render with an AA shader if possible (bilinearly interpolates data)
+ ZZshSetVertexShader(pvsBitBlt.prog);
+ ZZshSetPixelShader(ppsBaseTexture.prog);
+ DrawTriangleArray();
+
+ // restore
+ swap(ptex, ptexFeedback);
+
+ if (conf.wireframe()) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ glEnable(GL_SCISSOR_TEST);
+
+ status |= TS_FeedbackReady;
+
+ // TODO, reset depth?
+ if (icurctx >= 0)
+ {
+ // reset since settings changed
+ vb[icurctx].bVarsTexSync = 0;
+ }
+
+ GL_REPORT_ERRORD();
+}
+
+void CRenderTarget::SetRenderTarget(int targ)
+{
+ FUNCLOG
+
+ FB::Attach2D(targ, ptex);
+
+ //GL_REPORT_ERRORD();
+ //if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
+ //ERROR_LOG_SPAM("The Framebuffer is not complete. Glitches could appear onscreen.\n");
+}
+
+void CRenderTargetMngr::Destroy()
+{
+ FUNCLOG
+
+ for (MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it)
+ {
+ delete it->second;
+ }
+
+ mapTargets.clear();
+
+ for (MAPTARGETS::iterator it = mapDummyTargs.begin(); it != mapDummyTargs.end(); ++it)
+ {
+ delete it->second;
+ }
+
+ mapDummyTargs.clear();
+}
+
+// This block was repeated several times, so I inlined it.
+void CRenderTargetMngr::DestroyAllTargetsHelper(void* ptr)
+{
+ for (int i = 0; i < 2; ++i)
+ {
+ if (ptr == vb[i].prndr) { vb[i].prndr = NULL; vb[i].bNeedFrameCheck = 1; }
+ if (ptr == vb[i].pdepth) { vb[i].pdepth = NULL; vb[i].bNeedZCheck = 1; }
+ }
+}
+
+void CRenderTargetMngr::DestroyAllTargs(int start, int end, int fbw)
+{
+ FUNCLOG
+
+ for (MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end();)
+ {
+ if (it->second->start < end && start < it->second->end)
+ {
+ // if is depth, only resolve if fbw is the same
+ if (!it->second->IsDepth())
+ {
+ // only resolve if the widths are the same or it->second has bit outside the range
+ // shadow of colossus swaps between fbw=256,fbh=256 and fbw=512,fbh=448. This kills the game if doing || it->second->end > end
+
+ // kh hack, sometimes kh movies do this to clear the target, so have a static count that periodically checks end
+ static int count = 0;
+
+ if (it->second->fbw == fbw || (it->second->fbw != fbw && (it->second->start < start || ((count++&0xf) ? 0 : it->second->end > end))))
+ {
+ it->second->Resolve();
+ }
+ else
+ {
+ FlushIfNecesary(it->second);
+ it->second->status |= CRenderTarget::TS_Resolved;
+ }
+ }
+ else
+ {
+ if (it->second->fbw == fbw)
+ {
+ it->second->Resolve();
+ }
+ else
+ {
+ FlushIfNecesary(it->second);
+ it->second->status |= CRenderTarget::TS_Resolved;
+ }
+ }
+
+ DestroyAllTargetsHelper(it->second);
+
+ u32 dummykey = GetFrameKeyDummy(it->second);
+
+ if (mapDummyTargs.find(dummykey) == mapDummyTargs.end())
+ {
+ mapDummyTargs[dummykey] = it->second;
+ }
+ else
+ {
+ delete it->second;
+ }
+
+ mapTargets.erase(it++);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+}
+
+void CRenderTargetMngr::DestroyTarg(CRenderTarget* ptarg)
+{
+ FUNCLOG
+ DestroyAllTargetsHelper(ptarg);
+ delete ptarg;
+}
+
+void CRenderTargetMngr::DestroyIntersecting(CRenderTarget* prndr)
+{
+ FUNCLOG
+ assert(prndr != NULL);
+
+ int start, end;
+ GetRectMemAddressZero(start, end, prndr->psm, prndr->fbw, prndr->fbh, prndr->fbp, prndr->fbw);
+
+ for (MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end();)
+ {
+ if ((it->second != prndr) && (it->second->start < end) && (start < it->second->end))
+ {
+ it->second->Resolve();
+ DestroyAllTargetsHelper(it->second);
+ u32 dummykey = GetFrameKeyDummy(it->second);
+
+ if (mapDummyTargs.find(dummykey) == mapDummyTargs.end())
+ {
+ mapDummyTargs[dummykey] = it->second;
+ }
+ else
+ {
+ delete it->second;
+ }
+
+ mapTargets.erase(it++);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+}
+
+
+void CRenderTargetMngr::PrintTargets()
+{
+#ifdef _DEBUG
+ for (MAPTARGETS::iterator it1 = mapDummyTargs.begin(); it1 != mapDummyTargs.end(); ++it1)
+ ZZLog::Debug_Log("\t Dummy Targets(0x%x) fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", GetFrameKey(it1->second), it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp);
+
+ for (MAPTARGETS::iterator it1 = mapTargets.begin(); it1 != mapTargets.end(); ++it1)
+ ZZLog::Debug_Log("\t Targets(0x%x) fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", GetFrameKey(it1->second), it1->second->fbw, it1->second->fbh, it1->second->psm, it1->second->fbp);
+#endif
+}
+
+bool CRenderTargetMngr::isFound(const frameInfo& frame, MAPTARGETS::iterator& it, u32 opts, u32 key, int maxposheight)
+{
+ // only enforce height if frame.fbh <= 0x1c0
+ bool bfound = it != mapTargets.end();
+
+ if (bfound)
+ {
+ if (opts&TO_StrictHeight)
+ {
+ bfound = it->second->fbh == frame.fbh;
+
+ if ((conf.settings().partial_depth) && !bfound)
+ {
+ MAPTARGETS::iterator itnew = mapTargets.find(key + 1);
+
+ if (itnew != mapTargets.end() && itnew->second->fbh == frame.fbh)
+ {
+ // found! delete the previous and restore
+ delete it->second;
+ mapTargets.erase(it);
+
+ it = mapTargets.insert(MAPTARGETS::value_type(key, itnew->second)).first; // readd
+ mapTargets.erase(itnew); // delete old
+
+ bfound = true;
+ }
+ }
+ }
+ else
+ {
+ if (PSMT_ISHALF(frame.psm) == PSMT_ISHALF(it->second->psm) && !(conf.settings().full_16_bit_res))
+ bfound = ((frame.fbh > 0x1c0) || (it->second->fbh >= frame.fbh)) && (it->second->fbh <= maxposheight);
+ }
+ }
+
+ if (!bfound)
+ {
+ // might be a virtual target
+ it = mapTargets.find(key | TARGET_VIRTUAL_KEY);
+ bfound = it != mapTargets.end() && ((opts & TO_StrictHeight) ? it->second->fbh == frame.fbh : it->second->fbh >= frame.fbh) && it->second->fbh <= maxposheight;
+ }
+
+ if (bfound && PSMT_ISHALF(frame.psm) && PSMT_ISHALF(it->second->psm) && (conf.settings().full_16_bit_res))
+ {
+ // mgs3
+ if (frame.fbh > it->second->fbh)
+ {
+ bfound = false;
+ }
+ }
+
+ return bfound;
+}
+
+CRenderTarget* CRenderTargetMngr::GetTarg(const frameInfo& frame, u32 opts, int maxposheight)
+{
+ FUNCLOG
+
+ if (frame.fbw <= 0 || frame.fbh <= 0)
+ {
+ //ZZLog::Dev_Log("frame fbw == %d; fbh == %d", frame.fbw, frame.fbh);
+ return NULL;
+ }
+
+ GL_REPORT_ERRORD();
+
+ u32 key = GetFrameKey(frame);
+
+ MAPTARGETS::iterator it = mapTargets.find(key);
+
+ if (isFound(frame, it, opts, key, maxposheight))
+ {
+ // can be both 16bit and 32bit
+ if (PSMT_ISHALF(frame.psm) != PSMT_ISHALF(it->second->psm))
+ {
+ // a lot of games do this, actually...
+ ZZLog::Debug_Log("Really bad formats! %d %d", frame.psm, it->second->psm);
+
+// This code SHOULD be commented, until I redo the _Resolve function
+
+ if (!(opts & TO_StrictHeight))
+ {
+ if ((conf.settings().vss_hack_off))
+ {
+ if (PSMT_ISHALF(it->second->psm))
+ {
+ it->second->status |= CRenderTarget::TS_NeedConvert32;
+ it->second->fbh /= 2;
+ }
+ else
+ {
+ it->second->status |= CRenderTarget::TS_NeedConvert16;
+ it->second->fbh *= 2;
+ }
+ }
+ }
+
+ // recalc extents
+ GetRectMemAddressZero(it->second->start, it->second->end, frame.psm, frame.fbw, it->second->fbh, it->second->fbp, frame.fbw);
+ }
+ else
+ {
+ // certain variables have to be reset every time
+ if ((it->second->psm & ~1) != (frame.psm & ~1))
+ {
+ ZZLog::Dev_Log("Bad formats 2: %d %d", frame.psm, it->second->psm);
+
+ it->second->psm = frame.psm;
+
+ // recalc extents
+ GetRectMemAddressZero(it->second->start, it->second->end, frame.psm, frame.fbw, it->second->fbh, it->second->fbp, frame.fbw);
+ }
+ }
+
+ if (it->second->fbm != frame.fbm)
+ {
+ //ZZLog::Dev_Log("Bad fbm: 0x%8.8x 0x%8.8x, psm: %d", frame.fbm, it->second->fbm, frame.psm);
+ }
+
+ it->second->fbm &= frame.fbm;
+ it->second->psm = frame.psm; // have to convert (ffx2)
+
+ if ((it->first & TARGET_VIRTUAL_KEY) && !(opts&TO_Virtual))
+ {
+ // switch
+ it->second->lastused = timeGetTime();
+ return Promote(it->first&~TARGET_VIRTUAL_KEY);
+ }
+
+ // check if there exists a more recent target that this target could update from
+ // only update if target isn't mirrored
+ bool bCheckHalfCovering = (conf.settings().full_16_bit_res) && PSMT_ISHALF(it->second->psm) && it->second->fbh + 32 < frame.fbh;
+
+ for (MAPTARGETS::iterator itnew = mapTargets.begin(); itnew != mapTargets.end(); ++itnew)
+ {
+ if (itnew->second != it->second && itnew->second->ptex != it->second->ptex && itnew->second->ptexFeedback != it->second->ptex &&
+ itnew->second->lastused > it->second->lastused && !(itnew->second->status & CRenderTarget::TS_NeedUpdate))
+ {
+
+ // if new target totally encompasses the current one
+ if (itnew->second->start <= it->second->start && itnew->second->end >= it->second->end)
+ {
+ it->second->status |= CRenderTarget::TS_NeedUpdate;
+ it->second->nUpdateTarg = itnew->first;
+ break;
+ }
+
+ // if 16bit, then check for half encompassing targets
+ if (bCheckHalfCovering && itnew->second->start > it->second->start && itnew->second->start < it->second->end && itnew->second->end <= it->second->end + 0x2000)
+ {
+ it->second->status |= CRenderTarget::TS_NeedUpdate;
+ it->second->nUpdateTarg = itnew->first;
+ break;
+ }
+ }
+ }
+
+ it->second->lastused = timeGetTime();
+
+ return it->second;
+ }
+
+ // NOTE: instead of resolving, if current render targ is completely outside of old, can transfer
+ // the data like that.
+
+ // first search for the target
+ CRenderTarget* ptarg = NULL;
+
+ // have to change, so recreate (find all intersecting targets and Resolve)
+ u32 besttarg = 0;
+
+ if (!(opts & CRenderTargetMngr::TO_Virtual))
+ {
+
+ int start, end;
+ GetRectMemAddressZero(start, end, frame.psm, frame.fbw, frame.fbh, frame.fbp, frame.fbw);
+ CRenderTarget* pbesttarg = NULL;
+
+ if (besttarg == 0)
+ {
+ // if there is only one intersecting target and it encompasses the current one, update the new render target with
+ // its data instead of resolving then updating (ffx2). Do not change the original target.
+ for (MAPTARGETS::iterator it = mapTargets.begin(); it != mapTargets.end(); ++it)
+ {
+ if (it->second->start < end && start < it->second->end)
+ {
+ if ((conf.settings().fast_update) ||
+ ((frame.fbw == it->second->fbw) &&
+ // check depth targets only if partialdepth option
+ ((it->second->fbp != frame.fbp) || ((conf.settings().partial_depth) && (opts & CRenderTargetMngr::TO_DepthBuffer)))))
+ {
+ if (besttarg != 0)
+ {
+ besttarg = 0;
+ break;
+ }
+
+ if (start >= it->second->start && end <= it->second->end)
+ {
+ besttarg = it->first;
+ pbesttarg = it->second;
+ }
+ }
+ }
+ }
+ }
+
+ if (besttarg != 0 && pbesttarg->fbw != frame.fbw)
+ {
+ //ZZLog::Debug_Log("A %d %d %d %d\n", frame.psm, frame.fbw, pbesttarg->psm, pbesttarg->fbw);
+
+ vb[0].frame.fbw = pbesttarg->fbw;
+ // Something should be here, but what?
+ }
+
+ if (besttarg == 0)
+ {
+ // if none found, resolve all
+ DestroyAllTargs(start, end, frame.fbw);
+ }
+ else if (key == besttarg && pbesttarg != NULL)
+ {
+ // add one and store in a different location until best targ is processed
+ mapTargets.erase(besttarg);
+ besttarg++;
+ mapTargets[besttarg] = pbesttarg;
+ }
+ }
+
+ if (mapTargets.size() > 8)
+ {
+ // release some resources
+ it = GetOldestTarg(mapTargets);
+
+ // if more than 5s passed since target used, destroy
+
+ if ((it->second != vb[0].prndr) && (it->second != vb[1].prndr) &&
+ (it->second != vb[0].pdepth) && (it->second != vb[1].pdepth) &&
+ ((timeGetTime() - it->second->lastused) > 5000))
+ {
+ delete it->second;
+ mapTargets.erase(it);
+ }
+ }
+
+ if (ptarg == NULL)
+ {
+ // not found yet, so create
+
+ if (mapDummyTargs.size() > 8)
+ {
+ it = GetOldestTarg(mapDummyTargs);
+
+ delete it->second;
+ mapDummyTargs.erase(it);
+ }
+
+ it = mapDummyTargs.find(GetFrameKeyDummy(frame));
+
+ if (it != mapDummyTargs.end())
+ {
+ ZZLog::Debug_Log("Dummy Frame fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", frame.fbw, frame.fbh, frame.psm, frame.fbp);
+ PrintTargets();
+ ZZLog::Debug_Log("Dummy it->second fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", it->second->fbw, it->second->fbh, it->second->psm, it->second->fbp);
+ ptarg = it->second;
+
+ mapDummyTargs.erase(it);
+
+ // restore all setttings
+ ptarg->psm = frame.psm;
+ ptarg->fbm = frame.fbm;
+ ptarg->fbp = frame.fbp;
+
+ GetRectMemAddressZero(ptarg->start, ptarg->end, frame.psm, frame.fbw, frame.fbh, frame.fbp, frame.fbw);
+
+ ptarg->status = CRenderTarget::TS_NeedUpdate;
+ }
+ else
+ {
+ ZZLog::Debug_Log("Frame fbw:0x%x fbh:0x%x psm:0x%x fbp:0x%x", frame.fbw, frame.fbh, frame.psm, frame.fbp);
+ PrintTargets();
+ // create anew
+ ptarg = (opts & TO_DepthBuffer) ? new CDepthTarget : new CRenderTarget;
+ CRenderTargetMngr* pmngrs[2] = { &s_DepthRTs, this == &s_RTs ? &s_RTs : NULL };
+ int cur = 0;
+
+ while (!ptarg->Create(frame))
+ {
+ // destroy unused targets
+ if (mapDummyTargs.size() > 0)
+ {
+ it = mapDummyTargs.begin();
+ delete it->second;
+ mapDummyTargs.erase(it);
+ continue;
+ }
+
+ if (g_MemTargs.listClearedTargets.size() > 0)
+ {
+ g_MemTargs.DestroyCleared();
+ continue;
+ }
+ else if (g_MemTargs.listTargets.size() > 32)
+ {
+ g_MemTargs.DestroyOldest();
+ continue;
+ }
+
+ if (pmngrs[cur] == NULL)
+ {
+ cur = !cur;
+
+ if (pmngrs[cur] == NULL)
+ {
+ ZZLog::Warn_Log("Out of memory!");
+ delete ptarg;
+ return NULL;
+ }
+ }
+
+ if (pmngrs[cur]->mapTargets.size() == 0)
+ {
+ pmngrs[cur] = NULL;
+ cur = !cur;
+ continue;
+ }
+
+ it = GetOldestTarg(pmngrs[cur]->mapTargets);
+
+ DestroyTarg(it->second);
+ pmngrs[cur]->mapTargets.erase(it);
+ cur = !cur;
+ }
+ }
+ }
+
+ if ((opts & CRenderTargetMngr::TO_Virtual))
+ {
+ ptarg->status = CRenderTarget::TS_Virtual;
+ key |= TARGET_VIRTUAL_KEY;
+
+ if ((it = mapTargets.find(key)) != mapTargets.end())
+ {
+
+ DestroyTarg(it->second);
+ it->second = ptarg;
+ ptarg->nUpdateTarg = besttarg;
+ return ptarg;
+ }
+ }
+ else
+ {
+ assert(mapTargets.find(key) == mapTargets.end());
+ }
+
+ ptarg->nUpdateTarg = besttarg;
+
+ mapTargets[key] = ptarg;
+
+ return ptarg;
+}
+
+CRenderTargetMngr::MAPTARGETS::iterator CRenderTargetMngr::GetOldestTarg(MAPTARGETS& m)
+{
+ FUNCLOG
+
+ if (m.size() == 0)
+ {
+ return m.end();
+ }
+
+ // release some resources
+ MAPTARGETS::iterator itmaxtarg = m.begin();
+
+ for (MAPTARGETS::iterator it = ++m.begin(); it != m.end(); ++it)
+ {
+ if (itmaxtarg->second->lastused < it->second->lastused) itmaxtarg = it;
+ }
+
+ return itmaxtarg;
+}
+
+void CRenderTargetMngr::GetTargs(int start, int end, list& listTargets) const
+{
+ FUNCLOG
+
+ for (MAPTARGETS::const_iterator it = mapTargets.begin(); it != mapTargets.end(); ++it)
+ {
+ if ((it->second->start < end) && (start < it->second->end)) listTargets.push_back(it->second);
+ }
+}
+
+void CRenderTargetMngr::Resolve(int start, int end)
+{
+ FUNCLOG
+
+ for (MAPTARGETS::const_iterator it = mapTargets.begin(); it != mapTargets.end(); ++it)
+ {
+ if ((it->second->start < end) && (start < it->second->end))
+ it->second->Resolve();
+ }
+}
+
diff --git a/plugins/zzogl-pg/opengl/ZZoglCRTC.cpp b/plugins/zzogl-pg/opengl/ZZoglCRTC.cpp
index 152601321f..7acd72a291 100644
--- a/plugins/zzogl-pg/opengl/ZZoglCRTC.cpp
+++ b/plugins/zzogl-pg/opengl/ZZoglCRTC.cpp
@@ -21,7 +21,7 @@
// It draw picture direct on screen, so here we have interlacing and frame skipping.
//------------------ Includes
- #include "Util.h"
+#include "Util.h"
#include "ZZoglCRTC.h"
#include "GLWin.h"
#include "ZZoglShaders.h"
@@ -58,6 +58,17 @@ extern void ZZDestroy();
extern void ChangeDeviceSize(int nNewWidth, int nNewHeight);
extern GLuint vboRect;
+
+// I'm making this variable global for the moment in the course of fiddling with the interlace code
+// to try and make it more straightforward.
+int interlace_mode = 0; // 0 - not interlacing, 1 - interlacing.
+bool bUsingStencil = false;
+
+bool INTERLACE_COUNT()
+{
+ return (interlace_mode && (gs.interlace == conf.interlace));
+}
+
// Adjusts vertex shader BitBltPos vector v to preserve aspect ratio. It used to emulate 4:3 or 16:9.
void AdjustTransToAspect(float4& v)
{
@@ -151,20 +162,20 @@ inline void FrameSavingHelper()
}
// Function populated tex0Info[2] array
-inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo)
+inline void FrameObtainDispinfo(tex0Info* dispinfo)
{
for (int i = 0; i < 2; ++i)
{
-
- if (!(*(u32*)(PMODE) & (1 << i)))
+ if (!Circuit_Enabled(i))
{
dispinfo[i].tw = 0;
dispinfo[i].th = 0;
continue;
}
- GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1;
- GSRegDISPLAY* pd = i ? DISPLAY2 : DISPLAY1;
+ GSRegDISPFB* pfb = Dispfb_Reg(i);
+ GSRegDISPLAY* pd = Display_Reg(i);
+
int magh = pd->MAGH + 1;
int magv = pd->MAGV + 1;
@@ -177,7 +188,8 @@ 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 && !(conf.settings().interlace_2x))
+ // Note: This is what causes the double image if interlace is off on the Final Fantasy X-2 opening.
+ if (interlace_mode && 2 * dispinfo[i].tw / dispinfo[i].th <= 1 && !(conf.settings().interlace_2x))
{
dispinfo[i].th >>= 1;
}
@@ -187,9 +199,9 @@ inline void FrameObtainDispinfo(u32 bInterlace, tex0Info* dispinfo)
extern bool s_bWriteDepth;
// Something should be done before Renderering the picture.
-inline void RenderStartHelper(u32 bInterlace)
+inline void RenderStartHelper()
{
- if (conf.mrtdepth && pvs[8] == NULL)
+ if (conf.mrtdepth && ZZshExistProgram(pvs[8]))
{
conf.mrtdepth = 0;
s_bWriteDepth = false;
@@ -209,14 +221,13 @@ inline void RenderStartHelper(u32 bInterlace)
vb[0].fba.fba = 0;
vb[1].fba.fba = 0;
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
+ FB::Unbind(); // switch to the backbuffer
glViewport(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h);
// if interlace, only clear every other vsync
- if (!bInterlace)
+ if (!interlace_mode)
{
- //u32 color = COLOR_ARGB(0, BGCOLOR->R, BGCOLOR->G, BGCOLOR->B);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
@@ -232,7 +243,7 @@ inline void RenderStartHelper(u32 bInterlace)
GL_REPORT_ERRORD();
- if (bInterlace) g_PrevBitwiseTexX = -1; // reset since will be using
+ if (interlace_mode) g_PrevBitwiseTexX = -1; // reset since will be using
}
// Settings for interlace texture multiplied vector;
@@ -240,14 +251,14 @@ inline void RenderStartHelper(u32 bInterlace)
// on image y coords. So if we write valpha.z * F + valpha.w + 0.5, it would be switching odd
// and even strings at each frame.
// valpha.x and y are used for image blending.
-inline float4 RenderGetForClip(u32 bInterlace, int interlace, int psm, FRAGMENTSHADER* prog)
+inline float4 RenderGetForClip(int psm, CRTC_TYPE render_type)
{
SetShaderCaller("RenderGetForClip");
-
+ FRAGMENTSHADER* prog = curr_pps(render_type);
float4 valpha;
// first render the current render targets, then from ptexMem
- if (psm == 1)
+ if (psm == PSMCT24)
{
valpha.x = 1;
valpha.y = 0;
@@ -258,9 +269,9 @@ inline float4 RenderGetForClip(u32 bInterlace, int interlace, int psm, FRAGMENTS
valpha.y = 1;
}
- if (bInterlace)
+ if (interlace_mode)
{
- if (interlace == (conf.interlace & 1))
+ if (gs.interlace == (conf.interlace & 1))
{
// pass if odd
valpha.z = 1.0f;
@@ -286,17 +297,21 @@ inline float4 RenderGetForClip(u32 bInterlace, int interlace, int psm, FRAGMENTS
}
// 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)
+// Note: if the frame is interlaced, its th is halved, so we should multiply it by 2.
+inline void RenderCreateInterlaceTex(int th, CRTC_TYPE render_type)
{
- if (!bInterlace) return;
-
- int interlacetex = CreateInterlaceTex(2 * th);
+ FRAGMENTSHADER* prog;
+ int interlacetex;
+
+ if (!interlace_mode) return;
+
+ prog = curr_pps(render_type);
+ interlacetex = CreateInterlaceTex(2 * th);
ZZshGLSetTextureParameter(prog->prog, prog->sInterlace, interlacetex, "Interlace");
}
-// Well, do blending setup prior to second pass of half-frame drawing
+// Do blending setup prior to second pass of half-frame drawing.
inline void RenderSetupBlending()
{
// setup right blending
@@ -305,12 +320,14 @@ inline void RenderSetupBlending()
if (PMODE->MMOD)
{
+ // Use the ALP register for alpha blending.
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
{
+ // Use the alpha value of circuit 1 for alpha blending.
s_srcrgb = GL_SRC_ALPHA;
s_dstrgb = GL_ONE_MINUS_SRC_ALPHA;
}
@@ -332,17 +349,19 @@ inline void RenderSetupBlending()
// each frame could be drawn in two stages, so blending should be different for them
inline void RenderSetupStencil(int i)
{
- glStencilMask(1 << i);
s_stencilmask = 1 << i;
+ glStencilMask(s_stencilmask);
GL_STENCILFUNC_SET();
}
// do stencil check for each found target i -- texturing stage
-inline void RenderUpdateStencil(int i, bool* bUsingStencil)
+inline void RenderUpdateStencil(int i)
{
- if (!(*bUsingStencil)) glClear(GL_STENCIL_BUFFER_BIT);
-
- *bUsingStencil = 1;
+ if (!bUsingStencil)
+ {
+ glClear(GL_STENCIL_BUFFER_BIT);
+ bUsingStencil = true;
+ }
glEnable(GL_STENCIL_TEST);
GL_STENCILFUNC(GL_NOTEQUAL, 3, 1 << i);
@@ -351,16 +370,16 @@ inline void RenderUpdateStencil(int i, bool* bUsingStencil)
}
// CRTC24 could not be rendered
-inline void RenderCRTC24helper(u32 bInterlace, int interlace, int psm)
+/*inline void RenderCRTC24helper(int psm)
{
ZZLog::Debug_Log("ZZogl: CRTC24!!! I'm trying to show something.");
SetShaderCaller("RenderCRTC24helper");
// assume that data is already in ptexMem (do Resolve?)
- RenderGetForClip(bInterlace, interlace, psm, &ppsCRTC24[bInterlace]);
- ZZshSetPixelShader(ppsCRTC24[bInterlace].prog);
+ RenderGetForClip(psm, CRTC_RENDER_24);
+ ZZshSetPixelShader(curr_ppsCRTC24()->prog);
DrawTriangleArray();
-}
+}*/
// Maybe I do this function global-defined. Calculate bits per pixel for
// each psm. It's the only place with PSMCT16 which have a different bpp.
@@ -394,7 +413,7 @@ inline int RenderGetOffsets(int* dby, int* movy, tex0Info& texframe, CRenderTarg
}
// BltBit shader calculate vertex (4 coord's pixel) position at the viewport.
-inline float4 RenderSetTargetBitPos(int dh, int th, int movy, bool isInterlace)
+inline float4 RenderSetTargetBitPos(int dh, int th, int movy)
{
SetShaderCaller("RenderSetTargetBitPos");
float4 v;
@@ -408,7 +427,7 @@ inline float4 RenderSetTargetBitPos(int dh, int th, int movy, bool isInterlace)
AdjustTransToAspect(v);
- if (isInterlace)
+ if (INTERLACE_COUNT())
{
// move down by 1 pixel
v.w += 1.0f / (float)dh ;
@@ -423,7 +442,7 @@ inline float4 RenderSetTargetBitPos(int dh, int th, int movy, bool isInterlace)
// For example, use tw / X and tw / X magnify the viewport.
// Interlaced output is little out of VB, it could be seen as an evil blinking line on top
// and bottom, so we try to remove it.
-inline float4 RenderSetTargetBitTex(float th, float tw, float dh, float dw, bool isInterlace)
+inline float4 RenderSetTargetBitTex(float th, float tw, float dh, float dw)
{
SetShaderCaller("RenderSetTargetBitTex");
@@ -432,7 +451,7 @@ inline float4 RenderSetTargetBitTex(float th, float tw, float dh, float dw, bool
// Incorrect Aspect ratio on interlaced frames
- if (isInterlace)
+ if (INTERLACE_COUNT())
{
v.y -= 1.0f / conf.height;
v.w += 1.0f / conf.height;
@@ -455,10 +474,11 @@ inline float4 RenderSetTargetBitTrans(int th)
// use g_fInvTexDims to store inverse texture dims
// Seems, that Targ shader does not use it
-inline float4 RenderSetTargetInvTex(int bInterlace, int tw, int th, FRAGMENTSHADER* prog)
+inline float4 RenderSetTargetInvTex(int tw, int th, CRTC_TYPE render_type)
{
SetShaderCaller("RenderSetTargetInvTex");
+ FRAGMENTSHADER* prog = curr_pps(render_type);
float4 v = float4(0, 0, 0, 0);
if (prog->sInvTexDims)
@@ -496,17 +516,20 @@ inline bool RenderLookForABetterTarget(int fbp, int tbp, list& l
return false;
}
-inline void RenderCheckForMemory(tex0Info& texframe, list& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace);
+inline void RenderCheckForMemory(tex0Info& texframe, list& listTargs, int circuit);
// First try to draw frame from targets.
-inline void RenderCheckForTargets(tex0Info& texframe, list& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace)
+inline void RenderCheckForTargets(tex0Info& texframe, list& listTargs, int circuit)
{
// get the start and end addresses of the buffer
int bpp = RenderGetBpp(texframe.psm);
- GSRegDISPFB* pfb = i ? DISPFB2 : DISPFB1;
+ GSRegDISPFB* pfb = Dispfb_Reg(circuit);
int start, end;
- GetRectMemAddress(start, end, texframe.psm, 0, 0, texframe.tw, texframe.th, texframe.tbp0, texframe.tbw);
+ int tex_th = (interlace_mode) ? texframe.th * 2 : texframe.th;
+
+ //ZZLog::WriteLn("Render checking for targets, circuit %d", circuit);
+ GetRectMemAddressZero(start, end, texframe.psm, texframe.tw, tex_th, texframe.tbp0, texframe.tbw);
// We need share list of targets between functions
s_RTs.GetTargs(start, end, listTargs);
@@ -517,10 +540,14 @@ inline void RenderCheckForTargets(tex0Info& texframe, list& list
if (ptarg->fbw == texframe.tbw && !(ptarg->status&CRenderTarget::TS_NeedUpdate) && ((256 / bpp)*(texframe.tbp0 - ptarg->fbp)) % texframe.tbw == 0)
{
+ FRAGMENTSHADER* pps;
int dby = pfb->DBY;
int movy = 0;
- if (RenderLookForABetterTarget(ptarg->fbp, texframe.tbp0, listTargs, it)) continue;
+ 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));
@@ -529,37 +556,42 @@ inline void RenderCheckForTargets(tex0Info& texframe, list& list
if (dh >= 64)
{
-
- if (ptarg->fbh - dby < texframe.th - movy && !(*bUsingStencil))
- RenderUpdateStencil(i, bUsingStencil);
- else if (ptarg->fbh - dby > 2 * ( texframe.th - movy ))
+ if (ptarg->fbh - dby < tex_th - movy && !bUsingStencil)
+ {
+ RenderUpdateStencil(circuit);
+ }
+ else if (ptarg->fbh - dby > 2 * ( tex_th - movy )) // I'm not sure this is needed any more.
{
// Sometimes calculated position onscreen is misaligned, ie in FFX-2 intro. In such case some part of image are out of
// border's and we should move it manually.
- dby -= ((ptarg->fbh - dby) >> 2) - ((texframe.th + movy) >> 1) ;
+ dby -= ((ptarg->fbh - dby) >> 2) - ((tex_th + movy) >> 1);
}
SetShaderCaller("RenderCheckForTargets");
// Texture
- float4 v = RenderSetTargetBitTex((float)RW(texframe.tw), (float)RH(dh), (float)RW(pfb->DBX), (float)RH(dby), INTERLACE_COUNT);
-
+ float4 v = RenderSetTargetBitTex((float)RW(texframe.tw), (float)RH(dh), (float)RW(pfb->DBX), (float)RH(dby));
+
// dest rect
- v = RenderSetTargetBitPos(dh, texframe.th, movy, INTERLACE_COUNT);
+ v = RenderSetTargetBitPos(dh, texframe.th, movy);
v = RenderSetTargetBitTrans(ptarg->fbh);
- v = RenderSetTargetInvTex(bInterlace, texframe.tbw, ptarg->fbh, &ppsCRTCTarg[bInterlace]) ; // FIXME. This is no use
+ v = RenderSetTargetInvTex(texframe.tbw, ptarg->fbh, CRTC_RENDER_TARG); // FIXME. This is no use
- float4 valpha = RenderGetForClip(bInterlace, interlace, texframe.psm, &ppsCRTCTarg[bInterlace]);
+ float4 valpha = RenderGetForClip(texframe.psm, CRTC_RENDER_TARG);
+ pps = curr_ppsCRTCTarg();
// inside vb[0]'s target area, so render that region only
- ZZshGLSetTextureParameter(ppsCRTCTarg[bInterlace].prog, ppsCRTCTarg[bInterlace].sFinal, ptarg->ptex, "CRTC target");
- RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTCTarg[bInterlace]);
+ ZZshGLSetTextureParameter(pps->prog, pps->sFinal, ptarg->ptex, "CRTC target");
+ RenderCreateInterlaceTex(texframe.th, CRTC_RENDER_TARG);
- ZZshSetPixelShader(ppsCRTCTarg[bInterlace].prog);
+ ZZshSetPixelShader(pps->prog);
DrawTriangleArray();
- if (abs(dh - (int)texframe.th) <= 1) return;
+ if (abs(dh - (int)texframe.th) <= 1)
+ {
+ return;
+ }
if (abs(dh - (int)ptarg->fbh) <= 1)
{
@@ -571,14 +603,14 @@ inline void RenderCheckForTargets(tex0Info& texframe, list& list
++it;
}
- RenderCheckForMemory(texframe, listTargs, i, bUsingStencil, interlace, bInterlace);
+ RenderCheckForMemory(texframe, listTargs, circuit);
}
// 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& listTargs, int i, bool* bUsingStencil, int interlace, int bInterlace)
+inline void RenderCheckForMemory(tex0Info& texframe, list& listTargs, int circuit)
{
float4 v;
@@ -588,9 +620,9 @@ inline void RenderCheckForMemory(tex0Info& texframe, list& listT
}
// context has to be 0
- if (bInterlace >= 2) ZZLog::Error_Log("CRCR Check for memory shader fault.");
+ if (interlace_mode >= 2) ZZLog::Error_Log("CRCR Check for memory shader fault.");
- //if (!(*bUsingStencil)) RenderUpdateStencil(i, bUsingStencil);
+ //if (!bUsingStencil) RenderUpdateStencil(i);
SetShaderCaller("RenderCheckForMemory");
@@ -601,7 +633,7 @@ inline void RenderCheckForMemory(tex0Info& texframe, list& listT
h1 = texframe.th;
w2 = -0.5f;
h2 = -0.5f;
- SetTexVariablesInt(0, 2, texframe, false, &ppsCRTC[bInterlace], 1);
+ SetTexVariablesInt(0, 2, texframe, false, curr_ppsCRTC(), 1);
}
else
{
@@ -609,24 +641,24 @@ inline void RenderCheckForMemory(tex0Info& texframe, list& listT
h1 = 1;
w2 = -0.5f / (float)texframe.tw;
h2 = -0.5f / (float)texframe.th;
- SetTexVariablesInt(0, 0, texframe, false, &ppsCRTC[bInterlace], 1);
+ SetTexVariablesInt(0, 0, texframe, false, curr_ppsCRTC(), 1);
}
if (g_bSaveFinalFrame) SaveTex(&texframe, g_bSaveFinalFrame - 1 > 0);
// Fixme: Why is this here?
// We should probably call RenderSetTargetBitTex instead.
- v = RenderSetTargetBitTex(w1, h1, w2, h2, INTERLACE_COUNT);
+ v = RenderSetTargetBitTex(w1, h1, w2, h2);
// finally render from the memory (note that the stencil buffer will keep previous regions)
- v = RenderSetTargetBitPos(1, 1, 0, INTERLACE_COUNT);
+ v = RenderSetTargetBitPos(1, 1, 0);
v = RenderSetTargetBitTrans(texframe.th);
- v = RenderSetTargetInvTex(bInterlace, texframe.tw, texframe.th, &ppsCRTC[bInterlace]);
- float4 valpha = RenderGetForClip(bInterlace, interlace, texframe.psm, &ppsCRTC[bInterlace]);
+ v = RenderSetTargetInvTex(texframe.tw, texframe.th, CRTC_RENDER);
+ float4 valpha = RenderGetForClip(texframe.psm, CRTC_RENDER);
- ZZshGLSetTextureParameter(ppsCRTC[bInterlace].prog, ppsCRTC[bInterlace].sMemory, vb[0].pmemtarg->ptex->tex, "CRTC memory");
- RenderCreateInterlaceTex(bInterlace, texframe.th, &ppsCRTC[bInterlace]);
- ZZshSetPixelShader(ppsCRTC[bInterlace].prog);
+ ZZshGLSetTextureParameter(curr_ppsCRTC()->prog, curr_ppsCRTC()->sMemory, vb[0].pmemtarg->ptex->tex, "CRTC memory");
+ RenderCreateInterlaceTex(texframe.th, CRTC_RENDER_TARG);
+ ZZshSetPixelShader(curr_ppsCRTC()->prog);
DrawTriangleArray();
}
@@ -657,7 +689,7 @@ inline void DisplayFPS()
DrawText(str, left, top, 0xffc0ffff);
}
-// SnapeShoot helper
+// Snapshot helper
inline void MakeSnapshot()
{
@@ -694,7 +726,7 @@ void ZZReset()
s_nLastResolveReset = 0;
icurctx = -1;
- g_vsprog = g_psprog = 0;
+ g_vsprog = g_psprog = sZero;
ZZGSStateReset();
ZZDestroy();
@@ -759,12 +791,10 @@ inline void AfterRendererUnimportantJob()
maxmin = 608;
}
-extern u32 s_uFramebuffer;
-
// Swich Framebuffers
inline void AfterRendererSwitchBackToTextures()
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer);
+ FB::Bind();
g_MemTargs.DestroyCleared();
@@ -815,18 +845,6 @@ inline void AfterRendererAutoresetTargets()
s_RTs.ResolveAll();
return;
-// s_RTs.Destroy();
-// s_DepthRTs.ResolveAll();
-// s_DepthRTs.Destroy();
-//
-// vb[0].prndr = NULL;
-// vb[0].pdepth = NULL;
-// vb[0].bNeedFrameCheck = 1;
-// vb[0].bNeedZCheck = 1;
-// vb[1].prndr = NULL;
-// vb[1].pdepth = NULL;
-// vb[1].bNeedFrameCheck = 1;
-// vb[1].bNeedZCheck = 1;
}
}
@@ -840,49 +858,59 @@ inline void AfterRendererAutoresetTargets()
}
int count = 0;
+
// The main renderer function
-void RenderCRTC(int interlace)
+void RenderCRTC()
{
- if (FrameSkippingHelper()) return;
-
- u32 bInterlace = SMODE2->INT && SMODE2->FFMD && (conf.interlace < 2);
-
- RenderStartHelper(bInterlace);
-
- bool bUsingStencil = false;
tex0Info dispinfo[2];
+
+ if (FrameSkippingHelper()) return;
+
+ // If we are in frame mode and interlacing, and we haven't forced interlacing off, interlace_mode is 1.
+ interlace_mode = SMODE2->INT && SMODE2->FFMD && (conf.interlace < 2);
+ bUsingStencil = false;
- FrameObtainDispinfo(bInterlace, dispinfo);
+ RenderStartHelper();
+ FrameObtainDispinfo(dispinfo);
+
// start from the last circuit
for (int i = !PMODE->SLBG; i >= 0; --i)
{
+ if (!Circuit_Enabled(i)) continue;
tex0Info& texframe = dispinfo[i];
- if (texframe.th <= 1) continue;
+ // I don't think this is neccessary, now that we make sure the ciruit we are working with is enabled.
+ /*if (texframe.th <= 1)
+ {
+ continue;
+ }*/
+
if (SMODE2->INT && SMODE2->FFMD)
{
texframe.th >>= 1;
-
+
// Final Fantasy X-2 issue here.
- if (conf.interlace == 2 && texframe.th >= 512)
+ /*if (conf.interlace == 2 && texframe.th >= 512)
+ {
texframe.th >>= 1;
+ }*/
}
if (i == 0) RenderSetupBlending();
if (bUsingStencil) RenderSetupStencil(i);
- if (texframe.psm == 0x12)
+ /*if (texframe.psm == 0x12) // Probably broken - 0x12 isn't a valid psm. 24 bit is 1.
{
- RenderCRTC24helper(bInterlace, interlace, texframe.psm);
+ RenderCRTC24helper(texframe.psm);
continue;
- }
+ }*/
// We shader targets between two functions, so declare it here;
list listTargs;
- // if we could not draw image from target's do it from memory
- RenderCheckForTargets(texframe, listTargs, i, &bUsingStencil, interlace, bInterlace);
+ // if we could not draw image from target's, do it from memory
+ RenderCheckForTargets(texframe, listTargs, i);
}
GL_REPORT_ERRORD();
diff --git a/plugins/zzogl-pg/opengl/ZZoglCRTC.h b/plugins/zzogl-pg/opengl/ZZoglCRTC.h
index 5ca9830e73..e3741290eb 100644
--- a/plugins/zzogl-pg/opengl/ZZoglCRTC.h
+++ b/plugins/zzogl-pg/opengl/ZZoglCRTC.h
@@ -21,11 +21,8 @@
#define ZZOGLCRTC_H_INCLUDED
#include
-
#include "targets.h"
-#define INTERLACE_COUNT (bInterlace && interlace == (conf.interlace))
-
#ifdef _WIN32
extern HDC hDC; // Private GDI Device Context
extern HGLRC hRC; // Permanent Rendering Context
diff --git a/plugins/zzogl-pg/opengl/ZZoglCreate.cpp b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp
index 5de08ab18c..5adb52112d 100644
--- a/plugins/zzogl-pg/opengl/ZZoglCreate.cpp
+++ b/plugins/zzogl-pg/opengl/ZZoglCreate.cpp
@@ -35,42 +35,6 @@
# include "Win32.h"
#endif
-//------------------ Defines
-
-#ifdef _WIN32
-#define GL_LOADFN(name) { \
- if( (*(void**)&name = (void*)wglGetProcAddress(#name)) == NULL ) { \
- ZZLog::Error_Log("Failed to find %s, exiting.", #name); \
- } \
-}
-#else
-// let GLEW take care of it
-#define GL_LOADFN(name)
-#endif
-
-#define GL_BLEND_RGB(src, dst) { \
- s_srcrgb = src; \
- s_dstrgb = dst; \
- zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
-}
-
-#define GL_BLEND_ALPHA(src, dst) { \
- s_srcalpha = src; \
- s_dstalpha = dst; \
- zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
-}
-
-#define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \
- s_srcrgb = srcrgb; \
- s_dstrgb = dstrgb; \
- s_srcalpha = srcalpha; \
- s_dstalpha = dstalpha; \
- zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
-}
-
-#define GL_BLEND_SET() zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha)
-#define VB_NUMBUFFERS 512
-
// ----------------- Types
typedef void (APIENTRYP _PFNSWAPINTERVAL)(int);
@@ -81,8 +45,8 @@ extern bool ZZshLoadExtraEffects();
extern FRAGMENTSHADER* ZZshLoadShadeEffect(int type, int texfilter, int fog, int testaem, int exactcolor, const clampInfo& clamp, int context, bool* pbFailed);
GLuint vboRect = 0;
-vector g_vboBuffers; // VBOs for all drawing commands
-int g_nCurVBOIndex = 0;
+GLuint g_vboBuffers[VB_NUMBUFFERS]; // VBOs for all drawing commands
+u32 g_nCurVBOIndex = 0;
inline bool CreateImportantCheck();
inline void CreateOtherCheck();
@@ -125,10 +89,10 @@ void (APIENTRY *zgsBlendFuncSeparateEXT)(GLenum, GLenum, GLenum, GLenum) = NULL;
extern u8* s_lpShaderResources;
// String's for shader file in developer mode
-#ifdef ZEROGS_DEVBUILD
+//#ifdef ZEROGS_DEVBUILD
char* EFFECT_NAME = "";
char* EFFECT_DIR = "";
-#endif
+//#endif
/////////////////////
// graphics resources
@@ -143,12 +107,17 @@ GLenum g_internalRGBAFloat16Fmt = GL_RGBA_FLOAT16_ATI;
u32 ptexLogo = 0;
int nLogoWidth, nLogoHeight;
u32 s_ptexInterlace = 0; // holds interlace fields
+static bool vb_buffer_allocated = false;
//------------------ Global Variables
int GPU_TEXWIDTH = 512;
float g_fiGPU_TEXWIDTH = 1/512.0f;
int g_MaxTexWidth = 4096, g_MaxTexHeight = 4096;
-u32 s_uFramebuffer = 0;
+
+namespace FB
+{
+ u32 buf = 0;
+};
RasterFont* font_p = NULL;
float g_fBlockMult = 1;
@@ -157,7 +126,7 @@ float g_fBlockMult = 1;
u32 ptexBlocks = 0, ptexConv16to32 = 0; // holds information on block tiling
u32 ptexBilinearBlocks = 0;
u32 ptexConv32to16 = 0;
-int g_nDepthBias = 0;
+// int g_nDepthBias = 0;
extern void Delete_Avi_Capture();
extern void ZZDestroy();
@@ -505,7 +474,12 @@ bool ZZCreate(int _width, int _height)
GPU_TEXWIDTH = min (g_MaxTexWidth/8, 1024);
g_fiGPU_TEXWIDTH = 1.0f / GPU_TEXWIDTH;
+ // FIXME: not clean maybe re integrate the function in shader files --greg
+#ifndef GLSL_API
if (!CreateOpenShadersFile()) return false;
+#else
+ if (!ZZshCreateOpenShadersFile()) return false;
+#endif
GL_REPORT_ERROR();
@@ -520,16 +494,16 @@ bool ZZCreate(int _width, int _height)
if (err != GL_NO_ERROR) bSuccess = false;
- glGenFramebuffersEXT(1, &s_uFramebuffer);
+ FB::Create();
- if (s_uFramebuffer == 0)
+ if (FB::buf == 0)
{
ZZLog::Error_Log("Failed to create the renderbuffer.");
}
GL_REPORT_ERRORD();
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer);
+ FB::Bind();
DrawBuffers(s_drawbuffers);
@@ -600,14 +574,15 @@ bool ZZCreate(int _width, int _height)
g_nCurVBOIndex = 0;
- g_vboBuffers.resize(VB_NUMBUFFERS);
- glGenBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]);
-
- for (int 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);
- }
+ if (!vb_buffer_allocated) {
+ glGenBuffers((GLsizei)ArraySize(g_vboBuffers), g_vboBuffers);
+ for (int i = 0; i < ArraySize(g_vboBuffers); ++i)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[i]);
+ glBufferData(GL_ARRAY_BUFFER, 0x100*sizeof(VertexGPU), NULL, GL_STREAM_DRAW);
+ }
+ vb_buffer_allocated = true; // mark the buffer allocated
+ }
GL_REPORT_ERROR();
if (err != GL_NO_ERROR) bSuccess = false;
@@ -616,6 +591,11 @@ bool ZZCreate(int _width, int _height)
g_fBlockMult = 1;
bool do_not_use_billinear = false;
+#ifndef ZZNORMAL_MEMORY
+ FillAlowedPsnTable();
+ FillBlockTables();
+#endif
+
vector vBlockData, vBilinearData;
BLOCK::FillBlocks(vBlockData, vBilinearData, 1);
@@ -781,7 +761,7 @@ bool ZZCreate(int _width, int _height)
// This was changed in SetAA - should we be changing it back?
glPointSize(1.0f);
- g_nDepthBias = 0;
+ // g_nDepthBias = 0;
glEnable(GL_POLYGON_OFFSET_FILL);
glEnable(GL_POLYGON_OFFSET_LINE);
@@ -791,7 +771,7 @@ bool ZZCreate(int _width, int _height)
vb[0].Init(VB_BUFFERSIZE);
vb[1].Init(VB_BUFFERSIZE);
- g_vsprog = g_psprog = 0;
+ g_vsprog = g_psprog = sZero;
if (glGetError() == GL_NO_ERROR)
{
@@ -823,10 +803,10 @@ void ZZDestroy()
vb[0].Destroy();
vb[1].Destroy();
- if (g_vboBuffers.size() > 0)
+ if (vb_buffer_allocated)
{
- glDeleteBuffers((GLsizei)g_vboBuffers.size(), &g_vboBuffers[0]);
- g_vboBuffers.clear();
+ glDeleteBuffers((GLsizei)ArraySize(g_vboBuffers), g_vboBuffers);
+ vb_buffer_allocated = false; // mark the buffer unallocated
}
g_nCurVBOIndex = 0;
@@ -864,8 +844,8 @@ void ZZDestroy()
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(ppsCRTC24[0].prog);
+// SAFE_RELEASE_PROG(ppsCRTC24[1].prog);
SAFE_RELEASE_PROG(ppsOne.prog);
safe_delete(font_p);
diff --git a/plugins/zzogl-pg/opengl/ZZoglFlush.cpp b/plugins/zzogl-pg/opengl/ZZoglFlush.cpp
index bbe3e2a007..aa3cc7f082 100644
--- a/plugins/zzogl-pg/opengl/ZZoglFlush.cpp
+++ b/plugins/zzogl-pg/opengl/ZZoglFlush.cpp
@@ -20,6 +20,7 @@
// Realization of Flush -- drawing function of GS
#include
+#include
#include "GS.h"
#include "Mem.h"
@@ -27,109 +28,30 @@
#include "ZZoglFlushHack.h"
#include "ZZoglShaders.h"
#include "ZZClut.h"
-#include
+#include "ZZoglFlush.h"
//------------------ Defines
-#ifndef ZEROGS_DEVBUILD
-#define INC_GENVARS()
-#define INC_TEXVARS()
-#define INC_ALPHAVARS()
-#define INC_RESOLVE()
-
-#define g_bUpdateEffect 0
-#define g_bSaveTex 0
-bool g_bSaveTrans = 0;
-#define g_bSaveResolved 0
-
-#else // defined(ZEROGS_DEVBUILD)
-
-#define INC_GENVARS() ++g_nGenVars
-#define INC_TEXVARS() ++g_nTexVars
-#define INC_ALPHAVARS() ++g_nAlphaVars
-#define INC_RESOLVE() ++g_nResolve
-
-bool g_bSaveTrans = 0;
-bool g_bUpdateEffect = 0;
-bool g_bSaveTex = 0; // saves the curent texture
-bool g_bSaveResolved = 0;
+#ifdef ZEROGS_DEVBUILD
+bool g_bUpdateEffect = false;
+bool g_bSaveTex = false; // saves the current texture
+bool g_bSaveResolved = false;
#endif // !defined(ZEROGS_DEVBUILD)
-#define STENCIL_ALPHABIT 1 // if set, dest alpha >= 0x80
-#define STENCIL_PIXELWRITE 2 // if set, pixel just written (reset after every Flush)
-#define STENCIL_FBA 4 // if set, just written pixel's alpha >= 0 (reset after every Flush)
-#define STENCIL_SPECIAL 8 // if set, indicates that pixel passed its alpha test (reset after every Flush)
-//#define STENCIL_PBE 16
-#define STENCIL_CLEAR (2|4|8|16)
+bool g_bSaveTrans = false;
+bool s_bWriteDepth = false;
+bool s_bDestAlphaTest = false;
-void Draw(const VB& curvb)
-{
- glDrawArrays(primtype[curvb.curprim.prim], 0, curvb.nCount);
-}
-
-#define GL_BLEND_RGB(src, dst) { \
- s_srcrgb = src; \
- s_dstrgb = dst; \
- zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
-}
-
-#define GL_BLEND_ALPHA(src, dst) { \
- s_srcalpha = src; \
- s_dstalpha = dst; \
- zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
-}
-
-#define GL_BLEND_ALL(srcrgb, dstrgb, srcalpha, dstalpha) { \
- s_srcrgb = srcrgb; \
- s_dstrgb = dstrgb; \
- s_srcalpha = srcalpha; \
- s_dstalpha = dstalpha; \
- zgsBlendFuncSeparateEXT(s_srcrgb, s_dstrgb, s_srcalpha, s_dstalpha); \
-}
-
-#define GL_ZTEST(enable) { \
- if (enable) glEnable(GL_DEPTH_TEST); \
- else glDisable(GL_DEPTH_TEST); \
-}
-
-#define GL_ALPHATEST(enable) { \
- if( enable ) glEnable(GL_ALPHA_TEST); \
- else glDisable(GL_ALPHA_TEST); \
-}
-
-#define GL_BLENDEQ_RGB(eq) { \
- s_rgbeq = eq; \
- zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \
-}
-
-#define GL_BLENDEQ_ALPHA(eq) { \
- s_alphaeq = eq; \
- zgsBlendEquationSeparateEXT(s_rgbeq, s_alphaeq); \
-}
-
-#define COLORMASK_RED 1
-#define COLORMASK_GREEN 2
-#define COLORMASK_BLUE 4
-#define COLORMASK_ALPHA 8
-#define GL_COLORMASK(mask) glColorMask(!!((mask)&COLORMASK_RED), !!((mask)&COLORMASK_GREEN), !!((mask)&COLORMASK_BLUE), !!((mask)&COLORMASK_ALPHA))
-
-// ----------------- Types
-//------------------ Dummies
-
-//------------------ variables
-
-extern int g_nDepthBias;
-extern float g_fBlockMult; // used for old cards, that do not support Alpha-32float textures. We store block data in u16 and use it.
-bool g_bUpdateStencil = 1;
-
-extern ZZshProgram g_psprog; // 2 -- ZZ
+bool g_bUpdateStencil = true;
+bool bCanRenderStencil = true;
// local alpha blending settings
-static GLenum s_rgbeq, s_alphaeq; // set by zgsBlendEquationSeparateEXT // ZZ
+GLenum s_rgbeq, s_alphaeq; // set by zgsBlendEquationSeparateEXT // ZZ
-
-static const u32 blendalpha[3] = { GL_SRC_ALPHA, GL_DST_ALPHA, GL_CONSTANT_COLOR_EXT }; // ZZ
-static const u32 blendinvalpha[3] = { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_CONSTANT_COLOR_EXT }; //ZZ
+// Note: blendalpha[2] & blendinvalpha[2] are never used !!! The index 2 is changed to 0
+// Note: blendalpha[3] & blendinvalpha[3] are special case for dest blending on 24bits. FIXME: I was expected GL_ONE & GL_ZERO ! -- greg
+static const u32 blendalpha[4] = { GL_SRC_ALPHA, GL_DST_ALPHA, GL_CONSTANT_COLOR_EXT, GL_SRC_ALPHA }; // ZZ
+static const u32 blendinvalpha[4] = { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_CONSTANT_COLOR_EXT, GL_ONE_MINUS_SRC_ALPHA }; //ZZ
static const u32 g_dwAlphaCmp[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL }; // ZZ
// used for afail case
@@ -142,93 +64,38 @@ static const u32 g_dwZCmp[] = { GL_NEVER, GL_ALWAYS, GL_GEQUAL, GL_GREATER };
static u32 s_ptexCurSet[2] = {0};
static u32 s_ptexNextSet[2] = {0}; // ZZ
-
-extern vector s_vecTempTextures; // temporary textures, released at the end of every frame
-extern bool s_bTexFlush;
-extern int g_nCurVBOIndex;
-bool s_bWriteDepth = false;
-bool s_bDestAlphaTest = false;
int s_ClutResolve = 0; // ZZ
int g_nDepthUsed = 0; // ffx2 pal movies
int s_nWriteDepthCount = 0; // ZZ
int s_nWriteDestAlphaTest = 0; // ZZ
+int s_nWireframeCount = 0;
////////////////////
// State parameters
static float4 vAlphaBlendColor; // used for GPU_COLOR
-
static bool bNeedBlendFactorInAlpha; // set if the output source alpha is different from the real source alpha (only when blend factor > 0x80)
static u32 s_dwColorWrite = 0xf; // the color write mask of the current target
-typedef union
-{
- struct
- {
- u8 _bNeedAlphaColor; // set if vAlphaBlendColor needs to be set
- u8 _b2XAlphaTest; // Only valid when bNeedAlphaColor is set. if 1st bit set set, double all alpha testing values
- // otherwise alpha testing needs to be done separately.
- u8 _bDestAlphaColor; // set to 1 if blending with dest color (process only one tri at a time). If 2, dest alpha is always 1.
- u8 _bAlphaClamping; // if first bit is set, do min; if second bit, do max
- };
-
- u32 _bAlphaState;
-} g_flag_vars;
-
-g_flag_vars g_vars;
-
-//#define bNeedAlphaColor g_vars._bNeedAlphaColor
-#define b2XAlphaTest g_vars._b2XAlphaTest
-#define bDestAlphaColor g_vars._bDestAlphaColor
-#define bAlphaClamping g_vars._bAlphaClamping
-
-int g_PrevBitwiseTexX = -1, g_PrevBitwiseTexY = -1; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY // ZZ
+// g_flag_vars g_vars;
//static alphaInfo s_alphaInfo; // ZZ
-extern u8* g_pbyGSClut;
-extern int ppf;
-
-int s_nWireframeCount = 0;
-
-//------------------ Namespace
+int g_PrevBitwiseTexX = -1, g_PrevBitwiseTexY = -1; // textures stored in SAMP_BITWISEANDX and SAMP_BITWISEANDY // ZZ
+float fiTexWidth[2], fiTexHeight[2]; // current tex width and height
+Point AA = {0,0}; // if AA.y is set, then AA.x has to be set.
VB vb[2];
-float fiTexWidth[2], fiTexHeight[2]; // current tex width and height
-extern vector g_vboBuffers; // VBOs for all drawing commands
-
-//u8 s_AAx = 0, s_AAy = 0; // if AAy is set, then AAx has to be set
-Point AA = {0,0};
-
int icurctx = -1;
-extern CRangeManager s_RangeMngr; // manages overwritten memory // zz
-void FlushTransferRanges(const tex0Info* ptex); //zz
-
-// use to update the state
-void SetTexVariables(int context, FRAGMENTSHADER* pfragment); // zz
-void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint); // zz
-void SetAlphaVariables(const alphaInfo& ainfo); // zzz
-//void ResetAlphaVariables();
-
-inline void SetAlphaTestInt(pixTest curtest);
-
-inline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor);
-inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting);
-inline void ProcessStencil(const VB& curvb);
-inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor);
-inline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor); // zz
-
-void SetContextTarget(int context);
-
-void SetWriteDepth();
-bool IsWriteDepth();
-void SetDestAlphaTest();
-
-//------------------ Code
+void Draw(const VB& curvb)
+{
+ glDrawArrays(primtype[curvb.curprim.prim], 0, curvb.nCount);
+}
inline float AlphaReferedValue(int aref)
{
- return b2XAlphaTest ? min(1.0f, (float)aref / 127.5f) : (float)aref / 255.0f ;
+ // return (b2XAlphaTest) ? min(1.0f, (float)aref / 127.5f) : (float)aref / 255.0f ;
+ return min(1.0f, (float)aref / 127.5f);
}
inline void SetAlphaTest(const pixTest& curtest)
@@ -371,7 +238,7 @@ inline void FlushUpdateEffect()
#endif
}
-// Check, maybe we cold skip flush
+// Check, maybe we could skip flush
inline bool IsFlushNoNeed(VB& curvb, const pixTest& curtest)
{
if (curvb.nCount == 0 || (curtest.zte && curtest.ztst == 0) || IsBadFrame(curvb))
@@ -653,9 +520,13 @@ inline void FlushSetContextTarget(VB& curvb, int context)
inline void FlushSetStream(VB& curvb)
{
+ // setup current buffer
glBindBuffer(GL_ARRAY_BUFFER, g_vboBuffers[g_nCurVBOIndex]);
- g_nCurVBOIndex = (g_nCurVBOIndex + 1) % g_vboBuffers.size();
glBufferData(GL_ARRAY_BUFFER, curvb.nCount * sizeof(VertexGPU), curvb.pBufferData, GL_STREAM_DRAW);
+
+ g_nCurVBOIndex = (g_nCurVBOIndex + 1) % ArraySize(g_vboBuffers);
+
+
// void* pdata = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// memcpy_amd(pdata, curvb.pBufferData, curvb.nCount * sizeof(VertexGPU));
// glUnmapBuffer(GL_ARRAY_BUFFER);
@@ -664,9 +535,6 @@ inline void FlushSetStream(VB& curvb)
GL_REPORT_ERRORD();
}
-int SetMaskR = 0x0;
-int SetMaskG = 0x0;
-int SetMaskB = 0x0;
// Set color mask. Really, it's not as good as PS2 one.
inline void FlushSetColorMask(VB& curvb)
{
@@ -681,7 +549,7 @@ inline void FlushSetColorMask(VB& curvb)
if (maskG == 0xff) s_dwColorWrite &= ~COLORMASK_GREEN;
if (maskB == 0xff) s_dwColorWrite &= ~COLORMASK_BLUE;
- if ((maskA == 0xff) || (curvb.curprim.abe && (curvb.test.atst == 2 && curvb.test.aref == 128)))
+ if ((maskA == 0xff) || (curvb.curprim.abe && (curvb.test.atst == ATST_LESS && curvb.test.aref == 128)))
s_dwColorWrite &= ~COLORMASK_ALPHA;
GL_COLORMASK(s_dwColorWrite);
@@ -712,7 +580,7 @@ inline int FlushGetExactcolor(const pixTest curtest)
{
if (!(g_nPixelShaderVer&SHADER_REDUCED))
// ffx2 breaks when ==7
- return ((curtest.ate && curtest.aref <= 128) && (curtest.atst == 4));//||curtest.atst==7);
+ return ((curtest.ate && curtest.aref <= 128) && (curtest.atst == ATST_EQUAL));// || curtest.atst == ATST_NOTEQUAL);
return 0;
}
@@ -825,7 +693,7 @@ inline float4 FlushSetPageOffset(FRAGMENTSHADER* pfragment, int shadertype, CRen
return vpageoffset;
}
-//Set texture offsets depends omn shader type.
+//Setting texture offsets depends on shader type.
inline float4 FlushSetTexOffset(FRAGMENTSHADER* pfragment, int shadertype, VB& curvb, CRenderTarget* ptextarg)
{
SetShaderCaller("FlushSetTexOffset");
@@ -985,11 +853,10 @@ inline void FlushSetTexture(VB& curvb, FRAGMENTSHADER* pfragment, CRenderTarget*
if( pfragment->sMemory != NULL && s_ptexCurSet[context] != 0)
ZZshGLSetTextureParameter(pfragment->sMemory, s_ptexCurSet[context], "Clamp memory");
-
}
// Reset program and texture variables;
-inline void FlushBindProgramm(FRAGMENTSHADER* pfragment, int context)
+inline void FlushBindProgram(FRAGMENTSHADER* pfragment, int context)
{
vb[context].bTexConstsSync = 0;
vb[context].bVarsTexSync = 0;
@@ -1029,7 +896,7 @@ inline FRAGMENTSHADER* FlushRendererStage(VB& curvb, u32& dwFilterOpts, CRenderT
// set the shaders
SetShaderCaller("FlushRendererStage");
ZZshSetVertexShader(pvs[2 * ((curvb.curprim._val >> 1) & 3) + 8 * s_bWriteDepth + context]);
- FlushBindProgramm(pfragment, context);
+ FlushBindProgram(pfragment, context);
GL_REPORT_ERRORD();
return pfragment;
@@ -1041,9 +908,9 @@ inline bool AlphaCanRenderStencil(VB& curvb)
!ZZOglGet_fbmHighByte(curvb.frame.fbm) && !(conf.settings().no_stencil);
}
-inline void AlphaSetStencil(bool DoIt)
+inline void AlphaSetStencil()
{
- if (DoIt)
+ if (s_bDestAlphaTest && bCanRenderStencil)
{
glEnable(GL_STENCIL_TEST);
GL_STENCILFUNC(GL_ALWAYS, 0, 0);
@@ -1062,11 +929,13 @@ inline void AlphaSetDepthTest(VB& curvb, const pixTest curtest, FRAGMENTSHADER*
if (curtest.zte)
{
if (curtest.ztst > 1) g_nDepthUsed = 2;
+#if 0
if ((curtest.ztst == 2) ^(g_nDepthBias != 0))
{
g_nDepthBias = (curtest.ztst == 2);
//SETRS(D3DRS_DEPTHBIAS, g_nDepthBias?FtoDW(0.0003f):FtoDW(0.000015f));
}
+#endif
glDepthFunc(g_dwZCmp[curtest.ztst]);
}
@@ -1101,7 +970,7 @@ inline u32 AlphaSetupBlendTest(VB& curvb)
return oldabe;
}
-inline void AlphaRenderFBA(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil)
+inline void AlphaRenderFBA(VB& curvb, FRAGMENTSHADER* pfragment)
{
// needs to be before RenderAlphaTest
if ((gs.pabe) || (curvb.fba.fba && !ZZOglGet_fbmHighByte(curvb.frame.fbm)) || (s_bDestAlphaTest && bCanRenderStencil))
@@ -1118,7 +987,7 @@ inline u32 AlphaRenderAlpha(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pf
if (curvb.curprim.abe)
{
- if ((bNeedBlendFactorInAlpha || ((curtest.ate && curtest.atst > 1) && (curtest.aref > 0x80))))
+ if ((bNeedBlendFactorInAlpha || ((curtest.ate && curtest.atst > ATST_ALWAYS) && (curtest.aref > 0x80))))
{
// need special stencil processing for the alpha
RenderAlphaTest(curvb, pfragment->sOneColor);
@@ -1147,7 +1016,7 @@ inline u32 AlphaRenderAlpha(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pf
return dwUsingSpecialTesting;
}
-inline void AlphaRenderStencil(VB& curvb, bool s_bDestAlphaTest, bool bCanRenderStencil, u32 dwUsingSpecialTesting)
+inline void AlphaRenderStencil(VB& curvb, u32 dwUsingSpecialTesting)
{
if (s_bDestAlphaTest && bCanRenderStencil)
{
@@ -1170,13 +1039,13 @@ inline void AlphaRenderStencil(VB& curvb, bool s_bDestAlphaTest, bool bCanRender
}
}
-#ifdef _DEBUG
- if (bDestAlphaColor == 1)
- {
- ZZLog::Debug_Log("Dest alpha blending! Manipulate alpha here.");
- }
-
-#endif
+// #ifdef _DEBUG
+// if (bDestAlphaColor == 1)
+// {
+// ZZLog::Debug_Log("Dest alpha blending! Manipulate alpha here.");
+// }
+//
+// #endif
if (bCanRenderStencil && gs.pabe)
{
@@ -1193,7 +1062,7 @@ inline void AlphaTest(VB& curvb)
// return;
// Zeydlitz changed this with a reason! It's an "Alpha more than 1 hack."
- if (curvb.test.ate == 1 && curvb.test.atst == 1 && curvb.test.date == 1)
+ if (curvb.test.ate == 1 && curvb.test.atst == ATST_ALWAYS && curvb.test.date == 1)
{
if (curvb.test.datm == 1)
{
@@ -1206,7 +1075,7 @@ inline void AlphaTest(VB& curvb)
}
}
- if (!curvb.test.ate || curvb.test.atst > 0)
+ if (!curvb.test.ate || curvb.test.atst > ATST_NEVER)
{
Draw(curvb);
}
@@ -1248,23 +1117,23 @@ inline void AlphaPabe(VB& curvb, FRAGMENTSHADER* pfragment, int exactcolor)
// First three cases are trivial manual.
inline bool AlphaFailureIgnore(const pixTest curtest)
{
- if ((!curtest.ate) || (curtest.atst == 1) || (curtest.afail == 0)) return true;
+ if ((!curtest.ate) || (curtest.atst == ATST_ALWAYS) || (curtest.afail == AFAIL_KEEP)) return true;
if (conf.settings().no_alpha_fail && ((s_dwColorWrite < 8) || (s_dwColorWrite == 15 && curtest.atst == 5 && (curtest.aref == 64))))
return true;
// old and seemingly incorrect code.
-// if ((s_dwColorWrite < 8 && s_dwColorWrite !=8) && curtest.afail == 1)
+// if ((s_dwColorWrite < 8 && s_dwColorWrite !=8) && curtest.afail == AFAIL_FB_ONLY)
// return true;
-// if ((s_dwColorWrite == 0xf) && curtest.atst == 5 && curtest.afail == 1 && !(conf.settings() & GAME_REGETHACK))
+// if ((s_dwColorWrite == 0xf) && curtest.atst == ATST_GEQUAL && curtest.afail == AFAIL_FB_ONLY && !(conf.settings() & GAME_REGETHACK))
// return true;
return false;
}
// more work on alpha failure case
-inline void AlphaFailureTestJob(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor, bool bCanRenderStencil, int oldabe)
+inline void AlphaFailureTestJob(VB& curvb, const pixTest curtest, FRAGMENTSHADER* pfragment, int exactcolor, int oldabe)
{
- // Note, case when ate == 1, atst == 0 and afail > 0 in documentation wrote as failure case. But it seems that
+ // Note, case when ate == 1, atst == ATST_NEVER and afail > AFAIL_KEEP in documentation wrote as failure case. But it seems that
// either doc's are incorrect or this case has some issues.
if (AlphaFailureIgnore(curtest)) return;
@@ -1281,7 +1150,7 @@ inline void AlphaFailureTestJob(VB& curvb, const pixTest curtest, FRAGMENTSHADE
if (curtest.afail & 1) // front buffer update only
{
- if (curtest.afail == 3) glColorMask(1, 1, 1, 0);// disable alpha
+ if (curtest.afail == AFAIL_RGB_ONLY) glColorMask(1, 1, 1, 0);// disable alpha
glDepthMask(0);
@@ -1385,27 +1254,26 @@ inline void AlphaSpecialTesting(VB& curvb, FRAGMENTSHADER* pfragment, u32 dwUsin
GL_REPORT_ERRORD();
}
-inline void AlphaDestinationTest(VB& curvb, FRAGMENTSHADER* pfragment, bool s_bDestAlphaTest, bool bCanRenderStencil)
+inline void AlphaDestinationTest(VB& curvb, FRAGMENTSHADER* pfragment)
{
- if (s_bDestAlphaTest)
+ if (s_dwColorWrite & COLORMASK_ALPHA)
{
- if ((s_dwColorWrite & COLORMASK_ALPHA))
+ if (curvb.fba.fba)
{
- if (curvb.fba.fba)
- ProcessFBA(curvb, pfragment->sOneColor);
- else if (bCanRenderStencil)
- // finally make sure all entries are 1 when the dest alpha >= 0x80 (if fba is 1, this is already the case)
- ProcessStencil(curvb);
+ ProcessFBA(curvb, pfragment->sOneColor);
+ }
+ else if (s_bDestAlphaTest && bCanRenderStencil)
+ {
+ // finally make sure all entries are 1 when the dest alpha >= 0x80 (if fba is 1, this is already the case)
+ ProcessStencil(curvb);
}
}
- else if ((s_dwColorWrite & COLORMASK_ALPHA) && curvb.fba.fba)
- ProcessFBA(curvb, pfragment->sOneColor);
-
- if (bDestAlphaColor == 1)
- {
- // need to reset the dest colors to their original counter parts
- //WARN_LOG("Need to reset dest alpha color\n");
- }
+
+ // if (bDestAlphaColor == 1)
+ // {
+ // // need to reset the dest colors to their original counter parts
+ // //ZZLog::Warn_Log("Need to reset dest alpha color");
+ // }
}
inline void AlphaSaveTarget(VB& curvb)
@@ -1425,7 +1293,7 @@ inline void AlphaSaveTarget(VB& curvb)
// Needs a # after frame to work properly.
// sprintf(str, "frames/frame.tga");
-// //glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer
+// //FB::Unbind(); // switch to the backbuffer
// //glFlush();
// //SaveTexture("tex.jpg", GL_TEXTURE_RECTANGLE_NV, curvb.prndr->ptex, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh));
// SaveRenderTarget(str, RW(curvb.prndr->fbw), RH(curvb.prndr->fbh), 0);
@@ -1465,26 +1333,26 @@ void Flush(int context)
FRAGMENTSHADER* pfragment = FlushRendererStage(curvb, dwFilterOpts, ptextarg, exactcolor, context);
- bool bCanRenderStencil = AlphaCanRenderStencil(curvb);
+ bCanRenderStencil = AlphaCanRenderStencil(curvb);
if (curtest.date || gs.pabe) SetDestAlphaTest();
- AlphaSetStencil(s_bDestAlphaTest && bCanRenderStencil);
+ AlphaSetStencil();
AlphaSetDepthTest(curvb, curtest, pfragment); // Error!
SetAlphaTest(curtest);
u32 oldabe = AlphaSetupBlendTest(curvb); // Unavoidable
// needs to be before RenderAlphaTest
- AlphaRenderFBA(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil);
+ AlphaRenderFBA(curvb, pfragment);
dwUsingSpecialTesting = AlphaRenderAlpha(curvb, curtest, pfragment, exactcolor); // Unavoidable
- AlphaRenderStencil(curvb, s_bDestAlphaTest, bCanRenderStencil, dwUsingSpecialTesting);
+ AlphaRenderStencil(curvb, dwUsingSpecialTesting);
AlphaTest(curvb); // Unavoidable
AlphaPabe(curvb, pfragment, exactcolor);
- AlphaFailureTestJob(curvb, curtest, pfragment, exactcolor, bCanRenderStencil, oldabe);
+ AlphaFailureTestJob(curvb, curtest, pfragment, exactcolor, oldabe);
AlphaSpecialTesting(curvb, pfragment, dwUsingSpecialTesting, exactcolor);
- AlphaDestinationTest(curvb, pfragment, s_bDestAlphaTest, bCanRenderStencil);
+ AlphaDestinationTest(curvb, pfragment);
AlphaSaveTarget(curvb);
GL_REPORT_ERRORD();
@@ -1507,6 +1375,14 @@ void FlushBoth()
Flush(1);
}
+// Often called for several reasons
+// Call flush if renderer or depth target is equal to ptr
+void FlushIfNecesary(void* ptr)
+{
+ if (vb[0].prndr == ptr || vb[0].pdepth == ptr) Flush(0);
+ if (vb[1].prndr == ptr || vb[1].pdepth == ptr) Flush(1);
+}
+
inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor)
{
// add fba to all pixels
@@ -1555,7 +1431,7 @@ __forceinline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor)
{
if (!g_bUpdateStencil) return;
- if ((curvb.test.ate) && (curvb.test.afail == 1)) glDisable(GL_ALPHA_TEST);
+ if ((curvb.test.ate) && (curvb.test.afail == AFAIL_FB_ONLY)) glDisable(GL_ALPHA_TEST);
glDepthMask(0);
@@ -1585,10 +1461,10 @@ __forceinline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor)
GL_STENCILFUNC_SET();
Draw(curvb);
- if (curvb.test.ate && curvb.test.afail != 1 && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
+ if (curvb.test.ate && curvb.test.afail != AFAIL_FB_ONLY && USEALPHATESTING) glEnable(GL_ALPHA_TEST);
}
- if (curvb.test.ate && curvb.test.atst > 1 && curvb.test.aref > 0x80)
+ if (curvb.test.ate && curvb.test.atst > ATST_ALWAYS && curvb.test.aref > 0x80)
{
v = float4(1,1,0,0);
ZZshSetParameter4fv(sOneColor, v, "g_fOneColor");
@@ -1726,7 +1602,7 @@ __forceinline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor)
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
Draw(curvb);
- if (curvb.test.atst && USEALPHATESTING)
+ if ((curvb.test.atst != ATST_NEVER) && USEALPHATESTING)
{
glEnable(GL_ALPHA_TEST);
glAlphaFunc(g_dwAlphaCmp[curvb.test.atst], AlphaReferedValue(curvb.test.aref));
@@ -1897,23 +1773,23 @@ void SetTexClamping(int context, FRAGMENTSHADER* pfragment)
switch (pclamp->wms)
{
- case 0:
+ case CLAMP_REPEAT:
v2.x = -1e10;
v2.z = 1e10;
break;
- case 1: // pclamp
+ case CLAMP_CLAMP: // pclamp
// suikoden5 movie text
v2.x = 0;
v2.z = 1 - 0.5f / fw;
break;
- case 2: // reg pclamp
+ case CLAMP_REGION_CLAMP: // reg pclamp
v2.x = (pclamp->minu + 0.5f) / fw;
v2.z = (pclamp->maxu - 0.5f) / fw;
break;
- case 3: // region rep x
+ case CLAMP_REGION_REPEAT: // region rep x
v.x = 0.9999f;
v.z = (float)fw;
v2.x = (float)GPU_TEXMASKWIDTH / fw;
@@ -1932,23 +1808,23 @@ void SetTexClamping(int context, FRAGMENTSHADER* pfragment)
switch (pclamp->wmt)
{
- case 0:
+ case CLAMP_REPEAT:
v2.y = -1e10;
v2.w = 1e10;
break;
- case 1: // pclamp
+ case CLAMP_CLAMP: // pclamp
// suikoden5 movie text
v2.y = 0;
v2.w = 1 - 0.5f / fh;
break;
- case 2: // reg pclamp
+ case CLAMP_REGION_CLAMP: // reg pclamp
v2.y = (pclamp->minv + 0.5f) / fh;
v2.w = (pclamp->maxv - 0.5f) / fh;
break;
- case 3: // region rep y
+ case CLAMP_REGION_REPEAT: // region rep y
v.y = 0.9999f;
v.w = (float)fh;
v2.y = (float)GPU_TEXMASKWIDTH / fh;
@@ -1993,17 +1869,14 @@ void SetTexVariables(int context, FRAGMENTSHADER* pfragment)
SetShaderCaller("SetTexVariables");
// alpha and texture highlighting
- float4 valpha, valpha2 ;
+ float4 valpha, valpha2;
// if clut, use the frame format
int psm = PIXEL_STORAGE_FORMAT(tex0);
// ZZLog::Error_Log( "A %d psm, is-clut %d. cpsm %d | %d %d", psm, PSMT_ISCLUT(psm), tex0.cpsm, tex0.tfx, tex0.tcc );
- float4 vblack;
- vblack.x = vblack.y = vblack.z = vblack.w = 10;
-
- /* tcc -- Tecture Color Component 0=RGB, 1=RGBA + use Alpha from TEXA reg when not in PSM
+ /* tcc -- Texture Color Component 0=RGB, 1=RGBA + use Alpha from TEXA reg when not in PSM
* tfx -- Texture Function (0=modulate, 1=decal, 2=hilight, 3=hilight2)
*
* valpha2 = 0 0 2 1 0 0 2 1
@@ -2018,124 +1891,42 @@ void SetTexVariables(int context, FRAGMENTSHADER* pfragment)
* 0 0 1 1 0 1 1 0 1 0 ta0 0 1 0
*/
- valpha2.x = (tex0.tfx == 1) ;
- valpha2.y = (tex0.tcc == 1) && (tex0.tfx != 0) ;
- valpha2.z = (tex0.tfx != 1) * 2 ;
- valpha2.w = (tex0.tfx == 0) ;
+ valpha2.x = (tex0.tfx == TFX_DECAL);
+ valpha2.y = (tex0.tcc == 1) && (tex0.tfx != TFX_MODULATE);
+ valpha2.z = (tex0.tfx != TFX_DECAL) * 2;
+ valpha2.w = (tex0.tfx == TFX_MODULATE);
- if (tex0.tcc == 0 || !PSMT_ALPHAEXP(psm))
+ if (tex0.tcc && PSMT_ALPHAEXP(psm))
{
- valpha.x = 0 ;
- valpha.y = (!!tex0.tcc) * (1 + (tex0.tfx == 0)) ;
+ valpha.x = (gs.texa.ta[0] / 255.0f) * (1 + (tex0.tfx == TFX_MODULATE));
+ if (psm == PSMCT24)
+ {
+ valpha.y = 0;
+ }
+ else
+ {
+ valpha.y = ((gs.texa.ta[1] - gs.texa.ta[0]) / 255.0f) * (1 + (tex0.tfx == TFX_MODULATE));
+ }
}
else
{
- valpha.x = (gs.texa.fta[0]) * (1 + (tex0.tfx == 0)) ;
- valpha.y = (gs.texa.fta[psm != PSMCT24] - gs.texa.fta[0]) * (1 + (tex0.tfx == 0)) ;
-
+ valpha.x = 0;
+ valpha.y = (!!tex0.tcc) * (1 + (tex0.tfx == TFX_MODULATE));
}
- valpha.z = (tex0.tfx >= 3) ;
-
- valpha.w = (tex0.tcc == 0) || (tex0.tcc == 1 && tex0.tfx == 2) ;
-
- if (tex0.tcc && gs.texa.aem && psm == PSMCT24)
- vblack.w = 0;
-
- /*
- // Test, old code.
- float4 valpha3, valpha4;
- switch(tex0.tfx) {
- case 0:
- valpha3.z = 0; valpha3.w = 0;
- valpha4.x = 0; valpha4.y = 0;
- valpha4.z = 2; valpha4.w = 1;
-
- break;
- case 1:
- valpha3.z = 0; valpha3.w = 1;
- valpha4.x = 1; valpha4.y = 0;
- valpha4.z = 0; valpha4.w = 0;
-
- break;
- case 2:
- valpha3.z = 1; valpha3.w = 1.0f;
- valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f;
- valpha4.z = 2; valpha4.w = 0;
-
- break;
-
- case 3:
- valpha3.z = 1; valpha3.w = tex0.tcc ? 0.0f : 1.0f;
- valpha4.x = 0; valpha4.y = tex0.tcc ? 1.0f : 0.0f;
- valpha4.z = 2; valpha4.w = 0;
-
- break;
- }
- if( tex0.tcc ) {
-
- if( tex0.tfx == 1 ) {
- //mode.x = 10;
- valpha3.z = 0; valpha3.w = 0;
- valpha4.x = 1; valpha4.y = 1;
- valpha4.z = 0; valpha4.w = 0;
- }
-
- if( PSMT_ALPHAEXP(psm) ) {
-
- if( tex0.tfx == 0 ) {
- // make sure alpha is mult by two when the output is Cv = Ct*Cf
- valpha3.x = 2*gs.texa.fta[0];
- // if 24bit, always choose ta[0]
- valpha3.y = 2*gs.texa.fta[psm != 1];
- valpha3.y -= valpha.x;
- }
- else {
- valpha3.x = gs.texa.fta[0];
- // if 24bit, always choose ta[0]
- valpha3.y = gs.texa.fta[psm != 1];
- valpha3.y -= valpha.x;
- }
- }
- else {
- if( tex0.tfx == 0 ) {
- valpha3.x = 0;
- valpha3.y = 2;
- }
- else {
- valpha3.x = 0;
- valpha3.y = 1;
- }
- }
- }
- else {
-
- // reset alpha to color
- valpha3.x = valpha3.y = 0;
- valpha3.w = 1;
- }
-
- if ( equal_vectors(valpha, valpha3) && equal_vectors(valpha2, valpha4) ) {
- if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == 0) {
- ZZLog::Debug_Log ( "Good issue %d %d %d %d", tex0.tfx, tex0.tcc, psm, PSMT_ALPHAEXP(psm) );
- CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm) ] = 1;
- }
- }
- else if (CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] == -1) {
- ZZLog::Debug_Log ("Bad array, %d %d %d %d\n\tolf valpha %f, %f, %f, %f : valpha2 %f %f %f %f\n\tnew valpha %f, %f, %f, %f : valpha2 %f %f %f %f",
- tex0.tfx, tex0.tcc, psm, PSMT_ALPHAEXP(psm),
- valpha3.x, valpha3.y, valpha3.z, valpha3.w, valpha4.x, valpha4.y, valpha4.z, valpha4.w,
- valpha.x, valpha.y, valpha.z, valpha.w, valpha2.x, valpha2.y, valpha2.z, valpha2.w);
- CheckTexArray[tex0.tfx][tex0.tcc][psm!=1][PSMT_ALPHAEXP(psm)] = -1 ;
- }
-
- // Test;*/
+ valpha.z = (tex0.tfx == TFX_HIGHLIGHT2);
+ valpha.w = (tex0.tcc == 0) || (tex0.tcc == 1 && tex0.tfx == TFX_HIGHLIGHT);
ZZshSetParameter4fv(pfragment->fTexAlpha, valpha, "g_fTexAlpha");
ZZshSetParameter4fv(pfragment->fTexAlpha2, valpha2, "g_fTexAlpha2");
if (IsAlphaTestExpansion(tex0))
+ {
+ float4 vblack;
+ vblack.x = vblack.y = vblack.z = vblack.w = 10;
+ if (tex0.tcc && gs.texa.aem && psm == PSMCT24) vblack.w = 0;
ZZshSetParameter4fv(pfragment->fTestBlack, vblack, "g_fTestBlack");
+ }
SetTexClamping(context, pfragment);
@@ -2180,10 +1971,7 @@ void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool Ch
v.z = 1.0f / (float)fw;
v.w = 1.0f / (float)fh;
- if (pfragment->fRealTexDims)
- ZZshSetParameter4fv(pfragment->fRealTexDims, v, "g_fRealTexDims");
- else
- ZZshSetParameter4fv(cgGetNamedParameter(pfragment->prog,"g_fRealTexDims"),v, "g_fRealTexDims");
+ ZZshSetParameter4fvWithRetry(&pfragment->fRealTexDims, pfragment->prog, v, "g_fRealTexDims");
}
if (m_Blocks[tex0.psm].bpp == 0)
@@ -2273,13 +2061,14 @@ void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool Ch
vb[context].bVarsTexSync = false;
}
+#if 0
#define SET_ALPHA_COLOR_FACTOR(sign) \
{ \
switch(a.c) \
{ \
case 0: \
vAlphaBlendColor.y = (sign) ? 2.0f*255.0f/256.0f : -2.0f*255.0f/256.0f; \
- s_srcalpha = GL_ONE; \
+ s_srcalpha = GL_ONE; \
s_alphaeq = (sign) ? GL_FUNC_ADD : GL_FUNC_REVERSE_SUBTRACT; \
break; \
\
@@ -2298,7 +2087,7 @@ void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool Ch
/* default: 16bit surface, so returned alpha is ok */ \
} \
break; \
- \
+ \
case 2: \
bNeedBlendFactorInAlpha = true; /* should disable alpha channel writing */ \
vAlphaBlendColor.y = 0; \
@@ -2306,7 +2095,7 @@ void SetTexVariablesInt(int context, int bilinear, const tex0Info& tex0, bool Ch
usec = 0; /* change so that alpha comes from source*/ \
break; \
} \
-} \
+}
//if( a.fix <= 0x80 ) { \
// dwTemp = (a.fix*2)>255?255:(a.fix*2); \
@@ -2329,6 +2118,54 @@ inline void NeedFactor(int w)
vAlphaBlendColor.w = (float)w;
}
}
+#endif
+
+template
+__forceinline int Set_Alpha_Color_Factor(const alphaInfo& a)
+{
+ int usec;
+ switch(a.c)
+ {
+ case 0:
+ usec = 0;
+ /* Note: there are already default value when sign is 1. So only change them
+ * when sign is 0
+ */
+ if (!SIGN) {
+ vAlphaBlendColor.y = -2.0f*255.0f/256.0f;
+ s_alphaeq = GL_FUNC_REVERSE_SUBTRACT;
+ }
+ break;
+ case 1:
+ usec = 1;
+ /* if in 24 bit mode, dest alpha should be one */
+ if(PSMT_BITMODE(vb[icurctx].prndr->psm) == 1) {
+ /* dest alpha should be one */
+ ZZLog::Debug_Log("Alpha on a 24 bits framebuffer, good place to check the value of blend");
+ // FIMXE: the array constains GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA
+ // It will love a test with GL_ONE and GL_ZERO
+ usec = 4;
+
+ // need a factor correction
+ if (NEED_FACTOR) {
+ bNeedBlendFactorInAlpha = (SIGN) ? true : false;
+ vAlphaBlendColor.y = 0;
+ vAlphaBlendColor.w = (SIGN) ? 1.0 : -1.0;
+ }
+ }
+ break;
+ case 2:
+ usec = 0; /* change so that alpha comes from source*/
+ bNeedBlendFactorInAlpha = true; /* should disable alpha channel writing */
+ vAlphaBlendColor.y = 0;
+ vAlphaBlendColor.w = (SIGN) ? (float)a.fix * (2.0f/255.0f) : (float)a.fix * (-2.0f/255.0f);
+ break;
+
+ default:
+ assert(0);
+ }
+ return usec;
+}
//static int CheckArray[48][2] = {{0,}};
@@ -2338,21 +2175,25 @@ void SetAlphaVariables(const alphaInfo& a)
bool alphaenable = true;
// TODO: negative color when not clamping turns to positive???
- g_vars._bAlphaState = 0; // set all to zero
+ // g_vars._bAlphaState = 0; // set all to zero
bNeedBlendFactorInAlpha = false;
- b2XAlphaTest = 1;
+ // b2XAlphaTest = 1;
//u32 dwTemp = 0xffffffff;
- bDestAlphaColor = 0;
+ // bDestAlphaColor = 0;
// default
s_srcalpha = GL_ONE;
s_dstalpha = GL_ZERO;
s_alphaeq = GL_FUNC_ADD;
- s_rgbeq = 1;
+ s_rgbeq = GL_FUNC_ADD;
// s_alphaInfo = a;
vAlphaBlendColor = float4(1, 2 * 255.0f / 256.0f, 0, 0);
- u32 usec = a.c;
+ // u32 usec = a.c;
+ u32 usec;
+ const bool POS_A = true;
+ const bool NEG_A = false;
+ const bool NEED_FACTOR = true;
/*
@@ -2382,7 +2223,7 @@ void SetAlphaVariables(const alphaInfo& a)
* 1 102: 0+-a+ 0 | a+ 0+ 0 = a (R-) a | 112: 0+ 0+ 0 | a+-a+ 0 = 0 | 122: 0+ 0+ 0 | a+ 0+ 0 = 0 (+) a
* 2 202: 0+-a+ 0 | 0+ 0+ 0 = a (R-) 0 | 212: 0+ 0+ 0 | 0+-a+ 0 = 0 (-) a | 222: 0+ 0+ 0 | 0+ 0+ 0 = 0
*
- * Formulae is: (a-b) * (c /32) + d
+ * Formulae is: (a-b) * (c /128) + d
* 0 1 2
* a Cs Cd 0
* b Cs Cd 0
@@ -2396,23 +2237,26 @@ void SetAlphaVariables(const alphaInfo& a)
*/
int code = (a.a * 16) + (a.b * 4) + a.d ;
-#define one_minus_alpha (bDestAlphaColor == 2) ? GL_ONE_MINUS_SRC_ALPHA : blendinvalpha[usec]
-#define alpha (bDestAlphaColor == 2) ? GL_SRC_ALPHA : blendalpha[usec]
-#define one (bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec]
-#define zero (bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec]
+// #define one_minus_alpha (bDestAlphaColor == 2) ? GL_ONE_MINUS_SRC_ALPHA : blendinvalpha[usec]
+// #define alpha (bDestAlphaColor == 2) ? GL_SRC_ALPHA : blendalpha[usec]
+// #define one (bDestAlphaColor == 2) ? GL_ONE : blendalpha[usec]
+// #define zero (bDestAlphaColor == 2) ? GL_ZERO : blendinvalpha[usec]
+
+#define one_minus_alpha blendinvalpha[usec]
+#define alpha blendalpha[usec]
switch (code)
{
case 0: // 000 // Cs -- nothing changed
- case 20: // 110 = 16+4=20 // Cs
- case 40: // 220 = 32+8=40 // Cs
+ case 20: // 110 = 16+4=20 // Cs
+ case 40: // 220 = 32+8=40 // Cs
{
alphaenable = false;
break;
}
- case 2: //002 // 0 -- should be zero
+ case 2: //002 // 0 -- should be zero
case 22: //112 // 0
case 42: //222 = 32+8+2 =42 // 0
{
@@ -2434,34 +2278,37 @@ void SetAlphaVariables(const alphaInfo& a)
case 4: // 010 // (Cs-Cd)*A+Cs = Cs * (A + 1) - Cd * A
{
- bAlphaClamping = 3;
- SET_ALPHA_COLOR_FACTOR(0); // a = -A
+ // bAlphaClamping = 3;
+ // SET_ALPHA_COLOR_FACTOR(0); // a = -A
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD; // Cs*(1-a)+Cd*a
s_srcrgb = one_minus_alpha ;
s_dstrgb = alpha;
- NeedFactor(-1);
+ // NeedFactor(-1);
break;
}
case 5: // 011 // (Cs-Cd)*A+Cs = Cs * A + Cd * (1-A)
{
- bAlphaClamping = 3; // all testing
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 3; // all testing
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = alpha;
s_dstrgb = one_minus_alpha;
- NeedFactor(1);
+ // NeedFactor(1);
break;
}
- case 6: //012 // (Cs-Cd)*FIX
+ case 6: //012 // (Cs-Cd)*A = Cs*A - Cd*A
{
- bAlphaClamping = 3;
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 3;
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_SUBTRACT;
s_srcrgb = alpha;
@@ -2472,8 +2319,9 @@ void SetAlphaVariables(const alphaInfo& a)
case 8: //020 // Cs*A+Cs = Cs * (1+A)
{
- bAlphaClamping = 2; // max testing
- SET_ALPHA_COLOR_FACTOR(0); // Zeyflitz change this! a = -A
+ // bAlphaClamping = 2; // max testing
+ // SET_ALPHA_COLOR_FACTOR(0); // Zeydlitz change this! a = -A
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = one_minus_alpha; // Cs*(1-a).
@@ -2485,19 +2333,21 @@ void SetAlphaVariables(const alphaInfo& a)
case 9: //021 // Cs*A+Cd
{
- bAlphaClamping = 2; // max testing
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 2; // max testing
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
- s_srcrgb = alpha; // ZZ change it to.
+ s_srcrgb = alpha; // ZZ change it too.
s_dstrgb = GL_ONE;
break;
}
case 10: //022 // Cs*A
{
- bAlphaClamping = 2; // max testing
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 2; // max testing
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = alpha;
@@ -2505,36 +2355,39 @@ void SetAlphaVariables(const alphaInfo& a)
break;
}
- case 16: //100
+ case 16: //100 // (Cd-Cs)*A + Cs = Cd*A + Cs*(1-A)
{
- bAlphaClamping = 3;
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 3;
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = one_minus_alpha;
s_dstrgb = alpha;
- NeedFactor(1);
+ // NeedFactor(1);
break;
}
- case 17: //101
+ case 17: //101 // (Cd-Cs)*A + Cd = Cd*(A+1) - A*Cs
{
- bAlphaClamping = 3; // all testing
- SET_ALPHA_COLOR_FACTOR(0);
+ // bAlphaClamping = 3; // all testing
+ // SET_ALPHA_COLOR_FACTOR(0);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = alpha;
s_dstrgb = one_minus_alpha;
- NeedFactor(-1);
+ // NeedFactor(-1);
break;
}
- case 18: //102
+ case 18: //102 // (Cd-Cs)*A = Cd*A - Cs*A
{
- bAlphaClamping = 3;
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 3;
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
s_srcrgb = alpha;
@@ -2543,10 +2396,11 @@ void SetAlphaVariables(const alphaInfo& a)
break;
}
- case 24: //120 = 16+8
+ case 24: //120 = 16+8 // Cd*A + Cs
{
- bAlphaClamping = 2; // max testing
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 2; // max testing
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = GL_ONE;
@@ -2556,8 +2410,9 @@ void SetAlphaVariables(const alphaInfo& a)
case 25: //121 // Cd*(1+A)
{
- bAlphaClamping = 2; // max testing
- SET_ALPHA_COLOR_FACTOR(0);
+ // bAlphaClamping = 2; // max testing
+ // SET_ALPHA_COLOR_FACTOR(0);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = GL_ZERO;
@@ -2567,10 +2422,11 @@ void SetAlphaVariables(const alphaInfo& a)
break;
}
- case 26: //122
+ case 26: //122 // Cd*A
{
- bAlphaClamping = 2;
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 2;
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = GL_ZERO;
@@ -2578,10 +2434,11 @@ void SetAlphaVariables(const alphaInfo& a)
break;
}
- case 32: // 200 = 32
+ case 32: // 200 = 32 // -Cs*A + Cs = Cs*(1-A)
{
- bAlphaClamping = 1; // min testing
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 1; // min testing
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = one_minus_alpha;
@@ -2591,8 +2448,9 @@ void SetAlphaVariables(const alphaInfo& a)
case 33: //201 // -Cs*A + Cd
{
- bAlphaClamping = 1; // min testing
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 1; // min testing
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_REVERSE_SUBTRACT;
s_srcrgb = alpha;
@@ -2600,10 +2458,10 @@ void SetAlphaVariables(const alphaInfo& a)
break;
}
- case 34: //202
- case 38: //212
+ case 34: //202 // -Cs*A
+ case 38: //212 // -Cd*A
{
- bAlphaClamping = 1; // min testing -- negative values
+ // bAlphaClamping = 1; // min testing -- negative values
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = GL_ZERO;
@@ -2611,10 +2469,11 @@ void SetAlphaVariables(const alphaInfo& a)
break;
}
- case 36: //210
+ case 36: //210 // -Cd*A + Cs
{
- bAlphaClamping = 1; // min testing
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 1; // min testing
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_SUBTRACT;
s_srcrgb = GL_ONE;
@@ -2622,10 +2481,11 @@ void SetAlphaVariables(const alphaInfo& a)
break;
}
- case 37: //211
+ case 37: //211 // -Cd*A+Cd = Cd * (1-A)
{
- bAlphaClamping = 1; // min testing
- SET_ALPHA_COLOR_FACTOR(1);
+ // bAlphaClamping = 1; // min testing
+ // SET_ALPHA_COLOR_FACTOR(1);
+ usec = Set_Alpha_Color_Factor(a);
s_rgbeq = GL_FUNC_ADD;
s_srcrgb = GL_ZERO;
diff --git a/plugins/zzogl-pg/opengl/ZZoglFlush.h b/plugins/zzogl-pg/opengl/ZZoglFlush.h
new file mode 100644
index 0000000000..be635f5fdc
--- /dev/null
+++ b/plugins/zzogl-pg/opengl/ZZoglFlush.h
@@ -0,0 +1,123 @@
+/* ZZ Open GL graphics plugin
+ * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
+ * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef ZZOGLFLUSH_H_INCLUDED
+#define ZZOGLFLUSH_H_INCLUDED
+
+#ifndef ZEROGS_DEVBUILD
+
+#define INC_GENVARS()
+#define INC_TEXVARS()
+#define INC_ALPHAVARS()
+#define INC_RESOLVE()
+
+#define g_bUpdateEffect 0
+#define g_bSaveTex 0
+#define g_bSaveResolved 0
+
+#else // defined(ZEROGS_DEVBUILD)
+
+#define INC_GENVARS() ++g_nGenVars
+#define INC_TEXVARS() ++g_nTexVars
+#define INC_ALPHAVARS() ++g_nAlphaVars
+#define INC_RESOLVE() ++g_nResolve
+
+extern bool g_bUpdateEffect;
+extern bool g_bSaveTex; // saves the current texture
+extern bool g_bSaveResolved;
+#endif // !defined(ZEROGS_DEVBUILD)
+
+enum StencilBits
+{
+ STENCIL_ALPHABIT = 1, // if set, dest alpha >= 0x80
+ STENCIL_PIXELWRITE = 2, // if set, pixel just written (reset after every Flush)
+ STENCIL_FBA = 4, // if set, just written pixel's alpha >= 0 (reset after every Flush)
+ STENCIL_SPECIAL = 8 // if set, indicates that pixel passed its alpha test (reset after every Flush)
+ //STENCIL_PBE = 16
+};
+#define STENCIL_CLEAR (2|4|8|16)
+
+enum ColorMask
+{
+ COLORMASK_RED = 1,
+ COLORMASK_GREEN = 2,
+ COLORMASK_BLUE = 4,
+ COLORMASK_ALPHA = 8
+
+};
+#define GL_COLORMASK(mask) glColorMask(!!((mask)&COLORMASK_RED), !!((mask)&COLORMASK_GREEN), !!((mask)&COLORMASK_BLUE), !!((mask)&COLORMASK_ALPHA))
+
+// extern int g_nDepthBias;
+extern float g_fBlockMult; // used for old cards, that do not support Alpha-32float textures. We store block data in u16 and use it.
+extern u32 g_nCurVBOIndex;
+extern u8* g_pbyGSClut;
+extern int ppf;
+
+extern bool s_bTexFlush;
+
+extern vector s_vecTempTextures; // temporary textures, released at the end of every frame
+extern GLuint g_vboBuffers[VB_NUMBUFFERS]; // VBOs for all drawing commands
+extern CRangeManager s_RangeMngr; // manages overwritten memory // zz
+
+#if 0
+typedef union
+{
+ struct
+ {
+ u8 _bNeedAlphaColor; // set if vAlphaBlendColor needs to be set
+ u8 _b2XAlphaTest; // Only valid when bNeedAlphaColor is set. if 1st bit set set, double all alpha testing values
+ // otherwise alpha testing needs to be done separately.
+ u8 _bDestAlphaColor; // set to 1 if blending with dest color (process only one tri at a time). If 2, dest alpha is always 1.
+ u8 _bAlphaClamping; // if first bit is set, do min; if second bit, do max
+ };
+
+ u32 _bAlphaState;
+} g_flag_vars;
+
+extern g_flag_vars g_vars;
+#endif
+
+//#define bNeedAlphaColor g_vars._bNeedAlphaColor
+//#define b2XAlphaTest g_vars._b2XAlphaTest
+//#define bDestAlphaColor g_vars._bDestAlphaColor
+//#define bAlphaClamping g_vars._bAlphaClamping
+
+void FlushTransferRanges(const tex0Info* ptex); //zz
+
+// use to update the state
+void SetTexVariables(int context, FRAGMENTSHADER* pfragment); // zz
+void SetTexInt(int context, FRAGMENTSHADER* pfragment, int settexint); // zz
+void SetAlphaVariables(const alphaInfo& ainfo); // zzz
+//void ResetAlphaVariables();
+
+inline void SetAlphaTestInt(pixTest curtest);
+
+inline void RenderAlphaTest(const VB& curvb, ZZshParameter sOneColor);
+inline void RenderStencil(const VB& curvb, u32 dwUsingSpecialTesting);
+inline void ProcessStencil(const VB& curvb);
+inline void RenderFBA(const VB& curvb, ZZshParameter sOneColor);
+inline void ProcessFBA(const VB& curvb, ZZshParameter sOneColor); // zz
+
+void SetContextTarget(int context);
+
+void SetWriteDepth();
+bool IsWriteDepth();
+void SetDestAlphaTest();
+
+#endif // ZZOGLFLUSH_H_INCLUDED
diff --git a/plugins/zzogl-pg/opengl/ZZoglMath.h b/plugins/zzogl-pg/opengl/ZZoglMath.h
index 2e31aebb90..048ad9735e 100644
--- a/plugins/zzogl-pg/opengl/ZZoglMath.h
+++ b/plugins/zzogl-pg/opengl/ZZoglMath.h
@@ -212,7 +212,7 @@ typedef Vector4 float4;
// Reimplement, swiping a bunch of code from GSdx and adapting it. (specifically GSVector.h)
// This doesn't include more then half of the functions in there, as well as some of the structs...
-#include
+#include
#include "Pcsx2Types.h"
diff --git a/plugins/zzogl-pg/opengl/ZZoglMem.cpp b/plugins/zzogl-pg/opengl/ZZoglMem.cpp
new file mode 100644
index 0000000000..96a5183c24
--- /dev/null
+++ b/plugins/zzogl-pg/opengl/ZZoglMem.cpp
@@ -0,0 +1,564 @@
+/* ZeroGS KOSMOS
+ * Copyright (C) 2005-2006 zerofrog@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "GS.h"
+#include "Util.h"
+#include "ZZoglMem.h"
+#include "targets.h"
+#include "x86.h"
+
+#include "Mem_Swizzle.h"
+
+#ifndef ZZNORMAL_MEMORY
+
+bool allowed_psm[256] = {false, }; // Sometimes we got strange unknown psm
+PSM_value PSM_value_Table[64] = {PSMT_BAD_PSM, }; // for int -> PSM_value
+
+// return array of pointer of array string,
+// We SHOULD do memory allocation for u32** -- otherwize we have a lot of trouble!
+// if bw and bh are set correctly, as dimensions of table, than array have pointers
+// to table rows, so array[i][j] = table[i][j];
+inline u32** InitTable(int bh, int bw, u32* table) {
+ u32** array = (u32**)malloc(bh * sizeof(u32*));
+ for (int i = 0; i < bh; i++) {
+ array[i] = &table[i * bw];
+ }
+ return array;
+}
+
+// initialize dynamic arrays (u32**) for each regular psm.
+inline void SetTable(int psm) {
+ switch (psm) {
+ case PSMCT32:
+ g_pageTable[psm] = InitTable( 32, 64, &g_pageTable32[0][0]);
+ g_blockTable[psm] = InitTable( 4, 8, &g_blockTable32[0][0]);
+ g_columnTable[psm] = InitTable( 8, 8, &g_columnTable32[0][0]);
+ break;
+
+ case PSMCT24:
+ g_pageTable[psm] = g_pageTable[PSMCT32];;
+ g_blockTable[psm] = InitTable( 4, 8, &g_blockTable32[0][0]);
+ g_columnTable[psm] = InitTable( 8, 8, &g_columnTable32[0][0]);
+ break;
+
+ case PSMCT16:
+ g_pageTable[psm] = InitTable( 64, 64, &g_pageTable16[0][0]);
+ g_blockTable[psm] = InitTable( 8, 4, &g_blockTable16[0][0]);
+ g_columnTable[psm] = InitTable( 8, 16, &g_columnTable16[0][0]);
+ break;
+
+ case PSMCT16S:
+ g_pageTable[psm] = InitTable( 64, 64, &g_pageTable16S[0][0]);
+ g_blockTable[psm] = InitTable( 8, 4, &g_blockTable16S[0][0]);
+ g_columnTable[psm] = InitTable( 8, 16, &g_columnTable16[0][0]);
+ break;
+
+ case PSMT8:
+ g_pageTable[psm] = InitTable( 64, 128, &g_pageTable8[0][0]);
+ g_blockTable[psm] = InitTable( 4, 8, &g_blockTable8[0][0]);
+ g_columnTable[psm] = InitTable( 16, 16, &g_columnTable8[0][0]);
+ break;
+
+ case PSMT8H:
+ g_pageTable[psm] = g_pageTable[PSMCT32];
+ g_blockTable[psm] = InitTable( 4, 8, &g_blockTable8[0][0]);
+ g_columnTable[psm] = InitTable( 16, 16, &g_columnTable8[0][0]);
+ break;
+
+ case PSMT4:
+ g_pageTable[psm] = InitTable(128, 128, &g_pageTable4[0][0]);
+ g_blockTable[psm] = InitTable( 8, 4, &g_blockTable4[0][0]);
+ g_columnTable[psm] = InitTable( 16, 32, &g_columnTable4[0][0]);
+ break;
+
+ case PSMT4HL:
+ case PSMT4HH:
+ g_pageTable[psm] = g_pageTable[PSMCT32];
+ g_blockTable[psm] = InitTable( 8, 4, &g_blockTable4[0][0]);
+ g_columnTable[psm] = InitTable( 16, 32, &g_columnTable4[0][0]);
+ break;
+
+ case PSMT32Z:
+ g_pageTable[psm] = InitTable( 32, 64, &g_pageTable32Z[0][0]);
+ g_blockTable[psm] = InitTable( 4, 8, &g_blockTable32Z[0][0]);
+ g_columnTable[psm] = InitTable( 8, 8, &g_columnTable32[0][0]);
+ break;
+
+ case PSMT24Z:
+ g_pageTable[psm] = g_pageTable[PSMT32Z];
+ g_blockTable[psm] = InitTable( 4, 8, &g_blockTable32Z[0][0]);
+ g_columnTable[psm] = InitTable( 8, 8, &g_columnTable32[0][0]);
+ break;
+
+ case PSMT16Z:
+ g_pageTable[psm] = InitTable( 64, 64, &g_pageTable16Z[0][0]);
+ g_blockTable[psm] = InitTable( 8, 4, &g_blockTable16Z[0][0]);
+ g_columnTable[psm] = InitTable( 8, 16, &g_columnTable16[0][0]);
+ break;
+
+ case PSMT16SZ:
+ g_pageTable[psm] = InitTable( 64, 64, &g_pageTable16SZ[0][0]);
+ g_blockTable[psm] = InitTable( 8, 4, &g_blockTable16SZ[0][0]);
+ g_columnTable[psm] = InitTable( 8, 16, &g_columnTable16[0][0]);
+ break;
+ }
+}
+
+// After this, the function arrays with u32** have memory set and filled.
+void FillBlockTables() {
+ for (int i = 0; i < MAX_PSM; i++)
+ SetTable(i);
+}
+
+// Deallocate memory for u32** arrays.
+void DestroyBlockTables() {
+ for (int i = 0; i < MAX_PSM; i++) {
+ if (g_pageTable[i] != NULL && (i != PSMT8H && i != PSMT4HL && i != PSMT4HH && i != PSMCT24 && i != PSMT24Z))
+ free(g_pageTable[i]);
+
+ if (g_blockTable[i] != NULL)
+ free(g_blockTable[i]);
+
+ if (g_columnTable[i] != NULL)
+ free(g_columnTable[i]);
+ }
+}
+
+void FillNewPageTable() {
+ int k = 0;
+ for (int psm = 0; psm < MAX_PSM; psm ++)
+ if (allowed_psm[psm]) {
+ for (u32 i = 0; i < 127; i++)
+ for(u32 j = 0; j < 127; j++) {
+ u32 address;
+ u32 shift;
+
+ address = g_pageTable[psm][i & ZZ_DT[psm][3]][j & ZZ_DT[psm][4]];
+ shift = (((address << ZZ_DT[psm][5]) & 0x7 ) << 3)+ ZZ_DT[psm][7]; // last part is for 8H, 4HL and 4HH -- they have data from 24 and 28 byte
+ g_pageTable2[k][i][j] = (address >> ZZ_DT[psm][0]) + (shift << 16); // now lower 16 byte of page table is 32-bit aligned address, and upper --
+ // shift.
+ }
+ g_pageTableNew[psm] = InitTable( 128, 128, &g_pageTable2[k][0][0]);
+ k++;;
+ }
+}
+
+BLOCK m_Blocks[MAX_PSM]; // Do so that blocks are indexable.
+
+// At the begining and the end of each string we should made unaligned writes, with nSize checks. We should be sure that all
+// these pixels are inside one widthlimit space.
+template
+inline bool DoOneTransmitStep(void* pstart, int& nSize, int endj, const void* pbuf, int& k, int& i, int& j, int widthlimit) {
+ for (; j < endj && nSize > 0; j++, k++, nSize -= 1) {
+ writePixelMem((u32*)pstart, j%2048, i%2048, (u32*)(pbuf), k, gs.dstbuf.bw);
+ }
+
+ return (nSize == 0);
+}
+
+// FFX has PSMT8 transmit (starting intro -- sword and hairs).
+// Persona 4 texts at start are PSMCT32 (and there is also PSMCT16 transmit somwhere after that).
+// Tekken V has PSMCT24 and PSMT4 transfers
+
+// This function transfers "Y" block pixels. I use little another code than Zerofrog. My code often uses widthmult != 1 addition (Zerofrog's code
+// have an strict condition for fast path: width of transferred data should be widthlimit multiplied by j; EndY also should be multiplied. But
+// the usual data block of 255 pixels becomes transfered by 1.
+// I should check, maybe Unaligned_Start and Unaligned_End often == 0, and I could try a fastpath -- with this block off.
+template
+inline bool TRANSMIT_HOSTLOCAL_Y(u32* pbuf, int& nSize, u8* pstart, int endY, int& i, int& j, int& k) {
+// if (psm != PSMT8 && psm != 0 && psm != PSMT4 && psm != PSMCT24)
+// ERROR_LOG("This is usable function TRANSMIT_HOSTLOCAL_Y at ZZoglMem.cpp %d %d %d %d %d\n", psm, widthlimit, i, j, nSize);
+
+ int q = (gs.trxpos.dx - j) % widthlimit;
+ if (DoOneTransmitStep(pstart, nSize, q, pbuf, k, i, j, widthlimit)) return true; // After this j and dx are compatible by modyle of widthlimit
+
+ int Unaligned_Start = (gs.trxpos.dx % widthlimit == 0) ? 0 : widthlimit - gs.trxpos.dx % widthlimit; // gs.trpos.dx + Unaligned_Start is multiple of widthlimit
+ for (; i < endY; ++i) {
+ if (DoOneTransmitStep(pstart, nSize, j + Unaligned_Start, pbuf, k, i, j, widthlimit)) return true; // This operation made j % widthlimit == 0.
+ //assert (j % widthlimit != 0);
+
+ for (; j < gs.imageEnd.x - widthlimit + 1 && nSize >= widthlimit; j += widthlimit, nSize -= widthlimit) {
+ writePixelsFromMemory(pstart, pbuf, k, j % 2048, i % 2048, gs.dstbuf.bw);
+ }
+
+ assert ( gs.imageEnd.x - j < widthlimit || nSize < widthlimit);
+ if (DoOneTransmitStep(pstart, nSize, gs.imageEnd.x, pbuf, k, i, j, widthlimit)) return true; // There are 2 reasons for finish of previous for: 1) nSize < widthlimit
+ // 2) j > gs.imageEnd.x - widthlimit + 1. We would try to write pixels up do
+ // EndX, it's no more widthlimit pixels
+ j = gs.trxpos.dx;
+ }
+
+ return false;
+}
+
+// PSMT4 -- Tekken V
+template
+inline void TRANSMIT_HOSTLOCAL_X(u32* pbuf, int& nSize, u8* pstart, int& i, int& j, int& k, int blockheight, int startX, int pitch, int fracX) {
+ if (psm != PSMT8 && psm != PSMT4)
+ ZZLog::Error_Log("This is usable function TRANSMIT_HOSTLOCAL_X at ZZoglMem.cpp %d %d %d %d %d\n", psm, widthlimit, i, j, nSize);
+
+ for(int tempi = 0; tempi < blockheight; ++tempi) {
+ for(j = startX; j < gs.imageEnd.x; j++, k++) {
+ writePixelMem((u32*)pstart, j%2048, (i + tempi)%2048, (u32*)(pbuf), k, gs.dstbuf.bw);
+ }
+ k += ( pitch - fracX );
+ }
+}
+
+template
+inline int TRANSMIT_PITCH(int pitch) {
+ return (PSM_BITS_PER_PIXEL() * pitch) >> 3;
+}
+
+// ------------------------
+// | Y |
+// ------------------------
+// | block | |
+// | aligned area | X |
+// | | |
+// ------------------------
+// | Y |
+// ------------------------
+
+
+template
+int FinishTransfer(int i, int j, int nSize, int nLeftOver)
+{
+ if( i >= gs.imageEnd.y )
+ {
+ assert( gs.transferring == false || i == gs.imageEnd.y );
+ gs.transferring = false;
+ }
+ else {
+ /* update new params */
+ gs.image.y = i;
+ gs.image.x = j;
+ }
+
+ return (nSize * TRANSMIT_PITCH(2) + nLeftOver)/2;
+}
+
+template
+int TransferHostLocal(const void* pbyMem, u32 nQWordSize)
+{
+ assert( gs.imageTransfer == XFER_HOST_TO_LOCAL );
+ u8* pstart = g_pbyGSMemory + gs.dstbuf.bp*256;
+
+ int i = gs.image.y, j = gs.image.x;
+
+ const u8* pbuf = (const u8*)pbyMem;
+ int nLeftOver = (nQWordSize*4*2)%(TRANSMIT_PITCH(2));
+ int nSize = nQWordSize*4*2/TRANSMIT_PITCH(2);
+ nSize = min(nSize, gs.imageNew.w * gs.imageNew.h);
+
+ int pitch, area, fracX;
+ int endY = ROUND_UPPOW2(i, blockheight);
+ Point alignedPt;
+
+ alignedPt.x = ROUND_DOWNPOW2(gs.imageEnd.x, blockwidth);
+ alignedPt.y = ROUND_DOWNPOW2(gs.imageEnd.y, blockheight);
+
+ bool bAligned;
+ bool bCanAlign = MOD_POW2(gs.trxpos.dx, blockwidth) == 0 && (j == gs.trxpos.dx) && (alignedPt.y > endY) && alignedPt.x > gs.trxpos.dx;
+
+ if( (gs.imageEnd.x - gs.trxpos.dx) % widthlimit ) {
+ /* hack */
+ int testwidth = (int)nSize - (gs.imageEnd.y - i) * (gs.imageEnd.x - gs.trxpos.dx) + (j - gs.trxpos.dx);
+ if((testwidth <= widthlimit) && (testwidth >= -widthlimit)) {
+ /* don't transfer */
+ /*ZZLog::Debug_Log("bad texture %s: %d %d %d\n", #psm, gs.trxpos.dx, gs.imageEnd.x, nQWordSize);*/
+ gs.transferring = false;
+ }
+ bCanAlign = false;
+ }
+
+ /* first align on block boundary */
+ if( MOD_POW2(i, blockheight) || !bCanAlign ) {
+
+ if( !bCanAlign )
+ endY = gs.imageEnd.y; /* transfer the whole image */
+ else
+ assert( endY < gs.imageEnd.y); /* part of alignment condition */
+
+ int limit = widthlimit;
+ if (((gs.imageEnd.x - gs.trxpos.dx) % widthlimit) || ((gs.imageEnd.x - j) % widthlimit))
+ /* transmit with a width of 1 */
+ limit = 1 + (gs.dstbuf.psm == PSMT4);
+ /*TRANSMIT_HOSTLOCAL_Y##TransSfx(psm, T, limit, endY)*/
+ int k = 0;
+
+ if (TRANSMIT_HOSTLOCAL_Y((u32*)pbuf, nSize, pstart, endY, i, j, k))
+ return FinishTransfer(i, j, nSize, nLeftOver);
+
+ pbuf += TRANSMIT_PITCH(k);
+
+ if (nSize == 0 || i == gs.imageEnd.y) return FinishTransfer(i, j, nSize, nLeftOver);
+ }
+
+ assert( MOD_POW2(i, blockheight) == 0 && j == gs.trxpos.dx);
+
+ /* can align! */
+ pitch = gs.imageEnd.x - gs.trxpos.dx;
+ area = pitch * blockheight;
+ fracX = gs.imageEnd.x - alignedPt.x;
+
+ /* 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) && ((TRANSMIT_PITCH(pitch)&0xf) == 0);
+
+ /* transfer aligning to blocks */
+ for(; i < alignedPt.y && nSize >= area; i += blockheight, nSize -= area) {
+
+ for(int tempj = gs.trxpos.dx; tempj < alignedPt.x; tempj += blockwidth, pbuf += TRANSMIT_PITCH(blockwidth)) {
+ SwizzleBlock((u32*)(pstart + getPixelAddress(tempj, i, gs.dstbuf.bw)*blockbits/8),
+ (u32*)pbuf, TRANSMIT_PITCH(pitch));
+ }
+
+ /* transfer the rest */
+ if( alignedPt.x < gs.imageEnd.x ) {
+ int k = 0;
+ TRANSMIT_HOSTLOCAL_X((u32*)pbuf, nSize, pstart, i, j, k, blockheight, alignedPt.x, pitch, fracX);
+ pbuf += TRANSMIT_PITCH(k - alignedPt.x + gs.trxpos.dx);
+ }
+ else pbuf += (blockheight-1)*TRANSMIT_PITCH(pitch);
+ j = gs.trxpos.dx;
+ }
+
+ if( TRANSMIT_PITCH(nSize)/4 > 0 ) {
+ int k = 0;
+ TRANSMIT_HOSTLOCAL_Y((u32*)pbuf, nSize, pstart, gs.imageEnd.y, i, j, k);
+ pbuf += TRANSMIT_PITCH(k);
+ /* sometimes wrong sizes are sent (tekken tag) */
+ assert( gs.transferring == false || TRANSMIT_PITCH(nSize)/4 <= 2 );
+ }
+
+ return FinishTransfer(i, j, nSize, nLeftOver);
+}
+
+inline int TransferHostLocal32(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal32Z(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal24(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal24Z(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal16(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal16S(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal16Z(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal16SZ(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal8(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal4(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal8H(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal4HL(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+inline int TransferHostLocal4HH(const void* pbyMem, u32 nQWordSize)
+{
+ return TransferHostLocal( pbyMem, nQWordSize);
+}
+
+void TransferLocalHost32(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost24(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost16(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost16S(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost8(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost4(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost8H(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost4HL(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost4HH(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost32Z(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost24Z(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost16Z(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+void TransferLocalHost16SZ(void* pbyMem, u32 nQWordSize) { FUNCLOG }
+
+inline void FILL_BLOCK(BLOCK& b, int floatfmt, vector& vBlockData, vector& vBilinearData, int ox, int oy, int psmX) {
+ int bw = ZZ_DT[psmX][4] + 1;
+ int bh = ZZ_DT[psmX][3] + 1;
+ int mult = 1 << ZZ_DT[psmX][0];
+
+ b.vTexDims = float4 (BLOCK_TEXWIDTH/(float)(bw), BLOCK_TEXHEIGHT/(float)(bh), 0, 0);
+ b.vTexBlock = float4( (float)bw/BLOCK_TEXWIDTH, (float)bh/BLOCK_TEXHEIGHT, ((float)ox+0.2f)/BLOCK_TEXWIDTH, ((float)oy+0.05f)/BLOCK_TEXHEIGHT);
+ b.width = bw;
+ b.height = bh;
+ b.colwidth = bh / 4;
+ b.colheight = bw / 8;
+ b.bpp = 32/mult;
+
+ b.pageTable = g_pageTable[psmX];
+ b.blockTable = g_blockTable[psmX];
+ b.columnTable = g_columnTable[psmX];
+
+ // This is never true.
+ //assert( sizeof(g_pageTable[psmX]) == bw*bh*sizeof(g_pageTable[psmX][0][0]) );
+ float* psrcf = (float*)&vBlockData[0] + ox + oy * BLOCK_TEXWIDTH;
+ u16* psrcw = (u16*)&vBlockData[0] + ox + oy * BLOCK_TEXWIDTH;
+ for(int i = 0; i < bh; ++i) {
+ for(int j = 0; j < bw; ++j) {
+ /* fill the table */
+ u32 u = g_blockTable[psmX][(i / b.colheight)][(j / b.colwidth)] * 64 * mult + g_columnTable[psmX][i%b.colheight][j%b.colwidth];
+ b.pageTable[i][j] = u;
+ if( floatfmt ) {
+ psrcf[i*BLOCK_TEXWIDTH+j] = (float)(u) / (float)(GPU_TEXWIDTH*mult);
+ }
+ else {
+ psrcw[i*BLOCK_TEXWIDTH+j] = u;
+ }
+ }
+ }
+
+ if( floatfmt ) {
+ float4* psrcv = (float4*)&vBilinearData[0] + ox + oy * BLOCK_TEXWIDTH;
+ for(int i = 0; i < bh; ++i) {
+ for(int j = 0; j < bw; ++j) {
+ float4* pv = &psrcv[i*BLOCK_TEXWIDTH+j];
+ pv->x = psrcf[i*BLOCK_TEXWIDTH+j];
+ pv->y = psrcf[i*BLOCK_TEXWIDTH+((j+1)%bw)];
+ pv->z = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+j];
+ pv->w = psrcf[((i+1)%bh)*BLOCK_TEXWIDTH+((j+1)%bw)];
+ }
+ }
+ }
+}
+
+void BLOCK::FillBlocks(vector& vBlockData, vector& vBilinearData, int floatfmt)
+{
+ FUNCLOG
+ vBlockData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * (floatfmt ? 4 : 2));
+
+ if (floatfmt)
+ vBilinearData.resize(BLOCK_TEXWIDTH * BLOCK_TEXHEIGHT * sizeof(float4));
+
+ BLOCK b;
+
+ memset(m_Blocks, 0, sizeof(m_Blocks));
+
+ // 32
+ FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 0, PSMCT32);
+ b.TransferHostLocal = TransferHostLocal32;
+ b.TransferLocalHost = TransferLocalHost32;
+ m_Blocks[PSMCT32] = b;
+
+ // 24 (same as 32 except write/readPixel are different)
+ b.TransferHostLocal = TransferHostLocal24;
+ b.TransferLocalHost = TransferLocalHost24;
+ m_Blocks[PSMCT24] = b;
+
+ // 8H (same as 32 except write/readPixel are different)
+ b.TransferHostLocal = TransferHostLocal8H;
+ b.TransferLocalHost = TransferLocalHost8H;
+ m_Blocks[PSMT8H] = b;
+
+ b.TransferHostLocal = TransferHostLocal4HL;
+ b.TransferLocalHost = TransferLocalHost4HL;
+ m_Blocks[PSMT4HL] = b;
+
+ b.TransferHostLocal = TransferHostLocal4HH;
+ b.TransferLocalHost = TransferLocalHost4HH;
+ m_Blocks[PSMT4HH] = b;
+
+ // 32z
+ FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 64, 0, PSMT32Z);
+ b.TransferHostLocal = TransferHostLocal32Z;
+ b.TransferLocalHost = TransferLocalHost32Z;
+ m_Blocks[PSMT32Z] = b;
+
+ // 24Z (same as 32Z except write/readPixel are different)
+ b.TransferHostLocal = TransferHostLocal24Z;
+ b.TransferLocalHost = TransferLocalHost24Z;
+ m_Blocks[PSMT24Z] = b;
+
+ // 16
+ FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 32, PSMCT16);
+ b.TransferHostLocal = TransferHostLocal16;
+ b.TransferLocalHost = TransferLocalHost16;
+ m_Blocks[PSMCT16] = b;
+
+ // 16s
+ FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 64, 32, PSMCT16S);
+ b.TransferHostLocal = TransferHostLocal16S;
+ b.TransferLocalHost = TransferLocalHost16S;
+ m_Blocks[PSMCT16S] = b;
+
+ // 16z
+ FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 96, PSMT16Z);
+ b.TransferHostLocal = TransferHostLocal16Z;
+ b.TransferLocalHost = TransferLocalHost16Z;
+ m_Blocks[PSMT16Z] = b;
+
+ // 16sz
+ FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 64, 96, PSMT16SZ);
+ b.TransferHostLocal = TransferHostLocal16SZ;
+ b.TransferLocalHost = TransferLocalHost16SZ;
+ m_Blocks[PSMT16SZ] = b;
+
+ // 8
+ FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 160, PSMT8);
+ b.TransferHostLocal = TransferHostLocal8;
+ b.TransferLocalHost = TransferLocalHost8;
+ m_Blocks[PSMT8] = b;
+
+ // 4
+ FILL_BLOCK(b, floatfmt, vBlockData, vBilinearData, 0, 224, PSMT4);
+ b.TransferHostLocal = TransferHostLocal4;
+ b.TransferLocalHost = TransferLocalHost4;
+ m_Blocks[PSMT4] = b;
+}
+
+#endif
diff --git a/plugins/zzogl-pg/opengl/ZZoglMem.h b/plugins/zzogl-pg/opengl/ZZoglMem.h
new file mode 100644
index 0000000000..dbd9313ed1
--- /dev/null
+++ b/plugins/zzogl-pg/opengl/ZZoglMem.h
@@ -0,0 +1,790 @@
+/* ZeroGS KOSMOS
+ * Copyright (C) 2005-2006 zerofrog@gmail.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ZZOGL_MEM_H__
+#define __ZZOGL_MEM_H__
+
+#include
+#include
+#include "GS.h"
+#include "Util.h"
+#include "Mem.h"
+
+#ifndef ZZNORMAL_MEMORY
+
+extern u32 g_blockTable32[4][8];
+extern u32 g_blockTable32Z[4][8];
+extern u32 g_blockTable16[8][4];
+extern u32 g_blockTable16S[8][4];
+
+extern u32 g_blockTable16Z[8][4];
+
+extern u32 g_blockTable16SZ[8][4];
+
+extern u32 g_blockTable8[4][8];
+extern u32 g_blockTable4[8][4];
+
+extern u32 g_columnTable32[8][8];
+extern u32 g_columnTable16[8][16];
+extern u32 g_columnTable8[16][16];
+extern u32 g_columnTable4[16][32];
+
+//--
+
+extern u32 g_pageTable32[32][64];
+extern u32 g_pageTable32Z[32][64];
+extern u32 g_pageTable16[64][64];
+extern u32 g_pageTable16S[64][64];
+extern u32 g_pageTable16Z[64][64];
+extern u32 g_pageTable16SZ[64][64];
+extern u32 g_pageTable8[64][128];
+extern u32 g_pageTable4[128][128];
+
+
+//maximum PSM is 58, so our arrays have 58 + 1 = 59 elements
+
+// This table is used for fast access to memory storage data.
+extern u32 ZZ_DT[MAX_PSM][TABLE_WIDTH];
+
+
+//maxium PSM is 58, so our arrays have 58 + 1 = 59 elements
+extern u32** g_pageTable[MAX_PSM];
+extern u32** g_blockTable[MAX_PSM];
+extern u32** g_columnTable[MAX_PSM];
+extern u32 g_pageTable2[MAX_PSM][127][127];
+extern u32** g_pageTableNew[MAX_PSM];
+
+// rest not visible externally
+struct BLOCK
+{
+ BLOCK() { memset(this, 0, sizeof(BLOCK)); }
+
+ // shader constants for this block
+ float4 vTexBlock;
+ float4 vTexDims;
+ int width, height; // dims of one page in pixels
+ int bpp;
+ int colwidth, colheight;
+ u32** pageTable; // offset inside each page
+ u32** blockTable;
+ u32** columnTable;
+
+ // Nobody use this, so we better remove it.
+// u32 (*getPixelAddress)(int x, int y, u32 bp, u32 bw);
+// u32 (*getPixelAddress_0)(int x, int y, u32 bw);
+// void (*writePixel)(void* pmem, int x, int y, u32 pixel, u32 bp, u32 bw);
+// void (*writePixel_0)(void* pmem, int x, int y, u32 pixel, u32 bw);
+// u32 (*readPixel)(const void* pmem, int x, int y, u32 bp, u32 bw);
+// u32 (*readPixel_0)(const void* pmem, int x, int y, u32 bw);
+ int (*TransferHostLocal)(const void* pbyMem, u32 nQWordSize);
+ void (*TransferLocalHost)(void* pbyMem, u32 nQWordSize);
+
+ // texture must be of dims BLOCK_TEXWIDTH and BLOCK_TEXHEIGHT
+ static void FillBlocks(std::vector& vBlockData, std::vector& vBilinearData, int floatfmt);
+};
+
+void FillBlockTables();
+void DestroyBlockTables();
+void FillNewPageTable();
+
+extern BLOCK m_Blocks[];
+
+extern u32 g_blockTable32[4][8];
+extern u32 g_blockTable32Z[4][8];
+extern u32 g_blockTable16[8][4];
+extern u32 g_blockTable16S[8][4];
+extern u32 g_blockTable16Z[8][4];
+extern u32 g_blockTable16SZ[8][4];
+extern u32 g_blockTable8[4][8];
+extern u32 g_blockTable4[8][4];
+
+extern u32 g_columnTable32[8][8];
+extern u32 g_columnTable16[8][16];
+extern u32 g_columnTable8[16][16];
+extern u32 g_columnTable4[16][32];
+
+extern u32 g_pageTable32[32][64];
+extern u32 g_pageTable32Z[32][64];
+extern u32 g_pageTable16[64][64];
+extern u32 g_pageTable16S[64][64];
+extern u32 g_pageTable16Z[64][64];
+extern u32 g_pageTable16SZ[64][64];
+extern u32 g_pageTable8[64][128];
+extern u32 g_pageTable4[128][128];
+
+
+extern u32** g_pageTable[MAX_PSM];
+extern u32** g_blockTable[MAX_PSM];
+extern u32** g_columnTable[MAX_PSM];
+extern u32 ZZ_DT[MAX_PSM][TABLE_WIDTH];
+extern u32** g_pageTableNew[MAX_PSM];
+
+static __forceinline void MaskedOR(u32* dst, u32 pixel, u32 mask = 0xffffffff) {
+ if (mask == 0xffffffff)
+ *dst = pixel;
+ else
+ *dst = (*dst & (~mask)) | (pixel & mask);
+}
+
+// This two defines seems like idiotic code, but in reality it have one, but big importance -- this code
+// made psm variable (and psm2 in second case) -- constant, so optimiser could properly pass proper function
+#define PSM_SWITCHCASE(X) { \
+ switch (psm) { \
+ case PSMCT32: { \
+ const int psmC = PSMCT32; \
+ X; } \
+ break; \
+ case PSMT32Z: { \
+ const int psmC = PSMT32Z; \
+ X; } \
+ break; \
+ case PSMCT24: { \
+ const int psmC = PSMCT24; \
+ X; } \
+ break; \
+ case PSMT24Z: { \
+ const int psmC = PSMT24Z; \
+ X; } \
+ break; \
+ case PSMCT16: { \
+ const int psmC = PSMCT16; \
+ X; } \
+ break; \
+ case PSMCT16S: { \
+ const int psmC = PSMCT16S; \
+ X; } \
+ break; \
+ case PSMT16Z: { \
+ const int psmC = PSMT16Z; \
+ X; } \
+ break; \
+ case PSMT16SZ: { \
+ const int psmC = PSMT16SZ; \
+ X; } \
+ break; \
+ case PSMT8: { \
+ const int psmC = PSMT8; \
+ X; } \
+ break; \
+ case PSMT8H: { \
+ const int psmC = PSMT8H; \
+ X; } \
+ break; \
+ case PSMT4HH: { \
+ const int psmC = PSMT4HH; \
+ X; } \
+ break; \
+ case PSMT4HL: { \
+ const int psmC = PSMT4HL; \
+ X; } \
+ break; \
+ case PSMT4: { \
+ const int psmC = PSMT4; \
+ X; } \
+ break; \
+ }\
+}
+
+#define PSM_SWITCHCASE_2(X) { \
+ switch (psm) { \
+ case PSMCT32: \
+ if( psm2 == PSMCT32 ) { const int psmC = PSMCT32, psmC1 = PSMCT32; X; } \
+ else { const int psmC = PSMCT32, psmC1 = PSMT32Z; X; } \
+ break; \
+ case PSMCT24: \
+ if( psm2 == PSMCT24 ) { const int psmC = PSMCT24, psmC1 = PSMCT24; X; } \
+ else { const int psmC = PSMCT24, psmC1 = PSMT24Z; X; } \
+ break; \
+ case PSMT32Z: \
+ if( psm2 == PSMT32Z ) { const int psmC = PSMT32Z, psmC1 = PSMCT32; X; } \
+ else { const int psmC = PSMT32Z, psmC1 = PSMT32Z; X; } \
+ break; \
+ case PSMT24Z: \
+ if( psm2 == PSMCT24 ) { const int psmC = PSMT24Z, psmC1 = PSMCT24; X; } \
+ else { const int psmC = PSMT24Z, psmC1 = PSMT24Z; X; } \
+ break; \
+ case PSMCT16: \
+ switch(psm2) { \
+ case PSMCT16: { const int psmC = PSMCT16, psmC1 = PSMCT16; X; } break; \
+ case PSMCT16S: { const int psmC = PSMCT16, psmC1 = PSMCT16S; X; } break; \
+ case PSMT16Z: { const int psmC = PSMCT16, psmC1 = PSMT16Z; X; } break; \
+ case PSMT16SZ: { const int psmC = PSMCT16, psmC1 = PSMT16SZ; X; } break; \
+ } \
+ break; \
+ case PSMCT16S: \
+ switch(psm2) { \
+ case PSMCT16: { const int psmC = PSMCT16S, psmC1 = PSMCT16; X; } break; \
+ case PSMCT16S: { const int psmC = PSMCT16S, psmC1 = PSMCT16S; X; } break; \
+ case PSMT16Z: { const int psmC = PSMCT16S, psmC1 = PSMT16Z; X; } break; \
+ case PSMT16SZ: { const int psmC = PSMCT16S, psmC1 = PSMT16SZ; X; } break; \
+ } \
+ break; \
+ case PSMT16Z: \
+ switch(psm2) { \
+ case PSMCT16: { const int psmC = PSMT16Z, psmC1 = PSMCT16; X; } break; \
+ case PSMCT16S: { const int psmC = PSMT16Z, psmC1 = PSMCT16S; X; } break; \
+ case PSMT16Z: { const int psmC = PSMT16Z, psmC1 = PSMT16Z; X; } break; \
+ case PSMT16SZ: { const int psmC = PSMT16Z, psmC1 = PSMT16SZ; X; } break; \
+ } \
+ break; \
+ case PSMT16SZ: \
+ switch(psm2) { \
+ case PSMCT16: { const int psmC = PSMT16SZ, psmC1 = PSMCT16; X; } break; \
+ case PSMCT16S: { const int psmC = PSMT16SZ, psmC1 = PSMCT16S; X; } break; \
+ case PSMT16Z: { const int psmC = PSMT16SZ, psmC1 = PSMT16Z; X; } break; \
+ case PSMT16SZ: { const int psmC = PSMT16SZ, psmC1 = PSMT16SZ; X; } break; \
+ } \
+ break; \
+ case PSMT8: \
+ if( psm2 == PSMT8 ) { const int psmC = PSMT8, psmC1 = PSMT8; X; } \
+ else { const int psmC = PSMT8, psmC1 = PSMT8H; X; } \
+ break; \
+ case PSMT8H: \
+ if( psm2 == PSMT8H ) { const int psmC = PSMT8H, psmC1 = PSMT8; X; } \
+ else { const int psmC = PSMT8H, psmC1 = PSMT8H; X; } \
+ break; \
+ case PSMT4: \
+ switch(psm2) { \
+ case PSMT4: { const int psmC = PSMT4, psmC1 = PSMT4; X; } break; \
+ case PSMT4HL: { const int psmC = PSMT4, psmC1 = PSMT4HL; X; } break; \
+ case PSMT4HH: { const int psmC = PSMT4, psmC1 = PSMT4HH; X; } break; \
+ } \
+ break; \
+ case PSMT4HL: \
+ switch(psm2) { \
+ case PSMT4: { const int psmC = PSMT4HL, psmC1 = PSMT4; X; } break; \
+ case PSMT4HL: { const int psmC = PSMT4HL, psmC1 = PSMT4HL; X; } break; \
+ case PSMT4HH: { const int psmC = PSMT4HL, psmC1 = PSMT4HH; X; } break; \
+ } \
+ break; \
+ case PSMT4HH: \
+ switch(psm2) { \
+ case PSMT4: { const int psmC = PSMT4HH, psmC1 = PSMT4; X; } break; \
+ case PSMT4HL: { const int psmC = PSMT4HH, psmC1 = PSMT4HL; X; } break; \
+ case PSMT4HH: { const int psmC = PSMT4HH, psmC1 = PSMT4HH; X; } break; \
+ } \
+ break; \
+ } \
+}
+
+template
+static __forceinline void setPsmtConstantsX(u8& A, u8& B, u8& C, u8& D, u8& E, u8& F, u32& G, u8& H) {
+ switch (psm) {
+ case PSMCT32:
+ case PSMT32Z:
+ A = 5; B = 6; C = 0; D = 31; E = 63; F = 0; H = 1; G = 0xffffffff;
+ break;
+
+ case PSMCT24:
+ case PSMT24Z:
+ A = 5; B = 6; C = 0; D = 31; E = 63; F = 0; H = 1; G = 0xffffff;
+ break;
+
+ case PSMT8H:
+ A = 5; B = 6; C = 0; D = 31; E = 63; F = 24; H = 4; G = 0xff;
+ break;
+
+ case PSMT4HH:
+ A = 5; B = 6; C = 0; D = 31; E = 63; F = 28; H = 8; G = 0xf;
+ break;
+
+ case PSMT4HL:
+ A = 5; B = 6; C = 0; D = 31; E = 63; F = 24; H = 8; G = 0xf;
+ break;
+
+ case PSMCT16:
+ case PSMT16Z:
+ case PSMCT16S:
+ case PSMT16SZ:
+ A = 6; B = 6; C = 1; D = 63; E = 63; F = 0; H = 2; G = 0xffff;
+ break;
+
+ case PSMT8:
+ A = 6; B = 7; C = 2; D = 63; E = 127; F = 0; H = 4; G = 0xff;
+ break;
+
+ case PSMT4:
+ A = 7; B = 7; C = 3; D = 127; E = 127; F = 0; H = 8; G = 0xf;
+ break;
+ }
+}
+
+// This is where the NEW_CODE define used to be.
+
+// ------------------------------------------ get Address functions ------------------------------------
+// Yes, only 1 function to all cases of life!
+// Warning! We switch bp and bw for usage of default value, so be warned! It's
+// not C, it's C++, so not it.
+template
+static __forceinline u32 getPixelAddress(int x, int y, u32 bw, u32 bp = 0) {
+ u32 basepage;
+ u32 word;
+
+ u8 A = 0, B = 0, C = 0, D = 0, E = 0, F = 0; u32 G = 0; u8 H= 0;
+ setPsmtConstantsX(A, B, C, D, E, F, G, H);
+ basepage = ((y>>A) * (bw>>B)) + (x>>B);
+ word = ((bp * 64 + basepage * 2048) << C) + g_pageTable[psm][y&D][x&E];
+
+ return word;
+}
+
+// It's Zerofrog's function. I need to eliminate them all! All access should be 32-bit aligned.
+static __forceinline u32 getPixelAddress(int psm, int x, int y, u32 bw, u32 bp = 0) {
+ PSM_SWITCHCASE(return getPixelAddress(x, y, bw, bp) ;)
+ return 0;
+}
+
+// This is compatibility code, for reference,
+#define Def_getPixelAddress(psmT, psmX) \
+ static __forceinline u32 getPixelAddress##psmT(int x, int y, u32 bp, u32 bw) { \
+ return getPixelAddress(x, y, bw, bp); } \
+ static __forceinline u32 getPixelAddress##psmT##_0(int x, int y, u32 bw) { \
+ return getPixelAddress(x, y, bw); } \
+
+Def_getPixelAddress(32, PSMCT32)
+Def_getPixelAddress(16, PSMCT16)
+Def_getPixelAddress(16S, PSMCT16S)
+Def_getPixelAddress(8, PSMT8)
+Def_getPixelAddress(4, PSMT4)
+Def_getPixelAddress(32Z, PSMT32Z)
+Def_getPixelAddress(16Z, PSMT16Z)
+Def_getPixelAddress(16SZ, PSMT16SZ)
+
+#define getPixelAddress24 getPixelAddress32
+#define getPixelAddress24_0 getPixelAddress32_0
+#define getPixelAddress8H getPixelAddress32
+#define getPixelAddress8H_0 getPixelAddress32_0
+#define getPixelAddress4HL getPixelAddress32
+#define getPixelAddress4HL_0 getPixelAddress32_0
+#define getPixelAddress4HH getPixelAddress32
+#define getPixelAddress4HH_0 getPixelAddress32_0
+#define getPixelAddress24Z getPixelAddress32Z
+#define getPixelAddress24Z_0 getPixelAddress32Z_0
+
+// Check FFX-1 (very begining) for PSMT8
+// Check Tekken menu for PSMT4
+// ZZ_DT[7] is needed only for PSMT8H, PSMT4HL and PSMT4HH -- at this case word contain data not from a begining.
+
+// This function return shift from 32-bit aligned address and shift -- number of byte in u32 order.
+// so if ((u32*)mem + getPixelAddress_Aligned32) is exact location of u32, where our pixel data stored.
+// Just for remember:
+// PMSCT32, 24, 32Z, 24Z, 8HH, 4HL and 4HH have ZZ_DT[psm] == 3, so shift is always 0.
+// PSMCT16, 16S, 16SZ, 16Z have ZZ_DT[psm] == 2, so shift is 0 or 16.
+// PSMT8 ZZ_DT[psm] == 1, shift is 0, 8, 16, 24
+// PSMT4 ZZ_DT[psm] == 0, shift is 0, 4, 8, 12, 16, 20, 24, 28.
+
+// It allow us to made a fast access to pixels in the same basepage: if x % N == 0 (N = 1, 2, 4, 8, .. 64)
+// than we could guarantee that all pixels form x to x + N - 1 are in the same basepage.
+template
+static __forceinline u32* getPixelBasepage(const void* pmem, int x, int y, u32 bw, u32 bp = 0) {
+ u32 basepage;
+ u8 A = 0, B = 0, C = 0 , D = 0, E = 0, F = 0; u32 G = 0; u8 H = 0;
+ setPsmtConstantsX (A, B, C, D, E, F, G, H);
+ basepage = ((y>>A) * (bw>>B)) + (x>>B);
+ return ((u32*)pmem + (bp * 64 + basepage * 2048));
+}
+
+// And this is offset for this pixels.
+template
+static __forceinline u32* getPixelOffset(u32& mask, u32& shift, const void* pmem, int x, int y) {
+ u32 word;
+
+ u8 A = 0, B = 0, C = 0 , D = 0, E = 0, F = 0; u32 G = 0; u8 H = 0;
+ setPsmtConstantsX (A, B, C, D, E, F, G, H);
+
+ word = (g_pageTable[psm][y&D][x&E] << (3 - C));
+ shift = ((word & 0x7) << 2) + F;
+ mask &= G << shift;
+
+ return ((u32*)pmem + ((word & ~0x7) >> 3));
+}
+
+
+template
+static __forceinline u32* getPixelAddress_A32(u32& mask, u32& shift, const void* pmem, int x, int y, u32 bw, u32 bp = 0) {
+ return getPixelOffset(mask, shift, getPixelBasepage(pmem, x, y, bw, bp), x, y);
+
+}
+
+template
+static __forceinline u32* getPixelBaseAddress_A32(const void* pmem, int x, int y, u32 bw, u32 bp = 0) {
+ u32 word;
+
+ u8 A = 0, B = 0, C = 0 , D = 0, E = 0, F = 0; u32 G = 0; u8 H = 0;
+ setPsmtConstantsX (A, B, C, D, E, F, G, H);
+
+ word = (g_pageTable[psm][y&D][x&E] << (3 - C));
+ return ((u32*)getPixelBasepage(pmem, x, y, bw, bp) + ((word & ~0x7) >> 3));
+}
+
+// Wrapper for cases, where psm is not constant, should be avoided inside cycles
+static __forceinline u32* getPixelAddress_A32(u32& mask, u32& shift, int psm, const void* pmem, int x, int y, u32 bw, u32 bp = 0) {
+ PSM_SWITCHCASE( return getPixelAddress_A32(mask, shift, pmem, x, y, bw, bp) );
+ return 0;
+}
+
+static __forceinline u32* getClutAddress(u8* pmem, const tex0Info& tex0) {
+ if (PSMT_ISHALF(tex0.cpsm))
+ return (u32*)(pmem + 64 * (tex0.csa & 15) + (tex0.csa >= 16 ? 2 : 0) );
+ else
+ return (u32*)(pmem + 64 * (tex0.csa & 15));
+}
+
+//--------------------------------------------- Write Pixel -----------------------------------------------------------
+// Set proper mask for transfering multiple bytes per word.
+template
+inline u32 HandleWritemask(u32 Writemask) {
+ u8 G = PSM_BITS_PER_PIXEL();
+ u32 dmask = Writemask & ((1 << G) - 1); // drop all bits in writemask, that could not be used
+ u32 mask;
+
+ switch (psm) {
+ case PSMT8H: // modes with non-zero start bit should be handled differently
+ return 0xff000000;
+ case PSMT4HL:
+ return 0x0f000000;
+ case PSMT4HH:
+ return 0xf0000000;
+ default:
+ mask = dmask; // 32 targets and lower
+
+ if (G < 24) {
+ mask |= dmask << G; // 16 targets and lower
+ if (G < 16) {
+ mask |= dmask << (2 * G); // 8 targets and lower
+ mask |= dmask << (3 * G);
+ if (G < 8) {
+ mask |= dmask << (4 * G); // 4 targets
+ mask |= dmask << (5 * G);
+ mask |= dmask << (6 * G);
+ mask |= dmask << (7 * G);
+ }}}
+ return mask;
+ }
+}
+
+//push pixel data at position x,y, according psm storage format. pixel do not need to be properly masked, wrong bit's would not be used
+//mask should be made according PSM.
+template
+static __forceinline void writePixel(void* pmem, int x, int y, u32 pixel, u32 bw, u32 bp = 0, u32 mask = 0xffffffff) {
+ u32 shift;
+ u32* p = getPixelAddress_A32(mask, shift, pmem, x, y, bw, bp);
+
+ MaskedOR (p, pixel << shift, mask);
+}
+
+static __forceinline void writePixel(int psm, void* pmem, int x, int y, u32 pixel, u32 bw, u32 bp = 0, u32 mask = 0xffffffff) {
+ PSM_SWITCHCASE(writePixel(pmem, x, y, pixel, bw, bp, mask));
+}
+
+// Put pixel data from memory. Pixel is p, memory start from pixel, and we should count pmove words and shift resulting word to shift
+// 24 targets could be outside of 32-bit borders.
+template
+static __forceinline void pushPixelMem(u32* p, u32* pixel, int pmove, int shift, u32 mask = 0xffffffff) {
+ if (psm != PSMCT24 || psm != PSMT24Z) {
+ if (shift > 0)
+ MaskedOR (p, (*(pixel + pmove)) << (shift), mask);
+ else
+ MaskedOR (p, (*(pixel + pmove)) >> (-shift), mask);
+ }
+ else { // for 24 and 24Z psm data could be not-aligned by 32. Merde!
+ u64 pixel64 = (*(u64*)(pixel + pmove) ) >> (-shift); // we read more data, but for 24 targets shift always negative and resulting data is u32
+ MaskedOR(p, (u32)pixel64, mask); // drop upper part, we don't need it. all data is stored in lower part of u64 after shift
+
+// MaskedOR(p, (u32)((u8*)pixel + count * 3), mask);
+ }
+}
+
+// use it if pixel already shifted by needed number of bytes.
+// offseted mean that we should skip basepage calculation, pmem is link to basepage'ed memory. Just a little quicker.
+template
+static __forceinline void writePixelMem(const void* pmem, int x, int y, u32* pixel, int count, u32 bw, u32 bp = 0, u32 mask = 0xffffffff) {
+ u32 shift;
+ u32* p;
+
+ if (offseted)
+ p = getPixelOffset(mask, shift, pmem, x, y);
+ else
+ p = getPixelAddress_A32(mask, shift, pmem, x, y, bw, bp);
+
+ int A = PSM_BITS_PER_PIXEL();
+
+ int pmove = (count * A) >> 5;
+ int pshift = (count * A) & 31; // we assume, that if shift outside word, than user want next pixel data
+
+ pushPixelMem(p, pixel, pmove, (int)shift - pshift, mask);
+}
+
+
+// This function push several pixels. Note, that for 32, 24, 8HH, 4HL, 4HH it's simply write (and pixel should not be properly masked), 16 do push 2 pixels (and x should be even).
+// 8 push 4 pixels: 0,0; 0,1; 1,0 and 1,1. 4 push 8: 0,0; 0,1; 1,0; 1,1; 2,0, 2,1; 3,0; 3,1.
+template
+static __forceinline void writePixelWord(const void* pmem, int x, int y, u32 pixel, u32 bw, u32 bp = 0, u32 mask = 0xffffffff) {
+ u32 maskA = mask, shift;
+ u32* p = getPixelAddress_A32(maskA, shift, pmem, x, y, bw, bp);
+
+/* if (PSM_NON_FULL_WORD())
+ maskA = maskA & mask;
+ else
+ maskA = mask;*/
+
+ MaskedOR (p, pixel, mask);
+}
+
+// ------------------------------------- Read Pixel ---------------------------------------
+template
+static __forceinline u32 readPixel(const void* pmem, int x, int y, u32 bw, u32 bp = 0, u32 mask = 0xffffffff) {
+ u32 shift;
+ u32* p = getPixelAddress_A32(mask, shift, pmem, x, y, bw, bp);
+
+ return ((*p & mask) >> shift);
+}
+
+static __forceinline u32 readPixel(int psm, const void* pmem, int x, int y, u32 bw, u32 bp = 0, u32 mask = 0xffffffff) {
+ PSM_SWITCHCASE(return readPixel(pmem, x, y, bw, bp, mask););
+ return 0;
+}
+
+template
+static __forceinline u32 readPixelWord(const void* pmem, int x, int y, u32 bw, u32 bp = 0, u32 mask = 0xffffffff) {
+ u32 maskA = 0xffffffff, shift;
+ if (PSM_NON_FULL_WORD())
+ return *getPixelAddress_A32(mask, shift, pmem, x, y, bw, bp) & mask;
+ else
+ return *getPixelAddress_A32(maskA, shift, pmem, x, y, bw, bp) & mask;
+}
+
+template
+static __forceinline void fillMemoryFromPixels(u32* dst, const void* pmem, int& count, int x, int y, u32 bw, u32 bp = 0, u32 mask = 0xffffffff) {
+ u32 pixel;
+
+ u8 I = PSM_BITS_PER_PIXEL();
+ int K = count / PSM_PIXELS_STORED_PER_WORD(); // offset for pmem, count for 32, count / 2 for 16, etc.
+
+ pixel = readPixel(pmem, x, y, bw, bp, mask); // I prefer not to use for here. It's slow
+ if (I < 32) {
+ pixel += readPixel(pmem, x + 1, y, bw, bp, mask) << I;
+ if (I < 16) { // 8 and 4 targets
+ pixel += readPixel(pmem, x + 2, y, bw, bp, mask) << (2 * I);
+ pixel += readPixel(pmem, x + 3, y, bw, bp, mask) << (3 * I);
+ if (I < 8) { // This is for 4, 4HH and 4HL
+ pixel += readPixel(pmem, x + 4, y, bw, bp, mask) << (4 * I);
+ pixel += readPixel(pmem, x + 5, y, bw, bp, mask) << (5 * I);
+ pixel += readPixel(pmem, x + 6, y, bw, bp, mask) << (6 * I);
+ pixel += readPixel(pmem, x + 7, y, bw, bp, mask) << (7 * I);
+ }}}
+
+ if (I != 24) {
+ *(dst + K) = pixel;
+ }
+ else { // 24. should have special care.
+// ERROR_LOG("special care %d\n", count);
+ MaskedOR((u32*)((u8*)dst + 3 * count), pixel, 0xffffff);
+ }
+ count += PSM_PIXELS_STORED_PER_WORD();
+}
+
+
+// Fill count pixels form continues memory region, starting from pmem, First pixel to read have number shift in this region.
+// Read no more than count pixels. We could assert, that all this pixels would be place in the same basepage
+// Shift is automaticaly increased by count (or decreased if count < 0)
+template
+static __forceinline void writePixelsFromMemory(void* dst, const void* pmem, int& shift, int x, int y, u32 bw, u32 bp = 0, u32 mask = 0xffffffff) {
+ const void* base;
+ if (offseted)
+ base = getPixelBasepage(dst, x, y, bw, bp);
+ else
+ base = (const void*)dst;
+
+ shift += count;
+ writePixelMem(base, x, y, (u32*)pmem, shift - count, bw, bp, mask); // I prefer not to use for here. It's slow
+ if (count < 2) return;
+ writePixelMem(base, x + 1, y, (u32*)pmem, shift - count + 1, bw, bp, mask);
+ if (count < 3) return;
+ writePixelMem(base, x + 2, y, (u32*)pmem, shift - count + 2, bw, bp, mask);
+ if (count < 4) return;
+ writePixelMem(base, x + 3, y, (u32*)pmem, shift - count + 3, bw, bp, mask);
+ if (count < 5) return;
+ writePixelMem(base, x + 4, y, (u32*)pmem, shift - count + 4, bw, bp, mask);
+ if (count < 6) return;
+ writePixelMem