change pretty much everything so it does what I want :^)

This commit is contained in:
BotoX 2021-05-01 18:38:37 +02:00
parent 73ba4f105e
commit 36a3225a2b
402 changed files with 106422 additions and 18837 deletions

20
.vscode/c_cpp_properties.json vendored Normal file
View 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

File diff suppressed because it is too large Load Diff

25447
demboyz/base/json.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}

View File

@ -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
View 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

View File

@ -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;
} }

View File

@ -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();
}
} }

View File

@ -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();
}
} }

View File

@ -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;
}; };
} }

View File

@ -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();
}
} }

View File

@ -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;
}
} }

View File

@ -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();
}
} }

View File

@ -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;
}
} }

View File

@ -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;
}
} }

View File

@ -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();
}
} }

View File

@ -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);
}

View File

@ -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);
} }

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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;
} }
} }
} }

View File

@ -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
View 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
View 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;
};

View File

@ -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";
} }

View File

@ -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];
}; };

View 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);
}
}

View 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;
};

View File

@ -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
View 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;
}

View File

@ -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);
} }

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
};

View File

@ -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);
}

View File

@ -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());
}

View 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;
};

View File

@ -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,46 +29,7 @@ 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:
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) if(m_celtDecoder)
{ {
@ -95,24 +46,24 @@ public:
return true; return true;
} }
void Destroy() void CeltVoiceDecoder::Destroy()
{ {
celt_decoder_destroy(m_celtDecoder); celt_decoder_destroy(m_celtDecoder);
m_celtDecoder = NULL; m_celtDecoder = NULL;
} }
void Reset() void CeltVoiceDecoder::Reset()
{ {
} }
int Decompress( int CeltVoiceDecoder::Decompress(
const uint8_t* compressedData, const uint8_t* compressedData,
int compressedBytes, uint32_t compressedBytes,
int16_t* uncompressedData, int16_t* uncompressedData,
int maxUncompressedSamples) uint32_t maxUncompressedSamples)
{ {
int curCompressedByte = 0; uint32_t curCompressedByte = 0;
int curDecompressedSample = 0; uint32_t curDecompressedSample = 0;
const uint32_t encodedframeSizeBytes = m_encodedFrameSizeBytes; const uint32_t encodedframeSizeBytes = m_encodedFrameSizeBytes;
const uint32_t frameSizeSamples = m_frameSizeSamples; const uint32_t frameSizeSamples = m_frameSizeSamples;
@ -127,110 +78,92 @@ public:
return curDecompressedSample; return curDecompressedSample;
} }
private: void CeltVoiceDecoder::DecodeFrame(const uint8_t* compressedData, int16_t* uncompressedData)
void DecodeFrame(const uint8_t* compressedData, int16_t* uncompressedData)
{ {
int error = celt_decode(m_celtDecoder, compressedData, m_encodedFrameSizeBytes, uncompressedData, m_frameSizeSamples); int error = celt_decode(m_celtDecoder, compressedData, m_encodedFrameSizeBytes, uncompressedData, m_frameSizeSamples);
assert(error >= CELT_OK); assert(error >= CELT_OK);
} }
private:
static const int sCeltChannels = 1;
private: bool SilkVoiceDecoder::DoInit(int32_t sampleRate)
CELTDecoder* m_celtDecoder = NULL;
uint32_t m_frameSizeSamples = 0;
uint32_t m_encodedFrameSizeBytes = 0;
};
#endif // USE_VAUDIO_CELT
class VoiceDataWriter: public IDemoWriter
{ {
public: m_Silk_DecoderControl.API_sampleRate = sampleRate;
VoiceDataWriter(const char* outputPath); if(m_Silk_DecoderState)
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 return false;
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): int decoderSize;
m_celtMode(nullptr), SKP_Silk_SDK_Get_Decoder_Size(&decoderSize);
m_playerVoiceStates(),
m_curTick(-1), 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();
state.second.lastVoiceDataTick = -1;
} }
#else
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->quality == NetMsg::SVC_VoiceInit::QUALITY_HAS_SAMPLE_RATE);
assert(voiceInit->sampleRate == sCeltConfigs[sQuality].sampleRate); 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;
} }

View 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;
};

View File

@ -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;
}; };

View File

@ -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
}
} }

View File

@ -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
}
} }

View File

@ -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)
{
}
} }

View File

@ -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 << '"';
}
} }

View File

@ -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;
}
} }

View File

@ -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 << '"';
}
} }

View File

@ -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;
}
} }

View File

@ -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
}; };

View File

@ -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);
}

View File

@ -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);
} }

View 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);
}
}

View File

@ -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);
}
} }

View File

@ -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

View File

@ -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;
}
} }

View File

@ -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");
}
} }

View File

@ -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";
}
} }

View File

@ -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);
}
} }

View File

@ -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);
}
} }

View File

@ -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);
}
} }

View File

@ -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);
}
} }

View File

@ -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); BitRead bitbuf2(data->data.get(), numBytes, numBits);
const size_t id = bitbuf2.ReadUBitLong(9); const size_t id = bitbuf2.ReadUBitLong(9);
//std::vector<char> stringMem; GameEvents::EventDataMap eventData = GameEvents::ParseEventData(bitbuf2, context.gameEventList->eventDescriptors[id]);
//GameEvents::ParseEventData(bitbuf2, context.gameEventList->eventDescriptors[id], stringMem);
GameEvents::PrintEventData(bitbuf2, context.gameEventList->eventDescriptors[id]); context.OnGameEvent(context.gameEventList->eventDescriptors[id].name, eventData);
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);
}
} }

View File

@ -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);
}
} }

View File

@ -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;
}
} }

View File

@ -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";
}
} }

View File

@ -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 << ")";
}
} }

View File

@ -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);
/*
int last_index = -1;
for (int i = 0; i < data->numUpdatedEntries; i++)
{
last_index += 1 + bitbuf.ReadUBitVar();
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;
}
}
*/
return !bitbuf.IsOverflowed(); return !bitbuf.IsOverflowed();
} }
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);
bitbuf.WriteLong(data->deltaFromTick);
}
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();
}
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);
}
} }

View File

@ -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;
}
} }

View File

@ -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 << '"';
}
} }

View File

@ -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);
}
} }

View File

@ -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);
}
} }

View File

@ -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;
}; };
} }

View File

@ -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");
}
} }

View File

@ -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");
}
} }

View File

@ -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;
}
} }

View File

@ -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);
}
} }

View File

@ -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);
}
} }

View File

@ -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";
}
} }

View File

@ -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);
}
} }

View File

@ -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);
}
} }

View File

@ -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);
}
} }

View File

@ -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);
}
}
} }

View 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
View 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
View 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

View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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

View 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

View 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

View 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
View 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/>

View 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 */
}
}
}
}

View 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 ) );
}
}

View 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

View 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_*/

View 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