Theater stuff.

This commit is contained in:
momo5502
2016-01-09 20:56:28 +01:00
parent d70836e825
commit 0bcbd75787
7 changed files with 262 additions and 7 deletions

View File

@ -21,6 +21,7 @@ namespace Components
Loader::Register(new Console());
Loader::Register(new IPCPipe());
Loader::Register(new Network());
Loader::Register(new Theatre());
Loader::Register(new Download());
Loader::Register(new Playlist());
Loader::Register(new RawFiles());

View File

@ -32,6 +32,7 @@ namespace Components
#include "Modules\Console.hpp"
#include "Modules\IPCPipe.hpp"
#include "Modules\Network.hpp"
#include "Modules\Theatre.hpp"
#include "Modules\Party.hpp" // Destroys the order, but requires network classes :D
#include "Modules\Download.hpp"
#include "Modules\Playlist.hpp"

View File

@ -0,0 +1,167 @@
#include "STDInclude.hpp"
namespace Components
{
char Theatre::BaselineSnapshot[131072] = { 0 };
PBYTE Theatre::BaselineSnapshotMsg = 0;
int Theatre::BaselineSnapshotMsgLen;
int Theatre::BaselineSnapshotMsgOff;
void Theatre::GamestateWriteStub(Game::msg_t* msg, char byte)
{
Game::MSG_WriteLong(msg, 0);
Game::MSG_WriteByte(msg, byte);
}
void Theatre::RecordGamestateStub()
{
int sequence = (*Game::serverMessageSequence - 1);
Game::FS_Write(&sequence, 4, *Game::demoFile);
}
void __declspec(naked) Theatre::BaselineStoreStub()
{
// Store snapshot message
__asm mov Theatre::BaselineSnapshotMsg, edi
// Store offset and length
Theatre::BaselineSnapshotMsgLen = *(int*)(Theatre::BaselineSnapshotMsg + 20);
Theatre::BaselineSnapshotMsgOff = *(int*)(Theatre::BaselineSnapshotMsg + 28) - 7;
// Copy to our snapshot buffer
memcpy(Theatre::BaselineSnapshot, *(DWORD**)(Theatre::BaselineSnapshotMsg + 8), *(DWORD*)(Theatre::BaselineSnapshotMsg + 20));
__asm
{
mov edx, 5ABEF5h
jmp edx
}
}
void Theatre::WriteBaseline()
{
static char bufData[131072];
static char cmpData[131072];
Game::msg_t buf;
Game::MSG_Init(&buf, bufData, 131072);
Game::MSG_WriteData(&buf, &Theatre::BaselineSnapshot[Theatre::BaselineSnapshotMsgOff], Theatre::BaselineSnapshotMsgLen - Theatre::BaselineSnapshotMsgOff);
Game::MSG_WriteByte(&buf, 6);
int compressedSize = Game::MSG_WriteBitsCompress(false, buf.data, cmpData, buf.cursize);
int fileCompressedSize = compressedSize + 4;
int byte8 = 8;
char byte0 = 0;
Game::FS_Write(&byte0, 1, *Game::demoFile);
Game::FS_Write(Game::serverMessageSequence, 4, *Game::demoFile);
Game::FS_Write(&fileCompressedSize, 4, *Game::demoFile);
Game::FS_Write(&byte8, 4, *Game::demoFile);
for (int i = 0; i < compressedSize; i += 1024)
{
int size = min(compressedSize - i, 1024);
if (i + size >= sizeof(cmpData))
{
Logger::Print("Error: Writing compressed demo baseline exceeded buffer\n");
break;
}
Game::FS_Write(&cmpData[i], size, *Game::demoFile);
}
}
void __declspec(naked) Theatre::BaselineToFileStub()
{
__asm
{
call Theatre::WriteBaseline
// Restore overwritten operation
mov ecx, 0A5E9C4h
mov [ecx], 0
// Return to original code
mov ecx, 5A863Ah
jmp ecx
}
}
void __declspec(naked) Theatre::AdjustTimeDeltaStub()
{
__asm
{
mov eax, Game::demoPlaying
mov eax, [eax]
test al, al
jz continue
// delta doesn't drift for demos
retn
continue:
mov eax, 5A1AD0h
jmp eax
}
}
void __declspec(naked) Theatre::ServerTimedOutStub()
{
__asm
{
mov eax, Game::demoPlaying
mov eax, [eax]
test al, al
jz continue
mov eax, 5A8E70h
jmp eax
continue:
mov eax, 0B2BB90h
mov esi, 5A8E08h
jmp esi
}
}
void __declspec(naked) Theatre::UISetActiveMenuStub()
{
if (*Game::demoPlaying == 1)
{
__asm
{
mov eax, 4CB49Ch
jmp eax
}
}
__asm
{
mov ecx, [esp + 10h]
push 10h
push ecx
mov eax, 4CB3F6h
jmp eax
}
}
Theatre::Theatre()
{
Utils::Hook(0x5A8370, Theatre::GamestateWriteStub, HOOK_CALL).Install()->Quick();
Utils::Hook(0x5A85D2, Theatre::RecordGamestateStub, HOOK_CALL).Install()->Quick();
Utils::Hook(0x5ABE36, Theatre::BaselineStoreStub, HOOK_JUMP).Install()->Quick();
Utils::Hook(0x5A8630, Theatre::BaselineToFileStub, HOOK_JUMP).Install()->Quick();
Utils::Hook(0x4CB3EF, Theatre::UISetActiveMenuStub, HOOK_JUMP).Install()->Quick();
Utils::Hook(0x50320E, Theatre::AdjustTimeDeltaStub, HOOK_CALL).Install()->Quick();
Utils::Hook(0x5A8E03, Theatre::ServerTimedOutStub, HOOK_JUMP).Install()->Quick();
// set the configstrings stuff to load the default (empty) string table; this should allow demo recording on all gametypes/maps
if(!Dedicated::IsDedicated()) Utils::Hook::Set<char*>(0x47440B, "mp/defaultStringTable.csv");
*(BYTE*)0x5AC854 = 4;
*(BYTE*)0x5AC85A = 4;
}
}

View File

@ -0,0 +1,25 @@
namespace Components
{
class Theatre : public Component
{
public:
Theatre();
const char* GetName() { return "Theatre"; };
private:
static char BaselineSnapshot[131072];
static PBYTE BaselineSnapshotMsg;
static int BaselineSnapshotMsgLen;
static int BaselineSnapshotMsgOff;
static void WriteBaseline();
static void GamestateWriteStub(Game::msg_t* msg, char byte);
static void RecordGamestateStub();
static void BaselineStoreStub();
static void BaselineToFileStub();
static void AdjustTimeDeltaStub();
static void ServerTimedOutStub();
static void UISetActiveMenuStub();
};
}