From a0c29e7dd67abb15c74c85f07741784877edfdcd Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Mon, 2 Sep 2013 11:39:10 -0700 Subject: General: * Fixed a variety of server browser issues with mods based on this SDK * Fixed many warnings on various platforms * Added source code for fgdlib and raytrace * Updated many source files with the latest shared source from TF2. OSX: * Added support for Xcode 4.6 * Switched OSX builds to use Xcode instead of makefiles * Moved libs from src/lib/osx32 to src/lib/public/osx32 or src/lib/common/osx32 to match windows better. Linux: * Moved libs from src/lib/linux32 to src/lib/public/linux32 or src/lib/common/linux32 to match windows better. --- mp/src/tier1/bitbuf.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'mp/src/tier1/bitbuf.cpp') diff --git a/mp/src/tier1/bitbuf.cpp b/mp/src/tier1/bitbuf.cpp index 8294c93c..4c457aa4 100644 --- a/mp/src/tier1/bitbuf.cpp +++ b/mp/src/tier1/bitbuf.cpp @@ -877,7 +877,7 @@ unsigned int bf_read::CheckReadUBitLong(int numbits) void bf_read::ReadBits(void *pOutData, int nBits) { #if defined( BB_PROFILING ) - VPROF( "bf_write::ReadBits" ); + VPROF( "bf_read::ReadBits" ); #endif unsigned char *pOut = (unsigned char*)pOutData; @@ -1083,7 +1083,7 @@ unsigned int bf_read::ReadBitLong(int numbits, bool bSigned) float bf_read::ReadBitCoord (void) { #if defined( BB_PROFILING ) - VPROF( "bf_write::ReadBitCoord" ); + VPROF( "bf_read::ReadBitCoord" ); #endif int intval=0,fractval=0,signbit=0; float value = 0.0; @@ -1126,7 +1126,7 @@ float bf_read::ReadBitCoord (void) float bf_read::ReadBitCoordMP( bool bIntegral, bool bLowPrecision ) { #if defined( BB_PROFILING ) - VPROF( "bf_write::ReadBitCoordMP" ); + VPROF( "bf_read::ReadBitCoordMP" ); #endif // BitCoordMP float encoding: inbounds bit, integer bit, sign bit, optional int bits, float bits // BitCoordMP integer encoding: inbounds bit, integer bit, optional sign bit, optional int bits. @@ -1212,7 +1212,7 @@ float bf_read::ReadBitCoordMP( bool bIntegral, bool bLowPrecision ) unsigned int bf_read::ReadBitCoordBits (void) { #if defined( BB_PROFILING ) - VPROF( "bf_write::ReadBitCoordBits" ); + VPROF( "bf_read::ReadBitCoordBits" ); #endif unsigned int flags = ReadUBitLong(2); @@ -1231,7 +1231,7 @@ unsigned int bf_read::ReadBitCoordBits (void) unsigned int bf_read::ReadBitCoordMPBits( bool bIntegral, bool bLowPrecision ) { #if defined( BB_PROFILING ) - VPROF( "bf_write::ReadBitCoordMPBits" ); + VPROF( "bf_read::ReadBitCoordMPBits" ); #endif unsigned int flags = ReadUBitLong(2); -- cgit v1.2.3 From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/tier1/bitbuf.cpp | 2980 +++++++++++++++++++++++------------------------ 1 file changed, 1490 insertions(+), 1490 deletions(-) (limited to 'mp/src/tier1/bitbuf.cpp') diff --git a/mp/src/tier1/bitbuf.cpp b/mp/src/tier1/bitbuf.cpp index 4c457aa4..52a25e4d 100644 --- a/mp/src/tier1/bitbuf.cpp +++ b/mp/src/tier1/bitbuf.cpp @@ -1,1490 +1,1490 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "bitbuf.h" -#include "coordsize.h" -#include "mathlib/vector.h" -#include "mathlib/mathlib.h" -#include "tier1/strtools.h" -#include "bitvec.h" - -// FIXME: Can't use this until we get multithreaded allocations in tier0 working for tools -// This is used by VVIS and fails to link -// NOTE: This must be the last file included!!! -//#include "tier0/memdbgon.h" - -#ifdef _X360 -// mandatory ... wary of above comment and isolating, tier0 is built as MT though -#include "tier0/memdbgon.h" -#endif - -#if _WIN32 -#define FAST_BIT_SCAN 1 -#if _X360 -#define CountLeadingZeros(x) _CountLeadingZeros(x) -inline unsigned int CountTrailingZeros( unsigned int elem ) -{ - // this implements CountTrailingZeros() / BitScanForward() - unsigned int mask = elem-1; - unsigned int comp = ~elem; - elem = mask & comp; - return (32 - _CountLeadingZeros(elem)); -} -#else -#include -#pragma intrinsic(_BitScanReverse) -#pragma intrinsic(_BitScanForward) - -inline unsigned int CountLeadingZeros(unsigned int x) -{ - unsigned long firstBit; - if ( _BitScanReverse(&firstBit,x) ) - return 31 - firstBit; - return 32; -} -inline unsigned int CountTrailingZeros(unsigned int elem) -{ - unsigned long out; - if ( _BitScanForward(&out, elem) ) - return out; - return 32; -} - -#endif -#else -#define FAST_BIT_SCAN 0 -#endif - - -static BitBufErrorHandler g_BitBufErrorHandler = 0; - -inline int BitForBitnum(int bitnum) -{ - return GetBitForBitnum(bitnum); -} - -void InternalBitBufErrorHandler( BitBufErrorType errorType, const char *pDebugName ) -{ - if ( g_BitBufErrorHandler ) - g_BitBufErrorHandler( errorType, pDebugName ); -} - - -void SetBitBufErrorHandler( BitBufErrorHandler fn ) -{ - g_BitBufErrorHandler = fn; -} - - -// #define BB_PROFILING - -unsigned long g_LittleBits[32]; - -// Precalculated bit masks for WriteUBitLong. Using these tables instead of -// doing the calculations gives a 33% speedup in WriteUBitLong. -unsigned long g_BitWriteMasks[32][33]; - -// (1 << i) - 1 -unsigned long g_ExtraMasks[33]; - -class CBitWriteMasksInit -{ -public: - CBitWriteMasksInit() - { - for( unsigned int startbit=0; startbit < 32; startbit++ ) - { - for( unsigned int nBitsLeft=0; nBitsLeft < 33; nBitsLeft++ ) - { - unsigned int endbit = startbit + nBitsLeft; - g_BitWriteMasks[startbit][nBitsLeft] = BitForBitnum(startbit) - 1; - if(endbit < 32) - g_BitWriteMasks[startbit][nBitsLeft] |= ~(BitForBitnum(endbit) - 1); - } - } - - for ( unsigned int maskBit=0; maskBit < 32; maskBit++ ) - g_ExtraMasks[maskBit] = BitForBitnum(maskBit) - 1; - g_ExtraMasks[32] = ~0ul; - - for ( unsigned int littleBit=0; littleBit < 32; littleBit++ ) - StoreLittleDWord( &g_LittleBits[littleBit], 0, 1u<> ( 32 - numbits ) ); - int nSignExtension = ( nValue >> 31 ) & ~nPreserveBits; - nValue &= nPreserveBits; - nValue |= nSignExtension; - - AssertMsg2( nValue == data, "WriteSBitLong: 0x%08x does not fit in %d bits", data, numbits ); - - WriteUBitLong( nValue, numbits, false ); -} - -void bf_write::WriteVarInt32( uint32 data ) -{ - // Check if align and we have room, slow path if not - if ( (m_iCurBit & 7) == 0 && (m_iCurBit + bitbuf::kMaxVarint32Bytes * 8 ) <= m_nDataBits) - { - uint8 *target = ((uint8*)m_pData) + (m_iCurBit>>3); - - target[0] = static_cast(data | 0x80); - if ( data >= (1 << 7) ) - { - target[1] = static_cast((data >> 7) | 0x80); - if ( data >= (1 << 14) ) - { - target[2] = static_cast((data >> 14) | 0x80); - if ( data >= (1 << 21) ) - { - target[3] = static_cast((data >> 21) | 0x80); - if ( data >= (1 << 28) ) - { - target[4] = static_cast(data >> 28); - m_iCurBit += 5 * 8; - return; - } - else - { - target[3] &= 0x7F; - m_iCurBit += 4 * 8; - return; - } - } - else - { - target[2] &= 0x7F; - m_iCurBit += 3 * 8; - return; - } - } - else - { - target[1] &= 0x7F; - m_iCurBit += 2 * 8; - return; - } - } - else - { - target[0] &= 0x7F; - m_iCurBit += 1 * 8; - return; - } - } - else // Slow path - { - while ( data > 0x7F ) - { - WriteUBitLong( (data & 0x7F) | 0x80, 8 ); - data >>= 7; - } - WriteUBitLong( data & 0x7F, 8 ); - } -} - -void bf_write::WriteVarInt64( uint64 data ) -{ - // Check if align and we have room, slow path if not - if ( (m_iCurBit & 7) == 0 && (m_iCurBit + bitbuf::kMaxVarintBytes * 8 ) <= m_nDataBits ) - { - uint8 *target = ((uint8*)m_pData) + (m_iCurBit>>3); - - // Splitting into 32-bit pieces gives better performance on 32-bit - // processors. - uint32 part0 = static_cast(data ); - uint32 part1 = static_cast(data >> 28); - uint32 part2 = static_cast(data >> 56); - - int size; - - // Here we can't really optimize for small numbers, since the data is - // split into three parts. Cheking for numbers < 128, for instance, - // would require three comparisons, since you'd have to make sure part1 - // and part2 are zero. However, if the caller is using 64-bit integers, - // it is likely that they expect the numbers to often be very large, so - // we probably don't want to optimize for small numbers anyway. Thus, - // we end up with a hardcoded binary search tree... - if ( part2 == 0 ) - { - if ( part1 == 0 ) - { - if ( part0 < (1 << 14) ) - { - if ( part0 < (1 << 7) ) - { - size = 1; goto size1; - } - else - { - size = 2; goto size2; - } - } - else - { - if ( part0 < (1 << 21) ) - { - size = 3; goto size3; - } - else - { - size = 4; goto size4; - } - } - } - else - { - if ( part1 < (1 << 14) ) - { - if ( part1 < (1 << 7) ) - { - size = 5; goto size5; - } - else - { - size = 6; goto size6; - } - } - else - { - if ( part1 < (1 << 21) ) - { - size = 7; goto size7; - } - else - { - size = 8; goto size8; - } - } - } - } - else - { - if ( part2 < (1 << 7) ) - { - size = 9; goto size9; - } - else - { - size = 10; goto size10; - } - } - - AssertFatalMsg( false, "Can't get here." ); - - size10: target[9] = static_cast((part2 >> 7) | 0x80); - size9 : target[8] = static_cast((part2 ) | 0x80); - size8 : target[7] = static_cast((part1 >> 21) | 0x80); - size7 : target[6] = static_cast((part1 >> 14) | 0x80); - size6 : target[5] = static_cast((part1 >> 7) | 0x80); - size5 : target[4] = static_cast((part1 ) | 0x80); - size4 : target[3] = static_cast((part0 >> 21) | 0x80); - size3 : target[2] = static_cast((part0 >> 14) | 0x80); - size2 : target[1] = static_cast((part0 >> 7) | 0x80); - size1 : target[0] = static_cast((part0 ) | 0x80); - - target[size-1] &= 0x7F; - m_iCurBit += size * 8; - } - else // slow path - { - while ( data > 0x7F ) - { - WriteUBitLong( (data & 0x7F) | 0x80, 8 ); - data >>= 7; - } - WriteUBitLong( data & 0x7F, 8 ); - } -} - -void bf_write::WriteSignedVarInt32( int32 data ) -{ - WriteVarInt32( bitbuf::ZigZagEncode32( data ) ); -} - -void bf_write::WriteSignedVarInt64( int64 data ) -{ - WriteVarInt64( bitbuf::ZigZagEncode64( data ) ); -} - -int bf_write::ByteSizeVarInt32( uint32 data ) -{ - int size = 1; - while ( data > 0x7F ) { - size++; - data >>= 7; - } - return size; -} - -int bf_write::ByteSizeVarInt64( uint64 data ) -{ - int size = 1; - while ( data > 0x7F ) { - size++; - data >>= 7; - } - return size; -} - -int bf_write::ByteSizeSignedVarInt32( int32 data ) -{ - return ByteSizeVarInt32( bitbuf::ZigZagEncode32( data ) ); -} - -int bf_write::ByteSizeSignedVarInt64( int64 data ) -{ - return ByteSizeVarInt64( bitbuf::ZigZagEncode64( data ) ); -} - -void bf_write::WriteBitLong(unsigned int data, int numbits, bool bSigned) -{ - if(bSigned) - WriteSBitLong((int)data, numbits); - else - WriteUBitLong(data, numbits); -} - -bool bf_write::WriteBits(const void *pInData, int nBits) -{ -#if defined( BB_PROFILING ) - VPROF( "bf_write::WriteBits" ); -#endif - - unsigned char *pOut = (unsigned char*)pInData; - int nBitsLeft = nBits; - - // Bounds checking.. - if ( (m_iCurBit+nBits) > m_nDataBits ) - { - SetOverflowFlag(); - CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); - return false; - } - - // Align output to dword boundary - while (((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8) - { - - WriteUBitLong( *pOut, 8, false ); - ++pOut; - nBitsLeft -= 8; - } - - if ( IsPC() && (nBitsLeft >= 32) && (m_iCurBit & 7) == 0 ) - { - // current bit is byte aligned, do block copy - int numbytes = nBitsLeft >> 3; - int numbits = numbytes << 3; - - Q_memcpy( (char*)m_pData+(m_iCurBit>>3), pOut, numbytes ); - pOut += numbytes; - nBitsLeft -= numbits; - m_iCurBit += numbits; - } - - // X360TBD: Can't write dwords in WriteBits because they'll get swapped - if ( IsPC() && nBitsLeft >= 32 ) - { - unsigned long iBitsRight = (m_iCurBit & 31); - unsigned long iBitsLeft = 32 - iBitsRight; - unsigned long bitMaskLeft = g_BitWriteMasks[iBitsRight][32]; - unsigned long bitMaskRight = g_BitWriteMasks[0][iBitsRight]; - - unsigned long *pData = &m_pData[m_iCurBit>>5]; - - // Read dwords. - while(nBitsLeft >= 32) - { - unsigned long curData = *(unsigned long*)pOut; - pOut += sizeof(unsigned long); - - *pData &= bitMaskLeft; - *pData |= curData << iBitsRight; - - pData++; - - if ( iBitsLeft < 32 ) - { - curData >>= iBitsLeft; - *pData &= bitMaskRight; - *pData |= curData; - } - - nBitsLeft -= 32; - m_iCurBit += 32; - } - } - - - // write remaining bytes - while ( nBitsLeft >= 8 ) - { - WriteUBitLong( *pOut, 8, false ); - ++pOut; - nBitsLeft -= 8; - } - - // write remaining bits - if ( nBitsLeft ) - { - WriteUBitLong( *pOut, nBitsLeft, false ); - } - - return !IsOverflowed(); -} - - -bool bf_write::WriteBitsFromBuffer( bf_read *pIn, int nBits ) -{ - // This could be optimized a little by - while ( nBits > 32 ) - { - WriteUBitLong( pIn->ReadUBitLong( 32 ), 32 ); - nBits -= 32; - } - - WriteUBitLong( pIn->ReadUBitLong( nBits ), nBits ); - return !IsOverflowed() && !pIn->IsOverflowed(); -} - - -void bf_write::WriteBitAngle( float fAngle, int numbits ) -{ - int d; - unsigned int mask; - unsigned int shift; - - shift = BitForBitnum(numbits); - mask = shift - 1; - - d = (int)( (fAngle / 360.0) * shift ); - d &= mask; - - WriteUBitLong((unsigned int)d, numbits); -} - -void bf_write::WriteBitCoordMP( const float f, bool bIntegral, bool bLowPrecision ) -{ -#if defined( BB_PROFILING ) - VPROF( "bf_write::WriteBitCoordMP" ); -#endif - int signbit = (f <= -( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION )); - int intval = (int)abs(f); - int fractval = bLowPrecision ? - ( abs((int)(f*COORD_DENOMINATOR_LOWPRECISION)) & (COORD_DENOMINATOR_LOWPRECISION-1) ) : - ( abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1) ); - - bool bInBounds = intval < (1 << COORD_INTEGER_BITS_MP ); - - unsigned int bits, numbits; - - if ( bIntegral ) - { - // Integer encoding: in-bounds bit, nonzero bit, optional sign bit + integer value bits - if ( intval ) - { - // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] - --intval; - bits = intval * 8 + signbit * 4 + 2 + bInBounds; - numbits = 3 + (bInBounds ? COORD_INTEGER_BITS_MP : COORD_INTEGER_BITS); - } - else - { - bits = bInBounds; - numbits = 2; - } - } - else - { - // Float encoding: in-bounds bit, integer bit, sign bit, fraction value bits, optional integer value bits - if ( intval ) - { - // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] - --intval; - bits = intval * 8 + signbit * 4 + 2 + bInBounds; - bits += bInBounds ? (fractval << (3+COORD_INTEGER_BITS_MP)) : (fractval << (3+COORD_INTEGER_BITS)); - numbits = 3 + (bInBounds ? COORD_INTEGER_BITS_MP : COORD_INTEGER_BITS) - + (bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS); - } - else - { - bits = fractval * 8 + signbit * 4 + 0 + bInBounds; - numbits = 3 + (bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS); - } - } - - WriteUBitLong( bits, numbits ); -} - -void bf_write::WriteBitCoord (const float f) -{ -#if defined( BB_PROFILING ) - VPROF( "bf_write::WriteBitCoord" ); -#endif - int signbit = (f <= -COORD_RESOLUTION); - int intval = (int)abs(f); - int fractval = abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1); - - - // Send the bit flags that indicate whether we have an integer part and/or a fraction part. - WriteOneBit( intval ); - WriteOneBit( fractval ); - - if ( intval || fractval ) - { - // Send the sign bit - WriteOneBit( signbit ); - - // Send the integer if we have one. - if ( intval ) - { - // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] - intval--; - WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS ); - } - - // Send the fraction if we have one - if ( fractval ) - { - WriteUBitLong( (unsigned int)fractval, COORD_FRACTIONAL_BITS ); - } - } -} - -void bf_write::WriteBitVec3Coord( const Vector& fa ) -{ - int xflag, yflag, zflag; - - xflag = (fa[0] >= COORD_RESOLUTION) || (fa[0] <= -COORD_RESOLUTION); - yflag = (fa[1] >= COORD_RESOLUTION) || (fa[1] <= -COORD_RESOLUTION); - zflag = (fa[2] >= COORD_RESOLUTION) || (fa[2] <= -COORD_RESOLUTION); - - WriteOneBit( xflag ); - WriteOneBit( yflag ); - WriteOneBit( zflag ); - - if ( xflag ) - WriteBitCoord( fa[0] ); - if ( yflag ) - WriteBitCoord( fa[1] ); - if ( zflag ) - WriteBitCoord( fa[2] ); -} - -void bf_write::WriteBitNormal( float f ) -{ - int signbit = (f <= -NORMAL_RESOLUTION); - - // NOTE: Since +/-1 are valid values for a normal, I'm going to encode that as all ones - unsigned int fractval = abs( (int)(f*NORMAL_DENOMINATOR) ); - - // clamp.. - if (fractval > NORMAL_DENOMINATOR) - fractval = NORMAL_DENOMINATOR; - - // Send the sign bit - WriteOneBit( signbit ); - - // Send the fractional component - WriteUBitLong( fractval, NORMAL_FRACTIONAL_BITS ); -} - -void bf_write::WriteBitVec3Normal( const Vector& fa ) -{ - int xflag, yflag; - - xflag = (fa[0] >= NORMAL_RESOLUTION) || (fa[0] <= -NORMAL_RESOLUTION); - yflag = (fa[1] >= NORMAL_RESOLUTION) || (fa[1] <= -NORMAL_RESOLUTION); - - WriteOneBit( xflag ); - WriteOneBit( yflag ); - - if ( xflag ) - WriteBitNormal( fa[0] ); - if ( yflag ) - WriteBitNormal( fa[1] ); - - // Write z sign bit - int signbit = (fa[2] <= -NORMAL_RESOLUTION); - WriteOneBit( signbit ); -} - -void bf_write::WriteBitAngles( const QAngle& fa ) -{ - // FIXME: - Vector tmp( fa.x, fa.y, fa.z ); - WriteBitVec3Coord( tmp ); -} - -void bf_write::WriteChar(int val) -{ - WriteSBitLong(val, sizeof(char) << 3); -} - -void bf_write::WriteByte(int val) -{ - WriteUBitLong(val, sizeof(unsigned char) << 3); -} - -void bf_write::WriteShort(int val) -{ - WriteSBitLong(val, sizeof(short) << 3); -} - -void bf_write::WriteWord(int val) -{ - WriteUBitLong(val, sizeof(unsigned short) << 3); -} - -void bf_write::WriteLong(long val) -{ - WriteSBitLong(val, sizeof(long) << 3); -} - -void bf_write::WriteLongLong(int64 val) -{ - uint *pLongs = (uint*)&val; - - // Insert the two DWORDS according to network endian - const short endianIndex = 0x0100; - byte *idx = (byte*)&endianIndex; - WriteUBitLong(pLongs[*idx++], sizeof(long) << 3); - WriteUBitLong(pLongs[*idx], sizeof(long) << 3); -} - -void bf_write::WriteFloat(float val) -{ - // Pre-swap the float, since WriteBits writes raw data - LittleFloat( &val, &val ); - - WriteBits(&val, sizeof(val) << 3); -} - -bool bf_write::WriteBytes( const void *pBuf, int nBytes ) -{ - return WriteBits(pBuf, nBytes << 3); -} - -bool bf_write::WriteString(const char *pStr) -{ - if(pStr) - { - do - { - WriteChar( *pStr ); - ++pStr; - } while( *(pStr-1) != 0 ); - } - else - { - WriteChar( 0 ); - } - - return !IsOverflowed(); -} - -// ---------------------------------------------------------------------------------------- // -// bf_read -// ---------------------------------------------------------------------------------------- // - -bf_read::bf_read() -{ - m_pData = NULL; - m_nDataBytes = 0; - m_nDataBits = -1; // set to -1 so we overflow on any operation - m_iCurBit = 0; - m_bOverflow = false; - m_bAssertOnOverflow = true; - m_pDebugName = NULL; -} - -bf_read::bf_read( const void *pData, int nBytes, int nBits ) -{ - m_bAssertOnOverflow = true; - StartReading( pData, nBytes, 0, nBits ); -} - -bf_read::bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits ) -{ - m_bAssertOnOverflow = true; - m_pDebugName = pDebugName; - StartReading( pData, nBytes, 0, nBits ); -} - -void bf_read::StartReading( const void *pData, int nBytes, int iStartBit, int nBits ) -{ - // Make sure we're dword aligned. - Assert(((size_t)pData & 3) == 0); - - m_pData = (unsigned char*)pData; - m_nDataBytes = nBytes; - - if ( nBits == -1 ) - { - m_nDataBits = m_nDataBytes << 3; - } - else - { - Assert( nBits <= nBytes*8 ); - m_nDataBits = nBits; - } - - m_iCurBit = iStartBit; - m_bOverflow = false; -} - -void bf_read::Reset() -{ - m_iCurBit = 0; - m_bOverflow = false; -} - -void bf_read::SetAssertOnOverflow( bool bAssert ) -{ - m_bAssertOnOverflow = bAssert; -} - -void bf_read::SetDebugName( const char *pName ) -{ - m_pDebugName = pName; -} - -void bf_read::SetOverflowFlag() -{ - if ( m_bAssertOnOverflow ) - { - Assert( false ); - } - m_bOverflow = true; -} - -unsigned int bf_read::CheckReadUBitLong(int numbits) -{ - // Ok, just read bits out. - int i, nBitValue; - unsigned int r = 0; - - for(i=0; i < numbits; i++) - { - nBitValue = ReadOneBitNoCheck(); - r |= nBitValue << i; - } - m_iCurBit -= numbits; - - return r; -} - -void bf_read::ReadBits(void *pOutData, int nBits) -{ -#if defined( BB_PROFILING ) - VPROF( "bf_read::ReadBits" ); -#endif - - unsigned char *pOut = (unsigned char*)pOutData; - int nBitsLeft = nBits; - - - // align output to dword boundary - while( ((size_t)pOut & 3) != 0 && nBitsLeft >= 8 ) - { - *pOut = (unsigned char)ReadUBitLong(8); - ++pOut; - nBitsLeft -= 8; - } - - // X360TBD: Can't read dwords in ReadBits because they'll get swapped - if ( IsPC() ) - { - // read dwords - while ( nBitsLeft >= 32 ) - { - *((unsigned long*)pOut) = ReadUBitLong(32); - pOut += sizeof(unsigned long); - nBitsLeft -= 32; - } - } - - // read remaining bytes - while ( nBitsLeft >= 8 ) - { - *pOut = ReadUBitLong(8); - ++pOut; - nBitsLeft -= 8; - } - - // read remaining bits - if ( nBitsLeft ) - { - *pOut = ReadUBitLong(nBitsLeft); - } - -} - -int bf_read::ReadBitsClamped_ptr(void *pOutData, size_t outSizeBytes, size_t nBits) -{ - size_t outSizeBits = outSizeBytes * 8; - size_t readSizeBits = nBits; - int skippedBits = 0; - if ( readSizeBits > outSizeBits ) - { - // Should we print a message when we clamp the data being read? Only - // in debug builds I think. - AssertMsg( 0, "Oversized network packet received, and clamped." ); - readSizeBits = outSizeBits; - skippedBits = (int)( nBits - outSizeBits ); - // What should we do in this case, which should only happen if nBits - // is negative for some reason? - //if ( skippedBits < 0 ) - // return 0; - } - - ReadBits( pOutData, readSizeBits ); - SeekRelative( skippedBits ); - - // Return the number of bits actually read. - return (int)readSizeBits; -} - -float bf_read::ReadBitAngle( int numbits ) -{ - float fReturn; - int i; - float shift; - - shift = (float)( BitForBitnum(numbits) ); - - i = ReadUBitLong( numbits ); - fReturn = (float)i * (360.0 / shift); - - return fReturn; -} - -unsigned int bf_read::PeekUBitLong( int numbits ) -{ - unsigned int r; - int i, nBitValue; -#ifdef BIT_VERBOSE - int nShifts = numbits; -#endif - - bf_read savebf; - - savebf = *this; // Save current state info - - r = 0; - for(i=0; i < numbits; i++) - { - nBitValue = ReadOneBit(); - - // Append to current stream - if ( nBitValue ) - { - r |= BitForBitnum(i); - } - } - - *this = savebf; - -#ifdef BIT_VERBOSE - Con_Printf( "PeekBitLong: %i %i\n", nShifts, (unsigned int)r ); -#endif - - return r; -} - -unsigned int bf_read::ReadUBitLongNoInline( int numbits ) -{ - return ReadUBitLong( numbits ); -} - -unsigned int bf_read::ReadUBitVarInternal( int encodingType ) -{ - m_iCurBit -= 4; - // int bits = { 4, 8, 12, 32 }[ encodingType ]; - int bits = 4 + encodingType*4 + (((2 - encodingType) >> 31) & 16); - return ReadUBitLong( bits ); -} - -// Append numbits least significant bits from data to the current bit stream -int bf_read::ReadSBitLong( int numbits ) -{ - unsigned int r = ReadUBitLong(numbits); - unsigned int s = 1 << (numbits-1); - if (r >= s) - { - // sign-extend by removing sign bit and then subtracting sign bit again - r = r - s - s; - } - return r; -} - -uint32 bf_read::ReadVarInt32() -{ - uint32 result = 0; - int count = 0; - uint32 b; - - do - { - if ( count == bitbuf::kMaxVarint32Bytes ) - { - return result; - } - b = ReadUBitLong( 8 ); - result |= (b & 0x7F) << (7 * count); - ++count; - } while (b & 0x80); - - return result; -} - -uint64 bf_read::ReadVarInt64() -{ - uint64 result = 0; - int count = 0; - uint64 b; - - do - { - if ( count == bitbuf::kMaxVarintBytes ) - { - return result; - } - b = ReadUBitLong( 8 ); - result |= static_cast(b & 0x7F) << (7 * count); - ++count; - } while (b & 0x80); - - return result; -} - -int32 bf_read::ReadSignedVarInt32() -{ - uint32 value = ReadVarInt32(); - return bitbuf::ZigZagDecode32( value ); -} - -int64 bf_read::ReadSignedVarInt64() -{ - uint32 value = ReadVarInt64(); - return bitbuf::ZigZagDecode64( value ); -} - -unsigned int bf_read::ReadBitLong(int numbits, bool bSigned) -{ - if(bSigned) - return (unsigned int)ReadSBitLong(numbits); - else - return ReadUBitLong(numbits); -} - - -// Basic Coordinate Routines (these contain bit-field size AND fixed point scaling constants) -float bf_read::ReadBitCoord (void) -{ -#if defined( BB_PROFILING ) - VPROF( "bf_read::ReadBitCoord" ); -#endif - int intval=0,fractval=0,signbit=0; - float value = 0.0; - - - // Read the required integer and fraction flags - intval = ReadOneBit(); - fractval = ReadOneBit(); - - // If we got either parse them, otherwise it's a zero. - if ( intval || fractval ) - { - // Read the sign bit - signbit = ReadOneBit(); - - // If there's an integer, read it in - if ( intval ) - { - // Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE] - intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1; - } - - // If there's a fraction, read it in - if ( fractval ) - { - fractval = ReadUBitLong( COORD_FRACTIONAL_BITS ); - } - - // Calculate the correct floating point value - value = intval + ((float)fractval * COORD_RESOLUTION); - - // Fixup the sign if negative. - if ( signbit ) - value = -value; - } - - return value; -} - -float bf_read::ReadBitCoordMP( bool bIntegral, bool bLowPrecision ) -{ -#if defined( BB_PROFILING ) - VPROF( "bf_read::ReadBitCoordMP" ); -#endif - // BitCoordMP float encoding: inbounds bit, integer bit, sign bit, optional int bits, float bits - // BitCoordMP integer encoding: inbounds bit, integer bit, optional sign bit, optional int bits. - // int bits are always encoded as (value - 1) since zero is handled by the integer bit - - // With integer-only encoding, the presence of the third bit depends on the second - int flags = ReadUBitLong(3 - bIntegral); - enum { INBOUNDS=1, INTVAL=2, SIGN=4 }; - - if ( bIntegral ) - { - if ( flags & INTVAL ) - { - // Read the third bit and the integer portion together at once - unsigned int bits = ReadUBitLong( (flags & INBOUNDS) ? COORD_INTEGER_BITS_MP+1 : COORD_INTEGER_BITS+1 ); - // Remap from [0,N] to [1,N+1] - int intval = (bits >> 1) + 1; - return (bits & 1) ? -intval : intval; - } - return 0.f; - } - - static const float mul_table[4] = - { - 1.f/(1<> COORD_INTEGER_BITS_MP; - uint fracbits = bits >> COORD_INTEGER_BITS; - - uint intmaskMP = ((1<> 3; -} - -int bf_read::CompareBitsAt( int offset, bf_read * RESTRICT other, int otherOffset, int numbits ) RESTRICT -{ - extern unsigned long g_ExtraMasks[33]; - - if ( numbits == 0 ) - return 0; - - int overflow1 = offset + numbits > m_nDataBits; - int overflow2 = otherOffset + numbits > other->m_nDataBits; - - int x = overflow1 | overflow2; - if ( x != 0 ) - return x; - - unsigned int iStartBit1 = offset & 31u; - unsigned int iStartBit2 = otherOffset & 31u; - unsigned long *pData1 = (unsigned long*)m_pData + (offset >> 5); - unsigned long *pData2 = (unsigned long*)other->m_pData + (otherOffset >> 5); - unsigned long *pData1End = pData1 + ((offset + numbits - 1) >> 5); - unsigned long *pData2End = pData2 + ((otherOffset + numbits - 1) >> 5); - - while ( numbits > 32 ) - { - x = LoadLittleDWord( (unsigned long*)pData1, 0 ) >> iStartBit1; - x ^= LoadLittleDWord( (unsigned long*)pData1, 1 ) << (32 - iStartBit1); - x ^= LoadLittleDWord( (unsigned long*)pData2, 0 ) >> iStartBit2; - x ^= LoadLittleDWord( (unsigned long*)pData2, 1 ) << (32 - iStartBit2); - if ( x != 0 ) - { - return x; - } - ++pData1; - ++pData2; - numbits -= 32; - } - - x = LoadLittleDWord( (unsigned long*)pData1, 0 ) >> iStartBit1; - x ^= LoadLittleDWord( (unsigned long*)pData1End, 0 ) << (32 - iStartBit1); - x ^= LoadLittleDWord( (unsigned long*)pData2, 0 ) >> iStartBit2; - x ^= LoadLittleDWord( (unsigned long*)pData2End, 0 ) << (32 - iStartBit2); - return x & g_ExtraMasks[ numbits ]; -} +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include "bitbuf.h" +#include "coordsize.h" +#include "mathlib/vector.h" +#include "mathlib/mathlib.h" +#include "tier1/strtools.h" +#include "bitvec.h" + +// FIXME: Can't use this until we get multithreaded allocations in tier0 working for tools +// This is used by VVIS and fails to link +// NOTE: This must be the last file included!!! +//#include "tier0/memdbgon.h" + +#ifdef _X360 +// mandatory ... wary of above comment and isolating, tier0 is built as MT though +#include "tier0/memdbgon.h" +#endif + +#if _WIN32 +#define FAST_BIT_SCAN 1 +#if _X360 +#define CountLeadingZeros(x) _CountLeadingZeros(x) +inline unsigned int CountTrailingZeros( unsigned int elem ) +{ + // this implements CountTrailingZeros() / BitScanForward() + unsigned int mask = elem-1; + unsigned int comp = ~elem; + elem = mask & comp; + return (32 - _CountLeadingZeros(elem)); +} +#else +#include +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) + +inline unsigned int CountLeadingZeros(unsigned int x) +{ + unsigned long firstBit; + if ( _BitScanReverse(&firstBit,x) ) + return 31 - firstBit; + return 32; +} +inline unsigned int CountTrailingZeros(unsigned int elem) +{ + unsigned long out; + if ( _BitScanForward(&out, elem) ) + return out; + return 32; +} + +#endif +#else +#define FAST_BIT_SCAN 0 +#endif + + +static BitBufErrorHandler g_BitBufErrorHandler = 0; + +inline int BitForBitnum(int bitnum) +{ + return GetBitForBitnum(bitnum); +} + +void InternalBitBufErrorHandler( BitBufErrorType errorType, const char *pDebugName ) +{ + if ( g_BitBufErrorHandler ) + g_BitBufErrorHandler( errorType, pDebugName ); +} + + +void SetBitBufErrorHandler( BitBufErrorHandler fn ) +{ + g_BitBufErrorHandler = fn; +} + + +// #define BB_PROFILING + +unsigned long g_LittleBits[32]; + +// Precalculated bit masks for WriteUBitLong. Using these tables instead of +// doing the calculations gives a 33% speedup in WriteUBitLong. +unsigned long g_BitWriteMasks[32][33]; + +// (1 << i) - 1 +unsigned long g_ExtraMasks[33]; + +class CBitWriteMasksInit +{ +public: + CBitWriteMasksInit() + { + for( unsigned int startbit=0; startbit < 32; startbit++ ) + { + for( unsigned int nBitsLeft=0; nBitsLeft < 33; nBitsLeft++ ) + { + unsigned int endbit = startbit + nBitsLeft; + g_BitWriteMasks[startbit][nBitsLeft] = BitForBitnum(startbit) - 1; + if(endbit < 32) + g_BitWriteMasks[startbit][nBitsLeft] |= ~(BitForBitnum(endbit) - 1); + } + } + + for ( unsigned int maskBit=0; maskBit < 32; maskBit++ ) + g_ExtraMasks[maskBit] = BitForBitnum(maskBit) - 1; + g_ExtraMasks[32] = ~0ul; + + for ( unsigned int littleBit=0; littleBit < 32; littleBit++ ) + StoreLittleDWord( &g_LittleBits[littleBit], 0, 1u<> ( 32 - numbits ) ); + int nSignExtension = ( nValue >> 31 ) & ~nPreserveBits; + nValue &= nPreserveBits; + nValue |= nSignExtension; + + AssertMsg2( nValue == data, "WriteSBitLong: 0x%08x does not fit in %d bits", data, numbits ); + + WriteUBitLong( nValue, numbits, false ); +} + +void bf_write::WriteVarInt32( uint32 data ) +{ + // Check if align and we have room, slow path if not + if ( (m_iCurBit & 7) == 0 && (m_iCurBit + bitbuf::kMaxVarint32Bytes * 8 ) <= m_nDataBits) + { + uint8 *target = ((uint8*)m_pData) + (m_iCurBit>>3); + + target[0] = static_cast(data | 0x80); + if ( data >= (1 << 7) ) + { + target[1] = static_cast((data >> 7) | 0x80); + if ( data >= (1 << 14) ) + { + target[2] = static_cast((data >> 14) | 0x80); + if ( data >= (1 << 21) ) + { + target[3] = static_cast((data >> 21) | 0x80); + if ( data >= (1 << 28) ) + { + target[4] = static_cast(data >> 28); + m_iCurBit += 5 * 8; + return; + } + else + { + target[3] &= 0x7F; + m_iCurBit += 4 * 8; + return; + } + } + else + { + target[2] &= 0x7F; + m_iCurBit += 3 * 8; + return; + } + } + else + { + target[1] &= 0x7F; + m_iCurBit += 2 * 8; + return; + } + } + else + { + target[0] &= 0x7F; + m_iCurBit += 1 * 8; + return; + } + } + else // Slow path + { + while ( data > 0x7F ) + { + WriteUBitLong( (data & 0x7F) | 0x80, 8 ); + data >>= 7; + } + WriteUBitLong( data & 0x7F, 8 ); + } +} + +void bf_write::WriteVarInt64( uint64 data ) +{ + // Check if align and we have room, slow path if not + if ( (m_iCurBit & 7) == 0 && (m_iCurBit + bitbuf::kMaxVarintBytes * 8 ) <= m_nDataBits ) + { + uint8 *target = ((uint8*)m_pData) + (m_iCurBit>>3); + + // Splitting into 32-bit pieces gives better performance on 32-bit + // processors. + uint32 part0 = static_cast(data ); + uint32 part1 = static_cast(data >> 28); + uint32 part2 = static_cast(data >> 56); + + int size; + + // Here we can't really optimize for small numbers, since the data is + // split into three parts. Cheking for numbers < 128, for instance, + // would require three comparisons, since you'd have to make sure part1 + // and part2 are zero. However, if the caller is using 64-bit integers, + // it is likely that they expect the numbers to often be very large, so + // we probably don't want to optimize for small numbers anyway. Thus, + // we end up with a hardcoded binary search tree... + if ( part2 == 0 ) + { + if ( part1 == 0 ) + { + if ( part0 < (1 << 14) ) + { + if ( part0 < (1 << 7) ) + { + size = 1; goto size1; + } + else + { + size = 2; goto size2; + } + } + else + { + if ( part0 < (1 << 21) ) + { + size = 3; goto size3; + } + else + { + size = 4; goto size4; + } + } + } + else + { + if ( part1 < (1 << 14) ) + { + if ( part1 < (1 << 7) ) + { + size = 5; goto size5; + } + else + { + size = 6; goto size6; + } + } + else + { + if ( part1 < (1 << 21) ) + { + size = 7; goto size7; + } + else + { + size = 8; goto size8; + } + } + } + } + else + { + if ( part2 < (1 << 7) ) + { + size = 9; goto size9; + } + else + { + size = 10; goto size10; + } + } + + AssertFatalMsg( false, "Can't get here." ); + + size10: target[9] = static_cast((part2 >> 7) | 0x80); + size9 : target[8] = static_cast((part2 ) | 0x80); + size8 : target[7] = static_cast((part1 >> 21) | 0x80); + size7 : target[6] = static_cast((part1 >> 14) | 0x80); + size6 : target[5] = static_cast((part1 >> 7) | 0x80); + size5 : target[4] = static_cast((part1 ) | 0x80); + size4 : target[3] = static_cast((part0 >> 21) | 0x80); + size3 : target[2] = static_cast((part0 >> 14) | 0x80); + size2 : target[1] = static_cast((part0 >> 7) | 0x80); + size1 : target[0] = static_cast((part0 ) | 0x80); + + target[size-1] &= 0x7F; + m_iCurBit += size * 8; + } + else // slow path + { + while ( data > 0x7F ) + { + WriteUBitLong( (data & 0x7F) | 0x80, 8 ); + data >>= 7; + } + WriteUBitLong( data & 0x7F, 8 ); + } +} + +void bf_write::WriteSignedVarInt32( int32 data ) +{ + WriteVarInt32( bitbuf::ZigZagEncode32( data ) ); +} + +void bf_write::WriteSignedVarInt64( int64 data ) +{ + WriteVarInt64( bitbuf::ZigZagEncode64( data ) ); +} + +int bf_write::ByteSizeVarInt32( uint32 data ) +{ + int size = 1; + while ( data > 0x7F ) { + size++; + data >>= 7; + } + return size; +} + +int bf_write::ByteSizeVarInt64( uint64 data ) +{ + int size = 1; + while ( data > 0x7F ) { + size++; + data >>= 7; + } + return size; +} + +int bf_write::ByteSizeSignedVarInt32( int32 data ) +{ + return ByteSizeVarInt32( bitbuf::ZigZagEncode32( data ) ); +} + +int bf_write::ByteSizeSignedVarInt64( int64 data ) +{ + return ByteSizeVarInt64( bitbuf::ZigZagEncode64( data ) ); +} + +void bf_write::WriteBitLong(unsigned int data, int numbits, bool bSigned) +{ + if(bSigned) + WriteSBitLong((int)data, numbits); + else + WriteUBitLong(data, numbits); +} + +bool bf_write::WriteBits(const void *pInData, int nBits) +{ +#if defined( BB_PROFILING ) + VPROF( "bf_write::WriteBits" ); +#endif + + unsigned char *pOut = (unsigned char*)pInData; + int nBitsLeft = nBits; + + // Bounds checking.. + if ( (m_iCurBit+nBits) > m_nDataBits ) + { + SetOverflowFlag(); + CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); + return false; + } + + // Align output to dword boundary + while (((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8) + { + + WriteUBitLong( *pOut, 8, false ); + ++pOut; + nBitsLeft -= 8; + } + + if ( IsPC() && (nBitsLeft >= 32) && (m_iCurBit & 7) == 0 ) + { + // current bit is byte aligned, do block copy + int numbytes = nBitsLeft >> 3; + int numbits = numbytes << 3; + + Q_memcpy( (char*)m_pData+(m_iCurBit>>3), pOut, numbytes ); + pOut += numbytes; + nBitsLeft -= numbits; + m_iCurBit += numbits; + } + + // X360TBD: Can't write dwords in WriteBits because they'll get swapped + if ( IsPC() && nBitsLeft >= 32 ) + { + unsigned long iBitsRight = (m_iCurBit & 31); + unsigned long iBitsLeft = 32 - iBitsRight; + unsigned long bitMaskLeft = g_BitWriteMasks[iBitsRight][32]; + unsigned long bitMaskRight = g_BitWriteMasks[0][iBitsRight]; + + unsigned long *pData = &m_pData[m_iCurBit>>5]; + + // Read dwords. + while(nBitsLeft >= 32) + { + unsigned long curData = *(unsigned long*)pOut; + pOut += sizeof(unsigned long); + + *pData &= bitMaskLeft; + *pData |= curData << iBitsRight; + + pData++; + + if ( iBitsLeft < 32 ) + { + curData >>= iBitsLeft; + *pData &= bitMaskRight; + *pData |= curData; + } + + nBitsLeft -= 32; + m_iCurBit += 32; + } + } + + + // write remaining bytes + while ( nBitsLeft >= 8 ) + { + WriteUBitLong( *pOut, 8, false ); + ++pOut; + nBitsLeft -= 8; + } + + // write remaining bits + if ( nBitsLeft ) + { + WriteUBitLong( *pOut, nBitsLeft, false ); + } + + return !IsOverflowed(); +} + + +bool bf_write::WriteBitsFromBuffer( bf_read *pIn, int nBits ) +{ + // This could be optimized a little by + while ( nBits > 32 ) + { + WriteUBitLong( pIn->ReadUBitLong( 32 ), 32 ); + nBits -= 32; + } + + WriteUBitLong( pIn->ReadUBitLong( nBits ), nBits ); + return !IsOverflowed() && !pIn->IsOverflowed(); +} + + +void bf_write::WriteBitAngle( float fAngle, int numbits ) +{ + int d; + unsigned int mask; + unsigned int shift; + + shift = BitForBitnum(numbits); + mask = shift - 1; + + d = (int)( (fAngle / 360.0) * shift ); + d &= mask; + + WriteUBitLong((unsigned int)d, numbits); +} + +void bf_write::WriteBitCoordMP( const float f, bool bIntegral, bool bLowPrecision ) +{ +#if defined( BB_PROFILING ) + VPROF( "bf_write::WriteBitCoordMP" ); +#endif + int signbit = (f <= -( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION )); + int intval = (int)abs(f); + int fractval = bLowPrecision ? + ( abs((int)(f*COORD_DENOMINATOR_LOWPRECISION)) & (COORD_DENOMINATOR_LOWPRECISION-1) ) : + ( abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1) ); + + bool bInBounds = intval < (1 << COORD_INTEGER_BITS_MP ); + + unsigned int bits, numbits; + + if ( bIntegral ) + { + // Integer encoding: in-bounds bit, nonzero bit, optional sign bit + integer value bits + if ( intval ) + { + // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] + --intval; + bits = intval * 8 + signbit * 4 + 2 + bInBounds; + numbits = 3 + (bInBounds ? COORD_INTEGER_BITS_MP : COORD_INTEGER_BITS); + } + else + { + bits = bInBounds; + numbits = 2; + } + } + else + { + // Float encoding: in-bounds bit, integer bit, sign bit, fraction value bits, optional integer value bits + if ( intval ) + { + // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] + --intval; + bits = intval * 8 + signbit * 4 + 2 + bInBounds; + bits += bInBounds ? (fractval << (3+COORD_INTEGER_BITS_MP)) : (fractval << (3+COORD_INTEGER_BITS)); + numbits = 3 + (bInBounds ? COORD_INTEGER_BITS_MP : COORD_INTEGER_BITS) + + (bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS); + } + else + { + bits = fractval * 8 + signbit * 4 + 0 + bInBounds; + numbits = 3 + (bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS); + } + } + + WriteUBitLong( bits, numbits ); +} + +void bf_write::WriteBitCoord (const float f) +{ +#if defined( BB_PROFILING ) + VPROF( "bf_write::WriteBitCoord" ); +#endif + int signbit = (f <= -COORD_RESOLUTION); + int intval = (int)abs(f); + int fractval = abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1); + + + // Send the bit flags that indicate whether we have an integer part and/or a fraction part. + WriteOneBit( intval ); + WriteOneBit( fractval ); + + if ( intval || fractval ) + { + // Send the sign bit + WriteOneBit( signbit ); + + // Send the integer if we have one. + if ( intval ) + { + // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] + intval--; + WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS ); + } + + // Send the fraction if we have one + if ( fractval ) + { + WriteUBitLong( (unsigned int)fractval, COORD_FRACTIONAL_BITS ); + } + } +} + +void bf_write::WriteBitVec3Coord( const Vector& fa ) +{ + int xflag, yflag, zflag; + + xflag = (fa[0] >= COORD_RESOLUTION) || (fa[0] <= -COORD_RESOLUTION); + yflag = (fa[1] >= COORD_RESOLUTION) || (fa[1] <= -COORD_RESOLUTION); + zflag = (fa[2] >= COORD_RESOLUTION) || (fa[2] <= -COORD_RESOLUTION); + + WriteOneBit( xflag ); + WriteOneBit( yflag ); + WriteOneBit( zflag ); + + if ( xflag ) + WriteBitCoord( fa[0] ); + if ( yflag ) + WriteBitCoord( fa[1] ); + if ( zflag ) + WriteBitCoord( fa[2] ); +} + +void bf_write::WriteBitNormal( float f ) +{ + int signbit = (f <= -NORMAL_RESOLUTION); + + // NOTE: Since +/-1 are valid values for a normal, I'm going to encode that as all ones + unsigned int fractval = abs( (int)(f*NORMAL_DENOMINATOR) ); + + // clamp.. + if (fractval > NORMAL_DENOMINATOR) + fractval = NORMAL_DENOMINATOR; + + // Send the sign bit + WriteOneBit( signbit ); + + // Send the fractional component + WriteUBitLong( fractval, NORMAL_FRACTIONAL_BITS ); +} + +void bf_write::WriteBitVec3Normal( const Vector& fa ) +{ + int xflag, yflag; + + xflag = (fa[0] >= NORMAL_RESOLUTION) || (fa[0] <= -NORMAL_RESOLUTION); + yflag = (fa[1] >= NORMAL_RESOLUTION) || (fa[1] <= -NORMAL_RESOLUTION); + + WriteOneBit( xflag ); + WriteOneBit( yflag ); + + if ( xflag ) + WriteBitNormal( fa[0] ); + if ( yflag ) + WriteBitNormal( fa[1] ); + + // Write z sign bit + int signbit = (fa[2] <= -NORMAL_RESOLUTION); + WriteOneBit( signbit ); +} + +void bf_write::WriteBitAngles( const QAngle& fa ) +{ + // FIXME: + Vector tmp( fa.x, fa.y, fa.z ); + WriteBitVec3Coord( tmp ); +} + +void bf_write::WriteChar(int val) +{ + WriteSBitLong(val, sizeof(char) << 3); +} + +void bf_write::WriteByte(int val) +{ + WriteUBitLong(val, sizeof(unsigned char) << 3); +} + +void bf_write::WriteShort(int val) +{ + WriteSBitLong(val, sizeof(short) << 3); +} + +void bf_write::WriteWord(int val) +{ + WriteUBitLong(val, sizeof(unsigned short) << 3); +} + +void bf_write::WriteLong(long val) +{ + WriteSBitLong(val, sizeof(long) << 3); +} + +void bf_write::WriteLongLong(int64 val) +{ + uint *pLongs = (uint*)&val; + + // Insert the two DWORDS according to network endian + const short endianIndex = 0x0100; + byte *idx = (byte*)&endianIndex; + WriteUBitLong(pLongs[*idx++], sizeof(long) << 3); + WriteUBitLong(pLongs[*idx], sizeof(long) << 3); +} + +void bf_write::WriteFloat(float val) +{ + // Pre-swap the float, since WriteBits writes raw data + LittleFloat( &val, &val ); + + WriteBits(&val, sizeof(val) << 3); +} + +bool bf_write::WriteBytes( const void *pBuf, int nBytes ) +{ + return WriteBits(pBuf, nBytes << 3); +} + +bool bf_write::WriteString(const char *pStr) +{ + if(pStr) + { + do + { + WriteChar( *pStr ); + ++pStr; + } while( *(pStr-1) != 0 ); + } + else + { + WriteChar( 0 ); + } + + return !IsOverflowed(); +} + +// ---------------------------------------------------------------------------------------- // +// bf_read +// ---------------------------------------------------------------------------------------- // + +bf_read::bf_read() +{ + m_pData = NULL; + m_nDataBytes = 0; + m_nDataBits = -1; // set to -1 so we overflow on any operation + m_iCurBit = 0; + m_bOverflow = false; + m_bAssertOnOverflow = true; + m_pDebugName = NULL; +} + +bf_read::bf_read( const void *pData, int nBytes, int nBits ) +{ + m_bAssertOnOverflow = true; + StartReading( pData, nBytes, 0, nBits ); +} + +bf_read::bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits ) +{ + m_bAssertOnOverflow = true; + m_pDebugName = pDebugName; + StartReading( pData, nBytes, 0, nBits ); +} + +void bf_read::StartReading( const void *pData, int nBytes, int iStartBit, int nBits ) +{ + // Make sure we're dword aligned. + Assert(((size_t)pData & 3) == 0); + + m_pData = (unsigned char*)pData; + m_nDataBytes = nBytes; + + if ( nBits == -1 ) + { + m_nDataBits = m_nDataBytes << 3; + } + else + { + Assert( nBits <= nBytes*8 ); + m_nDataBits = nBits; + } + + m_iCurBit = iStartBit; + m_bOverflow = false; +} + +void bf_read::Reset() +{ + m_iCurBit = 0; + m_bOverflow = false; +} + +void bf_read::SetAssertOnOverflow( bool bAssert ) +{ + m_bAssertOnOverflow = bAssert; +} + +void bf_read::SetDebugName( const char *pName ) +{ + m_pDebugName = pName; +} + +void bf_read::SetOverflowFlag() +{ + if ( m_bAssertOnOverflow ) + { + Assert( false ); + } + m_bOverflow = true; +} + +unsigned int bf_read::CheckReadUBitLong(int numbits) +{ + // Ok, just read bits out. + int i, nBitValue; + unsigned int r = 0; + + for(i=0; i < numbits; i++) + { + nBitValue = ReadOneBitNoCheck(); + r |= nBitValue << i; + } + m_iCurBit -= numbits; + + return r; +} + +void bf_read::ReadBits(void *pOutData, int nBits) +{ +#if defined( BB_PROFILING ) + VPROF( "bf_read::ReadBits" ); +#endif + + unsigned char *pOut = (unsigned char*)pOutData; + int nBitsLeft = nBits; + + + // align output to dword boundary + while( ((size_t)pOut & 3) != 0 && nBitsLeft >= 8 ) + { + *pOut = (unsigned char)ReadUBitLong(8); + ++pOut; + nBitsLeft -= 8; + } + + // X360TBD: Can't read dwords in ReadBits because they'll get swapped + if ( IsPC() ) + { + // read dwords + while ( nBitsLeft >= 32 ) + { + *((unsigned long*)pOut) = ReadUBitLong(32); + pOut += sizeof(unsigned long); + nBitsLeft -= 32; + } + } + + // read remaining bytes + while ( nBitsLeft >= 8 ) + { + *pOut = ReadUBitLong(8); + ++pOut; + nBitsLeft -= 8; + } + + // read remaining bits + if ( nBitsLeft ) + { + *pOut = ReadUBitLong(nBitsLeft); + } + +} + +int bf_read::ReadBitsClamped_ptr(void *pOutData, size_t outSizeBytes, size_t nBits) +{ + size_t outSizeBits = outSizeBytes * 8; + size_t readSizeBits = nBits; + int skippedBits = 0; + if ( readSizeBits > outSizeBits ) + { + // Should we print a message when we clamp the data being read? Only + // in debug builds I think. + AssertMsg( 0, "Oversized network packet received, and clamped." ); + readSizeBits = outSizeBits; + skippedBits = (int)( nBits - outSizeBits ); + // What should we do in this case, which should only happen if nBits + // is negative for some reason? + //if ( skippedBits < 0 ) + // return 0; + } + + ReadBits( pOutData, readSizeBits ); + SeekRelative( skippedBits ); + + // Return the number of bits actually read. + return (int)readSizeBits; +} + +float bf_read::ReadBitAngle( int numbits ) +{ + float fReturn; + int i; + float shift; + + shift = (float)( BitForBitnum(numbits) ); + + i = ReadUBitLong( numbits ); + fReturn = (float)i * (360.0 / shift); + + return fReturn; +} + +unsigned int bf_read::PeekUBitLong( int numbits ) +{ + unsigned int r; + int i, nBitValue; +#ifdef BIT_VERBOSE + int nShifts = numbits; +#endif + + bf_read savebf; + + savebf = *this; // Save current state info + + r = 0; + for(i=0; i < numbits; i++) + { + nBitValue = ReadOneBit(); + + // Append to current stream + if ( nBitValue ) + { + r |= BitForBitnum(i); + } + } + + *this = savebf; + +#ifdef BIT_VERBOSE + Con_Printf( "PeekBitLong: %i %i\n", nShifts, (unsigned int)r ); +#endif + + return r; +} + +unsigned int bf_read::ReadUBitLongNoInline( int numbits ) +{ + return ReadUBitLong( numbits ); +} + +unsigned int bf_read::ReadUBitVarInternal( int encodingType ) +{ + m_iCurBit -= 4; + // int bits = { 4, 8, 12, 32 }[ encodingType ]; + int bits = 4 + encodingType*4 + (((2 - encodingType) >> 31) & 16); + return ReadUBitLong( bits ); +} + +// Append numbits least significant bits from data to the current bit stream +int bf_read::ReadSBitLong( int numbits ) +{ + unsigned int r = ReadUBitLong(numbits); + unsigned int s = 1 << (numbits-1); + if (r >= s) + { + // sign-extend by removing sign bit and then subtracting sign bit again + r = r - s - s; + } + return r; +} + +uint32 bf_read::ReadVarInt32() +{ + uint32 result = 0; + int count = 0; + uint32 b; + + do + { + if ( count == bitbuf::kMaxVarint32Bytes ) + { + return result; + } + b = ReadUBitLong( 8 ); + result |= (b & 0x7F) << (7 * count); + ++count; + } while (b & 0x80); + + return result; +} + +uint64 bf_read::ReadVarInt64() +{ + uint64 result = 0; + int count = 0; + uint64 b; + + do + { + if ( count == bitbuf::kMaxVarintBytes ) + { + return result; + } + b = ReadUBitLong( 8 ); + result |= static_cast(b & 0x7F) << (7 * count); + ++count; + } while (b & 0x80); + + return result; +} + +int32 bf_read::ReadSignedVarInt32() +{ + uint32 value = ReadVarInt32(); + return bitbuf::ZigZagDecode32( value ); +} + +int64 bf_read::ReadSignedVarInt64() +{ + uint32 value = ReadVarInt64(); + return bitbuf::ZigZagDecode64( value ); +} + +unsigned int bf_read::ReadBitLong(int numbits, bool bSigned) +{ + if(bSigned) + return (unsigned int)ReadSBitLong(numbits); + else + return ReadUBitLong(numbits); +} + + +// Basic Coordinate Routines (these contain bit-field size AND fixed point scaling constants) +float bf_read::ReadBitCoord (void) +{ +#if defined( BB_PROFILING ) + VPROF( "bf_read::ReadBitCoord" ); +#endif + int intval=0,fractval=0,signbit=0; + float value = 0.0; + + + // Read the required integer and fraction flags + intval = ReadOneBit(); + fractval = ReadOneBit(); + + // If we got either parse them, otherwise it's a zero. + if ( intval || fractval ) + { + // Read the sign bit + signbit = ReadOneBit(); + + // If there's an integer, read it in + if ( intval ) + { + // Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE] + intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1; + } + + // If there's a fraction, read it in + if ( fractval ) + { + fractval = ReadUBitLong( COORD_FRACTIONAL_BITS ); + } + + // Calculate the correct floating point value + value = intval + ((float)fractval * COORD_RESOLUTION); + + // Fixup the sign if negative. + if ( signbit ) + value = -value; + } + + return value; +} + +float bf_read::ReadBitCoordMP( bool bIntegral, bool bLowPrecision ) +{ +#if defined( BB_PROFILING ) + VPROF( "bf_read::ReadBitCoordMP" ); +#endif + // BitCoordMP float encoding: inbounds bit, integer bit, sign bit, optional int bits, float bits + // BitCoordMP integer encoding: inbounds bit, integer bit, optional sign bit, optional int bits. + // int bits are always encoded as (value - 1) since zero is handled by the integer bit + + // With integer-only encoding, the presence of the third bit depends on the second + int flags = ReadUBitLong(3 - bIntegral); + enum { INBOUNDS=1, INTVAL=2, SIGN=4 }; + + if ( bIntegral ) + { + if ( flags & INTVAL ) + { + // Read the third bit and the integer portion together at once + unsigned int bits = ReadUBitLong( (flags & INBOUNDS) ? COORD_INTEGER_BITS_MP+1 : COORD_INTEGER_BITS+1 ); + // Remap from [0,N] to [1,N+1] + int intval = (bits >> 1) + 1; + return (bits & 1) ? -intval : intval; + } + return 0.f; + } + + static const float mul_table[4] = + { + 1.f/(1<> COORD_INTEGER_BITS_MP; + uint fracbits = bits >> COORD_INTEGER_BITS; + + uint intmaskMP = ((1<> 3; +} + +int bf_read::CompareBitsAt( int offset, bf_read * RESTRICT other, int otherOffset, int numbits ) RESTRICT +{ + extern unsigned long g_ExtraMasks[33]; + + if ( numbits == 0 ) + return 0; + + int overflow1 = offset + numbits > m_nDataBits; + int overflow2 = otherOffset + numbits > other->m_nDataBits; + + int x = overflow1 | overflow2; + if ( x != 0 ) + return x; + + unsigned int iStartBit1 = offset & 31u; + unsigned int iStartBit2 = otherOffset & 31u; + unsigned long *pData1 = (unsigned long*)m_pData + (offset >> 5); + unsigned long *pData2 = (unsigned long*)other->m_pData + (otherOffset >> 5); + unsigned long *pData1End = pData1 + ((offset + numbits - 1) >> 5); + unsigned long *pData2End = pData2 + ((otherOffset + numbits - 1) >> 5); + + while ( numbits > 32 ) + { + x = LoadLittleDWord( (unsigned long*)pData1, 0 ) >> iStartBit1; + x ^= LoadLittleDWord( (unsigned long*)pData1, 1 ) << (32 - iStartBit1); + x ^= LoadLittleDWord( (unsigned long*)pData2, 0 ) >> iStartBit2; + x ^= LoadLittleDWord( (unsigned long*)pData2, 1 ) << (32 - iStartBit2); + if ( x != 0 ) + { + return x; + } + ++pData1; + ++pData2; + numbits -= 32; + } + + x = LoadLittleDWord( (unsigned long*)pData1, 0 ) >> iStartBit1; + x ^= LoadLittleDWord( (unsigned long*)pData1End, 0 ) << (32 - iStartBit1); + x ^= LoadLittleDWord( (unsigned long*)pData2, 0 ) >> iStartBit2; + x ^= LoadLittleDWord( (unsigned long*)pData2End, 0 ) << (32 - iStartBit2); + return x & g_ExtraMasks[ numbits ]; +} -- cgit v1.2.3