change pretty much everything so it does what I want :^)
This commit is contained in:
parent
73ba4f105e
commit
36a3225a2b
20
.vscode/c_cpp_properties.json
vendored
Normal file
20
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"/usr/include/opus",
|
||||||
|
"${workspaceFolder}/external/sourcesdk/include",
|
||||||
|
"${workspaceFolder}/external/celt-e18de77/include",
|
||||||
|
"${workspaceFolder}/external/SILK_SDK_SRC_FLP_v1.0.9/interface",
|
||||||
|
"${workspaceFolder}/external/snappy-1.1.9",
|
||||||
|
"${workspaceFolder}/demboyz"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/clang",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"intelliSenseMode": "linux-clang-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
2066
demboyz/base/CRC.h
Normal file
2066
demboyz/base/CRC.h
Normal file
File diff suppressed because it is too large
Load Diff
25447
demboyz/base/json.hpp
Normal file
25447
demboyz/base/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,470 +0,0 @@
|
|||||||
|
|
||||||
#include "jsonfile.h"
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#define CBASE64_IMPLEMENTATION
|
|
||||||
#include "cbase64/cbase64.h"
|
|
||||||
|
|
||||||
#define RIGHT_TO_LEFT_BITS
|
|
||||||
|
|
||||||
namespace base
|
|
||||||
{
|
|
||||||
JsonWriterFile::JsonWriterFile(FILE* fp, char* buffer, std::size_t length):
|
|
||||||
m_fileStream(fp, buffer, length),
|
|
||||||
m_writer(m_fileStream),
|
|
||||||
m_fp(fp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonWriterFile::~JsonWriterFile()
|
|
||||||
{
|
|
||||||
Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* JsonWriterFile::GetFp() const
|
|
||||||
{
|
|
||||||
return m_fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::Flush()
|
|
||||||
{
|
|
||||||
m_fileStream.Flush();
|
|
||||||
fflush(m_fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::Reset()
|
|
||||||
{
|
|
||||||
m_writer.Reset(m_fileStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonWriterFile::IsComplete() const
|
|
||||||
{
|
|
||||||
return m_writer.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::StartObject(const char* name /*= nullptr*/)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
writer.String(name);
|
|
||||||
}
|
|
||||||
writer.StartObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::EndObject()
|
|
||||||
{
|
|
||||||
m_writer.EndObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::StartArray(const char* name /*= nullptr*/)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
writer.String(name);
|
|
||||||
}
|
|
||||||
writer.StartArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::EndArray()
|
|
||||||
{
|
|
||||||
m_writer.EndArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteNull(const char* name)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.Null();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteBool(const char* name, bool value)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.Bool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteChar(const char* name, char value)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
|
|
||||||
char temp[2] = { value, '\0' };
|
|
||||||
writer.String(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteInt32(const char* name, std::int32_t value)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.Int(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteInt32(const char* name, std::int32_t value, bool writeCondition)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
if (writeCondition)
|
|
||||||
{
|
|
||||||
writer.Int(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
writer.Null();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteInt64(const char* name, std::int64_t value)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.Int64(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteUInt32(const char* name, std::uint32_t value)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.Uint(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteUInt32(const char* name, std::uint32_t value, bool writeCondition)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
if (writeCondition)
|
|
||||||
{
|
|
||||||
writer.Uint(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
writer.Null();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteUint64(const char* name, std::uint64_t value)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.Uint64(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteString(const char* name, const char* value)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.String(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteString(const char* name, const char* value, std::uint32_t length)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.String(value, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteString(const char* name, const std::string& value)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.String(value.c_str(), value.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteFloat(const char* name, const double value)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
writer.Double(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteBits(const char* name, const unsigned char* data, std::size_t numBits)
|
|
||||||
{
|
|
||||||
auto& writer = m_writer;
|
|
||||||
writer.String(name);
|
|
||||||
|
|
||||||
cbase64_encodestate state;
|
|
||||||
cbase64_init_encodestate(&state);
|
|
||||||
|
|
||||||
const std::size_t numBytes = ((numBits + 7) >> 3);
|
|
||||||
|
|
||||||
char* const encoded = (char*)malloc(cbase64_calc_encoded_length(numBytes));
|
|
||||||
char* encodedCurOut = encoded;
|
|
||||||
|
|
||||||
const std::size_t numBytesWithoutBits = (numBits >> 3);
|
|
||||||
const std::size_t numTrailingBits = (numBits & 7);
|
|
||||||
|
|
||||||
encodedCurOut += cbase64_encode_block(data, numBytesWithoutBits, encodedCurOut, &state);
|
|
||||||
if (numTrailingBits > 0)
|
|
||||||
{
|
|
||||||
#ifdef LEFT_TO_RIGHT_BITS
|
|
||||||
const unsigned char lastByteClean = data[numBytesWithoutBits] & (0xFF >> numTrailingBits);
|
|
||||||
#else // RIGHT_TO_LEFT_BITS
|
|
||||||
const unsigned char lastByteClean = data[numBytesWithoutBits] & ~(0xFF << numTrailingBits);
|
|
||||||
#endif
|
|
||||||
encodedCurOut += cbase64_encode_block(&lastByteClean, 1, encodedCurOut, &state);
|
|
||||||
}
|
|
||||||
encodedCurOut += cbase64_encode_blockend(encodedCurOut, &state);
|
|
||||||
|
|
||||||
writer.String(encoded, encodedCurOut - encoded);
|
|
||||||
free(encoded);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriterFile::WriteBytes(const char* name, const unsigned char* data, std::size_t numBytes)
|
|
||||||
{
|
|
||||||
JsonWriterFile::WriteBits(name, data, numBytes * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderObject::JsonReaderIterator::JsonReaderIterator(JsonValue* value, bool& hasReadError):
|
|
||||||
m_value(value),
|
|
||||||
m_hasReadError(hasReadError)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderObject JsonReaderIterator::operator*() const
|
|
||||||
{
|
|
||||||
return JsonReaderObject(*m_value, m_hasReadError);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderIterator& JsonReaderIterator::operator++()
|
|
||||||
{
|
|
||||||
++m_value;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonReaderIterator::operator==(const JsonReaderIterator& other) const
|
|
||||||
{
|
|
||||||
return m_value == other.m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonReaderIterator::operator!=(const JsonReaderIterator& other) const
|
|
||||||
{
|
|
||||||
return m_value != other.m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderObject::JsonReaderArray::JsonReaderArray(JsonValue& value, bool& parseError):
|
|
||||||
m_value(value),
|
|
||||||
m_hasReadError(parseError)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonReaderArray::HasReadError() const
|
|
||||||
{
|
|
||||||
return m_hasReadError;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t JsonReaderArray::size() const
|
|
||||||
{
|
|
||||||
return m_value.Size();
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderIterator JsonReaderArray::begin()
|
|
||||||
{
|
|
||||||
return JsonReaderIterator(m_value.Begin(), m_hasReadError);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderIterator JsonReaderArray::end()
|
|
||||||
{
|
|
||||||
return JsonReaderIterator(m_value.End(), m_hasReadError);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderObject::JsonReaderObject(JsonValue& value, bool& parseError):
|
|
||||||
m_value(value),
|
|
||||||
m_hasReadError(parseError)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonReaderObject::HasReadError() const
|
|
||||||
{
|
|
||||||
return m_hasReadError;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderObject JsonReaderObject::ReadObject(const char* name) const
|
|
||||||
{
|
|
||||||
JsonValue& value = m_value[name];
|
|
||||||
m_hasReadError |= !value.IsObject();
|
|
||||||
return JsonReaderObject(value, m_hasReadError);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderArray JsonReaderObject::ReadArray(const char* name) const
|
|
||||||
{
|
|
||||||
JsonValue& value = m_value[name];
|
|
||||||
m_hasReadError |= !value.IsArray();
|
|
||||||
return JsonReaderArray(value, m_hasReadError);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonReaderObject::ReadBool(const char* name)
|
|
||||||
{
|
|
||||||
const auto& val = m_value[name];
|
|
||||||
if (!val.IsBool())
|
|
||||||
{
|
|
||||||
m_hasReadError = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return val.GetBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
char JsonReaderObject::ReadChar(const char* name)
|
|
||||||
{
|
|
||||||
const auto& val = m_value[name];
|
|
||||||
if (!val.IsString() || val.GetStringLength() != 1)
|
|
||||||
{
|
|
||||||
m_hasReadError = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return *val.GetString();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::int32_t JsonReaderObject::ReadInt32(const char* name)
|
|
||||||
{
|
|
||||||
const auto& val = m_value[name];
|
|
||||||
if (!val.IsInt())
|
|
||||||
{
|
|
||||||
m_hasReadError = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return val.GetInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::int64_t JsonReaderObject::ReadInt64(const char* name)
|
|
||||||
{
|
|
||||||
const auto& val = m_value[name];
|
|
||||||
if (!val.IsInt64())
|
|
||||||
{
|
|
||||||
m_hasReadError = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return val.GetInt64();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint32_t JsonReaderObject::ReadUInt32(const char* name)
|
|
||||||
{
|
|
||||||
const auto& val = m_value[name];
|
|
||||||
if (!val.IsUint())
|
|
||||||
{
|
|
||||||
m_hasReadError = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return val.GetUint();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint64_t JsonReaderObject::ReadUint64(const char* name)
|
|
||||||
{
|
|
||||||
const auto& val = m_value[name];
|
|
||||||
if (!val.IsUint64())
|
|
||||||
{
|
|
||||||
m_hasReadError = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return val.GetUint64();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint32_t JsonReaderObject::ReadString(const char* name, char* dest, std::uint32_t maxLength)
|
|
||||||
{
|
|
||||||
const auto& val = m_value[name];
|
|
||||||
if (!val.IsString())
|
|
||||||
{
|
|
||||||
m_hasReadError = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
strncpy(dest, val.GetString(), maxLength - 1);
|
|
||||||
dest[maxLength - 1] = '\0';
|
|
||||||
return std::min(maxLength - 1, val.GetStringLength());
|
|
||||||
}
|
|
||||||
|
|
||||||
float JsonReaderObject::ReadFloat(const char* name)
|
|
||||||
{
|
|
||||||
const auto& val = m_value[name];
|
|
||||||
if (!val.IsDouble())
|
|
||||||
{
|
|
||||||
m_hasReadError = true;
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
return val.GetDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t JsonReaderObject::ReadBits(const char* name, unsigned char* dest, std::size_t numBits)
|
|
||||||
{
|
|
||||||
const auto& val = m_value[name];
|
|
||||||
if (!val.IsString())
|
|
||||||
{
|
|
||||||
m_hasReadError = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* const encodedBits = val.GetString();
|
|
||||||
const std::size_t numEncodedBytes = val.GetStringLength();
|
|
||||||
const std::size_t numDecodedBytes = cbase64_calc_decoded_length(encodedBits, numEncodedBytes);
|
|
||||||
if (!dest || (numDecodedBytes == 0))
|
|
||||||
{
|
|
||||||
return numDecodedBytes * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::size_t numBytes = ((numBits + 7) >> 3);
|
|
||||||
if ((numDecodedBytes == 0) || (numBytes < numDecodedBytes))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char* lastByte = &dest[numDecodedBytes - 1];
|
|
||||||
unsigned char restoreBits = *lastByte;
|
|
||||||
|
|
||||||
cbase64_decodestate state;
|
|
||||||
cbase64_init_decodestate(&state);
|
|
||||||
const size_t numWritten = cbase64_decode_block(encodedBits, numEncodedBytes, dest, &state);
|
|
||||||
assert(numWritten == numDecodedBytes);
|
|
||||||
|
|
||||||
const std::size_t numTrailingBits = (numBits & 7);
|
|
||||||
if (numTrailingBits > 0)
|
|
||||||
{
|
|
||||||
// clean up end of decoded, clean up start of restoreBits
|
|
||||||
// then combine
|
|
||||||
#ifdef LEFT_TO_RIGHT_BITS
|
|
||||||
*lastByte = (*lastByte & ~(0xFF >> numTrailingBits)) |
|
|
||||||
(restoreBits & (0xFF >> numTrailingBits));
|
|
||||||
#else // RIGHT_TO_LEFT_BITS
|
|
||||||
*lastByte = (*lastByte & ~(0xFF << numTrailingBits)) |
|
|
||||||
(restoreBits & (0xFF << numTrailingBits));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return numBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t JsonReaderObject::ReadBytes(const char* name, unsigned char* dest, std::size_t numBytes)
|
|
||||||
{
|
|
||||||
const std::size_t numBitsRead = ReadBits(name, dest, numBytes * 8);
|
|
||||||
assert((numBitsRead & 7) == 0);
|
|
||||||
return (numBitsRead / 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderFile::JsonReaderFile(FILE* fp, char* buffer, std::size_t length):
|
|
||||||
m_fileStream(fp, buffer, length),
|
|
||||||
m_document()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonReaderObject JsonReaderFile::ParseObject()
|
|
||||||
{
|
|
||||||
const int flags = rapidjson::kParseValidateEncodingFlag |
|
|
||||||
rapidjson::kParseStopWhenDoneFlag;
|
|
||||||
|
|
||||||
auto& document = m_document;
|
|
||||||
document.ParseStream<flags>(m_fileStream);
|
|
||||||
m_hasParseError = document.HasParseError();
|
|
||||||
m_hasReadError = false;
|
|
||||||
return JsonReaderObject(document, m_hasReadError);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonReaderFile::HasParseError() const
|
|
||||||
{
|
|
||||||
return m_hasParseError;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JsonReaderFile::HasReadError() const
|
|
||||||
{
|
|
||||||
return m_hasReadError;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,147 +0,0 @@
|
|||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <rapidjson/filewritestream.h>
|
|
||||||
#include <rapidjson/filereadstream.h>
|
|
||||||
#include <rapidjson/prettywriter.h>
|
|
||||||
#include <rapidjson/document.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace base
|
|
||||||
{
|
|
||||||
class JsonWriterFile
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
JsonWriterFile(FILE* fp, char* buffer, std::size_t length);
|
|
||||||
~JsonWriterFile();
|
|
||||||
|
|
||||||
FILE* GetFp() const;
|
|
||||||
void Flush();
|
|
||||||
void Reset();
|
|
||||||
bool IsComplete() const;
|
|
||||||
|
|
||||||
void StartObject(const char* name = nullptr);
|
|
||||||
void EndObject();
|
|
||||||
|
|
||||||
void StartArray(const char* name = nullptr);
|
|
||||||
void EndArray();
|
|
||||||
|
|
||||||
void WriteNull(const char* name);
|
|
||||||
void WriteBool(const char* name, bool value);
|
|
||||||
void WriteChar(const char* name, char value);
|
|
||||||
void WriteInt32(const char* name, std::int32_t value);
|
|
||||||
void WriteInt32(const char* name, std::int32_t value, bool writeCondition);
|
|
||||||
void WriteInt64(const char* name, std::int64_t value);
|
|
||||||
void WriteUInt32(const char* name, std::uint32_t value);
|
|
||||||
void WriteUInt32(const char* name, std::uint32_t value, bool writeCondition);
|
|
||||||
void WriteUint64(const char* name, std::uint64_t value);
|
|
||||||
void WriteString(const char* name, const char* value);
|
|
||||||
void WriteString(const char* name, const char* value, std::uint32_t length);
|
|
||||||
void WriteString(const char* name, const std::string& value);
|
|
||||||
void WriteFloat(const char* name, const double value);
|
|
||||||
|
|
||||||
void WriteBits(const char* name, const unsigned char* data, std::size_t numBits);
|
|
||||||
void WriteBytes(const char* name, const unsigned char* data, std::size_t numBytes);
|
|
||||||
|
|
||||||
private:
|
|
||||||
rapidjson::FileWriteStream m_fileStream;
|
|
||||||
rapidjson::PrettyWriter<rapidjson::FileWriteStream, rapidjson::ASCII<>> m_writer;
|
|
||||||
FILE* m_fp;
|
|
||||||
};
|
|
||||||
|
|
||||||
class JsonReaderObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using JsonValue = rapidjson::GenericValue<rapidjson::ASCII<>>;
|
|
||||||
|
|
||||||
class JsonReaderIterator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit JsonReaderIterator(JsonValue* value, bool& hasReadError);
|
|
||||||
|
|
||||||
JsonReaderObject operator*() const;
|
|
||||||
JsonReaderIterator& operator++();
|
|
||||||
bool operator==(const JsonReaderIterator& other) const;
|
|
||||||
bool operator!=(const JsonReaderIterator& other) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
JsonValue* m_value;
|
|
||||||
bool& m_hasReadError;
|
|
||||||
};
|
|
||||||
|
|
||||||
class JsonReaderArray
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit JsonReaderArray(JsonValue& value, bool& parseError);
|
|
||||||
|
|
||||||
bool HasReadError() const;
|
|
||||||
|
|
||||||
std::size_t size() const;
|
|
||||||
JsonReaderIterator begin();
|
|
||||||
JsonReaderIterator end();
|
|
||||||
|
|
||||||
template<typename Container, typename Fn>
|
|
||||||
void TransformTo(Container& c, Fn fn)
|
|
||||||
{
|
|
||||||
c.resize(m_value.Size());
|
|
||||||
std::size_t index = 0;
|
|
||||||
for (base::JsonReaderObject obj : *this)
|
|
||||||
{
|
|
||||||
fn(obj, c[index++]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
JsonValue& m_value;
|
|
||||||
bool& m_hasReadError;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit JsonReaderObject(JsonValue& value, bool& parseError);
|
|
||||||
|
|
||||||
bool HasReadError() const;
|
|
||||||
|
|
||||||
JsonReaderObject ReadObject(const char* name) const;
|
|
||||||
JsonReaderArray ReadArray(const char* name) const;
|
|
||||||
|
|
||||||
bool ReadBool(const char* name);
|
|
||||||
char ReadChar(const char* name);
|
|
||||||
std::int32_t ReadInt32(const char* name);
|
|
||||||
std::int64_t ReadInt64(const char* name);
|
|
||||||
std::uint32_t ReadUInt32(const char* name);
|
|
||||||
std::uint64_t ReadUint64(const char* name);
|
|
||||||
std::uint32_t ReadString(const char* name, char* dest, std::uint32_t maxLength);
|
|
||||||
//std::string ReadString(const char* name, std::uint32_t maxLength);
|
|
||||||
float ReadFloat(const char* name);
|
|
||||||
|
|
||||||
std::size_t ReadBits(const char* name, unsigned char* dest, std::size_t numBits);
|
|
||||||
std::size_t ReadBytes(const char* name, unsigned char* dest, std::size_t numBytes);
|
|
||||||
|
|
||||||
private:
|
|
||||||
JsonValue& m_value;
|
|
||||||
bool& m_hasReadError;
|
|
||||||
};
|
|
||||||
|
|
||||||
using JsonReaderIterator = JsonReaderObject::JsonReaderIterator;
|
|
||||||
using JsonReaderArray = JsonReaderObject::JsonReaderArray;
|
|
||||||
|
|
||||||
class JsonReaderFile
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
JsonReaderFile(FILE* fp, char* buffer, std::size_t length);
|
|
||||||
|
|
||||||
JsonReaderObject ParseObject();
|
|
||||||
|
|
||||||
bool HasParseError() const;
|
|
||||||
bool HasReadError() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
rapidjson::FileReadStream m_fileStream;
|
|
||||||
rapidjson::GenericDocument<rapidjson::ASCII<>> m_document;
|
|
||||||
bool m_hasParseError;
|
|
||||||
bool m_hasReadError;
|
|
||||||
};
|
|
||||||
}
|
|
457
demboyz/base/steamid.h
Normal file
457
demboyz/base/steamid.h
Normal file
@ -0,0 +1,457 @@
|
|||||||
|
/*!
|
||||||
|
* SteamID Parser
|
||||||
|
*
|
||||||
|
* Copyright 2014 Mukunda Johnson
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef _STEAMID_
|
||||||
|
#define _STEAMID_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
/** ---------------------------------------------------------------------------
|
||||||
|
* SteamID
|
||||||
|
*
|
||||||
|
* Contains a User Steam ID.
|
||||||
|
*
|
||||||
|
* @author Mukunda Johnson
|
||||||
|
*/
|
||||||
|
class SteamID {
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum class Formats {
|
||||||
|
AUTO = 0, // Auto-detect format --- this also supports
|
||||||
|
// other unlisted formats such as
|
||||||
|
// full profile URLs.
|
||||||
|
STEAMID32 = 1, // Classic STEAM_x:y:zzzzzz | x = 0/1
|
||||||
|
STEAMID64 = 2, // SteamID64: 7656119xxxxxxxxxx
|
||||||
|
STEAMID3 = 3, // SteamID3 format: [U:1:xxxxxx]
|
||||||
|
S32 = 4, // Raw 32-bit SIGNED format.
|
||||||
|
// this is a raw steamid index that overflows
|
||||||
|
// into negative bitspace.
|
||||||
|
// This is the format that SourceMod returns
|
||||||
|
// with GetSteamAccountID, and will always
|
||||||
|
// fit into a 32-bit signed variable. (e.g.
|
||||||
|
// a 32-bit PHP integer).
|
||||||
|
RAW = 5, // Raw index. like 64-bit minus the base value.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 64-bit type.
|
||||||
|
using bigint = long long;
|
||||||
|
using uint = unsigned int;
|
||||||
|
|
||||||
|
// base constant of 64-bit Steam IDs
|
||||||
|
static const bigint STEAMID64_BASE = 76561197960265728L;
|
||||||
|
|
||||||
|
// max allowed value. (sanity check)
|
||||||
|
// 2^36; update this in approx 2,400,000 years
|
||||||
|
static const bigint MAX_VALUE = 68719476736L;
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Parse a Steam ID.
|
||||||
|
*
|
||||||
|
* @param input Input to parse.
|
||||||
|
*
|
||||||
|
* @param format Input formatting, see Format constants.
|
||||||
|
* Defaults to Format::AUTO which detects the format.
|
||||||
|
*
|
||||||
|
* @param detect_raw Detect and parse RAW values. (only used with
|
||||||
|
* Format::AUTO. e.g "123" will resolve to the
|
||||||
|
* SteamID with the raw value 123.
|
||||||
|
* Default option set with ParseRawDefault.
|
||||||
|
*
|
||||||
|
* @returns SteamID instance or an empty SteamID if the parsing fails.
|
||||||
|
*/
|
||||||
|
static SteamID Parse( const std::string &input,
|
||||||
|
Formats format = Formats::AUTO,
|
||||||
|
int detect_raw = ParseRawDefault(-1) ) {
|
||||||
|
|
||||||
|
if( input.empty() ) return SteamID(); // no input...
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch( format ) {
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
case Formats::STEAMID32: {
|
||||||
|
|
||||||
|
// regex is slow as fuck for some reason.
|
||||||
|
if( input.size() < 11 || input[0] != 'S' || input[1] != 'T'
|
||||||
|
|| input[2] != 'E' || input[3] != 'A' || input[4] != 'M'
|
||||||
|
|| input[5] != '_' || !Is01(input,6) || input[7] != ':'
|
||||||
|
|| !Is01(input,8) || input[9] != ':' ) return SteamID();
|
||||||
|
|
||||||
|
// STEAM_X:Y:Z'
|
||||||
|
// static const std::regex r(
|
||||||
|
// R"--(^STEAM_[0-1]:[0-1]:[0-9]+$)--",
|
||||||
|
// rc::icase | rc::optimize );
|
||||||
|
//
|
||||||
|
// if( !std::regex_match( input, r ) ) return SteamID();
|
||||||
|
|
||||||
|
bigint z = std::stoll( input.substr( 10 ) );
|
||||||
|
z = (z << 1) + (input[8] - '0');
|
||||||
|
|
||||||
|
SteamID result(z);
|
||||||
|
//result.Cache( Format::STEAMID32, input );
|
||||||
|
return result;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
} case Formats::STEAMID64: {
|
||||||
|
|
||||||
|
// allow digits only
|
||||||
|
if( !IsDigits( input ) ) return SteamID();
|
||||||
|
|
||||||
|
// convert to raw (subtract base)
|
||||||
|
SteamID result( std::stoll( input ) - STEAMID64_BASE );
|
||||||
|
//result.Cache( Format::STEAMID64, input );
|
||||||
|
return result;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
} case Formats::STEAMID3: {
|
||||||
|
|
||||||
|
// [U:1:xxxxxx]
|
||||||
|
if( input.size() < 7 || input[0] != '[' || input[1] != 'U'
|
||||||
|
|| input[2] != ':' || input[3] != '1' || input[4] != ':'
|
||||||
|
|| input[input.size()-1] != ']'
|
||||||
|
|| !IsDigits( input, 5, input.size() - 1 - 5 ) ) {
|
||||||
|
|
||||||
|
return SteamID();
|
||||||
|
}
|
||||||
|
|
||||||
|
// slow.
|
||||||
|
// static const std::regex r( R"--(^\[U:1:[0-9]+\]$)--",
|
||||||
|
// rc::optimize );
|
||||||
|
// if( !std::regex_match( input, r ) ) return SteamID();
|
||||||
|
|
||||||
|
SteamID result( std::stoll(
|
||||||
|
input.substr( 5, input.size() - 1 - 5 )));
|
||||||
|
|
||||||
|
//result.Cache( Format::STEAMID3, input );
|
||||||
|
return result;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
} case Formats::S32: {
|
||||||
|
|
||||||
|
// signed digits
|
||||||
|
if( !IsDigits( input, input[0] == '-' ? 1:0 ) ) {
|
||||||
|
return SteamID();
|
||||||
|
}
|
||||||
|
|
||||||
|
bigint a = std::stoll( input );
|
||||||
|
if( a < 0 ) a += 4294967296L;
|
||||||
|
|
||||||
|
SteamID result( a );
|
||||||
|
//result.Cache( Format::S32, input );
|
||||||
|
return result;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------
|
||||||
|
} case Formats::RAW: {
|
||||||
|
|
||||||
|
// validate digits only
|
||||||
|
if( !IsDigits( input ) ) return SteamID();
|
||||||
|
|
||||||
|
return SteamID( std::stoll( input ));
|
||||||
|
}
|
||||||
|
|
||||||
|
case Formats::AUTO: {
|
||||||
|
break;
|
||||||
|
}}
|
||||||
|
} catch( std::out_of_range& ) {
|
||||||
|
|
||||||
|
// integer conversion out of range...
|
||||||
|
return SteamID();
|
||||||
|
}
|
||||||
|
// Auto detect format:
|
||||||
|
|
||||||
|
std::string cleaned = TrimString(input);
|
||||||
|
SteamID result;
|
||||||
|
result = Parse( cleaned, Formats::STEAMID32 );
|
||||||
|
if( *result ) return result;
|
||||||
|
result = Parse( cleaned, Formats::STEAMID64 );
|
||||||
|
if( *result ) return result;
|
||||||
|
result = Parse( cleaned, Formats::STEAMID3 );
|
||||||
|
if( *result ) return result;
|
||||||
|
|
||||||
|
result = TryConvertProfileURL( cleaned );
|
||||||
|
if( *result ) return result;
|
||||||
|
|
||||||
|
// static const std::regex r_url(
|
||||||
|
// R"--(^(?:https?:\/\/)?(?:www.)?steamcommunity.com\/profiles\/([0-9]+)$)--",
|
||||||
|
// rc::icase | rc::optimize );
|
||||||
|
|
||||||
|
// std::smatch matches;
|
||||||
|
// if( std::regex_match( cleaned, matches, r_url ) ) {
|
||||||
|
// result = Parse( matches[1], Formats::STEAMID64 );
|
||||||
|
// if( *result ) return result;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if( detect_raw ) {
|
||||||
|
result = Parse( input, Formats::S32 );
|
||||||
|
if( *result ) return result;
|
||||||
|
result = Parse( input, Formats::RAW );
|
||||||
|
if( *result ) return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unknown stem
|
||||||
|
return SteamID();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Format this SteamID to a string.
|
||||||
|
*
|
||||||
|
* @param format Output format. See Format constants.
|
||||||
|
* @returns Formatted Steam ID, or an empty string if an invalid
|
||||||
|
* format is given or the desired format cannot
|
||||||
|
* contain the SteamID.
|
||||||
|
*/
|
||||||
|
std::string Format( Formats format ) const {
|
||||||
|
|
||||||
|
switch( format ) {
|
||||||
|
case Formats::STEAMID32: {
|
||||||
|
bigint z = m_value >> 1;
|
||||||
|
int y = m_value & 1;
|
||||||
|
return std::string("STEAM_1:") + std::to_string(y)
|
||||||
|
+ ":" + std::to_string(z);
|
||||||
|
|
||||||
|
} case Formats::STEAMID64: {
|
||||||
|
return std::to_string( m_value + STEAMID64_BASE );
|
||||||
|
|
||||||
|
} case Formats::STEAMID3: {
|
||||||
|
return std::string( "[U:1:" ) +
|
||||||
|
std::to_string(m_value) + ']';
|
||||||
|
|
||||||
|
} case Formats::S32: {
|
||||||
|
if( m_value >= 4294967296L ) {
|
||||||
|
return ""; // too large for s32.
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_value >= 2147483648L ) {
|
||||||
|
return std::to_string( m_value - 4294967296L );
|
||||||
|
}
|
||||||
|
|
||||||
|
// -->
|
||||||
|
} case Formats::RAW: {
|
||||||
|
return std::to_string( m_value );
|
||||||
|
}
|
||||||
|
|
||||||
|
case Formats::AUTO: {
|
||||||
|
break;
|
||||||
|
}}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Set the default setting for detect_raw for Parse()
|
||||||
|
*
|
||||||
|
* @param detect_raw Default detect_raw value, see Parse function.
|
||||||
|
* @returns Current or updated setting.
|
||||||
|
*/
|
||||||
|
static bool ParseRawDefault( int detect_raw = -1 ) {
|
||||||
|
static int option = false;
|
||||||
|
if( detect_raw == -1 ) return !!option;
|
||||||
|
option = !!detect_raw;
|
||||||
|
return !!option;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Overload for Format.
|
||||||
|
*/
|
||||||
|
std::string operator[]( Formats format ) const {
|
||||||
|
return Format( format );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Get raw value. 0 = empty
|
||||||
|
*/
|
||||||
|
bigint Value() const {
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Get raw value. 0 = empty
|
||||||
|
*/
|
||||||
|
bigint operator*() const {
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Returns true if this SteamID is empty/invalid.
|
||||||
|
*/
|
||||||
|
bool operator!() {
|
||||||
|
return m_value == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Returns true if this SteamID is empty/invalid.
|
||||||
|
*/
|
||||||
|
bool Empty() const {
|
||||||
|
return m_value == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Get 64-bit Steam ID.
|
||||||
|
*/
|
||||||
|
bigint To64() {
|
||||||
|
return m_value + STEAMID64_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Get raw value, same as operator*.
|
||||||
|
*/
|
||||||
|
bigint ToRaw() {
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Get 32-bit value cast to signed.
|
||||||
|
*/
|
||||||
|
int ToS32() {
|
||||||
|
if( m_value > 0xFFFFFFFF ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (int)m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Parsing shortcut.
|
||||||
|
*/
|
||||||
|
SteamID( const std::string &input, Formats format = Formats::AUTO,
|
||||||
|
int detect_raw = ParseRawDefault() )
|
||||||
|
: SteamID( Parse( input, format, detect_raw )) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* Construct a Steam ID.
|
||||||
|
*
|
||||||
|
* @param raw RAW value of Steam ID.
|
||||||
|
*/
|
||||||
|
SteamID( bigint raw )
|
||||||
|
: m_value( (raw > 0 && raw <= MAX_VALUE) ? raw : 0 ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** -----------------------------------------------------------------------
|
||||||
|
* An empty steam id.
|
||||||
|
*/
|
||||||
|
SteamID() : m_value(0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
SteamID( const SteamID& o ) = default;
|
||||||
|
SteamID( SteamID&& o ) {
|
||||||
|
m_value = o.m_value;
|
||||||
|
}
|
||||||
|
SteamID& operator=( const SteamID& o ) = default;
|
||||||
|
SteamID& operator=( SteamID&& o ) {
|
||||||
|
m_value = o.m_value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bigint m_value; // RAW Steam ID value.
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static bool IsDigits( const std::string &str, size_t start = 0,
|
||||||
|
size_t length = 9000 ) {
|
||||||
|
|
||||||
|
for( size_t i = start; i != (start+length) && str[i]; i++ ) {
|
||||||
|
if( str[i] < '0' || str[i] > '9' ) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static bool Is01( const std::string &str, size_t index ) {
|
||||||
|
return str[index] == '0' || str[index] == '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static std::string TrimString( const std::string &input ) {
|
||||||
|
|
||||||
|
int start = 0, end = (int)input.size()-1;
|
||||||
|
if( end < 0 ) return "";
|
||||||
|
|
||||||
|
while( std::isspace( input[start] )) {
|
||||||
|
start++;
|
||||||
|
if( start == (int)input.size() ) return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
while( std::isspace( input[end] )) {
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input.substr( start, 1+end-start );
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
static SteamID TryConvertProfileURL( std::string &str ) {
|
||||||
|
if( str[0] != 'h' && str[0] != 'w' && str[0] != 's' ) return SteamID();
|
||||||
|
|
||||||
|
int lastslash = str.find_last_of( '/' );
|
||||||
|
if( lastslash == (int)std::string::npos ) return SteamID();
|
||||||
|
if( lastslash == (int)str.size()-1 ) {
|
||||||
|
str.pop_back();
|
||||||
|
lastslash = str.find_last_of( '/' );
|
||||||
|
if( lastslash == (int)std::string::npos ) return SteamID();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( CheckProfilePrefix( str, lastslash ) ) {
|
||||||
|
return Parse( str.substr( lastslash+1 ) );
|
||||||
|
}
|
||||||
|
return SteamID();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckProfilePrefix( std::string &str, int end ) {
|
||||||
|
// possible prefixes:
|
||||||
|
// 0123456789012345678901234567890123456789
|
||||||
|
// https://www.steamcommunity.com/profiles/
|
||||||
|
// http://www.steamcommunity.com/profiles/
|
||||||
|
// https://steamcommunity.com/profiles/
|
||||||
|
// http://steamcommunity.com/profiles/
|
||||||
|
// www.steamcommunity.com/profiles/
|
||||||
|
// steamcommunity.com/profiles/
|
||||||
|
|
||||||
|
if( end == 39 ) {
|
||||||
|
return str.compare( 0, 1+end,
|
||||||
|
"https://www.steamcommunity.com/profiles/" ) == 0;
|
||||||
|
} else if( end == 38 ) {
|
||||||
|
return str.compare( 0, 1+end,
|
||||||
|
"http://www.steamcommunity.com/profiles/" ) == 0;
|
||||||
|
} else if( end == 35 ) {
|
||||||
|
return str.compare( 0, 1+end,
|
||||||
|
"https://steamcommunity.com/profiles/" ) == 0;
|
||||||
|
} else if( end == 34 ) {
|
||||||
|
return str.compare( 0, 1+end,
|
||||||
|
"http://steamcommunity.com/profiles/" ) == 0;
|
||||||
|
} else if( end == 31 ) {
|
||||||
|
return str.compare( 0, 1+end,
|
||||||
|
"www.steamcommunity.com/profiles/" ) == 0;
|
||||||
|
} else if( end == 27 ) {
|
||||||
|
return str.compare( 0, 1+end,
|
||||||
|
"steamcommunity.com/profiles/" ) == 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,76 +1,20 @@
|
|||||||
|
|
||||||
#include "io/idemowriter.h"
|
|
||||||
#include "io/demoreader.h"
|
#include "io/demoreader.h"
|
||||||
#include "json_checker/JSON_checker.h"
|
#include "game/sourcecontext.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <filesystem>
|
||||||
std::string GetExtension(const std::string& filename)
|
|
||||||
{
|
|
||||||
size_t index = filename.find_last_of(".");
|
|
||||||
if (index != std::string::npos)
|
|
||||||
{
|
|
||||||
return filename.substr(index + 1);
|
|
||||||
}
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class FileType
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Dem,
|
|
||||||
Json,
|
|
||||||
ConLog
|
|
||||||
};
|
|
||||||
|
|
||||||
FileType GetFileType(const std::string& filename)
|
|
||||||
{
|
|
||||||
std::string ext = GetExtension(filename);
|
|
||||||
if (ext == "dem")
|
|
||||||
{
|
|
||||||
return FileType::Dem;
|
|
||||||
}
|
|
||||||
if (ext == "json")
|
|
||||||
{
|
|
||||||
return FileType::Json;
|
|
||||||
}
|
|
||||||
if (ext == "con")
|
|
||||||
{
|
|
||||||
return FileType::ConLog;
|
|
||||||
}
|
|
||||||
return FileType::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(const int argc, const char* argv[])
|
int main(const int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
if (argc != 3)
|
if (argc != 2)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s <in>.dem/json <out>.dem/json/con\n", argv[0]);
|
fprintf(stderr, "Usage: %s <in>.dem\n", argv[0]);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string inputFile(argv[1]);
|
|
||||||
std::string outputFile(argv[2]);
|
|
||||||
if (inputFile == outputFile)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error: Input and output file cannot be the same!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileType inputType = GetFileType(inputFile);
|
|
||||||
FileType outputType = GetFileType(outputFile);
|
|
||||||
if (inputType == FileType::None)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error: Bad type for input file\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (outputType == FileType::None)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Error: Bad type for output file\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::filesystem::path inputFile(argv[1]);
|
||||||
FILE* inputFp = fopen(inputFile.c_str(), "rb");
|
FILE* inputFp = fopen(inputFile.c_str(), "rb");
|
||||||
if (!inputFp)
|
if (!inputFp)
|
||||||
{
|
{
|
||||||
@ -78,66 +22,18 @@ int main(const int argc, const char* argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* outputFp = fopen(outputFile.c_str(), "wb");
|
std::filesystem::path outputDir = inputFile.filename().replace_extension();
|
||||||
if (!outputFp)
|
std::filesystem::path outputDirVoice = outputDir.string() + "/voice";
|
||||||
{
|
std::filesystem::create_directory(outputDir);
|
||||||
fprintf(stderr, "Error: Could not open input file\n");
|
std::filesystem::create_directory(outputDirVoice);
|
||||||
fclose(inputFp);
|
|
||||||
|
SourceGameContext context = SourceGameContext(outputDir, outputDirVoice);
|
||||||
|
if (!context.init())
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
IDemoWriter* writer = nullptr;
|
bool error = DemoReader::ProcessDem(inputFp, &context);
|
||||||
if (outputType == FileType::Dem)
|
|
||||||
{
|
|
||||||
writer = IDemoWriter::CreateDemoWriter(outputFp);
|
|
||||||
}
|
|
||||||
else if (outputType == FileType::Json)
|
|
||||||
{
|
|
||||||
writer = IDemoWriter::CreateJsonWriter(outputFp);
|
|
||||||
}
|
|
||||||
else if (outputType == FileType::ConLog)
|
|
||||||
{
|
|
||||||
writer = IDemoWriter::CreateConLogWriter(outputFp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputType == FileType::Dem)
|
|
||||||
{
|
|
||||||
DemoReader::ProcessDem(inputFp, writer);
|
|
||||||
}
|
|
||||||
else if (inputType == FileType::Json)
|
|
||||||
{
|
|
||||||
DemoReader::ProcessJson(inputFp, writer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
IDemoWriter::FreeDemoWriter(writer);
|
|
||||||
|
|
||||||
fclose(inputFp);
|
fclose(inputFp);
|
||||||
fclose(outputFp);
|
|
||||||
|
|
||||||
/*if (outputType == FileType::Json)
|
return error;
|
||||||
{
|
|
||||||
FILE* outputFp = fopen(outputFile.c_str(), "rb");
|
|
||||||
JSON_checker jc = new_JSON_checker(20);
|
|
||||||
int next_char = 0;
|
|
||||||
while ((next_char = fgetc(outputFp)) > 0)
|
|
||||||
{
|
|
||||||
if (!JSON_checker_char(jc, next_char))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "JSON_checker_char: syntax error\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!JSON_checker_done(jc))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "JSON_checker_end: syntax error\n");
|
|
||||||
}
|
|
||||||
fclose(outputFp);
|
|
||||||
}*/
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "dem_consolecmd.h"
|
#include "dem_consolecmd.h"
|
||||||
#include "demofile/demofile.h"
|
#include "demofile/demofile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace DemHandlers
|
namespace DemHandlers
|
||||||
{
|
{
|
||||||
@ -12,31 +11,4 @@ namespace DemHandlers
|
|||||||
data->command.assign(command);
|
data->command.assign(command);
|
||||||
return demofile.IsOk();
|
return demofile.IsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dem_ConsoleCmd_FileWrite_Internal(FileWrite& demofile, DemMsg::Dem_ConsoleCmd* data)
|
|
||||||
{
|
|
||||||
const uint8_t* command = reinterpret_cast<const uint8_t*>(data->command.data());
|
|
||||||
demofile.WriteRawData(command, data->command.length() + 1);
|
|
||||||
return demofile.IsOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_ConsoleCmd_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_ConsoleCmd* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
|
|
||||||
char command[DemMsg::Dem_ConsoleCmd::COMMAND_MAX_LENGTH];
|
|
||||||
reader.ReadString("command", command, sizeof(command));
|
|
||||||
data->command.assign(command);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_ConsoleCmd_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_ConsoleCmd* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteString("command", data->command);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,38 +1,74 @@
|
|||||||
|
|
||||||
#include "dem_datatables.h"
|
#include "dem_datatables.h"
|
||||||
#include "demofile/demofile.h"
|
#include "demofile/demofile.h"
|
||||||
#include "demofile/demojson.h"
|
#include "sourcesdk/bitbuf.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace DemHandlers
|
namespace DemHandlers
|
||||||
{
|
{
|
||||||
bool Dem_DataTables_FileRead_Internal(FileRead& demofile, DemMsg::Dem_DataTables* data)
|
bool Dem_DataTables_FileRead_Internal(FileRead& demofile, DemMsg::Dem_DataTables* data)
|
||||||
{
|
{
|
||||||
data->data = demofile.ReadRawData(DemMsg::Dem_DataTables::DATA_MAX_LENGTH);
|
Array<uint8_t> buffer = demofile.ReadRawData(DemMsg::Dem_DataTables::DATA_MAX_LENGTH);
|
||||||
|
bf_read bitbuf(buffer.begin(), buffer.length());
|
||||||
|
|
||||||
|
char strBuf[1024];
|
||||||
|
while (bitbuf.ReadOneBit() != 0)
|
||||||
|
{
|
||||||
|
DemMsg::Dem_DataTables::SendTable sendTable;
|
||||||
|
|
||||||
|
sendTable.needsDecoder = bitbuf.ReadOneBit() != 0;
|
||||||
|
bitbuf.ReadString(strBuf, sizeof(strBuf));
|
||||||
|
sendTable.name.assign(strBuf);
|
||||||
|
|
||||||
|
sendTable.numProps = bitbuf.ReadUBitLong(PROPINFOBITS_NUMPROPS);
|
||||||
|
|
||||||
|
for (int i = 0; i < sendTable.numProps; i++)
|
||||||
|
{
|
||||||
|
DemMsg::Dem_DataTables::SendProp prop;
|
||||||
|
|
||||||
|
prop.type = bitbuf.ReadUBitLong(PROPINFOBITS_TYPE);
|
||||||
|
|
||||||
|
bitbuf.ReadString(strBuf, sizeof(strBuf));
|
||||||
|
prop.name.assign(strBuf);
|
||||||
|
|
||||||
|
prop.flags = bitbuf.ReadUBitLong(PROPINFOBITS_FLAGS); // demoprotocol 2: 11
|
||||||
|
|
||||||
|
if (prop.type == DPT_DataTable || prop.flags & SPROP_EXCLUDE)
|
||||||
|
{
|
||||||
|
bitbuf.ReadString(strBuf, sizeof(strBuf));
|
||||||
|
prop.exclude.assign(strBuf);
|
||||||
|
}
|
||||||
|
else if (prop.type == DPT_Array)
|
||||||
|
{
|
||||||
|
prop.elements = bitbuf.ReadUBitLong(PROPINFOBITS_NUMELEMENTS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prop.lowValue = bitbuf.ReadBitFloat();
|
||||||
|
prop.highValue = bitbuf.ReadBitFloat();
|
||||||
|
prop.bits = bitbuf.ReadUBitLong(PROPINFOBITS_NUMBITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendTable.props.push_back(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->sendtables.push_back(sendTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numClasses = bitbuf.ReadShort();
|
||||||
|
data->classes.reset(numClasses);
|
||||||
|
for (int i = 0; i < numClasses; i++)
|
||||||
|
{
|
||||||
|
int classID = bitbuf.ReadShort();
|
||||||
|
DemMsg::Dem_DataTables::DataClass &dataClass = data->classes[classID];
|
||||||
|
|
||||||
|
bitbuf.ReadString(strBuf, sizeof(strBuf));
|
||||||
|
dataClass.className.assign(strBuf);
|
||||||
|
|
||||||
|
bitbuf.ReadString(strBuf, sizeof(strBuf));
|
||||||
|
dataClass.datatableName.assign(strBuf);
|
||||||
|
}
|
||||||
|
|
||||||
return demofile.IsOk();
|
return demofile.IsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dem_DataTables_FileWrite_Internal(FileWrite& demofile, DemMsg::Dem_DataTables* data)
|
|
||||||
{
|
|
||||||
demofile.WriteRawData(data->data.begin(), data->data.length());
|
|
||||||
return demofile.IsOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_DataTables_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_DataTables* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
|
|
||||||
data->data.reset(reader.ReadBytes("data", nullptr, 0));
|
|
||||||
reader.ReadBytes("data", data->data.begin(), DemMsg::Dem_DataTables::DATA_MAX_LENGTH);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_DataTables_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_DataTables* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteBytes("data", data->data.begin(), data->data.length());
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,114 @@
|
|||||||
|
|
||||||
#include "demhandlers.h"
|
#include "demhandlers.h"
|
||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define PROPINFOBITS_NUMPROPS 10
|
||||||
|
#define PROPINFOBITS_NUMPROPS 10
|
||||||
|
#define PROPINFOBITS_TYPE 5
|
||||||
|
#define PROPINFOBITS_FLAGS SPROP_NUMFLAGBITS_NETWORKED
|
||||||
|
#define PROPINFOBITS_STRINGBUFFERLEN 10
|
||||||
|
#define PROPINFOBITS_NUMBITS 7
|
||||||
|
#define PROPINFOBITS_RIGHTSHIFT 6
|
||||||
|
#define PROPINFOBITS_NUMELEMENTS 10 // For arrays.
|
||||||
|
|
||||||
|
|
||||||
|
// SendProp::m_Flags.
|
||||||
|
#define SPROP_UNSIGNED (1<<0) // Unsigned integer data.
|
||||||
|
|
||||||
|
#define SPROP_COORD (1<<1) // If this is set, the float/vector is treated like a world coordinate.
|
||||||
|
// Note that the bit count is ignored in this case.
|
||||||
|
|
||||||
|
#define SPROP_NOSCALE (1<<2) // For floating point, don't scale into range, just take value as is.
|
||||||
|
|
||||||
|
#define SPROP_ROUNDDOWN (1<<3) // For floating point, limit high value to range minus one bit unit
|
||||||
|
|
||||||
|
#define SPROP_ROUNDUP (1<<4) // For floating point, limit low value to range minus one bit unit
|
||||||
|
|
||||||
|
#define SPROP_NORMAL (1<<5) // If this is set, the vector is treated like a normal (only valid for vectors)
|
||||||
|
|
||||||
|
#define SPROP_EXCLUDE (1<<6) // This is an exclude prop (not excludED, but it points at another prop to be excluded).
|
||||||
|
|
||||||
|
#define SPROP_XYZE (1<<7) // Use XYZ/Exponent encoding for vectors.
|
||||||
|
|
||||||
|
#define SPROP_INSIDEARRAY (1<<8) // This tells us that the property is inside an array, so it shouldn't be put into the
|
||||||
|
// flattened property list. Its array will point at it when it needs to.
|
||||||
|
|
||||||
|
#define SPROP_PROXY_ALWAYS_YES (1<<9) // Set for datatable props using one of the default datatable proxies like
|
||||||
|
// SendProxy_DataTableToDataTable that always send the data to all clients.
|
||||||
|
|
||||||
|
#define SPROP_CHANGES_OFTEN (1<<10) // this is an often changed field, moved to head of sendtable so it gets a small index
|
||||||
|
|
||||||
|
#define SPROP_IS_A_VECTOR_ELEM (1<<11) // Set automatically if SPROP_VECTORELEM is used.
|
||||||
|
|
||||||
|
#define SPROP_COLLAPSIBLE (1<<12) // Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer
|
||||||
|
// (ie: for all automatically-chained base classes).
|
||||||
|
// In this case, it can get rid of this SendPropDataTable altogether and spare the
|
||||||
|
// trouble of walking the hierarchy more than necessary.
|
||||||
|
|
||||||
|
#define SPROP_COORD_MP (1<<13) // Like SPROP_COORD, but special handling for multiplayer games
|
||||||
|
#define SPROP_COORD_MP_LOWPRECISION (1<<14) // Like SPROP_COORD, but special handling for multiplayer games where the fractional component only gets a 3 bits instead of 5
|
||||||
|
#define SPROP_COORD_MP_INTEGRAL (1<<15) // SPROP_COORD_MP, but coordinates are rounded to integral boundaries
|
||||||
|
|
||||||
|
#define SPROP_VARINT SPROP_NORMAL // reuse existing flag so we don't break demo. note you want to include SPROP_UNSIGNED if needed, its more efficient
|
||||||
|
|
||||||
|
#define SPROP_NUMFLAGBITS_NETWORKED 16
|
||||||
|
|
||||||
|
// This is server side only, it's used to mark properties whose SendProxy_* functions encode against gpGlobals->tickcount (the only ones that currently do this are
|
||||||
|
// m_flAnimTime and m_flSimulationTime. MODs shouldn't need to mess with this probably
|
||||||
|
#define SPROP_ENCODED_AGAINST_TICKCOUNT (1<<16)
|
||||||
|
|
||||||
|
// See SPROP_NUMFLAGBITS_NETWORKED for the ones which are networked
|
||||||
|
#define SPROP_NUMFLAGBITS 17
|
||||||
|
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DPT_Int=0,
|
||||||
|
DPT_Float,
|
||||||
|
DPT_Vector,
|
||||||
|
DPT_VectorXY,
|
||||||
|
DPT_String,
|
||||||
|
DPT_Array,
|
||||||
|
DPT_DataTable,
|
||||||
|
DPT_Int64,
|
||||||
|
DPT_NUMSendPropTypes
|
||||||
|
};
|
||||||
|
|
||||||
namespace DemMsg
|
namespace DemMsg
|
||||||
{
|
{
|
||||||
struct Dem_DataTables
|
struct Dem_DataTables
|
||||||
{
|
{
|
||||||
static const int DATA_MAX_LENGTH = 256 * 1024;
|
static const int DATA_MAX_LENGTH = 256 * 1024;
|
||||||
Array<uint8_t> data;
|
|
||||||
|
struct SendProp
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string exclude;
|
||||||
|
int type;
|
||||||
|
int flags;
|
||||||
|
int elements;
|
||||||
|
int lowValue;
|
||||||
|
int highValue;
|
||||||
|
int bits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SendTable
|
||||||
|
{
|
||||||
|
bool needsDecoder;
|
||||||
|
std::string name;
|
||||||
|
int numProps;
|
||||||
|
std::vector<SendProp> props;
|
||||||
|
};
|
||||||
|
std::vector<SendTable> sendtables;
|
||||||
|
|
||||||
|
struct DataClass
|
||||||
|
{
|
||||||
|
std::string className;
|
||||||
|
std::string datatableName;
|
||||||
|
};
|
||||||
|
Array<DataClass> classes;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "dem_packet.h"
|
#include "dem_packet.h"
|
||||||
#include "demofile/demofile.h"
|
#include "demofile/demofile.h"
|
||||||
#include "demofile/demojson.h"
|
|
||||||
#include "netmessages/nethandlers.h"
|
#include "netmessages/nethandlers.h"
|
||||||
|
|
||||||
namespace DemHandlers
|
namespace DemHandlers
|
||||||
@ -12,31 +11,4 @@ namespace DemHandlers
|
|||||||
demofile.ReadSequenceInfo(data->sequenceNum1, data->sequenceNum2);
|
demofile.ReadSequenceInfo(data->sequenceNum1, data->sequenceNum2);
|
||||||
return demofile.IsOk();
|
return demofile.IsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dem_Packet_FileWrite_Internal(FileWrite& demofile, DemMsg::Dem_Packet* data)
|
|
||||||
{
|
|
||||||
demofile.WriteCmdInfo(data->cmdInfo);
|
|
||||||
demofile.WriteSequenceInfo(data->sequenceNum1, data->sequenceNum2);
|
|
||||||
return demofile.IsOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_Packet_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_Packet* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
|
|
||||||
bool readError = DemoJsonReader::ReadCmdInfo(reader, data->cmdInfo);
|
|
||||||
readError |= DemoJsonReader::ReadSequenceInfo(reader, data->sequenceNum1, data->sequenceNum2);
|
|
||||||
return !readError && !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_Packet_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_Packet* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
DemoJsonWriter::WriteCmdInfo(jsonbuf, data->cmdInfo);
|
|
||||||
DemoJsonWriter::WriteSequenceInfo(jsonbuf, data->sequenceNum1, data->sequenceNum2);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,4 @@ namespace DemHandlers
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dem_Stop_FileWrite_Internal(FileWrite& demofile, DemMsg::Dem_Stop* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_Stop_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_Stop* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_Stop_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_Stop* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,13 @@
|
|||||||
#include "demofile/demofile.h"
|
#include "demofile/demofile.h"
|
||||||
#include "netmessages/netcontants.h"
|
#include "netmessages/netcontants.h"
|
||||||
#include "sourcesdk/bitbuf.h"
|
#include "sourcesdk/bitbuf.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
static void StringTableEntry_BitRead(bf_read& bitbuf, DemMsg::Dem_StringTables::StringTableEntry* data)
|
static void StringTableEntry_BitRead(bf_read& bitbuf, DemMsg::Dem_StringTables::StringTableEntry* data)
|
||||||
{
|
{
|
||||||
using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry;
|
using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry;
|
||||||
{
|
|
||||||
char entryName[StringTableEntry::ENTRYNAME_MAX_LENGTH];
|
char entryName[StringTableEntry::ENTRYNAME_MAX_LENGTH];
|
||||||
bitbuf.ReadString(entryName, sizeof(entryName));
|
bitbuf.ReadString(entryName, sizeof(entryName));
|
||||||
data->entryName.assign(entryName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bitbuf.ReadOneBit() != 0)
|
if (bitbuf.ReadOneBit() != 0)
|
||||||
{
|
{
|
||||||
@ -27,46 +23,14 @@ static void StringTableEntry_BitRead(bf_read& bitbuf, DemMsg::Dem_StringTables::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void StringTableEntry_BitWrite(bf_write& bitbuf, DemMsg::Dem_StringTables::StringTableEntry* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteString(data->entryName.c_str());
|
|
||||||
const int32_t numDataBytes = data->data.length();
|
|
||||||
|
|
||||||
bitbuf.WriteOneBit(numDataBytes > 0);
|
|
||||||
if (numDataBytes > 0)
|
|
||||||
{
|
|
||||||
bitbuf.WriteWord(numDataBytes);
|
|
||||||
bitbuf.WriteBytes(data->data.begin(), numDataBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StringTableEntry_JsonRead(base::JsonReaderObject& jsonbuf, DemMsg::Dem_StringTables::StringTableEntry* data)
|
|
||||||
{
|
|
||||||
using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry;
|
|
||||||
{
|
|
||||||
char entryName[StringTableEntry::ENTRYNAME_MAX_LENGTH];
|
|
||||||
jsonbuf.ReadString("name", entryName, sizeof(entryName));
|
|
||||||
data->entryName.assign(entryName);
|
|
||||||
}
|
|
||||||
data->data.reset(jsonbuf.ReadBytes("data", nullptr, 0));
|
|
||||||
jsonbuf.ReadBytes("data", data->data.begin(), data->data.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StringTableEntry_JsonWrite(DemHandlers::JsonWrite& jsonbuf, const DemMsg::Dem_StringTables::StringTableEntry* data)
|
|
||||||
{
|
|
||||||
jsonbuf.WriteString("name", data->entryName);
|
|
||||||
jsonbuf.WriteBytes("data", data->data.begin(), data->data.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StringTable_BitRead(bf_read& bitbuf, DemMsg::Dem_StringTables::StringTable* data)
|
static void StringTable_BitRead(bf_read& bitbuf, DemMsg::Dem_StringTables::StringTable* data)
|
||||||
{
|
{
|
||||||
using StringTable = DemMsg::Dem_StringTables::StringTable;
|
using StringTable = DemMsg::Dem_StringTables::StringTable;
|
||||||
using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry;
|
using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry;
|
||||||
{
|
|
||||||
char tableName[StringTable::TABLENAME_MAX_LENGTH];
|
char tableName[StringTable::TABLENAME_MAX_LENGTH];
|
||||||
bitbuf.ReadString(tableName, sizeof(tableName));
|
bitbuf.ReadString(tableName, sizeof(tableName));
|
||||||
data->tableName.assign(tableName);
|
data->tableName.assign(tableName);
|
||||||
}
|
|
||||||
|
|
||||||
data->entries.reset(bitbuf.ReadWord());
|
data->entries.reset(bitbuf.ReadWord());
|
||||||
for (StringTableEntry& entry : data->entries)
|
for (StringTableEntry& entry : data->entries)
|
||||||
@ -87,78 +51,6 @@ static void StringTable_BitRead(bf_read& bitbuf, DemMsg::Dem_StringTables::Strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void StringTable_BitWrite(bf_write& bitbuf, DemMsg::Dem_StringTables::StringTable* data)
|
|
||||||
{
|
|
||||||
using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry;
|
|
||||||
bitbuf.WriteString(data->tableName.c_str());
|
|
||||||
|
|
||||||
bitbuf.WriteWord(data->entries.length());
|
|
||||||
for (StringTableEntry& entry : data->entries)
|
|
||||||
{
|
|
||||||
StringTableEntry_BitWrite(bitbuf, &entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int32_t numEntriesClientSide = data->entriesClientSide.length();
|
|
||||||
bitbuf.WriteOneBit(numEntriesClientSide > 0);
|
|
||||||
if (numEntriesClientSide > 0)
|
|
||||||
{
|
|
||||||
bitbuf.WriteWord(numEntriesClientSide);
|
|
||||||
for (StringTableEntry& entry : data->entriesClientSide)
|
|
||||||
{
|
|
||||||
StringTableEntry_BitWrite(bitbuf, &entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StringTable_JsonRead(base::JsonReaderObject& jsonbuf, DemMsg::Dem_StringTables::StringTable* data)
|
|
||||||
{
|
|
||||||
using StringTable = DemMsg::Dem_StringTables::StringTable;
|
|
||||||
using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry;
|
|
||||||
{
|
|
||||||
char tableName[StringTable::TABLENAME_MAX_LENGTH];
|
|
||||||
jsonbuf.ReadString("tableName", tableName, sizeof(tableName));
|
|
||||||
data->tableName.assign(tableName);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
base::JsonReaderArray entries = jsonbuf.ReadArray("entries");
|
|
||||||
entries.TransformTo(data->entries, [](base::JsonReaderObject& obj, StringTableEntry& entry)
|
|
||||||
{
|
|
||||||
StringTableEntry_JsonRead(obj, &entry);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
{
|
|
||||||
base::JsonReaderArray entriesClientSide = jsonbuf.ReadArray("entriesClientSide");
|
|
||||||
entriesClientSide.TransformTo(data->entriesClientSide, [](base::JsonReaderObject& obj, StringTableEntry& entry)
|
|
||||||
{
|
|
||||||
StringTableEntry_JsonRead(obj, &entry);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StringTable_JsonWrite(DemHandlers::JsonWrite& jsonbuf, const DemMsg::Dem_StringTables::StringTable* data)
|
|
||||||
{
|
|
||||||
using StringTableEntry = DemMsg::Dem_StringTables::StringTableEntry;
|
|
||||||
jsonbuf.WriteString("tableName", data->tableName);
|
|
||||||
jsonbuf.StartArray("entries");
|
|
||||||
for (const StringTableEntry& entry : data->entries)
|
|
||||||
{
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
StringTableEntry_JsonWrite(jsonbuf, &entry);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
}
|
|
||||||
jsonbuf.EndArray();
|
|
||||||
|
|
||||||
jsonbuf.StartArray("entriesClientSide");
|
|
||||||
for (const StringTableEntry& entry : data->entriesClientSide)
|
|
||||||
{
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
StringTableEntry_JsonWrite(jsonbuf, &entry);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
}
|
|
||||||
jsonbuf.EndArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace DemHandlers
|
namespace DemHandlers
|
||||||
{
|
{
|
||||||
bool Dem_StringTables_FileRead_Internal(FileRead& demofile, DemMsg::Dem_StringTables* data)
|
bool Dem_StringTables_FileRead_Internal(FileRead& demofile, DemMsg::Dem_StringTables* data)
|
||||||
@ -184,66 +76,4 @@ namespace DemHandlers
|
|||||||
}
|
}
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dem_StringTables_FileWrite_Internal(FileWrite& demofile, DemMsg::Dem_StringTables* data)
|
|
||||||
{
|
|
||||||
using StringTable = DemMsg::Dem_StringTables::StringTable;
|
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> buffer(new uint8_t[MAX_STRINGTABLE_DATA]);
|
|
||||||
bf_write bitbuf(buffer.get(), MAX_STRINGTABLE_DATA);
|
|
||||||
|
|
||||||
bitbuf.WriteByte(data->stringtables.length());
|
|
||||||
for (StringTable& table : data->stringtables)
|
|
||||||
{
|
|
||||||
StringTable_BitWrite(bitbuf, &table);
|
|
||||||
}
|
|
||||||
if (data->numTrailingBits > 0)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->trailingBitsValue, data->numTrailingBits);
|
|
||||||
}
|
|
||||||
demofile.WriteRawData(bitbuf.GetBasePointer(), bitbuf.GetNumBytesWritten());
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_StringTables_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_StringTables* data)
|
|
||||||
{
|
|
||||||
using StringTable = DemMsg::Dem_StringTables::StringTable;
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
|
|
||||||
data->stringtables.reset(reader.ReadInt32("numStringTables"));
|
|
||||||
data->numTrailingBits = reader.ReadUInt32("numTrailingBits");
|
|
||||||
data->trailingBitsValue = reader.ReadUInt32("trailingBitsValue");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
for (StringTable& table : data->stringtables)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
StringTable_JsonRead(reader, &table);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_StringTables_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_StringTables* data)
|
|
||||||
{
|
|
||||||
using StringTable = DemMsg::Dem_StringTables::StringTable;
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteInt32("numStringTables", data->stringtables.length());
|
|
||||||
jsonbuf.WriteUInt32("numTrailingBits", data->numTrailingBits);
|
|
||||||
jsonbuf.WriteUInt32("trailingBitsValue", data->trailingBitsValue, (data->numTrailingBits > 0));
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
|
|
||||||
for (const StringTable& table : data->stringtables)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
StringTable_JsonWrite(jsonbuf, &table);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
}
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,4 @@ namespace DemHandlers
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dem_SyncTick_FileWrite_Internal(FileWrite& demofile, DemMsg::Dem_SyncTick* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_SyncTick_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_SyncTick* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_SyncTick_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_SyncTick* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,4 @@ namespace DemHandlers
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dem_Unknown_FileWrite_Internal(FileWrite& demofile, DemMsg::Dem_Unknown* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_Unknown_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_Unknown* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_Unknown_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_Unknown* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "dem_usercmd.h"
|
#include "dem_usercmd.h"
|
||||||
#include "demofile/demofile.h"
|
#include "demofile/demofile.h"
|
||||||
#include "demofile/demojson.h"
|
|
||||||
|
|
||||||
namespace DemHandlers
|
namespace DemHandlers
|
||||||
{
|
{
|
||||||
@ -10,30 +9,4 @@ namespace DemHandlers
|
|||||||
data->commandData = demofile.ReadUserCmd(data->commandNum, DemMsg::Dem_UserCmd::COMMANDDATA_MAX_LENGTH);
|
data->commandData = demofile.ReadUserCmd(data->commandNum, DemMsg::Dem_UserCmd::COMMANDDATA_MAX_LENGTH);
|
||||||
return demofile.IsOk();
|
return demofile.IsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Dem_UserCmd_FileWrite_Internal(FileWrite& demofile, DemMsg::Dem_UserCmd* data)
|
|
||||||
{
|
|
||||||
demofile.WriteUserCmd(data->commandNum, data->commandData.begin(), data->commandData.length());
|
|
||||||
return demofile.IsOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_UserCmd_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::Dem_UserCmd* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
|
|
||||||
DemoJsonReader::ReadUserCmd(reader, data->commandNum,
|
|
||||||
data->commandData, DemMsg::Dem_UserCmd::COMMANDDATA_MAX_LENGTH);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Dem_UserCmd_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::Dem_UserCmd* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
DemoJsonWriter::WriteUserCmd(jsonbuf, data->commandNum,
|
|
||||||
data->commandData.begin(), data->commandData.length());
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,6 @@ void DemHandlers::DestroyDemMsgStructs(DemDataStructArray& demDataStructs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*DemMsgFileReadFn)(DemHandlers::FileRead& demofile, void* data);
|
typedef bool (*DemMsgFileReadFn)(DemHandlers::FileRead& demofile, void* data);
|
||||||
typedef bool (*DemMsgFileWriteFn)(DemHandlers::FileWrite& demofile, void* data);
|
|
||||||
typedef bool (*DemMsgJsonReadFn)(DemHandlers::JsonRead& jsonbuf, void* data);
|
|
||||||
typedef bool (*DemMsgJsonWriteFn)(DemHandlers::JsonWrite& jsonbuf, void* data);
|
|
||||||
|
|
||||||
bool DemHandlers::DemMsg_FileRead(uint32_t type, FileRead& demofile, void* data)
|
bool DemHandlers::DemMsg_FileRead(uint32_t type, FileRead& demofile, void* data)
|
||||||
{
|
{
|
||||||
@ -64,33 +61,3 @@ bool DemHandlers::DemMsg_FileRead(uint32_t type, FileRead& demofile, void* data)
|
|||||||
}
|
}
|
||||||
return demHandlers[type](demofile, data);
|
return demHandlers[type](demofile, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DemHandlers::DemMsg_FileWrite(uint32_t type, FileWrite& demofile, void* data)
|
|
||||||
{
|
|
||||||
static const DemMsgFileWriteFn demHandlers[] = DECLARE_DEM_HANDLER_ARRAY(FileWrite);
|
|
||||||
if (type >= (sizeof(demHandlers) / sizeof(DemMsgFileWriteFn)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return demHandlers[type](demofile, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemHandlers::DemMsg_JsonRead(uint32_t type, JsonRead& jsonbuf, void* data)
|
|
||||||
{
|
|
||||||
static const DemMsgJsonReadFn demHandlers[] = DECLARE_DEM_HANDLER_ARRAY(JsonRead);
|
|
||||||
if (type >= (sizeof(demHandlers) / sizeof(DemMsgJsonReadFn)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return demHandlers[type](jsonbuf, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemHandlers::DemMsg_JsonWrite(uint32_t type, JsonWrite& jsonbuf, void* data)
|
|
||||||
{
|
|
||||||
static const DemMsgJsonWriteFn demHandlers[] = DECLARE_DEM_HANDLER_ARRAY(JsonWrite);
|
|
||||||
if (type >= (sizeof(demHandlers) / sizeof(DemMsgJsonWriteFn)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return demHandlers[type](jsonbuf, data);
|
|
||||||
}
|
|
||||||
|
@ -5,48 +5,20 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include "demmessages.h"
|
#include "demmessages.h"
|
||||||
|
|
||||||
namespace base
|
|
||||||
{
|
|
||||||
class JsonReaderFile;
|
|
||||||
class JsonWriterFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DemoFileReader;
|
class DemoFileReader;
|
||||||
class DemoFileWriter;
|
|
||||||
class DemoFileReader2;
|
|
||||||
class DemoFileWriter2;
|
|
||||||
|
|
||||||
namespace DemHandlers
|
namespace DemHandlers
|
||||||
{
|
{
|
||||||
using FileRead = DemoFileReader;
|
using FileRead = DemoFileReader;
|
||||||
using FileWrite = DemoFileWriter;
|
|
||||||
using JsonRead = base::JsonReaderFile;
|
|
||||||
using JsonWrite = base::JsonWriterFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECLARE_DEM_HANDLERS(msgname) \
|
#define DECLARE_DEM_HANDLERS(msgname) \
|
||||||
namespace DemHandlers \
|
namespace DemHandlers \
|
||||||
{ \
|
{ \
|
||||||
bool msgname##_FileRead_Internal(FileRead& demofile, DemMsg::msgname* data); \
|
bool msgname##_FileRead_Internal(FileRead& demofile, DemMsg::msgname* data); \
|
||||||
bool msgname##_FileWrite_Internal(FileWrite& demofile, DemMsg::msgname* data); \
|
|
||||||
bool msgname##_JsonRead_Internal(JsonRead& jsonbuf, DemMsg::msgname* data); \
|
|
||||||
bool msgname##_JsonWrite_Internal(JsonWrite& jsonbuf, DemMsg::msgname* data); \
|
|
||||||
inline bool msgname##_FileRead(FileRead& demofile, void* data) \
|
inline bool msgname##_FileRead(FileRead& demofile, void* data) \
|
||||||
{ \
|
{ \
|
||||||
return msgname##_FileRead_Internal(demofile, reinterpret_cast<DemMsg::msgname*>(data)); \
|
return msgname##_FileRead_Internal(demofile, reinterpret_cast<DemMsg::msgname*>(data)); \
|
||||||
} \
|
} \
|
||||||
inline bool msgname##_FileWrite(FileWrite& demofile, void* data) \
|
|
||||||
{ \
|
|
||||||
return msgname##_FileWrite_Internal(demofile, reinterpret_cast<DemMsg::msgname*>(data)); \
|
|
||||||
} \
|
|
||||||
inline bool msgname##_JsonRead(JsonRead& jsonbuf, void* data) \
|
|
||||||
{ \
|
|
||||||
return msgname##_JsonRead_Internal(jsonbuf, reinterpret_cast<DemMsg::msgname*>(data)); \
|
|
||||||
} \
|
|
||||||
inline bool msgname##_JsonWrite(JsonWrite& jsonbuf, void* data) \
|
|
||||||
{ \
|
|
||||||
return msgname##_JsonWrite_Internal(jsonbuf, reinterpret_cast<DemMsg::msgname*>(data)); \
|
|
||||||
} \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace DemHandlers
|
namespace DemHandlers
|
||||||
@ -56,7 +28,4 @@ namespace DemHandlers
|
|||||||
void DestroyDemMsgStructs(DemDataStructArray& demDataStructs);
|
void DestroyDemMsgStructs(DemDataStructArray& demDataStructs);
|
||||||
|
|
||||||
bool DemMsg_FileRead(uint32_t type, FileRead& demofile, void* data);
|
bool DemMsg_FileRead(uint32_t type, FileRead& demofile, void* data);
|
||||||
bool DemMsg_FileWrite(uint32_t type, FileWrite& demofile, void* data);
|
|
||||||
bool DemMsg_JsonRead(uint32_t type, JsonRead& jsonbuf, void* data);
|
|
||||||
bool DemMsg_JsonWrite(uint32_t type, JsonWrite& jsonbuf, void* data);
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,14 @@
|
|||||||
|
|
||||||
// DemoFileReader
|
// DemoFileReader
|
||||||
|
|
||||||
|
size_t myfread ( void * ptr, size_t size, size_t count, FILE * stream )
|
||||||
|
{
|
||||||
|
size_t ret = fread(ptr, size, count, stream);
|
||||||
|
if (ret != count)
|
||||||
|
throw("fread error");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
DemoFileReader::DemoFileReader(FILE* fp):
|
DemoFileReader::DemoFileReader(FILE* fp):
|
||||||
m_demoFp(fp)
|
m_demoFp(fp)
|
||||||
{
|
{
|
||||||
@ -18,7 +26,7 @@ bool DemoFileReader::IsOk() const
|
|||||||
|
|
||||||
void DemoFileReader::ReadDemoHeader(demoheader_t& header)
|
void DemoFileReader::ReadDemoHeader(demoheader_t& header)
|
||||||
{
|
{
|
||||||
fread(&header, sizeof(demoheader_t), 1, m_demoFp);
|
myfread(&header, sizeof(demoheader_t), 1, m_demoFp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t DemoFileReader::ReadRawData(uint8_t* buffer, int32_t maxLength)
|
int32_t DemoFileReader::ReadRawData(uint8_t* buffer, int32_t maxLength)
|
||||||
@ -26,7 +34,7 @@ int32_t DemoFileReader::ReadRawData(uint8_t* buffer, int32_t maxLength)
|
|||||||
FILE* fp = m_demoFp;
|
FILE* fp = m_demoFp;
|
||||||
|
|
||||||
int32_t size;
|
int32_t size;
|
||||||
fread(&size, sizeof(int32_t), 1, fp);
|
myfread(&size, sizeof(int32_t), 1, fp);
|
||||||
|
|
||||||
if (buffer && (maxLength < size))
|
if (buffer && (maxLength < size))
|
||||||
{
|
{
|
||||||
@ -35,7 +43,7 @@ int32_t DemoFileReader::ReadRawData(uint8_t* buffer, int32_t maxLength)
|
|||||||
|
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
fread(buffer, 1, size, fp);
|
myfread(buffer, 1, size, fp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -49,104 +57,51 @@ Array<uint8_t> DemoFileReader::ReadRawData(int32_t maxLength)
|
|||||||
FILE* fp = m_demoFp;
|
FILE* fp = m_demoFp;
|
||||||
|
|
||||||
int32_t size;
|
int32_t size;
|
||||||
fread(&size, sizeof(int32_t), 1, fp);
|
myfread(&size, sizeof(int32_t), 1, fp);
|
||||||
|
|
||||||
Array<uint8_t> data;
|
Array<uint8_t> data;
|
||||||
if (maxLength < size)
|
if (maxLength < size)
|
||||||
{
|
{
|
||||||
return std::move(data);
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.reset(size);
|
data.reset(size);
|
||||||
fread(data.begin(), 1, size, fp);
|
myfread(data.begin(), 1, size, fp);
|
||||||
return std::move(data);
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemoFileReader::ReadSequenceInfo(int32_t& seqNum1, int32_t& seqNum2)
|
void DemoFileReader::ReadSequenceInfo(int32_t& seqNum1, int32_t& seqNum2)
|
||||||
{
|
{
|
||||||
FILE* fp = m_demoFp;
|
FILE* fp = m_demoFp;
|
||||||
fread(&seqNum1, sizeof(int32_t), 1, fp);
|
myfread(&seqNum1, sizeof(int32_t), 1, fp);
|
||||||
fread(&seqNum2, sizeof(int32_t), 1, fp);
|
myfread(&seqNum2, sizeof(int32_t), 1, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemoFileReader::ReadCmdInfo(democmdinfo_t& info)
|
void DemoFileReader::ReadCmdInfo(democmdinfo_t& info)
|
||||||
{
|
{
|
||||||
fread(&info, sizeof(democmdinfo_t), 1, m_demoFp);
|
myfread(&info, sizeof(democmdinfo_t), 1, m_demoFp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemoFileReader::ReadCmdHeader(unsigned char& cmd, int32_t& tick)
|
void DemoFileReader::ReadCmdHeader(unsigned char& cmd, int32_t& tick)
|
||||||
{
|
{
|
||||||
FILE* fp = m_demoFp;
|
FILE* fp = m_demoFp;
|
||||||
fread(&cmd, 1, sizeof(unsigned char), fp);
|
myfread(&cmd, 1, sizeof(unsigned char), fp);
|
||||||
fread(&tick, 1, sizeof(int32_t), fp);
|
|
||||||
if (cmd > dem_lastcmd)
|
if (cmd > dem_lastcmd)
|
||||||
{
|
{
|
||||||
cmd = dem_stop;
|
cmd = dem_stop;
|
||||||
}
|
}
|
||||||
|
if (cmd != dem_stop)
|
||||||
|
myfread(&tick, 1, sizeof(int32_t), fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t DemoFileReader::ReadUserCmd(int32_t& cmdNum, uint8_t* buffer, int32_t maxLength)
|
int32_t DemoFileReader::ReadUserCmd(int32_t& cmdNum, uint8_t* buffer, int32_t maxLength)
|
||||||
{
|
{
|
||||||
fread(&cmdNum, sizeof(int32_t), 1, m_demoFp);
|
myfread(&cmdNum, sizeof(int32_t), 1, m_demoFp);
|
||||||
return ReadRawData(buffer, maxLength);
|
return ReadRawData(buffer, maxLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
Array<uint8_t> DemoFileReader::ReadUserCmd(int32_t& cmdNum, int32_t maxLength)
|
Array<uint8_t> DemoFileReader::ReadUserCmd(int32_t& cmdNum, int32_t maxLength)
|
||||||
{
|
{
|
||||||
fread(&cmdNum, sizeof(int32_t), 1, m_demoFp);
|
myfread(&cmdNum, sizeof(int32_t), 1, m_demoFp);
|
||||||
return ReadRawData(maxLength);
|
return ReadRawData(maxLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DemoFileWriter
|
|
||||||
|
|
||||||
DemoFileWriter::DemoFileWriter(FILE* fp) :
|
|
||||||
m_demoFp(fp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* DemoFileWriter::GetFp() const
|
|
||||||
{
|
|
||||||
return m_demoFp;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemoFileWriter::IsOk() const
|
|
||||||
{
|
|
||||||
return ferror(m_demoFp) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoFileWriter::WriteDemoHeader(const demoheader_t& header)
|
|
||||||
{
|
|
||||||
fwrite(&header, sizeof(demoheader_t), 1, m_demoFp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoFileWriter::WriteRawData(const uint8_t* buffer, int32_t length)
|
|
||||||
{
|
|
||||||
FILE* fp = m_demoFp;
|
|
||||||
fwrite(&length, sizeof(int32_t), 1, fp);
|
|
||||||
fwrite(buffer, length, 1, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoFileWriter::WriteSequenceInfo(int32_t seqNum1, int32_t seqNum2)
|
|
||||||
{
|
|
||||||
FILE* fp = m_demoFp;
|
|
||||||
fwrite(&seqNum1, sizeof(int32_t), 1, fp);
|
|
||||||
fwrite(&seqNum2, sizeof(int32_t), 1, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoFileWriter::WriteCmdInfo(const democmdinfo_t& info)
|
|
||||||
{
|
|
||||||
fwrite(&info, sizeof(democmdinfo_t), 1, m_demoFp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoFileWriter::WriteCmdHeader(unsigned char cmd, int32_t tick)
|
|
||||||
{
|
|
||||||
FILE* fp = m_demoFp;
|
|
||||||
fwrite(&cmd, sizeof(unsigned char), 1, fp);
|
|
||||||
fwrite(&tick, sizeof(int32_t), 1, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoFileWriter::WriteUserCmd(int32_t cmdNum, const uint8_t* buffer, int32_t length)
|
|
||||||
{
|
|
||||||
fwrite(&cmdNum, sizeof(int32_t), 1, m_demoFp);
|
|
||||||
WriteRawData(buffer, length);
|
|
||||||
}
|
|
||||||
|
@ -26,21 +26,3 @@ public:
|
|||||||
private:
|
private:
|
||||||
FILE* m_demoFp;
|
FILE* m_demoFp;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DemoFileWriter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DemoFileWriter(FILE* fp);
|
|
||||||
|
|
||||||
FILE* GetFp() const;
|
|
||||||
bool IsOk() const;
|
|
||||||
void WriteDemoHeader(const demoheader_t& header);
|
|
||||||
void WriteRawData(const uint8_t* buffer, int32_t length);
|
|
||||||
void WriteSequenceInfo(int32_t seqNum1, int32_t seqNum2);
|
|
||||||
void WriteCmdInfo(const democmdinfo_t& info);
|
|
||||||
void WriteCmdHeader(unsigned char cmd, int32_t tick);
|
|
||||||
void WriteUserCmd(int32_t cmdNum, const uint8_t* buffer, int32_t length);
|
|
||||||
|
|
||||||
private:
|
|
||||||
FILE* m_demoFp;
|
|
||||||
};
|
|
||||||
|
@ -1,161 +0,0 @@
|
|||||||
|
|
||||||
#include "demojson.h"
|
|
||||||
#include "demofile/demotypes.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
bool DemoJsonReader::ReadDemoHeader(base::JsonReaderObject& reader, demoheader_t& header)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject object = reader.ReadObject("demoheader");
|
|
||||||
object.ReadString("demofilestamp", header.demofilestamp, sizeof(header.demofilestamp));
|
|
||||||
header.demoprotocol = object.ReadInt32("demoprotocol");
|
|
||||||
header.networkprotocol = object.ReadInt32("networkprotocol");
|
|
||||||
object.ReadString("servername", header.servername, sizeof(header.servername));
|
|
||||||
object.ReadString("clientname", header.clientname, sizeof(header.clientname));
|
|
||||||
object.ReadString("mapname", header.mapname, sizeof(header.mapname));
|
|
||||||
object.ReadString("gamedirectory", header.gamedirectory, sizeof(header.gamedirectory));
|
|
||||||
header.playback_time = object.ReadFloat("playback_time");
|
|
||||||
header.playback_ticks = object.ReadInt32("playback_ticks");
|
|
||||||
header.playback_frames = object.ReadInt32("playback_frames");
|
|
||||||
header.signonlength = object.ReadInt32("signonlength");
|
|
||||||
return !reader.HasReadError() && !object.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemoJsonReader::ReadSequenceInfo(base::JsonReaderObject& reader,
|
|
||||||
int32_t& seqNum1, int32_t& seqNum2)
|
|
||||||
{
|
|
||||||
seqNum1 = reader.ReadInt32("sequenceNum1");
|
|
||||||
seqNum2 = reader.ReadInt32("sequenceNum2");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemoJsonReader::ReadCmdInfo(base::JsonReaderObject& reader, democmdinfo_t& info)
|
|
||||||
{
|
|
||||||
democmdinfo_t::Split_t& split = info.u[0];
|
|
||||||
base::JsonReaderObject object = reader.ReadObject("democmdinfo");
|
|
||||||
split.flags = object.ReadInt32("flags");
|
|
||||||
bool readError = ReadVector(object, "viewOrigin", split.viewOrigin);
|
|
||||||
readError |= ReadAngle(object, "viewAngles", split.viewAngles);
|
|
||||||
readError |= ReadAngle(object, "localViewAngles", split.localViewAngles);
|
|
||||||
readError |= ReadVector(object, "viewOrigin2", split.viewOrigin2);
|
|
||||||
readError |= ReadAngle(object, "viewAngles2", split.viewAngles2);
|
|
||||||
readError |= ReadAngle(object, "localViewAngles2", split.localViewAngles2);
|
|
||||||
return !readError && !reader.HasReadError() && !object.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemoJsonReader::ReadCmdHeader(base::JsonReaderObject& reader, unsigned char& cmd, int32_t& tick)
|
|
||||||
{
|
|
||||||
cmd = reader.ReadUInt32("cmd");
|
|
||||||
tick = reader.ReadInt32("tick");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemoJsonReader::ReadUserCmd(base::JsonReaderObject& reader, int32_t& cmdNum,
|
|
||||||
uint8_t* buffer, int32_t length, int32_t& bytesRead)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject object = reader.ReadObject("usercmd");
|
|
||||||
cmdNum = object.ReadInt32("cmd");
|
|
||||||
bytesRead = object.ReadBytes("data", buffer, length);
|
|
||||||
return !object.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemoJsonReader::ReadUserCmd(base::JsonReaderObject& reader, int32_t cmdNum,
|
|
||||||
Array<uint8_t>& dest, int32_t maxLength)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject object = reader.ReadObject("usercmd");
|
|
||||||
cmdNum = object.ReadInt32("cmd");
|
|
||||||
|
|
||||||
const int32_t numBytes = object.ReadBytes("data", nullptr, 0);
|
|
||||||
dest.reset(std::min(maxLength, numBytes));
|
|
||||||
object.ReadBytes("data", dest.begin(), dest.length());
|
|
||||||
return !object.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemoJsonReader::ReadVector(base::JsonReaderObject& reader, const char* name, Vector& vec)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject object = reader.ReadObject(name);
|
|
||||||
vec.x = object.ReadFloat("x");
|
|
||||||
vec.y = object.ReadFloat("y");
|
|
||||||
vec.z = object.ReadFloat("z");
|
|
||||||
return !reader.HasReadError() && !object.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DemoJsonReader::ReadAngle(base::JsonReaderObject& reader, const char* name, QAngle& angles)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject object = reader.ReadObject(name);
|
|
||||||
angles.x = object.ReadFloat("pitch");
|
|
||||||
angles.y = object.ReadFloat("yaw");
|
|
||||||
angles.z = object.ReadFloat("roll");
|
|
||||||
return !reader.HasReadError() && !object.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoJsonWriter::WriteDemoHeader(base::JsonWriterFile& writer, const demoheader_t& header)
|
|
||||||
{
|
|
||||||
writer.StartObject("demoheader");
|
|
||||||
writer.WriteString("demofilestamp", header.demofilestamp);
|
|
||||||
writer.WriteInt32("demoprotocol", header.demoprotocol);
|
|
||||||
writer.WriteInt32("networkprotocol", header.networkprotocol);
|
|
||||||
writer.WriteString("servername", header.servername);
|
|
||||||
writer.WriteString("clientname", header.clientname);
|
|
||||||
writer.WriteString("mapname", header.mapname);
|
|
||||||
writer.WriteString("gamedirectory", header.gamedirectory);
|
|
||||||
writer.WriteFloat("playback_time", header.playback_time);
|
|
||||||
writer.WriteInt32("playback_ticks", header.playback_ticks);
|
|
||||||
writer.WriteInt32("playback_frames", header.playback_frames);
|
|
||||||
writer.WriteInt32("signonlength", header.signonlength);
|
|
||||||
writer.EndObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoJsonWriter::WriteSequenceInfo(base::JsonWriterFile& writer,
|
|
||||||
int32_t seqNum1, int32_t seqNum2)
|
|
||||||
{
|
|
||||||
writer.WriteInt32("sequenceNum1", seqNum1);
|
|
||||||
writer.WriteInt32("sequenceNum2", seqNum2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoJsonWriter::WriteCmdInfo(base::JsonWriterFile& writer,
|
|
||||||
const democmdinfo_t& info)
|
|
||||||
{
|
|
||||||
const democmdinfo_t::Split_t& split = info.u[0];
|
|
||||||
writer.StartObject("democmdinfo");
|
|
||||||
writer.WriteInt32("flags", split.flags);
|
|
||||||
WriteVector(writer, "viewOrigin", split.viewOrigin);
|
|
||||||
WriteAngle(writer, "viewAngles", split.viewAngles);
|
|
||||||
WriteAngle(writer, "localViewAngles", split.localViewAngles);
|
|
||||||
WriteVector(writer, "viewOrigin2", split.viewOrigin2);
|
|
||||||
WriteAngle(writer, "viewAngles2", split.viewAngles2);
|
|
||||||
WriteAngle(writer, "localViewAngles2", split.localViewAngles2);
|
|
||||||
writer.EndObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoJsonWriter::WriteCmdHeader(base::JsonWriterFile& writer, unsigned char cmd, int32_t tick)
|
|
||||||
{
|
|
||||||
writer.WriteUInt32("cmd", cmd);
|
|
||||||
writer.WriteInt32("tick", tick);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoJsonWriter::WriteUserCmd(base::JsonWriterFile& writer,
|
|
||||||
int32_t cmdNum, const uint8_t* buffer, int32_t length)
|
|
||||||
{
|
|
||||||
writer.StartObject("usercmd");
|
|
||||||
writer.WriteInt32("cmd", cmdNum);
|
|
||||||
writer.WriteBytes("data", buffer, length);
|
|
||||||
writer.EndObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoJsonWriter::WriteVector(base::JsonWriterFile& writer, const char* name, const Vector& vec)
|
|
||||||
{
|
|
||||||
writer.StartObject(name);
|
|
||||||
writer.WriteFloat("x", vec.x);
|
|
||||||
writer.WriteFloat("y", vec.y);
|
|
||||||
writer.WriteFloat("z", vec.z);
|
|
||||||
writer.EndObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoJsonWriter::WriteAngle(base::JsonWriterFile& writer, const char* name, const QAngle& angles)
|
|
||||||
{
|
|
||||||
writer.StartObject(name);
|
|
||||||
writer.WriteFloat("pitch", angles.x);
|
|
||||||
writer.WriteFloat("yaw", angles.y);
|
|
||||||
writer.WriteFloat("roll", angles.z);
|
|
||||||
writer.EndObject();
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "base/array.h"
|
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
struct demoheader_t;
|
|
||||||
struct democmdinfo_t;
|
|
||||||
class Vector;
|
|
||||||
class QAngle;
|
|
||||||
|
|
||||||
namespace DemoJsonReader
|
|
||||||
{
|
|
||||||
bool ReadDemoHeader(base::JsonReaderObject& reader, demoheader_t& header);
|
|
||||||
bool ReadSequenceInfo(base::JsonReaderObject& reader, int32_t& seqNum1, int32_t& seqNum2);
|
|
||||||
bool ReadCmdInfo(base::JsonReaderObject& reader, democmdinfo_t& info);
|
|
||||||
bool ReadCmdHeader(base::JsonReaderObject& reader, unsigned char& cmd, int32_t& tick);
|
|
||||||
bool ReadUserCmd(base::JsonReaderObject& reader, int32_t& cmdNum,
|
|
||||||
uint8_t* buffer, int32_t length, int32_t& bytesRead);
|
|
||||||
bool ReadUserCmd(base::JsonReaderObject& reader, int32_t cmdNum, Array<uint8_t>& dest, int32_t maxLength);
|
|
||||||
bool ReadVector(base::JsonReaderObject& reader, const char* name, Vector& vec);
|
|
||||||
bool ReadAngle(base::JsonReaderObject& reader, const char* name, QAngle& angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace DemoJsonWriter
|
|
||||||
{
|
|
||||||
void WriteDemoHeader(base::JsonWriterFile& writer, const demoheader_t& header);
|
|
||||||
void WriteSequenceInfo(base::JsonWriterFile& writer, int32_t seqNum1, int32_t seqNum2);
|
|
||||||
void WriteCmdInfo(base::JsonWriterFile& writer, const democmdinfo_t& info);
|
|
||||||
void WriteCmdHeader(base::JsonWriterFile& writer, unsigned char cmd, int32_t tick);
|
|
||||||
void WriteUserCmd(base::JsonWriterFile& writer, int32_t cmdNum, const uint8_t* buffer, int32_t length);
|
|
||||||
void WriteVector(base::JsonWriterFile& writer, const char* name, const Vector& vec);
|
|
||||||
void WriteAngle(base::JsonWriterFile& writer, const char* name, const QAngle& angle);
|
|
||||||
}
|
|
@ -2,12 +2,12 @@
|
|||||||
#include "gameevents.h"
|
#include "gameevents.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace GameEvents
|
namespace GameEvents
|
||||||
{
|
{
|
||||||
EventDataMap ParseEventData(bf_read& bitbuf, const EventDescriptor& desc, std::vector<char>& stringMem)
|
EventDataMap ParseEventData(bf_read& bitbuf, const EventDescriptor& desc)
|
||||||
{
|
{
|
||||||
stringMem.reserve(stringMem.size() + MAX_EVENT_BYTES);
|
|
||||||
EventDataMap data;
|
EventDataMap data;
|
||||||
char tempStr[MAX_EVENT_BYTES];
|
char tempStr[MAX_EVENT_BYTES];
|
||||||
for (const EventValue& value : desc.values)
|
for (const EventValue& value : desc.values)
|
||||||
@ -18,13 +18,9 @@ namespace GameEvents
|
|||||||
{
|
{
|
||||||
case EventValueType::String:
|
case EventValueType::String:
|
||||||
{
|
{
|
||||||
int length = 0;
|
const bool ok = bitbuf.ReadString(tempStr, sizeof(tempStr), false);
|
||||||
const bool ok = bitbuf.ReadString(tempStr, sizeof(tempStr), false, &length);
|
|
||||||
assert(ok);
|
assert(ok);
|
||||||
length += 1; // for null terminator
|
eventData.strValue.assign(tempStr);
|
||||||
|
|
||||||
eventData.strOffset = stringMem.size();
|
|
||||||
stringMem.insert(stringMem.end(), tempStr, tempStr + length + 1);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EventValueType::Float:
|
case EventValueType::Float:
|
||||||
@ -61,51 +57,41 @@ namespace GameEvents
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintEventData(bf_read& bitbuf, const EventDescriptor& desc)
|
void PrintEvent(const char* name, EventDataMap& data)
|
||||||
{
|
{
|
||||||
char tempStr[MAX_EVENT_BYTES];
|
std::cout << "[EVENT] " << name << "\n";
|
||||||
printf("%s:\n", desc.name);
|
for (const auto& d : data)
|
||||||
for (const EventValue& value : desc.values)
|
|
||||||
{
|
{
|
||||||
printf(" %s: ", value.name);
|
std::cout << "\t" << d.first << ": ";
|
||||||
switch(value.type)
|
switch(d.second.type)
|
||||||
{
|
{
|
||||||
case EventValueType::String:
|
case GameEvents::EventValueType::String:
|
||||||
{
|
{
|
||||||
const bool ok = bitbuf.ReadString(tempStr, sizeof(tempStr), false, nullptr);
|
std::cout << d.second.strValue << "\n";
|
||||||
assert(ok);
|
} break;
|
||||||
printf("%s\n", tempStr);
|
case GameEvents::EventValueType::Float:
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EventValueType::Float:
|
|
||||||
{
|
{
|
||||||
printf("%f\n", bitbuf.ReadFloat());
|
std::cout << d.second.flValue << "\n";
|
||||||
break;
|
} break;
|
||||||
}
|
case GameEvents::EventValueType::Long:
|
||||||
case EventValueType::Long:
|
|
||||||
{
|
{
|
||||||
printf("%i\n", bitbuf.ReadSBitLong(32));
|
std::cout << d.second.i32Value << "\n";
|
||||||
break;
|
} break;
|
||||||
}
|
case GameEvents::EventValueType::Short:
|
||||||
case EventValueType::Short:
|
|
||||||
{
|
{
|
||||||
printf("%i\n", bitbuf.ReadSBitLong(16));
|
std::cout << d.second.i16Value << "\n";
|
||||||
break;
|
} break;
|
||||||
}
|
case GameEvents::EventValueType::Byte:
|
||||||
case EventValueType::Byte:
|
|
||||||
{
|
{
|
||||||
printf("%u\n", bitbuf.ReadUBitLong(8));
|
std::cout << d.second.u8Value << "\n";
|
||||||
break;
|
} break;
|
||||||
}
|
case GameEvents::EventValueType::Bool:
|
||||||
case EventValueType::Bool:
|
|
||||||
{
|
{
|
||||||
printf("%s\n", (bitbuf.ReadOneBit() != 0) ? "true" : "false");
|
std::cout << d.second.bValue << "\n";
|
||||||
break;
|
} break;
|
||||||
}
|
|
||||||
case EventValueType::Local:
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
{
|
||||||
break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
//#define WIP_GAMEEVENTS
|
|
||||||
|
|
||||||
class bf_read;
|
class bf_read;
|
||||||
|
|
||||||
namespace GameEvents
|
namespace GameEvents
|
||||||
@ -43,16 +41,16 @@ namespace GameEvents
|
|||||||
EventValueType type;
|
EventValueType type;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
ptrdiff_t strOffset;
|
|
||||||
float flValue;
|
float flValue;
|
||||||
int32_t i32Value;
|
int32_t i32Value;
|
||||||
int16_t i16Value;
|
int16_t i16Value;
|
||||||
uint8_t u8Value;
|
uint8_t u8Value;
|
||||||
bool bValue;
|
bool bValue;
|
||||||
};
|
};
|
||||||
|
std::string strValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
using EventDataMap = std::map<std::string, EventData>;
|
using EventDataMap = std::map<std::string, EventData>;
|
||||||
EventDataMap ParseEventData(bf_read& bitbuf, const EventDescriptor& desc, std::vector<char>& stringMem);
|
EventDataMap ParseEventData(bf_read& bitbuf, const EventDescriptor& desc);
|
||||||
void PrintEventData(bf_read& bitbuf, const EventDescriptor& desc);
|
void PrintEvent(const char* name, EventDataMap& data);
|
||||||
}
|
}
|
||||||
|
196
demboyz/game/logic.cpp
Normal file
196
demboyz/game/logic.cpp
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
|
||||||
|
#include "logic.h"
|
||||||
|
#include "netmessages/svc_serverinfo.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
Logic::Logic(SourceGameContext* context):
|
||||||
|
context(context)
|
||||||
|
{
|
||||||
|
//memset(clients, 0, sizeof(clients));
|
||||||
|
data = json({
|
||||||
|
{"header", {}},
|
||||||
|
{"serverinfo", {}},
|
||||||
|
{"players", {}},
|
||||||
|
{"chat", {}}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Logic::~Logic()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logic::Start()
|
||||||
|
{
|
||||||
|
data["demoheader"] = json({
|
||||||
|
{"demofilestamp", context->header.demofilestamp},
|
||||||
|
{"demoprotocol", context->header.demoprotocol},
|
||||||
|
{"networkprotocol", context->header.networkprotocol},
|
||||||
|
{"servername", context->header.servername},
|
||||||
|
{"clientname", context->header.clientname},
|
||||||
|
{"mapname", context->header.mapname},
|
||||||
|
{"gamedirectory", context->header.gamedirectory},
|
||||||
|
{"playback_time", context->header.playback_time},
|
||||||
|
{"playback_ticks", context->header.playback_ticks},
|
||||||
|
{"playback_frames", context->header.playback_frames},
|
||||||
|
{"signonlength", context->header.signonlength}
|
||||||
|
});
|
||||||
|
|
||||||
|
// std::cout << data.dump(2, ' ', false, json::error_handler_t::replace) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logic::Finish(bool dirty)
|
||||||
|
{
|
||||||
|
// disconnect all remaining clients
|
||||||
|
for (int client = 0; client < MAX_PLAYERS; client++)
|
||||||
|
{
|
||||||
|
if (clients[client].connected == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
OnClientDisconnected(client, "#demoend");
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix header if demo is corrupt
|
||||||
|
data["demoheader"]["dirty"] = dirty;
|
||||||
|
if (dirty)
|
||||||
|
{
|
||||||
|
data["demoheader"]["playback_ticks"] = curTick;
|
||||||
|
data["demoheader"]["playback_time"] = curTick * context->fTickRate;
|
||||||
|
data["demoheader"]["playback_frames"] = context->curFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string out = data.dump(2, ' ', false, json::error_handler_t::replace);
|
||||||
|
out.append("\n");
|
||||||
|
fwrite(out.c_str(), out.size(), 1, context->outputFp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logic::OnServerInfo(NetMsg::SVC_ServerInfo* serverInfo)
|
||||||
|
{
|
||||||
|
char mapMD5[32+1];
|
||||||
|
for (int i = 0; i < 16; ++i)
|
||||||
|
{
|
||||||
|
mapMD5[(i * 2)] = "0123456789ABCDEF"[serverInfo->mapMD5[i] / 16];
|
||||||
|
mapMD5[(i * 2) + 1] = "0123456789ABCDEF"[serverInfo->mapMD5[i] % 16];
|
||||||
|
}
|
||||||
|
mapMD5[32] = 0;
|
||||||
|
|
||||||
|
json info = {
|
||||||
|
{"protocol", serverInfo->protocol},
|
||||||
|
{"serverCount", serverInfo->serverCount},
|
||||||
|
{"isHLTV", serverInfo->isHLTV},
|
||||||
|
{"isDedicated", serverInfo->isDedicated},
|
||||||
|
{"clientCRC", serverInfo->clientCRC},
|
||||||
|
{"maxClasses", serverInfo->maxClasses},
|
||||||
|
{"mapCRC", serverInfo->mapCRC},
|
||||||
|
{"mapMD5", mapMD5},
|
||||||
|
{"playerSlot", serverInfo->playerSlot},
|
||||||
|
{"maxClients", serverInfo->maxClients},
|
||||||
|
{"tickInterval", serverInfo->tickInterval},
|
||||||
|
{"os", serverInfo->os},
|
||||||
|
{"gameDir", serverInfo->gameDir},
|
||||||
|
{"mapName", serverInfo->mapName},
|
||||||
|
{"skyName", serverInfo->skyName},
|
||||||
|
{"hostName", serverInfo->hostName},
|
||||||
|
{"isReplay", serverInfo->isReplay}
|
||||||
|
};
|
||||||
|
data["serverinfo"] = info;
|
||||||
|
|
||||||
|
// std::cout << info.dump(2, ' ', false, json::error_handler_t::replace) << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logic::OnClientConnected(int client)
|
||||||
|
{
|
||||||
|
assert(clients[client].connected == -1);
|
||||||
|
|
||||||
|
const auto& info = context->players[client].info;
|
||||||
|
auto& player = data["players"][info.guid];
|
||||||
|
|
||||||
|
if (player.is_null())
|
||||||
|
{
|
||||||
|
player = json({
|
||||||
|
{"names", {}},
|
||||||
|
{"sprays", {}},
|
||||||
|
{"disconnect_reasons", {}},
|
||||||
|
{"playtime", 0},
|
||||||
|
{"voicetime", 0.0f}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
clients[client].connected = curTick;
|
||||||
|
|
||||||
|
OnClientSettingsChanged(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logic::OnClientDisconnected(int client, const char* reason)
|
||||||
|
{
|
||||||
|
assert(clients[client].connected != -1);
|
||||||
|
|
||||||
|
const auto& info = context->players[client].info;
|
||||||
|
auto& player = data["players"][info.guid];
|
||||||
|
|
||||||
|
// cumulative play time
|
||||||
|
unsigned int playtime = curTick - clients[client].connected;
|
||||||
|
playtime += player["playtime"].get<unsigned int>();
|
||||||
|
player["playtime"] = playtime;
|
||||||
|
|
||||||
|
// cumulative voice chat time
|
||||||
|
float voicetime = clients[client].voiceTime;
|
||||||
|
voicetime += player["voicetime"].get<float>();
|
||||||
|
player["voicetime"] = voicetime;
|
||||||
|
|
||||||
|
player["disconnect_reasons"] += reason;
|
||||||
|
|
||||||
|
clients[client].connected = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logic::OnClientSettingsChanged(int client)
|
||||||
|
{
|
||||||
|
assert(clients[client].connected != -1);
|
||||||
|
|
||||||
|
const auto& info = context->players[client].info;
|
||||||
|
auto& player = data["players"][info.guid];
|
||||||
|
|
||||||
|
// list of names
|
||||||
|
if (std::find(player["names"].begin(), player["names"].end(), info.name) == player["names"].end())
|
||||||
|
player["names"].push_back(info.name);
|
||||||
|
|
||||||
|
// list of spray hashes
|
||||||
|
if (info.customFiles[0])
|
||||||
|
{
|
||||||
|
char logohex[16];
|
||||||
|
sprintf(logohex, "%08x", info.customFiles[0]);
|
||||||
|
if (std::find(player["sprays"].begin(), player["sprays"].end(), logohex) == player["sprays"].end())
|
||||||
|
player["sprays"].push_back(logohex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logic::OnClientChat(int client, bool bWantsToChat, const char* msgName, const char* msgSender, const char* msgText)
|
||||||
|
{
|
||||||
|
const auto& info = context->players[client].info;
|
||||||
|
json chat = {
|
||||||
|
{"tick", curTick},
|
||||||
|
{"steamid", info.guid},
|
||||||
|
{"msgName", msgName},
|
||||||
|
{"msgSender", msgSender},
|
||||||
|
{"msgText", msgText}
|
||||||
|
};
|
||||||
|
|
||||||
|
data["chat"] += chat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logic::OnClientVoiceChat(int client, float length)
|
||||||
|
{
|
||||||
|
assert(clients[client].connected != -1);
|
||||||
|
|
||||||
|
clients[client].voiceTime += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logic::OnVoiceCodec(const char* codec, int quality, int sampleRate)
|
||||||
|
{
|
||||||
|
data["voice_init"] = json({
|
||||||
|
{"codec", codec},
|
||||||
|
{"quality", quality},
|
||||||
|
{"sampleRate", sampleRate}
|
||||||
|
});
|
||||||
|
}
|
39
demboyz/game/logic.h
Normal file
39
demboyz/game/logic.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/json.hpp"
|
||||||
|
#include "game/sourcecontext.h"
|
||||||
|
|
||||||
|
using nlohmann::json;
|
||||||
|
|
||||||
|
namespace NetMsg
|
||||||
|
{
|
||||||
|
struct SVC_ServerInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Logic
|
||||||
|
{
|
||||||
|
Logic(SourceGameContext* context);
|
||||||
|
~Logic();
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
void Finish(bool dirty);
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int32_t connected = -1;
|
||||||
|
float voiceTime = 0.0f;
|
||||||
|
} clients[MAX_PLAYERS];
|
||||||
|
|
||||||
|
void OnServerInfo(NetMsg::SVC_ServerInfo* serverInfo);
|
||||||
|
void OnClientConnected(int client);
|
||||||
|
void OnClientDisconnected(int client, const char* reason);
|
||||||
|
void OnClientSettingsChanged(int client);
|
||||||
|
void OnClientChat(int client, bool bWantsToChat, const char* msgName, const char* msgSender, const char* msgText);
|
||||||
|
void OnClientVoiceChat(int client, float length);
|
||||||
|
void OnVoiceCodec(const char* codec, int quality, int sampleRate);
|
||||||
|
|
||||||
|
int32_t curTick = 0;
|
||||||
|
SourceGameContext* context = nullptr;
|
||||||
|
json data;
|
||||||
|
};
|
@ -1,16 +1,177 @@
|
|||||||
|
|
||||||
#include "sourcecontext.h"
|
#include "sourcecontext.h"
|
||||||
|
#include "netmessages/netmath.h"
|
||||||
#include "netmessages/svc_gameeventlist.h"
|
#include "netmessages/svc_gameeventlist.h"
|
||||||
|
#include "netmessages/usermessages.h"
|
||||||
|
#include "netmessages/svc_usermessage.h"
|
||||||
|
#include "netmessages/svc_serverinfo.h"
|
||||||
|
#include "sourcesdk/bitbuf.h"
|
||||||
|
#include "game/gameevents.h"
|
||||||
|
#include "game/logic.h"
|
||||||
|
#include "io/voicewriter/voicedatawriter.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
SourceGameContext::SourceGameContext():
|
#include "netmessages/svc_voiceinit.h"
|
||||||
protocol(0),
|
#include "netmessages/svc_voicedata.h"
|
||||||
gameEventList(nullptr)
|
|
||||||
|
SourceGameContext::SourceGameContext(std::string outputDir, std::string outputDirVoice):
|
||||||
|
outputDir(outputDir),
|
||||||
|
outputDirVoice(outputDirVoice)
|
||||||
{
|
{
|
||||||
|
stringTables = new StringTableContainer(this);
|
||||||
|
memset(players, 0, sizeof(players));
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceGameContext::~SourceGameContext()
|
SourceGameContext::~SourceGameContext()
|
||||||
{
|
{
|
||||||
|
delete logic;
|
||||||
|
logic = nullptr;
|
||||||
|
|
||||||
protocol = 0;
|
protocol = 0;
|
||||||
delete gameEventList;
|
delete gameEventList;
|
||||||
gameEventList = nullptr;
|
gameEventList = nullptr;
|
||||||
|
delete stringTables;
|
||||||
|
stringTables = nullptr;
|
||||||
|
|
||||||
|
fclose(outputFp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SourceGameContext::init()
|
||||||
|
{
|
||||||
|
outputFp = fopen((outputDir + "/out.json").c_str(), "wb");
|
||||||
|
if (!outputFp)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: Could not open out.json\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
voiceWriter = new VoiceDataWriter(this, outputDirVoice.c_str());
|
||||||
|
logic = new Logic(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceGameContext::Start()
|
||||||
|
{
|
||||||
|
logic->Start();
|
||||||
|
voiceWriter->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceGameContext::Finish(bool dirty)
|
||||||
|
{
|
||||||
|
logic->Finish(dirty);
|
||||||
|
voiceWriter->Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceGameContext::StartCommandPacket(const CommandPacket& packet)
|
||||||
|
{
|
||||||
|
curFrame += (packet.cmd == dem_packet);
|
||||||
|
|
||||||
|
if(curTick == -1 && packet.tick > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
curTick = packet.tick;
|
||||||
|
logic->curTick = curTick;
|
||||||
|
|
||||||
|
voiceWriter->StartCommandPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceGameContext::EndCommandPacket(const PacketTrailingBits& trailingBits)
|
||||||
|
{
|
||||||
|
if(curTick == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
voiceWriter->EndCommandPacket(trailingBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceGameContext::OnNetPacket(NetPacket& packet)
|
||||||
|
{
|
||||||
|
if(packet.type == NetMsg::svc_ServerInfo)
|
||||||
|
{
|
||||||
|
NetMsg::SVC_ServerInfo* serverInfo = static_cast<NetMsg::SVC_ServerInfo*>(packet.data);
|
||||||
|
fTickInterval = serverInfo->tickInterval;
|
||||||
|
fTickRate = 1.f / fTickInterval;
|
||||||
|
logic->OnServerInfo(serverInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(packet.type == NetMsg::svc_UserMessage)
|
||||||
|
{
|
||||||
|
NetMsg::SVC_UserMessage* umsg = static_cast<NetMsg::SVC_UserMessage*>(packet.data);
|
||||||
|
|
||||||
|
bf_read msg(umsg->data.get(), math::BitsToBytes(umsg->dataLengthInBits));
|
||||||
|
|
||||||
|
if(umsg->msgType == UserMsg::SayText2)
|
||||||
|
{
|
||||||
|
int client = msg.ReadByte();
|
||||||
|
bool bWantsToChat = msg.ReadByte();
|
||||||
|
|
||||||
|
char msgName[2048] = {0};
|
||||||
|
char msgSender[2048] = {0};
|
||||||
|
char msgText[2048] = {0};
|
||||||
|
|
||||||
|
msg.ReadString(msgName, sizeof(msgName));
|
||||||
|
msg.ReadString(msgSender, sizeof(msgSender));
|
||||||
|
msg.ReadString(msgText, sizeof(msgText));
|
||||||
|
|
||||||
|
logic->OnClientChat(client, bWantsToChat, msgName, msgSender, msgText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(packet.type == NetMsg::svc_VoiceInit || packet.type == NetMsg::svc_VoiceData)
|
||||||
|
{
|
||||||
|
voiceWriter->OnNetPacket(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceGameContext::OnGameEvent(const char *name, GameEvents::EventDataMap &data)
|
||||||
|
{
|
||||||
|
// GameEvents::PrintEvent(name, data);
|
||||||
|
|
||||||
|
if (strcmp(name, "player_disconnect") == 0)
|
||||||
|
{
|
||||||
|
int userid = data["userid"].i16Value;
|
||||||
|
for (int client = 0; client < MAX_PLAYERS; client++)
|
||||||
|
{
|
||||||
|
auto& p = players[client];
|
||||||
|
if (!p.connected || p.info.userID != userid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p.connected = false;
|
||||||
|
logic->OnClientDisconnected(client, data["reason"].strValue.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceGameContext::OnStringtable(StringTable* table)
|
||||||
|
{
|
||||||
|
if (table->tableName == "userinfo")
|
||||||
|
{
|
||||||
|
table->callback = std::bind(&SourceGameContext::UserInfoChanged, this, std::placeholders::_1, std::placeholders::_2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceGameContext::UserInfoChanged(int tableIdx, int entryIdx)
|
||||||
|
{
|
||||||
|
StringTableEntry &entry = stringTables->tables[tableIdx].entries[entryIdx];
|
||||||
|
|
||||||
|
int client = std::stoi(entry.string);
|
||||||
|
player_info_t *info = (player_info_t *)entry.data.data();
|
||||||
|
|
||||||
|
if (entry.data.size() != sizeof(player_info_t))
|
||||||
|
{
|
||||||
|
memset(&players[client].info, 0, sizeof(player_info_t));
|
||||||
|
players[client].connected = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&players[client].info, info, sizeof(player_info_t));
|
||||||
|
|
||||||
|
if (!players[client].connected)
|
||||||
|
logic->OnClientConnected(client);
|
||||||
|
else
|
||||||
|
logic->OnClientSettingsChanged(client);
|
||||||
|
|
||||||
|
players[client].connected = true;
|
||||||
|
|
||||||
|
//std::cout << client << " (" << info->userID << "): N:" << info->name << " G:" << info->guid << " F:" << info->friendsID << "\n";
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,111 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "stringtables.h"
|
||||||
|
#include "game/gameevents.h"
|
||||||
|
#include "demofile/demotypes.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace NetMsg
|
namespace NetMsg
|
||||||
{
|
{
|
||||||
struct SVC_GameEventList;
|
struct SVC_GameEventList;
|
||||||
}
|
}
|
||||||
|
struct Logic;
|
||||||
|
class VoiceDataWriter;
|
||||||
|
|
||||||
|
struct CommandPacket
|
||||||
|
{
|
||||||
|
unsigned char cmd;
|
||||||
|
int32_t tick;
|
||||||
|
|
||||||
|
void* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NetPacket
|
||||||
|
{
|
||||||
|
int32_t type;
|
||||||
|
void* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PacketTrailingBits
|
||||||
|
{
|
||||||
|
uint32_t numTrailingBits;
|
||||||
|
uint32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_PLAYERS 65
|
||||||
|
#define MAX_PLAYER_NAME_LENGTH 32
|
||||||
|
#define SIGNED_GUID_LEN 32
|
||||||
|
#define MAX_CUSTOM_FILES 4
|
||||||
|
|
||||||
|
// Engine player info, no game related infos here
|
||||||
|
// If you change this, change the two byteswap defintions:
|
||||||
|
// cdll_client_int.cpp and cdll_engine_int.cpp
|
||||||
|
typedef struct player_info_s
|
||||||
|
{
|
||||||
|
// scoreboard information
|
||||||
|
char name[MAX_PLAYER_NAME_LENGTH];
|
||||||
|
// local server user ID, unique while server is running
|
||||||
|
int userID;
|
||||||
|
// global unique player identifer
|
||||||
|
char guid[SIGNED_GUID_LEN + 1];
|
||||||
|
// friends identification number
|
||||||
|
uint32_t friendsID;
|
||||||
|
// friends name
|
||||||
|
char friendsName[MAX_PLAYER_NAME_LENGTH];
|
||||||
|
// true, if player is a bot controlled by game.dll
|
||||||
|
bool fakeplayer;
|
||||||
|
// true if player is the HLTV proxy
|
||||||
|
bool ishltv;
|
||||||
|
#if defined( REPLAY_ENABLED )
|
||||||
|
// true if player is the Replay proxy
|
||||||
|
bool isreplay;
|
||||||
|
#endif
|
||||||
|
// custom files CRC for this player
|
||||||
|
uint32_t customFiles[MAX_CUSTOM_FILES];
|
||||||
|
// this counter increases each time the server downloaded a new file
|
||||||
|
unsigned char filesDownloaded;
|
||||||
|
} player_info_t;
|
||||||
|
|
||||||
struct SourceGameContext
|
struct SourceGameContext
|
||||||
{
|
{
|
||||||
SourceGameContext();
|
SourceGameContext(std::string outputDir, std::string outputDirVoice);
|
||||||
~SourceGameContext();
|
~SourceGameContext();
|
||||||
|
bool init();
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
void Finish(bool dirty);
|
||||||
|
|
||||||
|
void StartCommandPacket(const CommandPacket& packet);
|
||||||
|
void EndCommandPacket(const PacketTrailingBits& trailingBits);
|
||||||
|
bool IgnoreNetPacketType(int32_t type);
|
||||||
|
|
||||||
|
void OnNetPacket(NetPacket& packet);
|
||||||
|
void OnGameEvent(const char *name, GameEvents::EventDataMap &data);
|
||||||
|
void OnStringtable(StringTable* table);
|
||||||
|
void UserInfoChanged(int tableIdx, int entryIdx);
|
||||||
|
|
||||||
|
std::string outputDir;
|
||||||
|
std::string outputDirVoice;
|
||||||
|
|
||||||
|
FILE* outputFp;
|
||||||
|
Logic* logic;
|
||||||
|
|
||||||
|
demoheader_t header;
|
||||||
int16_t protocol;
|
int16_t protocol;
|
||||||
NetMsg::SVC_GameEventList* gameEventList;
|
NetMsg::SVC_GameEventList* gameEventList = nullptr;
|
||||||
|
StringTableContainer* stringTables = nullptr;
|
||||||
|
VoiceDataWriter* voiceWriter = nullptr;
|
||||||
|
|
||||||
|
int32_t curTick = -1;
|
||||||
|
int32_t curFrame = -1;
|
||||||
|
|
||||||
|
float fTickInterval = -1.f;
|
||||||
|
float fTickRate = -1.f;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool connected;
|
||||||
|
player_info_t info;
|
||||||
|
} players[MAX_PLAYERS];
|
||||||
};
|
};
|
||||||
|
174
demboyz/game/stringtables.cpp
Normal file
174
demboyz/game/stringtables.cpp
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
|
||||||
|
#include "base/bitfile.h"
|
||||||
|
#include "stringtables.h"
|
||||||
|
#include "game/sourcecontext.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
static size_t strlcpy(char * dst, const char * src, size_t maxlen) {
|
||||||
|
const size_t srclen = strlen(src);
|
||||||
|
if (srclen + 1 < maxlen) {
|
||||||
|
memcpy(dst, src, srclen + 1);
|
||||||
|
} else if (maxlen != 0) {
|
||||||
|
memcpy(dst, src, maxlen - 1);
|
||||||
|
dst[maxlen-1] = '\0';
|
||||||
|
}
|
||||||
|
return srclen;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTableContainer::StringTableContainer(SourceGameContext *context):
|
||||||
|
context(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTable *StringTableContainer::GetStringTable(const char *name, bool create)
|
||||||
|
{
|
||||||
|
StringTable *table = nullptr;
|
||||||
|
for (auto& t : tables)
|
||||||
|
{
|
||||||
|
if (t.tableName.compare(name) == 0)
|
||||||
|
{
|
||||||
|
table = &t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!table && create)
|
||||||
|
{
|
||||||
|
StringTable ttable;
|
||||||
|
tables.emplace_back(ttable);
|
||||||
|
table = &tables.back();
|
||||||
|
table->id = tables.size() - 1;
|
||||||
|
table->tableName.assign(name);
|
||||||
|
table->entries.clear();
|
||||||
|
context->OnStringtable(table);
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTableContainer::DumpAll()
|
||||||
|
{
|
||||||
|
for (auto& t : tables)
|
||||||
|
{
|
||||||
|
std::cout << "[STRINGTABLE] " << t.tableName << " (" << t.entries.size() << ")\n";
|
||||||
|
int idx = 0;
|
||||||
|
for (auto& e : t.entries)
|
||||||
|
{
|
||||||
|
std::cout << idx++ << ":\t" << e.string << " (" << e.data << ")\n";
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringTableEntry *StringTable::FindEntry(const char *string)
|
||||||
|
{
|
||||||
|
for (auto& e : entries)
|
||||||
|
{
|
||||||
|
if (e.string.compare(string) == 0)
|
||||||
|
return &e;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SUBSTRING_BITS 5
|
||||||
|
struct StringHistoryEntry
|
||||||
|
{
|
||||||
|
char string[(1 << SUBSTRING_BITS)];
|
||||||
|
};
|
||||||
|
|
||||||
|
void StringTable::AddEntry(StringTableEntry *entry)
|
||||||
|
{
|
||||||
|
StringTableEntry *e = FindEntry(entry->string.c_str());
|
||||||
|
if (!e)
|
||||||
|
{
|
||||||
|
entries.emplace_back(*entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e->string.assign(entry->string);
|
||||||
|
e->data.assign(entry->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTable::ParseUpdate(bf_read& bitbuf, int numEntries, SourceGameContext& context)
|
||||||
|
{
|
||||||
|
std::vector<StringHistoryEntry> history;
|
||||||
|
int entryIndex = -1;
|
||||||
|
for (int i = 0; i < numEntries; ++i)
|
||||||
|
{
|
||||||
|
entryIndex++;
|
||||||
|
|
||||||
|
if (bitbuf.ReadOneBit() == 0)
|
||||||
|
{
|
||||||
|
entryIndex = bitbuf.ReadUBitLong(entryBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *pEntry = NULL;
|
||||||
|
char entry[1024+1];
|
||||||
|
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);
|
||||||
|
strlcpy(entry, history.at(index).string, MIN((int)sizeof(StringHistoryEntry::string), bytestocopy + 1));
|
||||||
|
bitbuf.ReadString(substr, sizeof(substr));
|
||||||
|
strncat(entry, substr, sizeof(entry) - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitbuf.ReadString(entry, sizeof(entry));
|
||||||
|
}
|
||||||
|
pEntry = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int MAX_USERDATA_BITS = 14;
|
||||||
|
unsigned char tempbuf[(1 << MAX_USERDATA_BITS)] = { 0 };
|
||||||
|
const void *pUserData = NULL;
|
||||||
|
int nUserDataBytes = 0;
|
||||||
|
if (bitbuf.ReadOneBit() != 0)
|
||||||
|
{
|
||||||
|
if (isUserDataFixedSize)
|
||||||
|
{
|
||||||
|
bitbuf.ReadBits(tempbuf, userDataSizeBits);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nUserDataBytes = bitbuf.ReadUBitLong(MAX_USERDATA_BITS);
|
||||||
|
bitbuf.ReadBytes(tempbuf, nUserDataBytes);
|
||||||
|
}
|
||||||
|
pUserData = tempbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pEntry == NULL)
|
||||||
|
{
|
||||||
|
pEntry = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entryIndex >= (int)entries.size())
|
||||||
|
{
|
||||||
|
StringTableEntry entry = {};
|
||||||
|
entry.string.assign(pEntry);
|
||||||
|
entries.emplace_back(entry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pEntry = entries[entryIndex].string.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(entryIndex < (int)entries.size());
|
||||||
|
|
||||||
|
entries[entryIndex].data.assign((const char *)pUserData, nUserDataBytes);
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
callback(id, entryIndex);
|
||||||
|
|
||||||
|
if (history.size() > 31)
|
||||||
|
{
|
||||||
|
history.erase(history.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
StringHistoryEntry she;
|
||||||
|
strlcpy(she.string, pEntry, sizeof(she.string));
|
||||||
|
history.emplace_back(she);
|
||||||
|
}
|
||||||
|
}
|
48
demboyz/game/stringtables.h
Normal file
48
demboyz/game/stringtables.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class bf_read;
|
||||||
|
class SourceGameContext;
|
||||||
|
|
||||||
|
struct StringTableEntry
|
||||||
|
{
|
||||||
|
std::string string;
|
||||||
|
std::string data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StringTable
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
std::string tableName;
|
||||||
|
uint16_t maxEntries;
|
||||||
|
bool isUserDataFixedSize;
|
||||||
|
uint16_t userDataSize;
|
||||||
|
uint8_t userDataSizeBits;
|
||||||
|
int entryBits;
|
||||||
|
|
||||||
|
void ParseUpdate(bf_read& bitbuf, int numEntries, SourceGameContext& context);
|
||||||
|
|
||||||
|
void AddEntry(StringTableEntry *entry);
|
||||||
|
StringTableEntry *FindEntry(const char *string);
|
||||||
|
|
||||||
|
std::vector<StringTableEntry> entries;
|
||||||
|
std::function<void(int, int)> callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StringTableContainer
|
||||||
|
{
|
||||||
|
StringTableContainer(SourceGameContext *context);
|
||||||
|
|
||||||
|
StringTable *GetStringTable(const char *name, bool create);
|
||||||
|
|
||||||
|
void DumpAll();
|
||||||
|
|
||||||
|
SourceGameContext *context;
|
||||||
|
std::vector<StringTable> tables;
|
||||||
|
};
|
||||||
|
|
@ -1,60 +0,0 @@
|
|||||||
|
|
||||||
#include "idemowriter.h"
|
|
||||||
#include "netmessages/nethandlers.h"
|
|
||||||
#include "demofile/demotypes.h"
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
class ConLogWriter: public IDemoWriter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConLogWriter(FILE* outputFp);
|
|
||||||
|
|
||||||
virtual void StartWriting(demoheader_t& header) override final;
|
|
||||||
virtual void EndWriting() override final;
|
|
||||||
|
|
||||||
virtual void StartCommandPacket(const CommandPacket& packet) override final;
|
|
||||||
virtual void EndCommandPacket(const PacketTrailingBits& trailingBits) override final;
|
|
||||||
|
|
||||||
virtual void WriteNetPacket(NetPacket& packet, SourceGameContext& context) override final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
FILE* m_outputFp;
|
|
||||||
};
|
|
||||||
|
|
||||||
IDemoWriter* IDemoWriter::CreateConLogWriter(void* outputFp)
|
|
||||||
{
|
|
||||||
return new ConLogWriter(reinterpret_cast<FILE*>(outputFp));
|
|
||||||
}
|
|
||||||
|
|
||||||
ConLogWriter::ConLogWriter(FILE* outputFp):
|
|
||||||
m_outputFp(outputFp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConLogWriter::StartWriting(demoheader_t& header)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConLogWriter::EndWriting()
|
|
||||||
{
|
|
||||||
fflush(m_outputFp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConLogWriter::StartCommandPacket(const CommandPacket& packet)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConLogWriter::EndCommandPacket(const PacketTrailingBits& trailingBits)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConLogWriter::WriteNetPacket(NetPacket& packet, SourceGameContext& context)
|
|
||||||
{
|
|
||||||
std::ostringstream ss;
|
|
||||||
NetHandlers::NetMsg_ToString(packet.type, ss, packet.data);
|
|
||||||
if (ss.tellp() > 0)
|
|
||||||
{
|
|
||||||
ss << "\n";
|
|
||||||
fputs(ss.str().c_str(), m_outputFp);
|
|
||||||
}
|
|
||||||
}
|
|
107
demboyz/io/demoreader.cpp
Normal file
107
demboyz/io/demoreader.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "demoreader.h"
|
||||||
|
#include "demofile/demofile.h"
|
||||||
|
#include "demofile/demotypes.h"
|
||||||
|
|
||||||
|
#include "game/sourcecontext.h"
|
||||||
|
#include "netmessages/nethandlers.h"
|
||||||
|
#include "netmessages/netcontants.h"
|
||||||
|
#include "demmessages/demhandlers.h"
|
||||||
|
#include "demmessages/dem_stringtables.h"
|
||||||
|
#include "sourcesdk/bitbuf.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
PacketTrailingBits ParsePacket(uint8_t* packet, size_t length,
|
||||||
|
SourceGameContext& context,
|
||||||
|
const NetHandlers::NetDataStructArray& netDataStructs)
|
||||||
|
{
|
||||||
|
assert(length <= NET_MAX_PAYLOAD);
|
||||||
|
bf_read bitbuf(packet, length);
|
||||||
|
NetPacket netPacket;
|
||||||
|
while (bitbuf.GetNumBitsLeft() >= NETMSG_TYPE_BITS)
|
||||||
|
{
|
||||||
|
netPacket.type = bitbuf.ReadUBitLong(NETMSG_TYPE_BITS);
|
||||||
|
netPacket.data = netDataStructs[netPacket.type];
|
||||||
|
NetHandlers::NetMsg_BitRead(netPacket.type, bitbuf, context, netPacket.data);
|
||||||
|
context.OnNetPacket(netPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
PacketTrailingBits trailingBits;
|
||||||
|
trailingBits.numTrailingBits = bitbuf.GetNumBitsLeft();
|
||||||
|
if (trailingBits.numTrailingBits)
|
||||||
|
{
|
||||||
|
trailingBits.value = bitbuf.ReadUBitLong(trailingBits.numTrailingBits);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trailingBits.value = 0;
|
||||||
|
}
|
||||||
|
return trailingBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DemoReader::ProcessDem(std::FILE* inputFp, SourceGameContext* context)
|
||||||
|
{
|
||||||
|
NetHandlers::NetDataStructArray netDataStructs;
|
||||||
|
DemHandlers::DemDataStructArray demDataStructs;
|
||||||
|
NetHandlers::CreateNetMsgStructs(netDataStructs);
|
||||||
|
DemHandlers::CreateDemMsgStructs(demDataStructs);
|
||||||
|
|
||||||
|
DemoFileReader reader(inputFp);
|
||||||
|
{
|
||||||
|
reader.ReadDemoHeader(context->header);
|
||||||
|
context->protocol = context->header.networkprotocol;
|
||||||
|
context->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dirty = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CommandPacket packet;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
reader.ReadCmdHeader(packet.cmd, packet.tick);
|
||||||
|
packet.data = demDataStructs[packet.cmd];
|
||||||
|
DemHandlers::DemMsg_FileRead(packet.cmd, reader, packet.data);
|
||||||
|
|
||||||
|
PacketTrailingBits trailingBits = PacketTrailingBits();
|
||||||
|
context->StartCommandPacket(packet);
|
||||||
|
|
||||||
|
if (packet.cmd == dem_packet || packet.cmd == dem_signon)
|
||||||
|
{
|
||||||
|
Array<uint8_t> buffer = reader.ReadRawData(NET_MAX_PAYLOAD);
|
||||||
|
trailingBits = ParsePacket(buffer.begin(), buffer.length(), *context, netDataStructs);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (packet.cmd == dem_stringtables)
|
||||||
|
{
|
||||||
|
DemMsg::Dem_StringTables *stringTables = (DemMsg::Dem_StringTables *)packet.data;
|
||||||
|
for (const auto& s : stringTables->stringtables)
|
||||||
|
{
|
||||||
|
StringTable *table = context->stringTables->GetStringTable(s.tableName.c_str(), false);
|
||||||
|
if (!table)
|
||||||
|
continue;
|
||||||
|
for (const auto& e : s.entries)
|
||||||
|
{
|
||||||
|
StringTableEntry entry;
|
||||||
|
entry.string.assign(e.entryName);
|
||||||
|
entry.data.assign(e.data.begin(), e.data.end());
|
||||||
|
table->AddEntry(&entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context->EndCommandPacket(trailingBits);
|
||||||
|
} while (packet.cmd != dem_stop);
|
||||||
|
}
|
||||||
|
catch(const char *e)
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
fprintf(stderr, "Error: %s\n", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
context->Finish(dirty);
|
||||||
|
|
||||||
|
DemHandlers::DestroyDemMsgStructs(demDataStructs);
|
||||||
|
NetHandlers::DestroyNetMsgStructs(netDataStructs);
|
||||||
|
|
||||||
|
return !dirty;
|
||||||
|
}
|
@ -1,12 +1,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "game/sourcecontext.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
class IDemoWriter;
|
|
||||||
|
|
||||||
namespace DemoReader
|
namespace DemoReader
|
||||||
{
|
{
|
||||||
void ProcessDem(std::FILE* inputFp, IDemoWriter* writer);
|
bool ProcessDem(std::FILE* inputFp, SourceGameContext* context);
|
||||||
void ProcessJson(std::FILE* inputFp, IDemoWriter* writer);
|
|
||||||
}
|
}
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
|
|
||||||
#include "idemowriter.h"
|
|
||||||
#include "demofile/demotypes.h"
|
|
||||||
#include "demofile/demofile.h"
|
|
||||||
#include "netmessages/nethandlers.h"
|
|
||||||
#include "netmessages/netcontants.h"
|
|
||||||
#include "demmessages/demhandlers.h"
|
|
||||||
#include "sourcesdk/bitbuf.h"
|
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <io.h>
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
int truncate(FILE* fp, int relative_offset)
|
|
||||||
{
|
|
||||||
fflush(fp);
|
|
||||||
#ifdef _WIN32
|
|
||||||
const int fd = _fileno(fp);
|
|
||||||
#else
|
|
||||||
const int fd = fileno(fp);
|
|
||||||
#endif
|
|
||||||
struct stat statbuf;
|
|
||||||
fstat(fd, &statbuf);
|
|
||||||
#ifdef _WIN32
|
|
||||||
return _chsize_s(fd, statbuf.st_size + relative_offset);
|
|
||||||
#else
|
|
||||||
return ftruncate(fd, statbuf.st_size + relative_offset);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
class DemoWriter: public IDemoWriter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DemoWriter(FILE* outputFp);
|
|
||||||
|
|
||||||
virtual void StartWriting(demoheader_t& header) override final;
|
|
||||||
virtual void EndWriting() override final;
|
|
||||||
|
|
||||||
virtual void StartCommandPacket(const CommandPacket& packet) override final;
|
|
||||||
virtual void EndCommandPacket(const PacketTrailingBits& trailingBits) override final;
|
|
||||||
|
|
||||||
virtual void WriteNetPacket(NetPacket& packet, SourceGameContext& context) override final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
DemoFileWriter m_writer;
|
|
||||||
bf_write m_cmdPacketBuf;
|
|
||||||
std::unique_ptr<uint8_t[]> m_packetBuffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
IDemoWriter* IDemoWriter::CreateDemoWriter(void* outputFp)
|
|
||||||
{
|
|
||||||
return new DemoWriter(reinterpret_cast<FILE*>(outputFp));
|
|
||||||
}
|
|
||||||
|
|
||||||
DemoWriter::DemoWriter(FILE* outputFp):
|
|
||||||
m_writer(outputFp),
|
|
||||||
m_cmdPacketBuf(),
|
|
||||||
m_packetBuffer(new uint8_t[NET_MAX_PAYLOAD])
|
|
||||||
{
|
|
||||||
m_cmdPacketBuf.StartWriting(m_packetBuffer.get(), NET_MAX_PAYLOAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoWriter::StartWriting(demoheader_t& header)
|
|
||||||
{
|
|
||||||
m_writer.WriteDemoHeader(header);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoWriter::EndWriting()
|
|
||||||
{
|
|
||||||
// stv demos have a byte chopped off of the end
|
|
||||||
// i dunno why, just doit
|
|
||||||
truncate(m_writer.GetFp(), -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoWriter::StartCommandPacket(const CommandPacket& packet)
|
|
||||||
{
|
|
||||||
m_writer.WriteCmdHeader(packet.cmd, packet.tick);
|
|
||||||
DemHandlers::DemMsg_FileWrite(packet.cmd, m_writer, packet.data);
|
|
||||||
m_cmdPacketBuf.Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoWriter::EndCommandPacket(const PacketTrailingBits& trailingBits)
|
|
||||||
{
|
|
||||||
if (trailingBits.numTrailingBits > 0)
|
|
||||||
{
|
|
||||||
m_cmdPacketBuf.WriteUBitLong(trailingBits.value, trailingBits.numTrailingBits);
|
|
||||||
}
|
|
||||||
const int numBitsToWrite = m_cmdPacketBuf.GetNumBitsWritten() % 8;
|
|
||||||
if (numBitsToWrite != 0)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
if (m_cmdPacketBuf.GetNumBytesWritten() > 0)
|
|
||||||
{
|
|
||||||
m_writer.WriteRawData(m_cmdPacketBuf.GetBasePointer(), m_cmdPacketBuf.GetNumBytesWritten());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoWriter::WriteNetPacket(NetPacket& packet, SourceGameContext& context)
|
|
||||||
{
|
|
||||||
m_cmdPacketBuf.WriteUBitLong(packet.type, NETMSG_TYPE_BITS);
|
|
||||||
NetHandlers::NetMsg_BitWrite(packet.type, m_cmdPacketBuf, context, packet.data);
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
|
|
||||||
#include "demoreader.h"
|
|
||||||
#include "idemowriter.h"
|
|
||||||
#include "demofile/demofile.h"
|
|
||||||
#include "demofile/demotypes.h"
|
|
||||||
|
|
||||||
#include "game/sourcecontext.h"
|
|
||||||
#include "netmessages/nethandlers.h"
|
|
||||||
#include "netmessages/netcontants.h"
|
|
||||||
#include "demmessages/demhandlers.h"
|
|
||||||
#include "sourcesdk/bitbuf.h"
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
PacketTrailingBits ParsePacket(uint8_t* packet, size_t length,
|
|
||||||
SourceGameContext& context, IDemoWriter* writer,
|
|
||||||
const NetHandlers::NetDataStructArray& netDataStructs)
|
|
||||||
{
|
|
||||||
assert(length <= NET_MAX_PAYLOAD);
|
|
||||||
bf_read bitbuf(packet, length);
|
|
||||||
NetPacket netPacket;
|
|
||||||
while (bitbuf.GetNumBitsLeft() >= NETMSG_TYPE_BITS)
|
|
||||||
{
|
|
||||||
netPacket.type = bitbuf.ReadUBitLong(NETMSG_TYPE_BITS);
|
|
||||||
netPacket.data = netDataStructs[netPacket.type];
|
|
||||||
NetHandlers::NetMsg_BitRead(netPacket.type, bitbuf, context, netPacket.data);
|
|
||||||
writer->WriteNetPacket(netPacket, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketTrailingBits trailingBits;
|
|
||||||
trailingBits.numTrailingBits = bitbuf.GetNumBitsLeft();
|
|
||||||
if (trailingBits.numTrailingBits)
|
|
||||||
{
|
|
||||||
trailingBits.value = bitbuf.ReadUBitLong(trailingBits.numTrailingBits);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
trailingBits.value = 0;
|
|
||||||
}
|
|
||||||
return trailingBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoReader::ProcessDem(std::FILE* inputFp, IDemoWriter* writer)
|
|
||||||
{
|
|
||||||
NetHandlers::NetDataStructArray netDataStructs;
|
|
||||||
DemHandlers::DemDataStructArray demDataStructs;
|
|
||||||
NetHandlers::CreateNetMsgStructs(netDataStructs);
|
|
||||||
DemHandlers::CreateDemMsgStructs(demDataStructs);
|
|
||||||
|
|
||||||
SourceGameContext context = SourceGameContext();
|
|
||||||
DemoFileReader reader(inputFp);
|
|
||||||
{
|
|
||||||
demoheader_t header;
|
|
||||||
reader.ReadDemoHeader(header);
|
|
||||||
writer->StartWriting(header);
|
|
||||||
context.protocol = header.networkprotocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandPacket packet;
|
|
||||||
int frame = -1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
size_t rawDataSize = 0;
|
|
||||||
reader.ReadCmdHeader(packet.cmd, packet.tick);
|
|
||||||
packet.data = demDataStructs[packet.cmd];
|
|
||||||
DemHandlers::DemMsg_FileRead(packet.cmd, reader, packet.data);
|
|
||||||
|
|
||||||
PacketTrailingBits trailingBits = PacketTrailingBits();
|
|
||||||
writer->StartCommandPacket(packet);
|
|
||||||
frame += (packet.cmd == dem_packet);
|
|
||||||
if (packet.cmd == dem_packet || packet.cmd == dem_signon)
|
|
||||||
{
|
|
||||||
Array<uint8_t> buffer = reader.ReadRawData(NET_MAX_PAYLOAD);
|
|
||||||
trailingBits = ParsePacket(buffer.begin(), buffer.length(), context, writer, netDataStructs);
|
|
||||||
}
|
|
||||||
writer->EndCommandPacket(trailingBits);
|
|
||||||
} while (packet.cmd != dem_stop);
|
|
||||||
writer->EndWriting();
|
|
||||||
|
|
||||||
DemHandlers::DestroyDemMsgStructs(demDataStructs);
|
|
||||||
NetHandlers::DestroyNetMsgStructs(netDataStructs);
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
struct democmdinfo_t;
|
|
||||||
struct demoheader_t;
|
|
||||||
struct CommandPacket;
|
|
||||||
struct NetPacket;
|
|
||||||
struct SourceGameContext;
|
|
||||||
|
|
||||||
struct CommandPacket
|
|
||||||
{
|
|
||||||
unsigned char cmd;
|
|
||||||
int32_t tick;
|
|
||||||
|
|
||||||
void* data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NetPacket
|
|
||||||
{
|
|
||||||
int32_t type;
|
|
||||||
void* data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PacketTrailingBits
|
|
||||||
{
|
|
||||||
uint32_t numTrailingBits;
|
|
||||||
uint32_t value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IDemoWriter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~IDemoWriter() {}
|
|
||||||
|
|
||||||
virtual void StartWriting(demoheader_t& header) = 0;
|
|
||||||
virtual void EndWriting() = 0;
|
|
||||||
|
|
||||||
virtual void StartCommandPacket(const CommandPacket& packet) = 0;
|
|
||||||
virtual void EndCommandPacket(const PacketTrailingBits& trailingBits) = 0;
|
|
||||||
|
|
||||||
virtual void WriteNetPacket(NetPacket& packet, SourceGameContext& context) = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static IDemoWriter* CreateJsonWriter(void* outputFp);
|
|
||||||
static IDemoWriter* CreateDemoWriter(void* outputFp);
|
|
||||||
static IDemoWriter* CreateConLogWriter(void* outputFp);
|
|
||||||
static IDemoWriter* CreateVoiceDataWriter(const char* outputPath);
|
|
||||||
|
|
||||||
static void FreeDemoWriter(IDemoWriter* writer)
|
|
||||||
{
|
|
||||||
delete writer;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,92 +0,0 @@
|
|||||||
|
|
||||||
#include "demoreader.h"
|
|
||||||
#include "demofile/demotypes.h"
|
|
||||||
#include "demofile/demojson.h"
|
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "io/idemowriter.h"
|
|
||||||
|
|
||||||
#include "game/sourcecontext.h"
|
|
||||||
#include "netmessages/nethandlers.h"
|
|
||||||
#include "demmessages/demhandlers.h"
|
|
||||||
|
|
||||||
int32_t ReadNetpacket(base::JsonReaderFile& jsonReader, PacketTrailingBits& trailingBits)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonReader.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
const int32_t type = reader.ReadInt32("netpacket");
|
|
||||||
if (type < 0)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonReader.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
trailingBits.numTrailingBits = reader.ReadInt32("numTrailingBits");
|
|
||||||
trailingBits.value = reader.ReadInt32("trailingBitsValue");
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketTrailingBits ParsePacket(base::JsonReaderFile& jsonReader,
|
|
||||||
SourceGameContext& context, IDemoWriter* writer,
|
|
||||||
const NetHandlers::NetDataStructArray& netDataStructs)
|
|
||||||
{
|
|
||||||
PacketTrailingBits trailingBits = PacketTrailingBits();
|
|
||||||
NetPacket netPacket = NetPacket();
|
|
||||||
while ((netPacket.type = ReadNetpacket(jsonReader, trailingBits)) >= 0)
|
|
||||||
{
|
|
||||||
netPacket.data = netDataStructs[netPacket.type];
|
|
||||||
NetHandlers::NetMsg_JsonRead(netPacket.type, jsonReader, context, netPacket.data);
|
|
||||||
writer->WriteNetPacket(netPacket, context);
|
|
||||||
}
|
|
||||||
return trailingBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DemoReader::ProcessJson(std::FILE* inputFp, IDemoWriter* writer)
|
|
||||||
{
|
|
||||||
NetHandlers::NetDataStructArray netDataStructs;
|
|
||||||
DemHandlers::DemDataStructArray demDataStructs;
|
|
||||||
NetHandlers::CreateNetMsgStructs(netDataStructs);
|
|
||||||
DemHandlers::CreateDemMsgStructs(demDataStructs);
|
|
||||||
|
|
||||||
SourceGameContext context = SourceGameContext();
|
|
||||||
char buffer[4096];
|
|
||||||
base::JsonReaderFile jsonReader(inputFp, buffer, sizeof(buffer));
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonReader.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
|
|
||||||
demoheader_t header;
|
|
||||||
if (!DemoJsonReader::ReadDemoHeader(reader, header))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
writer->StartWriting(header);
|
|
||||||
context.protocol = header.networkprotocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandPacket packet;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonReader.ParseObject();
|
|
||||||
if (reader.HasReadError())
|
|
||||||
{
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
}
|
|
||||||
|
|
||||||
DemoJsonReader::ReadCmdHeader(reader, packet.cmd, packet.tick);
|
|
||||||
}
|
|
||||||
packet.data = demDataStructs[packet.cmd];
|
|
||||||
DemHandlers::DemMsg_JsonRead(packet.cmd, jsonReader, packet.data);
|
|
||||||
|
|
||||||
PacketTrailingBits trailingBits = PacketTrailingBits();
|
|
||||||
writer->StartCommandPacket(packet);
|
|
||||||
if (packet.cmd == dem_packet || packet.cmd == dem_signon)
|
|
||||||
{
|
|
||||||
trailingBits = ParsePacket(jsonReader, context, writer, netDataStructs);
|
|
||||||
}
|
|
||||||
writer->EndCommandPacket(trailingBits);
|
|
||||||
} while (packet.cmd != dem_stop);
|
|
||||||
writer->EndWriting();
|
|
||||||
|
|
||||||
DemHandlers::DestroyDemMsgStructs(demDataStructs);
|
|
||||||
NetHandlers::DestroyNetMsgStructs(netDataStructs);
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
|
|
||||||
#include "idemowriter.h"
|
|
||||||
#include "demofile/demojson.h"
|
|
||||||
#include "demofile/demotypes.h"
|
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "demmessages/demhandlers.h"
|
|
||||||
#include "netmessages/nethandlers.h"
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
class JsonWriter: public IDemoWriter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
JsonWriter(FILE* outputFp);
|
|
||||||
|
|
||||||
virtual void StartWriting(demoheader_t& header) override final;
|
|
||||||
virtual void EndWriting() override final;
|
|
||||||
|
|
||||||
virtual void StartCommandPacket(const CommandPacket& packet) override final;
|
|
||||||
virtual void EndCommandPacket(const PacketTrailingBits& trailingBits) override final;
|
|
||||||
|
|
||||||
virtual void WriteNetPacket(NetPacket& packet, SourceGameContext& context) override final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
base::JsonWriterFile m_jsonFile;
|
|
||||||
bool m_writingNetPackets;
|
|
||||||
char m_buffer[4096];
|
|
||||||
};
|
|
||||||
|
|
||||||
IDemoWriter* IDemoWriter::CreateJsonWriter(void* outputFp)
|
|
||||||
{
|
|
||||||
return new JsonWriter(reinterpret_cast<FILE*>(outputFp));
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonWriter::JsonWriter(FILE* outputFp):
|
|
||||||
m_jsonFile(outputFp, m_buffer, sizeof(m_buffer)),
|
|
||||||
m_writingNetPackets(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriter::StartWriting(demoheader_t& header)
|
|
||||||
{
|
|
||||||
auto& jsonFile = m_jsonFile;
|
|
||||||
jsonFile.Reset();
|
|
||||||
jsonFile.StartObject();
|
|
||||||
DemoJsonWriter::WriteDemoHeader(jsonFile, header);
|
|
||||||
jsonFile.EndObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriter::EndWriting()
|
|
||||||
{
|
|
||||||
auto& jsonFile = m_jsonFile;
|
|
||||||
jsonFile.Flush();
|
|
||||||
assert(jsonFile.IsComplete());
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriter::StartCommandPacket(const CommandPacket& packet)
|
|
||||||
{
|
|
||||||
auto& jsonFile = m_jsonFile;
|
|
||||||
jsonFile.Reset();
|
|
||||||
jsonFile.StartObject();
|
|
||||||
DemoJsonWriter::WriteCmdHeader(jsonFile, packet.cmd, packet.tick);
|
|
||||||
jsonFile.EndObject();
|
|
||||||
|
|
||||||
DemHandlers::DemMsg_JsonWrite(packet.cmd, jsonFile, packet.data);
|
|
||||||
assert(jsonFile.IsComplete());
|
|
||||||
|
|
||||||
if (packet.cmd == dem_packet || packet.cmd == dem_signon)
|
|
||||||
{
|
|
||||||
m_writingNetPackets = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriter::EndCommandPacket(const PacketTrailingBits& trailingBits)
|
|
||||||
{
|
|
||||||
if (m_writingNetPackets)
|
|
||||||
{
|
|
||||||
m_writingNetPackets = false;
|
|
||||||
auto& jsonFile = m_jsonFile;
|
|
||||||
jsonFile.Reset();
|
|
||||||
jsonFile.StartObject();
|
|
||||||
jsonFile.WriteInt32("netpacket", -1);
|
|
||||||
jsonFile.EndObject();
|
|
||||||
|
|
||||||
jsonFile.Reset();
|
|
||||||
jsonFile.StartObject();
|
|
||||||
jsonFile.WriteInt32("numTrailingBits", trailingBits.numTrailingBits);
|
|
||||||
jsonFile.WriteInt32("trailingBitsValue", trailingBits.value, (trailingBits.numTrailingBits > 0));
|
|
||||||
jsonFile.EndObject();
|
|
||||||
assert(jsonFile.IsComplete());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JsonWriter::WriteNetPacket(NetPacket& packet, SourceGameContext& context)
|
|
||||||
{
|
|
||||||
auto& jsonFile = m_jsonFile;
|
|
||||||
jsonFile.Reset();
|
|
||||||
jsonFile.StartObject();
|
|
||||||
jsonFile.WriteInt32("netpacket", packet.type);
|
|
||||||
jsonFile.EndObject();
|
|
||||||
|
|
||||||
NetHandlers::NetMsg_JsonWrite(packet.type, jsonFile, context, packet.data);
|
|
||||||
assert(jsonFile.IsComplete());
|
|
||||||
}
|
|
81
demboyz/io/voicewriter/opusfilewriter.h
Normal file
81
demboyz/io/voicewriter/opusfilewriter.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <opusenc.h>
|
||||||
|
|
||||||
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||||
|
|
||||||
|
class OpusFileWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpusFileWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~OpusFileWriter()
|
||||||
|
{
|
||||||
|
assert(!m_Enc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init(const char* file, uint32_t sampleRate)
|
||||||
|
{
|
||||||
|
assert(!m_Enc);
|
||||||
|
m_Samples = 0;
|
||||||
|
|
||||||
|
m_Comments = ope_comments_create();
|
||||||
|
|
||||||
|
int error;
|
||||||
|
m_Enc = ope_encoder_create_file(file, m_Comments, sampleRate, 1, 0, &error);
|
||||||
|
assert(error == 0);
|
||||||
|
|
||||||
|
ope_encoder_ctl(m_Enc, OPUS_SET_DTX(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Close()
|
||||||
|
{
|
||||||
|
if(!m_Enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ope_encoder_drain(m_Enc);
|
||||||
|
ope_encoder_destroy(m_Enc);
|
||||||
|
ope_comments_destroy(m_Comments);
|
||||||
|
m_Enc = nullptr;
|
||||||
|
m_Comments = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteSamples(const int16_t* samples, uint32_t numSamples)
|
||||||
|
{
|
||||||
|
if(!m_Enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ope_encoder_write(m_Enc, samples, numSamples);
|
||||||
|
m_Samples += numSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PadSilence(uint32_t numSamples)
|
||||||
|
{
|
||||||
|
if(!m_Enc || m_Samples >= numSamples)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static const int16_t silence[128] = {0};
|
||||||
|
uint32_t pad = numSamples - m_Samples;
|
||||||
|
while(pad > 0)
|
||||||
|
{
|
||||||
|
const int samples = MIN(sizeof(silence) / bytesPerSample, pad);
|
||||||
|
ope_encoder_write(m_Enc, silence, samples);
|
||||||
|
pad -= samples;
|
||||||
|
}
|
||||||
|
m_Samples = numSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
OggOpusComments *m_Comments = nullptr;
|
||||||
|
OggOpusEnc *m_Enc = nullptr;
|
||||||
|
uint32_t m_Samples = 0;
|
||||||
|
|
||||||
|
static const uint32_t bytesPerSample = 2;
|
||||||
|
};
|
@ -1,27 +1,17 @@
|
|||||||
|
|
||||||
#include "../idemowriter.h"
|
|
||||||
#include "netmessages/netmessages.h"
|
#include "netmessages/netmessages.h"
|
||||||
|
|
||||||
#include "netmessages/svc_voiceinit.h"
|
#include "netmessages/svc_voiceinit.h"
|
||||||
#include "netmessages/svc_voicedata.h"
|
#include "netmessages/svc_voicedata.h"
|
||||||
|
|
||||||
#include "celt/celt.h"
|
#include <celt/celt.h>
|
||||||
|
#include <SKP_Silk_SDK_API.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "wavfilewriter.h"
|
#include "base/CRC.h"
|
||||||
|
#include "game/logic.h"
|
||||||
#ifdef _WIN32
|
#include "voicedatawriter.h"
|
||||||
//#define USE_VAUDIO_CELT
|
#include <cstring>
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_PLAYERS 33
|
|
||||||
|
|
||||||
#ifdef USE_VAUDIO_CELT
|
|
||||||
#define VC_EXTRALEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <Windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct CeltConfig
|
struct CeltConfig
|
||||||
{
|
{
|
||||||
@ -39,198 +29,141 @@ static CeltConfig sCeltConfigs[] =
|
|||||||
{ 44100, 1024, 128 } // vaudio_celt_high
|
{ 44100, 1024, 128 } // vaudio_celt_high
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef USE_VAUDIO_CELT
|
bool CeltVoiceDecoder::DoInit(CELTMode* celtMode, uint32_t frameSizeSamples, uint32_t encodedFrameSizeBytes)
|
||||||
|
|
||||||
class IVoiceCodec
|
|
||||||
{
|
{
|
||||||
protected:
|
if(m_celtDecoder)
|
||||||
virtual ~IVoiceCodec() {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Initialize the object. The uncompressed format is always 8-bit signed mono.
|
|
||||||
virtual bool Init( int quality ) = 0;
|
|
||||||
|
|
||||||
// Use this to delete the object.
|
|
||||||
virtual void Release() = 0;
|
|
||||||
|
|
||||||
// Compress the voice data.
|
|
||||||
// pUncompressed - 16-bit signed mono voice data.
|
|
||||||
// maxCompressedBytes - The length of the pCompressed buffer. Don't exceed this.
|
|
||||||
// bFinal - Set to true on the last call to Compress (the user stopped talking).
|
|
||||||
// Some codecs like big block sizes and will hang onto data you give them in Compress calls.
|
|
||||||
// When you call with bFinal, the codec will give you compressed data no matter what.
|
|
||||||
// Return the number of bytes you filled into pCompressed.
|
|
||||||
virtual int Compress(const char *pUncompressed, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal) = 0;
|
|
||||||
|
|
||||||
// Decompress voice data. pUncompressed is 16-bit signed mono.
|
|
||||||
virtual int Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes) = 0;
|
|
||||||
|
|
||||||
// Some codecs maintain state between Compress and Decompress calls. This should clear that state.
|
|
||||||
virtual bool ResetState() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void* (CreateInterfaceFn)(const char *pName, int *pReturnCode);
|
|
||||||
static HINSTANCE celtDll;
|
|
||||||
static CreateInterfaceFn* createInterfaceFunc;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class CeltVoiceDecoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool DoInit(CELTMode* celtMode, uint32_t frameSizeSamples, uint32_t encodedFrameSizeBytes)
|
|
||||||
{
|
{
|
||||||
if(m_celtDecoder)
|
return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int error = CELT_OK;
|
|
||||||
m_celtDecoder = celt_decoder_create_custom(celtMode, sCeltChannels, &error);
|
|
||||||
assert(error == CELT_OK);
|
|
||||||
assert(m_celtDecoder);
|
|
||||||
|
|
||||||
m_frameSizeSamples = frameSizeSamples;
|
|
||||||
m_encodedFrameSizeBytes = encodedFrameSizeBytes;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Destroy()
|
int error = CELT_OK;
|
||||||
{
|
m_celtDecoder = celt_decoder_create_custom(celtMode, sCeltChannels, &error);
|
||||||
celt_decoder_destroy(m_celtDecoder);
|
assert(error == CELT_OK);
|
||||||
m_celtDecoder = NULL;
|
assert(m_celtDecoder);
|
||||||
}
|
|
||||||
|
|
||||||
void Reset()
|
m_frameSizeSamples = frameSizeSamples;
|
||||||
{
|
m_encodedFrameSizeBytes = encodedFrameSizeBytes;
|
||||||
}
|
return true;
|
||||||
|
|
||||||
int Decompress(
|
|
||||||
const uint8_t* compressedData,
|
|
||||||
int compressedBytes,
|
|
||||||
int16_t* uncompressedData,
|
|
||||||
int maxUncompressedSamples)
|
|
||||||
{
|
|
||||||
int curCompressedByte = 0;
|
|
||||||
int curDecompressedSample = 0;
|
|
||||||
|
|
||||||
const uint32_t encodedframeSizeBytes = m_encodedFrameSizeBytes;
|
|
||||||
const uint32_t frameSizeSamples = m_frameSizeSamples;
|
|
||||||
while(
|
|
||||||
((compressedBytes - curCompressedByte) >= encodedframeSizeBytes) &&
|
|
||||||
((maxUncompressedSamples - curDecompressedSample) >= frameSizeSamples))
|
|
||||||
{
|
|
||||||
DecodeFrame(&compressedData[curCompressedByte], &uncompressedData[curDecompressedSample]);
|
|
||||||
curCompressedByte += encodedframeSizeBytes;
|
|
||||||
curDecompressedSample += frameSizeSamples;
|
|
||||||
}
|
|
||||||
return curDecompressedSample;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void DecodeFrame(const uint8_t* compressedData, int16_t* uncompressedData)
|
|
||||||
{
|
|
||||||
int error = celt_decode(m_celtDecoder, compressedData, m_encodedFrameSizeBytes, uncompressedData, m_frameSizeSamples);
|
|
||||||
assert(error >= CELT_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const int sCeltChannels = 1;
|
|
||||||
|
|
||||||
private:
|
|
||||||
CELTDecoder* m_celtDecoder = NULL;
|
|
||||||
uint32_t m_frameSizeSamples = 0;
|
|
||||||
uint32_t m_encodedFrameSizeBytes = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // USE_VAUDIO_CELT
|
|
||||||
|
|
||||||
class VoiceDataWriter: public IDemoWriter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VoiceDataWriter(const char* outputPath);
|
|
||||||
|
|
||||||
virtual void StartWriting(demoheader_t& header) override final;
|
|
||||||
virtual void EndWriting() override final;
|
|
||||||
|
|
||||||
virtual void StartCommandPacket(const CommandPacket& packet) override final;
|
|
||||||
virtual void EndCommandPacket(const PacketTrailingBits& trailingBits) override final;
|
|
||||||
|
|
||||||
virtual void WriteNetPacket(NetPacket& packet, SourceGameContext& context) override final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct PlayerVoiceState
|
|
||||||
{
|
|
||||||
#ifdef USE_VAUDIO_CELT
|
|
||||||
IVoiceCodec* celtDecoder = nullptr;
|
|
||||||
#else
|
|
||||||
CeltVoiceDecoder decoder;
|
|
||||||
#endif
|
|
||||||
WaveFileWriter wavWriter;
|
|
||||||
int32_t lastVoiceDataTick = -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
CELTMode* m_celtMode;
|
|
||||||
PlayerVoiceState m_playerVoiceStates[MAX_PLAYERS];
|
|
||||||
|
|
||||||
int32_t m_curTick;
|
|
||||||
const char* m_outputPath;
|
|
||||||
|
|
||||||
int16_t m_decodeBuffer[8192];
|
|
||||||
|
|
||||||
static const int sQuality = 3;
|
|
||||||
};
|
|
||||||
|
|
||||||
IDemoWriter* IDemoWriter::CreateVoiceDataWriter(const char* outputPath)
|
|
||||||
{
|
|
||||||
return new VoiceDataWriter(outputPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VoiceDataWriter::VoiceDataWriter(const char* outputPath):
|
void CeltVoiceDecoder::Destroy()
|
||||||
m_celtMode(nullptr),
|
{
|
||||||
m_playerVoiceStates(),
|
celt_decoder_destroy(m_celtDecoder);
|
||||||
m_curTick(-1),
|
m_celtDecoder = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CeltVoiceDecoder::Reset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int CeltVoiceDecoder::Decompress(
|
||||||
|
const uint8_t* compressedData,
|
||||||
|
uint32_t compressedBytes,
|
||||||
|
int16_t* uncompressedData,
|
||||||
|
uint32_t maxUncompressedSamples)
|
||||||
|
{
|
||||||
|
uint32_t curCompressedByte = 0;
|
||||||
|
uint32_t curDecompressedSample = 0;
|
||||||
|
|
||||||
|
const uint32_t encodedframeSizeBytes = m_encodedFrameSizeBytes;
|
||||||
|
const uint32_t frameSizeSamples = m_frameSizeSamples;
|
||||||
|
while(
|
||||||
|
((compressedBytes - curCompressedByte) >= encodedframeSizeBytes) &&
|
||||||
|
((maxUncompressedSamples - curDecompressedSample) >= frameSizeSamples))
|
||||||
|
{
|
||||||
|
DecodeFrame(&compressedData[curCompressedByte], &uncompressedData[curDecompressedSample]);
|
||||||
|
curCompressedByte += encodedframeSizeBytes;
|
||||||
|
curDecompressedSample += frameSizeSamples;
|
||||||
|
}
|
||||||
|
return curDecompressedSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CeltVoiceDecoder::DecodeFrame(const uint8_t* compressedData, int16_t* uncompressedData)
|
||||||
|
{
|
||||||
|
int error = celt_decode(m_celtDecoder, compressedData, m_encodedFrameSizeBytes, uncompressedData, m_frameSizeSamples);
|
||||||
|
assert(error >= CELT_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SilkVoiceDecoder::DoInit(int32_t sampleRate)
|
||||||
|
{
|
||||||
|
m_Silk_DecoderControl.API_sampleRate = sampleRate;
|
||||||
|
if(m_Silk_DecoderState)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int decoderSize;
|
||||||
|
SKP_Silk_SDK_Get_Decoder_Size(&decoderSize);
|
||||||
|
|
||||||
|
m_Silk_DecoderState = malloc(decoderSize);
|
||||||
|
assert(m_Silk_DecoderState != NULL);
|
||||||
|
|
||||||
|
int retEnc = SKP_Silk_SDK_InitDecoder(m_Silk_DecoderState);
|
||||||
|
assert(retEnc == SKP_SILK_NO_ERROR);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SilkVoiceDecoder::Destroy()
|
||||||
|
{
|
||||||
|
if(m_Silk_DecoderState)
|
||||||
|
free(m_Silk_DecoderState);
|
||||||
|
m_Silk_DecoderState = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SilkVoiceDecoder::Reset()
|
||||||
|
{
|
||||||
|
SKP_Silk_SDK_InitDecoder(m_Silk_DecoderState);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SilkVoiceDecoder::Decompress(
|
||||||
|
const uint8_t* compressedData,
|
||||||
|
uint32_t compressedBytes,
|
||||||
|
int16_t* uncompressedData,
|
||||||
|
uint32_t maxUncompressedSamples)
|
||||||
|
{
|
||||||
|
short nSamplesOut = maxUncompressedSamples;
|
||||||
|
int decodeRes = SKP_Silk_SDK_Decode(m_Silk_DecoderState, &m_Silk_DecoderControl, 0, compressedData, compressedBytes, uncompressedData, &nSamplesOut);
|
||||||
|
|
||||||
|
if (SKP_SILK_NO_ERROR != decodeRes)
|
||||||
|
return 0;
|
||||||
|
return nSamplesOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VoiceDataWriter::VoiceDataWriter(SourceGameContext* context, const char* outputPath):
|
||||||
|
context(context),
|
||||||
m_outputPath(outputPath)
|
m_outputPath(outputPath)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceDataWriter::StartWriting(demoheader_t& header)
|
void VoiceDataWriter::Start()
|
||||||
{
|
{
|
||||||
#ifdef USE_VAUDIO_CELT
|
|
||||||
celtDll = LoadLibrary(TEXT("vaudio_celt.dll"));
|
|
||||||
createInterfaceFunc = (CreateInterfaceFn*)GetProcAddress(celtDll, "CreateInterface");
|
|
||||||
#else
|
|
||||||
int error = CELT_OK;
|
int error = CELT_OK;
|
||||||
const CeltConfig& config = sCeltConfigs[sQuality];
|
const CeltConfig& config = sCeltConfigs[sQuality];
|
||||||
m_celtMode = celt_mode_create(config.sampleRate, config.frameSizeSamples, &error);
|
m_celtMode = celt_mode_create(config.sampleRate, config.frameSizeSamples, &error);
|
||||||
assert(error == CELT_OK);
|
assert(error == CELT_OK);
|
||||||
assert(m_celtMode);
|
assert(m_celtMode);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceDataWriter::EndWriting()
|
void VoiceDataWriter::Finish()
|
||||||
{
|
{
|
||||||
for(PlayerVoiceState& state : m_playerVoiceStates)
|
for(auto& state : m_playerVoiceStates)
|
||||||
{
|
{
|
||||||
#ifdef USE_VAUDIO_CELT
|
state.second.celt_decoder.Destroy();
|
||||||
if(state.celtDecoder)
|
state.second.silk_decoder.Destroy();
|
||||||
{
|
|
||||||
state.celtDecoder->Release();
|
state.second.fileWriter.PadSilence((m_curTick * state.second.sampleRate) / context->fTickRate);
|
||||||
}
|
state.second.fileWriter.Close();
|
||||||
#else
|
state.second.lastVoiceDataTick = -1;
|
||||||
state.decoder.Destroy();
|
|
||||||
#endif
|
|
||||||
state.wavWriter.Close();
|
|
||||||
state.lastVoiceDataTick = -1;
|
|
||||||
}
|
}
|
||||||
#ifndef USE_VAUDIO_CELT
|
|
||||||
if(m_celtMode)
|
if(m_celtMode)
|
||||||
{
|
{
|
||||||
celt_mode_destroy(m_celtMode);
|
celt_mode_destroy(m_celtMode);
|
||||||
m_celtMode = nullptr;
|
m_celtMode = nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceDataWriter::StartCommandPacket(const CommandPacket& packet)
|
void VoiceDataWriter::StartCommandPacket(const CommandPacket& packet)
|
||||||
@ -240,53 +173,200 @@ void VoiceDataWriter::StartCommandPacket(const CommandPacket& packet)
|
|||||||
|
|
||||||
void VoiceDataWriter::EndCommandPacket(const PacketTrailingBits& trailingBits)
|
void VoiceDataWriter::EndCommandPacket(const PacketTrailingBits& trailingBits)
|
||||||
{
|
{
|
||||||
|
const int tickMargin = context->fTickRate / 10.0; // 100ms
|
||||||
|
if (m_curTick <= tickMargin)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(auto& state : m_playerVoiceStates)
|
||||||
|
{
|
||||||
|
if((m_curTick - state.second.lastVoiceDataTick) > tickMargin)
|
||||||
|
state.second.fileWriter.PadSilence((m_curTick * state.second.sampleRate) / context->fTickRate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceDataWriter::WriteNetPacket(NetPacket& packet, SourceGameContext& context)
|
int VoiceDataWriter::ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerVoiceState& state)
|
||||||
|
{
|
||||||
|
int numDecompressedSamples = 0;
|
||||||
|
int pos = 0;
|
||||||
|
if(numBytes < 4+4+4+1+2)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int dataLen = numBytes - 4; // skip CRC
|
||||||
|
|
||||||
|
uint32_t CRCdemo = *((uint32_t *)&bytes[dataLen]);
|
||||||
|
uint32_t CRCdata = CRC::Calculate(bytes, dataLen, CRC::CRC_32());
|
||||||
|
if(CRCdata != CRCdemo)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
//uint32_t iSteamAccountID = *((uint32_t *)&bytes[pos]);
|
||||||
|
pos += 4;
|
||||||
|
uint32_t iSteamCommunity = *((uint32_t *)&bytes[pos]);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
if(iSteamCommunity != 0x1100001)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (pos < dataLen)
|
||||||
|
{
|
||||||
|
uint8_t payloadType = bytes[pos];
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
switch(payloadType)
|
||||||
|
{
|
||||||
|
case 11: // Sample Rate
|
||||||
|
{
|
||||||
|
if(pos + 2 > dataLen)
|
||||||
|
return numDecompressedSamples;
|
||||||
|
short rate = *((int16_t *)&bytes[pos]);
|
||||||
|
pos += 2;
|
||||||
|
state.silk_decoder.DoInit(rate);
|
||||||
|
state.sampleRate = rate;
|
||||||
|
} break;
|
||||||
|
case 10: // Unknown / Unused
|
||||||
|
{
|
||||||
|
if(pos + 2 > dataLen)
|
||||||
|
return numDecompressedSamples;
|
||||||
|
//short unk = *((int16_t *)&bytes[pos]);
|
||||||
|
pos += 2;
|
||||||
|
} break;
|
||||||
|
case 1: // Unknown Codec???
|
||||||
|
case 2: // Speex Data (Unsupported)
|
||||||
|
case 3: // Uncompressed Data
|
||||||
|
case 4: // SILK Data
|
||||||
|
{
|
||||||
|
if(pos + 2 > dataLen)
|
||||||
|
return numDecompressedSamples;
|
||||||
|
short length = *((int16_t *)&bytes[pos]);
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
if(pos + length > dataLen)
|
||||||
|
return numDecompressedSamples;
|
||||||
|
|
||||||
|
if(payloadType == 3)
|
||||||
|
{
|
||||||
|
memcpy(&m_decodeBuffer[numDecompressedSamples], &bytes[pos], length);
|
||||||
|
numDecompressedSamples += length / sizeof(int16_t);
|
||||||
|
}
|
||||||
|
else if(payloadType == 4)
|
||||||
|
{
|
||||||
|
int tpos = pos;
|
||||||
|
int maxpos = tpos + length;
|
||||||
|
while(tpos <= (maxpos - 2))
|
||||||
|
{
|
||||||
|
short chunkLength = *((int16_t *)&bytes[tpos]);
|
||||||
|
tpos += 2;
|
||||||
|
|
||||||
|
if(chunkLength == -1)
|
||||||
|
{
|
||||||
|
state.silk_decoder.Reset();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(chunkLength == 0)
|
||||||
|
{
|
||||||
|
// DTX (discontinued transmission)
|
||||||
|
int numEmptySamples = state.sampleRate / 50;
|
||||||
|
memset(&m_decodeBuffer[numDecompressedSamples], 0, numEmptySamples * sizeof(int16_t));
|
||||||
|
numDecompressedSamples += numEmptySamples;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tpos + chunkLength > maxpos)
|
||||||
|
return numDecompressedSamples;
|
||||||
|
|
||||||
|
int ret = state.silk_decoder.Decompress(&bytes[tpos], chunkLength, &m_decodeBuffer[numDecompressedSamples],
|
||||||
|
(sizeof(m_decodeBuffer) / sizeof(int16_t)) - numDecompressedSamples);
|
||||||
|
numDecompressedSamples += ret;
|
||||||
|
tpos += chunkLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos += length;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case 0: // Silence
|
||||||
|
{
|
||||||
|
if(pos + 2 > dataLen)
|
||||||
|
return numDecompressedSamples;
|
||||||
|
short numSamples = *((int16_t *)&bytes[pos]);
|
||||||
|
memset(&m_decodeBuffer[numDecompressedSamples], 0, numSamples * sizeof(int16_t));
|
||||||
|
numDecompressedSamples += numSamples;
|
||||||
|
pos += 2;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return numDecompressedSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoiceDataWriter::OnNetPacket(NetPacket& packet)
|
||||||
{
|
{
|
||||||
if(packet.type == NetMsg::svc_VoiceInit)
|
if(packet.type == NetMsg::svc_VoiceInit)
|
||||||
{
|
{
|
||||||
NetMsg::SVC_VoiceInit* voiceInit = static_cast<NetMsg::SVC_VoiceInit*>(packet.data);
|
NetMsg::SVC_VoiceInit* voiceInit = static_cast<NetMsg::SVC_VoiceInit*>(packet.data);
|
||||||
assert(!strcmp(voiceInit->voiceCodec, "vaudio_celt"));
|
if(!strcmp(voiceInit->voiceCodec, "vaudio_celt"))
|
||||||
assert(voiceInit->quality == NetMsg::SVC_VoiceInit::QUALITY_HAS_SAMPLE_RATE);
|
{
|
||||||
assert(voiceInit->sampleRate == sCeltConfigs[sQuality].sampleRate);
|
assert(voiceInit->quality == NetMsg::SVC_VoiceInit::QUALITY_HAS_SAMPLE_RATE);
|
||||||
|
assert(voiceInit->sampleRate == sCeltConfigs[sQuality].sampleRate);
|
||||||
|
m_Codec = CODEC_CELT;
|
||||||
|
}
|
||||||
|
else if(!strcmp(voiceInit->voiceCodec, "vaudio_speex"))
|
||||||
|
{
|
||||||
|
m_Codec = CODEC_SPEEX;
|
||||||
|
}
|
||||||
|
else //if(!strcmp(voiceInit->voiceCodec, "steam"))
|
||||||
|
{
|
||||||
|
m_Codec = CODEC_STEAM;
|
||||||
|
}
|
||||||
|
context->logic->OnVoiceCodec(voiceInit->voiceCodec, voiceInit->quality, voiceInit->sampleRate);
|
||||||
}
|
}
|
||||||
else if(packet.type == NetMsg::svc_VoiceData)
|
else if(packet.type == NetMsg::svc_VoiceData)
|
||||||
{
|
{
|
||||||
NetMsg::SVC_VoiceData* voiceData = static_cast<NetMsg::SVC_VoiceData*>(packet.data);
|
NetMsg::SVC_VoiceData* voiceData = static_cast<NetMsg::SVC_VoiceData*>(packet.data);
|
||||||
assert(voiceData->fromClientIndex < MAX_PLAYERS);
|
assert(voiceData->fromClientIndex < MAX_PLAYERS);
|
||||||
|
const char* guid = context->players[voiceData->fromClientIndex].info.guid;
|
||||||
|
|
||||||
PlayerVoiceState& state = m_playerVoiceStates[voiceData->fromClientIndex];
|
uint8_t* bytes = voiceData->data.get();
|
||||||
|
|
||||||
const CeltConfig& config = sCeltConfigs[sQuality];
|
|
||||||
#ifdef USE_VAUDIO_CELT
|
|
||||||
const bool initWavWriter = !state.celtDecoder;
|
|
||||||
if(!state.celtDecoder)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
state.celtDecoder = static_cast<IVoiceCodec*>(createInterfaceFunc("vaudio_celt", &ret));
|
|
||||||
state.celtDecoder->Init(sQuality);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
const bool initWavWriter = state.decoder.DoInit(m_celtMode, config.frameSizeSamples, config.encodedFrameSizeBytes);
|
|
||||||
#endif
|
|
||||||
if(initWavWriter)
|
|
||||||
{
|
|
||||||
std::string name = std::string(m_outputPath) + "/client_" + std::to_string((uint32_t)voiceData->fromClientIndex) + ".wav";
|
|
||||||
state.wavWriter.Init(name.c_str(), config.sampleRate);
|
|
||||||
assert(state.lastVoiceDataTick == -1);
|
|
||||||
state.lastVoiceDataTick = m_curTick;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert((voiceData->dataLengthInBits % 8) == 0);
|
assert((voiceData->dataLengthInBits % 8) == 0);
|
||||||
const int numBytes = voiceData->dataLengthInBits / 8;
|
const int numBytes = voiceData->dataLengthInBits / 8;
|
||||||
|
|
||||||
#ifdef USE_VAUDIO_CELT
|
int numDecompressedSamples = 0;
|
||||||
const int numDecompressedSamples = state.celtDecoder->Decompress((const char*)voiceData->data.get(), numBytes, (char*)m_decodeBuffer, 8192*2);
|
|
||||||
#else
|
PlayerVoiceState& state = m_playerVoiceStates[guid];
|
||||||
const int numDecompressedSamples = state.decoder.Decompress(voiceData->data.get(), numBytes, m_decodeBuffer, 8192);
|
|
||||||
#endif
|
if(m_Codec == CODEC_CELT)
|
||||||
state.wavWriter.WriteSamples(m_decodeBuffer, numDecompressedSamples);
|
{
|
||||||
|
const CeltConfig& config = sCeltConfigs[sQuality];
|
||||||
|
state.sampleRate = config.sampleRate;
|
||||||
|
|
||||||
|
state.celt_decoder.DoInit(m_celtMode, config.frameSizeSamples, config.encodedFrameSizeBytes);
|
||||||
|
numDecompressedSamples = state.celt_decoder.Decompress(bytes, numBytes, m_decodeBuffer, sizeof(m_decodeBuffer));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Try Steam Voice
|
||||||
|
if(numBytes >= 15)
|
||||||
|
{
|
||||||
|
numDecompressedSamples = ParseSteamVoicePacket(bytes, numBytes, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Would try speex here, if I cared...
|
||||||
|
if(numDecompressedSamples <= 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(numDecompressedSamples <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(state.lastVoiceDataTick == -1)
|
||||||
|
{
|
||||||
|
std::string name = std::string(m_outputPath) + "/" + std::string(guid) + ".opus";
|
||||||
|
state.fileWriter.Init(name.c_str(), state.sampleRate);
|
||||||
|
state.fileWriter.PadSilence((m_curTick * state.sampleRate) / context->fTickRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.fileWriter.WriteSamples(m_decodeBuffer, numDecompressedSamples);
|
||||||
|
|
||||||
|
context->logic->OnClientVoiceChat(voiceData->fromClientIndex, (float)numDecompressedSamples / (float)state.sampleRate);
|
||||||
|
|
||||||
state.lastVoiceDataTick = m_curTick;
|
state.lastVoiceDataTick = m_curTick;
|
||||||
}
|
}
|
||||||
|
91
demboyz/io/voicewriter/voicedatawriter.h
Normal file
91
demboyz/io/voicewriter/voicedatawriter.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "opusfilewriter.h"
|
||||||
|
#include "game/sourcecontext.h"
|
||||||
|
#include <SKP_Silk_control.h>
|
||||||
|
|
||||||
|
struct CELTMode;
|
||||||
|
|
||||||
|
enum eCodec
|
||||||
|
{
|
||||||
|
CODEC_NONE = 0,
|
||||||
|
CODEC_CELT = 1,
|
||||||
|
CODEC_SPEEX = 2,
|
||||||
|
CODEC_STEAM = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
class CeltVoiceDecoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool DoInit(CELTMode* celtMode, uint32_t frameSizeSamples, uint32_t encodedFrameSizeBytes);
|
||||||
|
void Destroy();
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
int Decompress(const uint8_t* compressedData, uint32_t compressedBytes, int16_t* uncompressedData, uint32_t maxUncompressedSamples);
|
||||||
|
void DecodeFrame(const uint8_t* compressedData, int16_t* uncompressedData);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int sCeltChannels = 1;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct CELTDecoder* m_celtDecoder = NULL;
|
||||||
|
uint32_t m_frameSizeSamples = 0;
|
||||||
|
uint32_t m_encodedFrameSizeBytes = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SilkVoiceDecoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool DoInit(int32_t sampleRate);
|
||||||
|
void Destroy();
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
int Decompress(const uint8_t* compressedData, uint32_t compressedBytes, int16_t* uncompressedData, uint32_t maxUncompressedSamples);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int sSilkChannels = 1;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* m_Silk_DecoderState = NULL;
|
||||||
|
SKP_SILK_SDK_DecControlStruct m_Silk_DecoderControl;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VoiceDataWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VoiceDataWriter(SourceGameContext *context, const char* outputPath);
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
void Finish();
|
||||||
|
|
||||||
|
void StartCommandPacket(const CommandPacket& packet);
|
||||||
|
void EndCommandPacket(const PacketTrailingBits& trailingBits);
|
||||||
|
|
||||||
|
void OnNetPacket(NetPacket& packet);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct PlayerVoiceState
|
||||||
|
{
|
||||||
|
CeltVoiceDecoder celt_decoder;
|
||||||
|
SilkVoiceDecoder silk_decoder;
|
||||||
|
|
||||||
|
OpusFileWriter fileWriter;
|
||||||
|
int32_t lastVoiceDataTick = -1;
|
||||||
|
int sampleRate = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerVoiceState& state);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SourceGameContext *context = nullptr;
|
||||||
|
CELTMode* m_celtMode = nullptr;
|
||||||
|
std::map<std::string, PlayerVoiceState> m_playerVoiceStates;
|
||||||
|
|
||||||
|
int32_t m_curTick = -1;
|
||||||
|
const char* m_outputPath = nullptr;
|
||||||
|
|
||||||
|
int16_t m_decodeBuffer[8192];
|
||||||
|
|
||||||
|
static const int sQuality = 3;
|
||||||
|
eCodec m_Codec = CODEC_NONE;
|
||||||
|
};
|
@ -10,7 +10,7 @@ class WaveFileWriter
|
|||||||
public:
|
public:
|
||||||
WaveFileWriter():
|
WaveFileWriter():
|
||||||
m_file(nullptr),
|
m_file(nullptr),
|
||||||
m_DataBytes(0)
|
m_Samples(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ public:
|
|||||||
assert(fp);
|
assert(fp);
|
||||||
|
|
||||||
m_file = fp;
|
m_file = fp;
|
||||||
m_DataBytes = 0;
|
m_Samples = 0;
|
||||||
|
|
||||||
const uint32_t chunkSize = 0;
|
const uint32_t chunkSize = 0;
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t dataSize = m_DataBytes;
|
const uint32_t dataSize = m_Samples * bytesPerSample;
|
||||||
const uint32_t chunkSize = dataSize + 36;
|
const uint32_t chunkSize = dataSize + 36;
|
||||||
|
|
||||||
fseek(fp, 4, SEEK_SET);
|
fseek(fp, 4, SEEK_SET);
|
||||||
@ -78,13 +78,29 @@ public:
|
|||||||
|
|
||||||
void WriteSamples(const int16_t* samples, uint32_t numSamples)
|
void WriteSamples(const int16_t* samples, uint32_t numSamples)
|
||||||
{
|
{
|
||||||
const uint32_t bytesPerSample = 2;
|
if(!m_file)
|
||||||
|
return;
|
||||||
|
|
||||||
const size_t elemsWritten = fwrite(samples, bytesPerSample, numSamples, m_file);
|
const size_t elemsWritten = fwrite(samples, bytesPerSample, numSamples, m_file);
|
||||||
assert(elemsWritten == numSamples);
|
assert(elemsWritten == numSamples);
|
||||||
m_DataBytes += (elemsWritten * bytesPerSample);
|
m_Samples += elemsWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PadSilence(uint32_t numSamples)
|
||||||
|
{
|
||||||
|
if(!m_file || m_Samples >= numSamples)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const uint16_t silence[bytesPerSample] = {0};
|
||||||
|
const uint32_t pad = numSamples - m_Samples;
|
||||||
|
for(uint32_t i = 0; i < pad; i++)
|
||||||
|
fwrite(silence, bytesPerSample, 1, m_file);
|
||||||
|
m_Samples += pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE* m_file;
|
FILE* m_file;
|
||||||
uint32_t m_DataBytes;
|
uint32_t m_Samples;
|
||||||
|
|
||||||
|
static const uint32_t bytesPerSample = 2;
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "net_disconnect.h"
|
#include "net_disconnect.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -10,32 +9,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadString(data->message, sizeof(data->message));
|
bitbuf.ReadString(data->message, sizeof(data->message));
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Net_Disconnect_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::Net_Disconnect* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteString(data->message);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_Disconnect_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_Disconnect* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
reader.ReadString("message", data->message, sizeof(data->message));
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_Disconnect_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_Disconnect* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteString("message", data->message);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Net_Disconnect_ToString_Internal(std::ostringstream& out, NetMsg::Net_Disconnect* data)
|
|
||||||
{
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "net_file.h"
|
#include "net_file.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -12,38 +11,4 @@ namespace NetHandlers
|
|||||||
data->isRequest = bitbuf.ReadOneBit() != 0;
|
data->isRequest = bitbuf.ReadOneBit() != 0;
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Net_File_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::Net_File* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->transferID, 32);
|
|
||||||
bitbuf.WriteString(data->filename);
|
|
||||||
bitbuf.WriteOneBit(data->isRequest);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_File_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_File* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->transferID = reader.ReadUInt32("transferId");
|
|
||||||
reader.ReadString("filename", data->filename, sizeof(data->filename));
|
|
||||||
data->isRequest = reader.ReadBool("isRequest");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_File_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_File* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("transferId", data->transferID);
|
|
||||||
jsonbuf.WriteString("filename", data->filename);
|
|
||||||
jsonbuf.WriteBool("isRequest", data->isRequest);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Net_File_ToString_Internal(std::ostringstream& out, NetMsg::Net_File* data)
|
|
||||||
{
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
#include "net_nop.h"
|
#include "net_nop.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -8,23 +7,4 @@ namespace NetHandlers
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Net_NOP_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::Net_NOP* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_NOP_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_NOP* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_NOP_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_NOP* data)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Net_NOP_ToString_Internal(std::ostringstream& out, NetMsg::Net_NOP* data)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "net_setconvar.h"
|
#include "net_setconvar.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -14,55 +13,8 @@ namespace NetHandlers
|
|||||||
{
|
{
|
||||||
bitbuf.ReadString(cvar.name, sizeof(cvar.name));
|
bitbuf.ReadString(cvar.name, sizeof(cvar.name));
|
||||||
bitbuf.ReadString(cvar.value, sizeof(cvar.value));
|
bitbuf.ReadString(cvar.value, sizeof(cvar.value));
|
||||||
|
//printf("%s -> %s\n", cvar.name, cvar.value);
|
||||||
}
|
}
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Net_SetConVar_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::Net_SetConVar* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteByte(data->cvars.size());
|
|
||||||
for (const cvar_t& cvar : data->cvars)
|
|
||||||
{
|
|
||||||
bitbuf.WriteString(cvar.name);
|
|
||||||
bitbuf.WriteString(cvar.value);
|
|
||||||
}
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_SetConVar_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_SetConVar* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
|
|
||||||
base::JsonReaderArray cvars = reader.ReadArray("cvars");
|
|
||||||
cvars.TransformTo(data->cvars, [](base::JsonReaderObject& obj, cvar_t& cvar)
|
|
||||||
{
|
|
||||||
obj.ReadString("name", cvar.name, sizeof(cvar.name));
|
|
||||||
obj.ReadString("value", cvar.value, sizeof(cvar.value));
|
|
||||||
});
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_SetConVar_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_SetConVar* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.StartArray("cvars");
|
|
||||||
for (const cvar_t& cvar : data->cvars)
|
|
||||||
{
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteString("name", cvar.name);
|
|
||||||
jsonbuf.WriteString("value", cvar.value);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
}
|
|
||||||
jsonbuf.EndArray();
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Net_SetConVar_ToString_Internal(std::ostringstream& out, NetMsg::Net_SetConVar* data)
|
|
||||||
{
|
|
||||||
cvar_t cvar = data->cvars[0];
|
|
||||||
out << "net_SetConVar: " << data->cvars.size() << " cvars, \"" << cvar.name << "\"=\"" << cvar.value << '"';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "net_signonstate.h"
|
#include "net_signonstate.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -12,36 +11,4 @@ namespace NetHandlers
|
|||||||
//assert(signonState >= SIGNONSTATE_NONE && signonState <= SIGNONSTATE_CHANGELEVEL);
|
//assert(signonState >= SIGNONSTATE_NONE && signonState <= SIGNONSTATE_CHANGELEVEL);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Net_SignonState_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::Net_SignonState* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteByte(data->signonState);
|
|
||||||
bitbuf.WriteLong(data->spawnCount);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_SignonState_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_SignonState* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->signonState = reader.ReadUInt32("signonState");
|
|
||||||
data->spawnCount = reader.ReadUInt32("spawnCount");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_SignonState_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_SignonState* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("signonState", data->signonState);
|
|
||||||
jsonbuf.WriteUInt32("spawnCount", data->spawnCount);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Net_SignonState_ToString_Internal(std::ostringstream& out, NetMsg::Net_SignonState* data)
|
|
||||||
{
|
|
||||||
out << "net_SignonState: state " << static_cast<uint32_t>(data->signonState)
|
|
||||||
<< ", count " << data->spawnCount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "net_stringcmd.h"
|
#include "net_stringcmd.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -10,32 +9,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadString(data->command, sizeof(data->command));
|
bitbuf.ReadString(data->command, sizeof(data->command));
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Net_StringCmd_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::Net_StringCmd* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteString(data->command);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_StringCmd_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_StringCmd* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
reader.ReadString("command", data->command, sizeof(data->command));
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_StringCmd_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_StringCmd* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteString("command", data->command);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Net_StringCmd_ToString_Internal(std::ostringstream& out, NetMsg::Net_StringCmd* data)
|
|
||||||
{
|
|
||||||
out << "net_StringCmd: \"" << data->command << '"';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "net_tick.h"
|
#include "net_tick.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -12,38 +11,4 @@ namespace NetHandlers
|
|||||||
data->hostFrameTimeStdDev = bitbuf.ReadUBitLong(16);
|
data->hostFrameTimeStdDev = bitbuf.ReadUBitLong(16);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Net_Tick_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::Net_Tick* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->tick, 32);
|
|
||||||
bitbuf.WriteUBitLong(data->hostFrameTime, 16);
|
|
||||||
bitbuf.WriteUBitLong(data->hostFrameTimeStdDev, 16);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_Tick_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::Net_Tick* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->tick = reader.ReadInt32("tick");
|
|
||||||
data->hostFrameTime = reader.ReadUInt32("hostFrameTime");
|
|
||||||
data->hostFrameTimeStdDev = reader.ReadUInt32("hostFrameTimeStdDev");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Net_Tick_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::Net_Tick* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteInt32("tick", data->tick);
|
|
||||||
jsonbuf.WriteUInt32("hostFrameTime", data->hostFrameTime);
|
|
||||||
jsonbuf.WriteUInt32("hostFrameTimeStdDev", data->hostFrameTimeStdDev);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Net_Tick_ToString_Internal(std::ostringstream& out, NetMsg::Net_Tick* data)
|
|
||||||
{
|
|
||||||
out << "net_Tick: tick " << data->tick;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -49,5 +49,7 @@ enum constants
|
|||||||
SIGNONSTATE_FULL = 6, // we are fully connected, first non-delta packet received
|
SIGNONSTATE_FULL = 6, // we are fully connected, first non-delta packet received
|
||||||
SIGNONSTATE_CHANGELEVEL = 7, // server is changing level, please wait
|
SIGNONSTATE_CHANGELEVEL = 7, // server is changing level, please wait
|
||||||
|
|
||||||
MAX_STRINGTABLE_DATA = 2 * 524288 // 2^19
|
MAX_STRINGTABLE_DATA = 2 * 524288, // 2^19
|
||||||
|
|
||||||
|
NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS = 10
|
||||||
};
|
};
|
||||||
|
@ -45,78 +45,78 @@
|
|||||||
|
|
||||||
void NetHandlers::CreateNetMsgStructs(NetDataStructArray& netDataStructs)
|
void NetHandlers::CreateNetMsgStructs(NetDataStructArray& netDataStructs)
|
||||||
{
|
{
|
||||||
netDataStructs[0] = new NetMsg::Net_NOP();
|
netDataStructs[NetMsg::net_NOP] = new NetMsg::Net_NOP();
|
||||||
netDataStructs[1] = new NetMsg::Net_Disconnect();
|
netDataStructs[NetMsg::net_Disconnect] = new NetMsg::Net_Disconnect();
|
||||||
netDataStructs[2] = new NetMsg::Net_File();
|
netDataStructs[NetMsg::net_File] = new NetMsg::Net_File();
|
||||||
netDataStructs[3] = new NetMsg::Net_Tick();
|
netDataStructs[NetMsg::net_Tick] = new NetMsg::Net_Tick();
|
||||||
netDataStructs[4] = new NetMsg::Net_StringCmd();
|
netDataStructs[NetMsg::net_StringCmd] = new NetMsg::Net_StringCmd();
|
||||||
netDataStructs[5] = new NetMsg::Net_SetConVar();
|
netDataStructs[NetMsg::net_SetConVar] = new NetMsg::Net_SetConVar();
|
||||||
netDataStructs[6] = new NetMsg::Net_SignonState();
|
netDataStructs[NetMsg::net_SignonState] = new NetMsg::Net_SignonState();
|
||||||
netDataStructs[7] = new NetMsg::SVC_Print();
|
netDataStructs[NetMsg::svc_Print] = new NetMsg::SVC_Print();
|
||||||
netDataStructs[8] = new NetMsg::SVC_ServerInfo();
|
netDataStructs[NetMsg::svc_ServerInfo] = new NetMsg::SVC_ServerInfo();
|
||||||
netDataStructs[9] = new NetMsg::SVC_SendTable();
|
netDataStructs[NetMsg::svc_SendTable] = new NetMsg::SVC_SendTable();
|
||||||
netDataStructs[10] = new NetMsg::SVC_ClassInfo();
|
netDataStructs[NetMsg::svc_ClassInfo] = new NetMsg::SVC_ClassInfo();
|
||||||
netDataStructs[11] = new NetMsg::SVC_SetPause();
|
netDataStructs[NetMsg::svc_SetPause] = new NetMsg::SVC_SetPause();
|
||||||
netDataStructs[12] = new NetMsg::SVC_CreateStringTable();
|
netDataStructs[NetMsg::svc_CreateStringTable] = new NetMsg::SVC_CreateStringTable();
|
||||||
netDataStructs[13] = new NetMsg::SVC_UpdateStringTable();
|
netDataStructs[NetMsg::svc_UpdateStringTable] = new NetMsg::SVC_UpdateStringTable();
|
||||||
netDataStructs[14] = new NetMsg::SVC_VoiceInit();
|
netDataStructs[NetMsg::svc_VoiceInit] = new NetMsg::SVC_VoiceInit();
|
||||||
netDataStructs[15] = new NetMsg::SVC_VoiceData();
|
netDataStructs[NetMsg::svc_VoiceData] = new NetMsg::SVC_VoiceData();
|
||||||
netDataStructs[16] = new NetMsg::SVC_HLTV();
|
netDataStructs[NetMsg::svc_HLTV] = new NetMsg::SVC_HLTV();
|
||||||
netDataStructs[17] = new NetMsg::SVC_Sounds();
|
netDataStructs[NetMsg::svc_Sounds] = new NetMsg::SVC_Sounds();
|
||||||
netDataStructs[18] = new NetMsg::SVC_SetView();
|
netDataStructs[NetMsg::svc_SetView] = new NetMsg::SVC_SetView();
|
||||||
netDataStructs[19] = new NetMsg::SVC_FixAngle();
|
netDataStructs[NetMsg::svc_FixAngle] = new NetMsg::SVC_FixAngle();
|
||||||
netDataStructs[20] = new NetMsg::SVC_CrosshairAngle();
|
netDataStructs[NetMsg::svc_CrosshairAngle] = new NetMsg::SVC_CrosshairAngle();
|
||||||
netDataStructs[21] = new NetMsg::SVC_BSPDecal();
|
netDataStructs[NetMsg::svc_BSPDecal] = new NetMsg::SVC_BSPDecal();
|
||||||
netDataStructs[22] = new NetMsg::SVC_TerrainMod();
|
netDataStructs[NetMsg::svc_TerrainMod] = new NetMsg::SVC_TerrainMod();
|
||||||
netDataStructs[23] = new NetMsg::SVC_UserMessage();
|
netDataStructs[NetMsg::svc_UserMessage] = new NetMsg::SVC_UserMessage();
|
||||||
netDataStructs[24] = new NetMsg::SVC_EntityMessage();
|
netDataStructs[NetMsg::svc_EntityMessage] = new NetMsg::SVC_EntityMessage();
|
||||||
netDataStructs[25] = new NetMsg::SVC_GameEvent();
|
netDataStructs[NetMsg::svc_GameEvent] = new NetMsg::SVC_GameEvent();
|
||||||
netDataStructs[26] = new NetMsg::SVC_PacketEntities();
|
netDataStructs[NetMsg::svc_PacketEntities] = new NetMsg::SVC_PacketEntities();
|
||||||
netDataStructs[27] = new NetMsg::SVC_TempEntities();
|
netDataStructs[NetMsg::svc_TempEntities] = new NetMsg::SVC_TempEntities();
|
||||||
netDataStructs[28] = new NetMsg::SVC_Prefetch();
|
netDataStructs[NetMsg::svc_Prefetch] = new NetMsg::SVC_Prefetch();
|
||||||
netDataStructs[29] = new NetMsg::SVC_Menu();
|
netDataStructs[NetMsg::svc_Menu] = new NetMsg::SVC_Menu();
|
||||||
netDataStructs[30] = new NetMsg::SVC_GameEventList();
|
netDataStructs[NetMsg::svc_GameEventList] = new NetMsg::SVC_GameEventList();
|
||||||
netDataStructs[31] = new NetMsg::SVC_GetCvarValue();
|
netDataStructs[NetMsg::svc_GetCvarValue] = new NetMsg::SVC_GetCvarValue();
|
||||||
netDataStructs[32] = new NetMsg::SVC_CmdKeyValues();
|
netDataStructs[NetMsg::svc_CmdKeyValues] = new NetMsg::SVC_CmdKeyValues();
|
||||||
netDataStructs[33] = new NetMsg::SVC_SetPauseTimed();
|
netDataStructs[NetMsg::svc_SetPauseTimed] = new NetMsg::SVC_SetPauseTimed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetHandlers::DestroyNetMsgStructs(NetDataStructArray& netDataStructs)
|
void NetHandlers::DestroyNetMsgStructs(NetDataStructArray& netDataStructs)
|
||||||
{
|
{
|
||||||
delete reinterpret_cast<NetMsg::Net_NOP*>(netDataStructs[0]);
|
delete reinterpret_cast<NetMsg::Net_NOP*>(netDataStructs[NetMsg::net_NOP]);
|
||||||
delete reinterpret_cast<NetMsg::Net_Disconnect*>(netDataStructs[1]);
|
delete reinterpret_cast<NetMsg::Net_Disconnect*>(netDataStructs[NetMsg::net_Disconnect]);
|
||||||
delete reinterpret_cast<NetMsg::Net_File*>(netDataStructs[2]);
|
delete reinterpret_cast<NetMsg::Net_File*>(netDataStructs[NetMsg::net_File]);
|
||||||
delete reinterpret_cast<NetMsg::Net_Tick*>(netDataStructs[3]);
|
delete reinterpret_cast<NetMsg::Net_Tick*>(netDataStructs[NetMsg::net_Tick]);
|
||||||
delete reinterpret_cast<NetMsg::Net_StringCmd*>(netDataStructs[4]);
|
delete reinterpret_cast<NetMsg::Net_StringCmd*>(netDataStructs[NetMsg::net_StringCmd]);
|
||||||
delete reinterpret_cast<NetMsg::Net_SetConVar*>(netDataStructs[5]);
|
delete reinterpret_cast<NetMsg::Net_SetConVar*>(netDataStructs[NetMsg::net_SetConVar]);
|
||||||
delete reinterpret_cast<NetMsg::Net_SignonState*>(netDataStructs[6]);
|
delete reinterpret_cast<NetMsg::Net_SignonState*>(netDataStructs[NetMsg::net_SignonState]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_Print*>(netDataStructs[7]);
|
delete reinterpret_cast<NetMsg::SVC_Print*>(netDataStructs[NetMsg::svc_Print]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_ServerInfo*>(netDataStructs[8]);
|
delete reinterpret_cast<NetMsg::SVC_ServerInfo*>(netDataStructs[NetMsg::svc_ServerInfo]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_SendTable*>(netDataStructs[9]);
|
delete reinterpret_cast<NetMsg::SVC_SendTable*>(netDataStructs[NetMsg::svc_SendTable]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_ClassInfo*>(netDataStructs[10]);
|
delete reinterpret_cast<NetMsg::SVC_ClassInfo*>(netDataStructs[NetMsg::svc_ClassInfo]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_SetPause*>(netDataStructs[11]);
|
delete reinterpret_cast<NetMsg::SVC_SetPause*>(netDataStructs[NetMsg::svc_SetPause]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_CreateStringTable*>(netDataStructs[12]);
|
delete reinterpret_cast<NetMsg::SVC_CreateStringTable*>(netDataStructs[NetMsg::svc_CreateStringTable]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_UpdateStringTable*>(netDataStructs[13]);
|
delete reinterpret_cast<NetMsg::SVC_UpdateStringTable*>(netDataStructs[NetMsg::svc_UpdateStringTable]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_VoiceInit*>(netDataStructs[14]);
|
delete reinterpret_cast<NetMsg::SVC_VoiceInit*>(netDataStructs[NetMsg::svc_VoiceInit]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_VoiceData*>(netDataStructs[15]);
|
delete reinterpret_cast<NetMsg::SVC_VoiceData*>(netDataStructs[NetMsg::svc_VoiceData]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_HLTV*>(netDataStructs[16]);
|
delete reinterpret_cast<NetMsg::SVC_HLTV*>(netDataStructs[NetMsg::svc_HLTV]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_Sounds*>(netDataStructs[17]);
|
delete reinterpret_cast<NetMsg::SVC_Sounds*>(netDataStructs[NetMsg::svc_Sounds]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_SetView*>(netDataStructs[18]);
|
delete reinterpret_cast<NetMsg::SVC_SetView*>(netDataStructs[NetMsg::svc_SetView]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_FixAngle*>(netDataStructs[19]);
|
delete reinterpret_cast<NetMsg::SVC_FixAngle*>(netDataStructs[NetMsg::svc_FixAngle]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_CrosshairAngle*>(netDataStructs[20]);
|
delete reinterpret_cast<NetMsg::SVC_CrosshairAngle*>(netDataStructs[NetMsg::svc_CrosshairAngle]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_BSPDecal*>(netDataStructs[21]);
|
delete reinterpret_cast<NetMsg::SVC_BSPDecal*>(netDataStructs[NetMsg::svc_BSPDecal]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_TerrainMod*>(netDataStructs[22]);
|
delete reinterpret_cast<NetMsg::SVC_TerrainMod*>(netDataStructs[NetMsg::svc_TerrainMod]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_UserMessage*>(netDataStructs[23]);
|
delete reinterpret_cast<NetMsg::SVC_UserMessage*>(netDataStructs[NetMsg::svc_UserMessage]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_EntityMessage*>(netDataStructs[24]);
|
delete reinterpret_cast<NetMsg::SVC_EntityMessage*>(netDataStructs[NetMsg::svc_EntityMessage]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_GameEvent*>(netDataStructs[25]);
|
delete reinterpret_cast<NetMsg::SVC_GameEvent*>(netDataStructs[NetMsg::svc_GameEvent]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_PacketEntities*>(netDataStructs[26]);
|
delete reinterpret_cast<NetMsg::SVC_PacketEntities*>(netDataStructs[NetMsg::svc_PacketEntities]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_TempEntities*>(netDataStructs[27]);
|
delete reinterpret_cast<NetMsg::SVC_TempEntities*>(netDataStructs[NetMsg::svc_TempEntities]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_Prefetch*>(netDataStructs[28]);
|
delete reinterpret_cast<NetMsg::SVC_Prefetch*>(netDataStructs[NetMsg::svc_Prefetch]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_Menu*>(netDataStructs[29]);
|
delete reinterpret_cast<NetMsg::SVC_Menu*>(netDataStructs[NetMsg::svc_Menu]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_GameEventList*>(netDataStructs[30]);
|
delete reinterpret_cast<NetMsg::SVC_GameEventList*>(netDataStructs[NetMsg::svc_GameEventList]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_GetCvarValue*>(netDataStructs[31]);
|
delete reinterpret_cast<NetMsg::SVC_GetCvarValue*>(netDataStructs[NetMsg::svc_GetCvarValue]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_CmdKeyValues*>(netDataStructs[32]);
|
delete reinterpret_cast<NetMsg::SVC_CmdKeyValues*>(netDataStructs[NetMsg::svc_CmdKeyValues]);
|
||||||
delete reinterpret_cast<NetMsg::SVC_SetPauseTimed*>(netDataStructs[33]);
|
delete reinterpret_cast<NetMsg::SVC_SetPauseTimed*>(netDataStructs[NetMsg::svc_SetPauseTimed]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECLARE_NET_HANDLER_ARRAY(funcname) \
|
#define DECLARE_NET_HANDLER_ARRAY(funcname) \
|
||||||
@ -158,10 +158,6 @@ void NetHandlers::DestroyNetMsgStructs(NetDataStructArray& netDataStructs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*NetMsgBitReadFn)(NetHandlers::BitRead& bitbuf, SourceGameContext& context, void* data);
|
typedef bool (*NetMsgBitReadFn)(NetHandlers::BitRead& bitbuf, SourceGameContext& context, void* data);
|
||||||
typedef bool (*NetMsgBitWriteFn)(NetHandlers::BitWrite& bitbuf, const SourceGameContext& context, void* data);
|
|
||||||
typedef bool (*NetMsgJsonReadFn)(NetHandlers::JsonRead& jsonbuf, SourceGameContext& context, void* data);
|
|
||||||
typedef bool (*NetMsgJsonWriteFn)(NetHandlers::JsonWrite& jsonbuf, const SourceGameContext& context, void* data);
|
|
||||||
typedef void (*NetMsgToStringFn)(std::ostringstream& out, void* data);
|
|
||||||
|
|
||||||
template<typename BufType, typename FnType, typename ContextType, size_t NumHandlers>
|
template<typename BufType, typename FnType, typename ContextType, size_t NumHandlers>
|
||||||
bool NetMsgFuncRunner(const FnType (&netHandlers)[NumHandlers], uint32_t type, BufType& buf, ContextType& context, void* data)
|
bool NetMsgFuncRunner(const FnType (&netHandlers)[NumHandlers], uint32_t type, BufType& buf, ContextType& context, void* data)
|
||||||
@ -179,30 +175,3 @@ bool NetHandlers::NetMsg_BitRead(uint32_t type, BitRead& bitbuf, SourceGameConte
|
|||||||
return NetMsgFuncRunner(netHandlers, type, bitbuf, context, data);
|
return NetMsgFuncRunner(netHandlers, type, bitbuf, context, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetHandlers::NetMsg_BitWrite(uint32_t type, BitWrite& bitbuf, const SourceGameContext& context, void* data)
|
|
||||||
{
|
|
||||||
static const NetMsgBitWriteFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(BitWrite);
|
|
||||||
return NetMsgFuncRunner(netHandlers, type, bitbuf, context, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NetHandlers::NetMsg_JsonRead(uint32_t type, JsonRead& jsonbuf, SourceGameContext& context, void* data)
|
|
||||||
{
|
|
||||||
static const NetMsgJsonReadFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(JsonRead);
|
|
||||||
return NetMsgFuncRunner(netHandlers, type, jsonbuf, context, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NetHandlers::NetMsg_JsonWrite(uint32_t type, JsonWrite& jsonbuf, const SourceGameContext& context, void* data)
|
|
||||||
{
|
|
||||||
static const NetMsgJsonWriteFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(JsonWrite);
|
|
||||||
return NetMsgFuncRunner(netHandlers, type, jsonbuf, context, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetHandlers::NetMsg_ToString(uint32_t type, std::ostringstream& out, void* data)
|
|
||||||
{
|
|
||||||
static const NetMsgToStringFn netHandlers[] = DECLARE_NET_HANDLER_ARRAY(ToString);
|
|
||||||
if (type >= (sizeof(netHandlers) / sizeof(NetMsgToStringFn)))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
netHandlers[type](out, data);
|
|
||||||
}
|
|
||||||
|
@ -6,23 +6,11 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include "netmessages.h"
|
#include "netmessages.h"
|
||||||
|
|
||||||
namespace base
|
|
||||||
{
|
|
||||||
class JsonReaderFile;
|
|
||||||
class JsonWriterFile;
|
|
||||||
class BitFileRead;
|
|
||||||
class BitFileWrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
class bf_read;
|
class bf_read;
|
||||||
class bf_write;
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
using BitRead = bf_read;
|
using BitRead = bf_read;
|
||||||
using BitWrite = bf_write;
|
|
||||||
using JsonRead = base::JsonReaderFile;
|
|
||||||
using JsonWrite = base::JsonWriterFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SourceGameContext;
|
struct SourceGameContext;
|
||||||
@ -35,30 +23,10 @@ struct SourceGameContext;
|
|||||||
namespace NetHandlers \
|
namespace NetHandlers \
|
||||||
{ \
|
{ \
|
||||||
bool msgname##_BitRead_Internal(BitRead& bitbuf, SourceGameContext& context, NetMsg::msgname* data); \
|
bool msgname##_BitRead_Internal(BitRead& bitbuf, SourceGameContext& context, NetMsg::msgname* data); \
|
||||||
bool msgname##_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::msgname* data); \
|
|
||||||
bool msgname##_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::msgname* data); \
|
|
||||||
bool msgname##_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::msgname* data); \
|
|
||||||
void msgname##_ToString_Internal(std::ostringstream& out, NetMsg::msgname* data); \
|
|
||||||
inline bool msgname##_BitRead(BitRead& bitbuf, SourceGameContext& context, void* data) \
|
inline bool msgname##_BitRead(BitRead& bitbuf, SourceGameContext& context, void* data) \
|
||||||
{ \
|
{ \
|
||||||
return msgname##_BitRead_Internal(bitbuf, context, reinterpret_cast<NetMsg::msgname*>(data)); \
|
return msgname##_BitRead_Internal(bitbuf, context, reinterpret_cast<NetMsg::msgname*>(data)); \
|
||||||
} \
|
} \
|
||||||
inline bool msgname##_BitWrite(BitWrite& bitbuf, const SourceGameContext& context, void* data) \
|
|
||||||
{ \
|
|
||||||
return msgname##_BitWrite_Internal(bitbuf, context, reinterpret_cast<NetMsg::msgname*>(data)); \
|
|
||||||
} \
|
|
||||||
inline bool msgname##_JsonRead(JsonRead& jsonbuf, SourceGameContext& context, void* data) \
|
|
||||||
{ \
|
|
||||||
return msgname##_JsonRead_Internal(jsonbuf, context, reinterpret_cast<NetMsg::msgname*>(data)); \
|
|
||||||
} \
|
|
||||||
inline bool msgname##_JsonWrite(JsonWrite& jsonbuf, const SourceGameContext& context, void* data) \
|
|
||||||
{ \
|
|
||||||
return msgname##_JsonWrite_Internal(jsonbuf, context, reinterpret_cast<NetMsg::msgname*>(data)); \
|
|
||||||
} \
|
|
||||||
inline void msgname##_ToString(std::ostringstream& out, void* data) \
|
|
||||||
{ \
|
|
||||||
msgname##_ToString_Internal(out, reinterpret_cast<NetMsg::msgname*>(data)); \
|
|
||||||
} \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
@ -68,8 +36,4 @@ namespace NetHandlers
|
|||||||
void DestroyNetMsgStructs(NetDataStructArray& netDataStructs);
|
void DestroyNetMsgStructs(NetDataStructArray& netDataStructs);
|
||||||
|
|
||||||
bool NetMsg_BitRead(uint32_t type, BitRead& bitbuf, SourceGameContext& context, void* data);
|
bool NetMsg_BitRead(uint32_t type, BitRead& bitbuf, SourceGameContext& context, void* data);
|
||||||
bool NetMsg_BitWrite(uint32_t type, BitWrite& bitbuf, const SourceGameContext& context, void* data);
|
|
||||||
bool NetMsg_JsonRead(uint32_t type, JsonRead& jsonbuf, SourceGameContext& context, void* data);
|
|
||||||
bool NetMsg_JsonWrite(uint32_t type, JsonWrite& jsonbuf, const SourceGameContext& context, void* data);
|
|
||||||
void NetMsg_ToString(uint32_t type, std::ostringstream& out, void* data);
|
|
||||||
}
|
}
|
||||||
|
18
demboyz/netmessages/netmath.cpp
Normal file
18
demboyz/netmessages/netmath.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
#include "netmath.h"
|
||||||
|
|
||||||
|
namespace math
|
||||||
|
{
|
||||||
|
uint32_t log2(uint32_t value)
|
||||||
|
{
|
||||||
|
uint32_t res = 0;
|
||||||
|
while (value >>= 1)
|
||||||
|
++res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t BitsToBytes(uint32_t bits)
|
||||||
|
{
|
||||||
|
return ((bits + 7) >> 3);
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef>
|
#include <stdint.h>
|
||||||
|
|
||||||
namespace math
|
namespace math
|
||||||
{
|
{
|
||||||
static size_t log2(size_t value)
|
uint32_t log2(uint32_t value);
|
||||||
{
|
|
||||||
size_t res = 0;
|
|
||||||
while (value >>= 1)
|
|
||||||
++res;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t BitsToBytes(size_t bits)
|
uint32_t BitsToBytes(uint32_t bits);
|
||||||
{
|
|
||||||
return ((bits + 7) >> 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ namespace NetMsg
|
|||||||
svc_VoiceInit = 14, // inits used voice codecs & quality
|
svc_VoiceInit = 14, // inits used voice codecs & quality
|
||||||
svc_VoiceData = 15, // Voicestream data from the server
|
svc_VoiceData = 15, // Voicestream data from the server
|
||||||
|
|
||||||
//svc_HLTV = 16, // HLTV control messages
|
svc_HLTV = 16, // HLTV control messages
|
||||||
|
|
||||||
svc_Sounds = 17, // starts playing sound
|
svc_Sounds = 17, // starts playing sound
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ namespace NetMsg
|
|||||||
svc_BSPDecal = 21, // add a static decal to the world BSP
|
svc_BSPDecal = 21, // add a static decal to the world BSP
|
||||||
|
|
||||||
// NOTE: This is now unused!
|
// NOTE: This is now unused!
|
||||||
// svc_TerrainMod = 22, // modification to the terrain/displacement
|
svc_TerrainMod = 22, // modification to the terrain/displacement
|
||||||
|
|
||||||
// Message from server side to client side entity
|
// Message from server side to client side entity
|
||||||
svc_UserMessage = 23, // a game specific message
|
svc_UserMessage = 23, // a game specific message
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_bspdecal.h"
|
#include "svc_bspdecal.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "demofile/demojson.h"
|
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
@ -24,55 +22,4 @@ namespace NetHandlers
|
|||||||
data->lowPriority = bitbuf.ReadOneBit() != 0;
|
data->lowPriority = bitbuf.ReadOneBit() != 0;
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_BSPDecal_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_BSPDecal* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteBitVec3Coord(data->position);
|
|
||||||
bitbuf.WriteUBitLong(data->decalTextureIndex, MAX_DECAL_INDEX_BITS);
|
|
||||||
if (data->entIndex != 0)
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(1);
|
|
||||||
bitbuf.WriteUBitLong(data->entIndex, MAX_EDICT_BITS);
|
|
||||||
bitbuf.WriteUBitLong(data->modelIndex, SP_MODEL_INDEX_BITS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(0);
|
|
||||||
}
|
|
||||||
bitbuf.WriteOneBit(data->lowPriority);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_BSPDecal_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_BSPDecal* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
DemoJsonReader::ReadVector(reader, "position", data->position);
|
|
||||||
data->decalTextureIndex = reader.ReadUInt32("decalTextureIndex");
|
|
||||||
data->entIndex = reader.ReadUInt32("entIndex");
|
|
||||||
data->modelIndex = reader.ReadUInt32("modelIndex");
|
|
||||||
data->lowPriority = reader.ReadBool("lowPriority");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_BSPDecal_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_BSPDecal* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
DemoJsonWriter::WriteVector(jsonbuf, "position", data->position);
|
|
||||||
jsonbuf.WriteUInt32("decalTextureIndex", data->decalTextureIndex);
|
|
||||||
jsonbuf.WriteUInt32("entIndex", data->entIndex);
|
|
||||||
jsonbuf.WriteUInt32("modelIndex", data->modelIndex);
|
|
||||||
jsonbuf.WriteBool("lowPriority", data->lowPriority);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_BSPDecal_ToString_Internal(std::ostringstream& out, NetMsg::SVC_BSPDecal* data)
|
|
||||||
{
|
|
||||||
out << "svc_BSPDecal: tex " << data->decalTextureIndex
|
|
||||||
<< ", ent " << data->entIndex
|
|
||||||
<< ", mod " << data->modelIndex
|
|
||||||
<< " lowpriority " << data->lowPriority;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_classinfo.h"
|
#include "svc_classinfo.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
|
|
||||||
using class_t = NetMsg::SVC_ClassInfo::class_t;
|
using class_t = NetMsg::SVC_ClassInfo::class_t;
|
||||||
@ -27,67 +26,4 @@ namespace NetHandlers
|
|||||||
}
|
}
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_ClassInfo_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_ClassInfo* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteShort(data->numServerClasses);
|
|
||||||
bitbuf.WriteOneBit(data->createOnClient);
|
|
||||||
if (!data->createOnClient)
|
|
||||||
{
|
|
||||||
const int numServerClassBits = math::log2(data->numServerClasses) + 1;
|
|
||||||
for (class_t& serverClass : data->serverClasses)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(serverClass.classID, numServerClassBits);
|
|
||||||
bitbuf.WriteString(serverClass.className);
|
|
||||||
bitbuf.WriteString(serverClass.dataTableName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_ClassInfo_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_ClassInfo* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->numServerClasses = reader.ReadInt32("numServerClasses");
|
|
||||||
data->createOnClient = reader.ReadBool("createOnClient");
|
|
||||||
if (!data->createOnClient)
|
|
||||||
{
|
|
||||||
base::JsonReaderArray serverClasses = reader.ReadArray("serverClasses");
|
|
||||||
serverClasses.TransformTo(data->serverClasses, [](base::JsonReaderObject& obj, class_t& serverClass)
|
|
||||||
{
|
|
||||||
serverClass.classID = obj.ReadUInt32("classId");
|
|
||||||
obj.ReadString("className", serverClass.className, sizeof(serverClass.className));
|
|
||||||
obj.ReadString("dataTableName", serverClass.dataTableName, sizeof(serverClass.dataTableName));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_ClassInfo_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_ClassInfo* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteInt32("numServerClasses", data->numServerClasses);
|
|
||||||
jsonbuf.WriteBool("createOnClient", data->createOnClient);
|
|
||||||
if (!data->createOnClient)
|
|
||||||
{
|
|
||||||
jsonbuf.StartArray("serverClasses");
|
|
||||||
for (class_t& serverClass : data->serverClasses)
|
|
||||||
{
|
|
||||||
jsonbuf.WriteUInt32("classId", serverClass.classID);
|
|
||||||
jsonbuf.WriteString("className", serverClass.className);
|
|
||||||
jsonbuf.WriteString("dataTableName", serverClass.dataTableName);
|
|
||||||
}
|
|
||||||
jsonbuf.EndArray();
|
|
||||||
}
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_ClassInfo_ToString_Internal(std::ostringstream& out, NetMsg::SVC_ClassInfo* data)
|
|
||||||
{
|
|
||||||
out << "svc_ClassInfo: num " << data->numServerClasses
|
|
||||||
<< ", " << (data->createOnClient ? "use client classes" : "full update");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_cmdkeyvalues.h"
|
#include "svc_cmdkeyvalues.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -11,28 +10,4 @@ namespace NetHandlers
|
|||||||
assert(false);
|
assert(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_CmdKeyValues_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_CmdKeyValues* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_CmdKeyValues_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_CmdKeyValues* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_CmdKeyValues_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_CmdKeyValues* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_CmdKeyValues_ToString_Internal(std::ostringstream& out, NetMsg::SVC_CmdKeyValues* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
out << "svc_CmdKeyValues";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,94 +1,14 @@
|
|||||||
|
|
||||||
#include "svc_createstringtable.h"
|
#include "svc_createstringtable.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "game/sourcecontext.h"
|
#include "game/sourcecontext.h"
|
||||||
|
#include "game/stringtables.h"
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
|
|
||||||
// #define WIP_STRINGTABLE
|
|
||||||
|
|
||||||
#ifdef WIP_STRINGTABLE
|
|
||||||
#include "sourcesdk/common.h"
|
#include "sourcesdk/common.h"
|
||||||
#include <vector>
|
#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 entryIndex = -1;
|
|
||||||
for (uint i = 0; i < data->numEntries; ++i)
|
|
||||||
{
|
|
||||||
entryIndex++;
|
|
||||||
|
|
||||||
if (bitbuf.ReadOneBit() == 0)
|
|
||||||
{
|
|
||||||
entryIndex = bitbuf.ReadUBitLong(numEncodeBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
if (bitbuf.ReadOneBit() != 0)
|
|
||||||
{
|
|
||||||
if (data->isUserDataFixedSize)
|
|
||||||
{
|
|
||||||
bitbuf.ReadBits(tempbuf, data->userDataSizeBits);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int 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)
|
||||||
@ -105,21 +25,18 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadString(data->tableName, sizeof(data->tableName));
|
bitbuf.ReadString(data->tableName, sizeof(data->tableName));
|
||||||
data->maxEntries = bitbuf.ReadWord();
|
data->maxEntries = bitbuf.ReadWord();
|
||||||
|
|
||||||
const size_t numEncodeBits = math::log2(data->maxEntries);
|
const uint32_t numEncodeBits = math::log2(data->maxEntries);
|
||||||
data->numEntries = bitbuf.ReadUBitLong(numEncodeBits + 1);
|
data->numEntries = bitbuf.ReadUBitLong(numEncodeBits + 1);
|
||||||
|
|
||||||
size_t dataLengthInBits;
|
|
||||||
if (context.protocol > 23)
|
if (context.protocol > 23)
|
||||||
{
|
{
|
||||||
dataLengthInBits = bitbuf.ReadVarInt32();
|
data->dataLengthInBits = bitbuf.ReadVarInt32();
|
||||||
data->dataLengthInBits = dataLengthInBits;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dataLengthInBits = bitbuf.ReadUBitLong(NET_MAX_PAYLOAD_BITS_OLD + 3);
|
data->dataLengthInBits = bitbuf.ReadUBitLong(NET_MAX_PAYLOAD_BITS_OLD + 3);
|
||||||
data->dataLengthInBits = dataLengthInBits;
|
|
||||||
}
|
}
|
||||||
const size_t dataLengthInBytes = math::BitsToBytes(dataLengthInBits);
|
const uint32_t dataLengthInBytes = math::BitsToBytes(data->dataLengthInBits);
|
||||||
|
|
||||||
data->isUserDataFixedSize = bitbuf.ReadOneBit() != 0;
|
data->isUserDataFixedSize = bitbuf.ReadOneBit() != 0;
|
||||||
if (data->isUserDataFixedSize)
|
if (data->isUserDataFixedSize)
|
||||||
@ -136,13 +53,24 @@ namespace NetHandlers
|
|||||||
{
|
{
|
||||||
data->compressedData = bitbuf.ReadOneBit() != 0;
|
data->compressedData = bitbuf.ReadOneBit() != 0;
|
||||||
}
|
}
|
||||||
data->data.reset(new uint8_t[dataLengthInBytes]);
|
else
|
||||||
bitbuf.ReadBits(data->data.get(), dataLengthInBits);
|
{
|
||||||
|
data->compressedData = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->data.reset(new uint8_t[dataLengthInBytes]);
|
||||||
|
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
||||||
|
|
||||||
|
StringTable *table = context.stringTables->GetStringTable(data->tableName, true);
|
||||||
|
table->maxEntries = data->maxEntries;
|
||||||
|
table->isUserDataFixedSize = data->isUserDataFixedSize;
|
||||||
|
table->userDataSize = data->userDataSize;
|
||||||
|
table->userDataSizeBits = data->userDataSizeBits;
|
||||||
|
table->entryBits = math::log2(table->maxEntries);
|
||||||
|
|
||||||
#ifdef WIP_STRINGTABLE
|
|
||||||
if (data->compressedData)
|
if (data->compressedData)
|
||||||
{
|
{
|
||||||
bf_read bitbuf2(data->data.get(), dataLengthInBytes, dataLengthInBits);
|
bf_read bitbuf2(data->data.get(), dataLengthInBytes, data->dataLengthInBits);
|
||||||
const uint32_t decompressedNumBytes = bitbuf2.ReadUBitLong(32);
|
const uint32_t decompressedNumBytes = bitbuf2.ReadUBitLong(32);
|
||||||
const uint32_t compressedNumBytes = bitbuf2.ReadUBitLong(32);
|
const uint32_t compressedNumBytes = bitbuf2.ReadUBitLong(32);
|
||||||
std::unique_ptr<uint8_t[]> compressedData(new uint8[compressedNumBytes]);
|
std::unique_ptr<uint8_t[]> compressedData(new uint8[compressedNumBytes]);
|
||||||
@ -150,98 +78,16 @@ namespace NetHandlers
|
|||||||
bitbuf2.ReadBytes(compressedData.get(), compressedNumBytes);
|
bitbuf2.ReadBytes(compressedData.get(), compressedNumBytes);
|
||||||
|
|
||||||
uint32_t numWritten = COM_BufferToBufferDecompress(uncompressedData.get(), decompressedNumBytes, compressedData.get(), compressedNumBytes);
|
uint32_t numWritten = COM_BufferToBufferDecompress(uncompressedData.get(), decompressedNumBytes, compressedData.get(), compressedNumBytes);
|
||||||
|
assert(numWritten == decompressedNumBytes);
|
||||||
bitbuf2 = bf_read(uncompressedData.get(), decompressedNumBytes);
|
bitbuf2 = bf_read(uncompressedData.get(), decompressedNumBytes);
|
||||||
StringTable_BitRead(bitbuf2, context, data);
|
table->ParseUpdate(bitbuf2, data->numEntries, context);
|
||||||
}
|
}
|
||||||
else
|
else if(dataLengthInBytes)
|
||||||
{
|
{
|
||||||
bf_read bitbuf2(data->data.get(), dataLengthInBytes, dataLengthInBits);
|
bf_read bitbuf2(data->data.get(), dataLengthInBytes, data->dataLengthInBits);
|
||||||
StringTable_BitRead(bitbuf2, context, data);
|
table->ParseUpdate(bitbuf2, data->numEntries, context);
|
||||||
}
|
}
|
||||||
#endif // WIP_STRINGTABLE
|
|
||||||
|
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_CreateStringTable_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_CreateStringTable* data)
|
|
||||||
{
|
|
||||||
if (data->isFileNames)
|
|
||||||
{
|
|
||||||
bitbuf.WriteByte(':');
|
|
||||||
}
|
|
||||||
bitbuf.WriteString(data->tableName);
|
|
||||||
bitbuf.WriteWord(data->maxEntries);
|
|
||||||
bitbuf.WriteUBitLong(data->numEntries, math::log2(data->maxEntries) + 1);
|
|
||||||
if (context.protocol > 23)
|
|
||||||
{
|
|
||||||
bitbuf.WriteVarInt32(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, NET_MAX_PAYLOAD_BITS_OLD + 3);
|
|
||||||
}
|
|
||||||
bitbuf.WriteOneBit(data->isUserDataFixedSize);
|
|
||||||
if (data->isUserDataFixedSize)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->userDataSize, 12);
|
|
||||||
bitbuf.WriteUBitLong(data->userDataSizeBits, 4);
|
|
||||||
}
|
|
||||||
if (context.protocol > 14)
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(data->compressedData);
|
|
||||||
}
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_CreateStringTable_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_CreateStringTable* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->isFileNames = reader.ReadBool("isFilenames");
|
|
||||||
reader.ReadString("tableName", data->tableName, sizeof(data->tableName));
|
|
||||||
data->maxEntries = reader.ReadUInt32("maxEntries");
|
|
||||||
data->numEntries = reader.ReadUInt32("numEntries");
|
|
||||||
data->dataLengthInBits = reader.ReadInt32("dataLengthInBits");
|
|
||||||
data->isUserDataFixedSize = reader.ReadBool("isUserDataFixedSize");
|
|
||||||
data->userDataSize = reader.ReadUInt32("userDataSize");
|
|
||||||
data->userDataSizeBits = reader.ReadUInt32("userDataSizeBits");
|
|
||||||
if (context.protocol > 14)
|
|
||||||
{
|
|
||||||
data->compressedData = reader.ReadBool("compressedData");
|
|
||||||
}
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_CreateStringTable_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_CreateStringTable* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteBool("isFilenames", data->isFileNames);
|
|
||||||
jsonbuf.WriteString("tableName", data->tableName);
|
|
||||||
jsonbuf.WriteUInt32("maxEntries", data->maxEntries);
|
|
||||||
jsonbuf.WriteUInt32("numEntries", data->numEntries);
|
|
||||||
jsonbuf.WriteInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBool("isUserDataFixedSize", data->isUserDataFixedSize);
|
|
||||||
jsonbuf.WriteUInt32("userDataSize", data->userDataSize);
|
|
||||||
jsonbuf.WriteUInt32("userDataSizeBits", data->userDataSizeBits);
|
|
||||||
if (context.protocol > 14)
|
|
||||||
{
|
|
||||||
jsonbuf.WriteBool("compressedData", data->compressedData);
|
|
||||||
}
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_CreateStringTable_ToString_Internal(std::ostringstream& out, NetMsg::SVC_CreateStringTable* data)
|
|
||||||
{
|
|
||||||
out << "svc_CreateStringTable: table " << data->tableName
|
|
||||||
<< ", entries " << data->numEntries
|
|
||||||
<< ", bytes " << math::BitsToBytes(data->dataLengthInBits)
|
|
||||||
<< " userdatasize " << data->userDataSize
|
|
||||||
<< " userdatabits " << static_cast<uint32_t>(data->userDataSizeBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_crosshairangle.h"
|
#include "svc_crosshairangle.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "demofile/demojson.h"
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -14,41 +11,4 @@ namespace NetHandlers
|
|||||||
data->angle.z = bitbuf.ReadBitAngle(16);
|
data->angle.z = bitbuf.ReadBitAngle(16);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_CrosshairAngle_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_CrosshairAngle* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteBitAngle(data->angle.x, 16);
|
|
||||||
bitbuf.WriteBitAngle(data->angle.y, 16);
|
|
||||||
bitbuf.WriteBitAngle(data->angle.z, 16);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_CrosshairAngle_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_CrosshairAngle* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
DemoJsonReader::ReadAngle(reader, "angle", data->angle);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_CrosshairAngle_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_CrosshairAngle* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
DemoJsonWriter::WriteAngle(jsonbuf, "angle", data->angle);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_CrosshairAngle_ToString_Internal(std::ostringstream& out, NetMsg::SVC_CrosshairAngle* data)
|
|
||||||
{
|
|
||||||
const std::streamsize oldPrecision = out.precision();
|
|
||||||
out << "svc_CrosshairAngle:"
|
|
||||||
<< std::setprecision(1) << std::fixed
|
|
||||||
<< " (" << data->angle.x
|
|
||||||
<< " " << data->angle.y
|
|
||||||
<< " " << data->angle.z << ")"
|
|
||||||
<< std::setprecision(oldPrecision);
|
|
||||||
out.unsetf(std::ios_base::floatfield);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_entitymessage.h"
|
#include "svc_entitymessage.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
|
|
||||||
@ -16,44 +15,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_EntityMessage_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_EntityMessage* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->entIndex, MAX_EDICT_BITS);
|
|
||||||
bitbuf.WriteUBitLong(data->classID, MAX_SERVER_CLASS_BITS);
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, 11);
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_EntityMessage_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_EntityMessage* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->entIndex = reader.ReadUInt32("entIndex");
|
|
||||||
data->classID = reader.ReadUInt32("classId");
|
|
||||||
data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits");
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_EntityMessage_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_EntityMessage* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("entIndex", data->entIndex);
|
|
||||||
jsonbuf.WriteUInt32("classId", data->classID);
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_EntityMessage_ToString_Internal(std::ostringstream& out, NetMsg::SVC_EntityMessage* data)
|
|
||||||
{
|
|
||||||
out << "svc_EntityMessage: entity " << data->entIndex
|
|
||||||
<< ", class " << data->classID
|
|
||||||
<< ", bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_fixangle.h"
|
#include "svc_fixangle.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "demofile/demojson.h"
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -15,44 +12,4 @@ namespace NetHandlers
|
|||||||
data->angle.z = bitbuf.ReadBitAngle(16);
|
data->angle.z = bitbuf.ReadBitAngle(16);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_FixAngle_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_FixAngle* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(data->relative);
|
|
||||||
bitbuf.WriteBitAngle(data->angle.x, 16);
|
|
||||||
bitbuf.WriteBitAngle(data->angle.y, 16);
|
|
||||||
bitbuf.WriteBitAngle(data->angle.z, 16);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_FixAngle_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_FixAngle* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->relative = reader.ReadBool("relative");
|
|
||||||
DemoJsonReader::ReadAngle(reader, "angle", data->angle);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_FixAngle_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_FixAngle* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteBool("relative", data->relative);
|
|
||||||
DemoJsonWriter::WriteAngle(jsonbuf, "angle", data->angle);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_FixAngle_ToString_Internal(std::ostringstream& out, NetMsg::SVC_FixAngle* data)
|
|
||||||
{
|
|
||||||
const std::streamsize oldPrecision = out.precision();
|
|
||||||
out << "svc_FixAngle: " << (data->relative ? "relative" : "absolute")
|
|
||||||
<< std::setprecision(1) << std::fixed
|
|
||||||
<< " " << data->angle.x
|
|
||||||
<< " " << data->angle.y
|
|
||||||
<< " " << data->angle.z
|
|
||||||
<< std::setprecision(oldPrecision);
|
|
||||||
out.unsetf(std::ios_base::floatfield);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
|
|
||||||
#include "svc_gameevent.h"
|
#include "svc_gameevent.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
#include "game/sourcecontext.h"
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
|
|
||||||
#ifdef WIP_GAMEEVENTS
|
|
||||||
#include "svc_gameeventlist.h"
|
#include "svc_gameeventlist.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -20,49 +17,12 @@ namespace NetHandlers
|
|||||||
data->data.reset(new uint8_t[numBytes]);
|
data->data.reset(new uint8_t[numBytes]);
|
||||||
bitbuf.ReadBits(data->data.get(), numBits);
|
bitbuf.ReadBits(data->data.get(), numBits);
|
||||||
|
|
||||||
#ifdef WIP_GAMEEVENTS
|
BitRead bitbuf2(data->data.get(), numBytes, numBits);
|
||||||
{
|
const size_t id = bitbuf2.ReadUBitLong(9);
|
||||||
BitRead bitbuf2(data->data.get(), numBytes, numBits);
|
GameEvents::EventDataMap eventData = GameEvents::ParseEventData(bitbuf2, context.gameEventList->eventDescriptors[id]);
|
||||||
const size_t id = bitbuf2.ReadUBitLong(9);
|
|
||||||
//std::vector<char> stringMem;
|
context.OnGameEvent(context.gameEventList->eventDescriptors[id].name, eventData);
|
||||||
//GameEvents::ParseEventData(bitbuf2, context.gameEventList->eventDescriptors[id], stringMem);
|
|
||||||
GameEvents::PrintEventData(bitbuf2, context.gameEventList->eventDescriptors[id]);
|
|
||||||
printf("%i\n", id);
|
|
||||||
}
|
|
||||||
#endif // WIP_GAMEEVENTS
|
|
||||||
|
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_GameEvent_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_GameEvent* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, 11);
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_GameEvent_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_GameEvent* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits");
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_GameEvent_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_GameEvent* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_GameEvent_ToString_Internal(std::ostringstream& out, NetMsg::SVC_GameEvent* data)
|
|
||||||
{
|
|
||||||
out << "svc_GameEvent: bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_gameeventlist.h"
|
#include "svc_gameeventlist.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "game/sourcecontext.h"
|
#include "game/sourcecontext.h"
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
@ -47,84 +46,11 @@ namespace NetHandlers
|
|||||||
event.values.shrink_to_fit();
|
event.values.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIP_GAMEEVENTS
|
|
||||||
if (!context.gameEventList)
|
if (!context.gameEventList)
|
||||||
{
|
{
|
||||||
context.gameEventList = new NetMsg::SVC_GameEventList(*data);
|
context.gameEventList = new NetMsg::SVC_GameEventList(*data);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_GameEventList_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_GameEventList* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->eventDescriptors.size(), MAX_EVENT_BITS);
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, 20);
|
|
||||||
assert(data->dataLengthInBits == CalculateNumDataBits(data->eventDescriptors));
|
|
||||||
for (EventDescriptor& event : data->eventDescriptors)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(event.id, MAX_EVENT_BITS);
|
|
||||||
bitbuf.WriteString(event.name);
|
|
||||||
for (EventValue& value : event.values)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(value.type, 3);
|
|
||||||
bitbuf.WriteString(value.name);
|
|
||||||
}
|
|
||||||
bitbuf.WriteUBitLong(0, 3);
|
|
||||||
}
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_GameEventList_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_GameEventList* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
|
|
||||||
base::JsonReaderArray eventDescriptors = reader.ReadArray("eventDescriptors");
|
|
||||||
eventDescriptors.TransformTo(data->eventDescriptors, [](base::JsonReaderObject& obj, EventDescriptor& event)
|
|
||||||
{
|
|
||||||
event.id = obj.ReadUInt32("id");
|
|
||||||
obj.ReadString("name", event.name, sizeof(event.name));
|
|
||||||
base::JsonReaderArray values = obj.ReadArray("values");
|
|
||||||
values.TransformTo(event.values, [](base::JsonReaderObject& obj, EventValue& value)
|
|
||||||
{
|
|
||||||
value.type = static_cast<GameEvents::EventValueType>(obj.ReadUInt32("type"));
|
|
||||||
obj.ReadString("name", value.name, sizeof(value.name));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
data->dataLengthInBits = CalculateNumDataBits(data->eventDescriptors);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_GameEventList_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_GameEventList* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.StartArray("eventDescriptors");
|
|
||||||
for (const EventDescriptor& event : data->eventDescriptors)
|
|
||||||
{
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("id", event.id);
|
|
||||||
jsonbuf.WriteString("name", event.name);
|
|
||||||
jsonbuf.StartArray("values");
|
|
||||||
for (const EventValue& value : event.values)
|
|
||||||
{
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("type", value.type);
|
|
||||||
jsonbuf.WriteString("name", value.name);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
}
|
|
||||||
jsonbuf.EndArray();
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
}
|
|
||||||
jsonbuf.EndArray();
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_GameEventList_ToString_Internal(std::ostringstream& out, NetMsg::SVC_GameEventList* data)
|
|
||||||
{
|
|
||||||
out << "svc_GameEventList: number " << data->eventDescriptors.size()
|
|
||||||
<< ", bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_getcvarvalue.h"
|
#include "svc_getcvarvalue.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -11,36 +10,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadString(data->cvarName, sizeof(data->cvarName));
|
bitbuf.ReadString(data->cvarName, sizeof(data->cvarName));
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_GetCvarValue_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_GetCvarValue* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteSBitLong(data->cookie, 32);
|
|
||||||
bitbuf.WriteString(data->cvarName);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_GetCvarValue_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_GetCvarValue* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->cookie = reader.ReadInt32("cookie");
|
|
||||||
reader.ReadString("cvarName", data->cvarName, sizeof(data->cvarName));
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_GetCvarValue_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_GetCvarValue* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteInt32("cookie", data->cookie);
|
|
||||||
jsonbuf.WriteString("cvarName", data->cvarName);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_GetCvarValue_ToString_Internal(std::ostringstream& out, NetMsg::SVC_GetCvarValue* data)
|
|
||||||
{
|
|
||||||
out << "svc_GetCvarValue: cvar: " << data->cvarName
|
|
||||||
<< ", cookie: " << data->cookie;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,27 +9,4 @@ namespace NetHandlers
|
|||||||
assert(false);
|
assert(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_HLTV_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_HLTV* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_HLTV_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_HLTV* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_HLTV_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_HLTV* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_HLTV_ToString_Internal(std::ostringstream& out, NetMsg::SVC_HLTV* data)
|
|
||||||
{
|
|
||||||
out << "svc_HLTV";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,9 @@
|
|||||||
|
|
||||||
#include "svc_menu.h"
|
#include "svc_menu.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
using DialogType = NetMsg::SVC_Menu::DialogType;
|
using DialogType = NetMsg::SVC_Menu::DialogType;
|
||||||
|
|
||||||
#define KEYVALUES_TOKEN_SIZE 1024
|
|
||||||
|
|
||||||
static const char* KeyValuesBin_GetName(uint8_t* data, size_t dataLength)
|
|
||||||
{
|
|
||||||
if (dataLength <= 2)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return reinterpret_cast<const char*>(data + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
bool SVC_Menu_BitRead_Internal(BitRead& bitbuf, SourceGameContext& context, NetMsg::SVC_Menu* data)
|
bool SVC_Menu_BitRead_Internal(BitRead& bitbuf, SourceGameContext& context, NetMsg::SVC_Menu* data)
|
||||||
@ -26,44 +14,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadBytes(data->menuBinaryKeyValues.get(), data->dataLengthInBytes);
|
bitbuf.ReadBytes(data->menuBinaryKeyValues.get(), data->dataLengthInBytes);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_Menu_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_Menu* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteShort(static_cast<int16_t>(data->type));
|
|
||||||
bitbuf.WriteWord(data->dataLengthInBytes);
|
|
||||||
bitbuf.WriteBytes(data->menuBinaryKeyValues.get(), data->dataLengthInBytes);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_Menu_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Menu* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->type = static_cast<DialogType>(reader.ReadInt32("dialogType"));
|
|
||||||
data->dataLengthInBytes = reader.ReadUInt32("dataLengthInBytes");
|
|
||||||
data->menuBinaryKeyValues.reset(new uint8_t[data->dataLengthInBytes]);
|
|
||||||
reader.ReadBytes("data", data->menuBinaryKeyValues.get(), data->dataLengthInBytes);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_Menu_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_Menu* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteInt32("dialogType", static_cast<int16_t>(data->type));
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBytes", data->dataLengthInBytes);
|
|
||||||
jsonbuf.WriteBytes("data", data->menuBinaryKeyValues.get(), data->dataLengthInBytes);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_Menu_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Menu* data)
|
|
||||||
{
|
|
||||||
// binary keyvalues in form [type][name][value]
|
|
||||||
// [char][cstr][type]
|
|
||||||
const char* name = KeyValuesBin_GetName(data->menuBinaryKeyValues.get(), data->dataLengthInBytes);
|
|
||||||
out << "svc_Menu: " << static_cast<int16_t>(data->type)
|
|
||||||
<< " \"" << (name ? name : "No KeyValues")
|
|
||||||
<< "\" (len:" << data->dataLengthInBytes << ")";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_packetentities.h"
|
#include "svc_packetentities.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
|
|
||||||
@ -25,67 +24,35 @@ namespace NetHandlers
|
|||||||
data->updateBaseline = bitbuf.ReadOneBit() != 0;
|
data->updateBaseline = bitbuf.ReadOneBit() != 0;
|
||||||
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);
|
||||||
return !bitbuf.IsOverflowed();
|
/*
|
||||||
}
|
int last_index = -1;
|
||||||
|
for (int i = 0; i < data->numUpdatedEntries; i++)
|
||||||
bool SVC_PacketEntities_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_PacketEntities* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->maxEntries, MAX_EDICT_BITS);
|
|
||||||
if (data->isDelta)
|
|
||||||
{
|
{
|
||||||
bitbuf.WriteOneBit(1);
|
last_index += 1 + bitbuf.ReadUBitVar();
|
||||||
bitbuf.WriteLong(data->deltaFromTick);
|
|
||||||
|
int pvs = bitbuf.ReadUBitLong(2);
|
||||||
|
printf("%d - %d\n", last_index, pvs);
|
||||||
|
switch(pvs)
|
||||||
|
{
|
||||||
|
case 0: // delta
|
||||||
|
{
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case 2: // enter PVS
|
||||||
|
{
|
||||||
|
int iClass = bitbuf.ReadUBitLong(MAX_SERVER_CLASS_BITS);
|
||||||
|
int serial = bitbuf.ReadUBitLong(NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS);
|
||||||
|
printf("\t%d - %d\n", iClass, serial);
|
||||||
|
} break;
|
||||||
|
case 1: // leave PVS
|
||||||
|
case 3: // delete
|
||||||
|
{
|
||||||
|
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
*/
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(0);
|
|
||||||
}
|
|
||||||
bitbuf.WriteUBitLong(data->baselineIndex, 1);
|
|
||||||
bitbuf.WriteUBitLong(data->numUpdatedEntries, MAX_EDICT_BITS);
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, DELTASIZE_BITS);
|
|
||||||
bitbuf.WriteOneBit(data->updateBaseline);
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_PacketEntities_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_PacketEntities* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->maxEntries = reader.ReadInt32("maxEntries");
|
|
||||||
data->isDelta = reader.ReadBool("isDelta");
|
|
||||||
data->deltaFromTick = reader.ReadInt32("deltaFromTick");
|
|
||||||
data->baselineIndex = reader.ReadUInt32("baselineIndex");
|
|
||||||
data->numUpdatedEntries = reader.ReadUInt32("numUpdatedEntries");
|
|
||||||
data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits");
|
|
||||||
data->updateBaseline = reader.ReadBool("updateBaseline");
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_PacketEntities_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_PacketEntities* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteInt32("maxEntries", data->maxEntries);
|
|
||||||
jsonbuf.WriteBool("isDelta", data->isDelta);
|
|
||||||
jsonbuf.WriteInt32("deltaFromTick", data->deltaFromTick);
|
|
||||||
jsonbuf.WriteUInt32("baselineIndex", data->baselineIndex);
|
|
||||||
jsonbuf.WriteUInt32("numUpdatedEntries", data->numUpdatedEntries);
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBool("updateBaseline", data->updateBaseline);
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_PacketEntities_ToString_Internal(std::ostringstream& out, NetMsg::SVC_PacketEntities* data)
|
|
||||||
{
|
|
||||||
out << "svc_PacketEntities: delta " << data->deltaFromTick
|
|
||||||
<< ", max " << data->maxEntries
|
|
||||||
<< ", changed " << data->numUpdatedEntries
|
|
||||||
<< "," << (data->updateBaseline ? " BL update," : "")
|
|
||||||
<< " bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_prefetch.h"
|
#include "svc_prefetch.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "game/sourcecontext.h"
|
#include "game/sourcecontext.h"
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
|
|
||||||
@ -20,42 +19,4 @@ namespace NetHandlers
|
|||||||
}
|
}
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_Prefetch_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_Prefetch* data)
|
|
||||||
{
|
|
||||||
if (context.protocol > 23)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->soundIndex, MAX_SOUND_INDEX_BITS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->soundIndex, MAX_SOUND_INDEX_BITS_OLD);
|
|
||||||
}
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_Prefetch_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Prefetch* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->type = reader.ReadUInt32("type");
|
|
||||||
data->soundIndex = reader.ReadUInt32("soundIndex");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_Prefetch_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_Prefetch* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();;
|
|
||||||
jsonbuf.WriteUInt32("type", data->type);
|
|
||||||
jsonbuf.WriteUInt32("soundIndex", data->soundIndex);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_Prefetch_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Prefetch* data)
|
|
||||||
{
|
|
||||||
out << "svc_Prefetch: type " << data->type
|
|
||||||
<< " index " << data->soundIndex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_print.h"
|
#include "svc_print.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -10,32 +9,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadString(data->text, sizeof(data->text));
|
bitbuf.ReadString(data->text, sizeof(data->text));
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_Print_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_Print* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteString(data->text);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_Print_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Print* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
reader.ReadString("text", data->text, sizeof(data->text));
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_Print_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_Print* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteString("text", data->text);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_Print_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Print* data)
|
|
||||||
{
|
|
||||||
out << "svc_Print: \"" << data->text << '"';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_sendtable.h"
|
#include "svc_sendtable.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
@ -14,40 +13,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_SendTable_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_SendTable* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(data->needsDecoder);
|
|
||||||
bitbuf.WriteShort(data->dataLengthInBits);
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_SendTable_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SendTable* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->needsDecoder = reader.ReadBool("needsDecoder");
|
|
||||||
data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits");
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_SendTable_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_SendTable* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteBool("needsDecoder", data->needsDecoder);
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_SendTable_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SendTable* data)
|
|
||||||
{
|
|
||||||
out << "svc_SendTable: needs Decoder " << (data->needsDecoder ? "yes" : "no")
|
|
||||||
<< ",bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_serverinfo.h"
|
#include "svc_serverinfo.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "game/sourcecontext.h"
|
#include "game/sourcecontext.h"
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
@ -20,7 +19,7 @@ namespace NetHandlers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bitbuf.ReadBytes(data->unk1, sizeof(data->unk1));
|
bitbuf.ReadBytes(data->mapMD5, sizeof(data->mapMD5));
|
||||||
}
|
}
|
||||||
data->playerSlot = bitbuf.ReadByte();
|
data->playerSlot = bitbuf.ReadByte();
|
||||||
data->maxClients = bitbuf.ReadByte();
|
data->maxClients = bitbuf.ReadByte();
|
||||||
@ -32,113 +31,8 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadString(data->hostName, sizeof(data->hostName));
|
bitbuf.ReadString(data->hostName, sizeof(data->hostName));
|
||||||
if (context.protocol > 15)
|
if (context.protocol > 15)
|
||||||
{
|
{
|
||||||
data->unk2 = bitbuf.ReadOneBit() != 0;
|
data->isReplay = bitbuf.ReadOneBit() != 0;
|
||||||
}
|
}
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_ServerInfo_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_ServerInfo* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteShort(data->protocol);
|
|
||||||
bitbuf.WriteLong(data->serverCount);
|
|
||||||
bitbuf.WriteOneBit(data->isHLTV);
|
|
||||||
bitbuf.WriteOneBit(data->isDedicated);
|
|
||||||
bitbuf.WriteLong(data->clientCRC);
|
|
||||||
bitbuf.WriteWord(data->maxClasses);
|
|
||||||
if (context.protocol <= 17)
|
|
||||||
{
|
|
||||||
bitbuf.WriteLong(data->mapCRC);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bitbuf.WriteBytes(data->unk1, sizeof(data->unk1));
|
|
||||||
}
|
|
||||||
bitbuf.WriteByte(data->playerSlot);
|
|
||||||
bitbuf.WriteByte(data->maxClients);
|
|
||||||
bitbuf.WriteFloat(data->tickInterval);
|
|
||||||
bitbuf.WriteChar(data->os);
|
|
||||||
bitbuf.WriteString(data->gameDir);
|
|
||||||
bitbuf.WriteString(data->mapName);
|
|
||||||
bitbuf.WriteString(data->skyName);
|
|
||||||
bitbuf.WriteString(data->hostName);
|
|
||||||
if (context.protocol > 15)
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(data->unk2);
|
|
||||||
}
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_ServerInfo_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_ServerInfo* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->protocol = reader.ReadInt32("protocol");
|
|
||||||
data->serverCount = reader.ReadUInt32("serverCount");
|
|
||||||
data->isHLTV = reader.ReadBool("isHltv");
|
|
||||||
data->isDedicated = reader.ReadBool("isDedicated");
|
|
||||||
data->clientCRC = reader.ReadUInt32("clientCrc");
|
|
||||||
data->maxClasses = reader.ReadUInt32("maxClasses");
|
|
||||||
if (context.protocol <= 17)
|
|
||||||
{
|
|
||||||
data->mapCRC = reader.ReadUInt32("mapCRC");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reader.ReadBytes("unk1", data->unk1, sizeof(data->unk1));
|
|
||||||
}
|
|
||||||
data->playerSlot = reader.ReadUInt32("playerSlot");
|
|
||||||
data->maxClients = reader.ReadUInt32("maxClients");
|
|
||||||
data->tickInterval = reader.ReadFloat("tickInterval");
|
|
||||||
data->os = reader.ReadChar("os");
|
|
||||||
reader.ReadString("gameDir", data->gameDir, sizeof(data->gameDir));
|
|
||||||
reader.ReadString("mapName", data->mapName, sizeof(data->mapName));
|
|
||||||
reader.ReadString("skyName", data->skyName, sizeof(data->skyName));
|
|
||||||
reader.ReadString("hostName", data->hostName, sizeof(data->hostName));
|
|
||||||
if (context.protocol > 15)
|
|
||||||
{
|
|
||||||
data->unk2 = reader.ReadBool("unk2");
|
|
||||||
}
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_ServerInfo_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_ServerInfo* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteInt32("protocol", data->protocol);
|
|
||||||
jsonbuf.WriteUInt32("serverCount", data->serverCount);
|
|
||||||
jsonbuf.WriteBool("isHltv", data->isHLTV);
|
|
||||||
jsonbuf.WriteBool("isDedicated", data->isDedicated);
|
|
||||||
jsonbuf.WriteUInt32("clientCrc", data->clientCRC);
|
|
||||||
jsonbuf.WriteUInt32("maxClasses", data->maxClasses);
|
|
||||||
if (context.protocol <= 17)
|
|
||||||
{
|
|
||||||
jsonbuf.WriteUInt32("mapCRC", data->mapCRC);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
jsonbuf.WriteBytes("unk1", data->unk1, sizeof(data->unk1));
|
|
||||||
}
|
|
||||||
jsonbuf.WriteUInt32("playerSlot", data->playerSlot);
|
|
||||||
jsonbuf.WriteUInt32("maxClients", data->maxClients);
|
|
||||||
jsonbuf.WriteFloat("tickInterval", data->tickInterval);
|
|
||||||
jsonbuf.WriteChar("os", data->os);
|
|
||||||
jsonbuf.WriteString("gameDir", data->gameDir);
|
|
||||||
jsonbuf.WriteString("mapName", data->mapName);
|
|
||||||
jsonbuf.WriteString("skyName", data->skyName);
|
|
||||||
jsonbuf.WriteString("hostName", data->hostName);
|
|
||||||
if (context.protocol > 15)
|
|
||||||
{
|
|
||||||
jsonbuf.WriteBool("unk2", data->unk2);
|
|
||||||
}
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_ServerInfo_ToString_Internal(std::ostringstream& out, NetMsg::SVC_ServerInfo* data)
|
|
||||||
{
|
|
||||||
out << "svc_ServerInfo: game \"" << data->gameDir
|
|
||||||
<< "\", map \"" << data->mapName
|
|
||||||
<< "\", max " << static_cast<uint32_t>(data->maxClients);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ namespace NetMsg
|
|||||||
uint32_t clientCRC; // client.dll CRC server is using
|
uint32_t clientCRC; // client.dll CRC server is using
|
||||||
uint16_t maxClasses; // max number of server classes
|
uint16_t maxClasses; // max number of server classes
|
||||||
uint32_t mapCRC; // server map CRC
|
uint32_t mapCRC; // server map CRC
|
||||||
uint8_t unk1[16];
|
uint8_t mapMD5[16];
|
||||||
uint8_t playerSlot; // our client slot number
|
uint8_t playerSlot; // our client slot number
|
||||||
uint8_t maxClients; // max number of clients on server
|
uint8_t maxClients; // max number of clients on server
|
||||||
float tickInterval; // server tick interval
|
float tickInterval; // server tick interval
|
||||||
@ -23,7 +23,7 @@ namespace NetMsg
|
|||||||
char mapName[MAX_OSPATH]; // name of current map
|
char mapName[MAX_OSPATH]; // name of current map
|
||||||
char skyName[MAX_OSPATH]; // name of current skybox
|
char skyName[MAX_OSPATH]; // name of current skybox
|
||||||
char hostName[MAX_OSPATH]; // host name
|
char hostName[MAX_OSPATH]; // host name
|
||||||
bool unk2;
|
bool isReplay;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_setpause.h"
|
#include "svc_setpause.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -10,32 +9,4 @@ namespace NetHandlers
|
|||||||
data->isPaused = bitbuf.ReadOneBit() != 0;
|
data->isPaused = bitbuf.ReadOneBit() != 0;
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_SetPause_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_SetPause* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(data->isPaused);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_SetPause_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SetPause* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->isPaused = reader.ReadBool("isPaused");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_SetPause_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_SetPause* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteBool("isPaused", data->isPaused);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_SetPause_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SetPause* data)
|
|
||||||
{
|
|
||||||
out << "svc_SetPause: " << (data->isPaused ? "paused" : "unpaused");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_setpausetimed.h"
|
#include "svc_setpausetimed.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -11,35 +10,4 @@ namespace NetHandlers
|
|||||||
data->time = bitbuf.ReadFloat();
|
data->time = bitbuf.ReadFloat();
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_SetPauseTimed_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_SetPauseTimed* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(data->isPaused);
|
|
||||||
bitbuf.WriteFloat(data->time);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_SetPauseTimed_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SetPauseTimed* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->isPaused = reader.ReadBool("isPaused");
|
|
||||||
data->time = reader.ReadFloat("time");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_SetPauseTimed_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_SetPauseTimed* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteBool("isPaused", data->isPaused);
|
|
||||||
jsonbuf.WriteFloat("time", data->time);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_SetPauseTimed_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SetPauseTimed* data)
|
|
||||||
{
|
|
||||||
out << "svc_SetPauseTimed: " << (data->isPaused ? "paused" : "unpaused");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_setview.h"
|
#include "svc_setview.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
@ -11,32 +10,4 @@ namespace NetHandlers
|
|||||||
data->entIndex = bitbuf.ReadUBitLong(MAX_EDICT_BITS);
|
data->entIndex = bitbuf.ReadUBitLong(MAX_EDICT_BITS);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_SetView_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_SetView* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->entIndex, MAX_EDICT_BITS);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_SetView_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_SetView* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->entIndex = reader.ReadUInt32("entIndex");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_SetView_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_SetView* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("entIndex", data->entIndex);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_SetView_ToString_Internal(std::ostringstream& out, NetMsg::SVC_SetView* data)
|
|
||||||
{
|
|
||||||
out << "svc_SetView: view entity " << data->entIndex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_sounds.h"
|
#include "svc_sounds.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
@ -23,52 +22,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_Sounds_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_Sounds* data)
|
|
||||||
{
|
|
||||||
if (data->reliableSound)
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(1);
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, 8);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(0);
|
|
||||||
bitbuf.WriteUBitLong(data->numSounds, 8);
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, 16);
|
|
||||||
}
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_Sounds_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_Sounds* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->reliableSound = reader.ReadBool("reliableSound");
|
|
||||||
data->numSounds = reader.ReadUInt32("numSounds");
|
|
||||||
data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits");
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_Sounds_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_Sounds* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteBool("reliableSound", data->reliableSound);
|
|
||||||
jsonbuf.WriteUInt32("numSounds", data->numSounds);
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_Sounds_ToString_Internal(std::ostringstream& out, NetMsg::SVC_Sounds* data)
|
|
||||||
{
|
|
||||||
out << "svc_Sounds: number " << static_cast<uint32_t>(data->numSounds)
|
|
||||||
<< (data->reliableSound ? ", reliable" : "")
|
|
||||||
<< ", bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_tempentities.h"
|
#include "svc_tempentities.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "game/sourcecontext.h"
|
#include "game/sourcecontext.h"
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
@ -23,47 +22,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_TempEntities_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_TempEntities* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->numEntries, EVENT_INDEX_BITS);
|
|
||||||
if (context.protocol > 23)
|
|
||||||
{
|
|
||||||
bitbuf.WriteVarInt32(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, NET_MAX_PAYLOAD_BITS_OLD);
|
|
||||||
}
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_TempEntities_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_TempEntities* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->numEntries = reader.ReadUInt32("numEntries");
|
|
||||||
data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits");
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_TempEntities_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_TempEntities* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("numEntries", data->numEntries);
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_TempEntities_ToString_Internal(std::ostringstream& out, NetMsg::SVC_TempEntities* data)
|
|
||||||
{
|
|
||||||
out << "svc_TempEntities: number " << data->numEntries
|
|
||||||
<< ", bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,27 +9,4 @@ namespace NetHandlers
|
|||||||
assert(false);
|
assert(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_TerrainMod_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_TerrainMod* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_TerrainMod_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_TerrainMod* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_TerrainMod_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_TerrainMod* data)
|
|
||||||
{
|
|
||||||
assert(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_TerrainMod_ToString_Internal(std::ostringstream& out, NetMsg::SVC_TerrainMod* data)
|
|
||||||
{
|
|
||||||
out << "svc_TerrainMod";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
#include "svc_updatestringtable.h"
|
#include "svc_updatestringtable.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
#include "game/sourcecontext.h"
|
||||||
|
#include "game/stringtables.h"
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
|
|
||||||
@ -14,54 +15,11 @@ namespace NetHandlers
|
|||||||
data->dataLengthInBits = bitbuf.ReadUBitLong(20);
|
data->dataLengthInBits = bitbuf.ReadUBitLong(20);
|
||||||
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);
|
||||||
|
|
||||||
|
StringTable *table = &context.stringTables->tables[data->tableID];
|
||||||
|
bf_read bitbuf2(data->data.get(), math::BitsToBytes(data->dataLengthInBits), data->dataLengthInBits);
|
||||||
|
table->ParseUpdate(bitbuf2, data->numChangedEntries, context);
|
||||||
|
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_UpdateStringTable_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_UpdateStringTable* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteUBitLong(data->tableID, math::log2(MAX_TABLES));
|
|
||||||
if (data->numChangedEntries != 1)
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(1);
|
|
||||||
bitbuf.WriteWord(data->numChangedEntries);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bitbuf.WriteOneBit(0);
|
|
||||||
}
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, 20);
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_UpdateStringTable_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_UpdateStringTable* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->tableID = reader.ReadUInt32("tableId");
|
|
||||||
data->numChangedEntries = reader.ReadUInt32("numChangedEntries");
|
|
||||||
data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits");
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_UpdateStringTable_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_UpdateStringTable* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("tableId", data->tableID);
|
|
||||||
jsonbuf.WriteUInt32("numChangedEntries", data->numChangedEntries);
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_UpdateStringTable_ToString_Internal(std::ostringstream& out, NetMsg::SVC_UpdateStringTable* data)
|
|
||||||
{
|
|
||||||
out << "svc_UpdateStringTable: table " << data->tableID
|
|
||||||
<< ", changed " << data->numChangedEntries
|
|
||||||
<< ", bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_usermessage.h"
|
#include "svc_usermessage.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
#include "netcontants.h"
|
#include "netcontants.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -17,40 +16,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_UserMessage_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_UserMessage* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteByte(data->msgType);
|
|
||||||
bitbuf.WriteUBitLong(data->dataLengthInBits, 11);
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_UserMessage_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_UserMessage* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->msgType = reader.ReadUInt32("msgType");
|
|
||||||
data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits");
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_UserMessage_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_UserMessage* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("msgType", data->msgType);
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_UserMessage_ToString_Internal(std::ostringstream& out, NetMsg::SVC_UserMessage* data)
|
|
||||||
{
|
|
||||||
out << "svc_UserMessage: type " << static_cast<uint32_t>(data->msgType)
|
|
||||||
<< ", bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#include "svc_voicedata.h"
|
#include "svc_voicedata.h"
|
||||||
|
#include "svc_voiceinit.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
#include "netmath.h"
|
#include "netmath.h"
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
@ -15,43 +15,4 @@ namespace NetHandlers
|
|||||||
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
bitbuf.ReadBits(data->data.get(), data->dataLengthInBits);
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_VoiceData_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_VoiceData* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteByte(data->fromClientIndex);
|
|
||||||
bitbuf.WriteByte(data->proximity);
|
|
||||||
bitbuf.WriteWord(data->dataLengthInBits);
|
|
||||||
bitbuf.WriteBits(data->data.get(), data->dataLengthInBits);
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_VoiceData_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_VoiceData* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
data->fromClientIndex = reader.ReadUInt32("fromClientIndex");
|
|
||||||
data->proximity = reader.ReadBool("proximity");
|
|
||||||
data->dataLengthInBits = reader.ReadUInt32("dataLengthInBits");
|
|
||||||
data->data.reset(new uint8_t[math::BitsToBytes(data->dataLengthInBits)]);
|
|
||||||
reader.ReadBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_VoiceData_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_VoiceData* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteUInt32("fromClientIndex", data->fromClientIndex);
|
|
||||||
jsonbuf.WriteBool("proximity", data->proximity);
|
|
||||||
jsonbuf.WriteUInt32("dataLengthInBits", data->dataLengthInBits);
|
|
||||||
jsonbuf.WriteBits("data", data->data.get(), data->dataLengthInBits);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_VoiceData_ToString_Internal(std::ostringstream& out, NetMsg::SVC_VoiceData* data)
|
|
||||||
{
|
|
||||||
out << "svc_VoiceData: client " << static_cast<uint32_t>(data->fromClientIndex)
|
|
||||||
<< ", bytes " << math::BitsToBytes(data->dataLengthInBits);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
#include "svc_voiceinit.h"
|
#include "svc_voiceinit.h"
|
||||||
#include "base/bitfile.h"
|
#include "base/bitfile.h"
|
||||||
#include "base/jsonfile.h"
|
|
||||||
|
|
||||||
namespace NetHandlers
|
namespace NetHandlers
|
||||||
{
|
{
|
||||||
@ -20,49 +19,4 @@ namespace NetHandlers
|
|||||||
}
|
}
|
||||||
return !bitbuf.IsOverflowed();
|
return !bitbuf.IsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SVC_VoiceInit_BitWrite_Internal(BitWrite& bitbuf, const SourceGameContext& context, NetMsg::SVC_VoiceInit* data)
|
|
||||||
{
|
|
||||||
bitbuf.WriteString(data->voiceCodec);
|
|
||||||
bitbuf.WriteByte(data->quality);
|
|
||||||
if(data->quality == NetMsg::SVC_VoiceInit::QUALITY_HAS_SAMPLE_RATE)
|
|
||||||
{
|
|
||||||
bitbuf.WriteShort(data->sampleRate);
|
|
||||||
}
|
|
||||||
return !bitbuf.IsOverflowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_VoiceInit_JsonRead_Internal(JsonRead& jsonbuf, SourceGameContext& context, NetMsg::SVC_VoiceInit* data)
|
|
||||||
{
|
|
||||||
base::JsonReaderObject reader = jsonbuf.ParseObject();
|
|
||||||
assert(!reader.HasReadError());
|
|
||||||
reader.ReadString("voiceCodec", data->voiceCodec, sizeof(data->voiceCodec));
|
|
||||||
data->quality = reader.ReadUInt32("quality");
|
|
||||||
data->sampleRate = reader.ReadInt32("sampleRate");
|
|
||||||
return !reader.HasReadError();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SVC_VoiceInit_JsonWrite_Internal(JsonWrite& jsonbuf, const SourceGameContext& context, NetMsg::SVC_VoiceInit* data)
|
|
||||||
{
|
|
||||||
jsonbuf.Reset();
|
|
||||||
jsonbuf.StartObject();
|
|
||||||
jsonbuf.WriteString("voiceCodec", data->voiceCodec);
|
|
||||||
jsonbuf.WriteUInt32("quality", data->quality);
|
|
||||||
jsonbuf.WriteInt32("sampleRate", data->sampleRate);
|
|
||||||
jsonbuf.EndObject();
|
|
||||||
return jsonbuf.IsComplete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVC_VoiceInit_ToString_Internal(std::ostringstream& out, NetMsg::SVC_VoiceInit* data)
|
|
||||||
{
|
|
||||||
out << "svc_VoiceInit: codec \"" << data->voiceCodec;
|
|
||||||
if(data->quality == NetMsg::SVC_VoiceInit::QUALITY_HAS_SAMPLE_RATE)
|
|
||||||
{
|
|
||||||
out << "\", sample rate " << static_cast<uint32_t>(data->sampleRate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out << "\", qualitty " << static_cast<uint32_t>(data->quality);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
56
demboyz/netmessages/usermessages.h
Normal file
56
demboyz/netmessages/usermessages.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace UserMsg
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Geiger = 0,
|
||||||
|
Train = 1,
|
||||||
|
HudText = 2,
|
||||||
|
SayText = 3,
|
||||||
|
SayText2 = 4,
|
||||||
|
TextMsg = 5,
|
||||||
|
HudMsg = 6,
|
||||||
|
ResetHUD = 7,
|
||||||
|
GameTitle = 8,
|
||||||
|
ItemPickup = 9,
|
||||||
|
ShowMenu = 10,
|
||||||
|
Shake = 11,
|
||||||
|
Fade = 12,
|
||||||
|
VGUIMenu = 13,
|
||||||
|
Rumble = 14,
|
||||||
|
CloseCaption = 15,
|
||||||
|
SendAudio = 16,
|
||||||
|
RawAudio = 17,
|
||||||
|
VoiceMask = 18,
|
||||||
|
RequestState = 19,
|
||||||
|
BarTime = 20,
|
||||||
|
Damage = 21,
|
||||||
|
RadioText = 22,
|
||||||
|
HintText = 23,
|
||||||
|
KeyHintText = 24,
|
||||||
|
ReloadEffect = 25,
|
||||||
|
PlayerAnimEvent = 26,
|
||||||
|
AmmoDenied = 27,
|
||||||
|
UpdateRadar = 28,
|
||||||
|
KillCam = 29,
|
||||||
|
MarkAchievement = 30,
|
||||||
|
CallVoteFailed = 31,
|
||||||
|
VoteStart = 32,
|
||||||
|
VotePass = 33,
|
||||||
|
VoteFailed = 34,
|
||||||
|
VoteSetup = 35,
|
||||||
|
SPHapWeapEvent = 36,
|
||||||
|
HapDmg = 37,
|
||||||
|
HapPunch = 38,
|
||||||
|
HapSetDrag = 39,
|
||||||
|
HapSetConst = 40,
|
||||||
|
HapMeleeContact = 41,
|
||||||
|
PlayerStatsUpdate_DEPRECATED = 42,
|
||||||
|
AchievementEvent = 43,
|
||||||
|
MatchEndConditions = 44,
|
||||||
|
MatchStatsUpdate = 45,
|
||||||
|
PlayerStatsUpdate = 46
|
||||||
|
};
|
||||||
|
}
|
98
external/SILK_SDK_SRC_FLP_v1.0.9/Makefile
vendored
Executable file
98
external/SILK_SDK_SRC_FLP_v1.0.9/Makefile
vendored
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
#
|
||||||
|
# Makefile for Silk SDK
|
||||||
|
#
|
||||||
|
# Copyright (c) 2012, Skype Limited
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
#Platform detection and settings
|
||||||
|
|
||||||
|
BUILD_OS := $(shell uname | sed -e 's/^.*Darwin.*/MacOS-X/ ; s/^.*CYGWIN.*/Windows/')
|
||||||
|
BUILD_ARCHITECTURE := $(shell uname -m | sed -e 's/i686/i386/')
|
||||||
|
|
||||||
|
EXESUFFIX =
|
||||||
|
LIBPREFIX = lib
|
||||||
|
LIBSUFFIX = .a
|
||||||
|
OBJSUFFIX = .o
|
||||||
|
|
||||||
|
CC = $(TOOLCHAIN_PREFIX)gcc$(TOOLCHAIN_SUFFIX)
|
||||||
|
AR = $(TOOLCHAIN_PREFIX)ar
|
||||||
|
RANLIB = $(TOOLCHAIN_PREFIX)ranlib
|
||||||
|
CP = $(TOOLCHAIN_PREFIX)cp
|
||||||
|
|
||||||
|
cflags-from-defines = $(addprefix -D,$(1))
|
||||||
|
cflags-from-includes = $(addprefix -I,$(1))
|
||||||
|
ldflags-from-ldlibdirs = $(addprefix -L,$(1))
|
||||||
|
ldlibs-from-libs = $(addprefix -l,$(1))
|
||||||
|
|
||||||
|
CFLAGS += -Wall -enable-threads -O3
|
||||||
|
|
||||||
|
CFLAGS += $(call cflags-from-defines,$(CDEFINES))
|
||||||
|
CFLAGS += $(call cflags-from-defines,$(ADDED_DEFINES))
|
||||||
|
CFLAGS += $(call cflags-from-includes,$(CINCLUDES))
|
||||||
|
LDFLAGS += $(call ldflags-from-ldlibdirs,$(LDLIBDIRS))
|
||||||
|
LDLIBS += $(call ldlibs-from-libs,$(LIBS))
|
||||||
|
|
||||||
|
COMPILE.c.cmdline = $(CC) -c $(CFLAGS) -o $@ $<
|
||||||
|
LINK.o.cmdline = $(LINK.o) $^ $(LDLIBS) -lm -o $@$(EXESUFFIX)
|
||||||
|
ARCHIVE.cmdline = $(AR) $(ARFLAGS) $@ $^ && $(RANLIB) $@
|
||||||
|
|
||||||
|
%$(OBJSUFFIX):%.c
|
||||||
|
$(COMPILE.c.cmdline)
|
||||||
|
|
||||||
|
# Directives
|
||||||
|
|
||||||
|
CINCLUDES += interface src test
|
||||||
|
|
||||||
|
# VPATH e.g. VPATH = src:../headers
|
||||||
|
VPATH = ./ \
|
||||||
|
interface \
|
||||||
|
src \
|
||||||
|
test
|
||||||
|
|
||||||
|
# Variable definitions
|
||||||
|
LIB_NAME = SKP_SILK_SDK
|
||||||
|
TARGET = $(LIBPREFIX)$(LIB_NAME)$(LIBSUFFIX)
|
||||||
|
|
||||||
|
SRCS_C = $(wildcard src/*.c)
|
||||||
|
|
||||||
|
OBJS := $(patsubst %.c,%$(OBJSUFFIX),$(SRCS_C))
|
||||||
|
|
||||||
|
ENCODER_SRCS_C = test/Encoder.c
|
||||||
|
ENCODER_OBJS := $(patsubst %.c,%$(OBJSUFFIX),$(ENCODER_SRCS_C))
|
||||||
|
|
||||||
|
DECODER_SRCS_C = test/Decoder.c
|
||||||
|
DECODER_OBJS := $(patsubst %.c,%$(OBJSUFFIX),$(DECODER_SRCS_C))
|
||||||
|
|
||||||
|
SIGNALCMP_SRCS_C = test/signalCompare.c
|
||||||
|
SIGNALCMP_OBJS := $(patsubst %.c,%$(OBJSUFFIX),$(SIGNALCMP_SRCS_C))
|
||||||
|
|
||||||
|
LIBS = \
|
||||||
|
$(LIB_NAME)
|
||||||
|
|
||||||
|
LDLIBDIRS = ./
|
||||||
|
|
||||||
|
# Rules
|
||||||
|
default: all
|
||||||
|
|
||||||
|
all: $(TARGET) encoder decoder signalcompare
|
||||||
|
|
||||||
|
lib: $(TARGET)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
$(ARCHIVE.cmdline)
|
||||||
|
|
||||||
|
encoder$(EXESUFFIX): $(ENCODER_OBJS)
|
||||||
|
$(LINK.o.cmdline)
|
||||||
|
|
||||||
|
decoder$(EXESUFFIX): $(DECODER_OBJS)
|
||||||
|
$(LINK.o.cmdline)
|
||||||
|
|
||||||
|
signalcompare$(EXESUFFIX): $(SIGNALCMP_OBJS)
|
||||||
|
$(LINK.o.cmdline)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(TARGET)* $(OBJS) $(ENCODER_OBJS) $(DECODER_OBJS) \
|
||||||
|
$(SIGNALCMP_OBJS) $(TEST_OBJS) \
|
||||||
|
encoder$(EXESUFFIX) decoder$(EXESUFFIX) signalcompare$(EXESUFFIX)
|
||||||
|
|
56
external/SILK_SDK_SRC_FLP_v1.0.9/Silk_SDK.sln
vendored
Executable file
56
external/SILK_SDK_SRC_FLP_v1.0.9/Silk_SDK.sln
vendored
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual Studio 2010
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dec_SDK", "test\Dec_SDK.vcxproj", "{82685D7F-0589-42BD-877C-31A952D53A8E}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Enc_SDK", "test\Enc_SDK.vcxproj", "{6D97A8EF-5724-4D85-8BF4-C583714BBA78}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Silk_FLP", "src\Silk_FLP.vcxproj", "{56B91D01-9150-4BBF-AFA1-5B68AB991B76}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SignalCompare", "test\SignalCompare.vcxproj", "{7FE8F544-9175-40C3-A187-7F15CE9A75D8}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Release|x64.Build.0 = Release|x64
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|x64.Build.0 = Release|x64
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Release|x64.Build.0 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
44
external/SILK_SDK_SRC_FLP_v1.0.9/Silk_SDK_VS2005.sln
vendored
Executable file
44
external/SILK_SDK_SRC_FLP_v1.0.9/Silk_SDK_VS2005.sln
vendored
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||||
|
# Visual Studio 2005
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dec_SDK", "test\Dec_SDK.vcproj", "{82685D7F-0589-42BD-877C-31A952D53A8E}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76} = {56B91D01-9150-4BBF-AFA1-5B68AB991B76}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Enc_SDK", "test\Enc_SDK.vcproj", "{6D97A8EF-5724-4D85-8BF4-C583714BBA78}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76} = {56B91D01-9150-4BBF-AFA1-5B68AB991B76}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Silk_FLP", "src\Silk_FLP.vcproj", "{56B91D01-9150-4BBF-AFA1-5B68AB991B76}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SignalCompare", "test\SignalCompare.vcproj", "{7FE8F544-9175-40C3-A187-7F15CE9A75D8}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{82685D7F-0589-42BD-877C-31A952D53A8E}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{6D97A8EF-5724-4D85-8BF4-C583714BBA78}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{7FE8F544-9175-40C3-A187-7F15CE9A75D8}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
BIN
external/SILK_SDK_SRC_FLP_v1.0.9/doc/SILK_Evaluation.pdf
vendored
Executable file
BIN
external/SILK_SDK_SRC_FLP_v1.0.9/doc/SILK_Evaluation.pdf
vendored
Executable file
Binary file not shown.
BIN
external/SILK_SDK_SRC_FLP_v1.0.9/doc/SILK_RTP_PayloadFormat.pdf
vendored
Executable file
BIN
external/SILK_SDK_SRC_FLP_v1.0.9/doc/SILK_RTP_PayloadFormat.pdf
vendored
Executable file
Binary file not shown.
BIN
external/SILK_SDK_SRC_FLP_v1.0.9/doc/SILK_SDK_API.pdf
vendored
Executable file
BIN
external/SILK_SDK_SRC_FLP_v1.0.9/doc/SILK_SDK_API.pdf
vendored
Executable file
Binary file not shown.
152
external/SILK_SDK_SRC_FLP_v1.0.9/interface/SKP_Silk_SDK_API.h
vendored
Executable file
152
external/SILK_SDK_SRC_FLP_v1.0.9/interface/SKP_Silk_SDK_API.h
vendored
Executable file
@ -0,0 +1,152 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, (subject to the limitations in the disclaimer below)
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
- Neither the name of Skype Limited, nor the names of specific
|
||||||
|
contributors, may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||||
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#ifndef SKP_SILK_SDK_API_H
|
||||||
|
#define SKP_SILK_SDK_API_H
|
||||||
|
|
||||||
|
#include "SKP_Silk_control.h"
|
||||||
|
#include "SKP_Silk_typedef.h"
|
||||||
|
#include "SKP_Silk_errors.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SILK_MAX_FRAMES_PER_PACKET 5
|
||||||
|
|
||||||
|
/* Struct for TOC (Table of Contents) */
|
||||||
|
typedef struct {
|
||||||
|
SKP_int framesInPacket; /* Number of 20 ms frames in packet */
|
||||||
|
SKP_int fs_kHz; /* Sampling frequency in packet */
|
||||||
|
SKP_int inbandLBRR; /* Does packet contain LBRR information */
|
||||||
|
SKP_int corrupt; /* Packet is corrupt */
|
||||||
|
SKP_int vadFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* VAD flag for each frame in packet */
|
||||||
|
SKP_int sigtypeFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Signal type for each frame in packet */
|
||||||
|
} SKP_Silk_TOC_struct;
|
||||||
|
|
||||||
|
/****************************************/
|
||||||
|
/* Encoder functions */
|
||||||
|
/****************************************/
|
||||||
|
|
||||||
|
/***********************************************/
|
||||||
|
/* Get size in bytes of the Silk encoder state */
|
||||||
|
/***********************************************/
|
||||||
|
SKP_int SKP_Silk_SDK_Get_Encoder_Size(
|
||||||
|
SKP_int32 *encSizeBytes /* O: Number of bytes in SILK encoder state */
|
||||||
|
);
|
||||||
|
|
||||||
|
/*************************/
|
||||||
|
/* Init or reset encoder */
|
||||||
|
/*************************/
|
||||||
|
SKP_int SKP_Silk_SDK_InitEncoder(
|
||||||
|
void *encState, /* I/O: State */
|
||||||
|
SKP_SILK_SDK_EncControlStruct *encStatus /* O: Encoder Status */
|
||||||
|
);
|
||||||
|
|
||||||
|
/***************************************/
|
||||||
|
/* Read control structure from encoder */
|
||||||
|
/***************************************/
|
||||||
|
SKP_int SKP_Silk_SDK_QueryEncoder(
|
||||||
|
const void *encState, /* I: State */
|
||||||
|
SKP_SILK_SDK_EncControlStruct *encStatus /* O: Encoder Status */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**************************/
|
||||||
|
/* Encode frame with Silk */
|
||||||
|
/**************************/
|
||||||
|
SKP_int SKP_Silk_SDK_Encode(
|
||||||
|
void *encState, /* I/O: State */
|
||||||
|
const SKP_SILK_SDK_EncControlStruct *encControl, /* I: Control status */
|
||||||
|
const SKP_int16 *samplesIn, /* I: Speech sample input vector */
|
||||||
|
SKP_int nSamplesIn, /* I: Number of samples in input vector */
|
||||||
|
SKP_uint8 *outData, /* O: Encoded output vector */
|
||||||
|
SKP_int16 *nBytesOut /* I/O: Number of bytes in outData (input: Max bytes) */
|
||||||
|
);
|
||||||
|
|
||||||
|
/****************************************/
|
||||||
|
/* Decoder functions */
|
||||||
|
/****************************************/
|
||||||
|
|
||||||
|
/***********************************************/
|
||||||
|
/* Get size in bytes of the Silk decoder state */
|
||||||
|
/***********************************************/
|
||||||
|
SKP_int SKP_Silk_SDK_Get_Decoder_Size(
|
||||||
|
SKP_int32 *decSizeBytes /* O: Number of bytes in SILK decoder state */
|
||||||
|
);
|
||||||
|
|
||||||
|
/*************************/
|
||||||
|
/* Init or Reset decoder */
|
||||||
|
/*************************/
|
||||||
|
SKP_int SKP_Silk_SDK_InitDecoder(
|
||||||
|
void *decState /* I/O: State */
|
||||||
|
);
|
||||||
|
|
||||||
|
/******************/
|
||||||
|
/* Decode a frame */
|
||||||
|
/******************/
|
||||||
|
SKP_int SKP_Silk_SDK_Decode(
|
||||||
|
void* decState, /* I/O: State */
|
||||||
|
SKP_SILK_SDK_DecControlStruct* decControl, /* I/O: Control Structure */
|
||||||
|
SKP_int lostFlag, /* I: 0: no loss, 1 loss */
|
||||||
|
const SKP_uint8 *inData, /* I: Encoded input vector */
|
||||||
|
const SKP_int nBytesIn, /* I: Number of input bytes */
|
||||||
|
SKP_int16 *samplesOut, /* O: Decoded output speech vector */
|
||||||
|
SKP_int16 *nSamplesOut /* I/O: Number of samples (vector/decoded) */
|
||||||
|
);
|
||||||
|
|
||||||
|
/***************************************************************/
|
||||||
|
/* Find Low Bit Rate Redundancy (LBRR) information in a packet */
|
||||||
|
/***************************************************************/
|
||||||
|
void SKP_Silk_SDK_search_for_LBRR(
|
||||||
|
const SKP_uint8 *inData, /* I: Encoded input vector */
|
||||||
|
const SKP_int nBytesIn, /* I: Number of input Bytes */
|
||||||
|
SKP_int lost_offset, /* I: Offset from lost packet */
|
||||||
|
SKP_uint8 *LBRRData, /* O: LBRR payload */
|
||||||
|
SKP_int16 *nLBRRBytes /* O: Number of LBRR Bytes */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**************************************/
|
||||||
|
/* Get table of contents for a packet */
|
||||||
|
/**************************************/
|
||||||
|
void SKP_Silk_SDK_get_TOC(
|
||||||
|
const SKP_uint8 *inData, /* I: Encoded input vector */
|
||||||
|
const SKP_int nBytesIn, /* I: Number of input bytes */
|
||||||
|
SKP_Silk_TOC_struct *Silk_TOC /* O: Table of contents */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**************************/
|
||||||
|
/* Get the version number */
|
||||||
|
/**************************/
|
||||||
|
/* Return a pointer to string specifying the version */
|
||||||
|
const char *SKP_Silk_SDK_get_version();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
91
external/SILK_SDK_SRC_FLP_v1.0.9/interface/SKP_Silk_control.h
vendored
Executable file
91
external/SILK_SDK_SRC_FLP_v1.0.9/interface/SKP_Silk_control.h
vendored
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, (subject to the limitations in the disclaimer below)
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
- Neither the name of Skype Limited, nor the names of specific
|
||||||
|
contributors, may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||||
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#ifndef SKP_SILK_CONTROL_H
|
||||||
|
#define SKP_SILK_CONTROL_H
|
||||||
|
|
||||||
|
#include "SKP_Silk_typedef.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/***********************************************/
|
||||||
|
/* Structure for controlling encoder operation */
|
||||||
|
/***********************************************/
|
||||||
|
typedef struct {
|
||||||
|
/* I: Input signal sampling rate in Hertz; 8000/12000/16000/24000 */
|
||||||
|
SKP_int32 API_sampleRate;
|
||||||
|
|
||||||
|
/* I: Maximum internal sampling rate in Hertz; 8000/12000/16000/24000 */
|
||||||
|
SKP_int32 maxInternalSampleRate;
|
||||||
|
|
||||||
|
/* I: Number of samples per packet; must be equivalent of 20, 40, 60, 80 or 100 ms */
|
||||||
|
SKP_int packetSize;
|
||||||
|
|
||||||
|
/* I: Bitrate during active speech in bits/second; internally limited */
|
||||||
|
SKP_int32 bitRate;
|
||||||
|
|
||||||
|
/* I: Uplink packet loss in percent (0-100) */
|
||||||
|
SKP_int packetLossPercentage;
|
||||||
|
|
||||||
|
/* I: Complexity mode; 0 is lowest; 1 is medium and 2 is highest complexity */
|
||||||
|
SKP_int complexity;
|
||||||
|
|
||||||
|
/* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
|
||||||
|
SKP_int useInBandFEC;
|
||||||
|
|
||||||
|
/* I: Flag to enable discontinuous transmission (DTX); 0/1 */
|
||||||
|
SKP_int useDTX;
|
||||||
|
} SKP_SILK_SDK_EncControlStruct;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Structure for controlling decoder operation and reading decoder status */
|
||||||
|
/**************************************************************************/
|
||||||
|
typedef struct {
|
||||||
|
/* I: Output signal sampling rate in Hertz; 8000/12000/16000/24000 */
|
||||||
|
SKP_int32 API_sampleRate;
|
||||||
|
|
||||||
|
/* O: Number of samples per frame */
|
||||||
|
SKP_int frameSize;
|
||||||
|
|
||||||
|
/* O: Frames per packet 1, 2, 3, 4, 5 */
|
||||||
|
SKP_int framesPerPacket;
|
||||||
|
|
||||||
|
/* O: Flag to indicate that the decoder has remaining payloads internally */
|
||||||
|
SKP_int moreInternalDecoderFrames;
|
||||||
|
|
||||||
|
/* O: Distance between main payload and redundant payload in packets */
|
||||||
|
SKP_int inBandFECOffset;
|
||||||
|
} SKP_SILK_SDK_DecControlStruct;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
89
external/SILK_SDK_SRC_FLP_v1.0.9/interface/SKP_Silk_errors.h
vendored
Executable file
89
external/SILK_SDK_SRC_FLP_v1.0.9/interface/SKP_Silk_errors.h
vendored
Executable file
@ -0,0 +1,89 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, (subject to the limitations in the disclaimer below)
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
- Neither the name of Skype Limited, nor the names of specific
|
||||||
|
contributors, may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||||
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#ifndef SKP_SILK_ERRORS_H
|
||||||
|
#define SKP_SILK_ERRORS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/******************/
|
||||||
|
/* Error messages */
|
||||||
|
/******************/
|
||||||
|
#define SKP_SILK_NO_ERROR 0
|
||||||
|
|
||||||
|
/**************************/
|
||||||
|
/* Encoder error messages */
|
||||||
|
/**************************/
|
||||||
|
|
||||||
|
/* Input length is not a multiplum of 10 ms, or length is longer than the packet length */
|
||||||
|
#define SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES -1
|
||||||
|
|
||||||
|
/* Sampling frequency not 8000, 12000, 16000 or 24000 Hertz */
|
||||||
|
#define SKP_SILK_ENC_FS_NOT_SUPPORTED -2
|
||||||
|
|
||||||
|
/* Packet size not 20, 40, 60, 80 or 100 ms */
|
||||||
|
#define SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED -3
|
||||||
|
|
||||||
|
/* Allocated payload buffer too short */
|
||||||
|
#define SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT -4
|
||||||
|
|
||||||
|
/* Loss rate not between 0 and 100 percent */
|
||||||
|
#define SKP_SILK_ENC_INVALID_LOSS_RATE -5
|
||||||
|
|
||||||
|
/* Complexity setting not valid, use 0, 1 or 2 */
|
||||||
|
#define SKP_SILK_ENC_INVALID_COMPLEXITY_SETTING -6
|
||||||
|
|
||||||
|
/* Inband FEC setting not valid, use 0 or 1 */
|
||||||
|
#define SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING -7
|
||||||
|
|
||||||
|
/* DTX setting not valid, use 0 or 1 */
|
||||||
|
#define SKP_SILK_ENC_INVALID_DTX_SETTING -8
|
||||||
|
|
||||||
|
/* Internal encoder error */
|
||||||
|
#define SKP_SILK_ENC_INTERNAL_ERROR -9
|
||||||
|
|
||||||
|
/**************************/
|
||||||
|
/* Decoder error messages */
|
||||||
|
/**************************/
|
||||||
|
|
||||||
|
/* Output sampling frequency lower than internal decoded sampling frequency */
|
||||||
|
#define SKP_SILK_DEC_INVALID_SAMPLING_FREQUENCY -10
|
||||||
|
|
||||||
|
/* Payload size exceeded the maximum allowed 1024 bytes */
|
||||||
|
#define SKP_SILK_DEC_PAYLOAD_TOO_LARGE -11
|
||||||
|
|
||||||
|
/* Payload has bit errors */
|
||||||
|
#define SKP_SILK_DEC_PAYLOAD_ERROR -12
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
107
external/SILK_SDK_SRC_FLP_v1.0.9/interface/SKP_Silk_typedef.h
vendored
Executable file
107
external/SILK_SDK_SRC_FLP_v1.0.9/interface/SKP_Silk_typedef.h
vendored
Executable file
@ -0,0 +1,107 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, (subject to the limitations in the disclaimer below)
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
- Neither the name of Skype Limited, nor the names of specific
|
||||||
|
contributors, may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||||
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#ifndef _SKP_SILK_API_TYPDEF_H_
|
||||||
|
#define _SKP_SILK_API_TYPDEF_H_
|
||||||
|
|
||||||
|
#ifndef SKP_USE_DOUBLE_PRECISION_FLOATS
|
||||||
|
#define SKP_USE_DOUBLE_PRECISION_FLOATS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
#if defined( __GNUC__ )
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SKP_int int /* used for counters etc; at least 16 bits */
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define SKP_int64 int64_t
|
||||||
|
#else
|
||||||
|
# define SKP_int64 long long
|
||||||
|
#endif
|
||||||
|
#define SKP_int32 int
|
||||||
|
#define SKP_int16 short
|
||||||
|
#define SKP_int8 signed char
|
||||||
|
|
||||||
|
#define SKP_uint unsigned int /* used for counters etc; at least 16 bits */
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define SKP_uint64 uint64_t
|
||||||
|
#else
|
||||||
|
# define SKP_uint64 unsigned long long
|
||||||
|
#endif
|
||||||
|
#define SKP_uint32 unsigned int
|
||||||
|
#define SKP_uint16 unsigned short
|
||||||
|
#define SKP_uint8 unsigned char
|
||||||
|
|
||||||
|
#define SKP_int_ptr_size intptr_t
|
||||||
|
|
||||||
|
#if SKP_USE_DOUBLE_PRECISION_FLOATS
|
||||||
|
# define SKP_float double
|
||||||
|
# define SKP_float_MAX DBL_MAX
|
||||||
|
#else
|
||||||
|
# define SKP_float float
|
||||||
|
# define SKP_float_MAX FLT_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SKP_INLINE static __inline
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y)
|
||||||
|
#else
|
||||||
|
# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SKP_int64_MAX ((SKP_int64)0x7FFFFFFFFFFFFFFFLL) /* 2^63 - 1 */
|
||||||
|
#define SKP_int64_MIN ((SKP_int64)0x8000000000000000LL) /* -2^63 */
|
||||||
|
#define SKP_int32_MAX 0x7FFFFFFF /* 2^31 - 1 = 2147483647*/
|
||||||
|
#define SKP_int32_MIN ((SKP_int32)0x80000000) /* -2^31 = -2147483648*/
|
||||||
|
#define SKP_int16_MAX 0x7FFF /* 2^15 - 1 = 32767*/
|
||||||
|
#define SKP_int16_MIN ((SKP_int16)0x8000) /* -2^15 = -32768*/
|
||||||
|
#define SKP_int8_MAX 0x7F /* 2^7 - 1 = 127*/
|
||||||
|
#define SKP_int8_MIN ((SKP_int8)0x80) /* -2^7 = -128*/
|
||||||
|
|
||||||
|
#define SKP_uint32_MAX 0xFFFFFFFF /* 2^32 - 1 = 4294967295 */
|
||||||
|
#define SKP_uint32_MIN 0x00000000
|
||||||
|
#define SKP_uint16_MAX 0xFFFF /* 2^16 - 1 = 65535 */
|
||||||
|
#define SKP_uint16_MIN 0x0000
|
||||||
|
#define SKP_uint8_MAX 0xFF /* 2^8 - 1 = 255 */
|
||||||
|
#define SKP_uint8_MIN 0x00
|
||||||
|
|
||||||
|
#define SKP_TRUE 1
|
||||||
|
#define SKP_FALSE 0
|
||||||
|
|
||||||
|
/* assertions */
|
||||||
|
#if (defined _WIN32 && !defined _WINCE && !defined(__GNUC__) && !defined(NO_ASSERTS))
|
||||||
|
# ifndef SKP_assert
|
||||||
|
# include <crtdbg.h> /* ASSERTE() */
|
||||||
|
# define SKP_assert(COND) _ASSERTE(COND)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define SKP_assert(COND)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
94
external/SILK_SDK_SRC_FLP_v1.0.9/readme.txt
vendored
Executable file
94
external/SILK_SDK_SRC_FLP_v1.0.9/readme.txt
vendored
Executable file
@ -0,0 +1,94 @@
|
|||||||
|
************************************************************************
|
||||||
|
Floating Point SILK SDK 1.0.9 source code package
|
||||||
|
Copyright 2012 (c), Skype Limited
|
||||||
|
https://developer.skype.com/silk/
|
||||||
|
************************************************************************
|
||||||
|
|
||||||
|
Date: 03/08/2012 (Format: DD/MM/YYYY)
|
||||||
|
|
||||||
|
I. Description
|
||||||
|
|
||||||
|
This package contains files for compilation and evaluation of the floating
|
||||||
|
point SILK SDK library. The following is included in this package:
|
||||||
|
|
||||||
|
o Source code for the floating point SILK SDK library
|
||||||
|
o Source code for creating encoder and decoder executables
|
||||||
|
o Test vectors
|
||||||
|
o Comparison tool
|
||||||
|
o Microsoft Visual Studio solutions and project files
|
||||||
|
o Makefile for GNU C-compiler (GCC)
|
||||||
|
|
||||||
|
II. Files and Folders
|
||||||
|
|
||||||
|
o doc/ - contains more information about the SILK SDK
|
||||||
|
o interface/ - contains API header files
|
||||||
|
o src/ - contains all SILK SDK library source files
|
||||||
|
o test/ - contains source files for testing the SILK SDK
|
||||||
|
o test_vectors/ - contains test vectors
|
||||||
|
o Makefile - Makefile for compiling with GCC
|
||||||
|
o readme.txt - this file
|
||||||
|
o Silk_SDK.sln - Visual Studio 2010 solution for all SILK SDK code
|
||||||
|
o Silk_SDK_VS2005.sln - Visual Studio 2005 solution for all SILK SDK code
|
||||||
|
|
||||||
|
III. How to use the Makefile
|
||||||
|
|
||||||
|
1. How to clean and compile the SILK SDK library:
|
||||||
|
|
||||||
|
make clean lib
|
||||||
|
|
||||||
|
2. How to compile an encoder executable:
|
||||||
|
|
||||||
|
make encoder
|
||||||
|
|
||||||
|
3. How to compile a decoder executable:
|
||||||
|
|
||||||
|
make decoder
|
||||||
|
|
||||||
|
4. How to clean and compile all of the above:
|
||||||
|
|
||||||
|
make clean all
|
||||||
|
|
||||||
|
5. How to build for big endian CPU's
|
||||||
|
|
||||||
|
Make clean all ADDED_DEFINES+=_SYSTEM_IS_BIG_ENDIAN
|
||||||
|
To be able to use the test vectors with big endian CPU's the test programs
|
||||||
|
need to be compiled in a different way. Note that the 16 bit input and output
|
||||||
|
from the test programs will have the upper and lower bytes swapped with this setting.
|
||||||
|
|
||||||
|
6. How to use the comparison tool:
|
||||||
|
|
||||||
|
See 'How to use the test vectors.txt' in the test_vectors folder.
|
||||||
|
|
||||||
|
IV. History
|
||||||
|
|
||||||
|
Version 1.0.9 - Added 64-bit support. Added iOS LLVM compiler support. Lowered DTX mode bitrate. Bugfixes for ARM builds. Various other small fixes.
|
||||||
|
Version 1.0.8 - Improved noise shaping, various other improvements, and various bugfixes. Added a MIPS version
|
||||||
|
Version 1.0.7 - Updated with bugfixes for LBRR and pitch estimator. SignalCompare updated
|
||||||
|
Version 1.0.6 - Updated with bugfixes for ARM builds
|
||||||
|
Version 1.0.5 - Updated with bugfixes for ARM builds
|
||||||
|
Version 1.0.4 - Updated with various bugfixes and improvements, including some API changes
|
||||||
|
Added support for big endian platforms
|
||||||
|
Added resampler support for additional API sample rates
|
||||||
|
Version 1.0.3 - Updated with various bugfixes and improvements
|
||||||
|
Version 1.0.2 - Updated with various bugfixes and improvements
|
||||||
|
Version 1.0.1 - First beta source code release
|
||||||
|
|
||||||
|
V. Compatibility
|
||||||
|
|
||||||
|
This package has been tested on the following platforms:
|
||||||
|
|
||||||
|
Windows 7 Professional, 32-bit version, Intel Core i7 CPU
|
||||||
|
Windows 7 Professional, 64-bit version, Intel Core i7 CPU
|
||||||
|
Mac OS X Version 10.7.4, 64-bit version, Intel Core i7 CPU
|
||||||
|
Ubuntu Linux 10.04 LTS, 32-bit version, Intel Core i7 CPU
|
||||||
|
Ubuntu Linux 12.04 LTS, 64-bit version, Intel Core 2 Duo CPU
|
||||||
|
|
||||||
|
VI. Known Issues
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
VII. Additional Resources
|
||||||
|
|
||||||
|
For more information, visit the SILK SDK web site at:
|
||||||
|
|
||||||
|
<https://developer.skype.com/silk/>
|
279
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_A2NLSF.c
vendored
Executable file
279
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_A2NLSF.c
vendored
Executable file
@ -0,0 +1,279 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, (subject to the limitations in the disclaimer below)
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
- Neither the name of Skype Limited, nor the names of specific
|
||||||
|
contributors, may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||||
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
/* Conversion between prediction filter coefficients and NLSFs */
|
||||||
|
/* Requires the order to be an even number */
|
||||||
|
/* A piecewise linear approximation maps LSF <-> cos(LSF) */
|
||||||
|
/* Therefore the result is not accurate NLSFs, but the two */
|
||||||
|
/* function are accurate inverses of each other */
|
||||||
|
|
||||||
|
#include "SKP_Silk_SigProc_FIX.h"
|
||||||
|
|
||||||
|
/* Number of binary divisions */
|
||||||
|
#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
|
||||||
|
#define QPoly 16
|
||||||
|
#define MAX_ITERATIONS_A2NLSF_FIX 30
|
||||||
|
|
||||||
|
/* Flag for using 2x as many cosine sampling points, reduces the risk of missing a root */
|
||||||
|
#define OVERSAMPLE_COSINE_TABLE 0
|
||||||
|
|
||||||
|
/* Helper function for A2NLSF(..) */
|
||||||
|
/* Transforms polynomials from cos(n*f) to cos(f)^n */
|
||||||
|
SKP_INLINE void SKP_Silk_A2NLSF_trans_poly(
|
||||||
|
SKP_int32 *p, /* I/O Polynomial */
|
||||||
|
const SKP_int dd /* I Polynomial order (= filter order / 2 ) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int k, n;
|
||||||
|
|
||||||
|
for( k = 2; k <= dd; k++ ) {
|
||||||
|
for( n = dd; n > k; n-- ) {
|
||||||
|
p[ n - 2 ] -= p[ n ];
|
||||||
|
}
|
||||||
|
p[ k - 2 ] -= SKP_LSHIFT( p[ k ], 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Helper function for A2NLSF(..) */
|
||||||
|
/* Polynomial evaluation */
|
||||||
|
SKP_INLINE SKP_int32 SKP_Silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in QPoly */
|
||||||
|
SKP_int32 *p, /* I Polynomial, QPoly */
|
||||||
|
const SKP_int32 x, /* I Evaluation point, Q12 */
|
||||||
|
const SKP_int dd /* I Order */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int n;
|
||||||
|
SKP_int32 x_Q16, y32;
|
||||||
|
|
||||||
|
y32 = p[ dd ]; /* QPoly */
|
||||||
|
x_Q16 = SKP_LSHIFT( x, 4 );
|
||||||
|
for( n = dd - 1; n >= 0; n-- ) {
|
||||||
|
y32 = SKP_SMLAWW( p[ n ], y32, x_Q16 ); /* QPoly */
|
||||||
|
}
|
||||||
|
return y32;
|
||||||
|
}
|
||||||
|
|
||||||
|
SKP_INLINE void SKP_Silk_A2NLSF_init(
|
||||||
|
const SKP_int32 *a_Q16,
|
||||||
|
SKP_int32 *P,
|
||||||
|
SKP_int32 *Q,
|
||||||
|
const SKP_int dd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int k;
|
||||||
|
|
||||||
|
/* Convert filter coefs to even and odd polynomials */
|
||||||
|
P[dd] = SKP_LSHIFT( 1, QPoly );
|
||||||
|
Q[dd] = SKP_LSHIFT( 1, QPoly );
|
||||||
|
for( k = 0; k < dd; k++ ) {
|
||||||
|
#if( QPoly < 16 )
|
||||||
|
P[ k ] = SKP_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */
|
||||||
|
Q[ k ] = SKP_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */
|
||||||
|
#elif( QPoly == 16 )
|
||||||
|
P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; // QPoly
|
||||||
|
Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; // QPoly
|
||||||
|
#else
|
||||||
|
P[ k ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */
|
||||||
|
Q[ k ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Divide out zeros as we have that for even filter orders, */
|
||||||
|
/* z = 1 is always a root in Q, and */
|
||||||
|
/* z = -1 is always a root in P */
|
||||||
|
for( k = dd; k > 0; k-- ) {
|
||||||
|
P[ k - 1 ] -= P[ k ];
|
||||||
|
Q[ k - 1 ] += Q[ k ];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transform polynomials from cos(n*f) to cos(f)^n */
|
||||||
|
SKP_Silk_A2NLSF_trans_poly( P, dd );
|
||||||
|
SKP_Silk_A2NLSF_trans_poly( Q, dd );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
|
||||||
|
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
|
||||||
|
void SKP_Silk_A2NLSF(
|
||||||
|
SKP_int *NLSF, /* O Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d] */
|
||||||
|
SKP_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
|
||||||
|
const SKP_int d /* I Filter order (must be even) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int i, k, m, dd, root_ix, ffrac;
|
||||||
|
SKP_int32 xlo, xhi, xmid;
|
||||||
|
SKP_int32 ylo, yhi, ymid;
|
||||||
|
SKP_int32 nom, den;
|
||||||
|
SKP_int32 P[ SKP_Silk_MAX_ORDER_LPC / 2 + 1 ];
|
||||||
|
SKP_int32 Q[ SKP_Silk_MAX_ORDER_LPC / 2 + 1 ];
|
||||||
|
SKP_int32 *PQ[ 2 ];
|
||||||
|
SKP_int32 *p;
|
||||||
|
|
||||||
|
/* Store pointers to array */
|
||||||
|
PQ[ 0 ] = P;
|
||||||
|
PQ[ 1 ] = Q;
|
||||||
|
|
||||||
|
dd = SKP_RSHIFT( d, 1 );
|
||||||
|
|
||||||
|
SKP_Silk_A2NLSF_init( a_Q16, P, Q, dd );
|
||||||
|
|
||||||
|
/* Find roots, alternating between P and Q */
|
||||||
|
p = P; /* Pointer to polynomial */
|
||||||
|
|
||||||
|
xlo = SKP_Silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12
|
||||||
|
ylo = SKP_Silk_A2NLSF_eval_poly( p, xlo, dd );
|
||||||
|
|
||||||
|
if( ylo < 0 ) {
|
||||||
|
/* Set the first NLSF to zero and move on to the next */
|
||||||
|
NLSF[ 0 ] = 0;
|
||||||
|
p = Q; /* Pointer to polynomial */
|
||||||
|
ylo = SKP_Silk_A2NLSF_eval_poly( p, xlo, dd );
|
||||||
|
root_ix = 1; /* Index of current root */
|
||||||
|
} else {
|
||||||
|
root_ix = 0; /* Index of current root */
|
||||||
|
}
|
||||||
|
k = 1; /* Loop counter */
|
||||||
|
i = 0; /* Counter for bandwidth expansions applied */
|
||||||
|
while( 1 ) {
|
||||||
|
/* Evaluate polynomial */
|
||||||
|
#if OVERSAMPLE_COSINE_TABLE
|
||||||
|
xhi = SKP_Silk_LSFCosTab_FIX_Q12[ k >> 1 ] +
|
||||||
|
( ( SKP_Silk_LSFCosTab_FIX_Q12[ ( k + 1 ) >> 1 ] -
|
||||||
|
SKP_Silk_LSFCosTab_FIX_Q12[ k >> 1 ] ) >> 1 ); /* Q12 */
|
||||||
|
#else
|
||||||
|
xhi = SKP_Silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */
|
||||||
|
#endif
|
||||||
|
yhi = SKP_Silk_A2NLSF_eval_poly( p, xhi, dd );
|
||||||
|
|
||||||
|
/* Detect zero crossing */
|
||||||
|
if( ( ylo <= 0 && yhi >= 0 ) || ( ylo >= 0 && yhi <= 0 ) ) {
|
||||||
|
/* Binary division */
|
||||||
|
#if OVERSAMPLE_COSINE_TABLE
|
||||||
|
ffrac = -128;
|
||||||
|
#else
|
||||||
|
ffrac = -256;
|
||||||
|
#endif
|
||||||
|
for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {
|
||||||
|
/* Evaluate polynomial */
|
||||||
|
xmid = SKP_RSHIFT_ROUND( xlo + xhi, 1 );
|
||||||
|
ymid = SKP_Silk_A2NLSF_eval_poly( p, xmid, dd );
|
||||||
|
|
||||||
|
/* Detect zero crossing */
|
||||||
|
if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {
|
||||||
|
/* Reduce frequency */
|
||||||
|
xhi = xmid;
|
||||||
|
yhi = ymid;
|
||||||
|
} else {
|
||||||
|
/* Increase frequency */
|
||||||
|
xlo = xmid;
|
||||||
|
ylo = ymid;
|
||||||
|
#if OVERSAMPLE_COSINE_TABLE
|
||||||
|
ffrac = SKP_ADD_RSHIFT( ffrac, 64, m );
|
||||||
|
#else
|
||||||
|
ffrac = SKP_ADD_RSHIFT( ffrac, 128, m );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interpolate */
|
||||||
|
if( SKP_abs( ylo ) < 65536 ) {
|
||||||
|
/* Avoid dividing by zero */
|
||||||
|
den = ylo - yhi;
|
||||||
|
nom = SKP_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + SKP_RSHIFT( den, 1 );
|
||||||
|
if( den != 0 ) {
|
||||||
|
ffrac += SKP_DIV32( nom, den );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
|
||||||
|
ffrac += SKP_DIV32( ylo, SKP_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );
|
||||||
|
}
|
||||||
|
#if OVERSAMPLE_COSINE_TABLE
|
||||||
|
NLSF[ root_ix ] = (SKP_int)SKP_min_32( SKP_LSHIFT( (SKP_int32)k, 7 ) + ffrac, SKP_int16_MAX );
|
||||||
|
#else
|
||||||
|
NLSF[ root_ix ] = (SKP_int)SKP_min_32( SKP_LSHIFT( (SKP_int32)k, 8 ) + ffrac, SKP_int16_MAX );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SKP_assert( NLSF[ root_ix ] >= 0 );
|
||||||
|
SKP_assert( NLSF[ root_ix ] <= 32767 );
|
||||||
|
|
||||||
|
root_ix++; /* Next root */
|
||||||
|
if( root_ix >= d ) {
|
||||||
|
/* Found all roots */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Alternate pointer to polynomial */
|
||||||
|
p = PQ[ root_ix & 1 ];
|
||||||
|
|
||||||
|
/* Evaluate polynomial */
|
||||||
|
#if OVERSAMPLE_COSINE_TABLE
|
||||||
|
xlo = SKP_Silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] +
|
||||||
|
( ( SKP_Silk_LSFCosTab_FIX_Q12[ k >> 1 ] -
|
||||||
|
SKP_Silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] ) >> 1 ); // Q12
|
||||||
|
#else
|
||||||
|
xlo = SKP_Silk_LSFCosTab_FIX_Q12[ k - 1 ]; // Q12
|
||||||
|
#endif
|
||||||
|
ylo = SKP_LSHIFT( 1 - ( root_ix & 2 ), 12 );
|
||||||
|
} else {
|
||||||
|
/* Increment loop counter */
|
||||||
|
k++;
|
||||||
|
xlo = xhi;
|
||||||
|
ylo = yhi;
|
||||||
|
|
||||||
|
#if OVERSAMPLE_COSINE_TABLE
|
||||||
|
if( k > 2 * LSF_COS_TAB_SZ_FIX ) {
|
||||||
|
#else
|
||||||
|
if( k > LSF_COS_TAB_SZ_FIX ) {
|
||||||
|
#endif
|
||||||
|
i++;
|
||||||
|
if( i > MAX_ITERATIONS_A2NLSF_FIX ) {
|
||||||
|
/* Set NLSFs to white spectrum and exit */
|
||||||
|
NLSF[ 0 ] = SKP_DIV32_16( 1 << 15, d + 1 );
|
||||||
|
for( k = 1; k < d; k++ ) {
|
||||||
|
NLSF[ k ] = SKP_SMULBB( k + 1, NLSF[ 0 ] );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error: Apply progressively more bandwidth expansion and run again */
|
||||||
|
SKP_Silk_bwexpander_32( a_Q16, d, 65536 - SKP_SMULBB( 10 + i, i ) ); // 10_Q16 = 0.00015
|
||||||
|
|
||||||
|
SKP_Silk_A2NLSF_init( a_Q16, P, Q, dd );
|
||||||
|
p = P; /* Pointer to polynomial */
|
||||||
|
xlo = SKP_Silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12
|
||||||
|
ylo = SKP_Silk_A2NLSF_eval_poly( p, xlo, dd );
|
||||||
|
if( ylo < 0 ) {
|
||||||
|
/* Set the first NLSF to zero and move on to the next */
|
||||||
|
NLSF[ 0 ] = 0;
|
||||||
|
p = Q; /* Pointer to polynomial */
|
||||||
|
ylo = SKP_Silk_A2NLSF_eval_poly( p, xlo, dd );
|
||||||
|
root_ix = 1; /* Index of current root */
|
||||||
|
} else {
|
||||||
|
root_ix = 0; /* Index of current root */
|
||||||
|
}
|
||||||
|
k = 1; /* Reset loop counter */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
149
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_CNG.c
vendored
Executable file
149
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_CNG.c
vendored
Executable file
@ -0,0 +1,149 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, (subject to the limitations in the disclaimer below)
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
- Neither the name of Skype Limited, nor the names of specific
|
||||||
|
contributors, may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||||
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include "SKP_Silk_main.h"
|
||||||
|
|
||||||
|
/* Generates excitation for CNG LPC synthesis */
|
||||||
|
SKP_INLINE void SKP_Silk_CNG_exc(
|
||||||
|
SKP_int16 residual[], /* O CNG residual signal Q0 */
|
||||||
|
SKP_int32 exc_buf_Q10[], /* I Random samples buffer Q10 */
|
||||||
|
SKP_int32 Gain_Q16, /* I Gain to apply */
|
||||||
|
SKP_int length, /* I Length */
|
||||||
|
SKP_int32 *rand_seed /* I/O Seed to random index generator */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int32 seed;
|
||||||
|
SKP_int i, idx, exc_mask;
|
||||||
|
|
||||||
|
exc_mask = CNG_BUF_MASK_MAX;
|
||||||
|
while( exc_mask > length ) {
|
||||||
|
exc_mask = SKP_RSHIFT( exc_mask, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
seed = *rand_seed;
|
||||||
|
for( i = 0; i < length; i++ ) {
|
||||||
|
seed = SKP_RAND( seed );
|
||||||
|
idx = ( SKP_int )( SKP_RSHIFT( seed, 24 ) & exc_mask );
|
||||||
|
SKP_assert( idx >= 0 );
|
||||||
|
SKP_assert( idx <= CNG_BUF_MASK_MAX );
|
||||||
|
residual[ i ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SMULWW( exc_buf_Q10[ idx ], Gain_Q16 ), 10 ) );
|
||||||
|
}
|
||||||
|
*rand_seed = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SKP_Silk_CNG_Reset(
|
||||||
|
SKP_Silk_decoder_state *psDec /* I/O Decoder state */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int i, NLSF_step_Q15, NLSF_acc_Q15;
|
||||||
|
|
||||||
|
NLSF_step_Q15 = SKP_DIV32_16( SKP_int16_MAX, psDec->LPC_order + 1 );
|
||||||
|
NLSF_acc_Q15 = 0;
|
||||||
|
for( i = 0; i < psDec->LPC_order; i++ ) {
|
||||||
|
NLSF_acc_Q15 += NLSF_step_Q15;
|
||||||
|
psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15;
|
||||||
|
}
|
||||||
|
psDec->sCNG.CNG_smth_Gain_Q16 = 0;
|
||||||
|
psDec->sCNG.rand_seed = 3176576;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Updates CNG estimate, and applies the CNG when packet was lost */
|
||||||
|
void SKP_Silk_CNG(
|
||||||
|
SKP_Silk_decoder_state *psDec, /* I/O Decoder state */
|
||||||
|
SKP_Silk_decoder_control *psDecCtrl, /* I/O Decoder control */
|
||||||
|
SKP_int16 signal[], /* I/O Signal */
|
||||||
|
SKP_int length /* I Length of residual */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int i, subfr;
|
||||||
|
SKP_int32 tmp_32, Gain_Q26, max_Gain_Q16;
|
||||||
|
SKP_int16 LPC_buf[ MAX_LPC_ORDER ];
|
||||||
|
SKP_int16 CNG_sig[ MAX_FRAME_LENGTH ];
|
||||||
|
SKP_Silk_CNG_struct *psCNG;
|
||||||
|
psCNG = &psDec->sCNG;
|
||||||
|
|
||||||
|
if( psDec->fs_kHz != psCNG->fs_kHz ) {
|
||||||
|
/* Reset state */
|
||||||
|
SKP_Silk_CNG_Reset( psDec );
|
||||||
|
|
||||||
|
psCNG->fs_kHz = psDec->fs_kHz;
|
||||||
|
}
|
||||||
|
if( psDec->lossCnt == 0 && psDec->vadFlag == NO_VOICE_ACTIVITY ) {
|
||||||
|
/* Update CNG parameters */
|
||||||
|
|
||||||
|
/* Smoothing of LSF's */
|
||||||
|
for( i = 0; i < psDec->LPC_order; i++ ) {
|
||||||
|
psCNG->CNG_smth_NLSF_Q15[ i ] += SKP_SMULWB( psDec->prevNLSF_Q15[ i ] - psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 );
|
||||||
|
}
|
||||||
|
/* Find the subframe with the highest gain */
|
||||||
|
max_Gain_Q16 = 0;
|
||||||
|
subfr = 0;
|
||||||
|
for( i = 0; i < NB_SUBFR; i++ ) {
|
||||||
|
if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) {
|
||||||
|
max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
|
||||||
|
subfr = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Update CNG excitation buffer with excitation from this subframe */
|
||||||
|
SKP_memmove( &psCNG->CNG_exc_buf_Q10[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q10, ( NB_SUBFR - 1 ) * psDec->subfr_length * sizeof( SKP_int32 ) );
|
||||||
|
SKP_memcpy( psCNG->CNG_exc_buf_Q10, &psDec->exc_Q10[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( SKP_int32 ) );
|
||||||
|
|
||||||
|
/* Smooth gains */
|
||||||
|
for( i = 0; i < NB_SUBFR; i++ ) {
|
||||||
|
psCNG->CNG_smth_Gain_Q16 += SKP_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add CNG when packet is lost and / or when low speech activity */
|
||||||
|
if( psDec->lossCnt ) {//|| psDec->vadFlag == NO_VOICE_ACTIVITY ) {
|
||||||
|
|
||||||
|
/* Generate CNG excitation */
|
||||||
|
SKP_Silk_CNG_exc( CNG_sig, psCNG->CNG_exc_buf_Q10,
|
||||||
|
psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed );
|
||||||
|
|
||||||
|
/* Convert CNG NLSF to filter representation */
|
||||||
|
SKP_Silk_NLSF2A_stable( LPC_buf, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
|
||||||
|
|
||||||
|
Gain_Q26 = ( SKP_int32 )1 << 26; /* 1.0 */
|
||||||
|
|
||||||
|
/* Generate CNG signal, by synthesis filtering */
|
||||||
|
if( psDec->LPC_order == 16 ) {
|
||||||
|
SKP_Silk_LPC_synthesis_order16( CNG_sig, LPC_buf,
|
||||||
|
Gain_Q26, psCNG->CNG_synth_state, CNG_sig, length );
|
||||||
|
} else {
|
||||||
|
SKP_Silk_LPC_synthesis_filter( CNG_sig, LPC_buf,
|
||||||
|
Gain_Q26, psCNG->CNG_synth_state, CNG_sig, length, psDec->LPC_order );
|
||||||
|
}
|
||||||
|
/* Mix with signal */
|
||||||
|
for( i = 0; i < length; i++ ) {
|
||||||
|
tmp_32 = signal[ i ] + CNG_sig[ i ];
|
||||||
|
signal[ i ] = SKP_SAT16( tmp_32 );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SKP_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( SKP_int32 ) );
|
||||||
|
}
|
||||||
|
}
|
104
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_HP_variable_cutoff_FLP.c
vendored
Executable file
104
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_HP_variable_cutoff_FLP.c
vendored
Executable file
@ -0,0 +1,104 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, (subject to the limitations in the disclaimer below)
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
- Neither the name of Skype Limited, nor the names of specific
|
||||||
|
contributors, may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||||
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include "SKP_Silk_main_FLP.h"
|
||||||
|
#include "SKP_Silk_tuning_parameters.h"
|
||||||
|
|
||||||
|
#if HIGH_PASS_INPUT
|
||||||
|
|
||||||
|
/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
|
||||||
|
void SKP_Silk_HP_variable_cutoff_FLP(
|
||||||
|
SKP_Silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
|
||||||
|
SKP_Silk_encoder_control_FLP *psEncCtrl, /* I/O Encoder control FLP */
|
||||||
|
SKP_int16 *out, /* O High-pass filtered output signal */
|
||||||
|
const SKP_int16 *in /* I Input signal */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_float pitch_freq_Hz, pitch_freq_log, quality, delta_freq, smth_coef, Fc, r;
|
||||||
|
SKP_int32 B_Q28[ 3 ], A_Q28[ 2 ];
|
||||||
|
|
||||||
|
/*********************************************/
|
||||||
|
/* Estimate low end of pitch frequency range */
|
||||||
|
/*********************************************/
|
||||||
|
if( psEnc->sCmn.prev_sigtype == SIG_TYPE_VOICED ) {
|
||||||
|
|
||||||
|
/* Difference, in log domain */
|
||||||
|
pitch_freq_Hz = 1e3f * psEnc->sCmn.fs_kHz / psEnc->sCmn.prevLag;
|
||||||
|
pitch_freq_log = SKP_Silk_log2( pitch_freq_Hz );
|
||||||
|
|
||||||
|
/* Adjustment based on quality */
|
||||||
|
quality = psEncCtrl->input_quality_bands[ 0 ];
|
||||||
|
pitch_freq_log -= quality * quality * ( pitch_freq_log - SKP_Silk_log2( VARIABLE_HP_MIN_FREQ ) );
|
||||||
|
pitch_freq_log += 0.5f * ( 0.6f - quality );
|
||||||
|
|
||||||
|
delta_freq = pitch_freq_log - psEnc->variable_HP_smth1;
|
||||||
|
if( delta_freq < 0.0 ) {
|
||||||
|
/* Less smoothing for decreasing pitch frequency, to track something close to the minimum */
|
||||||
|
delta_freq *= 3.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Limit delta, to reduce impact of outliers */
|
||||||
|
delta_freq = SKP_LIMIT_float( delta_freq, -VARIABLE_HP_MAX_DELTA_FREQ, VARIABLE_HP_MAX_DELTA_FREQ );
|
||||||
|
|
||||||
|
/* Update smoother */
|
||||||
|
smth_coef = VARIABLE_HP_SMTH_COEF1 * psEnc->speech_activity;
|
||||||
|
psEnc->variable_HP_smth1 += smth_coef * delta_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Second smoother */
|
||||||
|
psEnc->variable_HP_smth2 += VARIABLE_HP_SMTH_COEF2 * ( psEnc->variable_HP_smth1 - psEnc->variable_HP_smth2 );
|
||||||
|
|
||||||
|
/* Convert from log scale to Hertz */
|
||||||
|
psEncCtrl->pitch_freq_low_Hz = ( SKP_float )pow( 2.0f, psEnc->variable_HP_smth2 );
|
||||||
|
|
||||||
|
/* Limit frequency range */
|
||||||
|
psEncCtrl->pitch_freq_low_Hz = SKP_LIMIT_float( psEncCtrl->pitch_freq_low_Hz, VARIABLE_HP_MIN_FREQ, VARIABLE_HP_MAX_FREQ );
|
||||||
|
|
||||||
|
/*******************************/
|
||||||
|
/* Compute filter coefficients */
|
||||||
|
/*******************************/
|
||||||
|
/* Compute cut-off frequency, in radians */
|
||||||
|
Fc = ( SKP_float )( 0.45f * 2.0f * 3.14159265359 * psEncCtrl->pitch_freq_low_Hz / ( 1e3f * psEnc->sCmn.fs_kHz ) );
|
||||||
|
|
||||||
|
/* 2nd order ARMA coefficients */
|
||||||
|
r = 1.0f - 0.92f * Fc;
|
||||||
|
|
||||||
|
/* b = r * [1; -2; 1]; */
|
||||||
|
/* a = [1; -2 * r * (1 - 0.5 * Fc^2); r^2]; */
|
||||||
|
B_Q28[ 0 ] = SKP_float2int( ( 1 << 28 ) * r );
|
||||||
|
B_Q28[ 1 ] = SKP_float2int( ( 1 << 28 ) * -2.0f * r );
|
||||||
|
B_Q28[ 2 ] = B_Q28[ 0 ];
|
||||||
|
A_Q28[ 0 ] = SKP_float2int( ( 1 << 28 ) * -2.0f * r * ( 1.0f - 0.5f * Fc * Fc ) );
|
||||||
|
A_Q28[ 1 ] = SKP_float2int( ( 1 << 28 ) * r * r );
|
||||||
|
|
||||||
|
/********************/
|
||||||
|
/* High-pass filter */
|
||||||
|
/********************/
|
||||||
|
SKP_Silk_biquad_alt( in, B_Q28, A_Q28, psEnc->sCmn.In_HP_State, out, psEnc->sCmn.frame_length );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HIGH_PASS_INPUT
|
278
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_Inlines.h
vendored
Executable file
278
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_Inlines.h
vendored
Executable file
@ -0,0 +1,278 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, (subject to the limitations in the disclaimer below)
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
- Neither the name of Skype Limited, nor the names of specific
|
||||||
|
contributors, may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||||
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
/*! \file SKP_Silk_Inlines.h
|
||||||
|
* \brief SigProcFix_Inlines.h defines inline signal processing functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SKP_SILK_FIX_INLINES_H_
|
||||||
|
#define _SKP_SILK_FIX_INLINES_H_
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* count leading zeros of SKP_int64 */
|
||||||
|
SKP_INLINE SKP_int32 SKP_Silk_CLZ64(SKP_int64 in)
|
||||||
|
{
|
||||||
|
SKP_int32 in_upper;
|
||||||
|
|
||||||
|
in_upper = (SKP_int32)SKP_RSHIFT64(in, 32);
|
||||||
|
if (in_upper == 0) {
|
||||||
|
/* Search in the lower 32 bits */
|
||||||
|
return 32 + SKP_Silk_CLZ32( (SKP_int32) in );
|
||||||
|
} else {
|
||||||
|
/* Search in the upper 32 bits */
|
||||||
|
return SKP_Silk_CLZ32( in_upper );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get number of leading zeros and fractional part (the bits right after the leading one */
|
||||||
|
SKP_INLINE void SKP_Silk_CLZ_FRAC(SKP_int32 in, /* I: input */
|
||||||
|
SKP_int32 *lz, /* O: number of leading zeros */
|
||||||
|
SKP_int32 *frac_Q7) /* O: the 7 bits right after the leading one */
|
||||||
|
{
|
||||||
|
SKP_int32 lzeros = SKP_Silk_CLZ32(in);
|
||||||
|
|
||||||
|
* lz = lzeros;
|
||||||
|
* frac_Q7 = SKP_ROR32(in, 24 - lzeros) & 0x7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Approximation of square root */
|
||||||
|
/* Accuracy: < +/- 10% for output values > 15 */
|
||||||
|
/* < +/- 2.5% for output values > 120 */
|
||||||
|
SKP_INLINE SKP_int32 SKP_Silk_SQRT_APPROX(SKP_int32 x)
|
||||||
|
{
|
||||||
|
SKP_int32 y, lz, frac_Q7;
|
||||||
|
|
||||||
|
if( x <= 0 ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SKP_Silk_CLZ_FRAC(x, &lz, &frac_Q7);
|
||||||
|
|
||||||
|
if( lz & 1 ) {
|
||||||
|
y = 32768;
|
||||||
|
} else {
|
||||||
|
y = 46214; /* 46214 = sqrt(2) * 32768 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get scaling right */
|
||||||
|
y >>= SKP_RSHIFT(lz, 1);
|
||||||
|
|
||||||
|
/* increment using fractional part of input */
|
||||||
|
y = SKP_SMLAWB(y, y, SKP_SMULBB(213, frac_Q7));
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns the number of left shifts before overflow for a 16 bit number (ITU definition with norm(0)=0) */
|
||||||
|
SKP_INLINE SKP_int32 SKP_Silk_norm16(SKP_int16 a) {
|
||||||
|
|
||||||
|
SKP_int32 a32;
|
||||||
|
|
||||||
|
/* if ((a == 0) || (a == SKP_int16_MIN)) return(0); */
|
||||||
|
if ((a << 1) == 0) return(0);
|
||||||
|
|
||||||
|
a32 = a;
|
||||||
|
/* if (a32 < 0) a32 = -a32 - 1; */
|
||||||
|
a32 ^= SKP_RSHIFT(a32, 31);
|
||||||
|
|
||||||
|
return SKP_Silk_CLZ32(a32) - 17;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns the number of left shifts before overflow for a 32 bit number (ITU definition with norm(0)=0) */
|
||||||
|
SKP_INLINE SKP_int32 SKP_Silk_norm32(SKP_int32 a) {
|
||||||
|
|
||||||
|
/* if ((a == 0) || (a == SKP_int32_MIN)) return(0); */
|
||||||
|
if ((a << 1) == 0) return(0);
|
||||||
|
|
||||||
|
/* if (a < 0) a = -a - 1; */
|
||||||
|
a ^= SKP_RSHIFT(a, 31);
|
||||||
|
|
||||||
|
return SKP_Silk_CLZ32(a) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Divide two int32 values and return result as int32 in a given Q-domain */
|
||||||
|
SKP_INLINE SKP_int32 SKP_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */
|
||||||
|
const SKP_int32 a32, /* I numerator (Q0) */
|
||||||
|
const SKP_int32 b32, /* I denominator (Q0) */
|
||||||
|
const SKP_int Qres /* I Q-domain of result (>= 0) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int a_headrm, b_headrm, lshift;
|
||||||
|
SKP_int32 b32_inv, a32_nrm, b32_nrm, result;
|
||||||
|
|
||||||
|
SKP_assert( b32 != 0 );
|
||||||
|
SKP_assert( Qres >= 0 );
|
||||||
|
|
||||||
|
/* Compute number of bits head room and normalize inputs */
|
||||||
|
a_headrm = SKP_Silk_CLZ32( SKP_abs(a32) ) - 1;
|
||||||
|
a32_nrm = SKP_LSHIFT(a32, a_headrm); /* Q: a_headrm */
|
||||||
|
b_headrm = SKP_Silk_CLZ32( SKP_abs(b32) ) - 1;
|
||||||
|
b32_nrm = SKP_LSHIFT(b32, b_headrm); /* Q: b_headrm */
|
||||||
|
|
||||||
|
/* Inverse of b32, with 14 bits of precision */
|
||||||
|
b32_inv = SKP_DIV32_16( SKP_int32_MAX >> 2, SKP_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
|
||||||
|
|
||||||
|
/* First approximation */
|
||||||
|
result = SKP_SMULWB(a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
|
||||||
|
|
||||||
|
/* Compute residual by subtracting product of denominator and first approximation */
|
||||||
|
a32_nrm -= SKP_LSHIFT_ovflw( SKP_SMMUL(b32_nrm, result), 3 ); /* Q: a_headrm */
|
||||||
|
|
||||||
|
/* Refinement */
|
||||||
|
result = SKP_SMLAWB(result, a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
|
||||||
|
|
||||||
|
/* Convert to Qres domain */
|
||||||
|
lshift = 29 + a_headrm - b_headrm - Qres;
|
||||||
|
if( lshift <= 0 ) {
|
||||||
|
return SKP_LSHIFT_SAT32(result, -lshift);
|
||||||
|
} else {
|
||||||
|
if( lshift < 32){
|
||||||
|
return SKP_RSHIFT(result, lshift);
|
||||||
|
} else {
|
||||||
|
/* Avoid undefined result */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invert int32 value and return result as int32 in a given Q-domain */
|
||||||
|
SKP_INLINE SKP_int32 SKP_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */
|
||||||
|
const SKP_int32 b32, /* I denominator (Q0) */
|
||||||
|
const SKP_int Qres /* I Q-domain of result (> 0) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int b_headrm, lshift;
|
||||||
|
SKP_int32 b32_inv, b32_nrm, err_Q32, result;
|
||||||
|
|
||||||
|
SKP_assert( b32 != 0 );
|
||||||
|
SKP_assert( b32 != SKP_int32_MIN ); /* SKP_int32_MIN is not handled by SKP_abs */
|
||||||
|
SKP_assert( Qres > 0 );
|
||||||
|
|
||||||
|
/* Compute number of bits head room and normalize input */
|
||||||
|
b_headrm = SKP_Silk_CLZ32( SKP_abs(b32) ) - 1;
|
||||||
|
b32_nrm = SKP_LSHIFT(b32, b_headrm); /* Q: b_headrm */
|
||||||
|
|
||||||
|
/* Inverse of b32, with 14 bits of precision */
|
||||||
|
b32_inv = SKP_DIV32_16( SKP_int32_MAX >> 2, SKP_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
|
||||||
|
|
||||||
|
/* First approximation */
|
||||||
|
result = SKP_LSHIFT(b32_inv, 16); /* Q: 61 - b_headrm */
|
||||||
|
|
||||||
|
/* Compute residual by subtracting product of denominator and first approximation from one */
|
||||||
|
err_Q32 = SKP_LSHIFT_ovflw( -SKP_SMULWB(b32_nrm, b32_inv), 3 ); /* Q32 */
|
||||||
|
|
||||||
|
/* Refinement */
|
||||||
|
result = SKP_SMLAWW(result, err_Q32, b32_inv); /* Q: 61 - b_headrm */
|
||||||
|
|
||||||
|
/* Convert to Qres domain */
|
||||||
|
lshift = 61 - b_headrm - Qres;
|
||||||
|
if( lshift <= 0 ) {
|
||||||
|
return SKP_LSHIFT_SAT32(result, -lshift);
|
||||||
|
} else {
|
||||||
|
if( lshift < 32){
|
||||||
|
return SKP_RSHIFT(result, lshift);
|
||||||
|
}else{
|
||||||
|
/* Avoid undefined result */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SKP_SIN_APPROX_CONST0 (1073735400)
|
||||||
|
#define SKP_SIN_APPROX_CONST1 (-82778932)
|
||||||
|
#define SKP_SIN_APPROX_CONST2 (1059577)
|
||||||
|
#define SKP_SIN_APPROX_CONST3 (-5013)
|
||||||
|
|
||||||
|
/* Sine approximation; an input of 65536 corresponds to 2 * pi */
|
||||||
|
/* Uses polynomial expansion of the input to the power 0, 2, 4 and 6 */
|
||||||
|
/* The relative error is below 1e-5 */
|
||||||
|
SKP_INLINE SKP_int32 SKP_Silk_SIN_APPROX_Q24( /* O returns approximately 2^24 * sin(x * 2 * pi / 65536) */
|
||||||
|
SKP_int32 x
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int y_Q30;
|
||||||
|
|
||||||
|
/* Keep only bottom 16 bits (the function repeats itself with period 65536) */
|
||||||
|
x &= 65535;
|
||||||
|
|
||||||
|
/* Split range in four quadrants */
|
||||||
|
if( x <= 32768 ) {
|
||||||
|
if( x < 16384 ) {
|
||||||
|
/* Return cos(pi/2 - x) */
|
||||||
|
x = 16384 - x;
|
||||||
|
} else {
|
||||||
|
/* Return cos(x - pi/2) */
|
||||||
|
x -= 16384;
|
||||||
|
}
|
||||||
|
if( x < 1100 ) {
|
||||||
|
/* Special case: high accuracy */
|
||||||
|
return SKP_SMLAWB( 1 << 24, SKP_MUL( x, x ), -5053 );
|
||||||
|
}
|
||||||
|
x = SKP_SMULWB( SKP_LSHIFT( x, 8 ), x ); /* contains x^2 in Q20 */
|
||||||
|
y_Q30 = SKP_SMLAWB( SKP_SIN_APPROX_CONST2, x, SKP_SIN_APPROX_CONST3 );
|
||||||
|
y_Q30 = SKP_SMLAWW( SKP_SIN_APPROX_CONST1, x, y_Q30 );
|
||||||
|
y_Q30 = SKP_SMLAWW( SKP_SIN_APPROX_CONST0 + 66, x, y_Q30 );
|
||||||
|
} else {
|
||||||
|
if( x < 49152 ) {
|
||||||
|
/* Return -cos(3*pi/2 - x) */
|
||||||
|
x = 49152 - x;
|
||||||
|
} else {
|
||||||
|
/* Return -cos(x - 3*pi/2) */
|
||||||
|
x -= 49152;
|
||||||
|
}
|
||||||
|
if( x < 1100 ) {
|
||||||
|
/* Special case: high accuracy */
|
||||||
|
return SKP_SMLAWB( -1 << 24, SKP_MUL( x, x ), 5053 );
|
||||||
|
}
|
||||||
|
x = SKP_SMULWB( SKP_LSHIFT( x, 8 ), x ); /* contains x^2 in Q20 */
|
||||||
|
y_Q30 = SKP_SMLAWB( -SKP_SIN_APPROX_CONST2, x, -SKP_SIN_APPROX_CONST3 );
|
||||||
|
y_Q30 = SKP_SMLAWW( -SKP_SIN_APPROX_CONST1, x, y_Q30 );
|
||||||
|
y_Q30 = SKP_SMLAWW( -SKP_SIN_APPROX_CONST0, x, y_Q30 );
|
||||||
|
}
|
||||||
|
return SKP_RSHIFT_ROUND( y_Q30, 6 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cosine approximation; an input of 65536 corresponds to 2 * pi */
|
||||||
|
/* The relative error is below 1e-5 */
|
||||||
|
SKP_INLINE SKP_int32 SKP_Silk_COS_APPROX_Q24( /* O returns approximately 2^24 * cos(x * 2 * pi / 65536) */
|
||||||
|
SKP_int32 x
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return SKP_Silk_SIN_APPROX_Q24( x + 16384 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /*_SKP_SILK_FIX_INLINES_H_*/
|
40
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_LBRR_reset.c
vendored
Executable file
40
external/SILK_SDK_SRC_FLP_v1.0.9/src/SKP_Silk_LBRR_reset.c
vendored
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, (subject to the limitations in the disclaimer below)
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
- Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
- Neither the name of Skype Limited, nor the names of specific
|
||||||
|
contributors, may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||||
|
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#include "SKP_Silk_main.h"
|
||||||
|
|
||||||
|
/* Resets LBRR buffer, used if packet size changes */
|
||||||
|
void SKP_Silk_LBRR_reset(
|
||||||
|
SKP_Silk_encoder_state *psEncC /* I/O state */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SKP_int i;
|
||||||
|
|
||||||
|
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
|
||||||
|
psEncC->LBRR_buffer[ i ].usage = SKP_SILK_NO_LBRR;
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user