2 Copyright (C) 1996-1997 Id Software, Inc.
3 Copyright (C) 2000-2020 DarkPlaces contributors
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.
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.
14 See the GNU General Public License for more details.
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.
26 ============================================================================
30 ============================================================================
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.
37 float BuffBigFloat (const unsigned char *buffer)
45 u.i = ((unsigned)buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
49 int BuffBigLong (const unsigned char *buffer)
51 return ((unsigned)buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
54 short BuffBigShort (const unsigned char *buffer)
56 return (buffer[0] << 8) | buffer[1];
59 float BuffLittleFloat (const unsigned char *buffer)
67 u.i = ((unsigned)buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
71 int BuffLittleLong (const unsigned char *buffer)
73 return ((unsigned)buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
76 short BuffLittleShort (const unsigned char *buffer)
78 return (buffer[1] << 8) | buffer[0];
81 void StoreBigLong (unsigned char *buffer, unsigned int i)
83 buffer[0] = (i >> 24) & 0xFF;
84 buffer[1] = (i >> 16) & 0xFF;
85 buffer[2] = (i >> 8) & 0xFF;
89 void StoreBigShort (unsigned char *buffer, unsigned short i)
91 buffer[0] = (i >> 8) & 0xFF;
95 void StoreLittleLong (unsigned char *buffer, unsigned int i)
98 buffer[1] = (i >> 8) & 0xFF;
99 buffer[2] = (i >> 16) & 0xFF;
100 buffer[3] = (i >> 24) & 0xFF;
103 void StoreLittleShort (unsigned char *buffer, unsigned short i)
105 buffer[0] = i & 0xFF;
106 buffer[1] = (i >> 8) & 0xFF;
110 ==============================================================================
114 Handles byte ordering and avoids alignment errors
115 ==============================================================================
122 void MSG_WriteChar (sizebuf_t *sb, int c)
126 buf = SZ_GetSpace (sb, 1);
130 void MSG_WriteByte (sizebuf_t *sb, int c)
134 buf = SZ_GetSpace (sb, 1);
138 void MSG_WriteShort (sizebuf_t *sb, int c)
142 buf = SZ_GetSpace (sb, 2);
147 void MSG_WriteLong (sizebuf_t *sb, int c)
151 buf = SZ_GetSpace (sb, 4);
153 buf[1] = (c>>8)&0xff;
154 buf[2] = (c>>16)&0xff;
158 void MSG_WriteFloat (sizebuf_t *sb, float f)
168 dat.l = LittleLong (dat.l);
170 SZ_Write (sb, (unsigned char *)&dat.l, 4);
173 void MSG_WriteString (sizebuf_t *sb, const char *s)
176 MSG_WriteChar (sb, 0);
178 SZ_Write (sb, (unsigned char *)s, (int)strlen(s)+1);
181 void MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s)
184 SZ_Write (sb, (unsigned char *)s, (int)strlen(s));
187 void MSG_WriteCoord13i (sizebuf_t *sb, float f)
189 MSG_WriteShort (sb, Q_rint(f*8));
192 void MSG_WriteCoord16i (sizebuf_t *sb, float f)
194 MSG_WriteShort (sb, Q_rint(f));
197 void MSG_WriteCoord32f (sizebuf_t *sb, float f)
199 MSG_WriteFloat (sb, f);
202 void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol)
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);
211 MSG_WriteCoord32f (sb, f);
214 void MSG_WriteVector (sizebuf_t *sb, const vec3_t v, protocolversion_t protocol)
216 MSG_WriteCoord (sb, v[0], protocol);
217 MSG_WriteCoord (sb, v[1], protocol);
218 MSG_WriteCoord (sb, v[2], protocol);
221 // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
222 void MSG_WriteAngle8i (sizebuf_t *sb, float f)
224 MSG_WriteByte (sb, (int)Q_rint(f*(256.0/360.0)) & 255);
227 void MSG_WriteAngle16i (sizebuf_t *sb, float f)
229 MSG_WriteShort (sb, (int)Q_rint(f*(65536.0/360.0)) & 65535);
232 void MSG_WriteAngle32f (sizebuf_t *sb, float f)
234 MSG_WriteFloat (sb, f);
237 void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol)
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);
242 MSG_WriteAngle16i (sb, f);
249 void MSG_InitReadBuffer (sizebuf_t *buf, unsigned char *data, int size)
251 memset(buf, 0, sizeof(*buf));
253 buf->maxsize = buf->cursize = size;
254 MSG_BeginReading(buf);
257 void MSG_BeginReading(sizebuf_t *sb)
263 int MSG_ReadLittleShort(sizebuf_t *sb)
265 if (sb->readcount+2 > sb->cursize)
271 return (short)(sb->data[sb->readcount-2] | (sb->data[sb->readcount-1]<<8));
274 int MSG_ReadBigShort (sizebuf_t *sb)
276 if (sb->readcount+2 > sb->cursize)
282 return (short)((sb->data[sb->readcount-2]<<8) + sb->data[sb->readcount-1]);
285 int MSG_ReadLittleLong (sizebuf_t *sb)
287 if (sb->readcount+4 > sb->cursize)
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);
296 int MSG_ReadBigLong (sizebuf_t *sb)
298 if (sb->readcount+4 > sb->cursize)
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];
307 float MSG_ReadLittleFloat (sizebuf_t *sb)
314 if (sb->readcount+4 > sb->cursize)
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);
324 float MSG_ReadBigFloat (sizebuf_t *sb)
331 if (sb->readcount+4 > sb->cursize)
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];
341 char *MSG_ReadString (sizebuf_t *sb, char *string, size_t maxstring)
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')
352 size_t MSG_ReadString_len (sizebuf_t *sb, char *string, size_t maxstring)
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')
364 size_t MSG_ReadBytes (sizebuf_t *sb, size_t numbytes, unsigned char *out)
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);
374 float MSG_ReadCoord13i (sizebuf_t *sb)
376 return MSG_ReadLittleShort(sb) * (1.0/8.0);
379 float MSG_ReadCoord16i (sizebuf_t *sb)
381 return (signed short) MSG_ReadLittleShort(sb);
384 float MSG_ReadCoord32f (sizebuf_t *sb)
386 return MSG_ReadLittleFloat(sb);
389 float MSG_ReadCoord (sizebuf_t *sb, protocolversion_t protocol)
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);
398 return MSG_ReadCoord32f(sb);
401 void MSG_ReadVector (sizebuf_t *sb, vec3_t v, protocolversion_t protocol)
403 v[0] = MSG_ReadCoord(sb, protocol);
404 v[1] = MSG_ReadCoord(sb, protocol);
405 v[2] = MSG_ReadCoord(sb, protocol);
408 // LadyHavoc: round to nearest value, rather than rounding toward zero, fixes crosshair problem
409 float MSG_ReadAngle8i (sizebuf_t *sb)
411 return (signed char) MSG_ReadByte (sb) * (360.0/256.0);
414 float MSG_ReadAngle16i (sizebuf_t *sb)
416 return (signed short)MSG_ReadShort (sb) * (360.0/65536.0);
419 float MSG_ReadAngle32f (sizebuf_t *sb)
421 return MSG_ReadFloat (sb);
424 float MSG_ReadAngle (sizebuf_t *sb, protocolversion_t protocol)
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);
429 return MSG_ReadAngle16i (sb);