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