[Debgging] Add read/write logger

- You can use the two comparison files (iw4_reads.log & zb_writes.log) to compare the two for differences
- Move the hook in QuickPatches around to change the asset that you're logging
This commit is contained in:
TheApadayo 2016-12-21 20:58:00 -05:00
parent ec37ab6714
commit 4cb109c3ee
6 changed files with 153 additions and 2 deletions

View File

@ -115,6 +115,7 @@ namespace Assets
AssertSize(Game::GfxWorldDpvsPlanes, 16);
Utils::Stream* buffer = builder->getBuffer();
SAVE_LOG_ENTER("GfxWorldDpvsPlanes");
if (asset->planes)
{
@ -151,11 +152,13 @@ namespace Assets
}
buffer->popBlock();
SAVE_LOG_EXIT();
}
void IGfxWorld::saveGfxWorldDraw(Game::GfxWorldDraw* asset, Game::GfxWorldDraw* dest, Components::ZoneBuilder::Zone* builder)
{
AssertSize(Game::GfxWorldDraw, 72);
SAVE_LOG_ENTER("GfxWorldDraw");
Utils::Stream* buffer = builder->getBuffer();
@ -284,6 +287,8 @@ namespace Assets
buffer->saveArray(asset->indices, asset->indexCount);
Utils::Stream::ClearPointer(&dest->indices);
}
SAVE_LOG_EXIT();
}
void IGfxWorld::saveGfxLightGrid(Game::GfxLightGrid* asset, Game::GfxLightGrid* dest, Components::ZoneBuilder::Zone* builder)
@ -291,6 +296,7 @@ namespace Assets
AssertSize(Game::GfxLightGrid, 56);
Utils::Stream* buffer = builder->getBuffer();
SAVE_LOG_ENTER("GfxLightGrid");
if (asset->rowDataStart)
{
@ -323,12 +329,15 @@ namespace Assets
buffer->saveArray(asset->colors, asset->colorCount);
Utils::Stream::ClearPointer(&dest->colors);
}
SAVE_LOG_EXIT();
}
void IGfxWorld::savesunflare_t(Game::sunflare_t* asset, Game::sunflare_t* dest, Components::ZoneBuilder::Zone* builder)
{
AssertSize(Game::sunflare_t, 96);
SAVE_LOG_ENTER("sunflare_t");
if (asset->spriteMaterial)
{
dest->spriteMaterial = builder->requireAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->spriteMaterial->name).material;
@ -338,6 +347,8 @@ namespace Assets
{
dest->flareMaterial = builder->requireAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->flareMaterial->name).material;
}
SAVE_LOG_EXIT();
}
void IGfxWorld::saveGfxWorldDpvsStatic(Game::GfxWorld* world, Game::GfxWorldDpvsStatic* asset, Game::GfxWorldDpvsStatic* dest, int /*planeCount*/, Components::ZoneBuilder::Zone* builder)
@ -345,6 +356,7 @@ namespace Assets
AssertSize(Game::GfxWorldDpvsStatic, 108);
Utils::Stream* buffer = builder->getBuffer();
SAVE_LOG_ENTER("GfxWorldDpvsStatic");
buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME);
@ -458,6 +470,7 @@ namespace Assets
}
buffer->popBlock();
SAVE_LOG_EXIT();
}
void IGfxWorld::saveGfxWorldDpvsDynamic(Game::GfxWorldDpvsDynamic* asset, Game::GfxWorldDpvsDynamic* dest, Components::ZoneBuilder::Zone* builder)
@ -465,6 +478,7 @@ namespace Assets
AssertSize(Game::GfxWorldDpvsDynamic, 48);
Utils::Stream* buffer = builder->getBuffer();
SAVE_LOG_ENTER("GfxWorldDpvsDynamic");
buffer->pushBlock(Game::XFILE_BLOCK_RUNTIME);
@ -497,6 +511,7 @@ namespace Assets
}
buffer->popBlock();
SAVE_LOG_EXIT();
}
void IGfxWorld::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
@ -504,6 +519,7 @@ namespace Assets
AssertSize(Game::GfxWorld, 0x274);
Utils::Stream* buffer = builder->getBuffer();
SAVE_LOG_ENTER("GfxWorld");
Game::GfxWorld* asset = header.gfxWorld;
Game::GfxWorld* dest = buffer->dest<Game::GfxWorld>();
buffer->save(asset);
@ -860,5 +876,6 @@ namespace Assets
}
buffer->popBlock();
SAVE_LOG_EXIT();
}
}

View File

