mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Tier1: fully implement bitbuf classes
All routines are now fully implemented. This was delayed on purpose as some bit buffer functions have changed due to the use of 64bit integers for sizes, and also the coord types. The porting of this has to be done carefully; all reimplemented functions have been changed to feature 64bit integers (where necessary) for syze types, and all values in coordsize.h have been tweaked to reflect the changes in the R5 engine 1:1, allowing us to properly implement the coord bit buffer functions as well.
This commit is contained in:
parent
5b0b386ea7
commit
51ba4c9dff
@ -10,6 +10,7 @@
|
|||||||
// } while (false)
|
// } while (false)
|
||||||
//#else
|
//#else
|
||||||
# define Assert(condition, ...) assert(condition)
|
# define Assert(condition, ...) assert(condition)
|
||||||
|
# define AssertFatalMsg Assert
|
||||||
|
|
||||||
// TODO: this needs to go to dbg.h
|
// TODO: this needs to go to dbg.h
|
||||||
# define AssertMsg(condition, ...) assert(condition)
|
# define AssertMsg(condition, ...) assert(condition)
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#include <Psapi.h>
|
#include <Psapi.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <tchar.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
|
@ -60,10 +60,11 @@
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
// Tier0 includes.
|
// Tier0 includes.
|
||||||
|
#include "tier0/basetypes.h"
|
||||||
|
#include "tier0/wchartypes.h"
|
||||||
#include "tier0/memaddr.h"
|
#include "tier0/memaddr.h"
|
||||||
#include "tier0/utility.h"
|
#include "tier0/utility.h"
|
||||||
#include "tier0/module.h"
|
#include "tier0/module.h"
|
||||||
#include "tier0/basetypes.h"
|
|
||||||
#include "tier0/platform.h"
|
#include "tier0/platform.h"
|
||||||
#include "tier0/platwindow.h"
|
#include "tier0/platwindow.h"
|
||||||
#include "tier0/annotations.h"
|
#include "tier0/annotations.h"
|
||||||
|
98
src/public/coordsize.h
Normal file
98
src/public/coordsize.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||||
|
//
|
||||||
|
// Purpose:
|
||||||
|
//
|
||||||
|
// $NoKeywords: $
|
||||||
|
//
|
||||||
|
//===========================================================================//
|
||||||
|
|
||||||
|
#ifndef COORDSIZE_H
|
||||||
|
#define COORDSIZE_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "worldsize.h"
|
||||||
|
|
||||||
|
// OVERALL Coordinate Size Limits used in COMMON.C MSG_*BitCoord() Routines (and someday the HUD)
|
||||||
|
#define COORD_INTEGER_BITS 16
|
||||||
|
#define COORD_FRACTIONAL_BITS 5
|
||||||
|
#define COORD_DENOMINATOR (1<<(COORD_FRACTIONAL_BITS))
|
||||||
|
#define COORD_RESOLUTION (1.0f/(COORD_DENOMINATOR))
|
||||||
|
|
||||||
|
// Special threshold for networking multiplayer origins
|
||||||
|
#define COORD_INTEGER_BITS_MP 11
|
||||||
|
#define COORD_FRACTIONAL_BITS_MP_LOWPRECISION 3
|
||||||
|
#define COORD_DENOMINATOR_LOWPRECISION (1<<(COORD_FRACTIONAL_BITS_MP_LOWPRECISION))
|
||||||
|
#define COORD_RESOLUTION_LOWPRECISION (1.0f/(COORD_DENOMINATOR_LOWPRECISION))
|
||||||
|
|
||||||
|
#define NORMAL_FRACTIONAL_BITS 11
|
||||||
|
#define NORMAL_DENOMINATOR ((1<<(NORMAL_FRACTIONAL_BITS))-1)
|
||||||
|
#define NORMAL_RESOLUTION (1.0f/(NORMAL_DENOMINATOR))
|
||||||
|
|
||||||
|
// this is limited by the network fractional bits used for coords
|
||||||
|
// because net coords will be only be accurate to 5 bits fractional
|
||||||
|
// Standard collision test epsilon
|
||||||
|
// 1/32nd inch collision epsilon
|
||||||
|
#define DIST_EPSILON (0.03125)
|
||||||
|
|
||||||
|
// Verify that coordsize.h and worldsize.h are consistently defined
|
||||||
|
#if (MAX_COORD_INTEGER != (1<<COORD_INTEGER_BITS))
|
||||||
|
#error MAX_COORD_INTEGER does not match COORD_INTEGER_BITS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The following are Bit Packing Diagrams for client/server Coordinate BitField Messages
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// "Coordinates" = +/-16384.9375 (21 Bits Max)
|
||||||
|
//
|
||||||
|
// | IntegerFlagBit:1 | FractionFlagBit:1 | SignBit:1 | IntegerField:14 | FractionPart:4 | Total
|
||||||
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
// 0 0 - - - 2
|
||||||
|
// 0 1 x - xxxx 7
|
||||||
|
// 1 0 x xxxxxxxxxxxxx - 17
|
||||||
|
// 1 1 x xxxxxxxxxxxxx xxxx 21
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// "Vec3Coordinate" = Up to 3 Coordinates (66 Bits Max)
|
||||||
|
//
|
||||||
|
// | NonZeroX:1 | NonZeroY:1 | NonZeroZ:1 | 0..3 "Coordinates" | BitField Total
|
||||||
|
// -------------------------------------------------------------------------------
|
||||||
|
// 0 0 0 - 3
|
||||||
|
// 0 0 1 7..21 Bits 10..24
|
||||||
|
// 0 1 0 7..21 Bits 10..24
|
||||||
|
// 1 0 0 7..21 Bits 10..24
|
||||||
|
// 0 1 1 14..42 Bits 17..45
|
||||||
|
// 1 1 0 14..42 Bits 17..45
|
||||||
|
// 1 0 1 14..42 Bits 17..45
|
||||||
|
// 1 1 1 21..63 Bits 24..66
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The following are Bit Packing Diagrams for client/server Normal BitField Messages
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// "Normals" = +/-1.0 (12 Bits Total)
|
||||||
|
//
|
||||||
|
// The only gotcha here is that normalization occurs so that
|
||||||
|
// 011111111111 = +1.0 and 1111111111111 = -1.0
|
||||||
|
//
|
||||||
|
// | SignBit:1 | FractionPart:11 | Total
|
||||||
|
// --------------------------------------------------------------------------------------------------
|
||||||
|
// 1 xxxxxxxxxxx 12
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// "Vec3Normal" = Up to 3 Coordinates (27 Bits Max)
|
||||||
|
//
|
||||||
|
// | NonZeroX:1 | NonZeroY:1 | 0..2 "Coordinates" | Z Sign Bit | BitField Total
|
||||||
|
// -------------------------------------------------------------------------------
|
||||||
|
// 0 0 - x 3
|
||||||
|
// 0 1 12 Bits x 14
|
||||||
|
// 1 0 12 Bits x 14
|
||||||
|
// 1 1 24 Bits x 27
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // COORDSIZE_H
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#ifndef BITBUF_H
|
#ifndef BITBUF_H
|
||||||
#define BITBUF_H
|
#define BITBUF_H
|
||||||
|
#include "mathlib/swap.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// You can define a handler function that will be called in case of
|
// You can define a handler function that will be called in case of
|
||||||
@ -97,63 +98,142 @@ namespace bitbuf
|
|||||||
return(n >> 1) ^ -static_cast<int64>(n & 1);
|
return(n >> 1) ^ -static_cast<int64>(n & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int kMaxVarintBytes = 10;
|
|
||||||
const int kMaxVarint32Bytes = 5;
|
const int kMaxVarint32Bytes = 5;
|
||||||
|
const int kMaxVarint64Bytes = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
enum EBitCoordType
|
||||||
|
{
|
||||||
|
kCW_None,
|
||||||
|
kCW_LowPrecision,
|
||||||
|
kCW_Integral
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
class CBitBuffer
|
class CBitBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CBitBuffer(void);
|
CBitBuffer(void);
|
||||||
FORCEINLINE void SetDebugName(const char* pName) { m_pDebugName = pName; }
|
|
||||||
FORCEINLINE const char* GetDebugName() const { return m_pDebugName; }
|
FORCEINLINE void SetDebugName(const char* pName) { m_pDebugName = pName; }
|
||||||
FORCEINLINE bool IsOverflowed() const { return m_bOverflow; }
|
FORCEINLINE const char* GetDebugName() const { return m_pDebugName; }
|
||||||
FORCEINLINE void SetOverflowFlag() { m_bOverflow = true; }
|
FORCEINLINE bool IsOverflowed() const { return m_bOverflow; }
|
||||||
|
FORCEINLINE void SetOverflowFlag() { m_bOverflow = true; }
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
const char* m_pDebugName;
|
const char* m_pDebugName;
|
||||||
uint8_t m_bOverflow;
|
bool m_bOverflow;
|
||||||
int64_t m_nDataBits;
|
ssize_t m_nDataBits;
|
||||||
size_t m_nDataBytes;
|
size_t m_nDataBytes;
|
||||||
|
|
||||||
|
static const uint32 s_nMaskTable[33]; // 0 1 3 7 15 ..
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
class CBitRead : public CBitBuffer
|
class CBitRead : public CBitBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CBitRead(const void* pData, int nBytes, int nBits = -1);
|
CBitRead(const void* pData, size_t nBytes, ssize_t nBits = -1);
|
||||||
CBitRead(const char* pDebugName, const void* pData, int nBytes, int nBits = -1);
|
CBitRead(const char* pDebugName, const void* pData, size_t nBytes, ssize_t nBits = -1);
|
||||||
CBitRead(void) : CBitBuffer()
|
CBitRead(void) : CBitBuffer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartReading(const void* pData, size_t nBytes, int64 iStartBit = 0, int64 nBits = -1);
|
void StartReading(const void* pData, size_t nBytes, ssize_t iStartBit = 0, ssize_t nBits = -1);
|
||||||
|
|
||||||
bool Seek(int64 nPosition);
|
FORCEINLINE ssize_t Tell(void) const;
|
||||||
FORCEINLINE int64 Tell(void) const;
|
bool Seek(ssize_t nPosition);
|
||||||
|
|
||||||
void GrabNextDWord(bool bOverFlowImmediately = false);
|
FORCEINLINE bool SeekRelative(ssize_t nOffset)
|
||||||
void FetchNext();
|
{
|
||||||
|
return Seek(GetNumBitsRead() + nOffset);
|
||||||
|
}
|
||||||
|
|
||||||
FORCEINLINE int64 GetNumBitsRead(void) const { return Tell(); };
|
FORCEINLINE unsigned char const* GetBasePointer()
|
||||||
FORCEINLINE int64 GetNumBytesRead(void) const { return ((GetNumBitsRead() + 7) >> 3); }
|
{
|
||||||
|
return reinterpret_cast<unsigned char const*>(m_pData);
|
||||||
|
}
|
||||||
|
|
||||||
FORCEINLINE int64 GetNumBitsLeft() const { return m_nDataBits - GetNumBitsRead(); }
|
FORCEINLINE ssize_t GetNumBitsRead(void) const { return Tell(); };
|
||||||
FORCEINLINE int64 GetNumBytesLeft() const { return GetNumBitsLeft() >> 3; }
|
FORCEINLINE ssize_t GetNumBytesRead(void) const { return ((GetNumBitsRead() + 7) >> 3); }
|
||||||
|
|
||||||
int ReadSBitLong(int numbits);
|
FORCEINLINE ssize_t GetNumBitsLeft(void) const { return m_nDataBits - GetNumBitsRead(); }
|
||||||
uint32 ReadUBitLong(int numbits);
|
FORCEINLINE ssize_t GetNumBytesLeft(void) const { return GetNumBitsLeft() >> 3; }
|
||||||
|
|
||||||
FORCEINLINE int ReadChar() { return ReadSBitLong(sizeof(char) << 3); }
|
FORCEINLINE size_t TotalBytesAvailable(void) const { return m_nDataBytes; }
|
||||||
FORCEINLINE int ReadByte() { return ReadSBitLong(sizeof(unsigned char) << 3); }
|
|
||||||
FORCEINLINE int ReadShort() { return ReadUBitLong(sizeof(short) << 3); }
|
|
||||||
FORCEINLINE int ReadWord() { return ReadUBitLong(sizeof(unsigned short) << 3); }
|
|
||||||
FORCEINLINE int ReadLong() { return ReadUBitLong(sizeof(int32) << 3); }
|
|
||||||
|
|
||||||
int64 ReadLongLong();
|
FORCEINLINE void GrabNextDWord(bool bOverFlowImmediately = false);
|
||||||
float ReadFloat();
|
FORCEINLINE void FetchNext(void);
|
||||||
void ReadBits(void* pOutData, int nBits);
|
|
||||||
bool ReadBytes(void* pOut, int nBytes);
|
FORCEINLINE unsigned int ReadUBitLong(int numbits);
|
||||||
bool ReadString(char* pStr, int bufLen, bool bLine = false, int* pOutNumChars = nullptr);
|
FORCEINLINE int ReadSBitLong(int numbits);
|
||||||
|
FORCEINLINE unsigned int PeekUBitLong(int numbits);
|
||||||
|
|
||||||
|
FORCEINLINE unsigned int ReadUBitVar(void);
|
||||||
|
|
||||||
|
FORCEINLINE float ReadBitFloat(void)
|
||||||
|
{
|
||||||
|
uint32 nvalue = ReadUBitLong(32);
|
||||||
|
return *((float*)&nvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float ReadBitCoord();
|
||||||
|
float ReadBitCoordMP(EBitCoordType coordType);
|
||||||
|
float ReadBitCellCoord(int bits, EBitCoordType coordType);
|
||||||
|
float ReadBitNormal();
|
||||||
|
void ReadBitVec3Coord(Vector3D& fa);
|
||||||
|
void ReadBitVec3Normal(Vector3D& fa);
|
||||||
|
void ReadBitAngles(QAngle& fa);
|
||||||
|
float ReadBitAngle(int numbits);
|
||||||
|
|
||||||
|
// returns 0 or 1.
|
||||||
|
FORCEINLINE int ReadOneBit(void);
|
||||||
|
|
||||||
|
FORCEINLINE int ReadChar(void) { return ReadSBitLong(sizeof(char) << 3); }
|
||||||
|
FORCEINLINE int ReadByte(void) { return ReadSBitLong(sizeof(unsigned char) << 3); }
|
||||||
|
FORCEINLINE int ReadShort(void) { return ReadUBitLong(sizeof(short) << 3); }
|
||||||
|
FORCEINLINE int ReadWord(void) { return ReadUBitLong(sizeof(unsigned short) << 3); }
|
||||||
|
FORCEINLINE int ReadLong(void) { return ReadUBitLong(sizeof(int32) << 3); }
|
||||||
|
FORCEINLINE float ReadFloat(void)
|
||||||
|
{
|
||||||
|
uint32 nUval = ReadUBitLong(sizeof(int32) << 3);
|
||||||
|
return *((float*)&nUval);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads a signed 64-bit integer from the buffer
|
||||||
|
int64 ReadLongLong(void);
|
||||||
|
|
||||||
|
// reads a varint encoded integer
|
||||||
|
uint32 ReadVarInt32();
|
||||||
|
uint64 ReadVarInt64();
|
||||||
|
int32 ReadSignedVarInt32() { return bitbuf::ZigZagDecode32(ReadVarInt32()); }
|
||||||
|
int64 ReadSignedVarInt64() { return bitbuf::ZigZagDecode64(ReadVarInt64()); }
|
||||||
|
|
||||||
|
void ReadBits(void* pOutData, int nBits);
|
||||||
|
bool ReadBytes(void* pOut, int nBytes);
|
||||||
|
|
||||||
|
|
||||||
|
// Returns false if bufLen isn't large enough to hold the
|
||||||
|
// string in the buffer.
|
||||||
|
//
|
||||||
|
// Always reads to the end of the string (so you can read the
|
||||||
|
// next piece of data waiting).
|
||||||
|
//
|
||||||
|
// If bLine is true, it stops when it reaches a '\n' or a null-terminator.
|
||||||
|
//
|
||||||
|
// pStr is always null-terminated (unless bufLen is 0).
|
||||||
|
//
|
||||||
|
// pOutNumChars is set to the number of characters left in pStr when the routine is
|
||||||
|
// complete (this will never exceed bufLen-1).
|
||||||
|
//
|
||||||
|
bool ReadString(char* pStr, int bufLen, bool bLine = false, int* pOutNumChars = NULL);
|
||||||
|
bool ReadWString(wchar_t* pStr, int bufLen, bool bLine = false, int* pOutNumChars = NULL);
|
||||||
|
|
||||||
|
// Reads a string and allocates memory for it. If the string in the buffer
|
||||||
|
// is > 2048 bytes, then pOverflow is set to true (if it's not NULL).
|
||||||
|
char* ReadAndAllocateString(bool *pOverflow = NULL);
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
uint32 m_nInBufWord;
|
uint32 m_nInBufWord;
|
||||||
@ -163,6 +243,7 @@ public:
|
|||||||
const uint32* m_pData;
|
const uint32* m_pData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
class CBitWrite
|
class CBitWrite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -174,44 +255,88 @@ public:
|
|||||||
CBitWrite(const char* pDebugName, void* pData, int nBytes, int nMaxBits = -1);
|
CBitWrite(const char* pDebugName, void* pData, int nBytes, int nMaxBits = -1);
|
||||||
|
|
||||||
// Restart buffer writing.
|
// Restart buffer writing.
|
||||||
inline void Reset() { m_iCurBit = 0; m_bOverflow = false; }
|
inline void Reset() { m_iCurBit = 0; m_bOverflow = false; }
|
||||||
inline void SeekToBit(int bitPos) { m_iCurBit = bitPos; }
|
inline void SeekToBit(int bitPos) { m_iCurBit = bitPos; }
|
||||||
|
|
||||||
void StartWriting(void* pData, int nBytes, int iStartBit = 0, int nMaxBits = -1);
|
void StartWriting(void* pData, int nBytes, int iStartBit = 0, int nMaxBits = -1);
|
||||||
|
|
||||||
// Bit functions.
|
// Bit functions.
|
||||||
void WriteOneBit(int nValue);
|
void WriteOneBit(int nValue);
|
||||||
void WriteOneBitNoCheck(int nValue);
|
void WriteOneBitNoCheck(int nValue);
|
||||||
void WriteOneBitAt(int iBit, int nValue);
|
void WriteOneBitAt(int iBit, int nValue);
|
||||||
|
|
||||||
// Write signed or unsigned. Range is only checked in debug.
|
// Write signed or unsigned. Range is only checked in debug.
|
||||||
void WriteUBitLong(unsigned int curData, int numbits, bool bCheckRange = false);
|
void WriteUBitLong(unsigned int curData, int numbits, bool bCheckRange = false);
|
||||||
void WriteSBitLong(int data, int numbits);
|
void WriteSBitLong(int data, int numbits);
|
||||||
|
|
||||||
// Tell it whether or not the data is unsigned. If it's signed,
|
// Tell it whether or not the data is unsigned. If it's signed,
|
||||||
// cast to unsigned before passing in (it will cast back inside).
|
// cast to unsigned before passing in (it will cast back inside).
|
||||||
void WriteBitLong(unsigned int data, int numbits, bool bSigned);
|
void WriteBitLong(unsigned int data, int numbits, bool bSigned);
|
||||||
|
|
||||||
// Write a list of bits in.
|
// Write a list of bits in.
|
||||||
bool WriteBits(const void* pIn, int nBits);
|
bool WriteBits(const void* pIn, int nBits);
|
||||||
inline bool WriteBytes(const void* pIn, int nBytes) { return WriteBits(pIn, nBytes << 3); }
|
|
||||||
|
// copy the bits straight out of pIn. This seeks pIn forward by nBits,
|
||||||
|
// returns false if this buffer or the read buffer overflows
|
||||||
|
bool WriteBitsFromBuffer(class bf_read *pIn, int nBits);
|
||||||
|
|
||||||
|
// writes an unsigned integer with variable bit length
|
||||||
|
void WriteUBitVar(unsigned int data);
|
||||||
|
|
||||||
|
// writes a varint encoded integer
|
||||||
|
void WriteVarInt32(uint32 data);
|
||||||
|
void WriteVarInt64(uint64 data);
|
||||||
|
void WriteSignedVarInt32(int32 data);
|
||||||
|
void WriteSignedVarInt64(int64 data);
|
||||||
|
int ByteSizeVarInt32(uint32 data);
|
||||||
|
int ByteSizeVarInt64(uint64 data);
|
||||||
|
int ByteSizeSignedVarInt32(int32 data);
|
||||||
|
int ByteSizeSignedVarInt64(int64 data);
|
||||||
|
|
||||||
|
// writes an angle or vector encoded
|
||||||
|
void WriteBitAngle(float fAngle, int numbits);
|
||||||
|
void WriteBitCoord(const float f);
|
||||||
|
void WriteBitCoordMP(const float f, bool bIntegral, bool bLowPrecision);
|
||||||
|
void WriteBitCellCoord(const float f, int bits, EBitCoordType coordType);
|
||||||
|
void WriteBitFloat(float val);
|
||||||
|
void WriteBitVec3Coord(const Vector3D& fa);
|
||||||
|
void WriteBitNormal(float f);
|
||||||
|
void WriteBitVec3Normal(const Vector3D& fa);
|
||||||
|
void WriteBitAngles(const QAngle& fa);
|
||||||
|
|
||||||
|
// byte functions
|
||||||
|
void WriteChar(int val);
|
||||||
|
void WriteByte(int val);
|
||||||
|
void WriteShort(int val);
|
||||||
|
void WriteWord(int val);
|
||||||
|
void WriteLong(long val);
|
||||||
|
void WriteLongLong(int64 val);
|
||||||
|
void WriteFloat(float val);
|
||||||
|
bool WriteBytes(const void* pBuf, int nBytes);
|
||||||
|
|
||||||
|
// Returns false if it overflows the buffer.
|
||||||
|
bool WriteString(const char* pStr);
|
||||||
|
bool WriteWString(const wchar_t* pStr);
|
||||||
|
|
||||||
// How many bytes are filled in?
|
// How many bytes are filled in?
|
||||||
FORCEINLINE int GetNumBytesWritten() const { return BitByte(this->m_iCurBit); }
|
FORCEINLINE int GetNumBytesWritten() const { return BitByte(this->m_iCurBit); }
|
||||||
FORCEINLINE int GetNumBitsWritten() const { return this->m_iCurBit; }
|
FORCEINLINE int GetNumBitsWritten() const { return this->m_iCurBit; }
|
||||||
FORCEINLINE int GetMaxNumBits() const { return this->m_nDataBits; }
|
FORCEINLINE int GetMaxNumBits() const { return this->m_nDataBits; }
|
||||||
FORCEINLINE int GetNumBitsLeft() const { return this->m_nDataBits - m_iCurBit; }
|
FORCEINLINE int GetNumBitsLeft() const { return this->m_nDataBits - m_iCurBit; }
|
||||||
FORCEINLINE int GetNumBytesLeft() const { return this->GetNumBitsLeft() >> 3; }
|
FORCEINLINE int GetNumBytesLeft() const { return this->GetNumBitsLeft() >> 3; }
|
||||||
FORCEINLINE unsigned char* GetData() const { return this->m_pData; }
|
|
||||||
|
|
||||||
inline const char* GetDebugName() const { return this->m_pDebugName; }
|
FORCEINLINE unsigned char* GetData() { return this->m_pData; }
|
||||||
inline void SetDebugName(const char* pDebugName) { m_pDebugName = pDebugName; }
|
FORCEINLINE const unsigned char* GetData() const { return this->m_pData; }
|
||||||
|
|
||||||
|
FORCEINLINE const char* GetDebugName() const { return this->m_pDebugName; }
|
||||||
|
FORCEINLINE void SetDebugName(const char* pDebugName) { m_pDebugName = pDebugName; }
|
||||||
|
|
||||||
// Has the buffer overflowed?
|
// Has the buffer overflowed?
|
||||||
bool CheckForOverflow(int nBits);
|
bool CheckForOverflow(int nBits);
|
||||||
void SetOverflowFlag();
|
void SetOverflowFlag();
|
||||||
|
|
||||||
FORCEINLINE bool IsOverflowed() const { return this->m_bOverflow; }
|
FORCEINLINE bool IsOverflowed() const { return this->m_bOverflow; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The current buffer.
|
// The current buffer.
|
||||||
unsigned char* m_pData;
|
unsigned char* m_pData;
|
||||||
@ -233,7 +358,14 @@ private:
|
|||||||
class bf_read : public CBitRead
|
class bf_read : public CBitRead
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
bf_read(const void* pData, int nBytes, int nBits = -1)
|
||||||
|
: CBitRead(pData, nBytes, nBits) {}
|
||||||
|
|
||||||
|
bf_read(const char* pDebugName, void* pData, int nBytes, int nMaxBits = -1)
|
||||||
|
: CBitRead(pDebugName, pData, nMaxBits) {}
|
||||||
|
|
||||||
|
bf_read(void) : CBitRead()
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -242,22 +374,264 @@ public:
|
|||||||
class bf_write : public CBitWrite
|
class bf_write : public CBitWrite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
bf_write(void* pData, int nBytes, int nMaxBits = -1)
|
||||||
|
: CBitWrite(pData, nBytes, nMaxBits) {}
|
||||||
|
|
||||||
|
bf_write(const char* pDebugName, void* pData, int nBytes, int nMaxBits = -1)
|
||||||
|
: CBitWrite(pDebugName, pData, nBytes, nMaxBits) {}
|
||||||
|
|
||||||
|
bf_write(void) : CBitWrite()
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Routines for getting positions and grabbing next data in the read buffer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose:
|
FORCEINLINE ssize_t CBitRead::Tell(void) const
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
FORCEINLINE int64 CBitRead::Tell(void) const
|
|
||||||
{
|
{
|
||||||
if (!m_pData) // pesky null ptr bitbufs. these happen.
|
if (!m_pData) // pesky null ptr bitbufs. these happen.
|
||||||
|
{
|
||||||
|
Assert(m_pData);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int64 nCurOfs = int64(((intp(m_pDataIn) - intp(m_pData)) / 4) - 1);
|
ssize_t nCurOfs = int64(((intp(m_pDataIn) - intp(m_pData)) / 4) - 1);
|
||||||
nCurOfs *= 32;
|
nCurOfs *= 32;
|
||||||
nCurOfs += (32 - m_nBitsAvail);
|
nCurOfs += (32 - m_nBitsAvail);
|
||||||
int64 nAdjust = 8 * (m_nDataBytes & 3);
|
ssize_t nAdjust = 8 * (m_nDataBytes & 3);
|
||||||
|
|
||||||
return MIN(nCurOfs + nAdjust, m_nDataBits);
|
return MIN(nCurOfs + nAdjust, m_nDataBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE void CBitRead::GrabNextDWord(bool bOverFlowImmediately)
|
||||||
|
{
|
||||||
|
if (m_pDataIn == m_pBufferEnd)
|
||||||
|
{
|
||||||
|
m_nBitsAvail = 1;
|
||||||
|
m_nInBufWord = 0;
|
||||||
|
|
||||||
|
m_pDataIn++;
|
||||||
|
|
||||||
|
if (bOverFlowImmediately)
|
||||||
|
SetOverflowFlag();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_pDataIn > m_pBufferEnd)
|
||||||
|
{
|
||||||
|
SetOverflowFlag();
|
||||||
|
m_nInBufWord = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(reinterpret_cast<uintp>(m_pDataIn) + 3 < reinterpret_cast<uintp>(m_pBufferEnd));
|
||||||
|
m_nInBufWord = LittleDWord(*(m_pDataIn++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE void CBitRead::FetchNext()
|
||||||
|
{
|
||||||
|
m_nBitsAvail = 32;
|
||||||
|
GrabNextDWord(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
FORCEINLINE int CBitRead::ReadOneBit(void)
|
||||||
|
{
|
||||||
|
int nRet = m_nInBufWord & 1;
|
||||||
|
if (--m_nBitsAvail == 0)
|
||||||
|
{
|
||||||
|
FetchNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_nInBufWord >>= 1;
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Routines for reading encoded integers from the buffer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// reads an unsigned integer from the buffer
|
||||||
|
FORCEINLINE unsigned int CBitRead::ReadUBitLong(int numbits)
|
||||||
|
{
|
||||||
|
if (m_nBitsAvail >= numbits)
|
||||||
|
{
|
||||||
|
unsigned int nRet = m_nInBufWord & s_nMaskTable[numbits];
|
||||||
|
m_nBitsAvail -= numbits;
|
||||||
|
if (m_nBitsAvail)
|
||||||
|
{
|
||||||
|
m_nInBufWord >>= numbits;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FetchNext();
|
||||||
|
}
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32 nRet = m_nInBufWord;
|
||||||
|
numbits -= m_nBitsAvail;
|
||||||
|
GrabNextDWord(true);
|
||||||
|
|
||||||
|
if (IsOverflowed())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nRet |= ((m_nInBufWord & s_nMaskTable[numbits]) << m_nBitsAvail);
|
||||||
|
m_nBitsAvail = 32 - numbits;
|
||||||
|
m_nInBufWord >>= numbits;
|
||||||
|
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// reads a signed integer from the buffer
|
||||||
|
FORCEINLINE int CBitRead::ReadSBitLong(int numbits)
|
||||||
|
{
|
||||||
|
int nRet = ReadUBitLong(numbits);
|
||||||
|
return (nRet << (32 - numbits)) >> (32 - numbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// peeks an unsigned integer from the buffer
|
||||||
|
FORCEINLINE unsigned int CBitRead::PeekUBitLong(int numbits)
|
||||||
|
{
|
||||||
|
int nSaveBA = m_nBitsAvail;
|
||||||
|
uint32_t nSaveW = m_nInBufWord;
|
||||||
|
uint32 const* pSaveP = m_pDataIn;
|
||||||
|
unsigned int nRet = ReadUBitLong(numbits);
|
||||||
|
m_nBitsAvail = nSaveBA;
|
||||||
|
m_nInBufWord = nSaveW;
|
||||||
|
m_pDataIn = pSaveP;
|
||||||
|
return nRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4715) // disable warning on not all cases
|
||||||
|
// returning a value. throwing default:
|
||||||
|
// in measurably reduces perf in bit
|
||||||
|
// packing benchmark
|
||||||
|
#endif
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// reads an unsigned integer with variable bit length
|
||||||
|
FORCEINLINE unsigned int CBitRead::ReadUBitVar(void)
|
||||||
|
{
|
||||||
|
unsigned int ret = ReadUBitLong(6);
|
||||||
|
switch (ret & (16 | 32))
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
ret = (ret & 15) | (ReadUBitLong(4) << 4);
|
||||||
|
Assert(ret >= 16);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 32:
|
||||||
|
ret = (ret & 15) | (ReadUBitLong(8) << 4);
|
||||||
|
Assert(ret >= 256);
|
||||||
|
break;
|
||||||
|
case 48:
|
||||||
|
ret = (ret & 15) | (ReadUBitLong(32 - 4) << 4);
|
||||||
|
Assert(ret >= 4096);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Routines for bit level writing operations
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// writes a bit to the buffer without checking for overflow
|
||||||
|
FORCEINLINE void CBitWrite::WriteOneBitNoCheck(int nValue)
|
||||||
|
{
|
||||||
|
if (nValue)
|
||||||
|
m_pData[m_iCurBit >> 3] |= (1 << (m_iCurBit & 7));
|
||||||
|
else
|
||||||
|
m_pData[m_iCurBit >> 3] &= ~(1 << (m_iCurBit & 7));
|
||||||
|
|
||||||
|
++m_iCurBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// writes a bit to the buffer
|
||||||
|
FORCEINLINE void CBitWrite::WriteOneBit(int nValue)
|
||||||
|
{
|
||||||
|
if (!CheckForOverflow(1))
|
||||||
|
WriteOneBitNoCheck(nValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// writes a bit to the buffer at a specific bit index
|
||||||
|
FORCEINLINE void CBitWrite::WriteOneBitAt(int iBit, int nValue)
|
||||||
|
{
|
||||||
|
if (iBit + 1 > m_nDataBits)
|
||||||
|
{
|
||||||
|
SetOverflowFlag();
|
||||||
|
CallErrorHandler(BITBUFERROR_BUFFER_OVERRUN, GetDebugName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nValue)
|
||||||
|
m_pData[iBit >> 3] |= (1 << (iBit & 7));
|
||||||
|
else
|
||||||
|
m_pData[iBit >> 3] &= ~(1 << (iBit & 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Routines for writing integers into the buffer
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// writes an unsigned integer with variable bit length
|
||||||
|
FORCEINLINE void CBitWrite::WriteUBitVar(unsigned int data)
|
||||||
|
{
|
||||||
|
/* Reference:
|
||||||
|
if ( data < 0x10u )
|
||||||
|
WriteUBitLong( 0, 2 ), WriteUBitLong( data, 4 );
|
||||||
|
else if ( data < 0x100u )
|
||||||
|
WriteUBitLong( 1, 2 ), WriteUBitLong( data, 8 );
|
||||||
|
else if ( data < 0x1000u )
|
||||||
|
WriteUBitLong( 2, 2 ), WriteUBitLong( data, 12 );
|
||||||
|
else
|
||||||
|
WriteUBitLong( 3, 2 ), WriteUBitLong( data, 32 );
|
||||||
|
*/
|
||||||
|
// a < b ? -1 : 0 translates into a CMP, SBB instruction pair
|
||||||
|
// with no flow control. should also be branchless on consoles.
|
||||||
|
int n = (data < 0x10u ? -1 : 0) + (data < 0x100u ? -1 : 0) + (data < 0x1000u ? -1 : 0);
|
||||||
|
WriteUBitLong(data * 4 + n + 3, 6 + n * 4 + 12);
|
||||||
|
if (data >= 0x1000u)
|
||||||
|
{
|
||||||
|
WriteUBitLong(data >> 16, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// write raw IEEE float bits in little endian form
|
||||||
|
FORCEINLINE void CBitWrite::WriteBitFloat(float val)
|
||||||
|
{
|
||||||
|
long intVal;
|
||||||
|
|
||||||
|
Assert(sizeof(long) == sizeof(float));
|
||||||
|
Assert(sizeof(float) == 4);
|
||||||
|
|
||||||
|
intVal = *((long*)&val);
|
||||||
|
WriteUBitLong(intVal, 32);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // BITBUF_H
|
#endif // BITBUF_H
|
||||||
|
1121
src/tier1/bitbuf.cpp
1121
src/tier1/bitbuf.cpp
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user