CnC_Remastered_Collection

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

LZOPIPE.CPP (15287B)


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