mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 18:00:25 +02:00
583 lines
15 KiB
C
583 lines
15 KiB
C
/*
|
|
DATA_PACKETS.C
|
|
|
|
symbols in this file:
|
|
0010A5F0 01d0:
|
|
_code_0010a5f0 (0000)
|
|
0010A7C0 0300:
|
|
_code_0010a7c0 (0000)
|
|
0010AAC0 02a0:
|
|
_code_0010aac0 (0000)
|
|
0010AD60 0110:
|
|
_data_packet_verify (0000)
|
|
0010AE70 0100:
|
|
_data_packet_encode (0000)
|
|
0010AF70 0100:
|
|
_data_packet_decode (0000)
|
|
0027D94C 0030:
|
|
??_C@_0DA@CDEMHOHB@field?5has?5negative?5or?5zero?5count@ (0000)
|
|
0027D980 0047:
|
|
??_C@_0EH@IJFFLBHG@unknown?5field?5type?5in?5packet?5?8?$CFs@ (0000)
|
|
0027D9C8 0025:
|
|
??_C@_0CF@HEIDLPDO@c?3?2halo?2SOURCE?2memory?2data_packe@ (0000)
|
|
0027D9F0 0030:
|
|
??_C@_0DA@LCBBKELK@element_count?$DO?$DN0?5?$CG?$CG?5element_coun@ (0000)
|
|
0027DA20 0028:
|
|
??_C@_0CI@PGBBKFEI@data_size?$DO?$DN0?5?$CG?$CG?5data_size?$DM?$DNfield@ (0000)
|
|
0027DA48 0049:
|
|
??_C@_0EJ@PJKAPNNJ@packet?5?8?$CFs?8?5fields?5added?5up?5to?5?$CD@ (0000)
|
|
0027DA94 0035:
|
|
??_C@_0DF@PHJLJBNP@packet_definition?9?$DOname?5?$CG?$CG?5packe@ (0000)
|
|
0027DACC 001e:
|
|
??_C@_0BO@OPEJACHI@packet_definition?9?$DOversion?$DO?$DN0?$AA@ (0000)
|
|
0027DAEC 001b:
|
|
??_C@_0BL@FEHKLID@packet_definition?9?$DOsize?$DO?$DN0?$AA@ (0000)
|
|
0027DB08 0012:
|
|
??_C@_0BC@CELFOEFM@packet_definition?$AA@ (0000)
|
|
0027DB1C 0017:
|
|
??_C@_0BH@HPAHFLDG@maximum_buffer_size?$DO?$DN0?$AA@ (0000)
|
|
0027DB34 0016:
|
|
??_C@_0BG@FEKHCMCH@buffer?5?$CG?$CG?5buffer_size?$AA@ (0000)
|
|
0027DB4C 0017:
|
|
??_C@_0BH@LODNBOPH@encoded_packet_size?$DO?$DN0?$AA@ (0000)
|
|
0027DB64 000f:
|
|
??_C@_0P@LFFMEHAO@encoded_packet?$AA@ (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries.h"
|
|
#include "memory/data_encoding.h"
|
|
#include "memory/data_packet_groups.h"
|
|
#include "memory/data_packets.h"
|
|
|
|
/* ---------- constants */
|
|
|
|
/* ---------- macros */
|
|
|
|
/* ---------- structures */
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static void _data_packet_verify(
|
|
struct data_packet_definition *packet_definition,
|
|
short *packet_size,
|
|
struct data_packet_field *fields,
|
|
short *field_count);
|
|
|
|
static void _data_packet_encode(
|
|
struct data_packet_definition *packet_definition,
|
|
struct data_encoding_state *state,
|
|
short packet_version,
|
|
void const *decoded_packet,
|
|
short *encoded_packet_size,
|
|
struct data_packet_field *fields,
|
|
short *field_count);
|
|
|
|
static void _data_packet_decode(
|
|
struct data_packet_definition *packet_definition,
|
|
struct data_encoding_state *state,
|
|
short packet_version,
|
|
void *decoded_packet,
|
|
short *encoded_packet_size,
|
|
struct data_packet_field *fields,
|
|
short *field_count);
|
|
|
|
/* ---------- globals */
|
|
|
|
/* ---------- public code */
|
|
|
|
void data_packet_verify(
|
|
struct data_packet_definition *packet_definition)
|
|
{
|
|
short packet_size;
|
|
short field_count;
|
|
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 32, packet_definition);
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 33, packet_definition->size>=0);
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 34, packet_definition->version>=0);
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 35, packet_definition->name && packet_definition->fields);
|
|
|
|
if (!packet_definition->initialized)
|
|
{
|
|
_data_packet_verify(packet_definition, &packet_size, packet_definition->fields, &field_count);
|
|
if (packet_size != packet_definition->size)
|
|
{
|
|
display_assert(
|
|
csprintf(
|
|
temporary,
|
|
"packet '%s' fields added up to #%d bytes but should have been #%d bytes.",
|
|
packet_definition->name,
|
|
packet_size,
|
|
packet_definition->size),
|
|
"c:\\halo\\SOURCE\\memory\\data_packets.c",
|
|
43,
|
|
TRUE);
|
|
system_exit(-1);
|
|
}
|
|
packet_definition->initialized = TRUE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
boolean data_packet_encode(
|
|
struct data_packet_definition *packet_definition,
|
|
long packet_version,
|
|
void const *decoded_packet,
|
|
void *buffer,
|
|
short *buffer_size,
|
|
short maximum_buffer_size)
|
|
{
|
|
struct data_encoding_state state;
|
|
short version;
|
|
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 61, packet_definition);
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 62, buffer && buffer_size);
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 63, maximum_buffer_size>=0);
|
|
|
|
data_packet_verify(packet_definition);
|
|
data_encode_new(&state, buffer, maximum_buffer_size);
|
|
version = (short)packet_version;
|
|
if (version == NONE)
|
|
version = packet_definition->version;
|
|
if (packet_definition->version > 0)
|
|
{
|
|
byte version_byte = (byte)version;
|
|
data_encode_memory(&state, &version_byte, 1, 1);
|
|
}
|
|
_data_packet_encode(
|
|
packet_definition,
|
|
&state,
|
|
version,
|
|
decoded_packet,
|
|
NULL,
|
|
packet_definition->fields,
|
|
NULL);
|
|
*buffer_size = (short)state.offset;
|
|
|
|
return !state.overflow;
|
|
}
|
|
|
|
boolean data_packet_decode(
|
|
struct data_packet_definition *packet_definition,
|
|
void const *encoded_packet,
|
|
short encoded_packet_size,
|
|
void *decoded_packet,
|
|
short *packet_version,
|
|
short *decoded_packet_size)
|
|
{
|
|
struct data_encoding_state state;
|
|
short version;
|
|
boolean result;
|
|
|
|
result = FALSE;
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 95, encoded_packet);
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 96, decoded_packet);
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 97, encoded_packet_size>=0);
|
|
|
|
data_packet_verify(packet_definition);
|
|
data_decode_new(&state, encoded_packet, encoded_packet_size);
|
|
if (packet_definition->version == 0)
|
|
version = 0;
|
|
else
|
|
version = data_decode_byte(&state);
|
|
if (version <= packet_definition->version)
|
|
{
|
|
_data_packet_decode(
|
|
packet_definition,
|
|
&state,
|
|
version,
|
|
decoded_packet,
|
|
NULL,
|
|
packet_definition->fields,
|
|
NULL);
|
|
if (!state.overflow)
|
|
result = TRUE;
|
|
}
|
|
if (packet_version)
|
|
*packet_version = version;
|
|
if (decoded_packet_size)
|
|
*decoded_packet_size = (short)state.offset;
|
|
|
|
return result;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
static void _data_packet_verify(
|
|
struct data_packet_definition *packet_definition,
|
|
short *packet_size,
|
|
struct data_packet_field *fields,
|
|
short *field_count)
|
|
{
|
|
short field_size;
|
|
short total_size;
|
|
struct data_packet_field *field;
|
|
|
|
field = fields;
|
|
total_size = 0;
|
|
/* BUG (original): a first version-ineligible field reads an indeterminate
|
|
* field_size; later ineligible fields reuse the preceding size. A corrected
|
|
* build should initialize field_size to zero before the loop. */
|
|
while (field->type != _data_packet_field_end)
|
|
{
|
|
if (field->type < 0 || field->type >= _data_packet_field_type_count)
|
|
{
|
|
display_assert(
|
|
csprintf(
|
|
temporary,
|
|
"unknown field type in packet '%s' (probably missing '__pack_pack_end')",
|
|
packet_definition->name),
|
|
"c:\\halo\\SOURCE\\memory\\data_packets.c",
|
|
142,
|
|
TRUE);
|
|
system_exit(-1);
|
|
}
|
|
if (field->count <= 0)
|
|
{
|
|
display_assert(
|
|
csprintf(
|
|
temporary,
|
|
"field has negative or zero count in packet '%s'",
|
|
packet_definition->name),
|
|
"c:\\halo\\SOURCE\\memory\\data_packets.c",
|
|
144,
|
|
TRUE);
|
|
system_exit(-1);
|
|
}
|
|
|
|
if (packet_definition->version >= field->minimum_version &&
|
|
(packet_definition->version <= field->maximum_version || field->maximum_version == 0))
|
|
{
|
|
switch (field->type)
|
|
{
|
|
case _data_packet_field_pad:
|
|
case _data_packet_field_bytes:
|
|
case _data_packet_field_raw:
|
|
field_size = field->count;
|
|
break;
|
|
case _data_packet_field_shorts:
|
|
field_size = field->count * sizeof(short);
|
|
break;
|
|
case _data_packet_field_longs:
|
|
field_size = field->count * sizeof(long);
|
|
break;
|
|
case _data_packet_field_int64s:
|
|
field_size = field->count * sizeof(__int64);
|
|
break;
|
|
case _data_packet_field_string:
|
|
field_size = field->count + 1;
|
|
break;
|
|
case _data_packet_field_data:
|
|
field_size = field->count + sizeof(short);
|
|
break;
|
|
case _data_packet_field_array:
|
|
{
|
|
short element_size;
|
|
short element_field_count;
|
|
|
|
_data_packet_verify(packet_definition, &element_size, field + 1, &element_field_count);
|
|
field_size = sizeof(short) + field->count * element_size;
|
|
field += element_field_count;
|
|
break;
|
|
}
|
|
case _data_packet_field_end:
|
|
field_size = 0;
|
|
break;
|
|
default:
|
|
display_assert(NULL, "c:\\halo\\SOURCE\\memory\\data_packets.c", 193, TRUE);
|
|
system_exit(-1);
|
|
break;
|
|
}
|
|
}
|
|
field->size = field_size;
|
|
total_size += field_size;
|
|
field++;
|
|
}
|
|
if (field_count)
|
|
*field_count = (short)(field - fields + 1);
|
|
if (packet_size)
|
|
*packet_size = total_size;
|
|
|
|
return;
|
|
}
|
|
|
|
static void _data_packet_encode(
|
|
struct data_packet_definition *packet_definition,
|
|
struct data_encoding_state *state,
|
|
short packet_version,
|
|
void const *decoded_packet,
|
|
short *encoded_packet_size,
|
|
struct data_packet_field *fields,
|
|
short *field_count)
|
|
{
|
|
struct data_packet_field *field;
|
|
byte const *decoded_data;
|
|
byte const *decoded_start;
|
|
|
|
field = fields;
|
|
decoded_data = decoded_packet;
|
|
decoded_start = decoded_data;
|
|
while (field->type != _data_packet_field_end)
|
|
{
|
|
if (packet_version >= field->minimum_version &&
|
|
(packet_version <= field->maximum_version || field->maximum_version == 0))
|
|
{
|
|
switch (field->type)
|
|
{
|
|
case _data_packet_field_pad:
|
|
break;
|
|
case _data_packet_field_bytes:
|
|
data_encode_memory(state, decoded_data, field->count, 1);
|
|
break;
|
|
case _data_packet_field_shorts:
|
|
data_encode_memory(state, decoded_data, field->count, -2);
|
|
break;
|
|
case _data_packet_field_longs:
|
|
data_encode_memory(state, decoded_data, field->count, -4);
|
|
break;
|
|
case _data_packet_field_int64s:
|
|
data_encode_memory(state, decoded_data, field->count, -8);
|
|
break;
|
|
case _data_packet_field_string:
|
|
data_encode_string(state, (char const *)decoded_data, field->count);
|
|
break;
|
|
case _data_packet_field_data:
|
|
{
|
|
short data_size = *(short const *)decoded_data;
|
|
byte const *data = decoded_data + sizeof(short);
|
|
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 253, data_size>=0 && data_size<=field->count);
|
|
/* (a bad size fails the packet: port) */
|
|
if (data_size < 0 || data_size > field->count)
|
|
{
|
|
state->overflow = TRUE;
|
|
data_size = 0;
|
|
}
|
|
data_encode_integer(state, data_size, field->count);
|
|
data_encode_memory(state, data, data_size, 1);
|
|
break;
|
|
}
|
|
case _data_packet_field_raw:
|
|
data_encode_memory(state, decoded_data, field->count, 1);
|
|
break;
|
|
case _data_packet_field_array:
|
|
{
|
|
short element_count = *(short const *)decoded_data;
|
|
short element_field_count;
|
|
byte const *element = decoded_data + sizeof(short);
|
|
|
|
_data_packet_verify(
|
|
packet_definition,
|
|
NULL,
|
|
field + 1,
|
|
&element_field_count);
|
|
match_assert("c:\\halo\\SOURCE\\memory\\data_packets.c", 281, element_count>=0 && element_count<=field->count);
|
|
/* (a bad count fails the packet: port) */
|
|
if (element_count < 0 || element_count > field->count)
|
|
{
|
|
state->overflow = TRUE;
|
|
element_count = 0;
|
|
}
|
|
data_encode_integer(state, element_count, field->count);
|
|
while (element_count-- > 0)
|
|
{
|
|
short element_size;
|
|
|
|
_data_packet_encode(
|
|
packet_definition,
|
|
state,
|
|
packet_version,
|
|
element,
|
|
&element_size,
|
|
field + 1,
|
|
NULL);
|
|
element += element_size;
|
|
}
|
|
field += element_field_count;
|
|
break;
|
|
}
|
|
default:
|
|
display_assert(NULL, "c:\\halo\\SOURCE\\memory\\data_packets.c", 297, TRUE);
|
|
system_exit(-1);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (field->type)
|
|
{
|
|
case _data_packet_field_pad:
|
|
break;
|
|
case _data_packet_field_bytes:
|
|
case _data_packet_field_shorts:
|
|
case _data_packet_field_longs:
|
|
case _data_packet_field_int64s:
|
|
case _data_packet_field_raw:
|
|
data_encode_memory(state, NULL, field->count, 1);
|
|
break;
|
|
case _data_packet_field_string:
|
|
{
|
|
byte zero;
|
|
|
|
zero = 0;
|
|
data_encode_memory(state, &zero, 1, 1);
|
|
break;
|
|
}
|
|
case _data_packet_field_data:
|
|
case _data_packet_field_array:
|
|
data_encode_integer(state, 0, field->count);
|
|
break;
|
|
default:
|
|
display_assert(NULL, "c:\\halo\\SOURCE\\memory\\data_packets.c", 324, TRUE);
|
|
system_exit(-1);
|
|
break;
|
|
}
|
|
}
|
|
decoded_data += field->size;
|
|
field++;
|
|
}
|
|
if (field_count)
|
|
*field_count = (short)(field - fields + 1);
|
|
if (encoded_packet_size)
|
|
*encoded_packet_size = (short)(decoded_data - decoded_start);
|
|
|
|
return;
|
|
}
|
|
|
|
static void _data_packet_decode(
|
|
struct data_packet_definition *packet_definition,
|
|
struct data_encoding_state *state,
|
|
short packet_version,
|
|
void *decoded_packet,
|
|
short *encoded_packet_size,
|
|
struct data_packet_field *fields,
|
|
short *field_count)
|
|
{
|
|
struct data_packet_field *field;
|
|
byte *decoded_data;
|
|
byte *decoded_start;
|
|
|
|
field = fields;
|
|
decoded_data = decoded_packet;
|
|
decoded_start = decoded_data;
|
|
while (field->type != _data_packet_field_end)
|
|
{
|
|
if (packet_version >= field->minimum_version &&
|
|
(packet_version <= field->maximum_version || field->maximum_version == 0))
|
|
{
|
|
switch (field->type)
|
|
{
|
|
case _data_packet_field_bytes:
|
|
{
|
|
void *source = data_decode_memory(state, field->count, 1);
|
|
if (source)
|
|
csmemcpy(decoded_data, source, field->count);
|
|
break;
|
|
}
|
|
case _data_packet_field_shorts:
|
|
{
|
|
void *source = data_decode_memory(state, field->count, -2);
|
|
if (source)
|
|
csmemcpy(decoded_data, source, field->count * sizeof(short));
|
|
break;
|
|
}
|
|
case _data_packet_field_longs:
|
|
{
|
|
void *source = data_decode_memory(state, field->count, -4);
|
|
if (source)
|
|
csmemcpy(decoded_data, source, field->count * sizeof(long));
|
|
break;
|
|
}
|
|
case _data_packet_field_int64s:
|
|
{
|
|
void *source = data_decode_memory(state, field->count, -8);
|
|
if (source)
|
|
csmemcpy(decoded_data, source, field->count * sizeof(__int64));
|
|
break;
|
|
}
|
|
case _data_packet_field_string:
|
|
{
|
|
char *string = data_decode_string(state, field->count);
|
|
if (string)
|
|
csstrcpy((char *)decoded_data, string);
|
|
break;
|
|
}
|
|
case _data_packet_field_data:
|
|
{
|
|
short data_size;
|
|
void *source;
|
|
|
|
data_size = (short)data_decode_integer(state, field->count);
|
|
/* port: no more than the field holds (the rest of the packet is
|
|
not to be read then) */
|
|
if (data_size < 0 || data_size > field->count)
|
|
{
|
|
state->overflow = TRUE;
|
|
data_size = 0;
|
|
}
|
|
*(short *)decoded_data = data_size;
|
|
source = data_decode_memory(state, data_size, 1);
|
|
if (source)
|
|
csmemcpy(decoded_data + sizeof(short), source, data_size);
|
|
break;
|
|
}
|
|
case _data_packet_field_raw:
|
|
{
|
|
void *source = data_decode_memory(state, field->count, 1);
|
|
if (source)
|
|
csmemcpy(decoded_data, source, field->count);
|
|
break;
|
|
}
|
|
case _data_packet_field_array:
|
|
{
|
|
short element_count;
|
|
short element_size;
|
|
short element_field_count;
|
|
byte *element;
|
|
|
|
element_count = (short)data_decode_integer(state, field->count);
|
|
_data_packet_verify(packet_definition, NULL, field + 1, &element_field_count);
|
|
/* port: no more than the field holds (the rest of the packet is
|
|
not to be read then) */
|
|
if (element_count < 0 || element_count > field->count)
|
|
{
|
|
state->overflow = TRUE;
|
|
element_count = 0;
|
|
}
|
|
*(short *)decoded_data = element_count;
|
|
element = decoded_data + sizeof(short);
|
|
while (element_count-- > 0)
|
|
{
|
|
_data_packet_decode(
|
|
packet_definition,
|
|
state,
|
|
packet_version,
|
|
element,
|
|
&element_size,
|
|
field + 1,
|
|
NULL);
|
|
element += element_size;
|
|
}
|
|
field += element_field_count;
|
|
break;
|
|
}
|
|
case _data_packet_field_pad:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
csmemset(decoded_data, 0, field->size);
|
|
decoded_data += field->size;
|
|
field++;
|
|
}
|
|
if (field_count)
|
|
*field_count = (short)(field - fields + 1);
|
|
if (encoded_packet_size)
|
|
*encoded_packet_size = (short)(decoded_data - decoded_start);
|
|
|
|
return;
|
|
}
|