1 /*
2 	Relay -- a tool to record and play Quake2 demos
3 	Copyright (C) 2000 Conor Davis
4 
5 	This program is free software; you can redistribute it and/or
6 	modify it under the terms of the GNU General Public License
7 	as published by the Free Software Foundation; either version 2
8 	of the License, or (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, write to the Free Software
17 	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 	Conor Davis
20 	cedavis@planetquake.com
21 */
22 
23 #include <string.h>
24 #include <assert.h>
25 
26 #include "shared.h"
27 #include "block.h"
28 #include "endian.h"
29 #include "q2defines.h"
30 
31 //
32 // generic block functions
33 //
34 
BlockInit(block_t * block,char * buffer,size_t size)35 void BlockInit(block_t *block, char *buffer, size_t size)
36 {
37 	block->buffer = buffer;
38 	block->size = size;
39 	block->readoffset = 0;
40 	block->writeoffset = 0;
41 	block->writelen = 0;
42 	block->readoverflow = false;
43 	block->writeoverflow = false;
44 }
45 
BlockRewind(block_t * block)46 void BlockRewind(block_t *block)
47 {
48 	block->readoffset = 0;
49 	block->writeoffset = 0;
50 	block->writelen = 0;
51 	block->readoverflow = false;
52 	block->writeoverflow = false;
53 }
54 
BlockRewindRead(block_t * block)55 void BlockRewindRead(block_t *block)
56 {
57 	block->readoffset = 0;
58 	block->readoverflow = false;
59 }
60 
ReadOverflow(block_t * block)61 qboolean ReadOverflow(block_t *block)
62 {
63 	return block->readoverflow;
64 }
65 
WriteOverflow(block_t * block)66 qboolean WriteOverflow(block_t *block)
67 {
68 	return block->writeoverflow;
69 }
70 
71 // CheckRead
72 // Determines whether it is safe to read len bytes
73 // from block
CheckRead(block_t * block,size_t len)74 static qboolean CheckRead(block_t *block, size_t len)
75 {
76 	if (block->readoffset + len > block->writeoffset)
77 	{
78 		block->readoverflow = true;
79 		return false;
80 	}
81 
82 	return true;
83 }
84 
85 // CheckWrite
86 // Determines whether it is safe to write len bytes
87 // to block
CheckWrite(block_t * block,size_t len)88 static qboolean CheckWrite(block_t *block, size_t len)
89 {
90 	block->writelen += len;
91 	if (block->writeoffset + len > block->size)
92 	{
93 		block->writeoverflow = true;
94 		return false;
95 	}
96 
97 	return true;
98 }
99 
BlockRead(block_t * block,char * buffer,size_t len)100 const char *BlockRead(block_t *block, char *buffer, size_t len)
101 {
102 	if (!CheckRead(block, len))
103 		return NULL;
104 
105 	if (buffer)
106 		memcpy(buffer, block->buffer + block->readoffset, len);
107 
108 	block->readoffset += len;
109 	return block->buffer + block->readoffset - len;
110 }
111 
BlockWrite(block_t * block,const char * buffer,size_t len)112 void BlockWrite(block_t *block, const char *buffer, size_t len)
113 {
114 	if (!CheckWrite(block, len))
115 		return;
116 
117 	memcpy(block->buffer + block->writeoffset, buffer, len);
118 	block->writeoffset += len;
119 }
120 
BlockCopy(block_t * dest,block_t * src,size_t len)121 const char *BlockCopy(block_t *dest, block_t *src, size_t len)
122 {
123 	if (!CheckRead(src, len))
124 		return NULL;
125 
126 	if (!CheckWrite(dest, len))
127 		return NULL;
128 
129 	memcpy(dest->buffer + dest->writeoffset, src->buffer + src->readoffset, len);
130 	src->readoffset += len;
131 	dest->writeoffset += len;
132 
133 	return dest->buffer + dest->writeoffset - len;
134 }
135 
136 //
137 // low-level read/write functions
138 //
139 
ReadChar(block_t * block)140 char ReadChar(block_t *block)
141 {
142 	char a;
143 
144 	if (!CheckRead(block, 1))
145 		return 0;
146 
147 	a = *(char *)(block->buffer + block->readoffset);
148 	block->readoffset++;
149 
150 	return a;
151 }
152 
WriteChar(block_t * block,char a)153 void WriteChar(block_t *block, char a)
154 {
155 	if (!CheckWrite(block, 1))
156 		return;
157 
158 	*(char *)(block->buffer + block->writeoffset) = a;
159 	block->writeoffset++;
160 }
161 
ReadByte(block_t * block)162 unsigned char ReadByte(block_t *block)
163 {
164 	unsigned char a;
165 
166 	if (!CheckRead(block, 1))
167 		return 0;
168 
169 	a = *(unsigned char *)(block->buffer + block->readoffset);
170 	block->readoffset++;
171 
172 	return a;
173 }
174 
WriteByte(block_t * block,unsigned char a)175 void WriteByte(block_t *block, unsigned char a)
176 {
177 	if (!CheckWrite(block, 1))
178 		return;
179 
180 	*(unsigned char *)(block->buffer + block->writeoffset) = a;
181 	block->writeoffset++;
182 }
183 
ReadShort(block_t * block)184 short ReadShort(block_t *block)
185 {
186 	short a;
187 
188 	if (!CheckRead(block, 2))
189 		return 0;
190 
191 	a = *(short *)(block->buffer + block->readoffset);
192 	block->readoffset += 2;
193 
194 	return LittleShort(a);
195 }
196 
WriteShort(block_t * block,short a)197 void WriteShort(block_t *block, short a)
198 {
199 	if (!CheckWrite(block, 2))
200 		return;
201 
202 	*(short *)(block->buffer + block->writeoffset) = LittleShort(a);
203 	block->writeoffset += 2;
204 }
205 
ReadLong(block_t * block)206 long ReadLong(block_t *block)
207 {
208 	long a;
209 
210 	if (!CheckRead(block, 4))
211 		return 0;
212 
213 	a = *(long *)(block->buffer + block->readoffset);
214 	block->readoffset += 4;
215 
216 	return LittleLong(a);
217 }
218 
WriteLong(block_t * block,long a)219 void WriteLong(block_t *block, long a)
220 {
221 	if (!CheckWrite(block, 4))
222 		return;
223 
224 	*(long *)(block->buffer + block->writeoffset) = LittleLong(a);
225 	block->writeoffset += 4;
226 }
227 
ReadULong(block_t * block)228 unsigned long ReadULong(block_t *block)
229 {
230 	unsigned long a;
231 
232 	if (!CheckRead(block, 4))
233 		return 0;
234 
235 	a = *(unsigned long *)(block->buffer + block->readoffset);
236 	block->readoffset += 4;
237 
238 	return LittleLong(a);
239 }
240 
WriteULong(block_t * block,unsigned long a)241 void WriteULong(block_t *block, unsigned long a)
242 {
243 	if (!CheckWrite(block, 4))
244 		return;
245 
246 	*(unsigned long *)(block->buffer + block->writeoffset) = LittleLong(a);
247 	block->writeoffset += 4;
248 }
249 
ReadString(block_t * block)250 const char *ReadString(block_t *block)
251 {
252 	char	*start;
253 
254 	start = block->buffer + block->readoffset;
255 	while (ReadChar(block))
256 		;
257 
258 	if (ReadOverflow(block))
259 		return "";
260 
261 	return start;
262 }
263 
WriteString(block_t * block,const char * string)264 void WriteString(block_t *block, const char *string)
265 {
266 	size_t len;
267 
268 	len = strlen(string) + 1;
269 	if (!CheckWrite(block, len))
270 		return;
271 
272 	strcpy(block->buffer + block->writeoffset, string);
273 	block->writeoffset += len;
274 }
275 
276 //
277 // higher-level functions that call
278 // the above functions
279 //
280 
ReadFloat(block_t * block)281 float ReadFloat(block_t *block)
282 {
283 	union {int l; float f;} a;
284 
285 	a.l = ReadLong(block);
286 	return a.f;
287 }
288 
ReadAngle(block_t * block)289 float ReadAngle(block_t *block)
290 {
291 	return (float)ReadChar(block) / 256 * 360;
292 }
293 
WriteAngle(block_t * block,float a)294 void WriteAngle(block_t *block, float a)
295 {
296 	WriteChar(block, (char)(a * 256 / 360));
297 }
298 
ReadAngle16(block_t * block)299 float ReadAngle16(block_t *block)
300 {
301 	return (float)ReadShort(block) / 65536 * 360;
302 }
303 
WriteAngle16(block_t * block,float a)304 void WriteAngle16(block_t *block, float a)
305 {
306 	WriteShort(block, (short)(a * 65535 / 360));
307 }
308 
ReadCoord(block_t * block)309 float ReadCoord(block_t *block)
310 {
311 	return (float)ReadShort(block) * 0.125F;
312 }
313 
WriteCoord(block_t * block,float a)314 void WriteCoord(block_t *block, float a)
315 {
316 	WriteShort(block, (short)(a * 8));
317 }
318 
ReadPosition(block_t * block,float * vec)319 float *ReadPosition(block_t *block, float *vec)
320 {
321 	vec[0] = ReadCoord(block);
322 	vec[1] = ReadCoord(block);
323 	vec[2] = ReadCoord(block);
324 
325 	return vec;
326 }
327 
WritePosition(block_t * block,const float * vec)328 void WritePosition(block_t *block, const float *vec)
329 {
330 	WriteCoord(block, vec[0]);
331 	WriteCoord(block, vec[1]);
332 	WriteCoord(block, vec[2]);
333 }
334 
ReadShortPosition(block_t * block,short * vec)335 short *ReadShortPosition(block_t *block, short *vec)
336 {
337 	vec[0] = ReadShort(block);
338 	vec[1] = ReadShort(block);
339 	vec[2] = ReadShort(block);
340 
341 	return vec;
342 }
343 
WriteShortPosition(block_t * block,const short * vec)344 void WriteShortPosition(block_t *block, const short *vec)
345 {
346 	WriteShort(block, vec[0]);
347 	WriteShort(block, vec[1]);
348 	WriteShort(block, vec[2]);
349 }
350 
351 #define DM2_NUMVERTEXNORMALS 162
352 float avertexnormals[3*DM2_NUMVERTEXNORMALS] =
353 {
354 	-0.525731027, 0, 0.850651026,
355 	-0.442862988, 0.238856003, 0.864188015,
356 	-0.295242012, 0, 0.955422997,
357 	-0.309017003, 0.5, 0.809017003,
358 	-0.162459999, 0.26286599, 0.951056004,
359 	0, 0, 1,
360 	0, 0.850651026, 0.525731027,
361 	-0.147621006, 0.71656698, 0.681717992,
362 	0.147621006, 0.71656698, 0.681717992,
363 	0, 0.525731027, 0.850651026,
364 	0.309017003, 0.5, 0.809017003,
365 	0.525731027, 0, 0.850651026,
366 	0.295242012, 0, 0.955422997,
367 	0.442862988, 0.238856003, 0.864188015,
368 	0.162459999, 0.26286599, 0.951056004,
369 	-0.681717992, 0.147621006, 0.71656698,
370 	-0.809017003, 0.309017003, 0.5,
371 	-0.587785006, 0.425325006, 0.688190997,
372 	-0.850651026, 0.525731027, 0,
373 	-0.864188015, 0.442862988, 0.238856003,
374 	-0.71656698, 0.681717992, 0.147621006,
375 	-0.688190997, 0.587785006, 0.425325006,
376 	-0.5, 0.809017003, 0.309017003,
377 	-0.238856003, 0.864188015, 0.442862988,
378 	-0.425325006, 0.688190997, 0.587785006,
379 	-0.71656698, 0.681717992, -0.147621006,
380 	-0.5, 0.809017003, -0.309017003,
381 	-0.525731027, 0.850651026, 0,
382 	0, 0.850651026, -0.525731027,
383 	-0.238856003, 0.864188015, -0.442862988,
384 	0, 0.955422997, -0.295242012,
385 	-0.26286599, 0.951056004, -0.162459999,
386 	0, 1, 0,
387 	0, 0.955422997, 0.295242012,
388 	-0.26286599, 0.951056004, 0.162459999,
389 	0.238856003, 0.864188015, 0.442862988,
390 	0.26286599, 0.951056004, 0.162459999,
391 	0.5, 0.809017003, 0.309017003,
392 	0.238856003, 0.864188015, -0.442862988,
393 	0.26286599, 0.951056004, -0.162459999,
394 	0.5, 0.809017003, -0.309017003,
395 	0.850651026, 0.525731027, 0,
396 	0.71656698, 0.681717992, 0.147621006,
397 	0.71656698, 0.681717992, -0.147621006,
398 	0.525731027, 0.850651026, 0,
399 	0.425325006, 0.688190997, 0.587785006,
400 	0.864188015, 0.442862988, 0.238856003,
401 	0.688190997, 0.587785006, 0.425325006,
402 	0.809017003, 0.309017003, 0.5,
403 	0.681717992, 0.147621006, 0.71656698,
404 	0.587785006, 0.425325006, 0.688190997,
405 	0.955422997, 0.295242012, 0,
406 	1, 0, 0,
407 	0.951056004, 0.162459999, 0.26286599,
408 	0.850651026, -0.525731027, 0,
409 	0.955422997, -0.295242012, 0,
410 	0.864188015, -0.442862988, 0.238856003,
411 	0.951056004, -0.162459999, 0.26286599,
412 	0.809017003, -0.309017003, 0.5,
413 	0.681717992, -0.147621006, 0.71656698,
414 	0.850651026, 0, 0.525731027,
415 	0.864188015, 0.442862988, -0.238856003,
416 	0.809017003, 0.309017003, -0.5,
417 	0.951056004, 0.162459999, -0.26286599,
418 	0.525731027, 0, -0.850651026,
419 	0.681717992, 0.147621006, -0.71656698,
420 	0.681717992, -0.147621006, -0.71656698,
421 	0.850651026, 0, -0.525731027,
422 	0.809017003, -0.309017003, -0.5,
423 	0.864188015, -0.442862988, -0.238856003,
424 	0.951056004, -0.162459999, -0.26286599,
425 	0.147621006, 0.71656698, -0.681717992,
426 	0.309017003, 0.5, -0.809017003,
427 	0.425325006, 0.688190997, -0.587785006,
428 	0.442862988, 0.238856003, -0.864188015,
429 	0.587785006, 0.425325006, -0.688190997,
430 	0.688190997, 0.587785006, -0.425325006,
431 	-0.147621006, 0.71656698, -0.681717992,
432 	-0.309017003, 0.5, -0.809017003,
433 	0, 0.525731027, -0.850651026,
434 	-0.525731027, 0, -0.850651026,
435 	-0.442862988, 0.238856003, -0.864188015,
436 	-0.295242012, 0, -0.955422997,
437 	-0.162459999, 0.26286599, -0.951056004,
438 	0, 0, -1,
439 	0.295242012, 0, -0.955422997,
440 	0.162459999, 0.26286599, -0.951056004,
441 	-0.442862988, -0.238856003, -0.864188015,
442 	-0.309017003, -0.5, -0.809017003,
443 	-0.162459999, -0.26286599, -0.951056004,
444 	0, -0.850651026, -0.525731027,
445 	-0.147621006, -0.71656698, -0.681717992,
446 	0.147621006, -0.71656698, -0.681717992,
447 	0, -0.525731027, -0.850651026,
448 	0.309017003, -0.5, -0.809017003,
449 	0.442862988, -0.238856003, -0.864188015,
450 	0.162459999, -0.26286599, -0.951056004,
451 	0.238856003, -0.864188015, -0.442862988,
452 	0.5, -0.809017003, -0.309017003,
453 	0.425325006, -0.688190997, -0.587785006,
454 	0.71656698, -0.681717992, -0.147621006,
455 	0.688190997, -0.587785006, -0.425325006,
456 	0.587785006, -0.425325006, -0.688190997,
457 	0, -0.955422997, -0.295242012,
458 	0, -1, 0,
459 	0.26286599, -0.951056004, -0.162459999,
460 	0, -0.850651026, 0.525731027,
461 	0, -0.955422997, 0.295242012,
462 	0.238856003, -0.864188015, 0.442862988,
463 	0.26286599, -0.951056004, 0.162459999,
464 	0.5, -0.809017003, 0.309017003,
465 	0.71656698, -0.681717992, 0.147621006,
466 	0.525731027, -0.850651026, 0,
467 	-0.238856003, -0.864188015, -0.442862988,
468 	-0.5, -0.809017003, -0.309017003,
469 	-0.26286599, -0.951056004, -0.162459999,
470 	-0.850651026, -0.525731027, 0,
471 	-0.71656698, -0.681717992, -0.147621006,
472 	-0.71656698, -0.681717992, 0.147621006,
473 	-0.525731027, -0.850651026, 0,
474 	-0.5, -0.809017003, 0.309017003,
475 	-0.238856003, -0.864188015, 0.442862988,
476 	-0.26286599, -0.951056004, 0.162459999,
477 	-0.864188015, -0.442862988, 0.238856003,
478 	-0.809017003, -0.309017003, 0.5,
479 	-0.688190997, -0.587785006, 0.425325006,
480 	-0.681717992, -0.147621006, 0.71656698,
481 	-0.442862988, -0.238856003, 0.864188015,
482 	-0.587785006, -0.425325006, 0.688190997,
483 	-0.309017003, -0.5, 0.809017003,
484 	-0.147621006, -0.71656698, 0.681717992,
485 	-0.425325006, -0.688190997, 0.587785006,
486 	-0.162459999, -0.26286599, 0.951056004,
487 	0.442862988, -0.238856003, 0.864188015,
488 	0.162459999, -0.26286599, 0.951056004,
489 	0.309017003, -0.5, 0.809017003,
490 	0.147621006, -0.71656698, 0.681717992,
491 	0, -0.525731027, 0.850651026,
492 	0.425325006, -0.688190997, 0.587785006,
493 	0.587785006, -0.425325006, 0.688190997,
494 	0.688190997, -0.587785006, 0.425325006,
495 	-0.955422997, 0.295242012, 0,
496 	-0.951056004, 0.162459999, 0.26286599,
497 	-1, 0, 0,
498 	-0.850651026, 0, 0.525731027,
499 	-0.955422997, -0.295242012, 0,
500 	-0.951056004, -0.162459999, 0.26286599,
501 	-0.864188015, 0.442862988, -0.238856003,
502 	-0.951056004, 0.162459999, -0.26286599,
503 	-0.809017003, 0.309017003, -0.5,
504 	-0.864188015, -0.442862988, -0.238856003,
505 	-0.951056004, -0.162459999, -0.26286599,
506 	-0.809017003, -0.309017003, -0.5,
507 	-0.681717992, 0.147621006, -0.71656698,
508 	-0.681717992, -0.147621006, -0.71656698,
509 	-0.850651026, 0, -0.525731027,
510 	-0.688190997, 0.587785006, -0.425325006,
511 	-0.587785006, 0.425325006, -0.688190997,
512 	-0.425325006, 0.688190997, -0.587785006,
513 	-0.425325006, -0.688190997, -0.587785006,
514 	-0.587785006, -0.425325006, -0.688190997,
515 	-0.688190997, -0.587785006, -0.425325006,
516 };
517 
ReadDir(block_t * block,float * a)518 float *ReadDir(block_t *block, float *a)
519 {
520 	int code;
521 
522 	code = ReadByte(block);
523 	if (code >= DM2_NUMVERTEXNORMALS)
524 		assert(0);
525 
526 	a[0] = avertexnormals[3 * code + 0];
527 	a[1] = avertexnormals[3 * code + 1];
528 	a[2] = avertexnormals[3 * code + 2];
529 
530 	return a;
531 }
532 
WriteDir(block_t * block,const float * a)533 void WriteDir(block_t *block, const float *a)
534 {
535 	int 	j, maxdotindex;
536 	float	dot, maxdot;
537 
538 	maxdot = -999999.0;
539 	maxdotindex = -1;
540 
541 	for (j = 0; j < DM2_NUMVERTEXNORMALS; j++)
542 	{
543 		dot = avertexnormals[3*j + 0] * a[0] +
544 			avertexnormals[3*j + 1] * a[1] +
545 			avertexnormals[3*j + 2] * a[2];
546 
547 		if (dot > maxdot)
548 		{
549 			maxdot = dot;
550 			maxdotindex = j;
551 		}
552 	}
553 
554 	WriteByte(block, (byte)maxdotindex);
555 }
556 
ReadBlend(block_t * block)557 float ReadBlend(block_t *block)
558 {
559 	return (float)ReadByte(block) / 255;
560 }
561 
WriteBlend(block_t * block,float a)562 void WriteBlend(block_t *block, float a)
563 {
564 	WriteByte(block, (byte)(a * 255));
565 }
566 
ReadBlendVec(block_t * block,float * a)567 float *ReadBlendVec(block_t *block, float *a)
568 {
569 	a[0] = ReadBlend(block);
570 	a[1] = ReadBlend(block);
571 	a[2] = ReadBlend(block);
572 	a[3] = ReadBlend(block);
573 
574 	return a;
575 }
576 
WriteBlendVec(block_t * block,const float * a)577 void WriteBlendVec(block_t *block, const float *a)
578 {
579 	WriteBlend(block, a[0]);
580 	WriteBlend(block, a[1]);
581 	WriteBlend(block, a[2]);
582 	WriteBlend(block, a[3]);
583 }
584 
ReadOffset(block_t * block)585 float ReadOffset(block_t *block)
586 {
587 	return (float)ReadChar(block) * 0.25F;
588 }
589 
WriteOffset(block_t * block,float a)590 void WriteOffset(block_t *block, float a)
591 {
592 	WriteChar(block, (char)(a * 4));
593 }
594 
ReadOffsetVec(block_t * block,float * a)595 float *ReadOffsetVec(block_t *block, float *a)
596 {
597 	a[0] = ReadOffset(block);
598 	a[1] = ReadOffset(block);
599 	a[2] = ReadOffset(block);
600 
601 	return a;
602 }
603 
WriteOffsetVec(block_t * block,const float * a)604 void WriteOffsetVec(block_t *block, const float *a)
605 {
606 	WriteOffset(block, a[0]);
607 	WriteOffset(block, a[1]);
608 	WriteOffset(block, a[2]);
609 }
610 
611