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