WIP SVC_CreateStringTable data parsing
This commit is contained in:
parent
a416145e27
commit
afad200209
@ -5,6 +5,93 @@
|
|||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
|
|
||||||
|
// #define WIP_STRINGTABLE
|
||||||
|
|
||||||
|
#ifdef WIP_STRINGTABLE
|
||||||
|
#include "sourcesdk/common.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define SUBSTRING_BITS 5
|
||||||
|
struct StringHistoryEntry
|
||||||
|
{
|
||||||
|
char string[(1 << SUBSTRING_BITS)];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void StringTable_BitRead(NetHandlers::BitRead& bitbuf, SourceGameContext& context, NetMsg::SVC_CreateStringTable* data)
|
||||||
|
{
|
||||||
|
const size_t numEncodeBits = math::log2(data->maxEntries);
|
||||||
|
std::vector<StringHistoryEntry> history;
|
||||||
|
int lastEntry = -1;
|
||||||
|
for (uint i = 0; i < data->numEntries; ++i)
|
||||||
|
{
|
||||||
|
int entryIndex = lastEntry + 1;
|
||||||
|
|
||||||
|
if (bitbuf.ReadOneBit() == 0)
|
||||||
|
{
|
||||||
|
entryIndex = bitbuf.ReadUBitLong(numEncodeBits);
|
||||||
|
}
|
||||||
|
lastEntry = entryIndex;
|
||||||
|
|
||||||
|
const char *pEntry = NULL;
|
||||||
|
char entry[1024];
|
||||||
|
char substr[1024];
|
||||||
|
if (bitbuf.ReadOneBit() != 0)
|
||||||
|
{
|
||||||
|
bool substringcheck = bitbuf.ReadOneBit() != 0;
|
||||||
|
if (substringcheck)
|
||||||
|
{
|
||||||
|
int index = bitbuf.ReadUBitLong(5);
|
||||||
|
int bytestocopy = bitbuf.ReadUBitLong(SUBSTRING_BITS);
|
||||||
|
strncpy(entry, history.at(index).string, bytestocopy + 1);
|
||||||
|
entry[bytestocopy + 1] = '\0';
|
||||||
|
bitbuf.ReadString(substr, sizeof(substr));
|
||||||
|
strncat(entry, substr, sizeof(entry));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitbuf.ReadString(entry, sizeof(entry));
|
||||||
|
}
|
||||||
|
pEntry = entry;
|
||||||
|
printf("%s\n", pEntry);
|
||||||
|
}
|
||||||
|
const int MAX_USERDATA_BITS = 14;
|
||||||
|
unsigned char tempbuf[(1 << MAX_USERDATA_BITS)] = { 0 };
|
||||||
|
const void *pUserData = NULL;
|
||||||
|
int nBytes = 0;
|
||||||
|
if (bitbuf.ReadOneBit() != 0)
|
||||||
|
{
|
||||||
|
if (data->isUserDataFixedSize)
|
||||||
|
{
|
||||||
|
nBytes = data->userDataSize;
|
||||||
|
tempbuf[nBytes - 1] = 0;
|
||||||
|
bitbuf.ReadBits(tempbuf, data->userDataSizeBits);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nBytes = bitbuf.ReadUBitLong(MAX_USERDATA_BITS);
|
||||||
|
bitbuf.ReadBytes(tempbuf, nBytes);
|
||||||
|
}
|
||||||
|
pUserData = tempbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pEntry == NULL)
|
||||||
|
{
|
||||||
|
pEntry = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (history.size() > 31)
|
||||||
|
{
|
||||||
|
history.erase(history.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
StringHistoryEntry she;
|
||||||
|
strncpy(she.string, pEntry, sizeof(she.string));
|
||||||
|
history.emplace_back(she);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WIP_STRINGTABLE
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
bool SVC_CreateStringTable_BitRead_Internal(BitRead& bitbuf, SourceGameContext& context, NetMsg::SVC_CreateStringTable* data)
|
bool SVC_CreateStringTable_BitRead_Internal(BitRead& bitbuf, SourceGameContext& context, NetMsg::SVC_CreateStringTable* data)
|
||||||
@ -20,7 +107,9 @@ namespace NetHandlers
|
|||||||
}
|
}
|
||||||
bitbuf.ReadString(data->tableName, sizeof(data->tableName));
|
bitbuf.ReadString(data->tableName, sizeof(data->tableName));
|
||||||
data->maxEntries = bitbuf.ReadWord();
|
data->maxEntries = bitbuf.ReadWord();
|
||||||
data->numEntries = bitbuf.ReadUBitLong(math::log2(data->maxEntries) + 1);
|
|
||||||
|
const size_t numEncodeBits = math::log2(data->maxEntries);
|
||||||
|
data->numEntries = bitbuf.ReadUBitLong(numEncodeBits + 1);
|
||||||
if (context.protocol > 23)
|
if (context.protocol > 23)
|
||||||
{
|
{
|
||||||
data->dataLengthInBits = bitbuf.ReadVarInt32();
|
data->dataLengthInBits = bitbuf.ReadVarInt32();
|
||||||
@ -46,6 +135,28 @@ namespace NetHandlers
|
|||||||
}
|
}
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
||||||
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
||||||
|
|
||||||
|
#ifdef WIP_STRINGTABLE
|
||||||
|
if (data->compressedData)
|
||||||
|
{
|
||||||
|
bf_read bitbuf2(data->data.get(), data->dataLengthInBits);
|
||||||
|
const uint32_t decompressedNumBytes = bitbuf2.ReadUBitLong(32);
|
||||||
|
const uint32_t compressedNumBytes = bitbuf2.ReadUBitLong(32);
|
||||||
|
std::unique_ptr<uint8_t[]> compressedData(new uint8[compressedNumBytes]);
|
||||||
|
std::unique_ptr<uint8_t[]> uncompressedData(new uint8[decompressedNumBytes]);
|
||||||
|
bitbuf2.ReadBytes(compressedData.get(), compressedNumBytes);
|
||||||
|
|
||||||
|
uint32_t numWritten = COM_BufferToBufferDecompress(uncompressedData.get(), decompressedNumBytes, compressedData.get(), compressedNumBytes);
|
||||||
|
bitbuf2 = bf_read(uncompressedData.get(), decompressedNumBytes);
|
||||||
|
StringTable_BitRead(bitbuf2, context, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bf_read bitbuf2(data->data.get(), data->dataLengthInBits);
|
||||||
|
StringTable_BitRead(bitbuf2, context, data);
|
||||||
|
}
|
||||||
|
#endif // WIP_STRINGTABLE
|
||||||
|
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
72
external/sourcesdk/common.cpp
vendored
Normal file
72
external/sourcesdk/common.cpp
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
|
||||||
|
#include "sourcesdk/common.h"
|
||||||
|
#include "snappy/snappy.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const uint32 INVALID = static_cast<uint32>(-1);
|
||||||
|
static const uint32 LZSS_ID = BigLong(('L' << 24) | ('Z' << 16) | ('S' << 8) | ('S'));
|
||||||
|
static const uint32 SNAPPY_ID = BigLong(('S' << 24) | ('N' << 16) | ('A' << 8) | ('P'));
|
||||||
|
|
||||||
|
inline uint32_t U8ToU32(const uint8* from)
|
||||||
|
{
|
||||||
|
union U8ToU32
|
||||||
|
{
|
||||||
|
uint8 bytes[4];
|
||||||
|
uint32 dword;
|
||||||
|
};
|
||||||
|
return reinterpret_cast<const U8ToU32*>(from)->dword;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 COM_BufferToBufferDecompress(uint8* dest, uint32 destLen, const uint8* src, uint32 srcLen)
|
||||||
|
{
|
||||||
|
const uint32 uncompressedLen = COM_GetUncompressedSize(src, srcLen);
|
||||||
|
if (uncompressedLen == INVALID)
|
||||||
|
{
|
||||||
|
if (srcLen <= destLen)
|
||||||
|
{
|
||||||
|
memcpy(dest, src, srcLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (uncompressedLen <= destLen)
|
||||||
|
{
|
||||||
|
const uint32 id = U8ToU32(src);
|
||||||
|
if (id == LZSS_ID)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
else if (id == SNAPPY_ID)
|
||||||
|
{
|
||||||
|
snappy::RawUncompress(reinterpret_cast<const char*>(src + 4), srcLen - 4, reinterpret_cast<char*>(dest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (uncompressedLen != INVALID) ? uncompressedLen : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 COM_GetUncompressedSize(const uint8* data, uint32 numBytes)
|
||||||
|
{
|
||||||
|
size_t uncompressedLength = INVALID;
|
||||||
|
if (numBytes > 4)
|
||||||
|
{
|
||||||
|
const uint32 magic = U8ToU32(data);
|
||||||
|
if (numBytes >= 8 && magic == LZSS_ID)
|
||||||
|
{
|
||||||
|
return U8ToU32(data + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (magic == SNAPPY_ID)
|
||||||
|
{
|
||||||
|
snappy::GetUncompressedLength(reinterpret_cast<const char*>(data + 4), numBytes - 4, &uncompressedLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return static_cast<uint32>(uncompressedLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 COM_GetIdealDestinationCompressionBufferSize_Snappy(uint32 srcLen)
|
||||||
|
{
|
||||||
|
return snappy::MaxCompressedLength(srcLen) + sizeof(uint32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*uint32 COM_CompressBuffer_Snappy(const uint8* src, uint32 srcLen, uint8* dest, uint32 destLen)
|
||||||
|
{
|
||||||
|
return COM_GetIdealDestinationCompressionBufferSize_Snappy(srcLen);
|
||||||
|
}*/
|
8
external/sourcesdk/include/sourcesdk/common.h
vendored
Normal file
8
external/sourcesdk/include/sourcesdk/common.h
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
#include "valve_support.h"
|
||||||
|
|
||||||
|
uint32 COM_BufferToBufferDecompress(uint8* dest, uint32 destLen, const uint8* src, uint32 srcLen);
|
||||||
|
uint32 COM_GetUncompressedSize(const uint8* data, uint32 numBytes);
|
||||||
|
|
||||||
|
uint32 COM_GetIdealDestinationCompressionBufferSize_Snappy(uint32 srcLen);
|
||||||
|
uint32 COM_CompressBuffer_Snappy(const uint8* src, uint32 srcLen, uint8* dest, uint32 destLen);
|
@ -59,17 +59,6 @@ inline bool is_little_endian()
|
|||||||
#define NORMAL_DENOMINATOR ( (1<<(NORMAL_FRACTIONAL_BITS)) - 1 )
|
#define NORMAL_DENOMINATOR ( (1<<(NORMAL_FRACTIONAL_BITS)) - 1 )
|
||||||
#define NORMAL_RESOLUTION (1.0/(NORMAL_DENOMINATOR))
|
#define NORMAL_RESOLUTION (1.0/(NORMAL_DENOMINATOR))
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T DWordSwapC( T dw )
|
|
||||||
{
|
|
||||||
uint32 temp;
|
|
||||||
temp = *((uint32 *)&dw) >> 24;
|
|
||||||
temp |= ((*((uint32 *)&dw) & 0x00FF0000) >> 8);
|
|
||||||
temp |= ((*((uint32 *)&dw) & 0x0000FF00) << 8);
|
|
||||||
temp |= ((*((uint32 *)&dw) & 0x000000FF) << 24);
|
|
||||||
return *((T*)&temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined( _MSC_VER ) && !defined( PLATFORM_WINDOWS_PC64 )
|
#if defined( _MSC_VER ) && !defined( PLATFORM_WINDOWS_PC64 )
|
||||||
#define DWordSwap DWordSwapAsm
|
#define DWordSwap DWordSwapAsm
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
@ -85,7 +74,7 @@ inline T DWordSwapC( T dw )
|
|||||||
}
|
}
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#else
|
#else
|
||||||
#define DWordSwap DWordSwapC
|
#error write the 64 bit swaps
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline unsigned long LoadLittleDWord(const unsigned long *base, unsigned int dwordIndex)
|
inline unsigned long LoadLittleDWord(const unsigned long *base, unsigned int dwordIndex)
|
||||||
@ -114,6 +103,11 @@ inline void LittleFloat(float* pOut, float* pIn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline long BigLong(long val)
|
||||||
|
{
|
||||||
|
return is_little_endian() ? DWordSwap(val) : val;
|
||||||
|
}
|
||||||
|
|
||||||
#define BITS_PER_INT 32
|
#define BITS_PER_INT 32
|
||||||
|
|
||||||
inline int GetBitForBitnum( int bitNum )
|
inline int GetBitForBitnum( int bitNum )
|
||||||
|
Loading…
Reference in New Issue
Block a user