]> git.xonotic.org Git - xonotic/darkplaces.git/blob - com_msg.c
vpk: Include stdint.h only
[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         MSG_WriteShort (sb, Q_rint(f*8));
186 }
187
188 void MSG_WriteCoord16i (sizebuf_t *sb, float f)
189 {
190         MSG_WriteShort (sb, Q_rint(f));
191 }
192
193 void MSG_WriteCoord32f (sizebuf_t *sb, float f)
194 {
195         MSG_WriteFloat (sb, f);
196 }
197
198 void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol)
199 {
200         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
201                 MSG_WriteCoord13i (sb, f);
202         else if (protocol == PROTOCOL_DARKPLACES1)
203                 MSG_WriteCoord32f (sb, f);
204         else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
205                 MSG_WriteCoord16i (sb, f);
206         else
207                 MSG_WriteCoord32f (sb, f);
208 }
209
210 void MSG_WriteVector (sizebuf_t *sb, const vec3_t v, protocolversion_t protocol)
211 {
212         MSG_WriteCoord (sb, v[0], protocol);
213         MSG_WriteCoord (sb, v[1], protocol);
214         MSG_WriteCoord (sb, v[2], protocol);
215 }
216
217 // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
218 void MSG_WriteAngle8i (sizebuf_t *sb, float f)
219 {
220         MSG_WriteByte (sb, (int)Q_rint(f*(256.0/360.0)) & 255);
221 }
222
223 void MSG_WriteAngle16i (sizebuf_t *sb, float f)
224 {
225         MSG_WriteShort (sb, (int)Q_rint(f*(65536.0/360.0)) & 65535);
226 }
227
228 void MSG_WriteAngle32f (sizebuf_t *sb, float f)
229 {
230         MSG_WriteFloat (sb, f);
231 }
232
233 void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol)
234 {
235         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)
236                 MSG_WriteAngle8i (sb, f);
237         else
238                 MSG_WriteAngle16i (sb, f);
239 }
240
241 //
242 // reading functions
243 //
244
245 void MSG_InitReadBuffer (sizebuf_t *buf, unsigned char *data, int size)
246 {
247         memset(buf, 0, sizeof(*buf));
248         buf->data = data;
249         buf->maxsize = buf->cursize = size;
250         MSG_BeginReading(buf);
251 }
252
253 void MSG_BeginReading(sizebuf_t *sb)
254 {
255         sb->readcount = 0;
256         sb->badread = false;
257 }
258
259 int MSG_ReadLittleShort(sizebuf_t *sb)
260 {
261         if (sb->readcount+2 > sb->cursize)
262         {
263                 sb->badread = true;
264                 return -1;
265         }
266         sb->readcount += 2;
267         return (short)(sb->data[sb->readcount-2] | (sb->data[sb->readcount-1]<<8));
268 }
269
270 int MSG_ReadBigShort (sizebuf_t *sb)
271 {
272         if (sb->readcount+2 > sb->cursize)
273         {
274                 sb->badread = true;
275                 return -1;
276         }
277         sb->readcount += 2;
278         return (short)((sb->data[sb->readcount-2]<<8) + sb->data[sb->readcount-1]);
279 }
280
281 int MSG_ReadLittleLong (sizebuf_t *sb)
282 {
283         if (sb->readcount+4 > sb->cursize)
284         {
285                 sb->badread = true;
286                 return -1;
287         }
288         sb->readcount += 4;
289         return sb->data[sb->readcount-4] | (sb->data[sb->readcount-3]<<8) | (sb->data[sb->readcount-2]<<16) | (sb->data[sb->readcount-1]<<24);
290 }
291
292 int MSG_ReadBigLong (sizebuf_t *sb)
293 {
294         if (sb->readcount+4 > sb->cursize)
295         {
296                 sb->badread = true;
297                 return -1;
298         }
299         sb->readcount += 4;
300         return (sb->data[sb->readcount-4]<<24) + (sb->data[sb->readcount-3]<<16) + (sb->data[sb->readcount-2]<<8) + sb->data[sb->readcount-1];
301 }
302
303 float MSG_ReadLittleFloat (sizebuf_t *sb)
304 {
305         union
306         {
307                 float f;
308                 int l;
309         } dat;
310         if (sb->readcount+4 > sb->cursize)
311         {
312                 sb->badread = true;
313                 return -1;
314         }
315         sb->readcount += 4;
316         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);
317         return dat.f;
318 }
319
320 float MSG_ReadBigFloat (sizebuf_t *sb)
321 {
322         union
323         {
324                 float f;
325                 int l;
326         } dat;
327         if (sb->readcount+4 > sb->cursize)
328         {
329                 sb->badread = true;
330                 return -1;
331         }
332         sb->readcount += 4;
333         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];
334         return dat.f;
335 }
336
337 char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring)
338 {
339         int c;
340         size_t l = 0;
341         // read string into sbfer, but only store as many characters as will fit
342         while ((c = MSG_ReadByte(sb)) > 0)
343                 if (l < maxstring - 1)
344                         string[l++] = c;
345         string[l] = 0;
346         return string;
347 }
348
349 int MSG_ReadBytes (sizebuf_t *sb, int numbytes, unsigned char *out)
350 {
351         int l, c;
352         for (l = 0;l < numbytes && (c = MSG_ReadByte(sb)) != -1;l++)
353                 out[l] = c;
354         return l;
355 }
356
357 float MSG_ReadCoord13i (sizebuf_t *sb)
358 {
359         return MSG_ReadLittleShort(sb) * (1.0/8.0);
360 }
361
362 float MSG_ReadCoord16i (sizebuf_t *sb)
363 {
364         return (signed short) MSG_ReadLittleShort(sb);
365 }
366
367 float MSG_ReadCoord32f (sizebuf_t *sb)
368 {
369         return MSG_ReadLittleFloat(sb);
370 }
371
372 float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol)
373 {
374         if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
375                 return MSG_ReadCoord13i(sb);
376         else if (protocol == PROTOCOL_DARKPLACES1)
377                 return MSG_ReadCoord32f(sb);
378         else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
379                 return MSG_ReadCoord16i(sb);
380         else
381                 return MSG_ReadCoord32f(sb);
382 }
383
384 void MSG_ReadVector (sizebuf_t *sb, vec3_t v, protocolversion_t protocol)
385 {
386         v[0] = MSG_ReadCoord(sb, protocol);
387         v[1] = MSG_ReadCoord(sb, protocol);
388         v[2] = MSG_ReadCoord(sb, protocol);
389 }
390
391 // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
392 float MSG_ReadAngle8i (sizebuf_t *sb)
393 {
394         return (signed char) MSG_ReadByte (sb) * (360.0/256.0);
395 }
396
397 float MSG_ReadAngle16i (sizebuf_t *sb)
398 {
399         return (signed short)MSG_ReadShort (sb) * (360.0/65536.0);
400 }
401
402 float MSG_ReadAngle32f (sizebuf_t *sb)
403 {
404         return MSG_ReadFloat (sb);
405 }
406
407 float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol)
408 {
409         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)
410                 return MSG_ReadAngle8i (sb);
411         else
412                 return MSG_ReadAngle16i (sb);
413 }