diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 21f342cb8f..c0c0abac87 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -5120,25 +5120,33 @@ public: // result contains the result of the hack call. typedef uint32 (__cdecl* DynaHackType)(uint32, uint32, uint32, uint32, uint32, uint32, uint32, int32*, uint32, int32); +typedef uint32 (__cdecl* DynaHackType2)(uint32, uint32, uint32, uint32, uint32, uint32, uint32, int32*, uint32, int32, uint32); // Also accept CRC -bool IsInvokedDynamicCrcHack( GSFrameInfo &fi, int& skip, int region, bool &result ) +bool IsInvokedDynamicCrcHack( GSFrameInfo &fi, int& skip, int region, bool &result, uint32 crc ) { static AutoReloadLibrary dll( DYNA_DLL_PATH ); static DynaHackType dllFunc = NULL; + static DynaHackType2 dllFunc2 = NULL; if( dll.isChanged() ) { - dllFunc = (DynaHackType)dll.GetSymbolAddress( "DynamicCrcHack" ); - printf( "GSdx: Dynamic CRC-hacks: %s\n", dllFunc? - "Loaded OK (-> overriding internal hacks)" : "Not available (-> using internal hacks)"); + dllFunc = (DynaHackType)dll.GetSymbolAddress( "DynamicCrcHack" ); + dllFunc2 = (DynaHackType2)dll.GetSymbolAddress( "DynamicCrcHack2" ); + printf( "GSdx: Dynamic CRC-hacks%s: %s\n", + ((dllFunc && !dllFunc2)?" [Old dynaDLL - No CRC support]":""), + dllFunc? "Loaded OK (-> overriding internal hacks)" : + "Not available (-> using internal hacks)"); } - if( !dllFunc ) + if( !dllFunc2 && !dllFunc ) return false; int32 skip32 = skip; bool hasSharedBits = GSUtil::HasSharedBits(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM); - result = dllFunc( fi.FBP, fi.FPSM, fi.FBMSK, fi.TBP0, fi.TPSM, fi.TZTST, (uint32)fi.TME, &skip32, (uint32)region, (uint32)(hasSharedBits?1:0) )?true:false; + if(dllFunc2) + result = dllFunc2( fi.FBP, fi.FPSM, fi.FBMSK, fi.TBP0, fi.TPSM, fi.TZTST, (uint32)fi.TME, &skip32, (uint32)region, (uint32)(hasSharedBits?1:0), crc )?true:false; + else + result = dllFunc( fi.FBP, fi.FPSM, fi.FBMSK, fi.TBP0, fi.TPSM, fi.TZTST, (uint32)fi.TME, &skip32, (uint32)region, (uint32)(hasSharedBits?1:0) )?true:false; skip = skip32; return true; @@ -5289,7 +5297,7 @@ bool GSState::IsBadFrame(int& skip, int UserHacks_SkipDraw) g_crc_region = m_game.region; #ifdef ENABLE_DYNAMIC_CRC_HACK - bool res=false; if(IsInvokedDynamicCrcHack(fi, skip, g_crc_region, res)){ if( !res ) return false; } else + bool res=false; if(IsInvokedDynamicCrcHack(fi, skip, g_crc_region, res, m_crc)){ if( !res ) return false; } else #endif if(gsc && !gsc(fi, skip)) { diff --git a/tools/dynacrchack/Auto_Compile.bat b/tools/dynacrchack/Auto_Compile.bat index ebf445062f..af9f43c7e4 100644 --- a/tools/dynacrchack/Auto_Compile.bat +++ b/tools/dynacrchack/Auto_Compile.bat @@ -1,26 +1,37 @@ @echo off set source=DynaCrcHack.c +set tcc=tcc\tcc -@cd /D "%~d1%~p1" > nul +pushd "%~dp0" -if not exist tcc\tcc.exe ( - echo. - echo Missing ^\tcc\tcc.exe - echo. - echo Please download TCC 0.9.25 for windows from http://bellard.org/tcc/ - echo and extract the package to ^\tcc - echo. - pause - goto end +if exist %tcc%.exe goto pre + +rem local tcc not found, try to invoke a global tcc +set tcc=tcc +%tcc% utils\ding.c -luser32 -o utils\ding.exe >nul 2>nul +if %errorlevel% == 0 ( + echo. + echo Using globally installed tcc ... + echo. +) else ( + echo. + echo Missing ^\tcc\tcc.exe + echo. + echo Please download TCC 0.9.25 for windows from http://bellard.org/tcc/ + echo and extract the package to ^\tcc + echo. + pause + goto end ) -if not exist utils\waitForChange.exe tcc\tcc utils\waitForChange.c -o utils\waitForChange.exe -if not exist utils\ding.exe tcc\tcc utils\ding.c -luser32 -o utils\ding.exe +:pre +if not exist utils\waitForChange.exe %tcc% utils\waitForChange.c -o utils\waitForChange.exe +if not exist utils\ding.exe %tcc% utils\ding.c -luser32 -o utils\ding.exe :start echo Compiling ... echo. -tcc\tcc -shared -Wall %source% +%tcc% -shared -Wall %source% if %errorlevel% == 0 ( echo -^> OK utils\ding 2 @@ -38,4 +49,5 @@ echo. goto start -:end \ No newline at end of file +:end +popd \ No newline at end of file diff --git a/tools/dynacrchack/DynaCrcHack.c b/tools/dynacrchack/DynaCrcHack.c index 6cc6e22ae8..79c2ed5de6 100644 --- a/tools/dynacrchack/DynaCrcHack.c +++ b/tools/dynacrchack/DynaCrcHack.c @@ -33,6 +33,7 @@ #include #include +#include #include //some common tokens not available in C @@ -53,7 +54,7 @@ enum GS_PSM{PSM_PSMCT32=0,PSM_PSMCT24=1,PSM_PSMCT16=2,PSM_PSMCT16S=10,PSM_PSMT8= #define skip (*pSkip) #define GSUtil_HasSharedBits(a,b,c,d) sharedBits #define GSC_AnyGame(a,b) _GSC_AnyGame() -GSFrameInfo fi; int* pSkip; uint32 g_crc_region; uint32 sharedBits; +GSFrameInfo fi; int* pSkip; uint32 g_crc_region; uint32 sharedBits; uint32 g_crc; //utils const int MODE_3_DELAY = 750; // ms @@ -61,7 +62,11 @@ void dprintf(const char* format, ...); void dings(const int n); bool isCornerTriggered(); bool IsIn(const DWORD val, ...); -#define END 0x72951413 +// END is a magic number, if we have such CRC - meh +#define END (0x72951413) +#define IsCRC(...) (g_crc!=END && IsIn(g_crc, __VA_ARGS__, END)) +// C99 syntax for variadic macro: #define FOO(fmt, ...) printf(fmt, __VA_ARGS__) // empty list not supported +// empty list is possible by suppressing prior comma by using ##__VA_ARGS__ // ---------- Configuration --------------------------------- @@ -85,7 +90,7 @@ bool GSC_AnyGame( const GSFrameInfo& fi, int& skip ) { //Example: MGS3 CRC hack copied directly from GSState.cpp (see the Notes section exceptions): - +if( IsCRC(0x086273D2, 0x26A6E286, 0x9F185CE1) ){ // 3 first MGS3 CRCs from GSCrc.c if(skip == 0) { if(fi.TME && fi.FBP == 0x02000 && fi.FPSM == PSM_PSMCT32 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x01000) && fi.TPSM == PSM_PSMCT24) @@ -120,17 +125,19 @@ bool GSC_AnyGame( const GSFrameInfo& fi, int& skip ) return true; } +} + /*********** Dynamic CRC hack code ends here *****************/ // Prints to the Debugger's output window or to DebugView ( http://technet.microsoft.com/en-us/sysinternals/bb896647 ) void dprintf( const char* format, ...) { - #define BUFSIZ 2048 - char buffer[BUFSIZ]; + #define _BUFSIZ 2048 + char buffer[_BUFSIZ]; va_list args; va_start( args, format ); - if( 0 > vsnprintf( buffer, BUFSIZ, format, args ) ) + if( 0 > vsnprintf( buffer, _BUFSIZ, format, args ) ) sprintf( buffer, "%s","\n" ); OutputDebugString( buffer ); va_end( args ); @@ -200,24 +207,70 @@ bool preProcess_isAbort() } +DWORD WINAPI thread_PrintStats( LPVOID lpParam ); +typedef struct _stats { uint32 overall, changed, skipped, nextPrint;} Stats; + #define DLL_EXPORT __declspec(dllexport) -#define CRC_HACK DynamicCrcHack +#define CRC_HACK DynamicCrcHack2 +#define CRC_HACK_OLD DynamicCrcHack #if INITIAL_MODE == 0 #define CRC_HACK Voldemort + #define CRC_HACK_OLD Voldemort #endif DLL_EXPORT bool CRC_HACK (uint32 FBP, uint32 FPSM, uint32 FBMSK, uint32 TBP0, uint32 TPSM, uint32 TZTST, - uint32 TME, int* _pSkip, uint32 _g_crc_region, uint32 _sharedBits) + uint32 TME, int* _pSkip, uint32 _g_crc_region, uint32 _sharedBits, uint32 _crc) { + + static Stats stat={overall:0, changed:0, skipped:0, nextPrint:0}; + + DWORD now=GetTickCount(); + if(stat.nextPrint <= now){ + dprintf("DH: Overall: %5d, skipped: %5d, actions:%5d\n", stat.overall, stat.skipped, stat.changed); + stat.overall=stat.changed=stat.skipped=0; + stat.nextPrint=now+1000; + } + + stat.overall++; + if(preProcess_isAbort()) // Process dings if required return true; // Abort hack depending on mode fi.FBP=FBP; fi.FPSM=FPSM; fi.FBMSK=FBMSK; fi.TBP0=TBP0; fi.TPSM=TPSM; fi.TZTST=TZTST; fi.TME=TME; - pSkip=_pSkip; g_crc_region=_g_crc_region; sharedBits=_sharedBits; + pSkip=_pSkip; g_crc_region=_g_crc_region; sharedBits=_sharedBits; g_crc = _crc; - return _GSC_AnyGame(); + int pre=skip; + bool res=_GSC_AnyGame(); + int post=skip; + + if(skip) stat.skipped++; + + if(post!=pre) stat.changed++; + + return res; + } +DLL_EXPORT bool CRC_HACK_OLD (uint32 FBP, uint32 FPSM, uint32 FBMSK, uint32 TBP0, uint32 TPSM, uint32 TZTST, + uint32 TME, int* _pSkip, uint32 _g_crc_region, uint32 _sharedBits) +{ + return CRC_HACK(FBP, FPSM, FBMSK, TBP0, TPSM, TZTST, TME,_pSkip, _g_crc_region,_sharedBits, END); +} + +char* v[]={ + "DLL_PROCESS_DETACH", + "DLL_PROCESS_ATTACH", + "DLL_THREAD_ATTACH", + "DLL_THREAD_DETACH" +}; +BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved) +{ + if (dwReason<4) + dprintf("DllMain: %s\n", v[dwReason]); + else + dprintf("DllMain: %d\n", dwReason); + return TRUE; +} /*-------------------- Notes- -------------------------------*\ 1. If required, Use CRC_ instead of CRC:: (e.g. CRC_US instead of CRC::US) @@ -230,6 +283,10 @@ DLL_EXPORT bool CRC_HACK (uint32 FBP, uint32 FPSM, uint32 FBMSK, uint32 TBP0, ui 3. When copying the code back to GSState.cpp, remember to restore CRC::.. and GSUtil::... + 4. GSdx v5215 onwards also sends the CRC of the game (even if it's not defined at GSdx). + You can test the CRC using IsCRC(0x12345678) or, for few CRCs: IsCRC(0x12345678, 0x87654321, ...) + NOTE: with GSdx v5214 and before: IsCRC(...) always returns false. + \*----------------------------------------------------------*/ /* --------------- Usage instructions --------------------------------------------*\