diff -Nur a/core/hw/pvr/Renderer_if.cpp b/core/hw/pvr/Renderer_if.cpp --- a/core/hw/pvr/Renderer_if.cpp 2015-10-06 21:43:53.028336301 -0300 +++ b/core/hw/pvr/Renderer_if.cpp 2015-10-06 21:49:25.016725724 -0300 @@ -5,10 +5,16 @@ #include "deps/zlib/zlib.h" +#include "deps/crypto/md5.h" + #if FEAT_HAS_NIXPROF #include "profiler/profiler.h" #endif +#define FRAME_MD5 0x1 +FILE* fLogFrames; +FILE* fCheckFrames; + /* rendv3 ideas @@ -291,6 +297,48 @@ if (ctx) { + if (fLogFrames || fCheckFrames) { + MD5Context md5; + u8 digest[16]; + + MD5Init(&md5); + MD5Update(&md5, ctx->tad.thd_root, ctx->tad.End() - ctx->tad.thd_root); + MD5Final(digest, &md5); + + if (fLogFrames) { + fputc(FRAME_MD5, fLogFrames); + fwrite(digest, 1, 16, fLogFrames); + fflush(fLogFrames); + } + + if (fCheckFrames) { + u8 v; + u8 digest2[16]; + int ch = fgetc(fCheckFrames); + + if (ch == EOF) { + printf("Testing: TA Hash log matches, exiting\n"); + exit(1); + } + + verify(ch == FRAME_MD5); + + fread(digest2, 1, 16, fCheckFrames); + + verify(memcmp(digest, digest2, 16) == 0); + + + } + + /* + u8* dig = digest; + printf("FRAME: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", + digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], + digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15] + ); + */ + } + if (!ctx->rend.Overrun) { //printf("REP: %.2f ms\n",render_end_pending_cycles/200000.0); @@ -366,6 +414,13 @@ bool rend_init() { + if (fLogFrames = fopen(settings.pvr.HashLogFile.c_str(), "wb")) { + printf("Saving frame hashes to: '%s'\n", settings.pvr.HashLogFile.c_str()); + } + + if (fCheckFrames = fopen(settings.pvr.HashCheckFile.c_str(), "rb")) { + printf("Comparing frame hashes against: '%s'\n", settings.pvr.HashCheckFile.c_str()); + } #ifdef NO_REND renderer = rend_norend(); @@ -435,6 +490,11 @@ void rend_term() { + if (fCheckFrames) + fclose(fCheckFrames); + + if (fLogFrames) + fclose(fLogFrames); } void rend_vblank() diff -Nur a/core/nullDC.cpp b/core/nullDC.cpp --- a/core/nullDC.cpp 2015-10-06 21:43:53.043336408 -0300 +++ b/core/nullDC.cpp 2015-10-06 21:49:25.017725731 -0300 @@ -260,6 +260,8 @@ #endif settings.bios.UseReios = cfgLoadInt("config", "bios.UseReios", 0); + settings.pvr.HashLogFile = cfgLoadStr("testing", "ta.HashLogFile", ""); + settings.pvr.HashCheckFile = cfgLoadStr("testing", "ta.HashCheckFile", ""); #if (HOST_OS != OS_LINUX || defined(_ANDROID) || defined(TARGET_PANDORA)) settings.aica.BufferSize=2048; diff -Nur a/core/types.h b/core/types.h --- a/core/types.h 2015-10-06 21:43:53.048336444 -0300 +++ b/core/types.h 2015-10-06 21:49:25.017725731 -0300 @@ -696,6 +696,9 @@ u32 MaxThreads; u32 SynchronousRendering; + + string HashLogFile; + string HashCheckFile; } pvr; struct {