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