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