ReplicatorID ReplicatorID::Null; char AssetsDirectory1[MAX_PATH]; HWND hWindow; MemoryStream::MemoryStream( void *stream_start, DWORD stream_size, DWORD initial_offset ) { Check_Pointer(this); streamStart = static_cast(stream_start); highWaterByte = streamStart; streamSize = stream_size; Verify(initial_offset <= stream_size); currentPosition = streamStart + initial_offset; currentBit = Empty_Bit_Buffer; } MemoryStream::~MemoryStream() { } MemoryStream& MemoryStream::ReadBytes( void *ptr, DWORD number_of_bytes ) { Check_Object(this); Check_Pointer(ptr); Verify(number_of_bytes > 0); #if defined(_ARMOR) DWORD remaining = GetBytesRemaining(); Verify(remaining >= number_of_bytes); #endif memcpy(ptr, GetPointer(), number_of_bytes); AdvancePointer(number_of_bytes); return *this; } MemoryStream& MemoryStream::WriteBytes( const void *ptr, DWORD number_of_bytes ) { Check_Object(this); Check_Pointer(ptr); Verify(number_of_bytes > 0); memcpy(GetPointer(), ptr, number_of_bytes); AdvancePointer(number_of_bytes); return *this; } void MemoryStream::WriteByteAlign() { if (currentBit == 0 || currentBit == Empty_Bit_Buffer) { return; } Check_Object(this); //SPEW(("jerryeds", "WRITE : %x", workingBitBuffer)); WriteBytes(&workingBitBuffer, 1); workingBitBuffer = 0x00; currentBit = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void MemoryStream::ReadByteAlign() { if (currentBit == Empty_Bit_Buffer) { return; } Check_Object(this); // we just read this byte but didn't read any bits.. // so unread it. if (currentBit == 0) { RewindPointer(1); } // this will trigger the next read... currentBit = Empty_Bit_Buffer; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MemoryStream& MemoryStream::ReadBit(bool &bit_value) { Check_Object(this); int result = 0; if (currentBit == Empty_Bit_Buffer) { ReadBytes(&workingBitBuffer, 1); //SPEW(("jerryeds", "READ : %x", workingBitBuffer)); currentBit = 0; } Verify(currentBit >= 0); Verify(currentBit < 8); result = (0x01 & (workingBitBuffer >> currentBit)); bit_value = (result)?true:false; currentBit++; if (currentBit > 7) { if (GetBytesRemaining()) { ReadBytes(&workingBitBuffer, 1); //SPEW(("jerryeds", "READ : %x", workingBitBuffer)); currentBit = 0; } else { currentBit = Empty_Bit_Buffer; } } return *this; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // MemoryStream& MemoryStream::WriteBit(const bool &bit_value) { Check_Object(this); int int_bit_value = (bit_value)?1:0; if (currentBit == Empty_Bit_Buffer) { currentBit = 0; workingBitBuffer = 0x0; } Verify(currentBit >= 0); Verify(currentBit < 8); workingBitBuffer |= (int_bit_value << currentBit); currentBit++; if (currentBit > 7) { WriteBytes(&workingBitBuffer, 1); //SPEW(("jerryeds", "WRITE : %x", workingBitBuffer)); workingBitBuffer = 0x00; currentBit = 0; } return *this; } Adept::AdeptNetMissionParameters::AdeptNetMissionParameters() { ResetParameters(); } void Adept::AdeptNetMissionParameters::ResetParameters(void) { m_runDedicated = 0; m_closedGame = 0; m_playerLimit = 16; m_visibility = 0; } void Adept::AdeptNetMissionParameters::SaveParameters(DynamicMemoryStream *stream) { stream->WriteBits(&m_runDedicated, 1); stream->WriteBits(&m_closedGame, 1); stream->WriteBits(&m_playerLimit, 8); // 256 stream->WriteBits(&m_visibility,3);//5 } void Adept::AdeptNetMissionParameters::LoadParameters(MemoryStream *stream) { stream->ReadBits(&m_runDedicated, 1); stream->ReadBits(&m_closedGame, 1); stream->ReadBits(&m_playerLimit, 8);// 256 stream->ReadBits(&m_visibility,3);//5 } NetMissionParameters::TeamParameters::TeamParameters() { ResetParameters(0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NetMissionParameters::TeamParameters::ResetParameters(int index) { m_maxPlayersOnTeam = 16; m_minimumTonnage = 0; m_maximumTonnage = 100; m_maximumTotalTonnage = 1600; m_currentTotalTonnage = 0; m_skin = (int)'0'; m_skin += index; m_alignment = index; m_allowedMech[0] = 0xffffffff; m_allowedBeam[0] = 0xfffffffd; m_allowedMissile[0] = 0xff3bffff; m_allowedProjectile[0] = 0xffffdfff; m_allowedSubsystem[0] = 0xffffffff; m_allowedMech[1] = 0xffffffff; m_allowedBeam[1] = 0xffffffff; m_allowedMissile[1] = 0xffffffff; m_allowedProjectile[1] = 0xffffffff; m_allowedSubsystem[1] = 0xffffffff; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NetMissionParameters::TeamParameters::SaveParameters(DynamicMemoryStream *stream) { stream->WriteBits(&m_maxPlayersOnTeam,7); stream->WriteBits(&m_minimumTonnage,8); stream->WriteBits(&m_maximumTonnage,8); stream->WriteBits(&m_maximumTotalTonnage,16); stream->WriteBits(&m_currentTotalTonnage,8*sizeof(Scalar)); stream->WriteBits(&m_skin,8); stream->WriteBits(&m_alignment,4); stream->WriteBits(&m_allowedMech[0],32); stream->WriteBits(&m_allowedBeam[0],32); stream->WriteBits(&m_allowedMissile[0],32); stream->WriteBits(&m_allowedProjectile[0],32); stream->WriteBits(&m_allowedSubsystem[0],32); stream->WriteBits(&m_allowedMech[1],32); stream->WriteBits(&m_allowedBeam[1],32); stream->WriteBits(&m_allowedMissile[1],32); stream->WriteBits(&m_allowedProjectile[1],32); stream->WriteBits(&m_allowedSubsystem[1],32); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void NetMissionParameters::TeamParameters::LoadParameters(MemoryStream *stream) { stream->ReadBits(&m_maxPlayersOnTeam,7); stream->ReadBits(&m_minimumTonnage,8); stream->ReadBits(&m_maximumTonnage,8); stream->ReadBits(&m_maximumTotalTonnage,16); stream->ReadBits(&m_currentTotalTonnage,8*sizeof(Scalar)); stream->ReadBits(&m_skin,8); stream->ReadBits(&m_alignment,4); stream->ReadBits(&m_allowedMech[0],32); stream->ReadBits(&m_allowedBeam[0],32); stream->ReadBits(&m_allowedMissile[0],32); stream->ReadBits(&m_allowedProjectile[0],32); stream->ReadBits(&m_allowedSubsystem[0],32); stream->ReadBits(&m_allowedMech[1],32); stream->ReadBits(&m_allowedBeam[1],32); stream->ReadBits(&m_allowedMissile[1],32); stream->ReadBits(&m_allowedProjectile[1],32); stream->ReadBits(&m_allowedSubsystem[1],32); } NetMissionParameters::MWNetMissionParameters::MWNetMissionParameters() { m_mapID = 0; m_mapName[0] = '\0'; m_scenarioName[0] = '\0'; m_scenarioPath[0] = '\0'; m_serverName[0] = '\0'; m_serverIP[0] = '\0'; m_scriptName[0] = '\0'; m_scenarioText[0] = '\0'; m_mapClientCRC = 0; ResetParameters(); } void NetMissionParameters::MWNetMissionParameters::ResetParameters(void) { AdeptNetMissionParameters::ResetParameters(); m_joinInProgress = 1; m_joinInProgressCutOff = false; m_joinInProgressCutOffTime = 0; m_heatOn = true; m_killLimit = false; m_killLimitNumber = 0; m_respawnLimit = false; m_respawnLimitNumber = 0; m_forceRespawn = true; m_splashOn = false; m_weaponjamOn = false; m_ammobayfireOn = false; // MSL 5.05 Advance Mode m_advancemodeOn = false; // MSL 5.06 Armor Mode m_armormodeOn = false; m_splashPercentage = 100; m_unlimitedAmmo = false; m_friendlyFirePercentage = 100; m_allowZoom = true; m_allow3rdPerson = true; m_allowAutoAim = true; m_allowDeadToChat = false; m_invulnerableDrop = false; m_isNight = false; m_weather = false; m_radarMode = 0; m_reportStats = true; m_serverConnection = MWApplication::LAN; m_serverBandwidth = MWApplication::c_10_Mbps; m_onlyStockMech = false; m_minimumTonnage = 0; m_maximumTonnage = 100; m_allowedMech[0] = 0xffffffff; m_allowedBeam[0] = 0xfffffffd; m_allowedMissile[0] = 0xff3bffff; m_allowedProjectile[0] = 0xffffdfff; m_allowedSubsystem[0] = 0xffffffff; m_allowedMech[1] = 0xffffffff; m_allowedBeam[1] = 0xffffffff; m_allowedMissile[1] = 0xffffffff; m_allowedProjectile[1] = 0xffffffff; m_allowedSubsystem[1] = 0xffffffff; m_gameLength = 10; m_serverRecycle = 0; m_recycleDelay = 60; m_playMissionReview = 0; m_ruleType = CustomAttrition; //StockAttrition; m_deadMechCantSee = false; m_deadMechCantSeeOtherTeam = false; m_teamAllowed = false; m_teamCount = 8; m_allowdecaltransfer = false; m_useMapCycle = false; m_pureMapCycle = false; for (int i = 0; i < 8; ++i) { m_teamParams[i].ResetParameters(i); } m_maxPlayers = 0; m_maxBots = 0; strcpy(m_serverCPU, "cpu"); //SPEW(("jerryeds", "RESET TIME : %d", m_gameLength)); } void NetMissionParameters::MWNetMissionParameters::SaveParameters(DynamicMemoryStream *stream) { AdeptNetMissionParameters::SaveParameters(stream); stream->WriteBits(&m_joinInProgress, 1); stream->WriteBits(&m_joinInProgressCutOff, 1); stream->WriteBits(&m_joinInProgressCutOffTime, 8); // minutes 256 stream->WriteBits(&m_heatOn, 1); stream->WriteBits(&m_killLimit, 1); stream->WriteBits(&m_killLimitNumber, 8); //256 stream->WriteBits(&m_respawnLimit, 1); stream->WriteBits(&m_respawnLimitNumber, 8); //256 stream->WriteBits(&m_forceRespawn, 1); stream->WriteBits(&m_splashOn, 1); stream->WriteBits(&m_weaponjamOn, 1); stream->WriteBits(&m_ammobayfireOn, 1); // MSL 5.05 Advance Mode stream->WriteBits(&m_advancemodeOn, 1); // MSL 5.06 Armor Mode stream->WriteBits(&m_armormodeOn, 1); stream->WriteBits(&m_splashPercentage, 8); //256 stream->WriteBits(&m_unlimitedAmmo, 1); stream->WriteBits(&m_friendlyFirePercentage, 8); //256 stream->WriteBits(&m_allowZoom, 1); stream->WriteBits(&m_allow3rdPerson, 1); stream->WriteBits(&m_allowAutoAim, 1); stream->WriteBits(&m_allowDeadToChat, 1); stream->WriteBits(&m_invulnerableDrop, 1); stream->WriteBits(&m_onlyStockMech,1); stream->WriteBits(&m_minimumTonnage,8); stream->WriteBits(&m_maximumTonnage,8); stream->WriteBits(&m_allowedMech[0],32); stream->WriteBits(&m_allowedBeam[0],32); stream->WriteBits(&m_allowedMissile[0],32); stream->WriteBits(&m_allowedProjectile[0],32); stream->WriteBits(&m_allowedSubsystem[0],32); stream->WriteBits(&m_allowedMech[1],32); stream->WriteBits(&m_allowedBeam[1],32); stream->WriteBits(&m_allowedMissile[1],32); stream->WriteBits(&m_allowedProjectile[1],32); stream->WriteBits(&m_allowedSubsystem[1],32); stream->WriteBits(&m_gameLength, 8); // 256 minutes stream->WriteBits(&m_serverRecycle, 1); stream->WriteBits(&m_recycleDelay, 16); //65535 seconds stream->WriteBits(&m_playMissionReview, 1); stream->WriteBits(&m_isNight, 1); stream->WriteBits(&m_weather,1); stream->WriteBits(&m_radarMode,2); stream->WriteBits(&m_reportStats,1); stream->WriteBits(&m_serverConnection,5);//32 stream->WriteBits(&m_serverBandwidth,5);//32 stream->WriteBits(&m_ruleType, 5);//32 stream->WriteBits(&m_deadMechCantSee,1); stream->WriteBits(&m_deadMechCantSeeOtherTeam,1); stream->WriteBits(&m_teamAllowed,1); stream->WriteBits(&m_teamCount, 4); stream->WriteBits(&m_allowdecaltransfer,1); stream->WriteBits(&m_useMapCycle,1); stream->WriteBits(&m_pureMapCycle,1); stream->WriteBits(&m_maxPlayers, 5); // 16 players maximum stream->WriteBits(&m_maxBots, 5); // 16 players maximum stream->WriteBits(&m_mapID, 16); // 65535 maps available stream->WriteBits(&m_mapClientCRC, 64); for (int i = 0; i < 8; ++i) { m_teamParams[i].SaveParameters(stream); } stream->WriteByteAlign(); int map_length = strlen(&m_mapName[0]); stream->WriteBytes(&map_length, 1); if (map_length > 0) stream->WriteBytes(&m_mapName[0], map_length); int scn_length = strlen(&m_scenarioName[0]); stream->WriteBytes(&scn_length, 1); if (scn_length > 0) stream->WriteBytes(&m_scenarioName[0], scn_length); int scp_length = strlen(&m_scenarioPath[0]); stream->WriteBytes(&scp_length, 1); if (scp_length > 0) stream->WriteBytes(&m_scenarioPath[0], scp_length); int srn_length = strlen(&m_serverName[0]); stream->WriteBytes(&srn_length, 1); if (srn_length > 0) stream->WriteBytes(&m_serverName[0], srn_length); int sip_length = strlen(&m_serverIP[0]); stream->WriteBytes(&sip_length, 1); if (sip_length > 0) stream->WriteBytes(&m_serverIP[0], sip_length); int cpu_length = strlen(&m_serverCPU[0]); stream->WriteBytes(&cpu_length, 1); if (cpu_length > 0) stream->WriteBytes(&m_serverCPU[0], cpu_length); int scriptname_length = strlen(&m_scriptName[0]); stream->WriteBytes(&scriptname_length,1); if (scriptname_length > 0) stream->WriteBytes(&m_scriptName[0],scriptname_length); int scenariotext_length = strlen(&m_scenarioText[0]); //_mbstrlen(&m_scenarioText[0]); ++scenariotext_length; stream->WriteBytes(&scenariotext_length,4); if (scenariotext_length > 0) stream->WriteBytes(&m_scenarioText[0],scenariotext_length); } void NetMissionParameters::MWNetMissionParameters::LoadParameters(MemoryStream *stream) { AdeptNetMissionParameters::LoadParameters(stream); stream->ReadBits(&m_joinInProgress, 1); stream->ReadBits(&m_joinInProgressCutOff, 1); stream->ReadBits(&m_joinInProgressCutOffTime, 8); // minutes 256 stream->ReadBits(&m_heatOn, 1); stream->ReadBits(&m_killLimit, 1); stream->ReadBits(&m_killLimitNumber, 8); //256 stream->ReadBits(&m_respawnLimit, 1); stream->ReadBits(&m_respawnLimitNumber, 8); //256 stream->ReadBits(&m_forceRespawn, 1); stream->ReadBits(&m_splashOn, 1); stream->ReadBits(&m_weaponjamOn, 1); stream->ReadBits(&m_ammobayfireOn, 1); // MSL 5.05 Advance Mode stream->ReadBits(&m_advancemodeOn, 1); // MSL 5.06 Armor Mode stream->ReadBits(&m_armormodeOn, 1); stream->ReadBits(&m_splashPercentage, 8); //256 stream->ReadBits(&m_unlimitedAmmo, 1); stream->ReadBits(&m_friendlyFirePercentage, 8); //256 stream->ReadBits(&m_allowZoom, 1); stream->ReadBits(&m_allow3rdPerson, 1); stream->ReadBits(&m_allowAutoAim, 1); stream->ReadBits(&m_allowDeadToChat, 1); stream->ReadBits(&m_invulnerableDrop, 1); stream->ReadBits(&m_onlyStockMech,1); stream->ReadBits(&m_minimumTonnage,8); stream->ReadBits(&m_maximumTonnage,8); stream->ReadBits(&m_allowedMech[0],32); stream->ReadBits(&m_allowedBeam[0],32); stream->ReadBits(&m_allowedMissile[0],32); stream->ReadBits(&m_allowedProjectile[0],32); stream->ReadBits(&m_allowedSubsystem[0],32); stream->ReadBits(&m_allowedMech[1],32); stream->ReadBits(&m_allowedBeam[1],32); stream->ReadBits(&m_allowedMissile[1],32); stream->ReadBits(&m_allowedProjectile[1],32); stream->ReadBits(&m_allowedSubsystem[1],32); stream->ReadBits(&m_gameLength, 8); // 256 minutes stream->ReadBits(&m_serverRecycle, 1); stream->ReadBits(&m_recycleDelay, 16); //65535 seconds stream->ReadBits(&m_playMissionReview, 1); stream->ReadBits(&m_isNight, 1); stream->ReadBits(&m_weather,1); stream->ReadBits(&m_radarMode,2); stream->ReadBits(&m_reportStats,1); stream->ReadBits(&m_serverConnection,5);//32 stream->ReadBits(&m_serverBandwidth,5);//32 stream->ReadBits(&m_ruleType, 5);//32 stream->ReadBits(&m_deadMechCantSee,1); stream->ReadBits(&m_deadMechCantSeeOtherTeam,1); stream->ReadBits(&m_teamAllowed,1); stream->ReadBits(&m_teamCount, 4); stream->ReadBits(&m_allowdecaltransfer,1); stream->ReadBits(&m_useMapCycle,1); stream->ReadBits(&m_pureMapCycle,1); stream->ReadBits(&m_maxPlayers, 5); // 16 players max stream->ReadBits(&m_maxBots, 5); // 16 players max stream->ReadBits(&m_mapID, 16); // 65535 maps available stream->ReadBits(&m_mapClientCRC, 64); for (int i = 0; i < 8; ++i) { m_teamParams[i].LoadParameters(stream); } stream->ReadByteAlign(); int map_length = 0; stream->ReadBytes(&map_length, 1); if (map_length > 0) stream->ReadBytes(&m_mapName[0], map_length); m_mapName[map_length] = '\0'; int scn_length = 0; stream->ReadBytes(&scn_length, 1); if (scn_length > 0) stream->ReadBytes(&m_scenarioName[0], scn_length); m_scenarioName[scn_length] = '\0'; int scp_length = 0; stream->ReadBytes(&scp_length, 1); if (scp_length > 0) stream->ReadBytes(&m_scenarioPath[0], scp_length); m_scenarioPath[scp_length] = '\0'; int srn_length = 0; stream->ReadBytes(&srn_length, 1); if (srn_length > 0) stream->ReadBytes(&m_serverName[0], srn_length); m_serverName[srn_length] = '\0'; int sip_length = 0; stream->ReadBytes(&sip_length, 1); if (sip_length > 0) stream->ReadBytes(&m_serverIP[0], sip_length); m_serverIP[sip_length] = '\0'; int cpu_length = 0; stream->ReadBytes(&cpu_length, 1); if (cpu_length > 0) stream->ReadBytes(&m_serverCPU[0], cpu_length); m_serverCPU[cpu_length] = '\0'; int scriptname_length = 0; stream->ReadBytes(&scriptname_length,1); if (scriptname_length > 0) stream->ReadBytes(&m_scriptName[0],scriptname_length); int scenariotext_length = 0; stream->ReadBytes(&scenariotext_length,4); if (scenariotext_length > 0) stream->ReadBytes(&m_scenarioText[0],scenariotext_length); } MemoryStream& MemoryStream::WriteBits( const void *ptr, DWORD number_of_bits ) { Check_Object(this); Check_Pointer(ptr); if (currentBit == Empty_Bit_Buffer) { workingBitBuffer = 0x00; currentBit = 0; } Verify(currentBit >= 0); Verify(currentBit < 8); int total_number_of_bytes = (int)(number_of_bits/8.0f); int total_remainder_bits = number_of_bits - (total_number_of_bytes*8); if ( total_remainder_bits != 0) { total_number_of_bytes += 1; } const BYTE *source_array = (const BYTE *)ptr; int source_byte_counter = 0; int bits_remaining = number_of_bits; while (bits_remaining > 0) { // if we are writing the full byte const BYTE *source = &source_array[source_byte_counter]; int total_bits_to_be_written = 8; Max_Clamp(total_bits_to_be_written, bits_remaining); int bits_in_first_destination_byte = total_bits_to_be_written; Max_Clamp(bits_in_first_destination_byte, 8-currentBit); // make sure our destination is empty workingBitBuffer &= (0xff >> (8-currentBit)); // move the source data to the correct bit location BYTE new_source = (BYTE)(*source << currentBit); // put the adjusted source into the destination workingBitBuffer |= new_source; currentBit += bits_in_first_destination_byte; if (currentBit == 8) { int bits_in_second_destination_byte = total_bits_to_be_written - bits_in_first_destination_byte; //SPEW(("jerryeds", "WRITE : %x", workingBitBuffer)); WriteBytes(&workingBitBuffer, 1); ++source_byte_counter; workingBitBuffer = 0x00; currentBit = 0; if (bits_in_second_destination_byte) { // remove bits we have already used workingBitBuffer = (BYTE)(*source >> bits_in_first_destination_byte); currentBit = bits_in_second_destination_byte; } } bits_remaining -= total_bits_to_be_written; } Verify(currentBit >= 0); Verify(currentBit < 8); return *this; } MemoryStream& MemoryStream::ReadUnsafeBits( void *ptr, DWORD number_of_bits ) { Check_Object(this); Check_Pointer(ptr); if (currentBit == Empty_Bit_Buffer) { ReadBytes(&workingBitBuffer, 1); //SPEW(("jerryeds", "READ : %x", workingBitBuffer)); currentBit = 0; } Verify(currentBit >= 0); Verify(currentBit < 8); int total_number_of_bytes = (int)(number_of_bits/8.0f); int total_remainder_bits = number_of_bits - (total_number_of_bytes*8); if ( total_remainder_bits != 0) { total_number_of_bytes += 1; } BYTE *dest_array = (BYTE *)ptr; int dest_byte_counter = 0; int bits_remaining = number_of_bits; while (bits_remaining > 0) { BYTE *dest = &dest_array[dest_byte_counter]; // empy out destination *dest = 0x00; int total_bits_to_be_read = 8; Max_Clamp(total_bits_to_be_read, bits_remaining); int bits_in_first_source_byte = total_bits_to_be_read; Max_Clamp(bits_in_first_source_byte, 8-currentBit); // make a mask of bits to be used int bit_mask = 0xff >> (8-bits_in_first_source_byte); // shift past the used bits in the buffer *dest = (BYTE)(workingBitBuffer >> currentBit); // remove any bits from the next set that tagged along *dest &= bit_mask; currentBit += bits_in_first_source_byte; if (currentBit == 8) { int bits_in_second_source_byte = total_bits_to_be_read - bits_in_first_source_byte; if (GetBytesRemaining()) { ReadBytes(&workingBitBuffer, 1); //SPEW(("jerryeds", "READ : %x", workingBitBuffer)); } ++dest_byte_counter; currentBit = 0; if (bits_in_second_source_byte) { // make a bitmask of the used bits bit_mask = 0xff >> (8-bits_in_second_source_byte); // mask the used bits out of the buffer and then shift the buffer to the correct // bit location. Then combine it with the destination *dest |= ((workingBitBuffer & bit_mask) << bits_in_first_source_byte); currentBit = bits_in_second_source_byte; } } bits_remaining -= total_bits_to_be_read; } Verify(currentBit >= 0); Verify(currentBit < 8); return *this; }