CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

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