From 6b1654bbff9d1a499702acd0eb21042c4f35cedf Mon Sep 17 00:00:00 2001 From: dreamstalker Date: Sun, 17 May 2015 15:30:30 +0400 Subject: [PATCH] Flightrec: WIP --- build.gradle | 8 ++ flightrec/decoder/build.gradle | 4 + .../flightrec/filescan/FileScanResult.java | 9 ++ .../filescan/FlightRecFileScanner.java | 102 ++++++++++++++++++ .../flightrec/filescan/HeaderScanResult.java | 20 ++++ flightrec/decoder_api/build.gradle | 4 + .../flightrec/api/DecodedExtraData.java | 8 ++ .../rehlds/flightrec/api/EntranceKind.java | 7 ++ .../flightrec/api/FlightrecMessage.java | 10 ++ .../rehlds/flightrec/api/ImmutablePair.java | 11 ++ rehlds/engine/host.cpp | 19 +++- rehlds/engine/pr_edict.cpp | 12 ++- rehlds/msvc/ReHLDS.vcxproj | 18 ++-- rehlds/rehlds/FlightRecorderImpl.cpp | 32 ++++-- rehlds/rehlds/FlightRecorderImpl.h | 8 ++ rehlds/rehlds/flight_recorder.cpp | 27 ++++- rehlds/rehlds/flight_recorder.h | 13 ++- settings.gradle | 1 + 18 files changed, 286 insertions(+), 27 deletions(-) create mode 100644 flightrec/decoder/build.gradle create mode 100644 flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/FileScanResult.java create mode 100644 flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/FlightRecFileScanner.java create mode 100644 flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/HeaderScanResult.java create mode 100644 flightrec/decoder_api/build.gradle create mode 100644 flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/DecodedExtraData.java create mode 100644 flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/EntranceKind.java create mode 100644 flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/FlightrecMessage.java create mode 100644 flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/ImmutablePair.java diff --git a/build.gradle b/build.gradle index 5710cf7..4b4bd5c 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,14 @@ apply plugin: 'maven-publish' apply from: 'shared.gradle' group = 'rehlds' +apply plugin: 'idea' + +idea { + project { + languageLevel = 'JDK_1_7' + } +} + def gitInfo = GitVersioner.versionForDir(project.rootDir) if (!gitInfo) { throw new RuntimeException('Running outside git repository') diff --git a/flightrec/decoder/build.gradle b/flightrec/decoder/build.gradle new file mode 100644 index 0000000..5fd35a5 --- /dev/null +++ b/flightrec/decoder/build.gradle @@ -0,0 +1,4 @@ +apply plugin: 'java' + +sourceCompatibility = '1.7' +targetCompatibility = '1.7' diff --git a/flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/FileScanResult.java b/flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/FileScanResult.java new file mode 100644 index 0000000..ed91a5a --- /dev/null +++ b/flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/FileScanResult.java @@ -0,0 +1,9 @@ +package org.rehlds.flightrec.filescan; + +import java.util.ArrayList; +import java.util.List; + +public class FileScanResult { + public List metaHeaders = new ArrayList<>(); + public List dataHeaders = new ArrayList<>(); +} diff --git a/flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/FlightRecFileScanner.java b/flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/FlightRecFileScanner.java new file mode 100644 index 0000000..1a27505 --- /dev/null +++ b/flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/FlightRecFileScanner.java @@ -0,0 +1,102 @@ +package org.rehlds.flightrec.filescan; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Arrays; +import java.util.List; +import java.util.zip.CRC32; + +public class FlightRecFileScanner { + RandomAccessFile file; + long fileLen; + FileScanResult scanRes = new FileScanResult(); + + private final static int HEADER_SIZE = 128; + private final static String META_HEADER = "REHLDS_FLIGHTREC_META"; + private final static String DATA_HEADER = "REHLDS_FLIGHTREC_DATA"; + // 012345678901234567890 + // 000000000011111111112 + + private static byte[] META_HEADER_SIGNATURE = (META_HEADER + META_HEADER + META_HEADER + ":").getBytes(); + private static byte[] DATA_HEADER_SIGNATURE = (META_HEADER + META_HEADER + META_HEADER + ":").getBytes(); + + private byte readBuf[] = new byte[65536]; + private byte header[] = new byte[HEADER_SIZE]; + + private FlightRecFileScanner(RandomAccessFile file) throws IOException { + this.file = file; + this.fileLen = file.length(); + } + + private void examineHeader(byte[] data, int size, int pos) throws IOException { + if (pos + HEADER_SIZE < size) { + System.arraycopy(data, pos, header, 0, HEADER_SIZE); + } else { + return; //will be read in next iteration + } + + String matchedType = null; + if (Arrays.equals(META_HEADER_SIGNATURE, Arrays.copyOfRange(header, 0, META_HEADER_SIGNATURE.length))) { + matchedType = META_HEADER; + } else if (Arrays.equals(DATA_HEADER_SIGNATURE, Arrays.copyOfRange(header, 0, DATA_HEADER_SIGNATURE.length))) { + matchedType = DATA_HEADER; + } + + if (matchedType == null) { + return; + } + List resList = (matchedType.equals(META_HEADER)) ? scanRes.metaHeaders : scanRes.dataHeaders; + int versionPos = matchedType.length() * 3 + 1; + int version = header[versionPos] | header[versionPos+1] << 8 | header[versionPos+2] << 16 | header[versionPos+3] << 24; + + int allocSizePos = matchedType.length() * 3 + 1 + 4; + int allocSize = header[allocSizePos] | header[allocSizePos+1] << 8 | header[allocSizePos+2] << 16 | header[allocSizePos+3] << 24; + + CRC32 crc32 = new CRC32(); + int bufCksumPos = matchedType.length() * 3 + 1 + 4 + 4; //3*head + ":" + version + allocsize + crc32.update(header, 0, bufCksumPos); + long calculatedChecksum = crc32.getValue(); + long bufChecksum = header[bufCksumPos] | header[bufCksumPos+1] << 8 | header[bufCksumPos+2] << 16 | header[bufCksumPos+3] << 24; + + if (calculatedChecksum != bufChecksum) { + resList.add(new HeaderScanResult(file.getFilePointer() + pos, allocSize, false, "Checksum mismatch", version)); + return; + } + + long endPos = file.getFilePointer() - size + pos + allocSize; + if (endPos >= file.length()) { + resList.add(new HeaderScanResult(file.getFilePointer() + pos, allocSize, false, "Regions partially lays outside the file", version)); + return; + } + resList.add(new HeaderScanResult(file.getFilePointer() + pos, allocSize, true, null, version)); + } + + private void scanForHeaders(byte[] data, int size) throws IOException { + int maxHeaderSize = Math.max(META_HEADER.length(), DATA_HEADER.length()); + for (int i = 0; i < size - maxHeaderSize; i++) { + if (data[i + 15] == META_HEADER_SIGNATURE[15] && data[i + 16] == META_HEADER_SIGNATURE[16] && data[i + 17] == META_HEADER_SIGNATURE[17] && data[i + 18] == META_HEADER_SIGNATURE[18]) { + examineHeader(data, size, i); + } else if (data[i + 15] == DATA_HEADER_SIGNATURE[15] && data[i + 16] == DATA_HEADER_SIGNATURE[16] && data[i + 17] == DATA_HEADER_SIGNATURE[17] && data[i + 18] == DATA_HEADER_SIGNATURE[18]) { + examineHeader(data, size, i); + } + } + } + + private void doScan() throws IOException { + file.seek(0); + int read; + + while (-1 != (read = file.read(readBuf))) { + scanForHeaders(readBuf, read); + if (read == readBuf.length) { + file.seek(file.getFilePointer() - HEADER_SIZE * 2); + } + } + } + + public static FileScanResult scan(RandomAccessFile file) throws IOException { + FlightRecFileScanner scanner = new FlightRecFileScanner(file); + scanner.doScan(); + return scanner.scanRes; + } +} diff --git a/flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/HeaderScanResult.java b/flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/HeaderScanResult.java new file mode 100644 index 0000000..fd03ae9 --- /dev/null +++ b/flightrec/decoder/src/main/java/org/rehlds/flightrec/filescan/HeaderScanResult.java @@ -0,0 +1,20 @@ +package org.rehlds.flightrec.filescan; + +public class HeaderScanResult { + public long pos; + public int len; + public boolean valid; + public String error; + public int version; + + public HeaderScanResult() { + } + + public HeaderScanResult(long pos, int len, boolean valid, String error, int version) { + this.pos = pos; + this.len = len; + this.valid = valid; + this.error = error; + this.version = version; + } +} diff --git a/flightrec/decoder_api/build.gradle b/flightrec/decoder_api/build.gradle new file mode 100644 index 0000000..5fd35a5 --- /dev/null +++ b/flightrec/decoder_api/build.gradle @@ -0,0 +1,4 @@ +apply plugin: 'java' + +sourceCompatibility = '1.7' +targetCompatibility = '1.7' diff --git a/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/DecodedExtraData.java b/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/DecodedExtraData.java new file mode 100644 index 0000000..77b2638 --- /dev/null +++ b/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/DecodedExtraData.java @@ -0,0 +1,8 @@ +package org.rehlds.flightrec.api; + +public class DecodedExtraData { + String decoderId; + String decoderVersion; + + ImmutablePair data[]; +} diff --git a/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/EntranceKind.java b/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/EntranceKind.java new file mode 100644 index 0000000..9f96aa2 --- /dev/null +++ b/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/EntranceKind.java @@ -0,0 +1,7 @@ +package org.rehlds.flightrec.api; + +public enum EntranceKind { + ENTRANCE_ENTER, + ENTRANCE_LEAVE, + ENTRANCE_UNUSED, +} diff --git a/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/FlightrecMessage.java b/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/FlightrecMessage.java new file mode 100644 index 0000000..133467f --- /dev/null +++ b/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/FlightrecMessage.java @@ -0,0 +1,10 @@ +package org.rehlds.flightrec.api; + +public class FlightrecMessage { + String type; + int version; + byte[] rawData; + EntranceKind entranceKind; + + DecodedExtraData decodedData; +} diff --git a/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/ImmutablePair.java b/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/ImmutablePair.java new file mode 100644 index 0000000..ed6f7ef --- /dev/null +++ b/flightrec/decoder_api/src/main/java/org/rehlds/flightrec/api/ImmutablePair.java @@ -0,0 +1,11 @@ +package org.rehlds.flightrec.api; + +public class ImmutablePair { + public final T first; + public final U second; + + public ImmutablePair(T first, U second) { + this.first = first; + this.second = second; + } +} diff --git a/rehlds/engine/host.cpp b/rehlds/engine/host.cpp index 8114beb..f175e6b 100644 --- a/rehlds/engine/host.cpp +++ b/rehlds/engine/host.cpp @@ -891,7 +891,11 @@ void _Host_Frame(float time) if (!Host_FilterTime(time)) return; - FR_StartFrame(); +#ifdef REHLDS_FLIGHT_REC + if (rehlds_flrec_frame.string[0] != '0') { + FR_StartFrame(); + } +#endif //REHLDS_FLIGHT_REC //SystemWrapper_RunFrame(host_frametime); @@ -951,7 +955,11 @@ void _Host_Frame(float time) Host_Quit_f(); } - FR_EndFrame(); +#ifdef REHLDS_FLIGHT_REC + if (rehlds_flrec_frame.string[0] != '0') { + FR_EndFrame(); + } +#endif //REHLDS_FLIGHT_REC } /* <36628> ../engine/host.c:1501 */ @@ -1136,12 +1144,17 @@ int Host_Init(quakeparms_t *parms) Ed_StrPool_Init(); #endif //REHLDS_FIXES - FR_Init(); + FR_Init(); //don't put it under REHLDS_FLIGHT_REC to allow recording via Rehlds API Cbuf_Init(); Cmd_Init(); Cvar_Init(); Cvar_CmdInit(); + +#ifdef REHLDS_FLIGHT_REC + FR_Rehlds_Init(); +#endif //REHLDS_FLIGHT_REC + V_Init(); Chase_Init(); COM_Init(parms->basedir); diff --git a/rehlds/engine/pr_edict.cpp b/rehlds/engine/pr_edict.cpp index cef96af..295aa38 100644 --- a/rehlds/engine/pr_edict.cpp +++ b/rehlds/engine/pr_edict.cpp @@ -452,7 +452,11 @@ void *PvAllocEntPrivateData(edict_t *pEdict, int32 cb) pEdict->pvPrivateData = Mem_Calloc(1, cb); - FR_AllocEntPrivateData(pEdict->pvPrivateData); +#ifdef REHLDS_FLIGHT_REC + if (rehlds_flrec_pvdata.string[0] != '0') { + FR_AllocEntPrivateData(pEdict->pvPrivateData); + } +#endif //REHLDS_FLIGHT_REC return pEdict->pvPrivateData; } @@ -478,7 +482,11 @@ void FreeEntPrivateData(edict_t *pEdict) gNewDLLFunctions.pfnOnFreeEntPrivateData(pEdict); } - FR_FreeEntPrivateData(pEdict->pvPrivateData); +#ifdef REHLDS_FLIGHT_REC + if (rehlds_flrec_pvdata.string[0] != '0') { + FR_FreeEntPrivateData(pEdict->pvPrivateData); + } +#endif //REHLDS_FLIGHT_REC Mem_Free(pEdict->pvPrivateData); pEdict->pvPrivateData = 0; diff --git a/rehlds/msvc/ReHLDS.vcxproj b/rehlds/msvc/ReHLDS.vcxproj index 30d485e..96b7bd0 100644 --- a/rehlds/msvc/ReHLDS.vcxproj +++ b/rehlds/msvc/ReHLDS.vcxproj @@ -639,7 +639,7 @@ Level3 Disabled true - REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -677,7 +677,7 @@ Level3 Disabled true - REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -714,7 +714,7 @@ Level3 Disabled true - REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -750,7 +750,7 @@ Level3 Disabled true - REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -789,7 +789,7 @@ Level3 Disabled true - REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -825,7 +825,7 @@ Level3 Disabled true - REHLDS_OPT_PEDANTIC;REHLDS_SELF;_BUILD_FROM_IDE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;_BUILD_FROM_IDE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) MultiThreadedDebug Use precompiled.h @@ -860,7 +860,7 @@ Level3 Disabled true - REHLDS_OPT_PEDANTIC;REHLDS_FIXES;REHLDS_SELF;_BUILD_FROM_IDE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_FIXES;REHLDS_SELF;_BUILD_FROM_IDE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) MultiThreadedDebug Use precompiled.h @@ -897,7 +897,7 @@ true true true - REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded /arch:IA32 %(AdditionalOptions) Use @@ -936,7 +936,7 @@ true true true - REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded /arch:IA32 %(AdditionalOptions) Use diff --git a/rehlds/rehlds/FlightRecorderImpl.cpp b/rehlds/rehlds/FlightRecorderImpl.cpp index d8bdc3f..1801529 100644 --- a/rehlds/rehlds/FlightRecorderImpl.cpp +++ b/rehlds/rehlds/FlightRecorderImpl.cpp @@ -18,15 +18,15 @@ #include "precompiled.h" CRehldsFlightRecorder::CRehldsFlightRecorder() { - m_MetaRegionPtr = (uint8*) sys_allocmem(META_REGION_SIZE); - m_DataRegionPtr = (uint8*) sys_allocmem(DATA_REGION_SIZE); + m_MetaRegion = (uint8*) sys_allocmem(META_REGION_SIZE); + m_DataRegion = (uint8*) sys_allocmem(DATA_REGION_SIZE); - if (!m_MetaRegionPtr || !m_DataRegionPtr) { + if (!m_MetaRegion || !m_DataRegion) { rehlds_syserror("%s: direct allocation failed", __FUNCTION__); } //initialize meta region header - char* metaPos = (char*)m_MetaRegionPtr; + char* metaPos = (char*)m_MetaRegion; const char* metaSignature = "REHLDS_FLIGHTREC_META"; metaPos += sprintf(metaPos, "%s%s%s:", metaSignature, metaSignature, metaSignature); @@ -35,12 +35,12 @@ CRehldsFlightRecorder::CRehldsFlightRecorder() { m_pRecorderState = (recorder_state*)metaPos; metaPos += sizeof(recorder_state); - if ((metaPos - (char*)m_MetaRegionPtr) > META_REGION_HEADER) { + if ((metaPos - (char*)m_MetaRegion) > META_REGION_HEADER) { rehlds_syserror("%s: Meta header overflow", __FUNCTION__); } //initialize data region header - char* dataPos = (char*)m_DataRegionPtr; + char* dataPos = (char*)m_DataRegion; const char* dataSignature = "REHLDS_FLIGHTREC_DATA"; dataPos += sprintf(dataPos, "%s%s%s:", dataSignature, dataSignature, dataSignature); @@ -53,8 +53,8 @@ CRehldsFlightRecorder::CRehldsFlightRecorder() { InitHeadersContent(); - m_MetaRegionPtr += META_REGION_HEADER; - m_DataRegionPtr += DATA_REGION_HEADER; + m_MetaRegionPtr = m_MetaRegion + META_REGION_HEADER; + m_DataRegionPtr = m_DataRegion + DATA_REGION_HEADER; } void CRehldsFlightRecorder::InitHeadersContent() { @@ -100,8 +100,6 @@ void CRehldsFlightRecorder::StartMessage(uint16 msg, bool entrance) { MoveToStart(); } - - m_pRecorderState->curMessage = msg; m_pRecorderState->lastMsgBeginPos = m_pRecorderState->wpos; *(uint16*)(m_DataRegionPtr + m_pRecorderState->wpos) = msg; @@ -222,3 +220,17 @@ uint16 CRehldsFlightRecorder::RegisterMessage(const char* module, const char *me return msgId; } + +void CRehldsFlightRecorder::dump(const char* fname) { + FILE* fl = fopen(fname, "wb"); + if (fl == NULL) { + Con_Printf("Failed to write Flight Recorder dump: could not open '%s' for writing\n", fname); + return; + } + + fwrite(m_MetaRegion, META_REGION_SIZE, 1, fl); + fwrite(m_DataRegion, DATA_REGION_SIZE, 1, fl); + fclose(fl); + + Con_Printf("Written flightrecorder dump to '%s'\n", fname); +} diff --git a/rehlds/rehlds/FlightRecorderImpl.h b/rehlds/rehlds/FlightRecorderImpl.h index ec9aea4..140f2bb 100644 --- a/rehlds/rehlds/FlightRecorderImpl.h +++ b/rehlds/rehlds/FlightRecorderImpl.h @@ -45,16 +45,23 @@ private: struct meta_header { unsigned int version; + unsigned int regionSize; + unsigned int headerCrc32; unsigned int numMessages; unsigned int metaRegionPos; }; struct data_header { unsigned int version; + unsigned int regionSize; + unsigned int headerCrc32; unsigned int prevItrLastPos; }; #pragma pack(pop) + uint8* m_MetaRegion; + uint8* m_DataRegion; + uint8* m_MetaRegionPtr; uint8* m_DataRegionPtr; meta_header* m_pMetaHeader; @@ -84,6 +91,7 @@ private: public: CRehldsFlightRecorder(); + void dump(const char* fname); virtual void StartMessage(uint16 msg, bool entrance); virtual void EndMessage(uint16 msg, bool entrance); diff --git a/rehlds/rehlds/flight_recorder.cpp b/rehlds/rehlds/flight_recorder.cpp index ac7ee71..6c7b322 100644 --- a/rehlds/rehlds/flight_recorder.cpp +++ b/rehlds/rehlds/flight_recorder.cpp @@ -19,13 +19,34 @@ CRehldsFlightRecorder* g_FlightRecorder; +void FR_Init() { + g_FlightRecorder = new CRehldsFlightRecorder(); +} + +#ifdef REHLDS_FLIGHT_REC + uint16 g_FRMsg_Frame; uint16 g_FRMsg_FreeEntPrivateData; uint16 g_FRMsg_AllocEntPrivateData; +cvar_t rehlds_flrec_frame = { "rehlds_flrec_frame", "1", 0, 1.0f, NULL }; +cvar_t rehlds_flrec_pvdata = { "rehlds_flrec_privdata", "1", 0, 1.0f, NULL }; -void FR_Init() { - g_FlightRecorder = new CRehldsFlightRecorder(); +void FR_Dump_f() { + const char* fname = "rehlds_flightrec.bin"; + if (Cmd_Argc() == 1) { + fname = Cmd_Argv(0); + } else if (Cmd_Argc() > 1) { + Con_Printf("usage: rehlds_flrec_dump < filename >\n"); + } + + g_FlightRecorder->dump(fname); +} + +void FR_Rehlds_Init() { + Cvar_RegisterVariable(&rehlds_flrec_frame); + Cvar_RegisterVariable(&rehlds_flrec_pvdata); + Cmd_AddCommand("rehlds_flrec_dump", &FR_Dump_f); g_FRMsg_Frame = g_FlightRecorder->RegisterMessage("rehlds", "Frame", 1, true); g_FRMsg_FreeEntPrivateData = g_FlightRecorder->RegisterMessage("rehlds", "FreeEntPrivateData", 1, false); @@ -54,3 +75,5 @@ void FR_FreeEntPrivateData(void* data) { g_FlightRecorder->WriteUInt32((size_t)data); g_FlightRecorder->EndMessage(g_FRMsg_FreeEntPrivateData, true); } + +#endif //REHLDS_FLIGHT_REC diff --git a/rehlds/rehlds/flight_recorder.h b/rehlds/rehlds/flight_recorder.h index 5ee2c12..e7ff49e 100644 --- a/rehlds/rehlds/flight_recorder.h +++ b/rehlds/rehlds/flight_recorder.h @@ -21,13 +21,24 @@ extern CRehldsFlightRecorder* g_FlightRecorder; +extern void FR_Init(); + +#ifdef REHLDS_FLIGHT_REC + +extern cvar_t rehlds_flrec_frame; +extern cvar_t rehlds_flrec_pvdata; + extern uint16 g_FRMsg_Frame; extern uint16 g_FRMsg_FreeEntPrivateData; extern uint16 g_FRMsg_AllocEntPrivateData; -extern void FR_Init(); +extern void FR_Dump_f(); +extern void FR_Rehlds_Init(); + extern void FR_StartFrame(); extern void FR_EndFrame(); extern void FR_FreeEntPrivateData(void* data); extern void FR_AllocEntPrivateData(void* res); + +#endif //REHLDS_FLIGHT_REC diff --git a/settings.gradle b/settings.gradle index 9e17208..0da4d36 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,3 +2,4 @@ rootProject.name = 'rehlds' include 'dep/cppunitlite' include 'dep/bzip2' include 'rehlds' +include 'flightrec/decoder_api', 'flightrec/decoder'