| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- /*
- ** 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
|