LCWPIPE.CPP (14689B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/LCWPIPE.CPP 1 3/03/97 10:25a Joe_bostic $ */ 17 /*********************************************************************************************** 18 *** 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 *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : LCWPIPE.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 06/30/96 * 28 * * 29 * Last Update : July 4, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * LCWPipe::Flush -- Flushes any partially accumulated block. * 34 * LCWPipe::LCWPipe -- Constructor for the LCW processor pipe. * 35 * LCWPipe::Put -- Send some data through the LCW processor pipe. * 36 * LCWPipe::~LCWPipe -- Deconstructor for the LCW pipe object. * 37 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 38 39 40 #include "lcwpipe.h" 41 #include "lcw.h" 42 #include <string.h> 43 #include <assert.h> 44 45 46 /*********************************************************************************************** 47 * LCWPipe::LCWPipe -- Constructor for the LCW processor pipe. * 48 * * 49 * This will initialize the LCWPipe object so that it is prepared for compression or * 50 * decompression as indicated. * 51 * * 52 * INPUT: decrypt -- Should decompression be performed? * 53 * * 54 * blocksize-- The size of the data blocks to process. * 55 * * 56 * OUTPUT: none * 57 * * 58 * WARNINGS: none * 59 * * 60 * HISTORY: * 61 * 07/04/1996 JLB : Created. * 62 *=============================================================================================*/ 63 LCWPipe::LCWPipe(CompControl control, int blocksize) : 64 Control(control), 65 Counter(0), 66 Buffer(NULL), 67 Buffer2(NULL), 68 BlockSize(blocksize) 69 { 70 SafetyMargin = BlockSize/128+1; 71 Buffer = new char[BlockSize+SafetyMargin]; 72 Buffer2 = new char[BlockSize+SafetyMargin]; 73 BlockHeader.CompCount = 0xFFFF; 74 } 75 76 77 /*********************************************************************************************** 78 * LCWPipe::~LCWPipe -- Deconstructor for the LCW pipe object. * 79 * * 80 * This will free any buffers it may have allocated. * 81 * * 82 * INPUT: none * 83 * * 84 * OUTPUT: none * 85 * * 86 * WARNINGS: none * 87 * * 88 * HISTORY: * 89 * 07/04/1996 JLB : Created. * 90 *=============================================================================================*/ 91 LCWPipe::~LCWPipe(void) 92 { 93 delete [] Buffer; 94 Buffer = NULL; 95 96 delete [] Buffer2; 97 Buffer2 = NULL; 98 } 99 100 101 /*********************************************************************************************** 102 * LCWPipe::Put -- Send some data through the LCW processor pipe. * 103 * * 104 * This routine will take the data requested and process it (decompression or compression). * 105 * It does this by accumulating the necessary bytes to make a whole block. Then the block * 106 * is processed and the entire contents are flushed to the next pipe segment in the chain. * 107 * * 108 * INPUT: source -- Pointer to the data to be fed to this LCW processor. * 109 * * 110 * length -- The number of bytes received. * 111 * * 112 * OUTPUT: Returns with the actual number of bytes output at the far distant final link in * 113 * the pipe chain. * 114 * * 115 * WARNINGS: The compression process may be slow as well as consuming two buffers. * 116 * * 117 * HISTORY: * 118 * 07/04/1996 JLB : Created. * 119 *=============================================================================================*/ 120 int LCWPipe::Put(void const * source, int slen) 121 { 122 if (source == NULL || slen < 1) { 123 return(Pipe::Put(source, slen)); 124 } 125 126 assert(Buffer != NULL); 127 128 int total = 0; 129 130 /* 131 ** Copy as much as can fit into the buffer from the source data supplied. 132 */ 133 if (Control == DECOMPRESS) { 134 135 while (slen > 0) { 136 137 /* 138 ** First check to see if we are in the block header accumulation phase. 139 ** When a whole block header has been accumulated, only then will the regular 140 ** data processing begin for the block. 141 */ 142 if (BlockHeader.CompCount == 0xFFFF) { 143 int len = (slen < ((int)sizeof(BlockHeader)-Counter)) ? slen : ((int)sizeof(BlockHeader)-Counter); 144 memmove(&Buffer[Counter], source, len); 145 source = ((char *)source) + len; 146 slen -= len; 147 Counter += len; 148 149 /* 150 ** A whole block header has been accumulated. Store it for safekeeping. 151 */ 152 if (Counter == sizeof(BlockHeader)) { 153 memmove(&BlockHeader, Buffer, sizeof(BlockHeader)); 154 Counter = 0; 155 } 156 } 157 158 /* 159 ** Fill the buffer with compressed data until there is enough to make a whole 160 ** data block. 161 */ 162 if (slen > 0) { 163 int len = (slen < (BlockHeader.CompCount-Counter)) ? slen : (BlockHeader.CompCount-Counter); 164 165 memmove(&Buffer[Counter], source, len); 166 slen -= len; 167 source = ((char *)source) + len; 168 Counter += len; 169 170 /* 171 ** If an entire block has been accumulated, then uncompress it and feed it 172 ** through the pipe. 173 */ 174 if (Counter == BlockHeader.CompCount) { 175 LCW_Uncomp(Buffer, Buffer2); 176 total += Pipe::Put(Buffer2, BlockHeader.UncompCount); 177 Counter = 0; 178 BlockHeader.CompCount = 0xFFFF; 179 } 180 } 181 } 182 183 } else { 184 185 /* 186 ** If the buffer already contains some data, then any new data must be stored 187 ** into the staging buffer until a full set has been accumulated. 188 */ 189 if (Counter > 0) { 190 int tocopy = (slen < (BlockSize-Counter)) ? slen : (BlockSize-Counter); 191 memmove(&Buffer[Counter], source, tocopy); 192 source = ((char *)source) + tocopy; 193 slen -= tocopy; 194 Counter += tocopy; 195 196 if (Counter == BlockSize) { 197 int len = LCW_Comp(Buffer, Buffer2, BlockSize); 198 199 BlockHeader.CompCount = (unsigned short)len; 200 BlockHeader.UncompCount = (unsigned short)BlockSize; 201 total += Pipe::Put(&BlockHeader, sizeof(BlockHeader)); 202 total += Pipe::Put(Buffer2, len); 203 Counter = 0; 204 } 205 } 206 207 /* 208 ** Process the source data in whole block chunks until there is insufficient 209 ** source data left for a whole data block. 210 */ 211 while (slen >= BlockSize) { 212 int len = LCW_Comp(source, Buffer2, BlockSize); 213 214 source = ((char *)source) + BlockSize; 215 slen -= BlockSize; 216 217 BlockHeader.CompCount = (unsigned short)len; 218 BlockHeader.UncompCount = (unsigned short)BlockSize; 219 total += Pipe::Put(&BlockHeader, sizeof(BlockHeader)); 220 total += Pipe::Put(Buffer2, len); 221 } 222 223 /* 224 ** If there is any remaining data, then it is stored into the buffer 225 ** until a full data block has been accumulated. 226 */ 227 if (slen > 0) { 228 memmove(Buffer, source, slen); 229 Counter = slen; 230 } 231 } 232 233 return(total); 234 } 235 236 237 /*********************************************************************************************** 238 * LCWPipe::Flush -- Flushes any partially accumulated block. * 239 * * 240 * This routine is called when any buffered data must be flushed out the pipe. For the * 241 * compression process, this will generate the sub-sized compressed block. For * 242 * decompression, this routine should not have any data in the buffer. In such a case, it * 243 * means that the data source was prematurely truncated. In such a case, just dump the * 244 * accumulated data through the pipe. * 245 * * 246 * INPUT: none * 247 * * 248 * OUTPUT: Returns with the actual number of data bytes output to the distant final link in * 249 * the pipe chain. * 250 * * 251 * WARNINGS: none * 252 * * 253 * HISTORY: * 254 * 07/04/1996 JLB : Created. * 255 *=============================================================================================*/ 256 int LCWPipe::Flush(void) 257 { 258 assert(Buffer != NULL); 259 260 int total = 0; 261 262 /* 263 ** If there is accumulated data, then it must processed. 264 */ 265 if (Counter > 0) { 266 if (Control == DECOMPRESS) { 267 268 /* 269 ** If the accumulated data is insufficient to make a block header, then 270 ** this means the data has been truncated. Just dump the data through 271 ** as if were already decompressed. 272 */ 273 if (BlockHeader.CompCount == 0xFFFF) { 274 total += Pipe::Put(Buffer, Counter); 275 Counter = 0; 276 } 277 278 /* 279 ** There appears to be a partial block accumulated in the buffer. It would 280 ** be disastrous to try to decompress the data since there wouldn't be 281 ** the special end of data code that LCW decompression needs. In this 282 ** case, dump the data out as if it were already decompressed. 283 */ 284 if (Counter > 0) { 285 total += Pipe::Put(&BlockHeader, sizeof(BlockHeader)); 286 total += Pipe::Put(Buffer, Counter); 287 Counter = 0; 288 BlockHeader.CompCount = 0xFFFF; 289 } 290 291 } else { 292 293 /* 294 ** A partial block in the compression process is a normal occurrence. Just 295 ** compress the partial block and output normally. 296 */ 297 int len = LCW_Comp(Buffer, Buffer2, Counter); 298 299 BlockHeader.CompCount = (unsigned short)len; 300 BlockHeader.UncompCount = (unsigned short)Counter; 301 total += Pipe::Put(&BlockHeader, sizeof(BlockHeader)); 302 total += Pipe::Put(Buffer2, len); 303 Counter = 0; 304 } 305 } 306 307 total += Pipe::Flush(); 308 return(total); 309 } 310