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);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
98
Code/wwbitpack/BitPacker.h
Normal file
98
Code/wwbitpack/BitPacker.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
** 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.h
|
||||
// Project: wwbitpack.lib
|
||||
// Author: Tom Spencer-Smith
|
||||
// Date: June 1998
|
||||
// Description: Minimal bit encoding
|
||||
//
|
||||
|
||||
#ifndef BITPACKER_H
|
||||
#define BITPACKER_H
|
||||
|
||||
|
||||
#include "always.h"
|
||||
#include "bittype.h"
|
||||
|
||||
|
||||
#pragma warning(disable:4514)
|
||||
|
||||
static const int MAX_BITS = 32;
|
||||
|
||||
// 1400 is too big. Minimum MTU allowable on the internet is 576. IP Header is 20 bytes. UDP header is 8 bytes
|
||||
// So our max packet size is 576 - 28 = 548
|
||||
//static const int MAX_BUFFER_SIZE = 1400;
|
||||
static const int MAX_BUFFER_SIZE = 548;
|
||||
|
||||
class cBitPacker
|
||||
{
|
||||
public:
|
||||
//cBitPacker(UINT buffer_size);
|
||||
cBitPacker();
|
||||
virtual ~cBitPacker();
|
||||
|
||||
char * Get_Data() const {return (char *) Buffer;}
|
||||
//UINT Get_Buffer_Size() const {return BufferSize;}
|
||||
UINT Get_Buffer_Size() const {return MAX_BUFFER_SIZE;}
|
||||
void Flush() {BitReadPosition = BitWritePosition;}
|
||||
bool Is_Flushed() const {return (BitReadPosition == BitWritePosition);}
|
||||
|
||||
void Add_Bits(ULONG value, UINT num_bits);
|
||||
void Get_Bits(ULONG & value, UINT num_bits);
|
||||
|
||||
void Set_Bit_Write_Position(UINT position);
|
||||
UINT Get_Bit_Write_Position() const {return BitWritePosition;}
|
||||
|
||||
protected:
|
||||
cBitPacker& operator=(const cBitPacker& rhs);
|
||||
|
||||
private:
|
||||
|
||||
cBitPacker(const cBitPacker& source); // Disallow copy constructor
|
||||
|
||||
//BYTE * Buffer;
|
||||
//const UINT BufferSize;
|
||||
BYTE Buffer[MAX_BUFFER_SIZE];
|
||||
UINT BitWritePosition;
|
||||
UINT BitReadPosition;
|
||||
};
|
||||
|
||||
#endif // BITPACKER_H
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void Reset() {BitWritePosition = 0;}
|
||||
UINT Get_Compressed_Size_Bytes() const;
|
||||
|
||||
void Flush() {NumBits = 0;}
|
||||
bool Is_Flushed() const {return (NumBits < 8);}
|
||||
|
||||
void Set_Num_Bits(int num) {WWASSERT(num >= 0); NumBits = num;}
|
||||
int Get_Num_Bits(void) {return NumBits;}
|
||||
|
||||
void Increment_Bit_Position(int num_bits);
|
||||
|
||||
|
||||
//inline void Advance_Bit_Position();
|
||||
|
||||
//int NumBits;
|
||||
*/
|
||||
BIN
Code/wwbitpack/Debug/wwbitpack.pch
Normal file
BIN
Code/wwbitpack/Debug/wwbitpack.pch
Normal file
Binary file not shown.
98
Code/wwbitpack/bitpackids.h
Normal file
98
Code/wwbitpack/bitpackids.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** Confidential - Westwood Studios ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Commando *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwbitpack/bitpackids.h $*
|
||||
* *
|
||||
* $Author:: Greg_h $*
|
||||
* *
|
||||
* $Modtime:: 10/14/01 11:15a $*
|
||||
* *
|
||||
* $Revision:: 6 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef BITPACKIDS_H
|
||||
#define BITPACKIDS_H
|
||||
|
||||
enum {
|
||||
/*
|
||||
//
|
||||
// 08/30/00 Use of pathfind extents for bitcompression decommissioned.
|
||||
// Flying vehicles and sea vehicles would have to use world extents
|
||||
// anyway.
|
||||
//
|
||||
|
||||
//
|
||||
// Use these for objects restricted to pathfindable areas
|
||||
//
|
||||
BITPACK_PATHFIND_POSITION_X,
|
||||
BITPACK_PATHFIND_POSITION_Y,
|
||||
BITPACK_PATHFIND_POSITION_Z,
|
||||
*/
|
||||
|
||||
//
|
||||
// Use these for objects restricted to world extents
|
||||
//
|
||||
BITPACK_WORLD_POSITION_X,
|
||||
BITPACK_WORLD_POSITION_Y,
|
||||
BITPACK_WORLD_POSITION_Z,
|
||||
|
||||
BITPACK_ONE_TIME_BOOLEAN_BITS,
|
||||
BITPACK_CONTINUOUS_BOOLEAN_BITS,
|
||||
BITPACK_ANALOG_VALUES,
|
||||
|
||||
BITPACK_HEALTH,
|
||||
BITPACK_SHIELD_STRENGTH,
|
||||
BITPACK_SHIELD_TYPE,
|
||||
|
||||
BITPACK_CTF_TEAM_FLAG,
|
||||
|
||||
BITPACK_HUMAN_STATE,
|
||||
BITPACK_HUMAN_SUB_STATE,
|
||||
|
||||
BITPACK_VEHICLE_VELOCITY,
|
||||
BITPACK_VEHICLE_ANGULAR_VELOCITY,
|
||||
BITPACK_VEHICLE_QUATERNION,
|
||||
BITPACK_VEHICLE_LOCK_TIMER,
|
||||
|
||||
BITPACK_DOOR_STATE,
|
||||
BITPACK_ELEVATOR_STATE,
|
||||
BITPACK_ELEVATOR_TOP_DOOR_STATE,
|
||||
BITPACK_ELEVATOR_BOTTOM_DOOR_STATE,
|
||||
|
||||
BITPACK_BUILDING_RADIUS,
|
||||
|
||||
BITPACK_BUILDING_STATE,
|
||||
|
||||
BITPACK_CONTROL_MOVES_CS,
|
||||
BITPACK_CONTROL_MOVES_SC,
|
||||
|
||||
BITPACK_PACKET_TYPE,
|
||||
BITPACK_PACKET_ID,
|
||||
|
||||
};
|
||||
|
||||
#endif // BITPACKIDS_H
|
||||
242
Code/wwbitpack/bitstream.cpp
Normal file
242
Code/wwbitpack/bitstream.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/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : wwbitpack *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwbitpack/bitstream.cpp $*
|
||||
* *
|
||||
* Original Author:: Tom Spencer-Smith *
|
||||
* *
|
||||
* $Author:: Bhayes $*
|
||||
* *
|
||||
* $Modtime:: 2/18/02 10:49p $*
|
||||
* *
|
||||
* $Revision:: 4 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "bitstream.h"
|
||||
|
||||
#include <string.h> // for strlen
|
||||
#include <math.h> // for ceil
|
||||
|
||||
#include "wwdebug.h"
|
||||
#include "mathutil.h"
|
||||
#include "widestring.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
BitStreamClass::BitStreamClass() :
|
||||
cBitPacker(),
|
||||
UncompressedSizeBytes(0)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
BitStreamClass& BitStreamClass::operator=(const BitStreamClass& rhs)
|
||||
{
|
||||
//
|
||||
// Call operator for base class
|
||||
//
|
||||
cBitPacker::operator= (rhs);
|
||||
|
||||
UncompressedSizeBytes = rhs.UncompressedSizeBytes;
|
||||
|
||||
return * this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BitStreamClass::Add(bool value)
|
||||
{
|
||||
if (cEncoderList::Is_Compression_Enabled()) {
|
||||
Add_Bits(value, 1);
|
||||
} else {
|
||||
Add_Bits(value, BIT_DEPTH(bool));
|
||||
}
|
||||
|
||||
UncompressedSizeBytes += BYTE_DEPTH(bool);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool BitStreamClass::Get(bool & value)
|
||||
{
|
||||
ULONG u_value;
|
||||
if (cEncoderList::Is_Compression_Enabled()) {
|
||||
Get_Bits(u_value, 1);
|
||||
} else {
|
||||
Get_Bits(u_value, BIT_DEPTH(bool));
|
||||
}
|
||||
|
||||
value = (u_value == 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BitStreamClass::Add_Raw_Data(LPCSTR data, USHORT data_size)
|
||||
{
|
||||
WWASSERT(data != NULL);
|
||||
WWASSERT(data_size >= 0);
|
||||
|
||||
for (int i = 0; i < data_size; i++) {
|
||||
Add(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BitStreamClass::Get_Raw_Data(char * buffer, USHORT buffer_size, USHORT data_size)
|
||||
{
|
||||
WWASSERT(buffer != NULL);
|
||||
WWASSERT(data_size >= 0);
|
||||
WWASSERT(buffer_size >= data_size);
|
||||
|
||||
for (int i = 0; i < data_size; i++) {
|
||||
Get(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BitStreamClass::Add_Terminated_String(LPCSTR string, bool permit_empty)
|
||||
{
|
||||
WWASSERT(string != NULL);
|
||||
|
||||
//
|
||||
// The terminating null is not transmitted.
|
||||
//
|
||||
USHORT len = (USHORT) strlen(string);
|
||||
if (!permit_empty) {
|
||||
WWASSERT(len > 0);
|
||||
}
|
||||
|
||||
Add(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Add(string[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BitStreamClass::Get_Terminated_String(char * buffer, USHORT buffer_size, bool permit_empty)
|
||||
{
|
||||
WWASSERT(buffer != NULL);
|
||||
WWASSERT(buffer_size > 0);
|
||||
|
||||
USHORT len;
|
||||
Get(len);
|
||||
WWASSERT(len < buffer_size);
|
||||
if (!permit_empty) {
|
||||
WWASSERT(len > 0);
|
||||
}
|
||||
|
||||
char temp = '?';
|
||||
int i = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
Get(temp);
|
||||
if (i < buffer_size - 1) {
|
||||
buffer[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// Null-terminate it.
|
||||
if (i < buffer_size) {
|
||||
buffer[i] = 0;
|
||||
} else {
|
||||
buffer[buffer_size - 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BitStreamClass::Add_Wide_Terminated_String(const WCHAR *string, bool permit_empty)
|
||||
{
|
||||
WWASSERT(string != NULL);
|
||||
|
||||
//
|
||||
// The terminating null is not transmitted.
|
||||
//
|
||||
USHORT len = (USHORT)wcslen (string);
|
||||
if (!permit_empty) {
|
||||
WWASSERT(len > 0 && "Empty string not permitted");
|
||||
}
|
||||
|
||||
Add(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
Add(string[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void BitStreamClass::Get_Wide_Terminated_String(WCHAR *buffer, USHORT buffer_len, bool permit_empty)
|
||||
{
|
||||
WWASSERT(buffer != NULL);
|
||||
WWASSERT(buffer_len > 0);
|
||||
|
||||
USHORT len;
|
||||
Get(len);
|
||||
WWASSERT(len < buffer_len && "String length exceeds provided buffer");
|
||||
if (!permit_empty) {
|
||||
WWASSERT(len > 0 && "Empty string not permitted");
|
||||
}
|
||||
|
||||
WCHAR temp = L'?';
|
||||
int i = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
Get(temp);
|
||||
if (i < buffer_len - 1) {
|
||||
buffer[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < buffer_len - 1) {
|
||||
buffer[i] = 0; // Null-terminate it.
|
||||
} else {
|
||||
buffer[buffer_len-1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UINT BitStreamClass::Get_Compressed_Size_Bytes() const
|
||||
{
|
||||
return (UINT) ceil(Get_Bit_Write_Position() / 8.0f);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
UINT BitStreamClass::Get_Compression_Pc() const
|
||||
{
|
||||
UINT c_size = Get_Compressed_Size_Bytes();
|
||||
UINT u_size = Get_Uncompressed_Size_Bytes();
|
||||
|
||||
if (cEncoderList::Is_Compression_Enabled()) {
|
||||
WWASSERT(c_size <= u_size);
|
||||
} else {
|
||||
WWASSERT(c_size == u_size);
|
||||
}
|
||||
|
||||
WWASSERT(u_size > 0);
|
||||
|
||||
UINT compression_pc = (UINT) cMathUtil::Round(100 * c_size / (float) u_size);
|
||||
WWASSERT(compression_pc >= 0 && compression_pc <= 100);
|
||||
|
||||
return compression_pc;
|
||||
}
|
||||
220
Code/wwbitpack/bitstream.h
Normal file
220
Code/wwbitpack/bitstream.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : wwbitpack *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwbitpack/bitstream.h $*
|
||||
* *
|
||||
* Original Author:: Tom Spencer-Smith *
|
||||
* *
|
||||
* $Author:: Patrick $*
|
||||
* *
|
||||
* $Modtime:: 6/13/01 9:05a $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#ifndef BITSTREAM_H
|
||||
#define BITSTREAM_H
|
||||
|
||||
|
||||
#include "bitpacker.h"
|
||||
#include "wwdebug.h"
|
||||
#include "encoderlist.h"
|
||||
#include "mathutil.h"
|
||||
#include "math.h"
|
||||
#include "widestring.h"
|
||||
|
||||
#define BYTE_DEPTH(x) (sizeof(x))
|
||||
#define BIT_DEPTH(x) (8 * sizeof(x))
|
||||
|
||||
|
||||
/**
|
||||
** BitStreamClass
|
||||
**
|
||||
** Author: Tom Spencer-Smith
|
||||
** Date: June 1998
|
||||
** Description: A class for minimal bit encoding.
|
||||
** Notes:
|
||||
** - Uncompressed data may be included in the bitstream.
|
||||
** - Compression may be disabled entirely if desired.
|
||||
** - Bools are compressed to 1 bit without requiring a precision
|
||||
** setup.
|
||||
** - Strings and raw data are uncompressed.
|
||||
**
|
||||
** (gth, 08/31/2000) - renamed this class to BitStreamClass (from cTypeEncoder) and
|
||||
** cleaned it up to become the interface that all game and library code uses to
|
||||
** package up their state variables for network transmission, converted to westwood
|
||||
** naming convention since it is going to propogate to a lot of other code.
|
||||
*/
|
||||
|
||||
class BitStreamClass : public cBitPacker
|
||||
{
|
||||
public:
|
||||
|
||||
BitStreamClass();
|
||||
BitStreamClass& operator=(const BitStreamClass& rhs);
|
||||
|
||||
UINT Get_Uncompressed_Size_Bytes() const {return UncompressedSizeBytes;}
|
||||
UINT Get_Compressed_Size_Bytes() const;
|
||||
UINT Get_Compression_Pc() const;
|
||||
|
||||
//
|
||||
// For data which may include NULL's.
|
||||
// Data will not be compressed.
|
||||
//
|
||||
void Add_Raw_Data(LPCSTR data, USHORT data_size);
|
||||
void Get_Raw_Data(char * buffer, USHORT buffer_size, USHORT data_size);
|
||||
|
||||
//
|
||||
// For data terminated with NULL.
|
||||
// Data will not be compressed.
|
||||
// You may permit or disallow empty strings to be passed.
|
||||
//
|
||||
void Add_Terminated_String(LPCSTR string, bool permit_empty = false);
|
||||
void Get_Terminated_String(char * buffer, USHORT buffer_size, bool permit_empty = false);
|
||||
|
||||
//
|
||||
// For data terminated with NULL.
|
||||
// Data will not be compressed.
|
||||
// You may permit or disallow empty strings to be passed.
|
||||
//
|
||||
void Add_Wide_Terminated_String(const WCHAR *string, bool permit_empty = false);
|
||||
void Get_Wide_Terminated_String (WCHAR *buffer, USHORT buffer_len, bool permit_empty = false);
|
||||
|
||||
//
|
||||
// Bool is special-cased because we know that we can always
|
||||
// represent it as 1 bit.
|
||||
//
|
||||
void Add(bool value);
|
||||
bool Get(bool & value);
|
||||
|
||||
//
|
||||
// For all other data types that we want to support, call into our internal
|
||||
// template function.
|
||||
//
|
||||
enum {NO_ENCODER = -1};
|
||||
|
||||
void Add(BYTE val,int type = NO_ENCODER) { Internal_Add(val,type); }
|
||||
void Add(USHORT val,int type = NO_ENCODER) { Internal_Add(val,type); }
|
||||
void Add(UINT val,int type = NO_ENCODER) { Internal_Add(val,type); }
|
||||
void Add(ULONG val,int type = NO_ENCODER) { Internal_Add(val,type); }
|
||||
void Add(char val,int type = NO_ENCODER) { Internal_Add(val,type); }
|
||||
void Add(int val,int type = NO_ENCODER) { Internal_Add(val,type); }
|
||||
void Add(float val,int type = NO_ENCODER) { Internal_Add(val,type); }
|
||||
|
||||
BYTE Get(BYTE & set_val,int type = NO_ENCODER) { return Internal_Get(set_val,type); }
|
||||
USHORT Get(USHORT & set_val,int type = NO_ENCODER) { return Internal_Get(set_val,type); }
|
||||
ULONG Get(ULONG & set_val,int type = NO_ENCODER) { return Internal_Get(set_val,type); }
|
||||
UINT Get(UINT & set_val,int type = NO_ENCODER) { return Internal_Get(set_val,type); }
|
||||
char Get(char & set_val,int type = NO_ENCODER) { return Internal_Get(set_val,type); }
|
||||
int Get(int & set_val,int type = NO_ENCODER) { return Internal_Get(set_val,type); }
|
||||
float Get(float & set_val,int type = NO_ENCODER) { return Internal_Get(set_val,type); }
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// Add/Get for remaining atomic data types.
|
||||
// I really wish the following 3 methods were in the source file, but
|
||||
// the compiler won't accept this. Hopefully the pragma and MSVC
|
||||
// will prevent inlining.
|
||||
//
|
||||
#pragma auto_inline(off)
|
||||
//------------------------------------------------------------------------------------
|
||||
template<class T> void Internal_Add(T value, int type = NO_ENCODER) {
|
||||
if (cEncoderList::Is_Compression_Enabled() && type != NO_ENCODER) {
|
||||
WWASSERT(type >= 0 && type < MAX_ENCODERTYPES);
|
||||
|
||||
cEncoderTypeEntry & entry = cEncoderList::Get_Encoder_Type_Entry(type);
|
||||
|
||||
//
|
||||
// If the following assert hits then the value of the type
|
||||
// parameter is unknown.
|
||||
//
|
||||
WWASSERT(entry.Is_Valid());
|
||||
|
||||
ULONG scaled_value;
|
||||
bool is_in_range = entry.Scale(value, scaled_value);
|
||||
if (!is_in_range) {
|
||||
//WWDEBUG_SAY(("BitStreamClass::Add : Warning: out-of-range value clamped (type %d).\n",
|
||||
// type));
|
||||
//DIE;
|
||||
}
|
||||
|
||||
Add_Bits(scaled_value, entry.Get_Bit_Precision());
|
||||
|
||||
} else {
|
||||
Add_Bits(*(reinterpret_cast<ULONG *>(&value)), BIT_DEPTH(T));
|
||||
}
|
||||
|
||||
UncompressedSizeBytes += BYTE_DEPTH(T);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
template<class T> T Internal_Get(T & value, int type = NO_ENCODER) {
|
||||
|
||||
if (cEncoderList::Is_Compression_Enabled() && type != NO_ENCODER) {
|
||||
WWASSERT(type >= 0 && type < MAX_ENCODERTYPES);
|
||||
|
||||
cEncoderTypeEntry & entry = cEncoderList::Get_Encoder_Type_Entry(type);
|
||||
|
||||
//
|
||||
// If the following assert hits then the value of the type
|
||||
// parameter is unknown.
|
||||
//
|
||||
WWASSERT(entry.Is_Valid());
|
||||
|
||||
ULONG u_value;
|
||||
Get_Bits(u_value, entry.Get_Bit_Precision());
|
||||
|
||||
double f_value = entry.Unscale(u_value);
|
||||
|
||||
if ((::fabs(f_value - static_cast<T>(f_value)) < MISCUTIL_EPSILON)) {
|
||||
//
|
||||
// N.B. More error may be introduced here
|
||||
//
|
||||
value = static_cast<T>(f_value);
|
||||
} else {
|
||||
value = static_cast<T>(cMathUtil::Round(f_value));
|
||||
}
|
||||
|
||||
WWASSERT(entry.Is_Value_In_Range(value));
|
||||
|
||||
} else {
|
||||
ULONG u_value;
|
||||
Get_Bits(u_value, BIT_DEPTH(T));
|
||||
|
||||
value = *(reinterpret_cast<T *>(&u_value));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
#pragma auto_inline(on)
|
||||
|
||||
UINT UncompressedSizeBytes; // for statistics only
|
||||
};
|
||||
|
||||
#endif // TYPEENCODER_H
|
||||
52
Code/wwbitpack/encoderlist.cpp
Normal file
52
Code/wwbitpack/encoderlist.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
** 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: encoderlist.cpp
|
||||
// Project: wwbitpack.lib
|
||||
// Author: Tom Spencer-Smith
|
||||
// Date: June 1998
|
||||
// Description:
|
||||
//
|
||||
|
||||
#include "encoderlist.h"
|
||||
|
||||
#include "wwdebug.h"
|
||||
|
||||
//
|
||||
// Class statics
|
||||
//
|
||||
bool cEncoderList::IsCompressionEnabled = true;
|
||||
cEncoderTypeEntry cEncoderList::EncoderTypes[];
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void cEncoderList::Clear_Entries()
|
||||
{
|
||||
WWDEBUG_SAY(("cEncoderList::Clear_Entries\n"));
|
||||
|
||||
for (int i = 0; i < MAX_ENCODERTYPES; i++) {
|
||||
EncoderTypes[i].Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
cEncoderTypeEntry & cEncoderList::Get_Encoder_Type_Entry(int index)
|
||||
{
|
||||
WWASSERT(index >= 0 && index < MAX_ENCODERTYPES);
|
||||
return EncoderTypes[index];
|
||||
}
|
||||
98
Code/wwbitpack/encoderlist.h
Normal file
98
Code/wwbitpack/encoderlist.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
** 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: encoderlist.h
|
||||
// Project: wwbitpack.lib
|
||||
// Author: Tom Spencer-Smith
|
||||
// Date: June 1998
|
||||
// Description:
|
||||
//
|
||||
|
||||
#ifndef ENCODERLIST_H
|
||||
#define ENCODERLIST_H
|
||||
|
||||
#include "encodertypeentry.h"
|
||||
#include "miscutil.h"
|
||||
#include "wwdebug.h"
|
||||
|
||||
|
||||
const int MAX_ENCODERTYPES = 100;
|
||||
|
||||
class cEncoderList
|
||||
{
|
||||
public:
|
||||
static void Clear_Entries();
|
||||
|
||||
static void Set_Compression_Enabled(bool flag) {IsCompressionEnabled = flag;}
|
||||
static bool Is_Compression_Enabled() {return IsCompressionEnabled;}
|
||||
|
||||
static cEncoderTypeEntry & Get_Encoder_Type_Entry(int index);
|
||||
|
||||
#pragma auto_inline(off)
|
||||
//------------------------------------------------------------------------------------
|
||||
template<class T> static T Set_Precision(int type, T min, T max,
|
||||
T resolution = 1)
|
||||
{
|
||||
WWASSERT(type >= 0 && type < MAX_ENCODERTYPES);
|
||||
WWASSERT(max - min > -MISCUTIL_EPSILON);
|
||||
WWASSERT(resolution > MISCUTIL_EPSILON);
|
||||
|
||||
EncoderTypes[type].Init(
|
||||
static_cast<double>(min),
|
||||
static_cast<double>(max),
|
||||
static_cast<double>(resolution));
|
||||
|
||||
WWDEBUG_SAY(("cEncoderList::Set_Precision for type %d: %d -> %d bits\n",
|
||||
type, sizeof(T) * 8, EncoderTypes[type].Get_Bit_Precision()));
|
||||
|
||||
//
|
||||
// Return maximum representation error
|
||||
//
|
||||
return static_cast<T>(resolution / 2.0f + MISCUTIL_EPSILON);
|
||||
/*
|
||||
double max_error = EncoderTypes[type].Get_Resolution() / 2.0f + MISCUTIL_EPSILON;
|
||||
if (::fabs(max_error - static_cast<T>(max_error)) < MISCUTIL_EPSILON) {
|
||||
//return static_cast<T>(max_error);
|
||||
return static_cast<T>(max_error);
|
||||
} else {
|
||||
return static_cast<T>(ceil(max_error));
|
||||
}
|
||||
/**/
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
static void Set_Precision(int type, int num_bits)
|
||||
{
|
||||
WWASSERT(type >= 0 && type < MAX_ENCODERTYPES);
|
||||
WWASSERT(num_bits > 0 && num_bits <= 32);
|
||||
|
||||
EncoderTypes[type].Init(num_bits);
|
||||
|
||||
WWDEBUG_SAY(("cEncoderList::Set_Precision for type %d: %d bits\n",
|
||||
type, num_bits));
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
#pragma auto_inline(on)
|
||||
|
||||
private:
|
||||
static cEncoderTypeEntry EncoderTypes[MAX_ENCODERTYPES];
|
||||
|
||||
static bool IsCompressionEnabled;
|
||||
};
|
||||
|
||||
#endif // ENCODERLIST_H
|
||||
186
Code/wwbitpack/encodertypeentry.cpp
Normal file
186
Code/wwbitpack/encodertypeentry.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
** 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: encodertypeentry.cpp
|
||||
// Project: wwbitpack.lib
|
||||
// Author: Tom Spencer-Smith
|
||||
// Date: June 2000
|
||||
// Description:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "encodertypeentry.h" // I WANNA BE FIRST!
|
||||
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "wwdebug.h"
|
||||
#include "miscutil.h"
|
||||
#include "mathutil.h"
|
||||
|
||||
static const int MAX_BITS = 32;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
cEncoderTypeEntry::cEncoderTypeEntry()
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool cEncoderTypeEntry::Is_Valid() const
|
||||
{
|
||||
return
|
||||
((Max - Min > -MISCUTIL_EPSILON) &&
|
||||
(Resolution > -MISCUTIL_EPSILON) &&
|
||||
(BitPrecision >= 0));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void cEncoderTypeEntry::Invalidate()
|
||||
{
|
||||
Min = 1;
|
||||
Max = -1;
|
||||
Resolution = -1;
|
||||
BitPrecision = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool cEncoderTypeEntry::Is_Value_In_Range(double value) const
|
||||
{
|
||||
return (value >= Min - MISCUTIL_EPSILON && value <= Max + MISCUTIL_EPSILON);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void cEncoderTypeEntry::Init(double min, double max, double resolution)
|
||||
{
|
||||
WWASSERT(!Is_Valid());
|
||||
|
||||
WWASSERT(max - min > -MISCUTIL_EPSILON);
|
||||
WWASSERT(resolution > MISCUTIL_EPSILON);
|
||||
|
||||
Min = min;
|
||||
Max = max;
|
||||
|
||||
Calc_Bit_Precision(resolution);
|
||||
|
||||
WWASSERT(Is_Valid());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void cEncoderTypeEntry::Init(int num_bits)
|
||||
{
|
||||
WWASSERT(!Is_Valid());
|
||||
|
||||
WWASSERT(num_bits > 0 && num_bits <= 32);
|
||||
|
||||
Min = 0;
|
||||
BitPrecision = num_bits;
|
||||
Resolution = 1;
|
||||
|
||||
UINT max = 0;
|
||||
for (int i = 0; i < num_bits; i++) {
|
||||
max += 1 << i;
|
||||
}
|
||||
|
||||
Max = max;
|
||||
|
||||
WWASSERT(Is_Valid());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool cEncoderTypeEntry::Scale(double value, ULONG & scaled_value)
|
||||
{
|
||||
WWASSERT(Is_Valid());
|
||||
|
||||
bool is_in_range = Is_Value_In_Range(value);
|
||||
|
||||
if (!is_in_range) {
|
||||
value = Clamp(value);
|
||||
}
|
||||
|
||||
scaled_value = static_cast<ULONG>
|
||||
(cMathUtil::Round((value - Min) / Resolution));
|
||||
|
||||
return is_in_range;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
double cEncoderTypeEntry::Unscale(ULONG u_value)
|
||||
{
|
||||
WWASSERT(Is_Valid());
|
||||
|
||||
double value = Min + u_value * Resolution;
|
||||
|
||||
WWASSERT(Is_Value_In_Range(value));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
double cEncoderTypeEntry::Clamp(double value)
|
||||
{
|
||||
WWASSERT(Is_Valid());
|
||||
|
||||
double retval = value;
|
||||
|
||||
if (retval < Min) {
|
||||
retval = Min;
|
||||
} else if (retval > Max) {
|
||||
retval = Max;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void cEncoderTypeEntry::Calc_Bit_Precision(double resolution)
|
||||
{
|
||||
//
|
||||
// Calculate the minimum number of bits required to encode this type with
|
||||
// the specified resolution.
|
||||
//
|
||||
|
||||
WWASSERT(Max - Min > -MISCUTIL_EPSILON);
|
||||
WWASSERT(resolution > MISCUTIL_EPSILON);
|
||||
|
||||
double f_units = (double) ceil((Max - Min) / resolution - MISCUTIL_EPSILON) + 1;
|
||||
WWASSERT(f_units <= UINT_MAX + MISCUTIL_EPSILON);
|
||||
UINT units = (UINT) f_units;
|
||||
|
||||
BitPrecision = 0;
|
||||
UINT max_units = 0;
|
||||
while (max_units < units) {
|
||||
max_units += 1 << BitPrecision;
|
||||
BitPrecision++;
|
||||
if (BitPrecision == 1) {
|
||||
max_units++;
|
||||
}
|
||||
}
|
||||
|
||||
WWASSERT(BitPrecision > 0 && BitPrecision <= MAX_BITS);
|
||||
WWASSERT(max_units > 0);
|
||||
|
||||
Resolution = (Max - Min) / (double) (max_units - 1);
|
||||
|
||||
/*TSS2001
|
||||
if (Resolution > 0) {
|
||||
WWASSERT(max_units ==
|
||||
(UINT) ceil((Max - Min) / Resolution - MISCUTIL_EPSILON) + 1);
|
||||
}
|
||||
*/
|
||||
}
|
||||
68
Code/wwbitpack/encodertypeentry.h
Normal file
68
Code/wwbitpack/encodertypeentry.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
** 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: encodertypeentry.h
|
||||
// Project: wwbitpack.lib
|
||||
// Author: Tom Spencer-Smith
|
||||
// Date: June 2000
|
||||
// Description:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#if defined(_MSV_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef ENCODERTYPEENTRY_H
|
||||
#define ENCODERTYPEENTRY_H
|
||||
|
||||
#include "bittype.h"
|
||||
|
||||
class cEncoderTypeEntry
|
||||
{
|
||||
public:
|
||||
cEncoderTypeEntry::cEncoderTypeEntry();
|
||||
|
||||
void Init(double min, double max, double resolution);
|
||||
void Init(int num_bits);
|
||||
|
||||
bool Scale(double value, ULONG & scaled_value);
|
||||
double Unscale(ULONG u_value);
|
||||
double Clamp(double value);
|
||||
|
||||
UINT Get_Bit_Precision() const {return BitPrecision;}
|
||||
double Get_Resolution() const {return Resolution;}
|
||||
|
||||
bool Is_Valid() const;
|
||||
void Invalidate();
|
||||
|
||||
bool Is_Value_In_Range(double value) const;
|
||||
|
||||
private:
|
||||
cEncoderTypeEntry(const cEncoderTypeEntry& source); // Disallow
|
||||
cEncoderTypeEntry& operator=(const cEncoderTypeEntry& rhs); // Disallow
|
||||
|
||||
void Calc_Bit_Precision(double resolution);
|
||||
|
||||
double Min;
|
||||
double Max;
|
||||
double Resolution;
|
||||
UINT BitPrecision;
|
||||
};
|
||||
|
||||
#endif // ENCODERTYPEENTRY_H
|
||||
147
Code/wwbitpack/wwbitpack.dsp
Normal file
147
Code/wwbitpack/wwbitpack.dsp
Normal file
@@ -0,0 +1,147 @@
|
||||
# Microsoft Developer Studio Project File - Name="wwbitpack" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=wwbitpack - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "wwbitpack.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "wwbitpack.mak" CFG="wwbitpack - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "wwbitpack - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "wwbitpack - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "wwbitpack - Win32 Profile" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/Commando/Code/wwbitpack", JAQDAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "wwbitpack - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W4 /WX /Zi /O2 /Ob2 /I "..\wwlib" /I "..\wwdebug" /I "..\wwutil" /D "NDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "WIN32" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"..\libs\Release\wwbitpack.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "wwbitpack - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W4 /WX /Gm /Gi /ZI /Od /I "..\wwlib" /I "..\wwdebug" /I "..\wwutil" /D "_DEBUG" /D "WWDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "WIN32" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"..\libs\Debug\wwbitpack.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "wwbitpack - Win32 Profile"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Profile"
|
||||
# PROP BASE Intermediate_Dir "Profile"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Profile"
|
||||
# PROP Intermediate_Dir "Profile"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W4 /WX /GX /O2 /I "..\wwlib" /I "..\wwdebug" /I "..\wwutil" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /MT /W4 /WX /Zi /O2 /Op /Ob2 /I "..\wwlib" /I "..\wwdebug" /I "..\wwutil" /D "NDEBUG" /D "WWDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "WIN32" /FD /c
|
||||
# SUBTRACT CPP /YX
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo /out:"..\libs\Release\wwbitpack.lib"
|
||||
# ADD LIB32 /nologo /out:"..\libs\Profile\wwbitpack.lib"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "wwbitpack - Win32 Release"
|
||||
# Name "wwbitpack - Win32 Debug"
|
||||
# Name "wwbitpack - Win32 Profile"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BitPacker.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\BitPacker.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\bitpackids.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\bitstream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\bitstream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\encoderlist.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\encoderlist.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\encodertypeentry.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\encodertypeentry.h
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
Reference in New Issue
Block a user