mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-15 23:21:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
242
Code/wwbitpack/BitPacker.cpp
Normal file
242
Code/wwbitpack/BitPacker.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//
|
||||
// Filename: bitpacker.cpp
|
||||
// Project: wwbitpack.lib
|
||||
// Author: Tom Spencer-Smith
|
||||
// Date: June 1998
|
||||
// Description: Minimal bit encoding
|
||||
//
|
||||
|
||||
#include "bitpacker.h"
|
||||
|
||||
#include <string.h> // for memset
|
||||
|
||||
#include "wwdebug.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//cBitPacker::cBitPacker(UINT buffer_size) :
|
||||
cBitPacker::cBitPacker() :
|
||||
//BufferSize(buffer_size),
|
||||
BitWritePosition(0),
|
||||
BitReadPosition(0)
|
||||
{
|
||||
//WWASSERT(BufferSize > 0);
|
||||
|
||||
//Buffer = new BYTE[BufferSize];
|
||||
//WWASSERT(Buffer != NULL);
|
||||
//memset(Buffer, 0, BufferSize);
|
||||
memset(Buffer, 0, MAX_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
cBitPacker::~cBitPacker()
|
||||
{
|
||||
//delete [] Buffer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
cBitPacker& cBitPacker::operator=(const cBitPacker& rhs)
|
||||
{
|
||||
//WWASSERT(BufferSize == rhs.BufferSize);
|
||||
|
||||
//memcpy(Buffer, rhs.Buffer, rhs.BufferSize);
|
||||
memcpy(Buffer, rhs.Buffer, MAX_BUFFER_SIZE);
|
||||
BitReadPosition = rhs.BitReadPosition;
|
||||
BitWritePosition = rhs.BitWritePosition;
|
||||
|
||||
return * this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// This method needs optimization
|
||||
//
|
||||
// 02-14-2002 Jani: Optimized the code somewhat. Note that the old code reverted
|
||||
// the bit order and the new one doesn't, so the versions are not compatible.
|
||||
// If you use optimized Add_Bits() you need to also use optimize Get_Bits().
|
||||
//
|
||||
|
||||
void cBitPacker::Add_Bits(ULONG value, UINT num_bits)
|
||||
{
|
||||
//
|
||||
// N.B. Presently you cannot use this class with an atomic type of more
|
||||
// than 4 bytes, such as a double. Hopefully you would be using a float
|
||||
// instead anyway.
|
||||
//
|
||||
#if 0 // Old version
|
||||
WWASSERT(num_bits > 0 && num_bits <= MAX_BITS);
|
||||
|
||||
ULONG mask = 1 << (num_bits - 1);
|
||||
while (mask > 0) {
|
||||
|
||||
//WWASSERT(BitWritePosition < BufferSize * 8);
|
||||
WWASSERT(BitWritePosition < MAX_BUFFER_SIZE * 8);
|
||||
|
||||
UINT byte_num = BitWritePosition / 8;
|
||||
UINT bit_offset = BitWritePosition % 8;
|
||||
bool bit_value = (value & mask) != 0;
|
||||
Buffer[byte_num] |= bit_value << bit_offset;
|
||||
|
||||
BitWritePosition++;
|
||||
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
#else // New faster version
|
||||
|
||||
// Verify that we're not writing over buffer
|
||||
WWASSERT(num_bits > 0 && num_bits <= MAX_BITS);
|
||||
WWASSERT(BitWritePosition+num_bits <= MAX_BUFFER_SIZE * 8);
|
||||
|
||||
// Fill the remaining bits of the write byte first
|
||||
UINT byte_num = BitWritePosition >> 3;
|
||||
UINT bit_offset = BitWritePosition & 0x7;
|
||||
BitWritePosition+=num_bits; // Advance the write position
|
||||
|
||||
// If write buffer is not byte aligned, write the remaining bits first
|
||||
value <<= 32-num_bits;
|
||||
if (bit_offset) {
|
||||
UINT bit_count = 8 - bit_offset;
|
||||
if (bit_count>num_bits) bit_count=num_bits;
|
||||
|
||||
ULONG bit_value = value;
|
||||
value <<= bit_count; // Remove the copied bits
|
||||
num_bits -= bit_count;
|
||||
bit_value >>= (24+bit_offset);
|
||||
Buffer[byte_num++] |= bit_value;
|
||||
}
|
||||
|
||||
// Write the rest of the data as bytes
|
||||
if (num_bits>8) {
|
||||
for (unsigned a=0;a<num_bits;a+=8) {
|
||||
Buffer[byte_num++]=unsigned char(value>>24);
|
||||
value<<=8;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Buffer[byte_num]=unsigned char(value>>24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// This method needs optimization
|
||||
// 02-14-2002 Jani: Optimized. See Add_Bits() for notes.
|
||||
//
|
||||
void cBitPacker::Get_Bits(ULONG & value, UINT num_bits)
|
||||
{
|
||||
#if 0 // Old version
|
||||
WWASSERT(num_bits > 0 && num_bits <= MAX_BITS);
|
||||
|
||||
value = 0;
|
||||
for (int bit = num_bits - 1; bit >= 0; bit--) {
|
||||
|
||||
//WWASSERT(BitReadPosition < BufferSize * 8);
|
||||
WWASSERT(BitReadPosition < MAX_BUFFER_SIZE * 8);
|
||||
WWASSERT(BitReadPosition < BitWritePosition);
|
||||
UINT byte_num = BitReadPosition / 8;
|
||||
UINT bit_offset = BitReadPosition % 8;
|
||||
bool b = (Buffer[byte_num] & (1 << bit_offset)) != 0;
|
||||
|
||||
value += (b << bit);
|
||||
|
||||
BitReadPosition++;
|
||||
}
|
||||
#else // New faster version
|
||||
|
||||
// Verify that we're not reading over buffer or write pointer
|
||||
WWASSERT(num_bits > 0 && num_bits <= MAX_BITS);
|
||||
WWASSERT(BitReadPosition+num_bits <= MAX_BUFFER_SIZE * 8);
|
||||
WWASSERT(BitReadPosition+num_bits <= BitWritePosition);
|
||||
|
||||
UINT read_len=num_bits;
|
||||
UINT byte_num = BitReadPosition / 8;
|
||||
UINT bit_offset = BitReadPosition % 8;
|
||||
BitReadPosition += num_bits;
|
||||
|
||||
UINT bit_count = 8 - bit_offset;
|
||||
if (bit_count>num_bits) bit_count=num_bits;
|
||||
value = (ULONG(Buffer[byte_num++]) << (bit_offset+24));
|
||||
num_bits-=bit_count;
|
||||
|
||||
for (int shift=24-bit_count;shift>0;shift-=8,num_bits-=8) value|=unsigned(Buffer[byte_num++]) << shift;
|
||||
if (num_bits>0) value|=Buffer[byte_num++]>>(-shift);
|
||||
|
||||
value >>= 32-read_len;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// This method is only for use by a packet class when data is received.
|
||||
//
|
||||
|
||||
void cBitPacker::Set_Bit_Write_Position(UINT position)
|
||||
{
|
||||
//WWASSERT(position <= BufferSize * 8);
|
||||
WWASSERT(position <= MAX_BUFFER_SIZE * 8);
|
||||
BitWritePosition = position;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
//-----------------------------------------------------------------------------
|
||||
void cBitPacker::Increment_Bit_Position(int num_bits)
|
||||
{
|
||||
WWASSERT(num_bits >= 0);
|
||||
|
||||
for (int i = 0; i < num_bits; i++) {
|
||||
Advance_Bit_Position();
|
||||
NumBits++;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UINT cBitPacker::Get_Compressed_Size_Bytes() const
|
||||
{
|
||||
return (int) ceil(BitWritePosition / 8.0f);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void cBitPacker::Advance_Bit_Position()
|
||||
{
|
||||
BitWritePosition++;
|
||||
|
||||
//
|
||||
// If the following assert hits then our buffer is not large enough.
|
||||
// We can advance BitWritePosition one bit past the end of the buffer, but
|
||||
// we cannot write there.
|
||||
//
|
||||
//WWASSERT(BitWritePosition < BufferSize * 8);
|
||||
WWASSERT(BitWritePosition <= BufferSize * 8);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user