@ -141,6 +141,54 @@ namespace Components
Game::CL_SelectStringTableEntryInDvar_f();
}
#ifdef DEBUG
FILE* QuickPatch::readLog = nullptr;
Utils::Hook QuickPatch::beginLoggingHook;
int* QuickPatch::g_streamPos = (int*)0x16E5554;
void QuickPatch::logReads(bool /*flush*/)
{
fopen_s(&readLog, "userraw/logs/iw4_reads.log", "w");
// call the original load func
__asm
{
push 1
call beginLoggingHook.original
add esp, 4
}
if(readLog)
{
fclose(readLog);
readLog = nullptr;
}
}
void QuickPatch::logXAssetRead(int len)
{
*g_streamPos = *g_streamPos + len;
if(!readLog) return;
fprintf(readLog, "%d\n", len);
fflush(readLog);
// manually flush file because otherwie when ZB crashes it wont get flushed
}
void QuickPatch::logXAssetVirtualRead(int len)
{
*g_streamPos = *g_streamPos + len;
if(!readLog) return;
fprintf(readLog, "(%d)\n", len);
fflush(readLog);
// manually flush file because otherwie when ZB crashes it wont get flushed
}
#endif
QuickPatch::QuickPatch()
{
// protocol version (workaround for hacks)
@ -433,6 +481,12 @@ namespace Components
Game::Con_DrawMiniConsole(0, 2, 4, (Game::CL_IsCgameInitialized() ? 1.0f : 0.4f));
}
});
beginLoggingHook.initialize(0x4BCB62, QuickPatch::logReads, HOOK_CALL); // currently set to Load_GfxWorld
beginLoggingHook.install()->quick();
Utils::Hook(0x470E75, QuickPatch::logXAssetRead, HOOK_CALL).install()->quick();
Utils::Hook(0x4E0E0B, QuickPatch::logXAssetRead, HOOK_CALL).install()->quick();
Utils::Hook(0x470E5A, QuickPatch::logXAssetVirtualRead, HOOK_CALL).install()->quick();
#endif
}

View File

@ -31,5 +31,14 @@ namespace Components
static int MsgReadBitsCompressCheckSV(const char *from, char *to, int size);
static int MsgReadBitsCompressCheckCL(const char *from, char *to, int size);
static void CL_HandleRelayPacketCheck(Game::msg_t* msg, int client);
#ifdef DEBUG
static FILE* readLog;
static Utils::Hook beginLoggingHook;
static int* g_streamPos;
static void logReads(bool flush);
static void logXAssetRead(int len);
static void logXAssetVirtualRead(int len);
#endif
};
}

View File

@ -148,6 +148,17 @@ using namespace std::literals;
#define AssertSize(x, size) static_assert(sizeof(x) == size, STRINGIZE(x) " structure has an invalid size.")
#define AssertOffset(x, y, offset) static_assert(offsetof(x, y) == offset, STRINGIZE(x) "::" STRINGIZE(y) " is not at the right offset.")
// write logs for ZoneBuilder
#ifndef DEBUG
#define SAVE_LOG_ENTER(x)
#define SAVE_LOG_EXIT()
#define SAVE_LOG_WRITE(size)
#else
#define SAVE_LOG_ENTER(x) builder->getBuffer()->enterStruct(x)
#define SAVE_LOG_EXIT() builder->getBuffer()->leaveStruct()
#define SAVE_LOG_WRITE(size) this->logWrite(size)
#endif
// Resource stuff
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS

View File

@ -62,6 +62,14 @@ namespace Utils
Stream::Stream() : criticalSectionState(0)
{
memset(this->blockSize, 0, sizeof(this->blockSize));
#ifdef DEBUG
if(this->writeLog) return;
if(fopen_s(&this->writeLog, "userraw/logs/zb_writes.log", "w"))
{
Components::Logger::Print("WARNING: Couldn't open write log. Writes from ZoneBuilder will not be logged.\n");
}
#endif
}
Stream::Stream(size_t size) : Stream()
@ -77,6 +85,13 @@ namespace Utils
{
MessageBoxA(0, Utils::String::VA("Invalid critical section state '%i' for stream destruction!", this->criticalSectionState), "WARNING", MB_ICONEXCLAMATION);
}
#ifdef DEBUG
if(this->writeLog)
{
fclose(this->writeLog);
}
#endif
};
size_t Stream::length()
@ -109,6 +124,9 @@ namespace Utils
this->buffer.append(static_cast<const char*>(_str), size * count);
// log the write for zonebuilder debugging
SAVE_LOG_WRITE(size * count);
if (this->data() != data && this->isCriticalSection())
{
MessageBoxA(0, "Stream reallocation during critical operations not permitted!\nPlease increase the initial memory size or reallocate memory during non-critical sections!", "ERROR", MB_ICONERROR);
@ -303,4 +321,38 @@ namespace Utils
return (this->criticalSectionState != 0);
}
#ifdef DEBUG
FILE* Stream::writeLog = nullptr;
int Stream::structLevel = 0;
void Stream::enterStruct(const char* structName)
{
if(!this->writeLog) return;
fprintf(this->writeLog, "%*s%s\n", this->structLevel++, "", structName);
}
void Stream::leaveStruct()
{
if(!this->writeLog) return;
this->structLevel--;
if(this->structLevel < 0) {
Components::Logger::Print("Stream::exitStruct underflow! All following writes will not be logged!\n");
fclose(this->writeLog);
this->writeLog = nullptr;
return;
}
fprintf(this->writeLog, "%*s-----\n", this->structLevel, "");
}
void Stream::logWrite(int writeLen)
{
if(!this->writeLog) return;
fprintf(this->writeLog, "%*s%d\n", this->structLevel, "", writeLen);
}
#endif
}

View File

@ -121,6 +121,14 @@ namespace Utils
void leaveCriticalSection();
bool isCriticalSection();
// for recording zb writes
#ifdef DEBUG
static FILE* writeLog;
static int structLevel;
void enterStruct(const char* structName);
void leaveStruct();
void logWrite(int writeLen);
#endif
// This represents packed offset in streams:
// - lowest 28 bits store the value/offset
@ -143,8 +151,8 @@ namespace Utils
Offset(Game::XFILE_BLOCK_TYPES _block, uint32_t _offset) : offset(_offset), block(_block) {};
// The game needs it to be incremented
uint32_t getPackedOffset()
{
uint32_t getPackedOffset()
{
return this->packed + 1;
};