1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein multiplayer GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”).
8 
9 RTCW MP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 RTCW MP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with RTCW MP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 
30 /* This is based on the Adaptive Huffman algorithm described in Sayood's Data
31  * Compression book.  The ranks are not actually stored, but implicitly defined
32  * by the location of a node within a doubly-linked list */
33 
34 #include "q_shared.h"
35 #include "qcommon.h"
36 
37 static int bloc = 0;
38 
Huff_putBit(int bit,byte * fout,int * offset)39 void Huff_putBit( int bit, byte *fout, int *offset ) {
40 	bloc = *offset;
41 	if ( ( bloc & 7 ) == 0 ) {
42 		fout[( bloc >> 3 )] = 0;
43 	}
44 	fout[( bloc >> 3 )] |= bit << ( bloc & 7 );
45 	bloc++;
46 	*offset = bloc;
47 }
48 
Huff_getBloc(void)49 int Huff_getBloc( void ) {
50 	return bloc;
51 }
52 
Huff_setBloc(int _bloc)53 void Huff_setBloc( int _bloc ) {
54 	bloc = _bloc;
55 }
56 
Huff_getBit(byte * fin,int * offset)57 int Huff_getBit( byte *fin, int *offset ) {
58 	int t;
59 	bloc = *offset;
60 	t = ( fin[( bloc >> 3 )] >> ( bloc & 7 ) ) & 0x1;
61 	bloc++;
62 	*offset = bloc;
63 	return t;
64 }
65 
66 /* Add a bit to the output file (buffered) */
add_bit(char bit,byte * fout)67 static void add_bit( char bit, byte *fout ) {
68 	if ( ( bloc & 7 ) == 0 ) {
69 		fout[( bloc >> 3 )] = 0;
70 	}
71 	fout[( bloc >> 3 )] |= bit << ( bloc & 7 );
72 	bloc++;
73 }
74 
75 /* Receive one bit from the input file (buffered) */
get_bit(byte * fin)76 static int get_bit( byte *fin ) {
77 	int t;
78 	t = ( fin[( bloc >> 3 )] >> ( bloc & 7 ) ) & 0x1;
79 	bloc++;
80 	return t;
81 }
82 
get_ppnode(huff_t * huff)83 static node_t **get_ppnode( huff_t* huff ) {
84 	node_t **tppnode;
85 	if ( !huff->freelist ) {
86 		return &( huff->nodePtrs[huff->blocPtrs++] );
87 	} else {
88 		tppnode = huff->freelist;
89 		huff->freelist = (node_t **)*tppnode;
90 		return tppnode;
91 	}
92 }
93 
free_ppnode(huff_t * huff,node_t ** ppnode)94 static void free_ppnode( huff_t* huff, node_t **ppnode ) {
95 	*ppnode = (node_t *)huff->freelist;
96 	huff->freelist = ppnode;
97 }
98 
99 /* Swap the location of these two nodes in the tree */
swap(huff_t * huff,node_t * node1,node_t * node2)100 static void swap( huff_t* huff, node_t *node1, node_t *node2 ) {
101 	node_t *par1, *par2;
102 
103 	par1 = node1->parent;
104 	par2 = node2->parent;
105 
106 	if ( par1 ) {
107 		if ( par1->left == node1 ) {
108 			par1->left = node2;
109 		} else {
110 			par1->right = node2;
111 		}
112 	} else {
113 		huff->tree = node2;
114 	}
115 
116 	if ( par2 ) {
117 		if ( par2->left == node2 ) {
118 			par2->left = node1;
119 		} else {
120 			par2->right = node1;
121 		}
122 	} else {
123 		huff->tree = node1;
124 	}
125 
126 	node1->parent = par2;
127 	node2->parent = par1;
128 }
129 
130 /* Swap these two nodes in the linked list (update ranks) */
swaplist(node_t * node1,node_t * node2)131 static void swaplist( node_t *node1, node_t *node2 ) {
132 	node_t *par1;
133 
134 	par1 = node1->next;
135 	node1->next = node2->next;
136 	node2->next = par1;
137 
138 	par1 = node1->prev;
139 	node1->prev = node2->prev;
140 	node2->prev = par1;
141 
142 	if ( node1->next == node1 ) {
143 		node1->next = node2;
144 	}
145 	if ( node2->next == node2 ) {
146 		node2->next = node1;
147 	}
148 	if ( node1->next ) {
149 		node1->next->prev = node1;
150 	}
151 	if ( node2->next ) {
152 		node2->next->prev = node2;
153 	}
154 	if ( node1->prev ) {
155 		node1->prev->next = node1;
156 	}
157 	if ( node2->prev ) {
158 		node2->prev->next = node2;
159 	}
160 }
161 
162 /* Do the increments */
increment(huff_t * huff,node_t * node)163 static void increment( huff_t* huff, node_t *node ) {
164 	node_t *lnode;
165 
166 	if ( !node ) {
167 		return;
168 	}
169 
170 	if ( node->next != NULL && node->next->weight == node->weight ) {
171 		lnode = *node->head;
172 		if ( lnode != node->parent ) {
173 			swap( huff, lnode, node );
174 		}
175 		swaplist( lnode, node );
176 	}
177 	if ( node->prev && node->prev->weight == node->weight ) {
178 		*node->head = node->prev;
179 	} else {
180 		*node->head = NULL;
181 		free_ppnode( huff, node->head );
182 	}
183 	node->weight++;
184 	if ( node->next && node->next->weight == node->weight ) {
185 		node->head = node->next->head;
186 	} else {
187 		node->head = get_ppnode( huff );
188 		*node->head = node;
189 	}
190 	if ( node->parent ) {
191 		increment( huff, node->parent );
192 		if ( node->prev == node->parent ) {
193 			swaplist( node, node->parent );
194 			if ( *node->head == node ) {
195 				*node->head = node->parent;
196 			}
197 		}
198 	}
199 }
200 
Huff_addRef(huff_t * huff,byte ch)201 void Huff_addRef( huff_t* huff, byte ch ) {
202 	node_t *tnode, *tnode2;
203 	if ( huff->loc[ch] == NULL ) { /* if this is the first transmission of this node */
204 		tnode = &( huff->nodeList[huff->blocNode++] );
205 		tnode2 = &( huff->nodeList[huff->blocNode++] );
206 
207 		tnode2->symbol = INTERNAL_NODE;
208 		tnode2->weight = 1;
209 		tnode2->next = huff->lhead->next;
210 		if ( huff->lhead->next ) {
211 			huff->lhead->next->prev = tnode2;
212 			if ( huff->lhead->next->weight == 1 ) {
213 				tnode2->head = huff->lhead->next->head;
214 			} else {
215 				tnode2->head = get_ppnode( huff );
216 				*tnode2->head = tnode2;
217 			}
218 		} else {
219 			tnode2->head = get_ppnode( huff );
220 			*tnode2->head = tnode2;
221 		}
222 		huff->lhead->next = tnode2;
223 		tnode2->prev = huff->lhead;
224 
225 		tnode->symbol = ch;
226 		tnode->weight = 1;
227 		tnode->next = huff->lhead->next;
228 		if ( huff->lhead->next ) {
229 			huff->lhead->next->prev = tnode;
230 			if ( huff->lhead->next->weight == 1 ) {
231 				tnode->head = huff->lhead->next->head;
232 			} else {
233 				/* this should never happen */
234 				tnode->head = get_ppnode( huff );
235 				*tnode->head = tnode2;
236 			}
237 		} else {
238 			/* this should never happen */
239 			tnode->head = get_ppnode( huff );
240 			*tnode->head = tnode;
241 		}
242 		huff->lhead->next = tnode;
243 		tnode->prev = huff->lhead;
244 		tnode->left = tnode->right = NULL;
245 
246 		if ( huff->lhead->parent ) {
247 			if ( huff->lhead->parent->left == huff->lhead ) { /* lhead is guaranteed to by the NYT */
248 				huff->lhead->parent->left = tnode2;
249 			} else {
250 				huff->lhead->parent->right = tnode2;
251 			}
252 		} else {
253 			huff->tree = tnode2;
254 		}
255 
256 		tnode2->right = tnode;
257 		tnode2->left = huff->lhead;
258 
259 		tnode2->parent = huff->lhead->parent;
260 		huff->lhead->parent = tnode->parent = tnode2;
261 
262 		huff->loc[ch] = tnode;
263 
264 		increment( huff, tnode2->parent );
265 	} else {
266 		increment( huff, huff->loc[ch] );
267 	}
268 }
269 
270 /* Get a symbol */
Huff_Receive(node_t * node,int * ch,byte * fin)271 int Huff_Receive( node_t *node, int *ch, byte *fin ) {
272 	while ( node && node->symbol == INTERNAL_NODE ) {
273 		if ( get_bit( fin ) ) {
274 			node = node->right;
275 		} else {
276 			node = node->left;
277 		}
278 	}
279 	if ( !node ) {
280 		return 0;
281 //		Com_Error(ERR_DROP, "Illegal tree!");
282 	}
283 	return ( *ch = node->symbol );
284 }
285 
286 /* Get a symbol */
Huff_offsetReceive(node_t * node,int * ch,byte * fin,int * offset,int maxoffset)287 void Huff_offsetReceive( node_t *node, int *ch, byte *fin, int *offset, int maxoffset ) {
288 	bloc = *offset;
289 	while ( node && node->symbol == INTERNAL_NODE ) {
290 		if ( bloc >= maxoffset ) {
291 			*ch = 0;
292 			*offset = maxoffset + 1;
293 			return;
294 		}
295 		if ( get_bit( fin ) ) {
296 			node = node->right;
297 		} else {
298 			node = node->left;
299 		}
300 	}
301 	if ( !node ) {
302 		*ch = 0;
303 		return;
304 //		Com_Error(ERR_DROP, "Illegal tree!");
305 	}
306 	*ch = node->symbol;
307 	*offset = bloc;
308 }
309 
310 /* Send the prefix code for this node */
send(node_t * node,node_t * child,byte * fout,int maxoffset)311 static void send( node_t *node, node_t *child, byte *fout, int maxoffset ) {
312 	if ( node->parent ) {
313 		send( node->parent, node, fout, maxoffset );
314 	}
315 	if ( child ) {
316 		if ( bloc >= maxoffset ) {
317 			bloc = maxoffset + 1;
318 			return;
319 		}
320 		if ( node->right == child ) {
321 			add_bit( 1, fout );
322 		} else {
323 			add_bit( 0, fout );
324 		}
325 	}
326 }
327 
328 /* Send a symbol */
Huff_transmit(huff_t * huff,int ch,byte * fout,int maxoffset)329 void Huff_transmit( huff_t *huff, int ch, byte *fout, int maxoffset ) {
330 	int i;
331 	if ( huff->loc[ch] == NULL ) {
332 		/* node_t hasn't been transmitted, send a NYT, then the symbol */
333 		Huff_transmit( huff, NYT, fout, maxoffset );
334 		for ( i = 7; i >= 0; i-- ) {
335 			add_bit( (char)( ( ch >> i ) & 0x1 ), fout );
336 		}
337 	} else {
338 		send( huff->loc[ch], NULL, fout, maxoffset );
339 	}
340 }
341 
Huff_offsetTransmit(huff_t * huff,int ch,byte * fout,int * offset,int maxoffset)342 void Huff_offsetTransmit( huff_t *huff, int ch, byte *fout, int *offset, int maxoffset ) {
343 	bloc = *offset;
344 	send( huff->loc[ch], NULL, fout, maxoffset );
345 	*offset = bloc;
346 }
347 
Huff_Decompress(msg_t * mbuf,int offset)348 void Huff_Decompress( msg_t *mbuf, int offset ) {
349 	int ch, cch, i, j, size;
350 	byte seq[65536];
351 	byte*       buffer;
352 	huff_t huff;
353 
354 	size = mbuf->cursize - offset;
355 	buffer = mbuf->data + offset;
356 
357 	if ( size <= 0 ) {
358 		return;
359 	}
360 
361 	Com_Memset( &huff, 0, sizeof( huff_t ) );
362 	// Initialize the tree & list with the NYT node
363 	huff.tree = huff.lhead = huff.ltail = huff.loc[NYT] = &( huff.nodeList[huff.blocNode++] );
364 	huff.tree->symbol = NYT;
365 	huff.tree->weight = 0;
366 	huff.lhead->next = huff.lhead->prev = NULL;
367 	huff.tree->parent = huff.tree->left = huff.tree->right = NULL;
368 
369 	cch = buffer[0] * 256 + buffer[1];
370 	// don't overflow with bad messages
371 	if ( cch > mbuf->maxsize - offset ) {
372 		cch = mbuf->maxsize - offset;
373 	}
374 	bloc = 16;
375 
376 	for ( j = 0; j < cch; j++ ) {
377 		ch = 0;
378 		// don't overflow reading from the messages
379 		// FIXME: would it be better to have an overflow check in get_bit ?
380 		if ( ( bloc >> 3 ) > size ) {
381 			seq[j] = 0;
382 			break;
383 		}
384 		Huff_Receive( huff.tree, &ch, buffer );				/* Get a character */
385 		if ( ch == NYT ) {						/* We got a NYT, get the symbol associated with it */
386 			ch = 0;
387 			for ( i = 0; i < 8; i++ ) {
388 				ch = ( ch << 1 ) + get_bit( buffer );
389 			}
390 		}
391 
392 		seq[j] = ch;							/* Write symbol */
393 
394 		Huff_addRef( &huff, (byte)ch );					/* Increment node */
395 	}
396 	mbuf->cursize = cch + offset;
397 	Com_Memcpy( mbuf->data + offset, seq, cch );
398 }
399 
400 extern int oldsize;
401 
Huff_Compress(msg_t * mbuf,int offset)402 void Huff_Compress( msg_t *mbuf, int offset ) {
403 	int i, ch, size;
404 	byte seq[65536];
405 	byte*       buffer;
406 	huff_t huff;
407 
408 	size = mbuf->cursize - offset;
409 	buffer = mbuf->data + offset;
410 
411 	if ( size <= 0 ) {
412 		return;
413 	}
414 
415 	Com_Memset( &huff, 0, sizeof( huff_t ) );
416 	// Add the NYT (not yet transmitted) node into the tree/list */
417 	huff.tree = huff.lhead = huff.loc[NYT] =  &( huff.nodeList[huff.blocNode++] );
418 	huff.tree->symbol = NYT;
419 	huff.tree->weight = 0;
420 	huff.lhead->next = huff.lhead->prev = NULL;
421 	huff.tree->parent = huff.tree->left = huff.tree->right = NULL;
422 
423 	seq[0] = ( size >> 8 );
424 	seq[1] = size & 0xff;
425 
426 	bloc = 16;
427 
428 	for ( i = 0; i < size; i++ ) {
429 		ch = buffer[i];
430 		Huff_transmit( &huff, ch, seq, size << 3 );			/* Transmit symbol */
431 		Huff_addRef( &huff, (byte)ch );					/* Do update */
432 	}
433 
434 	bloc += 8;								// next byte
435 
436 	mbuf->cursize = ( bloc >> 3 ) + offset;
437 	Com_Memcpy( mbuf->data + offset, seq, ( bloc >> 3 ) );
438 }
439 
Huff_Init(huffman_t * huff)440 void Huff_Init( huffman_t *huff ) {
441 
442 	Com_Memset( &huff->compressor, 0, sizeof( huff_t ) );
443 	Com_Memset( &huff->decompressor, 0, sizeof( huff_t ) );
444 
445 	// Initialize the tree & list with the NYT node
446 	huff->decompressor.tree = huff->decompressor.lhead = huff->decompressor.ltail = huff->decompressor.loc[NYT] = &( huff->decompressor.nodeList[huff->decompressor.blocNode++] );
447 	huff->decompressor.tree->symbol = NYT;
448 	huff->decompressor.tree->weight = 0;
449 	huff->decompressor.lhead->next = huff->decompressor.lhead->prev = NULL;
450 	huff->decompressor.tree->parent = huff->decompressor.tree->left = huff->decompressor.tree->right = NULL;
451 
452 	// Add the NYT (not yet transmitted) node into the tree/list */
453 	huff->compressor.tree = huff->compressor.lhead = huff->compressor.loc[NYT] =  &( huff->compressor.nodeList[huff->compressor.blocNode++] );
454 	huff->compressor.tree->symbol = NYT;
455 	huff->compressor.tree->weight = 0;
456 	huff->compressor.lhead->next = huff->compressor.lhead->prev = NULL;
457 	huff->compressor.tree->parent = huff->compressor.tree->left = huff->compressor.tree->right = NULL;
458 }
459 
460