rend/if: Logging/verification of MD5(ta command list data)

This allows for some very primitive auto-automated testing, by comparing known good frames.
As this happens on the TA level, it doesn't actually require rendering (and thus it's server friendly)

Two new config entries under the new [testing] namespace control behavior
- ta.HashLogFile, file where data should be logged, empty if not logging
- ta.HashCheckFile, past log to check against, empty if not checking

The emu will crash via verify if the logs don't match, and exit(1) if they do
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis 2015-10-05 23:32:25 +02:00
parent 915d6b26d6
commit 7d951b7697
3 changed files with 65 additions and 0 deletions

View File

@ -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 @@ void rend_start_render()
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 @@ void rend_end_wait()
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 @@ bool rend_init()
void rend_term()
{
if (fCheckFrames)
fclose(fCheckFrames);
if (fLogFrames)
fclose(fLogFrames);
}
void rend_vblank()

View File

@ -260,6 +260,8 @@ void LoadSettings()
#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;

View File

@ -696,6 +696,9 @@ struct settings_t
u32 MaxThreads;
u32 SynchronousRendering;
string HashLogFile;
string HashCheckFile;
} pvr;
struct {