]> git.xonotic.org Git - xonotic/darkplaces.git/blob - com_msg.c
Merge PR 'Make particles solid squares when cl_particles_quake is set to 2'
[xonotic/darkplaces.git] / com_msg.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the 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 */
20 // com_msg.c
21
22 #include "quakedef.h"
23
24 /*
25 ============================================================================
26
27                                         BYTE ORDER FUNCTIONS
28
29 ============================================================================
30 */
31
32
33 float BuffBigFloat (const unsigned char *buffer)
34 {
35         union
36         {
37                 float f;
38                 unsigned int i;
39         }
40         u;
41         u.i = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
42         return u.f;
43 }
44
45 int BuffBigLong (const unsigned char *buffer)
46 {
47         return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
48 }
49
50 short BuffBigShort (const unsigned char *buffer)
51 {
52         return (buffer[0] << 8) | buffer[1];
53 }
54
55 float BuffLittleFloat (const unsigned char *buffer)
56 {
57         union
58         {
59                 float f;
60                 unsigned int i;
61         }
62         u;
63         u.i = (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
64         return u.f;
65 }
66
67 int BuffLittleLong (const unsigned char *buffer)
68 {
69         return (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
70 }
71
72 short BuffLittleShort (const unsigned char *buffer)
73 {
74         return (buffer[1] << 8) | buffer[0];
75 }
76
77 void StoreBigLong (unsigned char *buffer, unsigned int i)
78 {
79         buffer[0] = (i >> 24) & 0xFF;
80         buffer[1] = (i >> 16) & 0xFF;
81         buffer[2] = (i >>  8) & 0xFF;
82         buffer[3] = i         & 0xFF;
83 }
84
85 void StoreBigShort (unsigned char *buffer, unsigned short i)
86 {
87         buffer[0] = (i >>  8) & 0xFF;
88         buffer[1] = i         & 0xFF;
89 }
90
91 void StoreLittleLong (unsigned char *buffer, unsigned int i)
92 {
93         buffer[0] = i         & 0xFF;
94         buffer[1] = (i >>  8) & 0xFF;
95         buffer[2] = (i >> 16) & 0xFF;
96         buffer[3] = (i >> 24) & 0xFF;
97 }
98
99 void StoreLittleShort (unsigned char *buffer, unsigned short i)
100 {
101         buffer[0] = i         & 0xFF;
102         buffer[1] = (i >>  8) & 0xFF;
103 }
104
105 /*
106 ==============================================================================
107
108                         MESSAGE IO FUNCTIONS
109
110 Handles byte ordering and avoids alignment errors
111 ==============================================================================
112 */
113
114 //
115 // writing functions
116 //
117
118 void MSG_WriteChar (sizebuf_t *sb, int c)
119 {
120         unsigned char    *buf;
121
122         buf = SZ_GetSpace (sb, 1);
123         buf[0] = c;
124 }
125
126 void MSG_WriteByte (sizebuf_t *sb, int c)
127 {
128         unsigned char    *buf;
129
130         buf = SZ_GetSpace (sb, 1);
131         buf[0] = c;
132 }
133
134 void MSG_WriteShort (sizebuf_t *sb, int c)
135 {
136         unsigned char    *buf;
137
138         buf = SZ_GetSpace (sb, 2);
139         buf[0] = c&0xff;
140         buf[1] = c>>8;
141 }
142
143 void MSG_WriteLong (sizebuf_t *sb, int c)
144 {
145         unsigned char    *buf;
146
147         buf = SZ_GetSpace (sb, 4);
148         buf[0] = c&0xff;
149         buf[1] = (c>>8)&0xff;
150         buf[2] = (c>>16)&0xff;
151         buf[3] = c>>24;
152 }
153
154 void MSG_WriteFloat (sizebuf_t *sb, float f)
155 {
156         union
157         {
158                 float   f;
159                 int     l;
160         } dat;
161
162
163         dat.f = f;
164         dat.l = LittleLong (dat.l);
165
166         SZ_Write (sb, (unsigned char *)&dat.l, 4);
167 }
168
169 void MSG_WriteString (sizebuf_t *sb, const char *s)
170 {
171         if (!s || !*s)
172                 MSG_WriteChar (sb, 0);
173         else
174                 SZ_Write (sb, (unsigned char *)s, (int)strlen(s)+1);
175 }
176
177 void MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s)
178 {
179         if (s && *s)
180                 SZ_Write (sb, (unsigned char *)s, (int)strlen(s));
181 }
182
183 void MSG_WriteCoord13i (sizebuf_t *sb, float f)
184 {
185         if (f >= 0)
186                 MSG_WriteShort (sb, (int)(f * 8.0 + 0.5));
187         else
188                 MSG_WriteShort (sb, (int)(f * 8.0 - 0.5));
189 }
190
191 void MSG_WriteCoord16i (sizebuf_t *sb, float f)
192 {
193         if (f >= 0)
194                 MSG_WriteShort (sb, (int)(f + 0.5));
195         else
196                 MSG_WriteShort (sb, (int)(f - 0.5));
197 }
198
199 void MSG_WriteCoord32f (sizebuf_t *sb, float f)
200 {
201         MSG_WriteFloat (sb, f);
202 }
203
204 void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol)
205 {
206         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
207                 MSG_WriteCoord13i (sb, f);
208         else if (protocol == PROTOCOL_DARKPLACES1)
209                 MSG_WriteCoord32f (sb, f);
210         else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
211                 MSG_WriteCoord16i (sb, f);
212         else
213                 MSG_WriteCoord32f (sb, f);
214 }
215
216 void MSG_WriteVector (sizebuf_t *sb, const vec3_t v, protocolversion_t protocol)
217 {
218         MSG_WriteCoord (sb, v[0], protocol);
219         MSG_WriteCoord (sb, v[1], protocol);
220         MSG_WriteCoord (sb, v[2], protocol);
221 }
222
223 // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
224 void MSG_WriteAngle8i (sizebuf_t *sb, float f)
225 {
226         if (f >= 0)
227                 MSG_WriteByte (sb, (int)(f*(256.0/360.0) + 0.5) & 255);
228         else
229                 MSG_WriteByte (sb, (int)(f*(256.0/360.0) - 0.5) & 255);
230 }
231
232 void MSG_WriteAngle16i (sizebuf_t *sb, float f)
233 {
234         if (f >= 0)
235                 MSG_WriteShort (sb, (int)(f*(65536.0/360.0) + 0.5) & 65535);
236         else
237                 MSG_WriteShort (sb, (int)(f*(65536.0/360.0) - 0.5) & 65535);
238 }
239
240 void MSG_WriteAngle32f (sizebuf_t *sb, float f)
241 {
242         MSG_WriteFloat (sb, f);
243 }
244
245 void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol)
246 {
247         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD)
248                 MSG_WriteAngle8i (sb, f);
249         else
250                 MSG_WriteAngle16i (sb, f);
251 }
252
253 //
254 // reading functions
255 //
256
257 void MSG_InitReadBuffer (sizebuf_t *buf, unsigned char *data, int size)
258 {
259         memset(buf, 0, sizeof(*buf));
260         buf->data = data;
261         buf->maxsize = buf->cursize = size;
262         MSG_BeginReading(buf);
263 }
264
265 void MSG_BeginReading(sizebuf_t *sb)
266 {
267         sb->readcount = 0;
268         sb->badread = false;
269 }
270
271 int MSG_ReadLittleShort(sizebuf_t *sb)
272 {
273         if (sb->readcount+2 > sb->cursize)
274         {
275                 sb->badread = true;
276                 return -1;
277         }
278         sb->readcount += 2;
279         return (short)(sb->data[sb->readcount-2] | (sb->data[sb->readcount-1]<<8));
280 }
281
282 int MSG_ReadBigShort (sizebuf_t *sb)
283 {
284         if (sb->readcount+2 > sb->cursize)
285         {
286                 sb->badread = true;
287                 return -1;
288         }
289         sb->readcount += 2;
290         return (short)((sb->data[sb->readcount-2]<<8) + sb->data[sb->readcount-1]);
291 }
292
293 int MSG_ReadLittleLong (sizebuf_t *sb)
294 {
295         if (sb->readcount+4 > sb->cursize)
296         {
297                 sb->badread = true;
298                 return -1;
299         }
300         sb->readcount += 4;
301         return sb->data[sb->readcount-4] | (sb->data[sb->readcount-3]<<8) | (sb->data[sb->readcount-2]<<16) | (sb->data[sb->readcount-1]<<24);
302 }
303
304 int MSG_ReadBigLong (sizebuf_t *sb)
305 {
306         if (sb->readcount+4 > sb->cursize)
307         {
308                 sb->badread = true;
309                 return -1;
310         }
311         sb->readcount += 4;
312         return (sb->data[sb->readcount-4]<<24) + (sb->data[sb->readcount-3]<<16) + (sb->data[sb->readcount-2]<<8) + sb->data[sb->readcount-1];
313 }
314
315 float MSG_ReadLittleFloat (sizebuf_t *sb)
316 {
317         union
318         {
319                 float f;
320                 int l;
321         } dat;
322         if (sb->readcount+4 > sb->cursize)
323         {
324                 sb->badread = true;
325                 return -1;
326         }
327         sb->readcount += 4;
328         dat.l = sb->data[sb->readcount-4] | (sb->data[sb->readcount-3]<<8) | (sb->data[sb->readcount-2]<<16) | (sb->data[sb->readcount-1]<<24);
329         return dat.f;
330 }
331
332 float MSG_ReadBigFloat (sizebuf_t *sb)
333 {
334         union
335         {
336                 float f;
337                 int l;
338         } dat;
339         if (sb->readcount+4 > sb->cursize)
340         {
341                 sb->badread = true;
342                 return -1;
343         }
344         sb->readcount += 4;
345         dat.l = (sb->data[sb->readcount-4]<<24) | (sb->data[sb->readcount-3]<<16) | (sb->data[sb->readcount-2]<<8) | sb->data[sb->readcount-1];
346         return dat.f;
347 }
348
349 char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring)
350 {
351         int c;
352         size_t l = 0;
353         // read string into sbfer, but only store as many characters as will fit
354         while ((c = MSG_ReadByte(sb)) > 0)
355                 if (l < maxstring - 1)
356                         string[l++] = c;
357         string[l] = 0;
358         return string;
359 }
360
361 int MSG_ReadBytes (sizebuf_t *sb, int numbytes, unsigned char *out)
362 {
363         int l, c;
364         for (l = 0;l < numbytes && (c = MSG_ReadByte(sb)) != -1;l++)
365                 out[l] = c;
366         return l;
367 }
368
369 float MSG_ReadCoord13i (sizebuf_t *sb)
370 {
371         return MSG_ReadLittleShort(sb) * (1.0/8.0);
372 }
373
374 float MSG_ReadCoord16i (sizebuf_t *sb)
375 {
376         return (signed short) MSG_ReadLittleShort(sb);
377 }
378
379 float MSG_ReadCoord32f (sizebuf_t *sb)
380 {
381         return MSG_ReadLittleFloat(sb);
382 }
383
384 float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol)
385 {
386         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
387                 return MSG_ReadCoord13i(sb);
388         else if (protocol == PROTOCOL_DARKPLACES1)
389                 return MSG_ReadCoord32f(sb);
390         else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
391                 return MSG_ReadCoord16i(sb);
392         else
393                 return MSG_ReadCoord32f(sb);
394 }
395
396 void MSG_ReadVector (sizebuf_t *sb, vec3_t v, protocolversion_t protocol)
397 {
398         v[0] = MSG_ReadCoord(sb, protocol);
399         v[1] = MSG_ReadCoord(sb, protocol);
400         v[2] = MSG_ReadCoord(sb, protocol);
401 }
402
403 // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
404 float MSG_ReadAngle8i (sizebuf_t *sb)
405 {
406         return (signed char) MSG_ReadByte (sb) * (360.0/256.0);
407 }
408
409 float MSG_ReadAngle16i (sizebuf_t *sb)
410 {
411         return (signed short)MSG_ReadShort (sb) * (360.0/65536.0);
412 }
413
414 float MSG_ReadAngle32f (sizebuf_t *sb)
415 {
416         return MSG_ReadFloat (sb);
417 }
418
419 float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol)
420 {
421         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4 || protocol == PROTOCOL_QUAKEWORLD)
422                 return MSG_ReadAngle8i (sb);
423         else
424                 return MSG_ReadAngle16i (sb);
425 }