DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
com_msg.c
Go to the documentation of this file.
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3Copyright (C) 2000-2020 DarkPlaces contributors
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
14See the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 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
37float 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
49int BuffBigLong (const unsigned char *buffer)
50{
51 return ((unsigned)buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
52}
53
54short BuffBigShort (const unsigned char *buffer)
55{
56 return (buffer[0] << 8) | buffer[1];
57}
58
59float 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
71int BuffLittleLong (const unsigned char *buffer)
72{
73 return ((unsigned)buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
74}
75
76short BuffLittleShort (const unsigned char *buffer)
77{
78 return (buffer[1] << 8) | buffer[0];
79}
80
81void 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
89void StoreBigShort (unsigned char *buffer, unsigned short i)
90{
91 buffer[0] = (i >> 8) & 0xFF;
92 buffer[1] = i & 0xFF;
93}
94
95void 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
103void 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
114Handles byte ordering and avoids alignment errors
115==============================================================================
116*/
117
118//
119// writing functions
120//
121
122void 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
130void 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
138void 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
147void 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
158void 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
173void 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
181void 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
188{
189 MSG_WriteShort (sb, Q_rint(f*8));
190}
191
193{
194 MSG_WriteShort (sb, Q_rint(f));
195}
196
198{
199 MSG_WriteFloat (sb, f);
200}
201
202void 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
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
222void MSG_WriteAngle8i (sizebuf_t *sb, float f)
223{
224 MSG_WriteByte (sb, (int)Q_rint(f*(256.0/360.0)) & 255);
225}
226
228{
229 MSG_WriteShort (sb, (int)Q_rint(f*(65536.0/360.0)) & 65535);
230}
231
233{
234 MSG_WriteFloat (sb, f);
235}
236
237void 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
249void 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;
255}
256
258{
259 sb->readcount = 0;
260 sb->badread = false;
261}
262
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
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
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
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
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
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
341char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring)
342{
343 size_t l = 0;
344
345 // read string into sbfer, but only store as many characters as will fit
346 // if dest buffer is full sb->readcount will still be advanced to end of message string
347 while ((string[l] = MSG_ReadByte_opt(sb)) != '\0')
348 if (l < maxstring)
349 ++l;
350 return string;
351}
352size_t MSG_ReadString_len (sizebuf_t *sb, char *string, size_t maxstring)
353{
354 size_t l = 0;
355
356 // read string into sbfer, but only store as many characters as will fit
357 // if dest buffer is full sb->readcount will still be advanced to end of message string
358 while ((string[l] = MSG_ReadByte_opt(sb)) != '\0')
359 if (l < maxstring)
360 ++l;
361 return l;
362}
363
364size_t MSG_ReadBytes (sizebuf_t *sb, size_t numbytes, unsigned char *out)
365{
366 size_t l = 0;
367
368 // when numbytes have been read sb->readcount won't be advanced any further
369 while (l < numbytes && !sb->badread)
370 out[l++] = MSG_ReadByte_opt(sb);
371 return l;
372}
373
375{
376 return MSG_ReadLittleShort(sb) * (1.0/8.0);
377}
378
380{
381 return (signed short) MSG_ReadLittleShort(sb);
382}
383
385{
386 return MSG_ReadLittleFloat(sb);
387}
388
390{
391 if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_NEHAHRABJP || protocol == PROTOCOL_NEHAHRABJP2 || protocol == PROTOCOL_NEHAHRABJP3 || protocol == PROTOCOL_QUAKEWORLD)
392 return MSG_ReadCoord13i(sb);
393 else if (protocol == PROTOCOL_DARKPLACES1)
394 return MSG_ReadCoord32f(sb);
395 else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
396 return MSG_ReadCoord16i(sb);
397 else
398 return MSG_ReadCoord32f(sb);
399}
400
402{
403 v[0] = MSG_ReadCoord(sb, protocol);
404 v[1] = MSG_ReadCoord(sb, protocol);
405 v[2] = MSG_ReadCoord(sb, protocol);
406}
407
408// LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
410{
411 return (signed char) MSG_ReadByte (sb) * (360.0/256.0);
412}
413
415{
416 return (signed short)MSG_ReadShort (sb) * (360.0/65536.0);
417}
418
420{
421 return MSG_ReadFloat (sb);
422}
423
425{
426 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)
427 return MSG_ReadAngle8i (sb);
428 else
429 return MSG_ReadAngle16i (sb);
430}
void MSG_WriteCoord32f(sizebuf_t *sb, float f)
Definition com_msg.c:197
void MSG_BeginReading(sizebuf_t *sb)
Definition com_msg.c:257
int MSG_ReadBigShort(sizebuf_t *sb)
Definition com_msg.c:274
char * MSG_ReadString(sizebuf_t *sb, char *string, size_t maxstring)
Definition com_msg.c:341
void StoreBigShort(unsigned char *buffer, unsigned short i)
Encode a big endian 16bit int to the given buffer.
Definition com_msg.c:89
float BuffLittleFloat(const unsigned char *buffer)
Extract a little endian 32bit float from the given buffer.
Definition com_msg.c:59
float MSG_ReadAngle(sizebuf_t *sb, protocolversion_t protocol)
Definition com_msg.c:424
void MSG_WriteShort(sizebuf_t *sb, int c)
Definition com_msg.c:138
void MSG_ReadVector(sizebuf_t *sb, vec3_t v, protocolversion_t protocol)
Definition com_msg.c:401
float MSG_ReadAngle32f(sizebuf_t *sb)
Definition com_msg.c:419
void MSG_WriteString(sizebuf_t *sb, const char *s)
Definition com_msg.c:173
float MSG_ReadCoord32f(sizebuf_t *sb)
Definition com_msg.c:384
void MSG_WriteAngle16i(sizebuf_t *sb, float f)
Definition com_msg.c:227
void StoreLittleShort(unsigned char *buffer, unsigned short i)
Encode a little endian 16bit int to the given buffer.
Definition com_msg.c:103
float MSG_ReadLittleFloat(sizebuf_t *sb)
Definition com_msg.c:307
size_t MSG_ReadBytes(sizebuf_t *sb, size_t numbytes, unsigned char *out)
Definition com_msg.c:364
short BuffLittleShort(const unsigned char *buffer)
Extract a little endian 16bit short from the given buffer.
Definition com_msg.c:76
void MSG_WriteLong(sizebuf_t *sb, int c)
Definition com_msg.c:147
int MSG_ReadBigLong(sizebuf_t *sb)
Definition com_msg.c:296
void MSG_InitReadBuffer(sizebuf_t *buf, unsigned char *data, int size)
Definition com_msg.c:249
void MSG_WriteCoord(sizebuf_t *sb, float f, protocolversion_t protocol)
Definition com_msg.c:202
float MSG_ReadCoord13i(sizebuf_t *sb)
Definition com_msg.c:374
float MSG_ReadAngle8i(sizebuf_t *sb)
Definition com_msg.c:409
float MSG_ReadAngle16i(sizebuf_t *sb)
Definition com_msg.c:414
void MSG_WriteByte(sizebuf_t *sb, int c)
Definition com_msg.c:130
void MSG_WriteFloat(sizebuf_t *sb, float f)
Definition com_msg.c:158
void MSG_WriteVector(sizebuf_t *sb, const vec3_t v, protocolversion_t protocol)
Definition com_msg.c:214
float BuffBigFloat(const unsigned char *buffer)
Extract a big endian 32bit float from the given buffer.
Definition com_msg.c:37
void MSG_WriteAngle(sizebuf_t *sb, float f, protocolversion_t protocol)
Definition com_msg.c:237
float MSG_ReadBigFloat(sizebuf_t *sb)
Definition com_msg.c:324
int BuffLittleLong(const unsigned char *buffer)
Extract a little endian 32bit int from the given buffer.
Definition com_msg.c:71
float MSG_ReadCoord(sizebuf_t *sb, protocolversion_t protocol)
Definition com_msg.c:389
void MSG_WriteUnterminatedString(sizebuf_t *sb, const char *s)
Definition com_msg.c:181
void MSG_WriteAngle32f(sizebuf_t *sb, float f)
Definition com_msg.c:232
int MSG_ReadLittleLong(sizebuf_t *sb)
Definition com_msg.c:285
float MSG_ReadCoord16i(sizebuf_t *sb)
Definition com_msg.c:379
int MSG_ReadLittleShort(sizebuf_t *sb)
Definition com_msg.c:263
short BuffBigShort(const unsigned char *buffer)
Extract a big endian 16bit short from the given buffer.
Definition com_msg.c:54
void MSG_WriteCoord13i(sizebuf_t *sb, float f)
Definition com_msg.c:187
size_t MSG_ReadString_len(sizebuf_t *sb, char *string, size_t maxstring)
Same as MSG_ReadString except it returns the number of bytes written to *string excluding the \0 term...
Definition com_msg.c:352
void StoreLittleLong(unsigned char *buffer, unsigned int i)
Encode a little endian 32bit int to the given buffer.
Definition com_msg.c:95
void MSG_WriteChar(sizebuf_t *sb, int c)
Definition com_msg.c:122
void StoreBigLong(unsigned char *buffer, unsigned int i)
Encode a big endian 32bit int to the given buffer.
Definition com_msg.c:81
int BuffBigLong(const unsigned char *buffer)
Extract a big endian 32bit int from the given buffer.
Definition com_msg.c:49
void MSG_WriteAngle8i(sizebuf_t *sb, float f)
Definition com_msg.c:222
void MSG_WriteCoord16i(sizebuf_t *sb, float f)
Definition com_msg.c:192
unsigned char * SZ_GetSpace(sizebuf_t *buf, int length)
Definition common.c:49
void SZ_Write(sizebuf_t *buf, const unsigned char *data, int length)
Definition common.c:72
#define MSG_ReadShort
Definition common.h:191
#define MSG_ReadFloat
Definition common.h:193
protocolversion_t
Definition common.h:132
@ PROTOCOL_DARKPLACES2
various changes
Definition common.h:140
@ PROTOCOL_DARKPLACES4
various changes
Definition common.h:138
@ PROTOCOL_NEHAHRABJP2
same as NEHAHRABJP but with 16bit soundindex
Definition common.h:147
@ PROTOCOL_DARKPLACES3
uses EntityFrame4 entity snapshot encoder/decoder which is broken, this attempted to do partial snaps...
Definition common.h:139
@ PROTOCOL_NEHAHRABJP
same as QUAKEDP but with 16bit modelindex
Definition common.h:146
@ PROTOCOL_QUAKEDP
darkplaces extended quake protocol (used by TomazQuake and others), backwards compatible as long as n...
Definition common.h:142
@ PROTOCOL_QUAKE
quake (aka netquake/normalquake/nq) protocol
Definition common.h:144
@ PROTOCOL_NEHAHRABJP3
same as NEHAHRABJP2 but with some changes
Definition common.h:148
@ PROTOCOL_NEHAHRAMOVIE
Nehahra movie protocol, a big nasty hack dating back to early days of the Quake Standards Group (but ...
Definition common.h:143
@ PROTOCOL_QUAKEWORLD
quakeworld protocol
Definition common.h:145
@ PROTOCOL_DARKPLACES1
uses EntityFrame entity snapshot encoder/decoder which is a QuakeWorld-like entity snapshot delta com...
Definition common.h:141
#define LittleLong(l)
Definition common.h:92
#define MSG_ReadByte_opt(sb)
Same as MSG_ReadByte but with no need to copy twice (first to int to check for -1) so each byte can b...
Definition common.h:190
#define MSG_ReadByte(sb)
Definition common.h:188
vector size
GLsizei const GLchar ** string
Definition glquake.h:728
GLuint buffer
Definition glquake.h:630
const GLdouble * v
Definition glquake.h:762
GLsizeiptr const GLvoid * data
Definition glquake.h:639
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
#define Q_rint(x)
Definition mathlib.h:69
float strlen(string s)
int i
vec_t vec3_t[3]
Definition qtypes.h:71
float f
unsigned char * data
Definition common.h:52
int cursize
Definition common.h:54
qbool badread
Definition common.h:56
int readcount
Definition common.h:55