faluco@1541: //========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// faluco@1541: // faluco@1541: // Purpose: faluco@1541: // faluco@1541: // $NoKeywords: $ faluco@1541: // faluco@1541: //=============================================================================// faluco@1541: faluco@1541: #include "bitbuf.h" faluco@1541: #include "coordsize.h" faluco@1541: #include "vector.h" faluco@1541: #include "mathlib/math_base.h" faluco@1541: #include "vstdlib/strtools.h" faluco@1541: faluco@1541: faluco@1541: // FIXME: Can't use this until we get multithreaded allocations in tier0 working for tools faluco@1541: // This is used by VVIS and fails to link faluco@1541: // NOTE: This must be the last file included!!! faluco@1541: //#include "tier0/memdbgon.h" faluco@1541: faluco@1541: #ifdef _XBOX faluco@1541: // mandatory ... wary of above comment and isolating, tier0 is built as MT though faluco@1541: #include "tier0/memdbgon.h" faluco@1541: #endif faluco@1541: faluco@1541: static BitBufErrorHandler g_BitBufErrorHandler = 0; faluco@1541: faluco@1541: faluco@1541: void InternalBitBufErrorHandler( BitBufErrorType errorType, const char *pDebugName ) faluco@1541: { faluco@1541: if ( g_BitBufErrorHandler ) faluco@1541: g_BitBufErrorHandler( errorType, pDebugName ); faluco@1541: } faluco@1541: faluco@1541: faluco@1541: void SetBitBufErrorHandler( BitBufErrorHandler fn ) faluco@1541: { faluco@1541: g_BitBufErrorHandler = fn; faluco@1541: } faluco@1541: faluco@1541: faluco@1541: // #define BB_PROFILING faluco@1541: faluco@1541: faluco@1541: // Precalculated bit masks for WriteUBitLong. Using these tables instead of faluco@1541: // doing the calculations gives a 33% speedup in WriteUBitLong. faluco@1541: unsigned long g_BitWriteMasks[32][33]; faluco@1541: faluco@1541: // (1 << i) - 1 faluco@1541: unsigned long g_ExtraMasks[32]; faluco@1541: faluco@1541: class CBitWriteMasksInit faluco@1541: { faluco@1541: public: faluco@1541: CBitWriteMasksInit() faluco@1541: { faluco@1541: for( unsigned int startbit=0; startbit < 32; startbit++ ) faluco@1541: { faluco@1541: for( unsigned int nBitsLeft=0; nBitsLeft < 33; nBitsLeft++ ) faluco@1541: { faluco@1541: unsigned int endbit = startbit + nBitsLeft; faluco@1541: g_BitWriteMasks[startbit][nBitsLeft] = (1 << startbit) - 1; faluco@1541: if(endbit < 32) faluco@1541: g_BitWriteMasks[startbit][nBitsLeft] |= ~((1 << endbit) - 1); faluco@1541: } faluco@1541: } faluco@1541: faluco@1541: for ( unsigned int maskBit=0; maskBit < 32; maskBit++ ) faluco@1541: g_ExtraMasks[maskBit] = (1 << maskBit) - 1; faluco@1541: } faluco@1541: }; faluco@1541: CBitWriteMasksInit g_BitWriteMasksInit; faluco@1541: faluco@1541: faluco@1541: // ---------------------------------------------------------------------------------------- // faluco@1541: // bf_write faluco@1541: // ---------------------------------------------------------------------------------------- // faluco@1541: faluco@1541: bf_write::bf_write() faluco@1541: { faluco@1541: m_pData = NULL; faluco@1541: m_nDataBytes = 0; faluco@1541: m_nDataBits = -1; // set to -1 so we generate overflow on any operation faluco@1541: m_iCurBit = 0; faluco@1541: m_bOverflow = false; faluco@1541: m_bAssertOnOverflow = true; faluco@1541: m_pDebugName = NULL; faluco@1541: } faluco@1541: faluco@1541: bf_write::bf_write( const char *pDebugName, void *pData, int nBytes, int nBits ) faluco@1541: { faluco@1541: m_bAssertOnOverflow = true; faluco@1541: m_pDebugName = pDebugName; faluco@1541: StartWriting( pData, nBytes, 0, nBits ); faluco@1541: } faluco@1541: faluco@1541: bf_write::bf_write( void *pData, int nBytes, int nBits ) faluco@1541: { faluco@1541: m_bAssertOnOverflow = true; faluco@1541: StartWriting( pData, nBytes, 0, nBits ); faluco@1541: } faluco@1541: faluco@1541: void bf_write::StartWriting( void *pData, int nBytes, int iStartBit, int nBits ) faluco@1541: { faluco@1541: // Make sure it's dword aligned and padded. faluco@1541: Assert( (nBytes % 4) == 0 ); faluco@1541: Assert(((unsigned long)pData & 3) == 0); faluco@1541: faluco@1541: m_pData = (unsigned char*)pData; faluco@1541: m_nDataBytes = nBytes; faluco@1541: faluco@1541: if ( nBits == -1 ) faluco@1541: { faluco@1541: m_nDataBits = nBytes << 3; faluco@1541: } faluco@1541: else faluco@1541: { faluco@1541: Assert( nBits <= nBytes*8 ); faluco@1541: m_nDataBits = nBits; faluco@1541: } faluco@1541: faluco@1541: m_iCurBit = iStartBit; faluco@1541: m_bOverflow = false; faluco@1541: } faluco@1541: faluco@1541: void bf_write::Reset() faluco@1541: { faluco@1541: m_iCurBit = 0; faluco@1541: m_bOverflow = false; faluco@1541: } faluco@1541: faluco@1541: faluco@1541: void bf_write::SetAssertOnOverflow( bool bAssert ) faluco@1541: { faluco@1541: m_bAssertOnOverflow = bAssert; faluco@1541: } faluco@1541: faluco@1541: faluco@1541: const char* bf_write::GetDebugName() faluco@1541: { faluco@1541: return m_pDebugName; faluco@1541: } faluco@1541: faluco@1541: faluco@1541: void bf_write::SetDebugName( const char *pDebugName ) faluco@1541: { faluco@1541: m_pDebugName = pDebugName; faluco@1541: } faluco@1541: faluco@1541: faluco@1541: void bf_write::SeekToBit( int bitPos ) faluco@1541: { faluco@1541: m_iCurBit = bitPos; faluco@1541: } faluco@1541: faluco@1541: faluco@1541: // Sign bit comes first faluco@1541: void bf_write::WriteSBitLong( int data, int numbits ) faluco@1541: { faluco@1541: // Do we have a valid # of bits to encode with? faluco@1541: Assert( numbits >= 1 ); faluco@1541: faluco@1541: // Note: it does this wierdness here so it's bit-compatible with regular integer data in the buffer. faluco@1541: // (Some old code writes direct integers right into the buffer). faluco@1541: if(data < 0) faluco@1541: { faluco@1541: #ifdef _DEBUG faluco@1541: if( numbits < 32 ) faluco@1541: { faluco@1541: // Make sure it doesn't overflow. faluco@1541: faluco@1541: if( data < 0 ) faluco@1541: { faluco@1541: Assert( data >= -(1 << (numbits-1)) ); faluco@1541: } faluco@1541: else faluco@1541: { faluco@1541: Assert( data < (1 << (numbits-1)) ); faluco@1541: } faluco@1541: } faluco@1541: #endif faluco@1541: faluco@1541: WriteUBitLong( (unsigned int)(0x80000000 + data), numbits - 1, false ); faluco@1541: WriteOneBit( 1 ); faluco@1541: } faluco@1541: else faluco@1541: { faluco@1541: WriteUBitLong((unsigned int)data, numbits - 1); faluco@1541: WriteOneBit( 0 ); faluco@1541: } faluco@1541: } faluco@1541: faluco@1541: // writes an unsigned integer with variable bit length faluco@1541: void bf_write::WriteUBitVar( unsigned int data ) faluco@1541: { faluco@1541: unsigned int bits = 0; faluco@1541: unsigned int base = 0; faluco@1541: faluco@1541: while (data > (base<<1)) faluco@1541: { faluco@1541: bits++; faluco@1541: base = (1< 0) faluco@1541: WriteUBitLong( 0, bits ); faluco@1541: faluco@1541: // end marker faluco@1541: WriteOneBit( 1 ); faluco@1541: faluco@1541: // write the value faluco@1541: if ( bits > 0) faluco@1541: WriteUBitLong( data - base , bits ); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteBitLong(unsigned int data, int numbits, bool bSigned) faluco@1541: { faluco@1541: if(bSigned) faluco@1541: WriteSBitLong((int)data, numbits); faluco@1541: else faluco@1541: WriteUBitLong(data, numbits); faluco@1541: } faluco@1541: faluco@1541: bool bf_write::WriteBits(const void *pInData, int nBits) faluco@1541: { faluco@1541: #if defined( BB_PROFILING ) faluco@1541: VPROF( "bf_write::WriteBits" ); faluco@1541: #endif faluco@1541: faluco@1541: unsigned char *pOut = (unsigned char*)pInData; faluco@1541: int nBitsLeft = nBits; faluco@1541: faluco@1541: if((m_iCurBit+nBits) > m_nDataBits) faluco@1541: { faluco@1541: SetOverflowFlag(); faluco@1541: CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); faluco@1541: return false; faluco@1541: } faluco@1541: faluco@1541: // Get output dword-aligned. faluco@1541: while(((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8) faluco@1541: { faluco@1541: faluco@1541: WriteUBitLong( *pOut, 8, false ); faluco@1541: ++pOut; faluco@1541: nBitsLeft -= 8; faluco@1541: } faluco@1541: faluco@1541: // check if we can use fast memcpy if m_iCurBit is byte aligned faluco@1541: if ( (nBitsLeft >= 32) && (m_iCurBit & 7) == 0 ) faluco@1541: { faluco@1541: int numbytes = (nBitsLeft >> 3); faluco@1541: int numbits = numbytes << 3; faluco@1541: faluco@1541: // Bounds checking.. faluco@1541: // TODO: May not need this check anymore faluco@1541: if((m_iCurBit+numbits) > m_nDataBits) faluco@1541: { faluco@1541: m_iCurBit = m_nDataBits; faluco@1541: SetOverflowFlag(); faluco@1541: CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); faluco@1541: return false; faluco@1541: } faluco@1541: faluco@1541: Q_memcpy( m_pData+(m_iCurBit>>3), pOut, numbytes ); faluco@1541: pOut += numbytes; faluco@1541: nBitsLeft -= numbits; faluco@1541: m_iCurBit += numbits; faluco@1541: } faluco@1541: faluco@1541: // Read dwords. faluco@1541: while(nBitsLeft >= 32) faluco@1541: { faluco@1541: WriteUBitLong( *((unsigned long*)pOut), 32, false ); faluco@1541: pOut += sizeof(unsigned long); faluco@1541: nBitsLeft -= 32; faluco@1541: } faluco@1541: faluco@1541: // Read the remaining bytes. faluco@1541: while(nBitsLeft >= 8) faluco@1541: { faluco@1541: WriteUBitLong( *pOut, 8, false ); faluco@1541: ++pOut; faluco@1541: nBitsLeft -= 8; faluco@1541: } faluco@1541: faluco@1541: // Read the remaining bits. faluco@1541: if(nBitsLeft) faluco@1541: { faluco@1541: WriteUBitLong( *pOut, nBitsLeft, false ); faluco@1541: } faluco@1541: faluco@1541: return !IsOverflowed(); faluco@1541: } faluco@1541: faluco@1541: faluco@1541: bool bf_write::WriteBitsFromBuffer( bf_read *pIn, int nBits ) faluco@1541: { faluco@1541: // This could be optimized a little by faluco@1541: while ( nBits > 32 ) faluco@1541: { faluco@1541: WriteUBitLong( pIn->ReadUBitLong( 32 ), 32 ); faluco@1541: nBits -= 32; faluco@1541: } faluco@1541: faluco@1541: WriteUBitLong( pIn->ReadUBitLong( nBits ), nBits ); faluco@1541: return !IsOverflowed() && !pIn->IsOverflowed(); faluco@1541: } faluco@1541: faluco@1541: faluco@1541: void bf_write::WriteBitAngle( float fAngle, int numbits ) faluco@1541: { faluco@1541: int d; faluco@1541: unsigned int mask; faluco@1541: unsigned int shift; faluco@1541: faluco@1541: shift = (1<(f)); faluco@1541: int fractval = abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1); faluco@1541: faluco@1541: faluco@1541: // Send the bit flags that indicate whether we have an integer part and/or a fraction part. faluco@1541: WriteOneBit( intval ); faluco@1541: WriteOneBit( fractval ); faluco@1541: faluco@1541: if ( intval || fractval ) faluco@1541: { faluco@1541: // Send the sign bit faluco@1541: WriteOneBit( signbit ); faluco@1541: faluco@1541: // Send the integer if we have one. faluco@1541: if ( intval ) faluco@1541: { faluco@1541: // Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1] faluco@1541: intval--; faluco@1541: WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS ); faluco@1541: } faluco@1541: faluco@1541: // Send the fraction if we have one faluco@1541: if ( fractval ) faluco@1541: { faluco@1541: WriteUBitLong( (unsigned int)fractval, COORD_FRACTIONAL_BITS ); faluco@1541: } faluco@1541: } faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteBitFloat(float val) faluco@1541: { faluco@1541: long intVal; faluco@1541: faluco@1541: Assert(sizeof(long) == sizeof(float)); faluco@1541: Assert(sizeof(float) == 4); faluco@1541: faluco@1541: void *v = &val; faluco@1541: intVal = *reinterpret_cast(v); faluco@1541: WriteUBitLong( intVal, 32 ); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteBitVec3Coord( const Vector& fa ) faluco@1541: { faluco@1541: int xflag, yflag, zflag; faluco@1541: faluco@1541: xflag = (fa[0] >= COORD_RESOLUTION) || (fa[0] <= -COORD_RESOLUTION); faluco@1541: yflag = (fa[1] >= COORD_RESOLUTION) || (fa[1] <= -COORD_RESOLUTION); faluco@1541: zflag = (fa[2] >= COORD_RESOLUTION) || (fa[2] <= -COORD_RESOLUTION); faluco@1541: faluco@1541: WriteOneBit( xflag ); faluco@1541: WriteOneBit( yflag ); faluco@1541: WriteOneBit( zflag ); faluco@1541: faluco@1541: if ( xflag ) faluco@1541: WriteBitCoord( fa[0] ); faluco@1541: if ( yflag ) faluco@1541: WriteBitCoord( fa[1] ); faluco@1541: if ( zflag ) faluco@1541: WriteBitCoord( fa[2] ); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteBitNormal( float f ) faluco@1541: { faluco@1541: int signbit = (f <= -NORMAL_RESOLUTION); faluco@1541: faluco@1541: // NOTE: Since +/-1 are valid values for a normal, I'm going to encode that as all ones faluco@1541: unsigned int fractval = abs( (int)(f*NORMAL_DENOMINATOR) ); faluco@1541: faluco@1541: // clamp.. faluco@1541: if (fractval > NORMAL_DENOMINATOR) faluco@1541: fractval = NORMAL_DENOMINATOR; faluco@1541: faluco@1541: // Send the sign bit faluco@1541: WriteOneBit( signbit ); faluco@1541: faluco@1541: // Send the fractional component faluco@1541: WriteUBitLong( fractval, NORMAL_FRACTIONAL_BITS ); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteBitVec3Normal( const Vector& fa ) faluco@1541: { faluco@1541: int xflag, yflag; faluco@1541: faluco@1541: xflag = (fa[0] >= NORMAL_RESOLUTION) || (fa[0] <= -NORMAL_RESOLUTION); faluco@1541: yflag = (fa[1] >= NORMAL_RESOLUTION) || (fa[1] <= -NORMAL_RESOLUTION); faluco@1541: faluco@1541: WriteOneBit( xflag ); faluco@1541: WriteOneBit( yflag ); faluco@1541: faluco@1541: if ( xflag ) faluco@1541: WriteBitNormal( fa[0] ); faluco@1541: if ( yflag ) faluco@1541: WriteBitNormal( fa[1] ); faluco@1541: faluco@1541: // Write z sign bit faluco@1541: int signbit = (fa[2] <= -NORMAL_RESOLUTION); faluco@1541: WriteOneBit( signbit ); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteBitAngles( const QAngle& fa ) faluco@1541: { faluco@1541: // FIXME: faluco@1541: Vector tmp( fa.x, fa.y, fa.z ); faluco@1541: WriteBitVec3Coord( tmp ); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteChar(int val) faluco@1541: { faluco@1541: WriteSBitLong(val, sizeof(char) << 3); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteByte(int val) faluco@1541: { faluco@1541: WriteUBitLong(val, sizeof(unsigned char) << 3); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteShort(int val) faluco@1541: { faluco@1541: WriteSBitLong(val, sizeof(short) << 3); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteWord(int val) faluco@1541: { faluco@1541: WriteUBitLong(val, sizeof(unsigned short) << 3); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteLong(long val) faluco@1541: { faluco@1541: WriteSBitLong(val, sizeof(long) << 3); faluco@1541: } faluco@1541: faluco@1541: void bf_write::WriteFloat(float val) faluco@1541: { faluco@1541: WriteBits(&val, sizeof(val) << 3); faluco@1541: } faluco@1541: faluco@1541: bool bf_write::WriteBytes( const void *pBuf, int nBytes ) faluco@1541: { faluco@1541: return WriteBits(pBuf, nBytes << 3); faluco@1541: } faluco@1541: faluco@1541: bool bf_write::WriteString(const char *pStr) faluco@1541: { faluco@1541: if(pStr) faluco@1541: { faluco@1541: do faluco@1541: { faluco@1541: WriteChar( *pStr ); faluco@1541: ++pStr; faluco@1541: } while( *(pStr-1) != 0 ); faluco@1541: } faluco@1541: else faluco@1541: { faluco@1541: WriteChar( 0 ); faluco@1541: } faluco@1541: faluco@1541: return !IsOverflowed(); faluco@1541: } faluco@1541: faluco@1541: // ---------------------------------------------------------------------------------------- // faluco@1541: // bf_read faluco@1541: // ---------------------------------------------------------------------------------------- // faluco@1541: faluco@1541: bf_read::bf_read() faluco@1541: { faluco@1541: m_pData = NULL; faluco@1541: m_nDataBytes = 0; faluco@1541: m_nDataBits = -1; // set to -1 so we overflow on any operation faluco@1541: m_iCurBit = 0; faluco@1541: m_bOverflow = false; faluco@1541: m_bAssertOnOverflow = true; faluco@1541: m_pDebugName = NULL; faluco@1541: } faluco@1541: faluco@1541: bf_read::bf_read( const void *pData, int nBytes, int nBits ) faluco@1541: { faluco@1541: m_bAssertOnOverflow = true; faluco@1541: StartReading( pData, nBytes, 0, nBits ); faluco@1541: } faluco@1541: faluco@1541: bf_read::bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits ) faluco@1541: { faluco@1541: m_bAssertOnOverflow = true; faluco@1541: m_pDebugName = pDebugName; faluco@1541: StartReading( pData, nBytes, 0, nBits ); faluco@1541: } faluco@1541: faluco@1541: void bf_read::StartReading( const void *pData, int nBytes, int iStartBit, int nBits ) faluco@1541: { faluco@1541: // Make sure we're dword aligned. faluco@1541: Assert(((unsigned long)pData & 3) == 0); faluco@1541: faluco@1541: m_pData = (unsigned char*)pData; faluco@1541: m_nDataBytes = nBytes; faluco@1541: faluco@1541: if ( nBits == -1 ) faluco@1541: { faluco@1541: m_nDataBits = m_nDataBytes << 3; faluco@1541: } faluco@1541: else faluco@1541: { faluco@1541: Assert( nBits <= nBytes*8 ); faluco@1541: m_nDataBits = nBits; faluco@1541: } faluco@1541: faluco@1541: m_iCurBit = iStartBit; faluco@1541: m_bOverflow = false; faluco@1541: } faluco@1541: faluco@1541: void bf_read::Reset() faluco@1541: { faluco@1541: m_iCurBit = 0; faluco@1541: m_bOverflow = false; faluco@1541: } faluco@1541: faluco@1541: void bf_read::SetAssertOnOverflow( bool bAssert ) faluco@1541: { faluco@1541: m_bAssertOnOverflow = bAssert; faluco@1541: } faluco@1541: faluco@1541: const char* bf_read::GetDebugName() faluco@1541: { faluco@1541: return m_pDebugName; faluco@1541: } faluco@1541: faluco@1541: void bf_read::SetDebugName( const char *pName ) faluco@1541: { faluco@1541: m_pDebugName = pName; faluco@1541: } faluco@1541: faluco@1541: unsigned int bf_read::CheckReadUBitLong(int numbits) faluco@1541: { faluco@1541: // Ok, just read bits out. faluco@1541: int i, nBitValue; faluco@1541: unsigned int r = 0; faluco@1541: faluco@1541: for(i=0; i < numbits; i++) faluco@1541: { faluco@1541: nBitValue = ReadOneBitNoCheck(); faluco@1541: r |= nBitValue << i; faluco@1541: } faluco@1541: m_iCurBit -= numbits; faluco@1541: faluco@1541: return r; faluco@1541: } faluco@1541: faluco@1541: bool bf_read::ReadBits(void *pOutData, int nBits) faluco@1541: { faluco@1541: #if defined( BB_PROFILING ) faluco@1541: VPROF( "bf_write::ReadBits" ); faluco@1541: #endif faluco@1541: faluco@1541: unsigned char *pOut = (unsigned char*)pOutData; faluco@1541: int nBitsLeft = nBits; faluco@1541: faluco@1541: faluco@1541: // Get output dword-aligned. faluco@1541: while(((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8) faluco@1541: { faluco@1541: *pOut = (unsigned char)ReadUBitLong(8); faluco@1541: ++pOut; faluco@1541: nBitsLeft -= 8; faluco@1541: } faluco@1541: faluco@1541: // Read dwords. faluco@1541: while(nBitsLeft >= 32) faluco@1541: { faluco@1541: *((unsigned long*)pOut) = ReadUBitLong(32); faluco@1541: pOut += sizeof(unsigned long); faluco@1541: nBitsLeft -= 32; faluco@1541: } faluco@1541: faluco@1541: // Read the remaining bytes. faluco@1541: while(nBitsLeft >= 8) faluco@1541: { faluco@1541: *pOut = ReadUBitLong(8); faluco@1541: ++pOut; faluco@1541: nBitsLeft -= 8; faluco@1541: } faluco@1541: faluco@1541: // Read the remaining bits. faluco@1541: if(nBitsLeft) faluco@1541: { faluco@1541: *pOut = ReadUBitLong(nBitsLeft); faluco@1541: } faluco@1541: faluco@1541: return !IsOverflowed(); faluco@1541: } faluco@1541: faluco@1541: float bf_read::ReadBitAngle( int numbits ) faluco@1541: { faluco@1541: float fReturn; faluco@1541: int i; faluco@1541: float shift; faluco@1541: faluco@1541: shift = (float)( 1 << numbits ); faluco@1541: faluco@1541: i = ReadUBitLong( numbits ); faluco@1541: fReturn = (float)i * (360.0 / shift); faluco@1541: faluco@1541: return fReturn; faluco@1541: } faluco@1541: faluco@1541: unsigned int bf_read::PeekUBitLong( int numbits ) faluco@1541: { faluco@1541: unsigned int r; faluco@1541: int i, nBitValue; faluco@1541: #ifdef BIT_VERBOSE faluco@1541: int nShifts = numbits; faluco@1541: #endif faluco@1541: faluco@1541: bf_read savebf; faluco@1541: faluco@1541: savebf = *this; // Save current state info faluco@1541: faluco@1541: r = 0; faluco@1541: for(i=0; i < numbits; i++) faluco@1541: { faluco@1541: nBitValue = ReadOneBit(); faluco@1541: faluco@1541: // Append to current stream faluco@1541: if ( nBitValue ) faluco@1541: { faluco@1541: r |= 1 << i; faluco@1541: } faluco@1541: } faluco@1541: faluco@1541: *this = savebf; faluco@1541: faluco@1541: #ifdef BIT_VERBOSE faluco@1541: Con_Printf( "PeekBitLong: %i %i\n", nShifts, (unsigned int)r ); faluco@1541: #endif faluco@1541: faluco@1541: return r; faluco@1541: } faluco@1541: faluco@1541: // Append numbits least significant bits from data to the current bit stream faluco@1541: int bf_read::ReadSBitLong( int numbits ) faluco@1541: { faluco@1541: int r, sign; faluco@1541: faluco@1541: r = ReadUBitLong(numbits - 1); faluco@1541: faluco@1541: // Note: it does this wierdness here so it's bit-compatible with regular integer data in the buffer. faluco@1541: // (Some old code writes direct integers right into the buffer). faluco@1541: sign = ReadOneBit(); faluco@1541: if(sign) faluco@1541: r = -((1 << (numbits-1)) - r); faluco@1541: faluco@1541: return r; faluco@1541: } faluco@1541: faluco@1541: unsigned int bf_read::ReadUBitVar() faluco@1541: { faluco@1541: int bits = 0; // how many bits are used to encode delta offset faluco@1541: faluco@1541: // how many bits do we use faluco@1541: while ( ReadOneBit() == 0 ) faluco@1541: bits++; faluco@1541: faluco@1541: unsigned int data = (1< 0) faluco@1541: data += ReadUBitLong( bits ); faluco@1541: faluco@1541: return data; faluco@1541: } faluco@1541: faluco@1541: faluco@1541: unsigned int bf_read::ReadBitLong(int numbits, bool bSigned) faluco@1541: { faluco@1541: if(bSigned) faluco@1541: return (unsigned int)ReadSBitLong(numbits); faluco@1541: else faluco@1541: return ReadUBitLong(numbits); faluco@1541: } faluco@1541: faluco@1541: faluco@1541: // Basic Coordinate Routines (these contain bit-field size AND fixed point scaling constants) faluco@1541: float bf_read::ReadBitCoord (void) faluco@1541: { faluco@1541: #if defined( BB_PROFILING ) faluco@1541: VPROF( "bf_write::ReadBitCoord" ); faluco@1541: #endif faluco@1541: int intval=0,fractval=0,signbit=0; faluco@1541: float value = 0.0; faluco@1541: faluco@1541: faluco@1541: // Read the required integer and fraction flags faluco@1541: intval = ReadOneBit(); faluco@1541: fractval = ReadOneBit(); faluco@1541: faluco@1541: // If we got either parse them, otherwise it's a zero. faluco@1541: if ( intval || fractval ) faluco@1541: { faluco@1541: // Read the sign bit faluco@1541: signbit = ReadOneBit(); faluco@1541: faluco@1541: // If there's an integer, read it in faluco@1541: if ( intval ) faluco@1541: { faluco@1541: // Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE] faluco@1541: intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1; faluco@1541: } faluco@1541: faluco@1541: // If there's a fraction, read it in faluco@1541: if ( fractval ) faluco@1541: { faluco@1541: fractval = ReadUBitLong( COORD_FRACTIONAL_BITS ); faluco@1541: } faluco@1541: faluco@1541: // Calculate the correct floating point value faluco@1541: value = intval + ((float)fractval * COORD_RESOLUTION); faluco@1541: faluco@1541: // Fixup the sign if negative. faluco@1541: if ( signbit ) faluco@1541: value = -value; faluco@1541: } faluco@1541: faluco@1541: return value; faluco@1541: } faluco@1541: faluco@1541: void bf_read::ReadBitVec3Coord( Vector& fa ) faluco@1541: { faluco@1541: int xflag, yflag, zflag; faluco@1541: faluco@1541: // This vector must be initialized! Otherwise, If any of the flags aren't set, faluco@1541: // the corresponding component will not be read and will be stack garbage. faluco@1541: fa.Init( 0, 0, 0 ); faluco@1541: faluco@1541: xflag = ReadOneBit(); faluco@1541: yflag = ReadOneBit(); faluco@1541: zflag = ReadOneBit(); faluco@1541: faluco@1541: if ( xflag ) faluco@1541: fa[0] = ReadBitCoord(); faluco@1541: if ( yflag ) faluco@1541: fa[1] = ReadBitCoord(); faluco@1541: if ( zflag ) faluco@1541: fa[2] = ReadBitCoord(); faluco@1541: } faluco@1541: faluco@1541: float bf_read::ReadBitNormal (void) faluco@1541: { faluco@1541: // Read the sign bit faluco@1541: int signbit = ReadOneBit(); faluco@1541: faluco@1541: // Read the fractional part faluco@1541: unsigned int fractval = ReadUBitLong( NORMAL_FRACTIONAL_BITS ); faluco@1541: faluco@1541: // Calculate the correct floating point value faluco@1541: float value = (float)fractval * NORMAL_RESOLUTION; faluco@1541: faluco@1541: // Fixup the sign if negative. faluco@1541: if ( signbit ) faluco@1541: value = -value; faluco@1541: faluco@1541: return value; faluco@1541: } faluco@1541: faluco@1541: void bf_read::ReadBitVec3Normal( Vector& fa ) faluco@1541: { faluco@1541: int xflag = ReadOneBit(); faluco@1541: int yflag = ReadOneBit(); faluco@1541: faluco@1541: if (xflag) faluco@1541: fa[0] = ReadBitNormal(); faluco@1541: else faluco@1541: fa[0] = 0.0f; faluco@1541: faluco@1541: if (yflag) faluco@1541: fa[1] = ReadBitNormal(); faluco@1541: else faluco@1541: fa[1] = 0.0f; faluco@1541: faluco@1541: // The first two imply the third (but not its sign) faluco@1541: int znegative = ReadOneBit(); faluco@1541: faluco@1541: float fafafbfb = fa[0] * fa[0] + fa[1] * fa[1]; faluco@1541: if (fafafbfb < 1.0f) faluco@1541: fa[2] = sqrt( 1.0f - fafafbfb ); faluco@1541: else faluco@1541: fa[2] = 0.0f; faluco@1541: faluco@1541: if (znegative) faluco@1541: fa[2] = -fa[2]; faluco@1541: } faluco@1541: faluco@1541: void bf_read::ReadBitAngles( QAngle& fa ) faluco@1541: { faluco@1541: Vector tmp; faluco@1541: ReadBitVec3Coord( tmp ); faluco@1541: fa.Init( tmp.x, tmp.y, tmp.z ); faluco@1541: } faluco@1541: faluco@1541: int bf_read::ReadChar() faluco@1541: { faluco@1541: return ReadSBitLong(sizeof(char) << 3); faluco@1541: } faluco@1541: faluco@1541: int bf_read::ReadByte() faluco@1541: { faluco@1541: return ReadUBitLong(sizeof(unsigned char) << 3); faluco@1541: } faluco@1541: faluco@1541: int bf_read::ReadShort() faluco@1541: { faluco@1541: return ReadSBitLong(sizeof(short) << 3); faluco@1541: } faluco@1541: faluco@1541: int bf_read::ReadWord() faluco@1541: { faluco@1541: return ReadUBitLong(sizeof(unsigned short) << 3); faluco@1541: } faluco@1541: faluco@1541: long bf_read::ReadLong() faluco@1541: { faluco@1541: return ReadSBitLong(sizeof(long) << 3); faluco@1541: } faluco@1541: faluco@1541: float bf_read::ReadFloat() faluco@1541: { faluco@1541: float ret; faluco@1541: Assert( sizeof(ret) == 4 ); faluco@1541: ReadBits(&ret, 32); faluco@1541: return ret; faluco@1541: } faluco@1541: faluco@1541: bool bf_read::ReadBytes(void *pOut, int nBytes) faluco@1541: { faluco@1541: return ReadBits(pOut, nBytes << 3); faluco@1541: } faluco@1541: faluco@1541: bool bf_read::ReadString( char *pStr, int maxLen, bool bLine, int *pOutNumChars ) faluco@1541: { faluco@1541: Assert( maxLen != 0 ); faluco@1541: faluco@1541: bool bTooSmall = false; faluco@1541: int iChar = 0; faluco@1541: while(1) faluco@1541: { faluco@1541: char val = ReadChar(); faluco@1541: if ( val == 0 ) faluco@1541: break; faluco@1541: else if ( bLine && val == '\n' ) faluco@1541: break; faluco@1541: faluco@1541: if ( iChar < (maxLen-1) ) faluco@1541: { faluco@1541: pStr[iChar] = val; faluco@1541: ++iChar; faluco@1541: } faluco@1541: else faluco@1541: { faluco@1541: bTooSmall = true; faluco@1541: } faluco@1541: } faluco@1541: faluco@1541: // Make sure it's null-terminated. faluco@1541: Assert( iChar < maxLen ); faluco@1541: pStr[iChar] = 0; faluco@1541: faluco@1541: if ( pOutNumChars ) faluco@1541: *pOutNumChars = iChar; faluco@1541: faluco@1541: return !IsOverflowed() && !bTooSmall; faluco@1541: } faluco@1541: faluco@1541: faluco@1541: char* bf_read::ReadAndAllocateString( bool *pOverflow ) faluco@1541: { faluco@1541: char str[2048]; faluco@1541: faluco@1541: int nChars; faluco@1541: bool bOverflow = !ReadString( str, sizeof( str ), false, &nChars ); faluco@1541: if ( pOverflow ) faluco@1541: *pOverflow = bOverflow; faluco@1541: faluco@1541: // Now copy into the output and return it; faluco@1541: char *pRet = new char[ nChars + 1 ]; faluco@1541: for ( int i=0; i <= nChars; i++ ) faluco@1541: pRet[i] = str[i]; faluco@1541: faluco@1541: return pRet; faluco@1541: } faluco@1541: faluco@1541: faluco@1541: bool bf_read::Seek(int iBit) faluco@1541: { faluco@1541: if(iBit < 0) faluco@1541: { faluco@1541: SetOverflowFlag(); faluco@1541: m_iCurBit = m_nDataBits; faluco@1541: return false; faluco@1541: } faluco@1541: else if(iBit > m_nDataBits) faluco@1541: { faluco@1541: SetOverflowFlag(); faluco@1541: m_iCurBit = m_nDataBits; faluco@1541: return false; faluco@1541: } faluco@1541: else faluco@1541: { faluco@1541: m_iCurBit = iBit; faluco@1541: return true; faluco@1541: } faluco@1541: } faluco@1541: faluco@1541: void bf_read::ExciseBits( int startbit, int bitstoremove ) faluco@1541: { faluco@1541: int endbit = startbit + bitstoremove; faluco@1541: int remaining_to_end = m_nDataBits - endbit; faluco@1541: faluco@1541: bf_write temp; faluco@1541: temp.StartWriting( (void *)m_pData, m_nDataBits << 3, startbit ); faluco@1541: faluco@1541: Seek( endbit ); faluco@1541: faluco@1541: for ( int i = 0; i < remaining_to_end; i++ ) faluco@1541: { faluco@1541: temp.WriteOneBit( ReadOneBit() ); faluco@1541: } faluco@1541: faluco@1541: Seek( startbit ); faluco@1541: faluco@1541: m_nDataBits -= bitstoremove; faluco@1541: m_nDataBytes = m_nDataBits >> 3; faluco@1541: }