Non-initial commit
This commit is contained in:
parent
347f2c439c
commit
65810867d8
3
.gitignore
vendored
3
.gitignore
vendored
@ -26,3 +26,6 @@
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Generated Project Files
|
||||
premake/*/
|
||||
|
20
demboyz/demboyz.cpp
Normal file
20
demboyz/demboyz.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
#include "demofile.h"
|
||||
|
||||
int main(const int argc, const char* argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
CDemoFile demoFile;
|
||||
if (!demoFile.Open(argv[1]))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
demoFile.Close();
|
||||
|
||||
return 0;
|
||||
}
|
192
demboyz/demofile.cpp
Normal file
192
demboyz/demofile.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
//====== Copyright (c) 2014, Valve Corporation, All rights reserved. ========//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//===========================================================================//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstring>
|
||||
#include <assert.h>
|
||||
#include "demofile.h"
|
||||
|
||||
CDemoFile::CDemoFile()
|
||||
{
|
||||
}
|
||||
|
||||
CDemoFile::~CDemoFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void CDemoFile::ReadSequenceInfo( int32 &nSeqNrIn, int32 &nSeqNrOut )
|
||||
{
|
||||
if ( !m_fileBuffer.size() )
|
||||
return;
|
||||
|
||||
nSeqNrIn = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
|
||||
m_fileBufferPos += sizeof( int32 );
|
||||
nSeqNrOut = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
|
||||
m_fileBufferPos += sizeof( int32 );
|
||||
}
|
||||
|
||||
void CDemoFile::ReadCmdInfo( democmdinfo_t& info )
|
||||
{
|
||||
if ( !m_fileBuffer.size() )
|
||||
return;
|
||||
|
||||
memcpy( &info, &m_fileBuffer[ m_fileBufferPos ], sizeof( democmdinfo_t ) );
|
||||
m_fileBufferPos += sizeof( democmdinfo_t );
|
||||
}
|
||||
|
||||
void CDemoFile::ReadCmdHeader( unsigned char& cmd, int32& tick, unsigned char& playerSlot )
|
||||
{
|
||||
if ( !m_fileBuffer.size() )
|
||||
return;
|
||||
|
||||
// Read the command
|
||||
cmd = *( unsigned char * )( &m_fileBuffer[ m_fileBufferPos ] );
|
||||
m_fileBufferPos += sizeof( unsigned char );
|
||||
|
||||
if ( cmd <=0 )
|
||||
{
|
||||
fprintf( stderr, "CDemoFile::ReadCmdHeader: Missing end tag in demo file.\n");
|
||||
cmd = dem_stop;
|
||||
return;
|
||||
}
|
||||
|
||||
assert( cmd >= 1 && cmd <= dem_lastcmd );
|
||||
|
||||
// Read the timestamp
|
||||
tick = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
|
||||
m_fileBufferPos += sizeof( int32 );
|
||||
|
||||
// read playerslot
|
||||
playerSlot = *( unsigned char * )( &m_fileBuffer[ m_fileBufferPos ] );
|
||||
m_fileBufferPos += sizeof( unsigned char );
|
||||
}
|
||||
|
||||
int32 CDemoFile::ReadUserCmd( char *buffer, int32 &size )
|
||||
{
|
||||
if ( !m_fileBuffer.size() )
|
||||
return 0;
|
||||
|
||||
int32 outgoing_sequence = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
|
||||
m_fileBufferPos += sizeof( int32 );
|
||||
|
||||
size = ReadRawData( buffer, size );
|
||||
|
||||
return outgoing_sequence;
|
||||
}
|
||||
|
||||
int32 CDemoFile::ReadRawData( char *buffer, int32 length )
|
||||
{
|
||||
if ( !m_fileBuffer.size() )
|
||||
return 0;
|
||||
|
||||
// read length of data block
|
||||
int32 size = *( int32 * )( &m_fileBuffer[ m_fileBufferPos ] );
|
||||
m_fileBufferPos += sizeof( int32 );
|
||||
|
||||
if ( buffer && (length < size) )
|
||||
{
|
||||
fprintf( stderr, "CDemoFile::ReadRawData: buffer overflow (%i).\n", size );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( buffer )
|
||||
{
|
||||
// read data into buffer
|
||||
memcpy( buffer, &m_fileBuffer[ m_fileBufferPos ], size );
|
||||
m_fileBufferPos += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// just skip it
|
||||
m_fileBufferPos += size;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool CDemoFile::Open( const char *name )
|
||||
{
|
||||
Close();
|
||||
|
||||
FILE *fp = NULL;
|
||||
fp = fopen( name, "rb" );
|
||||
if( fp )
|
||||
{
|
||||
size_t Length;
|
||||
|
||||
fseek( fp, 0, SEEK_END );
|
||||
Length = ftell( fp );
|
||||
fseek( fp, 0, SEEK_SET );
|
||||
|
||||
if( Length < sizeof( m_DemoHeader ) )
|
||||
{
|
||||
fprintf( stderr, "CDemoFile::Open: file too small. %s.\n", name );
|
||||
fclose( fp );
|
||||
return false;
|
||||
}
|
||||
|
||||
fread( &m_DemoHeader, 1, sizeof( m_DemoHeader ), fp );
|
||||
Length -= sizeof( m_DemoHeader );
|
||||
|
||||
if ( strcmp ( m_DemoHeader.demofilestamp, DEMO_HEADER_ID ) )
|
||||
{
|
||||
fprintf( stderr, "CDemoFile::Open: %s has invalid demo header ID.\n", m_szFileName.c_str() );
|
||||
fclose( fp );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( m_DemoHeader.demoprotocol != DEMO_PROTOCOL )
|
||||
{
|
||||
fprintf( stderr, "CDemoFile::Open: demo file protocol %i invalid, expected version is %i \n", m_DemoHeader.demoprotocol, DEMO_PROTOCOL );
|
||||
fclose( fp );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fileBuffer.resize( Length );
|
||||
fread( &m_fileBuffer[ 0 ], 1, Length, fp );
|
||||
|
||||
fclose( fp );
|
||||
fp = NULL;
|
||||
}
|
||||
|
||||
if ( !m_fileBuffer.size() )
|
||||
{
|
||||
fprintf( stderr, "CDemoFile::Open: couldn't open file %s.\n", name );
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fileBufferPos = 0;
|
||||
m_szFileName = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDemoFile::Close()
|
||||
{
|
||||
m_szFileName.clear();
|
||||
|
||||
m_fileBufferPos = 0;
|
||||
m_fileBuffer.clear();
|
||||
}
|
251
demboyz/demofile.h
Normal file
251
demboyz/demofile.h
Normal file
@ -0,0 +1,251 @@
|
||||
//====== Copyright (c) 2014, Valve Corporation, All rights reserved. ========//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef DEMOFILE_H
|
||||
#define DEMOFILE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <inttypes.h>
|
||||
|
||||
#define DEMO_HEADER_ID "HL2DEMO"
|
||||
#define DEMO_PROTOCOL 4
|
||||
|
||||
#if !defined( MAX_OSPATH )
|
||||
#define MAX_OSPATH 260 // max length of a filesystem pathname
|
||||
#endif
|
||||
|
||||
typedef int32_t int32;
|
||||
typedef uint32_t uint32;
|
||||
typedef int64_t int64;
|
||||
typedef uint64_t uint64;
|
||||
typedef unsigned long CRC32_t;
|
||||
|
||||
// Demo messages
|
||||
enum
|
||||
{
|
||||
// it's a startup message, process as fast as possible
|
||||
dem_signon = 1,
|
||||
// it's a normal network packet that we stored off
|
||||
dem_packet,
|
||||
// sync client clock to demo tick
|
||||
dem_synctick,
|
||||
// console command
|
||||
dem_consolecmd,
|
||||
// user input command
|
||||
dem_usercmd,
|
||||
// network data tables
|
||||
dem_datatables,
|
||||
// end of time.
|
||||
dem_stop,
|
||||
// a blob of binary data understood by a callback function
|
||||
dem_customdata,
|
||||
|
||||
dem_stringtables,
|
||||
|
||||
// Last command
|
||||
dem_lastcmd = dem_stringtables
|
||||
};
|
||||
|
||||
struct demoheader_t
|
||||
{
|
||||
char demofilestamp[ 8 ]; // Should be HL2DEMO
|
||||
int32 demoprotocol; // Should be DEMO_PROTOCOL
|
||||
int32 networkprotocol; // Should be PROTOCOL_VERSION
|
||||
char servername[ MAX_OSPATH ]; // Name of server
|
||||
char clientname[ MAX_OSPATH ]; // Name of client who recorded the game
|
||||
char mapname[ MAX_OSPATH ]; // Name of map
|
||||
char gamedirectory[ MAX_OSPATH ]; // Name of game directory (com_gamedir)
|
||||
float playback_time; // Time of track
|
||||
int32 playback_ticks; // # of ticks in track
|
||||
int32 playback_frames; // # of frames in track
|
||||
int32 signonlength; // length of sigondata in bytes
|
||||
};
|
||||
|
||||
#define FDEMO_NORMAL 0
|
||||
#define FDEMO_USE_ORIGIN2 ( 1 << 0 )
|
||||
#define FDEMO_USE_ANGLES2 ( 1 << 1 )
|
||||
#define FDEMO_NOINTERP ( 1 << 2 ) // don't interpolate between this an last view
|
||||
|
||||
#define MAX_SPLITSCREEN_CLIENTS 2
|
||||
|
||||
struct QAngle
|
||||
{
|
||||
float x, y, z;
|
||||
void Init( void )
|
||||
{
|
||||
x = y = z = 0.0f;
|
||||
}
|
||||
void Init( float _x, float _y, float _z )
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
};
|
||||
struct Vector
|
||||
{
|
||||
float x, y, z;
|
||||
void Init( void )
|
||||
{
|
||||
x = y = z = 0.0f;
|
||||
}
|
||||
void Init( float _x, float _y, float _z )
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
};
|
||||
|
||||
struct democmdinfo_t
|
||||
{
|
||||
democmdinfo_t( void )
|
||||
{
|
||||
}
|
||||
|
||||
struct Split_t
|
||||
{
|
||||
Split_t( void )
|
||||
{
|
||||
flags = FDEMO_NORMAL;
|
||||
viewOrigin.Init();
|
||||
viewAngles.Init();
|
||||
localViewAngles.Init();
|
||||
|
||||
// Resampled origin/angles
|
||||
viewOrigin2.Init();
|
||||
viewAngles2.Init();
|
||||
localViewAngles2.Init();
|
||||
}
|
||||
|
||||
Split_t& operator=( const Split_t& src )
|
||||
{
|
||||
if ( this == &src )
|
||||
return *this;
|
||||
|
||||
flags = src.flags;
|
||||
viewOrigin = src.viewOrigin;
|
||||
viewAngles = src.viewAngles;
|
||||
localViewAngles = src.localViewAngles;
|
||||
viewOrigin2 = src.viewOrigin2;
|
||||
viewAngles2 = src.viewAngles2;
|
||||
localViewAngles2 = src.localViewAngles2;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vector& GetViewOrigin( void )
|
||||
{
|
||||
if ( flags & FDEMO_USE_ORIGIN2 )
|
||||
{
|
||||
return viewOrigin2;
|
||||
}
|
||||
return viewOrigin;
|
||||
}
|
||||
|
||||
const QAngle& GetViewAngles( void )
|
||||
{
|
||||
if ( flags & FDEMO_USE_ANGLES2 )
|
||||
{
|
||||
return viewAngles2;
|
||||
}
|
||||
return viewAngles;
|
||||
}
|
||||
const QAngle& GetLocalViewAngles( void )
|
||||
{
|
||||
if ( flags & FDEMO_USE_ANGLES2 )
|
||||
{
|
||||
return localViewAngles2;
|
||||
}
|
||||
return localViewAngles;
|
||||
}
|
||||
|
||||
void Reset( void )
|
||||
{
|
||||
flags = 0;
|
||||
viewOrigin2 = viewOrigin;
|
||||
viewAngles2 = viewAngles;
|
||||
localViewAngles2 = localViewAngles;
|
||||
}
|
||||
|
||||
int32 flags;
|
||||
|
||||
// original origin/viewangles
|
||||
Vector viewOrigin;
|
||||
QAngle viewAngles;
|
||||
QAngle localViewAngles;
|
||||
|
||||
// Resampled origin/viewangles
|
||||
Vector viewOrigin2;
|
||||
QAngle viewAngles2;
|
||||
QAngle localViewAngles2;
|
||||
};
|
||||
|
||||
void Reset( void )
|
||||
{
|
||||
for ( int i = 0; i < MAX_SPLITSCREEN_CLIENTS; ++i )
|
||||
{
|
||||
u[ i ].Reset();
|
||||
}
|
||||
}
|
||||
|
||||
Split_t u[ MAX_SPLITSCREEN_CLIENTS ];
|
||||
};
|
||||
|
||||
class CDemoFile
|
||||
{
|
||||
public:
|
||||
CDemoFile();
|
||||
virtual ~CDemoFile();
|
||||
|
||||
bool Open( const char *name );
|
||||
void Close();
|
||||
|
||||
int32 ReadRawData( char *buffer, int32 length );
|
||||
|
||||
void ReadSequenceInfo( int32 &nSeqNrIn, int32 &nSeqNrOutAck );
|
||||
|
||||
void ReadCmdInfo( democmdinfo_t& info );
|
||||
|
||||
void ReadCmdHeader( unsigned char &cmd, int32 &tick, unsigned char& playerSlot );
|
||||
|
||||
int32 ReadUserCmd( char *buffer, int32 &size );
|
||||
|
||||
demoheader_t *ReadDemoHeader();
|
||||
|
||||
public:
|
||||
demoheader_t m_DemoHeader; //general demo info
|
||||
|
||||
std::string m_szFileName;
|
||||
|
||||
size_t m_fileBufferPos;
|
||||
std::string m_fileBuffer;
|
||||
};
|
||||
|
||||
#endif // DEMOFILE_H
|
691
demboyz/demofilebitbuf.cpp
Normal file
691
demboyz/demofilebitbuf.cpp
Normal file
@ -0,0 +1,691 @@
|
||||
//====== Copyright (c) 2014, Valve Corporation, All rights reserved. ========//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//===========================================================================//
|
||||
|
||||
#include <assert.h>
|
||||
#include "demofilebitbuf.h"
|
||||
|
||||
const uint32 CBitRead::s_nMaskTable[33] = {
|
||||
0,
|
||||
( 1 << 1 ) - 1,
|
||||
( 1 << 2 ) - 1,
|
||||
( 1 << 3 ) - 1,
|
||||
( 1 << 4 ) - 1,
|
||||
( 1 << 5 ) - 1,
|
||||
( 1 << 6 ) - 1,
|
||||
( 1 << 7 ) - 1,
|
||||
( 1 << 8 ) - 1,
|
||||
( 1 << 9 ) - 1,
|
||||
( 1 << 10 ) - 1,
|
||||
( 1 << 11 ) - 1,
|
||||
( 1 << 12 ) - 1,
|
||||
( 1 << 13 ) - 1,
|
||||
( 1 << 14 ) - 1,
|
||||
( 1 << 15 ) - 1,
|
||||
( 1 << 16 ) - 1,
|
||||
( 1 << 17 ) - 1,
|
||||
( 1 << 18 ) - 1,
|
||||
( 1 << 19 ) - 1,
|
||||
( 1 << 20 ) - 1,
|
||||
( 1 << 21 ) - 1,
|
||||
( 1 << 22 ) - 1,
|
||||
( 1 << 23 ) - 1,
|
||||
( 1 << 24 ) - 1,
|
||||
( 1 << 25 ) - 1,
|
||||
( 1 << 26 ) - 1,
|
||||
( 1 << 27 ) - 1,
|
||||
( 1 << 28 ) - 1,
|
||||
( 1 << 29 ) - 1,
|
||||
( 1 << 30 ) - 1,
|
||||
0x7fffffff,
|
||||
0xffffffff,
|
||||
};
|
||||
|
||||
int CBitRead::GetNumBitsRead( void ) const
|
||||
{
|
||||
if ( ! m_pData ) // pesky null ptr bitbufs. these happen.
|
||||
return 0;
|
||||
|
||||
int nCurOfs = ( ( int( m_pDataIn ) - int( m_pData ) ) / 4 ) - 1;
|
||||
nCurOfs *= 32;
|
||||
nCurOfs += ( 32 - m_nBitsAvail );
|
||||
int nAdjust = 8 * ( m_nDataBytes & 3 );
|
||||
return MIN( nCurOfs + nAdjust, m_nDataBits );
|
||||
}
|
||||
|
||||
int CBitRead::GetNumBytesRead( void ) const
|
||||
{
|
||||
return ( ( GetNumBitsRead() + 7 ) >> 3 );
|
||||
}
|
||||
|
||||
void CBitRead::GrabNextDWord( bool bOverFlowImmediately )
|
||||
{
|
||||
if ( m_pDataIn == m_pBufferEnd )
|
||||
{
|
||||
m_nBitsAvail = 1; // so that next read will run out of words
|
||||
m_nInBufWord = 0;
|
||||
m_pDataIn++; // so seek count increments like old
|
||||
if ( bOverFlowImmediately )
|
||||
{
|
||||
SetOverflowFlag();
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( m_pDataIn > m_pBufferEnd )
|
||||
{
|
||||
SetOverflowFlag();
|
||||
m_nInBufWord = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( reinterpret_cast< int >( m_pDataIn ) + 3 < reinterpret_cast< int >( m_pBufferEnd ) );
|
||||
m_nInBufWord = *( m_pDataIn++ );
|
||||
}
|
||||
}
|
||||
|
||||
void CBitRead::FetchNext( void )
|
||||
{
|
||||
m_nBitsAvail = 32;
|
||||
GrabNextDWord( false );
|
||||
}
|
||||
|
||||
int CBitRead::ReadOneBit( void )
|
||||
{
|
||||
int nRet = m_nInBufWord & 1;
|
||||
if ( --m_nBitsAvail == 0 )
|
||||
{
|
||||
FetchNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nInBufWord >>= 1;
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
// need to merge words
|
||||
unsigned int nRet = m_nInBufWord;
|
||||
numbits -= m_nBitsAvail;
|
||||
GrabNextDWord( true );
|
||||
if ( m_bOverflow )
|
||||
return 0;
|
||||
nRet |= ( ( m_nInBufWord & s_nMaskTable[ numbits ] ) << m_nBitsAvail );
|
||||
m_nBitsAvail = 32 - numbits;
|
||||
m_nInBufWord >>= numbits;
|
||||
return nRet;
|
||||
}
|
||||
}
|
||||
|
||||
int CBitRead::ReadSBitLong( int numbits )
|
||||
{
|
||||
int nRet = ReadUBitLong( numbits );
|
||||
// sign extend
|
||||
return ( nRet << ( 32 - numbits ) ) >> ( 32 - numbits );
|
||||
}
|
||||
|
||||
#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
|
||||
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
|
||||
|
||||
int CBitRead::ReadChar( void )
|
||||
{
|
||||
return ReadSBitLong( sizeof( char ) << 3 );
|
||||
}
|
||||
|
||||
int CBitRead::ReadByte( void )
|
||||
{
|
||||
return ReadUBitLong( sizeof( unsigned char ) << 3 );
|
||||
}
|
||||
|
||||
int CBitRead::ReadShort( void )
|
||||
{
|
||||
return ReadSBitLong( sizeof( short ) << 3 );
|
||||
}
|
||||
|
||||
int CBitRead::ReadWord( void )
|
||||
{
|
||||
return ReadUBitLong( sizeof( unsigned short ) << 3 );
|
||||
}
|
||||
|
||||
bool CBitRead::Seek( int nPosition )
|
||||
{
|
||||
bool bSucc = true;
|
||||
if ( nPosition < 0 || nPosition > m_nDataBits )
|
||||
{
|
||||
SetOverflowFlag();
|
||||
bSucc = false;
|
||||
nPosition = m_nDataBits;
|
||||
}
|
||||
int nHead = m_nDataBytes & 3; // non-multiple-of-4 bytes at head of buffer. We put the "round off"
|
||||
// at the head to make reading and detecting the end efficient.
|
||||
|
||||
int nByteOfs = nPosition / 8;
|
||||
if ( ( m_nDataBytes < 4 ) || ( nHead && ( nByteOfs < nHead ) ) )
|
||||
{
|
||||
// partial first dword
|
||||
unsigned char const *pPartial = ( unsigned char const *) m_pData;
|
||||
if ( m_pData )
|
||||
{
|
||||
m_nInBufWord = *( pPartial++ );
|
||||
if ( nHead > 1 )
|
||||
{
|
||||
m_nInBufWord |= ( *pPartial++ ) << 8;
|
||||
}
|
||||
if ( nHead > 2 )
|
||||
{
|
||||
m_nInBufWord |= ( *pPartial++ ) << 16;
|
||||
}
|
||||
}
|
||||
m_pDataIn = ( uint32 const * ) pPartial;
|
||||
m_nInBufWord >>= ( nPosition & 31 );
|
||||
m_nBitsAvail = ( nHead << 3 ) - ( nPosition & 31 );
|
||||
}
|
||||
else
|
||||
{
|
||||
int nAdjPosition = nPosition - ( nHead << 3 );
|
||||
m_pDataIn = reinterpret_cast< uint32 const * > ( reinterpret_cast< unsigned char const * >( m_pData ) + ( ( nAdjPosition / 32 ) << 2 ) + nHead );
|
||||
if ( m_pData )
|
||||
{
|
||||
m_nBitsAvail = 32;
|
||||
GrabNextDWord();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nInBufWord = 0;
|
||||
m_nBitsAvail = 1;
|
||||
}
|
||||
m_nInBufWord >>= ( nAdjPosition & 31 );
|
||||
m_nBitsAvail = MIN( m_nBitsAvail, 32 - ( nAdjPosition & 31 ) ); // in case grabnextdword overflowed
|
||||
}
|
||||
return bSucc;
|
||||
}
|
||||
|
||||
|
||||
void CBitRead::StartReading( const void *pData, int nBytes, int iStartBit, int nBits )
|
||||
{
|
||||
// Make sure it's dword aligned and padded.
|
||||
assert( ( ( unsigned long )pData & 3 ) == 0 );
|
||||
m_pData = ( uint32 * ) pData;
|
||||
m_pDataIn = m_pData;
|
||||
m_nDataBytes = nBytes;
|
||||
|
||||
if ( nBits == -1 )
|
||||
{
|
||||
m_nDataBits = nBytes << 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( nBits <= nBytes * 8 );
|
||||
m_nDataBits = nBits;
|
||||
}
|
||||
m_bOverflow = false;
|
||||
m_pBufferEnd = reinterpret_cast< uint32 const * > ( reinterpret_cast< unsigned char const * >( m_pData ) + nBytes );
|
||||
if ( m_pData )
|
||||
{
|
||||
Seek( iStartBit );
|
||||
}
|
||||
}
|
||||
|
||||
bool CBitRead::ReadString( char *pStr, int maxLen, bool bLine, int *pOutNumChars )
|
||||
{
|
||||
assert( maxLen != 0 );
|
||||
|
||||
bool bTooSmall = false;
|
||||
int iChar = 0;
|
||||
while(1)
|
||||
{
|
||||
char val = ReadChar();
|
||||
if ( val == 0 )
|
||||
break;
|
||||
else if ( bLine && val == '\n' )
|
||||
break;
|
||||
|
||||
if ( iChar < ( maxLen - 1 ) )
|
||||
{
|
||||
pStr[ iChar ] = val;
|
||||
++iChar;
|
||||
}
|
||||
else
|
||||
{
|
||||
bTooSmall = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure it's null-terminated.
|
||||
assert( iChar < maxLen );
|
||||
pStr[ iChar ] = 0;
|
||||
|
||||
if ( pOutNumChars )
|
||||
{
|
||||
*pOutNumChars = iChar;
|
||||
}
|
||||
|
||||
return !IsOverflowed() && !bTooSmall;
|
||||
}
|
||||
|
||||
// Read 1-5 bytes in order to extract a 32-bit unsigned value from the
|
||||
// stream. 7 data bits are extracted from each byte with the 8th bit used
|
||||
// to indicate whether the loop should continue.
|
||||
// This allows variable size numbers to be stored with tolerable
|
||||
// efficiency. Numbers sizes that can be stored for various numbers of
|
||||
// encoded bits are:
|
||||
// 8-bits: 0-127
|
||||
// 16-bits: 128-16383
|
||||
// 24-bits: 16384-2097151
|
||||
// 32-bits: 2097152-268435455
|
||||
// 40-bits: 268435456-0xFFFFFFFF
|
||||
uint32 CBitRead::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 CBitRead::ReadVarInt64()
|
||||
{
|
||||
uint64 result = 0;
|
||||
int count = 0;
|
||||
uint64 b;
|
||||
|
||||
do
|
||||
{
|
||||
if ( count == bitbuf::kMaxVarintBytes )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
b = ReadUBitLong( 8 );
|
||||
result |= static_cast<uint64>(b & 0x7F) << (7 * count);
|
||||
++count;
|
||||
} while (b & 0x80);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CBitRead::ReadBits( void *pOutData, int nBits )
|
||||
{
|
||||
unsigned char *pOut = ( unsigned char* )pOutData;
|
||||
int nBitsLeft = nBits;
|
||||
|
||||
|
||||
// align output to dword boundary
|
||||
while( ( ( unsigned long )pOut & 3 ) != 0 && nBitsLeft >= 8 )
|
||||
{
|
||||
*pOut = ( unsigned char )ReadUBitLong( 8 );
|
||||
++pOut;
|
||||
nBitsLeft -= 8;
|
||||
}
|
||||
|
||||
// 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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool CBitRead::ReadBytes( void *pOut, int nBytes )
|
||||
{
|
||||
ReadBits( pOut, nBytes << 3 );
|
||||
return !IsOverflowed();
|
||||
}
|
||||
|
||||
#define BITS_PER_INT 32
|
||||
inline int GetBitForBitnum( int bitNum )
|
||||
{
|
||||
static int bitsForBitnum[] =
|
||||
{
|
||||
( 1 << 0 ),
|
||||
( 1 << 1 ),
|
||||
( 1 << 2 ),
|
||||
( 1 << 3 ),
|
||||
( 1 << 4 ),
|
||||
( 1 << 5 ),
|
||||
( 1 << 6 ),
|
||||
( 1 << 7 ),
|
||||
( 1 << 8 ),
|
||||
( 1 << 9 ),
|
||||
( 1 << 10 ),
|
||||
( 1 << 11 ),
|
||||
( 1 << 12 ),
|
||||
( 1 << 13 ),
|
||||
( 1 << 14 ),
|
||||
( 1 << 15 ),
|
||||
( 1 << 16 ),
|
||||
( 1 << 17 ),
|
||||
( 1 << 18 ),
|
||||
( 1 << 19 ),
|
||||
( 1 << 20 ),
|
||||
( 1 << 21 ),
|
||||
( 1 << 22 ),
|
||||
( 1 << 23 ),
|
||||
( 1 << 24 ),
|
||||
( 1 << 25 ),
|
||||
( 1 << 26 ),
|
||||
( 1 << 27 ),
|
||||
( 1 << 28 ),
|
||||
( 1 << 29 ),
|
||||
( 1 << 30 ),
|
||||
( 1 << 31 ),
|
||||
};
|
||||
|
||||
return bitsForBitnum[ (bitNum) & (BITS_PER_INT-1) ];
|
||||
}
|
||||
|
||||
float CBitRead::ReadBitAngle( int numbits )
|
||||
{
|
||||
float shift = (float)( GetBitForBitnum(numbits) );
|
||||
|
||||
int i = ReadUBitLong( numbits );
|
||||
float fReturn = (float)i * (360.0f / shift);
|
||||
|
||||
return fReturn;
|
||||
}
|
||||
|
||||
// Basic Coordinate Routines (these contain bit-field size AND fixed point scaling constants)
|
||||
float CBitRead::ReadBitCoord (void)
|
||||
{
|
||||
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 CBitRead::ReadBitCoordMP( EBitCoordType coordType )
|
||||
{
|
||||
bool bIntegral = ( coordType == kCW_Integral );
|
||||
bool bLowPrecision = ( coordType == kCW_LowPrecision );
|
||||
|
||||
int intval=0,fractval=0,signbit=0;
|
||||
float value = 0.0;
|
||||
|
||||
bool bInBounds = ReadOneBit() ? true : false;
|
||||
|
||||
if ( bIntegral )
|
||||
{
|
||||
// Read the required integer and fraction flags
|
||||
intval = ReadOneBit();
|
||||
// If we got either parse them, otherwise it's a zero.
|
||||
if ( intval )
|
||||
{
|
||||
// Read the sign bit
|
||||
signbit = ReadOneBit();
|
||||
|
||||
// If there's an integer, read it in
|
||||
// Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE]
|
||||
if ( bInBounds )
|
||||
{
|
||||
value = ( float )( ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
value = ( float )( ReadUBitLong( COORD_INTEGER_BITS ) + 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read the required integer and fraction flags
|
||||
intval = ReadOneBit();
|
||||
|
||||
// Read the sign bit
|
||||
signbit = ReadOneBit();
|
||||
|
||||
// If we got either parse them, otherwise it's a zero.
|
||||
if ( intval )
|
||||
{
|
||||
if ( bInBounds )
|
||||
{
|
||||
intval = ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If there's a fraction, read it in
|
||||
fractval = ReadUBitLong( bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS );
|
||||
|
||||
// Calculate the correct floating point value
|
||||
value = intval + ((float)fractval * ( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION ) );
|
||||
}
|
||||
|
||||
// Fixup the sign if negative.
|
||||
if ( signbit )
|
||||
value = -value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float CBitRead::ReadBitCellCoord( int bits, EBitCoordType coordType )
|
||||
{
|
||||
bool bIntegral = ( coordType == kCW_Integral );
|
||||
bool bLowPrecision = ( coordType == kCW_LowPrecision );
|
||||
|
||||
int intval=0,fractval=0;
|
||||
float value = 0.0;
|
||||
|
||||
if ( bIntegral )
|
||||
{
|
||||
value = ( float )( ReadUBitLong( bits ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
intval = ReadUBitLong( bits );
|
||||
|
||||
// If there's a fraction, read it in
|
||||
fractval = ReadUBitLong( bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS );
|
||||
|
||||
// Calculate the correct floating point value
|
||||
value = intval + ((float)fractval * ( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION ) );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void CBitRead::ReadBitVec3Coord( Vector& fa )
|
||||
{
|
||||
int xflag, yflag, zflag;
|
||||
|
||||
// This vector must be initialized! Otherwise, If any of the flags aren't set,
|
||||
// the corresponding component will not be read and will be stack garbage.
|
||||
fa.Init( 0, 0, 0 );
|
||||
|
||||
xflag = ReadOneBit();
|
||||
yflag = ReadOneBit();
|
||||
zflag = ReadOneBit();
|
||||
|
||||
if ( xflag )
|
||||
fa.x = ReadBitCoord();
|
||||
if ( yflag )
|
||||
fa.y = ReadBitCoord();
|
||||
if ( zflag )
|
||||
fa.z = ReadBitCoord();
|
||||
}
|
||||
|
||||
float CBitRead::ReadBitNormal (void)
|
||||
{
|
||||
// Read the sign bit
|
||||
int signbit = ReadOneBit();
|
||||
|
||||
// Read the fractional part
|
||||
unsigned int fractval = ReadUBitLong( NORMAL_FRACTIONAL_BITS );
|
||||
|
||||
// Calculate the correct floating point value
|
||||
float value = (float)fractval * NORMAL_RESOLUTION;
|
||||
|
||||
// Fixup the sign if negative.
|
||||
if ( signbit )
|
||||
value = -value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void CBitRead::ReadBitVec3Normal( Vector& fa )
|
||||
{
|
||||
int xflag = ReadOneBit();
|
||||
int yflag = ReadOneBit();
|
||||
|
||||
if (xflag)
|
||||
fa.x = ReadBitNormal();
|
||||
else
|
||||
fa.x = 0.0f;
|
||||
|
||||
if (yflag)
|
||||
fa.y = ReadBitNormal();
|
||||
else
|
||||
fa.y = 0.0f;
|
||||
|
||||
// The first two imply the third (but not its sign)
|
||||
int znegative = ReadOneBit();
|
||||
|
||||
float fafafbfb = fa.x * fa.x + fa.y * fa.y;
|
||||
if (fafafbfb < 1.0f)
|
||||
fa.z = sqrt( 1.0f - fafafbfb );
|
||||
else
|
||||
fa.z = 0.0f;
|
||||
|
||||
if (znegative)
|
||||
fa.z = -fa.z;
|
||||
}
|
||||
|
||||
void CBitRead::ReadBitAngles( QAngle& fa )
|
||||
{
|
||||
Vector tmp;
|
||||
ReadBitVec3Coord( tmp );
|
||||
fa.Init( tmp.x, tmp.y, tmp.z );
|
||||
}
|
||||
|
||||
float CBitRead::ReadBitFloat( void )
|
||||
{
|
||||
uint32 nvalue = ReadUBitLong( 32 );
|
||||
return *( ( float * ) &nvalue );
|
||||
}
|
||||
|
240
demboyz/demofilebitbuf.h
Normal file
240
demboyz/demofilebitbuf.h
Normal file
@ -0,0 +1,240 @@
|
||||
//====== Copyright (c) 2014, Valve Corporation, All rights reserved. ========//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef DEMOFILEBITBUF_H
|
||||
#define DEMOFILEBITBUF_H
|
||||
|
||||
#include <math.h>
|
||||
#include "demofile.h"
|
||||
|
||||
// OVERALL Coordinate Size Limits used in COMMON.C MSG_*BitCoord() Routines (and someday the HUD)
|
||||
#define COORD_INTEGER_BITS 14
|
||||
#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))
|
||||
|
||||
enum EBitCoordType
|
||||
{
|
||||
kCW_None,
|
||||
kCW_LowPrecision,
|
||||
kCW_Integral
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// namespaced helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace bitbuf
|
||||
{
|
||||
// ZigZag Transform: Encodes signed integers so that they can be
|
||||
// effectively used with varint encoding.
|
||||
//
|
||||
// varint operates on unsigned integers, encoding smaller numbers into
|
||||
// fewer bytes. If you try to use it on a signed integer, it will treat
|
||||
// this number as a very large unsigned integer, which means that even
|
||||
// small signed numbers like -1 will take the maximum number of bytes
|
||||
// (10) to encode. ZigZagEncode() maps signed integers to unsigned
|
||||
// in such a way that those with a small absolute value will have smaller
|
||||
// encoded values, making them appropriate for encoding using varint.
|
||||
//
|
||||
// int32 -> uint32
|
||||
// -------------------------
|
||||
// 0 -> 0
|
||||
// -1 -> 1
|
||||
// 1 -> 2
|
||||
// -2 -> 3
|
||||
// ... -> ...
|
||||
// 2147483647 -> 4294967294
|
||||
// -2147483648 -> 4294967295
|
||||
//
|
||||
// >> encode >>
|
||||
// << decode <<
|
||||
|
||||
inline uint32 ZigZagEncode32(int32 n)
|
||||
{
|
||||
// Note: the right-shift must be arithmetic
|
||||
return(n << 1) ^ (n >> 31);
|
||||
}
|
||||
|
||||
inline int32 ZigZagDecode32(uint32 n)
|
||||
{
|
||||
return(n >> 1) ^ -static_cast<int32>(n & 1);
|
||||
}
|
||||
|
||||
inline uint64 ZigZagEncode64(int64 n)
|
||||
{
|
||||
// Note: the right-shift must be arithmetic
|
||||
return(n << 1) ^ (n >> 63);
|
||||
}
|
||||
|
||||
inline int64 ZigZagDecode64(uint64 n)
|
||||
{
|
||||
return(n >> 1) ^ -static_cast<int64>(n & 1);
|
||||
}
|
||||
|
||||
const int kMaxVarintBytes = 10;
|
||||
const int kMaxVarint32Bytes = 5;
|
||||
}
|
||||
|
||||
class CBitRead
|
||||
{
|
||||
uint32 m_nInBufWord;
|
||||
int m_nBitsAvail;
|
||||
uint32 const *m_pDataIn;
|
||||
uint32 const *m_pBufferEnd;
|
||||
uint32 const *m_pData;
|
||||
|
||||
bool m_bOverflow;
|
||||
int m_nDataBits;
|
||||
size_t m_nDataBytes;
|
||||
|
||||
static const uint32 s_nMaskTable[ 33 ]; // 0 1 3 7 15 ..
|
||||
|
||||
public:
|
||||
CBitRead( const void *pData, int nBytes, int nBits = -1 )
|
||||
{
|
||||
m_bOverflow = false;
|
||||
m_nDataBits = -1;
|
||||
m_nDataBytes = 0;
|
||||
StartReading( pData, nBytes, 0, nBits );
|
||||
}
|
||||
|
||||
CBitRead( void )
|
||||
{
|
||||
m_bOverflow = false;
|
||||
m_nDataBits = -1;
|
||||
m_nDataBytes = 0;
|
||||
}
|
||||
|
||||
void SetOverflowFlag( void )
|
||||
{
|
||||
m_bOverflow = true;
|
||||
}
|
||||
|
||||
bool IsOverflowed( void ) const
|
||||
{
|
||||
return m_bOverflow;
|
||||
}
|
||||
|
||||
int Tell( void ) const
|
||||
{
|
||||
return GetNumBitsRead();
|
||||
}
|
||||
|
||||
size_t TotalBytesAvailable( void ) const
|
||||
{
|
||||
return m_nDataBytes;
|
||||
}
|
||||
|
||||
int GetNumBitsLeft( void ) const
|
||||
{
|
||||
return m_nDataBits - Tell();
|
||||
}
|
||||
|
||||
int GetNumBytesLeft( void ) const
|
||||
{
|
||||
return GetNumBitsLeft() >> 3;
|
||||
}
|
||||
|
||||
bool Seek( int nPosition );
|
||||
|
||||
bool SeekRelative( int nOffset )
|
||||
{
|
||||
return Seek( GetNumBitsRead() + nOffset );
|
||||
}
|
||||
|
||||
unsigned char const * GetBasePointer()
|
||||
{
|
||||
return reinterpret_cast< unsigned char const *>( m_pData );
|
||||
}
|
||||
|
||||
void StartReading( const void *pData, int nBytes, int iStartBit = 0, int nBits = -1 );
|
||||
|
||||
int GetNumBitsRead( void ) const;
|
||||
int GetNumBytesRead( void ) const;
|
||||
|
||||
void GrabNextDWord( bool bOverFlowImmediately = false );
|
||||
void FetchNext( void );
|
||||
unsigned int ReadUBitLong( int numbits );
|
||||
int ReadSBitLong( int numbits );
|
||||
unsigned int ReadUBitVar( void );
|
||||
unsigned int PeekUBitLong( int numbits );
|
||||
bool ReadBytes( void *pOut, int nBytes );
|
||||
|
||||
// Returns 0 or 1.
|
||||
int ReadOneBit( void );
|
||||
int ReadLong( void );
|
||||
int ReadChar( void );
|
||||
int ReadByte( void );
|
||||
int ReadShort( void );
|
||||
int ReadWord( void );
|
||||
float ReadFloat( void );
|
||||
void ReadBits( void *pOut, int nBits );
|
||||
|
||||
float ReadBitCoord();
|
||||
float ReadBitCoordMP( EBitCoordType coordType );
|
||||
float ReadBitCellCoord( int bits, EBitCoordType coordType );
|
||||
float ReadBitNormal();
|
||||
void ReadBitVec3Coord( Vector& fa );
|
||||
void ReadBitVec3Normal( Vector& fa );
|
||||
void ReadBitAngles( QAngle& fa );
|
||||
float ReadBitAngle( int numbits );
|
||||
float ReadBitFloat( void );
|
||||
|
||||
// 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 );
|
||||
|
||||
// reads a varint encoded integer
|
||||
uint32 ReadVarInt32();
|
||||
uint64 ReadVarInt64();
|
||||
int32 ReadSignedVarInt32() { return bitbuf::ZigZagDecode32( ReadVarInt32() ); }
|
||||
int64 ReadSignedVarInt64() { return bitbuf::ZigZagDecode64( ReadVarInt64() ); }
|
||||
};
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
|
||||
#endif
|
||||
|
||||
#endif
|
28
premake/demboyz.lua
Normal file
28
premake/demboyz.lua
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
solution "demboyz"
|
||||
basedir ".."
|
||||
location (_ACTION)
|
||||
startproject "demboyz"
|
||||
configurations { "Debug", "Release" }
|
||||
platforms "x32"
|
||||
|
||||
vpaths
|
||||
{
|
||||
["Header Files"] = { "../**.h" },
|
||||
["Source Files"] = { "../**.cpp" }
|
||||
}
|
||||
|
||||
project "demboyz"
|
||||
kind "ConsoleApp"
|
||||
language "C++"
|
||||
files { "../demboyz/**.h", "../demboyz/**.cpp" }
|
||||
|
||||
configuration "Debug"
|
||||
targetdir (_ACTION .. "/build/Debug")
|
||||
defines { "DEBUG" }
|
||||
flags { "Symbols" }
|
||||
|
||||
configuration "Release"
|
||||
targetdir (_ACTION .. "/build/Release")
|
||||
defines { "NDEBUG" }
|
||||
optimize "Full"
|
BIN
premake/premake5.exe
Normal file
BIN
premake/premake5.exe
Normal file
Binary file not shown.
4
premake/vs2013.bat
Normal file
4
premake/vs2013.bat
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
premake5 --file=demboyz.lua vs2013
|
||||
|
||||
pause
|
Loading…
Reference in New Issue
Block a user