mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 16:21:04 +02:00
965 lines
28 KiB
C++
965 lines
28 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
IceTech GPL Source Code
|
|
Copyright (C) 2026 Justin Marshall
|
|
|
|
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
|
|
|
|
IceTech Source Code 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.
|
|
|
|
IceTech Source Code 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 IceTech Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the IceTech Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the IceTech Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing Justin Marshall, justinmarshall20@gmail.com
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#ifndef __BITMSG_H__
|
|
#define __BITMSG_H__
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
idBitMsg
|
|
|
|
Handles byte ordering and avoids alignment errors.
|
|
Allows concurrent writing and reading.
|
|
The data set with Init is never freed.
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
class idBitMsg {
|
|
public:
|
|
idBitMsg();
|
|
~idBitMsg() {}
|
|
|
|
void Init(byte* data, int length);
|
|
void Init(const byte* data, int length);
|
|
byte* GetData(void); // get data for writing
|
|
const byte* GetData(void) const; // get data for reading
|
|
#ifdef QUAKE4
|
|
const byte* GetReadData(void) const;
|
|
#endif
|
|
int GetMaxSize(void) const; // get the maximum message size
|
|
void SetAllowOverflow(bool set); // generate error if not set and message is overflowed
|
|
bool IsOverflowed(void) const; // returns true if the message was overflowed
|
|
|
|
int GetSize(void) const; // size of the message in bytes
|
|
void SetSize(int size); // set the message size
|
|
int GetWriteBit(void) const; // get current write bit
|
|
void SetWriteBit(int bit); // set current write bit
|
|
int GetNumBitsWritten(void) const; // returns number of bits written
|
|
int GetRemainingWriteBits(void) const; // space left in bits for writing
|
|
void SaveWriteState(int& s, int& b) const; // save the write state
|
|
void RestoreWriteState(int s, int b); // restore the write state
|
|
|
|
int GetReadCount(void) const; // bytes read so far
|
|
void SetReadCount(int bytes); // set the number of bytes and bits read
|
|
int GetReadBit(void) const; // get current read bit
|
|
void SetReadBit(int bit); // set current read bit
|
|
int GetNumBitsRead(void) const; // returns number of bits read
|
|
int GetRemainingReadBits(void) const; // number of bits left to read
|
|
void SaveReadState(int& c, int& b) const; // save the read state
|
|
#ifdef QUAKE4
|
|
void RestoreReadState(int c, int b) const; // restore the read state
|
|
#else
|
|
void RestoreReadState(int c, int b); // restore the read state
|
|
#endif
|
|
|
|
void BeginWriting(void); // begin writing
|
|
int GetRemainingSpace(void) const; // space left in bytes
|
|
void WriteByteAlign(void); // write up to the next byte boundary
|
|
void WriteBits(int value, int numBits); // write the specified number of bits
|
|
void WriteChar(int c);
|
|
void WriteByte(int c);
|
|
void WriteShort(int c);
|
|
void WriteUShort(int c);
|
|
void WriteLong(int c);
|
|
void WriteFloat(float f);
|
|
void WriteFloat(float f, int exponentBits, int mantissaBits);
|
|
void WriteAngle8(float f);
|
|
void WriteAngle16(float f);
|
|
void WriteDir(const idVec3& dir, int numBits);
|
|
void WriteString(const char* s, int maxLength = -1, bool make7Bit = true);
|
|
void WriteData(const void* data, int length);
|
|
void WriteNetadr(const netadr_t adr);
|
|
|
|
void WriteDeltaChar(int oldValue, int newValue);
|
|
void WriteDeltaByte(int oldValue, int newValue);
|
|
void WriteDeltaShort(int oldValue, int newValue);
|
|
void WriteDeltaLong(int oldValue, int newValue);
|
|
void WriteDeltaFloat(float oldValue, float newValue);
|
|
void WriteDeltaFloat(float oldValue, float newValue, int exponentBits, int mantissaBits);
|
|
void WriteDeltaByteCounter(int oldValue, int newValue);
|
|
void WriteDeltaShortCounter(int oldValue, int newValue);
|
|
void WriteDeltaLongCounter(int oldValue, int newValue);
|
|
bool WriteDeltaDict(const idDict& dict, const idDict* base);
|
|
|
|
void BeginReading(void) const; // begin reading.
|
|
int GetRemaingData(void) const; // number of bytes left to read
|
|
#ifdef QUAKE4
|
|
int GetRemainingData(void) const; // number of bytes left to read
|
|
#endif
|
|
void ReadByteAlign(void) const; // read up to the next byte boundary
|
|
int ReadBits(int numBits) const; // read the specified number of bits
|
|
int ReadChar(void) const;
|
|
int ReadByte(void) const;
|
|
int ReadShort(void) const;
|
|
int ReadUShort(void) const;
|
|
int ReadLong(void) const;
|
|
float ReadFloat(void) const;
|
|
float ReadFloat(int exponentBits, int mantissaBits) const;
|
|
float ReadAngle8(void) const;
|
|
float ReadAngle16(void) const;
|
|
idVec3 ReadDir(int numBits) const;
|
|
int ReadString(char* buffer, int bufferSize) const;
|
|
int ReadData(void* data, int length) const;
|
|
void ReadNetadr(netadr_t* adr) const;
|
|
|
|
void WriteVec3(const idVec3& vector);
|
|
void WriteMat3(const idMat3& axis);
|
|
void WriteBool(bool boolean);
|
|
|
|
idVec3 ReadVec3() const;
|
|
idMat3 ReadMat3() const;
|
|
bool ReadBool() const;
|
|
|
|
int ReadDeltaChar(int oldValue) const;
|
|
int ReadDeltaByte(int oldValue) const;
|
|
int ReadDeltaShort(int oldValue) const;
|
|
int ReadDeltaLong(int oldValue) const;
|
|
float ReadDeltaFloat(float oldValue) const;
|
|
float ReadDeltaFloat(float oldValue, int exponentBits, int mantissaBits) const;
|
|
int ReadDeltaByteCounter(int oldValue) const;
|
|
int ReadDeltaShortCounter(int oldValue) const;
|
|
int ReadDeltaLongCounter(int oldValue) const;
|
|
bool ReadDeltaDict(idDict& dict, const idDict* base) const;
|
|
|
|
static int DirToBits(const idVec3& dir, int numBits);
|
|
static idVec3 BitsToDir(int bits, int numBits);
|
|
|
|
private:
|
|
byte* writeData; // pointer to data for writing
|
|
const byte* readData; // pointer to data for reading
|
|
int maxSize; // maximum size of message in bytes
|
|
int curSize; // current size of message in bytes
|
|
int writeBit; // number of bits written to the last written byte
|
|
mutable int readCount; // number of bytes read so far
|
|
mutable int readBit; // number of bits read from the last read byte
|
|
bool allowOverflow; // if false, generate an error when the message is overflowed
|
|
bool overflowed; // set to true if the buffer size failed (with allowOverflow set)
|
|
|
|
private:
|
|
bool CheckOverflow(int numBits);
|
|
byte* GetByteSpace(int length);
|
|
void WriteDelta(int oldValue, int newValue, int numBits);
|
|
int ReadDelta(int oldValue, int numBits) const;
|
|
};
|
|
|
|
|
|
ID_INLINE void idBitMsg::Init(byte* data, int length) {
|
|
writeData = data;
|
|
readData = data;
|
|
maxSize = length;
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::Init(const byte* data, int length) {
|
|
writeData = NULL;
|
|
readData = data;
|
|
maxSize = length;
|
|
}
|
|
|
|
ID_INLINE byte* idBitMsg::GetData(void) {
|
|
return writeData;
|
|
}
|
|
|
|
ID_INLINE const byte* idBitMsg::GetData(void) const {
|
|
return readData;
|
|
}
|
|
|
|
#ifdef QUAKE4
|
|
ID_INLINE const byte* idBitMsg::GetReadData(void) const {
|
|
return (readData + readCount);
|
|
}
|
|
#endif
|
|
|
|
ID_INLINE int idBitMsg::GetMaxSize(void) const {
|
|
return maxSize;
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::SetAllowOverflow(bool set) {
|
|
allowOverflow = set;
|
|
}
|
|
|
|
ID_INLINE bool idBitMsg::IsOverflowed(void) const {
|
|
return overflowed;
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetSize(void) const {
|
|
return curSize;
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::SetSize(int size) {
|
|
if (size > maxSize) {
|
|
curSize = maxSize;
|
|
}
|
|
else {
|
|
curSize = size;
|
|
}
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetWriteBit(void) const {
|
|
return writeBit;
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::SetWriteBit(int bit) {
|
|
writeBit = bit & 7;
|
|
if (writeBit) {
|
|
writeData[curSize - 1] &= (1 << writeBit) - 1;
|
|
}
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetNumBitsWritten(void) const {
|
|
return ((curSize << 3) - ((8 - writeBit) & 7));
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetRemainingWriteBits(void) const {
|
|
return (maxSize << 3) - GetNumBitsWritten();
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::SaveWriteState(int& s, int& b) const {
|
|
s = curSize;
|
|
b = writeBit;
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::RestoreWriteState(int s, int b) {
|
|
curSize = s;
|
|
writeBit = b & 7;
|
|
if (writeBit) {
|
|
writeData[curSize - 1] &= (1 << writeBit) - 1;
|
|
}
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetReadCount(void) const {
|
|
return readCount;
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::SetReadCount(int bytes) {
|
|
readCount = bytes;
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetReadBit(void) const {
|
|
return readBit;
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::SetReadBit(int bit) {
|
|
readBit = bit & 7;
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetNumBitsRead(void) const {
|
|
return ((readCount << 3) - ((8 - readBit) & 7));
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetRemainingReadBits(void) const {
|
|
return (curSize << 3) - GetNumBitsRead();
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::SaveReadState(int& c, int& b) const {
|
|
c = readCount;
|
|
b = readBit;
|
|
}
|
|
|
|
#ifdef QUAKE4
|
|
ID_INLINE void idBitMsg::RestoreReadState(int c, int b) const {
|
|
readCount = c;
|
|
readBit = b & 7;
|
|
}
|
|
#else
|
|
ID_INLINE void idBitMsg::RestoreReadState(int c, int b) {
|
|
readCount = c;
|
|
readBit = b & 7;
|
|
}
|
|
#endif
|
|
|
|
ID_INLINE void idBitMsg::BeginWriting(void) {
|
|
curSize = 0;
|
|
overflowed = false;
|
|
writeBit = 0;
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetRemainingSpace(void) const {
|
|
return maxSize - curSize;
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteByteAlign(void) {
|
|
writeBit = 0;
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteChar(int c) {
|
|
WriteBits(c, -8);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteByte(int c) {
|
|
WriteBits(c, 8);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteShort(int c) {
|
|
WriteBits(c, -16);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteUShort(int c) {
|
|
WriteBits(c, 16);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteLong(int c) {
|
|
WriteBits(c, 32);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteFloat(float f) {
|
|
WriteBits(*reinterpret_cast<int*>(&f), 32);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteFloat(float f, int exponentBits, int mantissaBits) {
|
|
int bits = idMath::FloatToBits(f, exponentBits, mantissaBits);
|
|
WriteBits(bits, 1 + exponentBits + mantissaBits);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteAngle8(float f) {
|
|
WriteByte(ANGLE2BYTE(f));
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteAngle16(float f) {
|
|
WriteShort(ANGLE2SHORT(f));
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteDir(const idVec3& dir, int numBits) {
|
|
WriteBits(DirToBits(dir, numBits), numBits);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteDeltaChar(int oldValue, int newValue) {
|
|
WriteDelta(oldValue, newValue, -8);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteDeltaByte(int oldValue, int newValue) {
|
|
WriteDelta(oldValue, newValue, 8);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteDeltaShort(int oldValue, int newValue) {
|
|
WriteDelta(oldValue, newValue, -16);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteDeltaLong(int oldValue, int newValue) {
|
|
WriteDelta(oldValue, newValue, 32);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteDeltaFloat(float oldValue, float newValue) {
|
|
WriteDelta(*reinterpret_cast<int*>(&oldValue), *reinterpret_cast<int*>(&newValue), 32);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteDeltaFloat(float oldValue, float newValue, int exponentBits, int mantissaBits) {
|
|
int oldBits = idMath::FloatToBits(oldValue, exponentBits, mantissaBits);
|
|
int newBits = idMath::FloatToBits(newValue, exponentBits, mantissaBits);
|
|
WriteDelta(oldBits, newBits, 1 + exponentBits + mantissaBits);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::BeginReading(void) const {
|
|
readCount = 0;
|
|
readBit = 0;
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::GetRemaingData(void) const {
|
|
return curSize - readCount;
|
|
}
|
|
|
|
#ifdef QUAKE4
|
|
ID_INLINE int idBitMsg::GetRemainingData(void) const {
|
|
return curSize - readCount;
|
|
}
|
|
#endif
|
|
|
|
ID_INLINE void idBitMsg::ReadByteAlign(void) const {
|
|
readBit = 0;
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::ReadChar(void) const {
|
|
return (signed char)ReadBits(-8);
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::ReadByte(void) const {
|
|
return (unsigned char)ReadBits(8);
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::ReadShort(void) const {
|
|
return (short)ReadBits(-16);
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::ReadUShort(void) const {
|
|
return (unsigned short)ReadBits(16);
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::ReadLong(void) const {
|
|
return ReadBits(32);
|
|
}
|
|
|
|
ID_INLINE float idBitMsg::ReadFloat(void) const {
|
|
float value;
|
|
*reinterpret_cast<int*>(&value) = ReadBits(32);
|
|
return value;
|
|
}
|
|
|
|
ID_INLINE float idBitMsg::ReadFloat(int exponentBits, int mantissaBits) const {
|
|
int bits = ReadBits(1 + exponentBits + mantissaBits);
|
|
return idMath::BitsToFloat(bits, exponentBits, mantissaBits);
|
|
}
|
|
|
|
ID_INLINE float idBitMsg::ReadAngle8(void) const {
|
|
return BYTE2ANGLE(ReadByte());
|
|
}
|
|
|
|
ID_INLINE float idBitMsg::ReadAngle16(void) const {
|
|
return SHORT2ANGLE(ReadShort());
|
|
}
|
|
|
|
ID_INLINE idVec3 idBitMsg::ReadDir(int numBits) const {
|
|
return BitsToDir(ReadBits(numBits), numBits);
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::ReadDeltaChar(int oldValue) const {
|
|
return (signed char)ReadDelta(oldValue, -8);
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::ReadDeltaByte(int oldValue) const {
|
|
return (unsigned char)ReadDelta(oldValue, 8);
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::ReadDeltaShort(int oldValue) const {
|
|
return (short)ReadDelta(oldValue, -16);
|
|
}
|
|
|
|
ID_INLINE int idBitMsg::ReadDeltaLong(int oldValue) const {
|
|
return ReadDelta(oldValue, 32);
|
|
}
|
|
|
|
ID_INLINE float idBitMsg::ReadDeltaFloat(float oldValue) const {
|
|
float value;
|
|
*reinterpret_cast<int*>(&value) = ReadDelta(*reinterpret_cast<int*>(&oldValue), 32);
|
|
return value;
|
|
}
|
|
|
|
ID_INLINE float idBitMsg::ReadDeltaFloat(float oldValue, int exponentBits, int mantissaBits) const {
|
|
int oldBits = idMath::FloatToBits(oldValue, exponentBits, mantissaBits);
|
|
int newBits = ReadDelta(oldBits, 1 + exponentBits + mantissaBits);
|
|
return idMath::BitsToFloat(newBits, exponentBits, mantissaBits);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteVec3(const idVec3& vector) {
|
|
WriteFloat(vector[0]);
|
|
WriteFloat(vector[1]);
|
|
WriteFloat(vector[2]);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteMat3(const idMat3& axis) {
|
|
WriteVec3(axis[0]);
|
|
WriteVec3(axis[1]);
|
|
WriteVec3(axis[2]);
|
|
}
|
|
|
|
ID_INLINE void idBitMsg::WriteBool(bool boolean) {
|
|
WriteBits(boolean, 1);
|
|
}
|
|
|
|
ID_INLINE idVec3 idBitMsg::ReadVec3() const {
|
|
idVec3 vector;
|
|
vector[0] = ReadFloat();
|
|
vector[1] = ReadFloat();
|
|
vector[2] = ReadFloat();
|
|
return vector;
|
|
}
|
|
|
|
ID_INLINE idMat3 idBitMsg::ReadMat3() const {
|
|
idMat3 axis;
|
|
axis[0] = ReadVec3();
|
|
axis[1] = ReadVec3();
|
|
axis[2] = ReadVec3();
|
|
return axis;
|
|
}
|
|
|
|
ID_INLINE bool idBitMsg::ReadBool() const {
|
|
int boolean = ReadBits(1);
|
|
return *(bool*)&boolean;//We seem to get a performance warning unless I do this. Ick!
|
|
}
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
idBitMsgDelta
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
class idBitMsgDelta {
|
|
public:
|
|
idBitMsgDelta();
|
|
~idBitMsgDelta() {}
|
|
|
|
void Init(const idBitMsg* base, idBitMsg* newBase, idBitMsg* delta);
|
|
void Init(const idBitMsg* base, idBitMsg* newBase, const idBitMsg* delta);
|
|
#ifdef QUAKE4
|
|
void InitWriting(const idBitMsg* base, idBitMsg* newBase, idBitMsg* delta);
|
|
void InitReading(const idBitMsg* base, idBitMsg* newBase, const idBitMsg* delta);
|
|
#endif
|
|
bool HasChanged(void) const;
|
|
|
|
void WriteBits(int value, int numBits);
|
|
void WriteChar(int c);
|
|
void WriteByte(int c);
|
|
void WriteShort(int c);
|
|
void WriteUShort(int c);
|
|
void WriteLong(int c);
|
|
void WriteFloat(float f);
|
|
void WriteFloat(float f, int exponentBits, int mantissaBits);
|
|
#ifdef QUAKE4
|
|
void WriteVec3(const idVec3& v);
|
|
void WriteDeltaVec3(const idVec3& oldValue, const idVec3& newValue);
|
|
void WriteVec4(const idVec4& v);
|
|
void WriteDeltaVec4(const idVec4& oldValue, const idVec4& newValue);
|
|
void WriteQuat(const idQuat& q);
|
|
void WriteDeltaQuat(const idQuat& oldValue, const idQuat& newValue);
|
|
void WriteMat3(const idMat3& m);
|
|
void WriteDeltaMat3(const idMat3& oldValue, const idMat3& newValue);
|
|
#endif
|
|
void WriteAngle8(float f);
|
|
void WriteAngle16(float f);
|
|
void WriteDir(const idVec3& dir, int numBits);
|
|
void WriteString(const char* s, int maxLength = -1);
|
|
void WriteData(const void* data, int length);
|
|
void WriteDict(const idDict& dict);
|
|
|
|
void WriteDeltaChar(int oldValue, int newValue);
|
|
void WriteDeltaByte(int oldValue, int newValue);
|
|
void WriteDeltaShort(int oldValue, int newValue);
|
|
void WriteDeltaLong(int oldValue, int newValue);
|
|
void WriteDeltaFloat(float oldValue, float newValue);
|
|
void WriteDeltaFloat(float oldValue, float newValue, int exponentBits, int mantissaBits);
|
|
void WriteDeltaByteCounter(int oldValue, int newValue);
|
|
void WriteDeltaShortCounter(int oldValue, int newValue);
|
|
void WriteDeltaLongCounter(int oldValue, int newValue);
|
|
|
|
int ReadBits(int numBits) const;
|
|
int ReadChar(void) const;
|
|
int ReadByte(void) const;
|
|
int ReadShort(void) const;
|
|
int ReadUShort(void) const;
|
|
int ReadLong(void) const;
|
|
float ReadFloat(void) const;
|
|
float ReadFloat(int exponentBits, int mantissaBits) const;
|
|
#ifdef QUAKE4
|
|
idVec3 ReadVec3(void) const;
|
|
idVec3 ReadDeltaVec3(const idVec3& oldValue) const;
|
|
idVec4 ReadVec4(void) const;
|
|
idVec4 ReadDeltaVec4(const idVec4& oldValue) const;
|
|
idQuat ReadQuat(void) const;
|
|
idQuat ReadDeltaQuat(const idQuat& oldValue) const;
|
|
idMat3 ReadMat3(void) const;
|
|
idMat3 ReadDeltaMat3(const idMat3& oldValue) const;
|
|
#endif
|
|
float ReadAngle8(void) const;
|
|
float ReadAngle16(void) const;
|
|
idVec3 ReadDir(int numBits) const;
|
|
void ReadString(char* buffer, int bufferSize) const;
|
|
void ReadData(void* data, int length) const;
|
|
void ReadDict(idDict& dict);
|
|
|
|
int ReadDeltaChar(int oldValue) const;
|
|
int ReadDeltaByte(int oldValue) const;
|
|
int ReadDeltaShort(int oldValue) const;
|
|
int ReadDeltaLong(int oldValue) const;
|
|
float ReadDeltaFloat(float oldValue) const;
|
|
float ReadDeltaFloat(float oldValue, int exponentBits, int mantissaBits) const;
|
|
int ReadDeltaByteCounter(int oldValue) const;
|
|
int ReadDeltaShortCounter(int oldValue) const;
|
|
int ReadDeltaLongCounter(int oldValue) const;
|
|
|
|
private:
|
|
const idBitMsg* base; // base
|
|
idBitMsg* newBase; // new base
|
|
idBitMsg* writeDelta; // delta from base to new base for writing
|
|
const idBitMsg* readDelta; // delta from base to new base for reading
|
|
mutable bool changed; // true if the new base is different from the base
|
|
|
|
private:
|
|
void WriteDelta(int oldValue, int newValue, int numBits);
|
|
int ReadDelta(int oldValue, int numBits) const;
|
|
};
|
|
|
|
ID_INLINE idBitMsgDelta::idBitMsgDelta() {
|
|
base = NULL;
|
|
newBase = NULL;
|
|
writeDelta = NULL;
|
|
readDelta = NULL;
|
|
changed = false;
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::Init(const idBitMsg* base, idBitMsg* newBase, idBitMsg* delta) {
|
|
this->base = base;
|
|
this->newBase = newBase;
|
|
this->writeDelta = delta;
|
|
this->readDelta = delta;
|
|
this->changed = false;
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::Init(const idBitMsg* base, idBitMsg* newBase, const idBitMsg* delta) {
|
|
this->base = base;
|
|
this->newBase = newBase;
|
|
this->writeDelta = NULL;
|
|
this->readDelta = delta;
|
|
this->changed = false;
|
|
}
|
|
|
|
#ifdef QUAKE4
|
|
ID_INLINE void idBitMsgDelta::InitWriting(const idBitMsg* base, idBitMsg* newBase, idBitMsg* delta) {
|
|
Init(base, newBase, delta);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::InitReading(const idBitMsg* base, idBitMsg* newBase, const idBitMsg* delta) {
|
|
Init(base, newBase, delta);
|
|
}
|
|
#endif
|
|
|
|
ID_INLINE bool idBitMsgDelta::HasChanged(void) const {
|
|
return changed;
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteChar(int c) {
|
|
WriteBits(c, -8);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteByte(int c) {
|
|
WriteBits(c, 8);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteShort(int c) {
|
|
WriteBits(c, -16);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteUShort(int c) {
|
|
WriteBits(c, 16);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteLong(int c) {
|
|
WriteBits(c, 32);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteFloat(float f) {
|
|
WriteBits(*reinterpret_cast<int*>(&f), 32);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteFloat(float f, int exponentBits, int mantissaBits) {
|
|
int bits = idMath::FloatToBits(f, exponentBits, mantissaBits);
|
|
WriteBits(bits, 1 + exponentBits + mantissaBits);
|
|
}
|
|
|
|
#ifdef QUAKE4
|
|
ID_INLINE void idBitMsgDelta::WriteVec3(const idVec3& v) {
|
|
for (int ix = 0; ix < v.GetDimension(); ++ix) {
|
|
WriteFloat(v[ix]);
|
|
}
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaVec3(const idVec3& oldValue, const idVec3& newValue) {
|
|
for (int ix = 0; ix < oldValue.GetDimension(); ++ix) {
|
|
WriteDeltaFloat(oldValue[ix], newValue[ix]);
|
|
}
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteVec4(const idVec4& v) {
|
|
for (int ix = 0; ix < v.GetDimension(); ++ix) {
|
|
WriteFloat(v[ix]);
|
|
}
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaVec4(const idVec4& oldValue, const idVec4& newValue) {
|
|
for (int ix = 0; ix < oldValue.GetDimension(); ++ix) {
|
|
WriteDeltaFloat(oldValue[ix], newValue[ix]);
|
|
}
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteQuat(const idQuat& q) {
|
|
for (int ix = 0; ix < q.GetDimension(); ++ix) {
|
|
WriteFloat(q[ix]);
|
|
}
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaQuat(const idQuat& oldValue, const idQuat& newValue) {
|
|
for (int ix = 0; ix < oldValue.GetDimension(); ++ix) {
|
|
WriteDeltaFloat(oldValue[ix], newValue[ix]);
|
|
}
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteMat3(const idMat3& m) {
|
|
for (int ix = 0; ix < m.GetVec3Dimension(); ++ix) {
|
|
WriteVec3(m[ix]);
|
|
}
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaMat3(const idMat3& oldValue, const idMat3& newValue) {
|
|
for (int ix = 0; ix < oldValue.GetVec3Dimension(); ++ix) {
|
|
WriteDeltaVec3(oldValue[ix], newValue[ix]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteAngle8(float f) {
|
|
WriteBits(ANGLE2BYTE(f), 8);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteAngle16(float f) {
|
|
WriteBits(ANGLE2SHORT(f), 16);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDir(const idVec3& dir, int numBits) {
|
|
WriteBits(idBitMsg::DirToBits(dir, numBits), numBits);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaChar(int oldValue, int newValue) {
|
|
WriteDelta(oldValue, newValue, -8);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaByte(int oldValue, int newValue) {
|
|
WriteDelta(oldValue, newValue, 8);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaShort(int oldValue, int newValue) {
|
|
WriteDelta(oldValue, newValue, -16);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaLong(int oldValue, int newValue) {
|
|
WriteDelta(oldValue, newValue, 32);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaFloat(float oldValue, float newValue) {
|
|
WriteDelta(*reinterpret_cast<int*>(&oldValue), *reinterpret_cast<int*>(&newValue), 32);
|
|
}
|
|
|
|
ID_INLINE void idBitMsgDelta::WriteDeltaFloat(float oldValue, float newValue, int exponentBits, int mantissaBits) {
|
|
int oldBits = idMath::FloatToBits(oldValue, exponentBits, mantissaBits);
|
|
int newBits = idMath::FloatToBits(newValue, exponentBits, mantissaBits);
|
|
WriteDelta(oldBits, newBits, 1 + exponentBits + mantissaBits);
|
|
}
|
|
|
|
ID_INLINE int idBitMsgDelta::ReadChar(void) const {
|
|
return (signed char)ReadBits(-8);
|
|
}
|
|
|
|
ID_INLINE int idBitMsgDelta::ReadByte(void) const {
|
|
return (unsigned char)ReadBits(8);
|
|
}
|
|
|
|
ID_INLINE int idBitMsgDelta::ReadShort(void) const {
|
|
return (short)ReadBits(-16);
|
|
}
|
|
|
|
ID_INLINE int idBitMsgDelta::ReadUShort(void) const {
|
|
return (unsigned short)ReadBits(16);
|
|
}
|
|
|
|
ID_INLINE int idBitMsgDelta::ReadLong(void) const {
|
|
return ReadBits(32);
|
|
}
|
|
|
|
ID_INLINE float idBitMsgDelta::ReadFloat(void) const {
|
|
float value;
|
|
*reinterpret_cast<int*>(&value) = ReadBits(32);
|
|
return value;
|
|
}
|
|
|
|
ID_INLINE float idBitMsgDelta::ReadFloat(int exponentBits, int mantissaBits) const {
|
|
int bits = ReadBits(1 + exponentBits + mantissaBits);
|
|
return idMath::BitsToFloat(bits, exponentBits, mantissaBits);
|
|
}
|
|
|
|
#ifdef QUAKE4
|
|
ID_INLINE idVec3 idBitMsgDelta::ReadVec3(void) const {
|
|
idVec3 v;
|
|
for (int ix = 0; ix < v.GetDimension(); ++ix) {
|
|
v[ix] = ReadFloat();
|
|
}
|
|
return v;
|
|
}
|
|
|
|
ID_INLINE idVec3 idBitMsgDelta::ReadDeltaVec3(const idVec3& oldValue) const {
|
|
idVec3 value;
|
|
for (int ix = 0; ix < value.GetDimension(); ++ix) {
|
|
value[ix] = ReadDeltaFloat(oldValue[ix]);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
ID_INLINE idVec4 idBitMsgDelta::ReadVec4(void) const {
|
|
idVec4 v;
|
|
for (int ix = 0; ix < v.GetDimension(); ++ix) {
|
|
v[ix] = ReadFloat();
|
|
}
|
|
return v;
|
|
}
|
|
|
|
ID_INLINE idVec4 idBitMsgDelta::ReadDeltaVec4(const idVec4& oldValue) const {
|
|
idVec4 value;
|
|
for (int ix = 0; ix < value.GetDimension(); ++ix) {
|
|
value[ix] = ReadDeltaFloat(oldValue[ix]);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
ID_INLINE idQuat idBitMsgDelta::ReadQuat(void) const {
|
|
idQuat q;
|
|
for (int ix = 0; ix < q.GetDimension(); ++ix) {
|
|
q[ix] = ReadFloat();
|
|
}
|
|
return q;
|
|
}
|
|
|
|
ID_INLINE idQuat idBitMsgDelta::ReadDeltaQuat(const idQuat& oldValue) const {
|
|
idQuat value;
|
|
for (int ix = 0; ix < value.GetDimension(); ++ix) {
|
|
value[ix] = ReadDeltaFloat(oldValue[ix]);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
ID_INLINE idMat3 idBitMsgDelta::ReadMat3(void) const {
|
|
idMat3 m;
|
|
for (int ix = 0; ix < m.GetVec3Dimension(); ++ix) {
|
|
m[ix] = ReadVec3();
|
|
}
|
|
return m;
|
|
}
|
|
|
|
ID_INLINE idMat3 idBitMsgDelta::ReadDeltaMat3(const idMat3& oldValue) const {
|
|
idMat3 value;
|
|
for (int ix = 0; ix < value.GetVec3Dimension(); ++ix) {
|
|
value[ix] = ReadDeltaVec3(oldValue[ix]);
|
|
}
|
|
return value;
|
|
}
|
|
#endif
|
|
|
|
ID_INLINE float idBitMsgDelta::ReadAngle8(void) const {
|
|
return BYTE2ANGLE(ReadByte());
|
|
}
|
|
|
|
ID_INLINE float idBitMsgDelta::ReadAngle16(void) const {
|
|
return SHORT2ANGLE(ReadShort());
|
|
}
|
|
|
|
ID_INLINE idVec3 idBitMsgDelta::ReadDir(int numBits) const {
|
|
return idBitMsg::BitsToDir(ReadBits(numBits), numBits);
|
|
}
|
|
|
|
ID_INLINE int idBitMsgDelta::ReadDeltaChar(int oldValue) const {
|
|
return (signed char)ReadDelta(oldValue, -8);
|
|
}
|
|
|
|
ID_INLINE int idBitMsgDelta::ReadDeltaByte(int oldValue) const {
|
|
return (unsigned char)ReadDelta(oldValue, 8);
|
|
}
|
|
|
|
ID_INLINE int idBitMsgDelta::ReadDeltaShort(int oldValue) const {
|
|
return (short)ReadDelta(oldValue, -16);
|
|
}
|
|
|
|
ID_INLINE int idBitMsgDelta::ReadDeltaLong(int oldValue) const {
|
|
return ReadDelta(oldValue, 32);
|
|
}
|
|
|
|
ID_INLINE float idBitMsgDelta::ReadDeltaFloat(float oldValue) const {
|
|
float value;
|
|
*reinterpret_cast<int*>(&value) = ReadDelta(*reinterpret_cast<int*>(&oldValue), 32);
|
|
return value;
|
|
}
|
|
|
|
ID_INLINE float idBitMsgDelta::ReadDeltaFloat(float oldValue, int exponentBits, int mantissaBits) const {
|
|
int oldBits = idMath::FloatToBits(oldValue, exponentBits, mantissaBits);
|
|
int newBits = ReadDelta(oldBits, 1 + exponentBits + mantissaBits);
|
|
return idMath::BitsToFloat(newBits, exponentBits, mantissaBits);
|
|
}
|
|
|
|
#ifdef QUAKE4
|
|
#define MAX_MSG_QUEUE_SIZE 16384 // must be a power of 2
|
|
|
|
class idMsgQueue {
|
|
public:
|
|
idMsgQueue();
|
|
|
|
void Init(int sequence);
|
|
|
|
bool Add(const byte* data, const int size, bool sequencing);
|
|
// prepend to a message without the need to a memcopy and readjust
|
|
bool AddConcat(const byte* data1, const int size1, const byte* data2, const int size2, bool sequencing);
|
|
bool Get(byte* data, int dataSize, int& size, bool sequencing);
|
|
int GetTotalSize(void) const;
|
|
int GetSpaceLeft(void) const;
|
|
int GetFirst(void) const { return first; }
|
|
int GetLast(void) const { return last; }
|
|
void CopyToBuffer(byte* buf) const;
|
|
|
|
void WriteTo(idBitMsg& msg);
|
|
void FlushTo(idBitMsg& msg);
|
|
void ReadFrom(const idBitMsg& msg);
|
|
|
|
void Save(idFile* file) const;
|
|
void Restore(idFile* file);
|
|
|
|
private:
|
|
byte buffer[MAX_MSG_QUEUE_SIZE];
|
|
int first; // sequence number of first message in queue
|
|
int last; // sequence number of last message in queue
|
|
int startIndex; // index pointing to the first byte of the first message
|
|
int endIndex; // index pointing to the first byte after the last message
|
|
|
|
public:
|
|
void WriteByte(byte b);
|
|
byte ReadByte(void);
|
|
void WriteShort(int s);
|
|
void WriteUShort(int s);
|
|
int ReadShort(void);
|
|
int ReadUShort(void);
|
|
void WriteLong(int l);
|
|
int ReadLong(void);
|
|
void WriteData(const byte* data, const int size);
|
|
void ReadData(byte* data, const int size);
|
|
};
|
|
|
|
class idBitMsgQueue {
|
|
public:
|
|
idBitMsgQueue();
|
|
|
|
void Init(void);
|
|
|
|
void Add(const idBitMsg& msg, const int timestamp);
|
|
bool Get(idBitMsg& msg, int& timestamp);
|
|
bool Get(idBitMsg& msg) { int dummy; return Get(msg, dummy); }
|
|
bool GetTimestamp(int& timestamp);
|
|
|
|
private:
|
|
int nextTimestamp;
|
|
bool readTimestamp;
|
|
idLinkList<idMsgQueue> writeList, readList;
|
|
};
|
|
#endif
|
|
|
|
#endif /* !__BITMSG_H__ */
|