#ifndef CODUO_ENGINE_STRUCTS_H
#define CODUO_ENGINE_STRUCTS_H

/*
 * Host-side structure map for coduo_lnxded.
 *
 * Treat offsets and sizes as confirmed only when the local comments name
 * binary evidence such as objdump/Ghidra addresses, runtime probes, or ABI
 * call sites. Opaque reserved byte spans intentionally preserve proven record
 * size while leaving unproven fields unnamed.
 */

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "coduo_engine_abi.h"
#include "huffman.h"
#include "q_shared_types.h"

#ifdef __cplusplus
#define _Static_assert static_assert
#endif

#define CODUO_HUNK_TEMP_MAGIC UINT32_C(0x89537892)
#define CODUO_HUNK_FREED_MAGIC UINT32_C(0x89537893)

#ifdef __cplusplus
extern "C" {
#endif

typedef struct coduo_patch_collide_s coduo_patch_collide_t;
typedef struct patchCollide_s patchCollide_t;
struct cmd_function_s;
struct coduo_hunk_log_block_s;
struct worldSector_s;
struct worldSectorAreaLink_s;
struct svEntity_s;
struct dshader_s;
struct searchpath_s;
typedef struct archivedSnapshotFrameIndex_s archivedSnapshotFrameIndex_t;
typedef struct fileData_s fileData_t;
typedef struct XModel_s XModel;
typedef struct XModelInfo_s XModelInfo;
typedef struct XModelSurfs_s XModelSurfs;
typedef struct XModelSurfsData_s XModelSurfsData;
typedef struct XModelPartsData_s XModelPartsData;
typedef void (*fileDataFree_t)(fileData_t *fileData);
struct coduo_script_yy_buffer_s;
union sval_u;
typedef void (*coduo_cmd_function_fn)(void);
typedef struct coduo_vm_s coduo_vm_t;
typedef struct coduo_engine_name_value_s coduo_engine_name_value_t;
typedef struct snd_alias_sound_file_s snd_alias_sound_file_t;
enum {
    CODUO_CLIENT_DELTA_MESSAGE_NONE = -1
};
typedef void *coduo_pb_server_opaque_slot_t;
/* Quake III l_script/l_precomp names for the inherited private parser graph.
 * CoD's Linux layouts below retain those roles while using 0x40-byte path
 * fields and twelve-byte x87 storage in token_t. */
typedef struct token_s token_t;
typedef struct define_s define_t;
typedef struct script_s script_t;
typedef struct indent_s indent_t;
typedef struct punctuation_s punctuation_t;
typedef struct orientation_s {
    vec3_t origin;
    vec3_t axis[3];
} orientation_t;
_Static_assert(sizeof(vec2_t) == 2 * sizeof(float), "vec2_t size mismatch");
_Static_assert(sizeof(vec3_t) == 3 * sizeof(float), "vec3_t size mismatch");
_Static_assert(sizeof(vec4_t) == 4 * sizeof(float), "vec4_t size mismatch");
_Static_assert(sizeof(vec3_t[3]) == 9 * sizeof(float),
               "vec3_t[3] matrix size mismatch");
_Static_assert(sizeof(orientation_t) == 12 * sizeof(float),
               "orientation_t size mismatch");
_Static_assert(offsetof(orientation_t, origin) == 0,
               "orientation_t.origin offset mismatch");
_Static_assert(offsetof(orientation_t, axis) == 3 * sizeof(float),
               "orientation_t.axis offset mismatch");
typedef struct DObjSkelMat_s {
    float axis[3][4];
    float origin[4];
} DObjSkelMat;
typedef struct coduo_compact_affine_matrix43_s {
    vec3_t axis[3];
    vec3_t origin;
} coduo_compact_affine_matrix43_t;
typedef XModel *coduo_xanim_eval_child_ref_t;
typedef struct coduo_xanim_eval_storage_s coduo_xanim_eval_storage_t;
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(char *) == 4,
               "char * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_engine_name_value_t *) ==
                   4,
               "coduo_engine_name_value_t * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(struct coduo_hunk_log_block_s *) ==
                   4,
               "struct coduo_hunk_log_block_s * size mismatch");
_Static_assert(sizeof(void *) == 4,
               "void * size mismatch");
_Static_assert(sizeof(const char *) == 4,
               "const char * size mismatch");
_Static_assert(sizeof(uint8_t *) == 4,
               "uint8_t * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(struct svEntity_s *) ==
                   4,
               "struct svEntity_s * size mismatch");
_Static_assert(sizeof(struct worldSectorAreaLink_s *) ==
                   4,
               "struct worldSectorAreaLink_s * size mismatch");
_Static_assert(sizeof(struct worldSector_s *) ==
                   4,
               "struct worldSector_s * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(struct worldSector_s *) ==
                   4,
               "struct worldSector_s * size mismatch");
_Static_assert(sizeof(struct svEntity_s *) ==
                   4,
               "struct svEntity_s * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(struct dshader_s *) ==
                   4,
               "struct dshader_s * size mismatch");
#endif
_Static_assert(sizeof(struct client_s *) ==
                   sizeof(struct client_s *),
               "struct client_s * size mismatch");
_Static_assert(sizeof(struct coduo_host_snapshot_entity_record_s *) ==
                   sizeof(struct coduo_host_snapshot_entity_record_s *),
               "struct coduo_host_snapshot_entity_record_s * size mismatch");
_Static_assert(sizeof(struct coduo_host_client_snapshot_s *) ==
                   sizeof(struct coduo_host_client_snapshot_s *),
               "struct coduo_host_client_snapshot_s * size mismatch");
_Static_assert(sizeof(archivedSnapshotFrameIndex_t *) ==
                   sizeof(archivedSnapshotFrameIndex_t *),
               "archivedSnapshotFrameIndex_t * size mismatch");
_Static_assert(sizeof(uint8_t *) == sizeof(uint8_t *),
               "uint8_t * size mismatch");
_Static_assert(sizeof(struct coduo_host_snapshot_entity_s *) ==
                   sizeof(struct coduo_host_snapshot_entity_s *),
               "struct coduo_host_snapshot_entity_s * size mismatch");
_Static_assert(sizeof(struct serverCachedSnapshotClient_s *) ==
                   sizeof(struct serverCachedSnapshotClient_s *),
               "struct serverCachedSnapshotClient_s * size mismatch");
_Static_assert(sizeof(struct serverCachedSnapshotFrame_s *) ==
                   sizeof(struct serverCachedSnapshotFrame_s *),
               "struct serverCachedSnapshotFrame_s * size mismatch");
_Static_assert(sizeof(qboolean) ==
                   sizeof(int32_t),
               "qboolean size mismatch");
_Static_assert(sizeof(qboolean) == sizeof(int32_t),
               "qboolean size mismatch");
_Static_assert(sizeof(coduo_pb_server_opaque_slot_t) == sizeof(void *),
               "coduo_pb_server_opaque_slot_t size mismatch");
_Static_assert(sizeof(const char *) == sizeof(void *),
               "const char * size mismatch");
_Static_assert(sizeof(uint32_t) ==
                   4,
               "uint32_t size mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(punctuation_t *) ==
                   4,
               "punctuation_t * size mismatch");
_Static_assert(sizeof(punctuation_t **) ==
                   4,
               "punctuation_t ** size mismatch");
_Static_assert(sizeof(script_t *) == 4,
               "script_t * size mismatch");
_Static_assert(sizeof(define_t **) ==
                   4,
               "define_t ** size mismatch");
_Static_assert(sizeof(indent_t *) == 4,
               "indent_t * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(char *) ==
                   4,
               "char * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(token_t *) == 4,
               "token_t * size mismatch");
_Static_assert(sizeof(char *) == 4,
               "char * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(define_t *) == 4,
               "define_t * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(scr_anim_t) == sizeof(uint32_t),
               "original i386 scr_anim_t size changed");
_Static_assert(offsetof(scr_anim_t, animIndex) == 0,
               "original i386 scr_anim_t.animIndex moved");
_Static_assert(offsetof(scr_anim_t, treeIndex) == 2,
               "original i386 scr_anim_t.treeIndex moved");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(struct coduo_script_yy_buffer_s *) ==
                   4,
               "struct coduo_script_yy_buffer_s * size mismatch");
_Static_assert(sizeof(FILE *) == 4,
               "FILE * size mismatch");
_Static_assert(sizeof(char *) == 4,
               "char * size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(union sval_u *) ==
                   4,
               "union sval_u * size mismatch");
_Static_assert(sizeof(int32_t *) ==
                   4,
               "int32_t * size mismatch");
#endif
_Static_assert(sizeof(DObjSkelMat) == 0x40,
               "DObjSkelMat size mismatch");
_Static_assert(offsetof(DObjSkelMat, origin) == 0x30,
               "DObjSkelMat.origin offset mismatch");
_Static_assert(sizeof(coduo_compact_affine_matrix43_t) == 0x30,
               "coduo_compact_affine_matrix43_t size mismatch");
_Static_assert(offsetof(coduo_compact_affine_matrix43_t, origin) == 0x24,
               "coduo_compact_affine_matrix43_t.origin offset mismatch");
_Static_assert(sizeof(qboolean) ==
                   sizeof(int32_t),
               "qboolean size mismatch");

/* Keep a named size or count in this shared inventory only when more than one
 * declaration/runtime operation needs the same domain. Pointer-bearing record
 * extents are asserted directly against original-image literals; native
 * allocation, traversal, and copying use the owning type's sizeof. */
enum {
    CODUO_MAX_QPATH = 64,
    CODUO_MAX_GENTITIES = 1024,
    CODUO_MAX_CLIENTS = 64,
    CODUO_MAX_CONFIGSTRINGS = 2048,
    CODUO_MAX_RELIABLE_COMMANDS = 64,
    CODUO_MAX_PACKET_USERCMDS = 32,
    CODUO_MAX_STRING_CHARS = 1024,
    CODUO_BIG_INFO_STRING = 0x2000,
    CODUO_MAX_INFO_STRING = 1024,
    CODUO_MAX_NAME_LENGTH = 32,
    CODUO_SNAPSHOT_ENTITY_NUMBER_LIST_COUNT = CODUO_MAX_GENTITIES,
    CODUO_COM_MAX_ARGS = 32,
    CODUO_MSG_BITMASK_TABLE_COUNT = 33,
    CODUO_OBJECTIVE_NET_FIELD_COUNT = 6,
    CODUO_HUD_ELEM_NET_FIELD_COUNT = 30,
    CODUO_MD4_STATE_WORD_COUNT = 4,
    CODUO_MD4_COUNT_WORD_COUNT = 2,
    CODUO_MD4_BLOCK_SIZE = 64,
    CODUO_MD4_DIGEST_SIZE = 16,
    CODUO_MD4_PADDING_SIZE = 64,
    CODUO_MD5_STATE_WORD_COUNT = 4,
    CODUO_MD5_COUNT_WORD_COUNT = 2,
    CODUO_MD5_BLOCK_SIZE = 64,
    CODUO_MD5_DIGEST_SIZE = 16,
    CODUO_MD5_PADDING_SIZE = 64,
    CODUO_COM_PARSE_TOKEN_SIZE = 0x400,
    CODUO_COM_PARSE_STATE_COUNT = 16,
    CODUO_COM_PARSE_FILE_NAME_SIZE = 0x40,
    CODUO_COM_PARSE_OPERATOR_STRING_COUNT = 14,
    CODUO_PC_SOURCE_HANDLE_COUNT = 64,
    CODUO_PC_SOURCE_INCLUDE_PATH_SIZE = 0x40,
    CODUO_PC_DEFAULT_PUNCTUATION_COUNT = 53,
    CODUO_PC_PUNCTUATION_BUCKET_COUNT = 256,
    CODUO_PC_TOKEN_STRING_SIZE = 0x400,
    /* Original x87 long-double payload width shared by token storage and the
     * parser's byte-copy/conversion paths; this is not host sizeof(double). */
    CODUO_PC_TOKEN_FLOAT_VALUE_SIZE = 0x0c,
    CODUO_PC_SCRIPT_FILENAME_SIZE = 0x40,
    CODUO_PC_DEFINE_HASH_BUCKET_COUNT = 1024,
    CODUO_PC_DEFINE_HASH_TABLE_SIZE =
        CODUO_PC_DEFINE_HASH_BUCKET_COUNT *
            sizeof(define_t *),
    CODUO_CMD_MAX_ARGS = 512,
    CODUO_CMD_TOKEN_BUFFER_SIZE = 8704,
    CODUO_COM_ERROR_MESSAGE_SIZE = 4096,
    CODUO_COM_VA_SCRATCH_SIZE = 32000,
    CODUO_COM_VA_RETURN_RING_SIZE = 32000,
    CODUO_SYS_EVENT_QUEUE_COUNT = 256,
    CODUO_INFO_VALUE_BUFFER_COUNT = 2,
    CODUO_INFO_VALUE_BUFFER_SIZE = CODUO_BIG_INFO_STRING,
    CODUO_PACKET_BACKUP = 32,
    CODUO_MAX_MAP_AREA_BYTES = 32,
    /* CoD:UO message buffers are 32,768 bytes in Com_EventLoop, netchan,
       and server send/parse paths. */
    CODUO_MAX_MSGLEN = 32768,
    CODUO_NET_PROFILE_SAMPLE_COUNT = 60,
    CODUO_NET_PROFILE_SOCKET_NAME_COUNT = 2,
    CODUO_SOUND_ALIAS_LOCALE_COUNT = 3,
    CODUO_SOUND_ALIAS_HASH_BUCKET_COUNT = 256,
    CODUO_SOUND_ALIAS_TABLE_POINTER_COUNT = CODUO_SOUND_ALIAS_LOCALE_COUNT,
    CODUO_SOUND_ALIAS_LOADED_FLAG_SLOT_COUNT = 4,
    CODUO_SOUND_ALIAS_CHANNEL_NAME_COUNT = 10,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_SLOT_COUNT = 19,
    CODUO_NET_LOOPBACK_PACKET_COUNT = 16,
    CODUO_NET_LOOPBACK_PACKET_BYTES = 1400,
    CODUO_NET_LOOPBACK_SOCKET_COUNT = 2,
    CODUO_MAX_DOWNLOAD_WINDOW = 8,
    CODUO_MAX_CHALLENGES = 1024,
    CODUO_PUNKBUSTER_SERVER_QUERY_COPY_LIMIT = 255,
    CODUO_PUNKBUSTER_SERVER_MAGIC = 0x357afe19,
    CODUO_PUNKBUSTER_SERVER_TITLE_SIZE = 0x020,
    CODUO_PUNKBUSTER_SERVER_BASE_PATH_SIZE = 0x104,
    CODUO_SCRIPT_VARIABLE_NODE_COUNT = 65536,
    CODUO_SCRIPT_VARIABLE_NODE_TYPE_MASK = 0x1f,
    CODUO_SCRIPT_VARIABLE_NODE_PACKED_INDEX_SHIFT = 8,
    CODUO_SCRIPT_VARIABLE_TYPE_COUNT = 19,
    CODUO_SCRIPT_ANIM_PROPERTY_NAME_COUNT = 3,
    CODUO_SCRIPT_ANIM_SLOT_COUNT = 2,
    CODUO_SCRIPT_ANIM_TREE_SLOT_COUNT = 128,
    CODUO_SCRIPT_VALUE_STACK_COUNT = 2048,
    CODUO_SCRIPT_CALL_STACK_COUNT = 32,
    CODUO_SCRIPT_YYSTACK_COUNT = 500,
    CODUO_SCRIPT_YY_RULE_STORAGE_COUNT = 128,
    CODUO_SCRIPT_YY_STATE_TABLE_COUNT = 256,
    CODUO_SCRIPT_YY_NONTERM_TABLE_COUNT = 32,
    CODUO_SCRIPT_YYTABLE_INDEX_MAX = 0x5f1,
    CODUO_SCRIPT_YYTABLE_STORAGE_COUNT = 1536,
    CODUO_SCRIPT_YY_ACTION_INDEX_MAX = 0x7c,
    CODUO_SCRIPT_YY_ACTION_COUNT = CODUO_SCRIPT_YY_ACTION_INDEX_MAX + 1,
    /* These capacities drive both the declared storage and runtime traversal
     * or copy bounds; keep one name for each proven fixed domain. */
    CODUO_SCRIPT_OBJECT_ID_MAP_COUNT = 65536,
    CODUO_XANIM_POOL_NODE_COUNT = 2048,
    CODUO_XANIM_TREE_TAIL_WORDS_PER_NODE = 3,
    CODUO_XMODEL_COLLISION_LOD_RECORD_COUNT = 3,
    CODUO_XMODEL_COLLISION_PROVEN_PREFIX_END = 0x68,
    CODUO_XMODEL_COLLISION_FACET_PLANE_COUNT = 3,
    CODUO_XMODEL_SURFACE_BONE_USAGE_BYTES = 16,
    CODUO_XSURFACE_TRIANGLE_INDEX_COUNT = 3,
    CODUO_XMODEL_TEST_LOD_DISTANCE_COUNT = 3,
    CODUO_XANIM_PART_BITSET_WORD_COUNT = 4,
    CODUO_XANIM_PART_BITSET_SIZE =
        CODUO_XANIM_PART_BITSET_WORD_COUNT *
        sizeof(uint32_t),
    CODUO_XANIM_PART_BITSET_MAX_BITS =
        CODUO_XANIM_PART_BITSET_WORD_COUNT * 32,
    /* The remap payload is a byte format: its first 16 bytes are the part
     * bitset and the variable remap bytes begin immediately afterward. */
    CODUO_XANIM_PART_REMAP_BYTES_OFFSET = CODUO_XANIM_PART_BITSET_SIZE,
    CODUO_XANIM_PART_REMAP_PREFIX_SIZE = CODUO_XANIM_PART_REMAP_BYTES_OFFSET,
    CODUO_XANIM_PART_REMAP_SENTINEL = 0x7f,
    CODUO_XANIM_EVAL_LEAF_OUTPUT_DUAL_SAMPLE = 0,
    CODUO_XANIM_EVAL_LEAF_OUTPUT_SINGLE_SAMPLE = 1,
    CODUO_XANIM_EVAL_POOL_WEIGHT_CURRENT = 0,
    CODUO_XANIM_EVAL_POOL_WEIGHT_TARGET = 1,
    CODUO_DOBJ_POOL_COUNT = 1024,
    CODUO_DOBJ_SLOT_INDEX_NULL = 0,
    CODUO_DOBJ_CHILD_SLOT_COUNT = 8,
    CODUO_DOBJ_CHILD_PARENT_PART_INDEX_NONE = 0xff,
    CODUO_DOBJ_PART_INDEX_NOT_FOUND = -1,
    CODUO_DOBJ_PART_INDEX_MAX = 0x7f,
    CODUO_DOBJ_OCCUPANCY_RECORDS_PER_BYTE = 4,
    CODUO_DOBJ_OCCUPANCY_BITS_PER_RECORD = 2,
    CODUO_DOBJ_OCCUPANCY_BYTE_COUNT =
        CODUO_DOBJ_POOL_COUNT / CODUO_DOBJ_OCCUPANCY_RECORDS_PER_BYTE,
    CODUO_DOBJ_PRIMARY_LOOKUP_COUNT = 1152,
    CODUO_DOBJ_SECONDARY_LOOKUP_COUNT = 1024,
    CODUO_DOBJ_LAST_SEARCH_SLOT_INITIAL_VALUE = 1,
    CODUO_MAX_MASTER_SERVERS = 5,
    CODUO_MAX_ENT_CLUSTERS = 16,
    CODUO_WORLD_SECTOR_CHILD_COUNT = 2,
    CODUO_WORLD_SECTOR_POOL_COUNT = 1024,
    CODUO_HUNK_ALIGNMENT = 32
};

typedef enum coduo_vm_interpret_e {
    CODUO_VMI_NATIVE = 0,
    CODUO_VMI_BYTECODE = 1,
    CODUO_VMI_COMPILED = 2
} coduo_vm_interpret_t;

typedef enum coduo_server_state_e {
    CODUO_SS_DEAD = 0,
    CODUO_SS_LOADING = 1,
    CODUO_SS_GAME = 2
} coduo_server_state_t;

typedef enum coduo_client_state_e {
    CODUO_CS_FREE = 0,
    CODUO_CS_ZOMBIE = 1,
    CODUO_CS_CONNECTED = 2,
    CODUO_CS_PRIMED = 3,
    CODUO_CS_ACTIVE = 4
} coduo_client_state_t;

typedef enum coduo_tr_type_e {
    CODUO_TR_STATIONARY = 0,
    CODUO_TR_INTERPOLATE = 1,
    CODUO_TR_LINEAR = 2,
    CODUO_TR_LINEAR_STOP = 3,
    CODUO_TR_SINE = 4,
    CODUO_TR_GRAVITY = 5,
    CODUO_TR_GRAVITY_LOW = 6,
    CODUO_TR_GRAVITY_FLOAT = 7,
    CODUO_TR_LINKED = 8,
    CODUO_TR_ACCELERATE = 9,
    CODUO_TR_DECCELERATE = 10
} coduo_tr_type_t;

typedef enum coduo_netadr_type_e {
    CODUO_NA_BAD = 0,
    CODUO_NA_BOT = 1,
    CODUO_NA_LOOPBACK = 2,
    CODUO_NA_BROADCAST = 3,
    CODUO_NA_IP = 4,
    CODUO_NA_IPX = 5,
    CODUO_NA_BROADCAST_IPX = 6
} coduo_netadr_type_t;

typedef enum netsrc_e {
    NS_CLIENT = 0,
    NS_SERVER = 1
} netsrc_t;

typedef enum coduo_cbuf_exec_when_e {
    CODUO_EXEC_NOW = 0,
    CODUO_EXEC_INSERT = 1,
    CODUO_EXEC_APPEND = 2
} coduo_cbuf_exec_when_t;

typedef enum coduo_net_cvar_pointer_slot_e {
    CODUO_NET_CVAR_SLOT_LANAUTHORIZE = 0,
    CODUO_NET_CVAR_SLOT_PROFILE = 1,
    CODUO_NET_CVAR_SLOT_SHOWDROP = 2,
    CODUO_NET_CVAR_SLOT_SHOWPROFILE = 3,
    CODUO_NET_CVAR_SLOT_QPORT = 4,
    CODUO_NET_CVAR_SLOT_SHOWPACKETS = 5
} coduo_net_cvar_pointer_slot_t;

typedef enum coduo_net_profile_mode_e {
    CODUO_NET_PROFILE_OFF = 0,
    CODUO_NET_PROFILE_CLIENT = 1,
    CODUO_NET_PROFILE_SERVER = 2
} coduo_net_profile_mode_t;

typedef enum coduo_sound_alias_type_e {
    CODUO_SOUND_ALIAS_TYPE_UNKNOWN = 0,
    CODUO_SOUND_ALIAS_TYPE_LOADED = 1,
    CODUO_SOUND_ALIAS_TYPE_STREAMED = 2
} coduo_sound_alias_type_t;

typedef enum coduo_sound_alias_channel_e {
    CODUO_SOUND_ALIAS_CHANNEL_AUTO = 0,
    CODUO_SOUND_ALIAS_CHANNEL_MENU = 1,
    CODUO_SOUND_ALIAS_CHANNEL_WEAPON = 2,
    CODUO_SOUND_ALIAS_CHANNEL_VOICE = 3,
    CODUO_SOUND_ALIAS_CHANNEL_ITEM = 4,
    CODUO_SOUND_ALIAS_CHANNEL_BODY = 5,
    CODUO_SOUND_ALIAS_CHANNEL_LOCAL = 6,
    CODUO_SOUND_ALIAS_CHANNEL_MUSIC = 7,
    CODUO_SOUND_ALIAS_CHANNEL_ANNOUNCER = 8,
    CODUO_SOUND_ALIAS_CHANNEL_SHELLSHOCK = 9
} coduo_sound_alias_channel_t;

typedef enum coduo_sound_alias_loop_value_e {
    CODUO_SOUND_ALIAS_NONLOOPING = 0,
    CODUO_SOUND_ALIAS_LOOPING = 1
} coduo_sound_alias_loop_value_t;

typedef enum coduo_sound_alias_parse_column_e {
    CODUO_SOUND_ALIAS_PARSE_COLUMN_UNKNOWN = 0,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_NAME = 1,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_SEQUENCE = 2,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_FILE = 3,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_SUBTITLE = 4,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_VOL_MIN = 5,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_VOL_MAX = 6,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_PITCH_MIN = 7,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_PITCH_MAX = 8,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_DIST_MIN = 9,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_DIST_MAX = 10,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_CHANNEL = 11,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_TYPE = 12,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_LOOP = 13,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_PROBABILITY = 14,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_LOADSPEC = 15,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_MASTERSLAVE = 16,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_LOD_MIN = 17,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_LOD_MAX = 18,
    CODUO_SOUND_ALIAS_PARSE_COLUMN_COUNT =
        CODUO_SOUND_ALIAS_PARSE_COLUMN_SLOT_COUNT
} coduo_sound_alias_parse_column_value_t;

/*
 * Temporary sound-alias parse node used while loading CSV files.
 *
 * Evidence:
 * - Com_InitSoundAliasParseNode at VA 0x806c9c8 writes default values at the
 *   listed offsets.
 * - Com_CloneSoundAliasParseNode allocates and copies 0x1108 bytes, then links
 *   next through +0x1104.
 * - Com_BuildSoundAliasTables consumes this node to build compact
 *   coduo_sound_alias_t records and shared string storage.
 */
typedef struct coduo_sound_alias_parse_node_s {
    char sourceFile[64];
    char name[0x0040];
    char subtitle[0x1000];
    int32_t sequence;
    char file[0x0040];
    const char *compactFile;
    float volumeMin;
    float volumeMax;
    float pitchMin;
    float pitchMax;
    float distMin;
    float distMax;
    coduo_sound_alias_channel_t channel;
    coduo_sound_alias_type_t type;
    uint8_t loop;
    uint8_t isMaster;
    uint8_t isSlave;
    uint8_t padding10eb;
    float slavePercentage;
    float selectionWeight;
    int32_t loadspec;
    float selectorMin;
    float selectorMax;
    struct coduo_sound_alias_parse_node_s *duplicateFileNode;
    struct coduo_sound_alias_parse_node_s *next;
} coduo_sound_alias_parse_node_t;

/*
 * Confirmed sound-alias record prefix and lookup tables.
 *
 * Evidence:
 * - Com_FindSoundAlias at VA 0x806c93d hashes a name into a
 *   2 * 256-bucket table at VA 0x8238988, compares the name pointer at +0x00,
 *   filters through selector bounds at +0x40/+0x44, and follows hashNext +0x48.
 * - Com_PickSoundAlias at VA 0x806e6a2 walks 0x4c-byte records from the
 *   per-locale base pointer table at VA 0x8239588 and counts at VA 0x8239594;
 *   it consumes selectionWeight +0x3c and updates pickSequence +0x10.
 * - Com_SoundAliasFromIndex and Com_SoundAliasIndex convert between 1-based
 *   indices and records using the same 0x4c-byte stride.
 * - The final compact-record copier at VA 0x806d6fc writes CSV-backed file,
 *   subtitle, volume, pitch, distance, channel, type, loop, probability, and
 *   selector fields before linking hashNext into the locale hash table.
 * - The masterslave parser at VA 0x806d096 sets isMaster/isSlave and copies
 *   the numeric non-master value to slavePercentage.
 */
typedef struct coduo_sound_alias_s {
    const char *name;
    const char *file;
    const char *subtitle;
    /* Shared client record member. The dedicated engine initializes it to
     * NULL and never dereferences it because no sound backend is loaded. */
    snd_alias_sound_file_t *soundFileInfo;
    int32_t pickSequence;
    float volumeMin;
    float volumeMax;
    float pitchMin;
    float pitchMax;
    float distMin;
    float distMax;
    coduo_sound_alias_channel_t channel;
    coduo_sound_alias_type_t type;
    uint8_t loop;
    uint8_t isMaster;
    uint8_t isSlave;
    /* Shared client record member; unused by the Linux dedicated engine. */
    uint8_t streamedFileExists;
    float slavePercentage;
    float selectionWeight;
    float selectorMin;
    float selectorMax;
    struct coduo_sound_alias_s *hashNext;
} coduo_sound_alias_t;

typedef coduo_sound_alias_t *
    coduo_sound_alias_hash_table_t
        [CODUO_SOUND_ALIAS_LOCALE_COUNT]
        [CODUO_SOUND_ALIAS_HASH_BUCKET_COUNT];
typedef coduo_sound_alias_t *
    coduo_sound_alias_table_pointer_table_t
        [CODUO_SOUND_ALIAS_TABLE_POINTER_COUNT];
typedef int32_t
    coduo_sound_alias_count_table_t[CODUO_SOUND_ALIAS_LOCALE_COUNT];
typedef uint8_t
    coduo_sound_alias_loaded_flags_t
        [CODUO_SOUND_ALIAS_LOADED_FLAG_SLOT_COUNT];
typedef const char *
    coduo_sound_alias_channel_name_table_t
        [CODUO_SOUND_ALIAS_CHANNEL_NAME_COUNT];
typedef const char *
    coduo_sound_alias_parse_column_name_table_t
        [CODUO_SOUND_ALIAS_PARSE_COLUMN_SLOT_COUNT];
typedef uint8_t
    coduo_sound_alias_parse_seen_column_table_t
        [CODUO_SOUND_ALIAS_PARSE_COLUMN_SLOT_COUNT];
typedef void *
    coduo_sound_alias_parse_column_case_table_t
        [CODUO_SOUND_ALIAS_PARSE_COLUMN_SLOT_COUNT];
typedef char
    coduo_sound_alias_localized_source_name_t
        [64];
typedef char
    coduo_sound_alias_subtitle_reference_buffer_t
        [1024];
typedef int32_t
    coduo_sound_alias_checksum_table_t[CODUO_SOUND_ALIAS_LOCALE_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_sound_alias_t) == 0x4c,
               "coduo_sound_alias_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_parse_node_t) ==
                   0x1108,
               "coduo_sound_alias_parse_node_t size mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, sourceFile) ==
                   0x0000,
               "coduo_sound_alias_parse_node_t.sourceFile mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, name) ==
                   0x0040,
               "coduo_sound_alias_parse_node_t.name mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, subtitle) ==
                   0x0080,
               "coduo_sound_alias_parse_node_t.subtitle mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, sequence) ==
                   0x1080,
               "coduo_sound_alias_parse_node_t.sequence mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, file) ==
                   0x1084,
               "coduo_sound_alias_parse_node_t.file mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, compactFile) ==
                   0x10c4,
               "coduo_sound_alias_parse_node_t.compactFile mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, volumeMin) ==
                   0x10c8,
               "coduo_sound_alias_parse_node_t.volumeMin mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, volumeMax) ==
                   0x10cc,
               "coduo_sound_alias_parse_node_t.volumeMax mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, pitchMin) ==
                   0x10d0,
               "coduo_sound_alias_parse_node_t.pitchMin mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, pitchMax) ==
                   0x10d4,
               "coduo_sound_alias_parse_node_t.pitchMax mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, distMin) ==
                   0x10d8,
               "coduo_sound_alias_parse_node_t.distMin mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, distMax) ==
                   0x10dc,
               "coduo_sound_alias_parse_node_t.distMax mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, channel) ==
                   0x10e0,
               "coduo_sound_alias_parse_node_t.channel mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, type) ==
                   0x10e4,
               "coduo_sound_alias_parse_node_t.type mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, loop) ==
                   0x10e8,
               "coduo_sound_alias_parse_node_t.loop mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, isMaster) ==
                   0x10e9,
               "coduo_sound_alias_parse_node_t.isMaster mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, isSlave) ==
                   0x10ea,
               "coduo_sound_alias_parse_node_t.isSlave mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, slavePercentage) ==
                   0x10ec,
               "coduo_sound_alias_parse_node_t.slavePercentage mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, selectionWeight) ==
                   0x10f0,
               "coduo_sound_alias_parse_node_t.selectionWeight mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, loadspec) ==
                   0x10f4,
               "coduo_sound_alias_parse_node_t.loadspec mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, selectorMin) ==
                   0x10f8,
               "coduo_sound_alias_parse_node_t.selectorMin mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, selectorMax) ==
                   0x10fc,
               "coduo_sound_alias_parse_node_t.selectorMax mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, duplicateFileNode) ==
                   0x1100,
               "coduo_sound_alias_parse_node_t.duplicateFileNode mismatch");
_Static_assert(offsetof(coduo_sound_alias_parse_node_t, next) ==
                   0x1104,
               "coduo_sound_alias_parse_node_t.next mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, name) ==
                   0x00,
               "coduo_sound_alias_t.name offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, file) ==
                   0x04,
               "coduo_sound_alias_t.file offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, subtitle) ==
                   0x08,
               "coduo_sound_alias_t.subtitle offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, soundFileInfo) ==
                   0x0c,
               "coduo_sound_alias_t.soundFileInfo offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, pickSequence) ==
                   0x10,
               "coduo_sound_alias_t.pickSequence offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, volumeMin) ==
                   0x14,
               "coduo_sound_alias_t.volumeMin offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, volumeMax) ==
                   0x18,
               "coduo_sound_alias_t.volumeMax offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, pitchMin) ==
                   0x1c,
               "coduo_sound_alias_t.pitchMin offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, pitchMax) ==
                   0x20,
               "coduo_sound_alias_t.pitchMax offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, distMin) ==
                   0x24,
               "coduo_sound_alias_t.distMin offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, distMax) ==
                   0x28,
               "coduo_sound_alias_t.distMax offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, channel) ==
                   0x2c,
               "coduo_sound_alias_t.channel offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, type) ==
                   0x30,
               "coduo_sound_alias_t.type offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, loop) ==
                   0x34,
               "coduo_sound_alias_t.loop offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, isMaster) ==
                   0x35,
               "coduo_sound_alias_t.isMaster offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, isSlave) ==
                   0x36,
               "coduo_sound_alias_t.isSlave offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, streamedFileExists) ==
                   0x37,
               "coduo_sound_alias_t.streamedFileExists offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, slavePercentage) ==
                   0x38,
               "coduo_sound_alias_t.slavePercentage offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, selectionWeight) ==
                   0x3c,
               "coduo_sound_alias_t.selectionWeight offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, selectorMin) ==
                   0x40,
               "coduo_sound_alias_t.selectorMin offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, selectorMax) ==
                   0x44,
               "coduo_sound_alias_t.selectorMax offset mismatch");
_Static_assert(offsetof(coduo_sound_alias_t, hashNext) ==
                   0x48,
               "coduo_sound_alias_t.hashNext offset mismatch");
_Static_assert(sizeof(coduo_sound_alias_hash_table_t) ==
                    3 * 256 * sizeof(void *),
               "coduo_sound_alias_hash_table_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_table_pointer_table_t) ==
                    3 * sizeof(void *),
               "coduo_sound_alias_table_pointer_table_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_count_table_t) ==
                    3 * sizeof(int32_t),
               "coduo_sound_alias_count_table_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_loaded_flags_t) ==
                    4 * sizeof(uint8_t),
               "coduo_sound_alias_loaded_flags_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_channel_name_table_t) ==
                    10 * sizeof(const char *),
               "coduo_sound_alias_channel_name_table_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_parse_column_name_table_t) ==
                    19 * sizeof(const char *),
               "coduo_sound_alias_parse_column_name_table_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_parse_seen_column_table_t) ==
                    19 * sizeof(uint8_t),
               "coduo_sound_alias_parse_seen_column_table_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_parse_column_case_table_t) ==
                    19 * sizeof(void *),
               "coduo_sound_alias_parse_column_case_table_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_localized_source_name_t) ==
                   64,
               "coduo_sound_alias_localized_source_name_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_subtitle_reference_buffer_t) ==
                   1024,
               "coduo_sound_alias_subtitle_reference_buffer_t size mismatch");
_Static_assert(sizeof(coduo_sound_alias_checksum_table_t) ==
                    3 * sizeof(int32_t),
               "coduo_sound_alias_checksum_table_t size mismatch");
#endif

/*
 * Confirmed filesystem open modes accepted by FS_FOpenFileByMode.
 *
 * Evidence:
 * - FS_FOpenFileByMode at VA 0x8065d85 switches on mode values 0..3.
 * - Mode 3 sets the per-handle sync flag and then follows the append path.
 */
typedef enum coduo_fs_mode_e {
    CODUO_FS_READ = 0,
    CODUO_FS_WRITE = 1,
    CODUO_FS_APPEND = 2,
    CODUO_FS_APPEND_SYNC = 3
} coduo_fs_mode_t;

/*
 * Confirmed module-facing vmCvar_t layout copied by the engine.
 *
 * Evidence:
 * - Cvar_Register at VA 0x80738d4 writes handle +0x00 and initializes
 *   modificationCount +0x04 to -1, then calls Cvar_Update.
 * - Cvar_Update at VA 0x807392b copies the host cvar string to +0x10 with
 *   a 0x100-byte bound, writes value +0x08, and writes integer +0x0c.
 */
typedef struct vmCvar_s {
    int32_t handle;
    int32_t modificationCount;
    float value;
    int32_t integer;
    char string[256];
} vmCvar_t;

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(vmCvar_t) == 0x110,
               "vmCvar_t size mismatch");
_Static_assert(offsetof(vmCvar_t, handle) ==
                   0x00,
               "vmCvar_t.handle offset mismatch");
_Static_assert(offsetof(vmCvar_t, modificationCount) ==
                   0x04,
               "vmCvar_t.modificationCount offset mismatch");
_Static_assert(offsetof(vmCvar_t, value) == 0x08,
               "vmCvar_t.value offset mismatch");
_Static_assert(offsetof(vmCvar_t, integer) ==
                   0x0c,
               "vmCvar_t.integer offset mismatch");
_Static_assert(offsetof(vmCvar_t, string) ==
                   0x10,
               "vmCvar_t.string offset mismatch");
_Static_assert(sizeof(((vmCvar_t *)0)->string) ==
                   0x100,
               "vmCvar_t.string size mismatch");
#endif

/*
 * Confirmed cvar layout.
 *
 * Evidence:
 * - Cvar_Get at VA 0x8073114 allocates from a static array at VA 0x8253540
 *   using a 0x2c-byte stride.
 * - Cvar_FindVar walks the hash table at VA 0x8269540 through hashNext +0x28.
 * - Sorted traversal/insertion walks through next +0x24.
 * - The value/integer prefix is stable across Cvar_Get, Cvar_Set2,
 *   Cvar_Update, network cvar gates, and sv_maxclients reads.
 */
typedef struct coduo_engine_cvar_binary_s {
    uint32_t name;
    uint32_t string;
    uint32_t resetString;
    uint32_t latchedString;
    uint32_t flags;
    qboolean modified;
    int32_t modificationCount;
    float value;
    int32_t integer;
    uint32_t next;
    uint32_t hashNext;
} coduo_engine_cvar_binary_t;

typedef struct cvar_s {
    char *name;
    char *string;
    char *resetString;
    char *latchedString;
    uint32_t flags;
    qboolean modified;
    int32_t modificationCount;
    float value;
    int32_t integer;
    struct cvar_s *next;
    struct cvar_s *hashNext;
} cvar_t;

enum {
    CODUO_ENGINE_CVAR_COUNT = 2048,
    CODUO_ENGINE_CVAR_HASH_SIZE = 256,
    CODUO_CVAR_ARCHIVE = 0x0001,
    CODUO_CVAR_USERINFO = 0x0002,
    CODUO_CVAR_SERVERINFO = 0x0004,
    CODUO_CVAR_SYSTEMINFO = 0x0008,
    CODUO_CVAR_INIT = 0x0010,
    CODUO_CVAR_LATCH = 0x0020,
    CODUO_CVAR_ROM = 0x0040,
    CODUO_CVAR_USER_CREATED = 0x0080,
    CODUO_CVAR_TEMP = 0x0100,
    CODUO_CVAR_CHEAT = 0x0200,
    CODUO_CVAR_NORESTART = 0x0400,
    CODUO_CVAR_SCRIPT_MAKE_SERVERINFO = 0x0800,
    CODUO_CVAR_SCRIPT_SETCVAR = 0x1000,
    CODUO_CVAR_SCRIPT_SETCVAR_SERVERINFO = 0x2000,
    CODUO_CVAR_PLACEHOLDER_CREATED_MASK =
        CODUO_CVAR_USER_CREATED | CODUO_CVAR_SCRIPT_SETCVAR,
    CODUO_CVAR_RESTART_PRESERVE_MASK =
        CODUO_CVAR_INIT | CODUO_CVAR_ROM | CODUO_CVAR_NORESTART,
    CODUO_CVAR_SERVERINFO_SYNC_MASK =
        CODUO_CVAR_SERVERINFO | CODUO_CVAR_SCRIPT_SETCVAR_SERVERINFO,
    CODUO_CVAR_SYSTEMINFO_SYNC_MASK = CODUO_CVAR_SYSTEMINFO,
    CODUO_CVAR_SYSTEMINFO_KEY_VALUE = CODUO_CVAR_SCRIPT_MAKE_SERVERINFO,
    CODUO_CVAR_SYSTEMINFO_KEY_VALUE_SYNC_MASK =
        CODUO_CVAR_SCRIPT_MAKE_SERVERINFO,
    CODUO_NET_CVAR_POINTER_SLOT_COUNT = 6
};

typedef cvar_t
    coduo_engine_cvar_table_t[CODUO_ENGINE_CVAR_COUNT];
typedef coduo_engine_cvar_binary_t
    coduo_engine_cvar_binary_table_t[CODUO_ENGINE_CVAR_COUNT];
typedef uint32_t
    coduo_engine_cvar_binary_hash_table_t[CODUO_ENGINE_CVAR_HASH_SIZE];
typedef cvar_t *
    coduo_engine_cvar_hash_table_t[CODUO_ENGINE_CVAR_HASH_SIZE];
typedef cvar_t *
    coduo_net_cvar_pointer_table_t[CODUO_NET_CVAR_POINTER_SLOT_COUNT];
typedef const char *
    coduo_net_profile_socket_name_table_t
        [CODUO_NET_PROFILE_SOCKET_NAME_COUNT];

/*
 * Confirmed MSG delta field descriptor record.
 *
 * Evidence:
 * - Static objective field descriptors at VA 0x80f0360 use six 0x0c-byte
 *   records.
 * - Static HUD element field descriptors at VA 0x80f03c0 use thirty
 *   0x0c-byte records with the same name/offset/bits layout.
 */
typedef struct coduo_net_field_descriptor_s {
    const char *name;
    int32_t offset;
    int32_t bits;
} coduo_net_field_descriptor_t;
typedef coduo_net_field_descriptor_t
    coduo_objective_net_field_table_t[CODUO_OBJECTIVE_NET_FIELD_COUNT];
typedef coduo_net_field_descriptor_t
    coduo_hud_elem_net_field_table_t[CODUO_HUD_ELEM_NET_FIELD_COUNT];
typedef uint8_t coduo_md4_digest_t[CODUO_MD4_DIGEST_SIZE];
typedef uint8_t coduo_md4_padding_t[CODUO_MD4_PADDING_SIZE];
typedef struct coduo_md4_context_s {
    uint32_t state[CODUO_MD4_STATE_WORD_COUNT];
    uint32_t count[CODUO_MD4_COUNT_WORD_COUNT];
    uint8_t buffer[CODUO_MD4_BLOCK_SIZE];
} coduo_md4_context_t;

/*
 * Small engine name/value variable node used by the openlog helper family.
 *
 * Evidence:
 * - The allocator at VA 0x8077a61 reserves strlen(name) + 0x19 bytes, clears
 *   the fixed 0x18-byte prefix, stores name at +0x00 as node + 0x18, and
 *   links nodes through +0x14.
 * - Lookup/get/set helpers at VA 0x8077b40..0x8077d83 use stringValue +0x04,
 *   modified +0x0c, floatValue +0x10, and next +0x14.
 */
struct coduo_engine_name_value_s {
    char *name;
    char *stringValue;
    uint32_t reserved08;
    qboolean modified;
    float floatValue;
    coduo_engine_name_value_t *next;
    char inlineName[];
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_engine_cvar_binary_t) == 0x2c,
               "coduo_engine_cvar_binary_t size mismatch");
_Static_assert(sizeof(coduo_engine_cvar_binary_table_t) ==
                   2048 * 0x2c,
               "coduo_engine_cvar_binary_table_t size mismatch");
_Static_assert(sizeof(coduo_engine_cvar_binary_hash_table_t) ==
                   256 *
                       4,
               "coduo_engine_cvar_binary_hash_table_t size mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(cvar_t) == 0x2c,
               "cvar_t size mismatch");
_Static_assert(sizeof(coduo_engine_cvar_table_t) ==
                   2048 * 0x2c,
               "coduo_engine_cvar_table_t size mismatch");
_Static_assert(sizeof(coduo_engine_cvar_hash_table_t) ==
                   256 *
                       sizeof(cvar_t *),
               "coduo_engine_cvar_hash_table_t size mismatch");
_Static_assert(sizeof(coduo_net_cvar_pointer_table_t) ==
                   6 *
                       sizeof(cvar_t *),
               "coduo_net_cvar_pointer_table_t size mismatch");
#endif
_Static_assert(sizeof(coduo_net_profile_socket_name_table_t) ==
                    2 * sizeof(const char *),
               "coduo_net_profile_socket_name_table_t size mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_net_field_descriptor_t) ==
                   0x0c,
               "coduo_net_field_descriptor_t size mismatch");
_Static_assert(offsetof(coduo_net_field_descriptor_t, name) ==
                   0x00,
               "coduo_net_field_descriptor_t.name offset mismatch");
_Static_assert(offsetof(coduo_net_field_descriptor_t, offset) ==
                   0x04,
               "coduo_net_field_descriptor_t.offset offset mismatch");
_Static_assert(offsetof(coduo_net_field_descriptor_t, bits) ==
                   0x08,
               "coduo_net_field_descriptor_t.bits offset mismatch");
_Static_assert(sizeof(coduo_objective_net_field_table_t) ==
                   6 *
                       0x0c,
               "coduo_objective_net_field_table_t size mismatch");
_Static_assert(sizeof(coduo_hud_elem_net_field_table_t) ==
                   30 *
                       0x0c,
               "coduo_hud_elem_net_field_table_t size mismatch");
#endif
_Static_assert(sizeof(coduo_md4_digest_t) == 16,
               "coduo_md4_digest_t size mismatch");
_Static_assert(sizeof(coduo_md4_padding_t) == 64,
               "coduo_md4_padding_t size mismatch");
_Static_assert(sizeof(coduo_md4_context_t) == 0x58,
               "coduo_md4_context_t size mismatch");
_Static_assert(offsetof(coduo_md4_context_t, state) ==
                   0x00,
               "coduo_md4_context_t.state offset mismatch");
_Static_assert(offsetof(coduo_md4_context_t, count) ==
                   0x10,
               "coduo_md4_context_t.count offset mismatch");
_Static_assert(offsetof(coduo_md4_context_t, buffer) ==
                   0x18,
               "coduo_md4_context_t.buffer offset mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_engine_name_value_t) ==
                   0x18,
               "coduo_engine_name_value_t size mismatch");
#endif
_Static_assert(offsetof(coduo_engine_cvar_binary_t, name) ==
                   0x00,
               "coduo_engine_cvar_binary_t.name offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, string) ==
                   0x04,
               "coduo_engine_cvar_binary_t.string offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, resetString) ==
                   0x08,
               "coduo_engine_cvar_binary_t.resetString offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, latchedString) ==
                   0x0c,
               "coduo_engine_cvar_binary_t.latchedString offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, flags) ==
                   0x10,
               "coduo_engine_cvar_binary_t.flags offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, modified) ==
                   0x14,
               "coduo_engine_cvar_binary_t.modified offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, modificationCount) ==
                   0x18,
               "coduo_engine_cvar_binary_t.modificationCount offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, value) ==
                   0x1c,
               "coduo_engine_cvar_binary_t.value offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, integer) ==
                   0x20,
               "coduo_engine_cvar_binary_t.integer offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, next) ==
                   0x24,
               "coduo_engine_cvar_binary_t.next offset mismatch");
_Static_assert(offsetof(coduo_engine_cvar_binary_t, hashNext) ==
                   0x28,
               "coduo_engine_cvar_binary_t.hashNext offset mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(offsetof(cvar_t, name) ==
                   0x00,
               "cvar_t.name offset mismatch");
_Static_assert(offsetof(cvar_t, string) ==
                   0x04,
               "cvar_t.string offset mismatch");
_Static_assert(offsetof(cvar_t, resetString) ==
                   0x08,
               "cvar_t.resetString offset mismatch");
_Static_assert(offsetof(cvar_t, latchedString) ==
                   0x0c,
               "cvar_t.latchedString offset mismatch");
_Static_assert(offsetof(cvar_t, flags) ==
                   0x10,
               "cvar_t.flags offset mismatch");
_Static_assert(offsetof(cvar_t, modified) ==
                   0x14,
               "cvar_t.modified offset mismatch");
_Static_assert(offsetof(cvar_t, modificationCount) ==
                   0x18,
               "cvar_t.modificationCount offset mismatch");
_Static_assert(offsetof(cvar_t, value) ==
                   0x1c,
               "cvar_t.value offset mismatch");
_Static_assert(offsetof(cvar_t, integer) ==
                   0x20,
               "cvar_t.integer offset mismatch");
_Static_assert(offsetof(cvar_t, next) ==
                   0x24,
               "cvar_t.next offset mismatch");
_Static_assert(offsetof(cvar_t, hashNext) ==
                   0x28,
               "cvar_t.hashNext offset mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(offsetof(coduo_engine_name_value_t, name) ==
                   0x00,
               "coduo_engine_name_value_t.name offset mismatch");
_Static_assert(offsetof(coduo_engine_name_value_t, stringValue) ==
                   0x04,
               "coduo_engine_name_value_t.stringValue offset mismatch");
_Static_assert(offsetof(coduo_engine_name_value_t, reserved08) ==
                   0x08,
               "coduo_engine_name_value_t.reserved08 offset mismatch");
_Static_assert(offsetof(coduo_engine_name_value_t, modified) ==
                   0x0c,
               "coduo_engine_name_value_t.modified offset mismatch");
_Static_assert(offsetof(coduo_engine_name_value_t, floatValue) ==
                   0x10,
               "coduo_engine_name_value_t.floatValue offset mismatch");
_Static_assert(offsetof(coduo_engine_name_value_t, next) ==
                   0x14,
               "coduo_engine_name_value_t.next offset mismatch");
_Static_assert(offsetof(coduo_engine_name_value_t, inlineName) ==
                   0x18,
               "coduo_engine_name_value_t.inlineName offset mismatch");
#endif
#endif

/*
 * Confirmed native VM slot layout for coduo_lnxded, with one inherited field
 * identity at +0x84.
 *
 * Evidence:
 * - VM_Init clears 3 * 0x90 bytes at VA 0x850c120.
 * - VM_Create indexes the table with i * 0x90 and writes:
 *   +0x00 systemCall, +0x04 name, +0x44 loaded path, +0x88 dllHandle.
 * - Sys_LoadDll receives &slot->entryPoint and writes vmMain at +0x8c.
 * - VM_Call loads currentVM globally, then calls slot->entryPoint.
 * - coduo_lnxded has no direct load or store at +0x84.  VM_Init, VM_Free, and
 *   VM_Clear affect it only as part of whole-slot clearing, so CoD proves an
 *   otherwise-unused four-byte lane there, not its semantic identity.
 * - `searchPath` is a provisional identity inherited from the same-position
 *   field in the closely related iocod VM record.  Conditional on that
 *   identity, the pointee is not unknown: iocod's FS_ReadFileDir and FS_Which
 *   consumers use it as searchpath_s even though vm_local.h hides the private
 *   filesystem type behind `void *`.  The typed pointer below therefore makes
 *   the inherited hypothesis explicit and widens correctly on 64-bit hosts.
 *   If a CoD +0x84 access is found, re-adjudicate the name and type against it.
 *
 * The recovered source uses source-level pointer/function types for the live
 * fields. The binary offset assertions below are therefore i386-only; 64-bit
 * ports should preserve the semantics rather than the original slot stride.
 */
struct coduo_vm_s {
    coduo_vm_system_call_fn systemCall;
    char name[CODUO_MAX_QPATH];
    char fqpath[CODUO_MAX_QPATH];
    /* INHERITED, NOT CODUO-MACHINE-CODE-PROVED; unused by coduo_lnxded. */
    struct searchpath_s *searchPath;
    coduo_native_dll_host_handle_t dllHandle;
    coduo_vm_main_fn entryPoint;
};

enum {
    CODUO_VM_COUNT = 3
};

typedef coduo_vm_t coduo_vm_table_t[CODUO_VM_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_vm_t) == 0x90,
               "coduo_vm_t must match the native VM slot size");
_Static_assert(sizeof(coduo_vm_table_t) == (3 * 0x90),
               "coduo_vm_table_t size mismatch");
_Static_assert(offsetof(coduo_vm_t, systemCall) == 0x00,
               "coduo_vm_t.systemCall offset mismatch");
_Static_assert(offsetof(coduo_vm_t, name) == 0x04,
               "coduo_vm_t.name offset mismatch");
_Static_assert(sizeof(((coduo_vm_t *)0)->name) == 64,
               "coduo_vm_t.name size mismatch");
_Static_assert(offsetof(coduo_vm_t, fqpath) == 0x44,
               "coduo_vm_t.fqpath offset mismatch");
_Static_assert(sizeof(((coduo_vm_t *)0)->fqpath) == 64,
               "coduo_vm_t.fqpath size mismatch");
_Static_assert(offsetof(coduo_vm_t, searchPath) == 0x84,
               "coduo_vm_t provisional searchPath lane offset mismatch");
_Static_assert(offsetof(coduo_vm_t, dllHandle) == 0x88,
               "coduo_vm_t.dllHandle offset mismatch");
_Static_assert(offsetof(coduo_vm_t, entryPoint) == 0x8c,
               "coduo_vm_t.entryPoint offset mismatch");
#endif
#endif

typedef struct worldSector_s worldSector_t;
typedef struct trace_s trace_t;
typedef struct sphere_s sphere_t;
typedef struct coduo_dobj_trace_result_s coduo_dobj_trace_result_t;
typedef struct cmClipMoveWork_s cmClipMoveWork_t;
typedef struct cmPointTraceWork_s
    cmPointTraceWork_t;
typedef struct cmPointSightTraceWork_s
    cmPointSightTraceWork_t;
typedef struct cmClipSightTraceWork_s
    cmClipSightTraceWork_t;
typedef struct sharedEntity_s sharedEntity_t;
typedef struct svEntity_s svEntity_t;
/* Pointer-free records embedded in playerState_t.  CoDUOMP's objective/HUD
 * delta tables prove the member offsets, while the game and cgame consumers
 * establish the same objective and client-visible HUD record identities. */
enum {
    PLAYERSTATE_OBJECTIVE_COUNT = 16,
    PLAYERSTATE_HUD_ELEM_COUNT = 63
};

typedef struct objective_s {
    int32_t state;
    vec3_t origin;
    int32_t entityNum;
    int32_t teamNum;
    int32_t icon;
} objective_t;

typedef union hudelem_color_u {
    uint32_t rgba;
    struct {
        uint8_t red;
        uint8_t green;
        uint8_t blue;
        uint8_t alpha;
    } components;
} hudelem_color_t;

typedef struct hudElem_s {
    int32_t type;
    int32_t x;
    int32_t y;
    float fontScale;
    int32_t font;
    int32_t alignX;
    int32_t alignY;
    hudelem_color_t color;
    hudelem_color_t fromColor;
    int32_t fadeStartTime;
    int32_t fadeTime;
    int32_t label;
    int32_t width;
    int32_t height;
    int32_t materialIndex;
    int32_t scaleFromWidth;
    int32_t scaleFromHeight;
    int32_t scaleStartTime;
    int32_t scaleTime;
    int32_t moveFromX;
    int32_t moveFromY;
    int32_t moveStartTime;
    int32_t moveTime;
    int32_t timerValue;
    int32_t rotationPeriodMs;
    float value;
    int32_t text;
    float sortKey;
    float shaderRightTexcoord;
    float shaderBottomTexcoord;
    uint32_t unused78;
} hudElem_t;

#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(objective_t) == 0x1c,
               "original i386 objective_t layout changed");
_Static_assert(sizeof(hudElem_t) == 0x7c,
               "original i386 hudElem_t layout changed");
_Static_assert(offsetof(hudElem_t, fadeStartTime) == 0x24 &&
                   offsetof(hudElem_t, scaleStartTime) == 0x44 &&
                   offsetof(hudElem_t, moveStartTime) == 0x54 &&
                   offsetof(hudElem_t, timerValue) == 0x5c,
               "original i386 HUD timestamp layout changed");
#endif

/* Shared 0x4504-byte player-state ABI. Field names reconcile the original
 * engine delta-table strings with the recovered game and cgame consumers. */
typedef struct playerState_s {
    int32_t commandTime;                 /* +0x000 */
    int32_t pmType;                      /* +0x004 */
    int32_t bobCycle;                    /* +0x008 */
    uint32_t playerStateFlags;           /* +0x00c */
    int32_t pmTime;                      /* +0x010 */
    vec3_t psOrigin;                     /* +0x014 */
    vec3_t velocity;                     /* +0x020 */
    int32_t weaponTime;                  /* +0x02c */
    int32_t weaponDelay;                 /* +0x030 */
    int32_t grenadeTimeLeft;             /* +0x034 */
    int32_t foliageSoundTime;            /* +0x038 */
    int32_t fatigueSoundTime;            /* +0x03c */
    int32_t gravity;                     /* +0x040 */
    float leanFraction;                  /* +0x044 */
    int32_t speed;                       /* +0x048 */
    int32_t deltaAngles[3];              /* +0x04c */
    int32_t groundEntityNum;             /* +0x058 */
    vec3_t ladderNormal;                 /* +0x05c */
    int32_t lastJumpCommandTime;         /* +0x068 */
    float jumpOriginZ;                   /* +0x06c; netfield `fJumpOriginZ` */
    int32_t legsTimer;                   /* +0x070 */
    int32_t legsAnim;                    /* +0x074 */
    int32_t torsoTimer;                  /* +0x078 */
    int32_t torsoAnim;                   /* +0x07c */
    int32_t movementDir;                 /* +0x080 */
    uint32_t entityStateFlags;           /* +0x084 */
    int32_t eventIndex;                  /* +0x088 */
    int32_t events[4];                   /* +0x08c */
    int32_t eventParms[4];               /* +0x09c */
    int32_t lastEventIndex;              /* +0x0ac */
    uint8_t unused0B0[36];               /* +0x0b0..+0x0d3; copied with the complete state but otherwise unused by coduo_lnxded, CoDUOMP.exe, game.mp.uo.i386.so, and uo_cgame_mp_x86.dll */
    int32_t psClientNum;                 /* +0x0d4 */
    int32_t currentWeapon;               /* +0x0d8 */
    int32_t weaponState;                 /* +0x0dc */
    float adsFraction;                   /* +0x0e0 */
    int32_t viewModelIndex;              /* +0x0e4 */
    vec3_t viewAngles;                   /* +0x0e8 */
    int32_t viewHeightTarget;            /* +0x0f4 */
    float viewHeightCurrent;             /* +0x0f8 */
    int32_t viewHeightLerpTime;           /* +0x0fc */
    int32_t viewHeightLerpTarget;         /* +0x100 */
    int32_t viewHeightLerpDown;           /* +0x104 */
    float viewHeightLerpPosAdj;           /* +0x108 */
    int32_t damageEvent;                 /* +0x10c */
    int32_t damageYaw;                   /* +0x110 */
    int32_t damagePitch;                 /* +0x114 */
    int32_t damageCount;                 /* +0x118 */
    int32_t health;                      /* +0x11c */
    int32_t deathYaw;                    /* +0x120 */
    int32_t maxHealth;                   /* +0x124 */
    int32_t identClientNum;              /* +0x128 */
    int32_t identClientHealth;           /* +0x12c */
    int32_t spawnCount;                  /* +0x130 */
    int32_t ammo[128];                   /* +0x134 */
    int32_t clips[128];                  /* +0x334 */
    uint32_t weaponBits[4];              /* +0x534 */
    uint8_t weaponSlots[8];              /* +0x544 */
    uint32_t weaponRechamberBits[4];     /* +0x54c */
    vec3_t playerMins;                   /* +0x55c */
    vec3_t playerMaxs;                   /* +0x568 */
    int32_t proneViewHeight;             /* +0x574 */
    int32_t crouchViewHeight;            /* +0x578 */
    int32_t standViewHeight;             /* +0x57c */
    int32_t deadViewHeight;              /* +0x580 */
    float walkSpeedScale;                /* +0x584 */
    float runSpeedScale;                 /* +0x588 */
    float sprintSpeedScale;              /* +0x58c */
    float proneSpeedScale;               /* +0x590 */
    float crouchSpeedScale;              /* +0x594 */
    float strafeSpeedScale;              /* +0x598 */
    float backSpeedScale;                /* +0x59c */
    float leanSpeedScale;                /* +0x5a0 */
    float proneDirection;                /* +0x5a4 */
    float proneDirectionPitch;           /* +0x5a8 */
    float proneTorsoPitch;               /* +0x5ac */
    float fatigueScale;                  /* +0x5b0 */
    int32_t lastSprintTime;              /* +0x5b4 */
    int32_t viewLocked;                  /* +0x5b8 */
    int32_t viewLockedEntityNum;         /* +0x5bc */
    float friction;                      /* +0x5c0 */
    int32_t serverCursorHint;            /* +0x5c4 */
    int32_t serverCursorHintVal;         /* +0x5c8 */
    int32_t serverCursorHintString;      /* +0x5cc */
    uint8_t unused5D0[28];               /* +0x5d0..+0x5eb; copied with the complete state but otherwise unused by coduo_lnxded, CoDUOMP.exe, game.mp.uo.i386.so, and uo_cgame_mp_x86.dll */
    uint32_t cursorHintFlags;            /* +0x5ec */
    uint8_t unused5F0[8];                /* +0x5f0..+0x5f7; copied with the complete state but otherwise unused by coduo_lnxded, CoDUOMP.exe, game.mp.uo.i386.so, and uo_cgame_mp_x86.dll */
    uint16_t cursorHintEntNum;           /* +0x5f8 */
    uint8_t unused5FA[6];                /* +0x5fa..+0x5ff; copied with the complete state but otherwise unused by coduo_lnxded, CoDUOMP.exe, game.mp.uo.i386.so, and uo_cgame_mp_x86.dll */
    int32_t compassFriendInfo;           /* +0x600 */
    int32_t compassTankInfo;             /* +0x604 */
    float torsoHeight;                   /* +0x608 */
    float torsoPitch;                    /* +0x60c */
    float waistPitch;                    /* +0x610 */
    int32_t vehiclePosition;             /* +0x614 */
    int32_t vehicleType;                 /* +0x618 */
    int32_t vehicleMotion;               /* +0x61c */
    int32_t oldEventIndex;               /* +0x620 */
    uint32_t weaponAnim;                 /* +0x624 */
    float aimSpreadScale;                /* +0x628 */
    union {
        vec3_t externalVelocity;
        struct {
            int32_t index;
            int32_t time;
            int32_t duration;
        } shellshock;
    } motionState;                       /* +0x62c */
    objective_t objectives[PLAYERSTATE_OBJECTIVE_COUNT]; /* +0x638 */
    hudElem_t hudCurrent[PLAYERSTATE_HUD_ELEM_COUNT];    /* +0x7f8 */
    hudElem_t hudArchival[PLAYERSTATE_HUD_ELEM_COUNT];   /* +0x267c */
    int32_t deltaTime;                   /* +0x4500 */
} playerState_t;

_Static_assert(sizeof(playerState_t) == 0x4504,
               "playerState_t size mismatch");
_Static_assert(offsetof(playerState_t, health) == 0x11c,
               "playerState_t.health offset mismatch");
_Static_assert(offsetof(playerState_t, spawnCount) == 0x130,
               "playerState_t.spawnCount offset mismatch");
_Static_assert(offsetof(playerState_t, objectives) == 0x638,
               "playerState_t.objectives offset mismatch");
_Static_assert(offsetof(playerState_t, deltaTime) == 0x4500,
               "playerState_t.deltaTime offset mismatch");
typedef struct coduo_entity_state_s coduo_entity_state_t;
typedef struct netchan_s netchan_t;
typedef struct netadr_s netadr_t;
typedef struct usercmd_s {
    int32_t commandTime;
    uint8_t buttons;
    uint8_t wbuttons;
    uint8_t weapon;
    int32_t angles[3];
    int8_t forwardmove;
    int8_t rightmove;
    int8_t upmove;
} usercmd_t;
/*
 * SV_ParseUsercmds at VA 0x808d8af decodes at most 32 packet usercmds into a
 * stack batch of 0x18-byte records before applying the newest valid commands.
 */
typedef usercmd_t
    coduo_packet_usercmd_batch_t[CODUO_MAX_PACKET_USERCMDS];
typedef const char *
    coduo_cmd_argv_table_t[CODUO_CMD_MAX_ARGS];
typedef char *
    coduo_com_argv_table_t[CODUO_COM_MAX_ARGS];
typedef char coduo_com_open_log_filename_t[1024];
typedef char coduo_msg_read_string_buffer_t[CODUO_MAX_STRING_CHARS];
typedef char coduo_msg_read_big_string_buffer_t[CODUO_BIG_INFO_STRING];
typedef char coduo_cvar_info_string_buffer_t[CODUO_MAX_INFO_STRING];
typedef char coduo_cvar_big_info_string_buffer_t[CODUO_BIG_INFO_STRING];
typedef char coduo_com_parse_netadr_string_t[CODUO_COM_PARSE_FILE_NAME_SIZE];
typedef char coduo_com_parse_token_t[CODUO_COM_PARSE_TOKEN_SIZE];
typedef char
    coduo_com_parse_accumulator_t[CODUO_COM_PARSE_TOKEN_SIZE];
typedef const char *
    coduo_com_parse_operator_string_table_t
        [CODUO_COM_PARSE_OPERATOR_STRING_COUNT + 1];
typedef struct com_parse_session_s {
    coduo_com_parse_token_t token;
    int32_t line;
    int32_t ungetToken;
    int32_t spaceDelimited;
    int32_t csv;
    int32_t parseNegativeNumbers;
    int32_t savedLine;
    char *savedParse;
    char name[CODUO_COM_PARSE_FILE_NAME_SIZE];
} com_parse_session_t;
typedef com_parse_session_t
    com_parse_session_stack_t[CODUO_COM_PARSE_STATE_COUNT];
typedef struct token_s {
    char string[CODUO_PC_TOKEN_STRING_SIZE];
    int32_t type;
    int32_t subtype;
    int32_t intValue;
    uint8_t floatValue[CODUO_PC_TOKEN_FLOAT_VALUE_SIZE];
    char * whitespaceStart;
    char * whitespaceEnd;
    int32_t line;
    int32_t linesCrossed;
    token_t *next;
} token_t;
struct punctuation_s {
    const char * p;
    int32_t n;
    punctuation_t *next;
};
typedef punctuation_t
    coduo_pc_default_punctuation_table_t[CODUO_PC_DEFAULT_PUNCTUATION_COUNT];
typedef punctuation_t *
    coduo_pc_punctuation_bucket_table_t[CODUO_PC_PUNCTUATION_BUCKET_COUNT];
typedef struct script_s {
    char filename[CODUO_PC_SCRIPT_FILENAME_SIZE];
    char *buffer;
    char *script_p;
    char *end_p;
    char *lastscript_p;
    char *whitespace_p;
    char *endwhitespace_p;
    int32_t length;
    int32_t line;
    int32_t lastline;
    int32_t tokenavailable;
    int32_t flags;
    punctuation_t *punctuations;
    punctuation_t **punctuationtable;
    token_t token;
    script_t *next;
} script_t;
typedef struct indent_s {
    int32_t type;
    int32_t skip;
    script_t *script;
    indent_t *next;
} indent_t;
typedef struct source_s {
    char filename[0x40];
    char includePath[CODUO_PC_SOURCE_INCLUDE_PATH_SIZE];
    punctuation_t *punctuations;
    script_t *scriptStack;
    token_t *tokens;
    define_t *defines;
    define_t **defineHash;
    indent_t *indentStack;
    int32_t skip;
    token_t token;
} source_t;
typedef struct define_s {
    char *name;
    int32_t flags;
    int32_t builtin;
    int32_t numParms;
    token_t *parms;
    token_t *tokens;
    define_t *next;
    define_t *hashNext;
    char nameStorage[];
} define_t;
typedef source_t *
    coduo_pc_source_handle_table_t[CODUO_PC_SOURCE_HANDLE_COUNT];
typedef define_t *
    coduo_pc_define_hash_table_t[CODUO_PC_DEFINE_HASH_BUCKET_COUNT];
typedef char coduo_pc_base_folder_t[CODUO_MAX_QPATH];
typedef uint32_t
    coduo_msg_bitmask_table_t[CODUO_MSG_BITMASK_TABLE_COUNT];
typedef char
    coduo_cmd_token_buffer_t[CODUO_CMD_TOKEN_BUFFER_SIZE];
typedef char
    coduo_sv_gametype_normalize_buffer_t
        [64];
typedef char coduo_cbuf_text_buffer_t[65536];
typedef char coduo_com_error_message_t[CODUO_COM_ERROR_MESSAGE_SIZE];
typedef char coduo_com_va_scratch_t[CODUO_COM_VA_SCRATCH_SIZE];
typedef char coduo_com_va_return_ring_t[CODUO_COM_VA_RETURN_RING_SIZE];
typedef void (*coduo_com_redirect_flush_t)(char *buffer);
typedef struct coduo_com_redirect_state_s {
    char *buffer;
    int32_t bufferSize;
    coduo_com_redirect_flush_t flush;
} coduo_com_redirect_state_t;
/*
 * Com_GetRealEvent at VA 0x8070b87 journals this fixed record to journal.dat.
 * Replay reads 0x18 bytes into the same shape, allocates payloadLength bytes
 * when non-zero, stores that pointer in payload, then reads the event payload
 * bytes from journal.dat. journaldata.dat is used by FS file journaling.
 */
typedef struct coduo_journal_event_record_s {
    int32_t time;
    int32_t type;
    int32_t value;
    int32_t value2;
    int32_t payloadLength;
    uint32_t payload;
} coduo_journal_event_record_t;
typedef struct sysEvent_s {
    int32_t time;
    int32_t type;
    int32_t value;
    int32_t value2;
    int32_t payloadLength;
    void *payload;
} sysEvent_t;
typedef coduo_journal_event_record_t coduo_binary_sys_event_t;
typedef coduo_binary_sys_event_t
    coduo_binary_sys_event_queue_t[CODUO_SYS_EVENT_QUEUE_COUNT];
typedef sysEvent_t
    coduo_sys_event_queue_t[CODUO_SYS_EVENT_QUEUE_COUNT];
typedef char coduo_info_value_buffer_table_t[ CODUO_INFO_VALUE_BUFFER_COUNT * CODUO_INFO_VALUE_BUFFER_SIZE];
typedef char coduo_host_client_userinfo_t[CODUO_MAX_INFO_STRING];
typedef char coduo_host_client_name_t[CODUO_MAX_NAME_LENGTH];
typedef char coduo_host_client_command_string_t[CODUO_MAX_STRING_CHARS];
typedef char coduo_host_download_name_t[CODUO_MAX_QPATH];
typedef char coduo_host_punkbuster_guid_t[0x21];
typedef char coduo_punkbuster_info_string_t[0x21];
typedef struct fileHandleData_s fileHandleData_t;
typedef struct cmd_function_s cmd_function_t;
typedef struct coduo_cmd_text_s coduo_cmd_text_t;
typedef struct client_s client_t;
typedef struct coduo_sv_client_command_handler_s
    coduo_sv_client_command_handler_t;
typedef struct clientSnapshot_s
    clientSnapshot_t;
typedef struct coduo_punkbuster_client_info_s coduo_punkbuster_client_info_t;
typedef struct coduo_punkbuster_server_s coduo_punkbuster_server_t;
enum {
    CODUO_SYS_TTY_INPUT_RETURN_BUFFER_SIZE = 0x100,
    CODUO_SYS_TTY_LINE_TEXT_SIZE = 0x100,
    CODUO_SYS_TTY_HISTORY_COUNT = 32
};

typedef uint8_t coduo_sys_tty_termios_blob_t[0x3c];
typedef char
    coduo_sys_tty_input_return_buffer_t
        [CODUO_SYS_TTY_INPUT_RETURN_BUFFER_SIZE];

/*
 * Terminal-console line record used by the edited tty input path.
 *
 * Evidence:
 * - Newline handling copies currentLine.text at VA 0x8456b3c into the
 *   0x100-byte return buffer at VA 0x84569e0.
 * - History storage shifts/copies 0x11c-byte records starting at
 *   VA 0x8456c40 and stores the current 0x11c-byte record at history[0].
 * - Field_Clear-matched VA 0x8072140 clears text, cursor, and scroll, then
 *   stores widthInChars = 0x100 at +0x08.
 * - Backspace/append paths update currentLine.cursor at VA 0x8456b20 and
 *   edit bytes at currentLine.text[cursor].
 * - CoDUOMP's machine-code-proven console_input_field_t has the same 0x11c
 *   layout and names the four +0x0c..+0x18 lanes below. The dedicated server
 *   preserves them in whole-record history copies but does not otherwise use
 *   them in its tty path.
 */
typedef struct coduo_sys_tty_line_s {
    int32_t cursor;
    int32_t scroll;
    int32_t widthInChars;
    int32_t widthInPixels;
    float charWidth;
    float charHeight;
    qboolean fixedSize;
    char text[CODUO_SYS_TTY_LINE_TEXT_SIZE];
} coduo_sys_tty_line_t;

typedef coduo_sys_tty_line_t
    coduo_sys_tty_history_t[CODUO_SYS_TTY_HISTORY_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_sys_tty_termios_blob_t) ==
                   0x3c,
               "coduo_sys_tty_termios_blob_t size mismatch");
_Static_assert(sizeof(coduo_sys_tty_input_return_buffer_t) ==
                   0x100,
               "coduo_sys_tty_input_return_buffer_t size mismatch");
_Static_assert(sizeof(coduo_sys_tty_line_t) ==
                   0x11c,
               "coduo_sys_tty_line_t size mismatch");
_Static_assert(offsetof(coduo_sys_tty_line_t, cursor) ==
                   0x00,
               "coduo_sys_tty_line_t.cursor offset mismatch");
_Static_assert(offsetof(coduo_sys_tty_line_t, scroll) ==
                   0x04,
               "coduo_sys_tty_line_t.scroll offset mismatch");
_Static_assert(offsetof(coduo_sys_tty_line_t, widthInChars) ==
                   0x08,
               "coduo_sys_tty_line_t.widthInChars offset mismatch");
_Static_assert(offsetof(coduo_sys_tty_line_t, widthInPixels) ==
                   0x0c,
               "coduo_sys_tty_line_t.widthInPixels offset mismatch");
_Static_assert(offsetof(coduo_sys_tty_line_t, charWidth) ==
                   0x10,
               "coduo_sys_tty_line_t.charWidth offset mismatch");
_Static_assert(offsetof(coduo_sys_tty_line_t, charHeight) ==
                   0x14,
               "coduo_sys_tty_line_t.charHeight offset mismatch");
_Static_assert(offsetof(coduo_sys_tty_line_t, fixedSize) ==
                   0x18,
               "coduo_sys_tty_line_t.fixedSize offset mismatch");
_Static_assert(offsetof(coduo_sys_tty_line_t, text) ==
                   0x1c,
               "coduo_sys_tty_line_t.text offset mismatch");
_Static_assert(sizeof(((coduo_sys_tty_line_t *)0)->text) ==
                   0x100,
               "coduo_sys_tty_line_t.text size mismatch");
_Static_assert(sizeof(coduo_sys_tty_history_t) ==
                   0x11c *
                       32,
               "coduo_sys_tty_history_t size mismatch");
#endif
typedef union VariableUnion VariableUnion;
typedef struct VariableValue VariableValue;
typedef struct VariableValueInternal VariableValueInternal;
typedef struct Variable Variable;
typedef struct VariableStackBuffer VariableStackBuffer;
typedef struct coduo_script_variable_node_s coduo_script_variable_node_t;
typedef struct coduo_script_entity_type_usage_s
    coduo_script_entity_type_usage_t;
typedef struct coduo_script_yy_buffer_s coduo_script_yy_buffer_t;
typedef union sval_u sval_u;
typedef struct XAnimState XAnimState;
typedef struct XAnimInfo XAnimInfo;
typedef struct xanim_notetrack_s xanim_notetrack_t;
typedef struct xanim_int16_vec2_s xanim_int16_vec2_t;
typedef struct xanim_int16_vec4_s xanim_int16_vec4_t;
typedef union xanim_rotation_stream_data_u xanim_rotation_stream_data_t;
typedef union xanim_rotation_stream_tail_u xanim_rotation_stream_tail_t;
typedef union xanim_translation_stream_data_u
    xanim_translation_stream_data_t;
typedef union xanim_translation_stream_key_u
    xanim_translation_stream_key_t;
typedef struct xanim_translation_stream_inline_lanes_s
    xanim_translation_stream_inline_lanes_t;
typedef struct xanim_rotation_stream_s xanim_rotation_stream_t;
typedef struct xanim_translation_stream_s xanim_translation_stream_t;
typedef struct xanim_part_stream_pair_s xanim_part_stream_pair_t;
typedef struct XAnimParts XAnimParts;
typedef struct XAnimEntry XAnimEntry;
typedef struct XAnim_s XAnim;
typedef struct XAnimTree_s XAnimTree;
typedef struct coduo_xanim_runtime_tree_tail_span_s
    coduo_xanim_runtime_tree_tail_span_t;
typedef struct xanim_deferred_notify_s xanim_deferred_notify_t;
typedef struct XModelPartNameTable_s XModelPartNameTable;
typedef struct XModelPartNameTableSlot_s XModelPartNameTableSlot;
typedef struct XModelPartColl_s XModelPartColl;
typedef struct XModelLodInfo_s XModelLodInfo;
typedef struct XModelCollTriPlane_s XModelCollTriPlane;
typedef struct XModelCollTri_s XModelCollTri;
typedef struct XModelCollSurf_s XModelCollSurf;
typedef struct XModelConfigLod_s XModelConfigLod;
typedef struct XModelConfig XModelConfig;
typedef struct XStripInfo_s XStripInfo;
typedef struct XSimpleBlendInfo_s XSimpleBlendInfo;
typedef struct XSurfaceWeightedPoint_s XSurfaceWeightedPoint;
typedef struct XSurfaceRigidVert_s XSurfaceRigidVert;
typedef struct XSurfaceBlendVert_s XSurfaceBlendVert;
typedef struct XSurfaceBlendVertNoWeight_s XSurfaceBlendVertNoWeight;
typedef union XSurfaceVertexData_u XSurfaceVertexData;
typedef struct XSurfaceOptimizedDataARB_s XSurfaceOptimizedDataARB;
typedef struct XSurfaceOptimizedDataATI_s XSurfaceOptimizedDataATI;
typedef struct XSurfaceOptimizedDataNV_s XSurfaceOptimizedDataNV;
typedef struct XSurface_s XSurface;

typedef uint16_t XSurfaceTriangle[3];
typedef vec2_t XSurfaceTexCoord;
typedef struct DObjAnimMat_s DObjAnimMat;
typedef struct coduo_xanim_eval_part_span_s coduo_xanim_eval_part_span_t;
typedef union coduo_xanim_eval_storage_part_span_view_u
    coduo_xanim_eval_storage_part_span_view_t;
typedef uint32_t coduo_xanim_part_bitset_t[CODUO_XANIM_PART_BITSET_WORD_COUNT];
typedef struct XAnimToXModel XAnimToXModel;
typedef struct DObjTracePartRemap_s DObjTracePartRemap;
typedef struct DObjModel_s DObjModel;
typedef struct DObj_s DObj;
typedef struct coduo_host_sv_prefix_s coduo_host_sv_prefix_t;
typedef struct coduo_host_game_data_globals_s coduo_host_game_data_globals_t;
typedef struct coduo_host_svs_header_s coduo_host_svs_header_t;
typedef struct coduo_hunk_state_s coduo_hunk_state_t;
typedef struct coduo_hunk_log_block_s coduo_hunk_log_block_t;
typedef struct coduo_hunk_temp_header_s coduo_hunk_temp_header_t;
typedef struct pack_s pack_t;
typedef struct netProfileSample_s netProfileSample_t;
typedef struct netProfileStream_s netProfileStream_t;
typedef struct netProfileInfo_s netProfileInfo_t;
typedef struct loopmsg_s loopmsg_t;
typedef struct loopback_s loopback_t;
typedef enum coduo_punkbuster_server_query_e {
    /* Writes decimal sv_maxclients text into buffer. */
    CODUO_PB_SERVER_QUERY_MAX_CLIENTS = 'e',
    /* Parses buffer as a client number and fills client info. */
    CODUO_PB_SERVER_QUERY_CLIENT_INFO = 'f',
    /* Treats buffer as a cvar name and copies its value with a 255-byte bound. */
    CODUO_PB_SERVER_QUERY_CVAR_STRING = 'g',
    /* Parses buffer as a client number and fills ping/status text. */
    CODUO_PB_SERVER_QUERY_CLIENT_STATUS = 'r'
} coduo_punkbuster_server_query_t;
typedef int32_t (*coduo_pb_command_bridge_fn)(
    const char *command,
    intptr_t value);
/*
 * PB_ServerQuery at VA 0x80b6fb6 first clamps buffer[0xff] to NUL, mutates
 * the buffer in place for successful queries, and returns NULL or an error
 * string for failed client lookups.
 */
typedef const char *(*coduo_pb_query_bridge_fn)(
    coduo_punkbuster_server_query_t query,
    char *buffer);
typedef int32_t (*coduo_pb_output_bridge_fn)(
    const char *text);
typedef int32_t (*coduo_pb_checksum_bridge_fn)(
    const char * data,
    int32_t length,
    int32_t client_num);
typedef const void *coduo_pb_packet_payload_t;
typedef int32_t (*coduo_pb_packet_bridge_fn)(
    const char *address, uint16_t port,
    coduo_pb_packet_payload_t data, int32_t length);
_Static_assert(sizeof(coduo_pb_packet_payload_t) == sizeof(void *),
               "coduo_pb_packet_payload_t size mismatch");
typedef void (*coduo_pb_event_callback_fn)(
    coduo_punkbuster_server_t *server_object, const char *text,
    intptr_t value);
typedef const char *(*coduo_pb_string_query_callback_fn)(
    coduo_punkbuster_server_t *server_object, const char *text,
    intptr_t arg1, intptr_t arg2);
typedef void (*coduo_pb_print_callback_fn)(
    coduo_punkbuster_server_t *server_object, const char *text,
    int32_t text_limit);
typedef void (*coduo_sv_client_command_handler_fn)(
    client_t *client);

typedef enum coduo_server_message_opcode_e {
    CODUO_SVC_DOWNLOAD = 6,
    CODUO_SVC_SNAPSHOT = 7,
    CODUO_SVC_EOF = 8
} coduo_server_message_opcode_t;

typedef enum coduo_www_download_subcommand_e {
    /* Sets host-client redirectAcknowledged when a WWW redirect is active. */
    CODUO_WWWDL_ACK = 0,
    /* Drops the client with the download-disconnected localized reason. */
    CODUO_WWWDL_CLIENT_DISCONNECT = 1,
    /* Clears regular and WWW download state without retrying locally. */
    CODUO_WWWDL_DONE = 2,
    /* Clears state, marks fallback, and resumes regular download handling. */
    CODUO_WWWDL_FAIL = 3,
    /* Logs the checksum failure before the same fallback path as fail. */
    CODUO_WWWDL_CHECKSUM_FAIL = 4
} coduo_www_download_subcommand_t;

typedef enum coduo_pb_server_sa_value_e {
    CODUO_PB_SERVER_SA_FRAME = 0,
    CODUO_PB_SERVER_SA_COMMAND_DRAIN = -1
} coduo_pb_server_sa_value_t;

typedef enum coduo_pb_server_sb_opcode_e {
    CODUO_PB_SERVER_SB_CLIENT_PACKET = 0x0d,
    CODUO_PB_SERVER_SB_START = 0x10,
    CODUO_PB_SERVER_SB_NOTIFY_ENABLED = 0x75,
    CODUO_PB_SERVER_SB_NOTIFY_DISABLED = 0x76
} coduo_pb_server_sb_opcode_t;

/*
 * PunkBuster module exports resolved from pbsv.so:
 * - `sa` is called by PB_CallServerSa at VA 0x80b73f0 as
 *   (pb.serverObject, value). The main loop passes 0 after Com_Frame;
 *   the pb_sv_ packet and Cmd_Exec pb_ paths pass -1.
 * - `sb` is called by PB_CallServerSb at VA 0x80b7330 as
 *   (pb.serverObject, opcode, arg0, arg1, arg2, arg3). The host wrappers
 *   currently prove the opcode values named above; other observed opcode-only
 *   wrappers remain intentionally unnamed. The indirect call has exactly six
 *   i386 words: server, opcode, and arg0..arg3. The four payload
 *   words use intptr_t so pointer-bearing calls remain lossless on native
 *   wider hosts while retaining the original 32-bit widths on i386.
 */
typedef int32_t (*coduo_pb_server_sa_fn)(
    coduo_punkbuster_server_t *server_object,
    coduo_pb_server_sa_value_t value);
typedef intptr_t (*coduo_pb_server_sb_fn)(
    coduo_punkbuster_server_t *server_object,
    int32_t opcode, intptr_t arg0, intptr_t arg1,
    intptr_t arg2, intptr_t arg3);

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_cmd_argv_table_t) == 0x800,
               "coduo_cmd_argv_table_t size mismatch");
#endif
_Static_assert(sizeof(coduo_com_argv_table_t) == 32 * sizeof(char *),
               "coduo_com_argv_table_t size mismatch");
_Static_assert(sizeof(coduo_com_open_log_filename_t) ==
                   1024,
               "coduo_com_open_log_filename_t size mismatch");
_Static_assert(sizeof(coduo_msg_read_string_buffer_t) ==
                   1024,
               "coduo_msg_read_string_buffer_t size mismatch");
_Static_assert(sizeof(coduo_msg_read_big_string_buffer_t) ==
                   0x2000,
               "coduo_msg_read_big_string_buffer_t size mismatch");
_Static_assert(sizeof(coduo_cvar_info_string_buffer_t) ==
                   1024,
               "coduo_cvar_info_string_buffer_t size mismatch");
_Static_assert(sizeof(coduo_cvar_big_info_string_buffer_t) ==
                   0x2000,
               "coduo_cvar_big_info_string_buffer_t size mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(node_t *) == 4,
               "node_t * size mismatch");
_Static_assert(sizeof(node_t) == 0x20,
               "node_t size mismatch");
_Static_assert(offsetof(node_t, left) ==
                   0x00,
               "node_t.left offset mismatch");
_Static_assert(offsetof(node_t, right) ==
                   0x04,
               "node_t.right offset mismatch");
_Static_assert(offsetof(node_t, parent) ==
                   0x08,
               "node_t.parent offset mismatch");
_Static_assert(offsetof(node_t, next) ==
                   0x0c,
               "node_t.next offset mismatch");
_Static_assert(offsetof(node_t, prev) ==
                   0x10,
               "node_t.prev offset mismatch");
_Static_assert(offsetof(node_t, head) ==
                   0x14,
               "node_t.head offset mismatch");
_Static_assert(offsetof(node_t, weight) ==
                   0x18,
               "node_t.weight offset mismatch");
_Static_assert(offsetof(node_t, symbol) ==
                   0x1c,
               "node_t.symbol offset mismatch");
_Static_assert(sizeof(huff_t) == 0x701c,
               "huff_t size mismatch");
_Static_assert(sizeof(huffman_t) ==
                   (0x701c) * 2,
               "huffman_t size mismatch");
_Static_assert(offsetof(huffman_t, compressor) == 0,
               "huffman_t.compressor offset mismatch");
_Static_assert(offsetof(huffman_t, decompressor) ==
                   0x701c,
               "huffman_t.decompressor offset mismatch");
_Static_assert(offsetof(huff_t, blocNode) ==
                   0x0000,
               "huff_t.blocNode offset mismatch");
_Static_assert(offsetof(huff_t, blocPtrs) ==
                   0x0004,
               "huff_t.blocPtrs offset mismatch");
_Static_assert(offsetof(huff_t, tree) ==
                   0x0008,
               "huff_t.tree offset mismatch");
_Static_assert(offsetof(huff_t, lhead) ==
                   0x000c,
               "huff_t.lhead offset mismatch");
_Static_assert(offsetof(huff_t, ltail) ==
                   0x0010,
               "huff_t.ltail offset mismatch");
_Static_assert(offsetof(huff_t, loc) ==
                   0x0014,
               "huff_t.loc offset mismatch");
_Static_assert(sizeof(((huff_t *)0)->loc) ==
                   (256 + 1) *
                       sizeof(node_t *),
               "huff_t.loc size mismatch");
_Static_assert(offsetof(huff_t, freelist) ==
                   0x0418,
               "huff_t.freelist offset mismatch");
_Static_assert(offsetof(huff_t, nodeList) ==
                   0x041c,
               "huff_t.nodeList offset mismatch");
_Static_assert(sizeof(((huff_t *)0)->nodeList[0]) ==
                   0x20,
               "huff_t.nodeList stride mismatch");
_Static_assert(offsetof(huff_t, nodePtrs) ==
                   0x641c,
               "huff_t.nodePtrs offset mismatch");
_Static_assert(sizeof(((huff_t *)0)->nodePtrs[0]) ==
                   sizeof(node_t *),
               "huff_t.nodePtrs stride mismatch");
#endif
_Static_assert(sizeof(coduo_com_parse_netadr_string_t) ==
                   0x40,
               "coduo_com_parse_netadr_string_t size mismatch");
_Static_assert(sizeof(coduo_com_parse_accumulator_t) ==
                   0x400,
               "coduo_com_parse_accumulator_t size mismatch");
_Static_assert(sizeof(coduo_com_parse_operator_string_table_t) ==
                    (CODUO_COM_PARSE_OPERATOR_STRING_COUNT + 1) *
                        sizeof(const char *),
               "coduo_com_parse_operator_string_table_t size mismatch");
_Static_assert(offsetof(com_parse_session_t, token) ==
                   0x000,
               "com_parse_session_t.token offset mismatch");
_Static_assert(offsetof(com_parse_session_t, line) ==
                   0x400,
               "com_parse_session_t.line offset mismatch");
_Static_assert(offsetof(com_parse_session_t, ungetToken) ==
                   0x404,
               "com_parse_session_t.ungetToken offset mismatch");
_Static_assert(offsetof(com_parse_session_t, spaceDelimited) ==
                   0x408,
               "com_parse_session_t.spaceDelimited offset mismatch");
_Static_assert(offsetof(com_parse_session_t, csv) ==
                   0x40c,
               "com_parse_session_t.csv offset mismatch");
_Static_assert(offsetof(com_parse_session_t, parseNegativeNumbers) ==
                   0x410,
               "com_parse_session_t.parseNegativeNumbers offset mismatch");
_Static_assert(sizeof(((com_parse_session_t *)0)
                   ->parseNegativeNumbers) == sizeof(int32_t),
               "com_parse_session_t.parseNegativeNumbers size mismatch");
_Static_assert(offsetof(com_parse_session_t, savedLine) ==
                   0x414,
               "com_parse_session_t.savedLine offset mismatch");
_Static_assert(offsetof(com_parse_session_t, savedParse) ==
                   0x418,
               "com_parse_session_t.savedParse offset mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(char *) ==
                   4,
               "char * size mismatch");
_Static_assert(offsetof(com_parse_session_t, name) ==
                   0x41c,
               "com_parse_session_t.name offset mismatch");
_Static_assert(sizeof(com_parse_session_t) ==
                   0x45c,
               "com_parse_session_t size mismatch");
_Static_assert(sizeof(com_parse_session_stack_t) ==
                   16 *
                       sizeof(com_parse_session_t),
               "com_parse_session_stack_t size mismatch");
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(offsetof(token_t, string) ==
                   0x000,
               "token_t.string offset mismatch");
_Static_assert(sizeof(((token_t *)0)->string) ==
                   0x400,
               "token_t.string size mismatch");
_Static_assert(offsetof(token_t, type) ==
                   0x400,
               "token_t.type offset mismatch");
_Static_assert(offsetof(token_t, subtype) ==
                   0x404,
               "token_t.subtype offset mismatch");
_Static_assert(offsetof(token_t, intValue) ==
                   0x408,
               "token_t.intValue offset mismatch");
_Static_assert(offsetof(token_t, floatValue) ==
                   0x40c,
               "token_t.floatValue offset mismatch");
_Static_assert(sizeof(((token_t *)0)->floatValue) ==
                   0x0c,
               "token_t.floatValue size mismatch");
_Static_assert(offsetof(token_t, whitespaceStart) ==
                   0x418,
               "token_t.whitespaceStart offset mismatch");
_Static_assert(offsetof(token_t, whitespaceEnd) ==
                   0x41c,
               "token_t.whitespaceEnd offset mismatch");
_Static_assert(offsetof(token_t, line) ==
                   0x420,
               "token_t.line offset mismatch");
_Static_assert(offsetof(token_t, linesCrossed) ==
                   0x424,
               "token_t.linesCrossed offset mismatch");
_Static_assert(offsetof(token_t, next) ==
                   0x428,
               "token_t.next offset mismatch");
_Static_assert(sizeof(token_t) == 0x42c,
               "token_t size mismatch");
_Static_assert(sizeof(punctuation_t) == 0x0c,
               "punctuation_t size mismatch");
_Static_assert(offsetof(punctuation_t, p) ==
                   0x00,
               "punctuation_t.p offset mismatch");
_Static_assert(offsetof(punctuation_t, n) ==
                   0x04,
               "punctuation_t.n offset mismatch");
_Static_assert(offsetof(punctuation_t, next) ==
                   0x08,
               "punctuation_t.next offset mismatch");
_Static_assert(sizeof(coduo_pc_default_punctuation_table_t) ==
                   53 *
                       0x0c,
               "coduo_pc_default_punctuation_table_t size mismatch");
_Static_assert(sizeof(coduo_pc_punctuation_bucket_table_t) ==
                    256 * sizeof(punctuation_t *),
               "coduo_pc_punctuation_bucket_table_t size mismatch");
_Static_assert(sizeof(script_t) == 0x4a4,
               "script_t size mismatch");
_Static_assert(offsetof(script_t, filename) ==
                   0x000,
               "script_t.filename offset mismatch");
_Static_assert(sizeof(((script_t *)0)->filename) ==
                   0x40,
               "script_t.filename size mismatch");
_Static_assert(offsetof(script_t, buffer) ==
                   0x040,
               "script_t.buffer offset mismatch");
_Static_assert(offsetof(script_t, script_p) ==
                   0x044,
               "script_t.script_p offset mismatch");
_Static_assert(offsetof(script_t, end_p) ==
                   0x048,
               "script_t.end_p offset mismatch");
_Static_assert(offsetof(script_t, lastscript_p) ==
                   0x04c,
               "script_t.lastscript_p offset mismatch");
_Static_assert(offsetof(script_t, whitespace_p) ==
                   0x050,
               "script_t.whitespace_p offset mismatch");
_Static_assert(offsetof(script_t, endwhitespace_p) ==
                   0x054,
               "script_t.endwhitespace_p offset mismatch");
_Static_assert(offsetof(script_t, length) ==
                   0x058,
               "script_t.length offset mismatch");
_Static_assert(offsetof(script_t, line) ==
                   0x05c,
               "script_t.line offset mismatch");
_Static_assert(offsetof(script_t, lastline) ==
                   0x060,
               "script_t.lastline offset mismatch");
_Static_assert(offsetof(script_t, tokenavailable) ==
                   0x064,
               "script_t.tokenavailable offset mismatch");
_Static_assert(offsetof(script_t, flags) ==
                   0x068,
               "script_t.flags offset mismatch");
_Static_assert(offsetof(script_t, punctuations) ==
                   0x06c,
               "script_t.punctuations offset mismatch");
_Static_assert(offsetof(script_t, punctuationtable) ==
                   0x070,
               "script_t.punctuationtable offset mismatch");
_Static_assert(offsetof(script_t, token) ==
                   0x074,
               "script_t.token offset mismatch");
_Static_assert(offsetof(script_t, next) ==
                   0x4a0,
               "script_t.next offset mismatch");
_Static_assert(offsetof(indent_t, type) ==
                   0x00,
               "indent_t.type offset mismatch");
_Static_assert(offsetof(indent_t, skip) ==
                   0x04,
               "indent_t.skip offset mismatch");
_Static_assert(offsetof(indent_t, script) ==
                   0x08,
               "indent_t.script offset mismatch");
_Static_assert(offsetof(indent_t, next) ==
                   0x0c,
               "indent_t.next offset mismatch");
_Static_assert(sizeof(indent_t) == 0x10,
               "indent_t size mismatch");
_Static_assert(sizeof(source_t) == 0x4c8,
               "source_t size mismatch");
_Static_assert(offsetof(source_t, filename) ==
                   0x000,
               "source_t.filename offset mismatch");
_Static_assert(sizeof(((source_t *)0)->filename) ==
                   0x40,
               "source_t.filename size mismatch");
_Static_assert(offsetof(source_t, includePath) ==
                   0x040,
               "source_t.includePath offset mismatch");
_Static_assert(sizeof(((source_t *)0)->includePath) ==
                   0x40,
               "source_t.includePath size mismatch");
_Static_assert(offsetof(source_t, punctuations) ==
                   0x080,
               "source_t.punctuations offset mismatch");
_Static_assert(offsetof(source_t, scriptStack) ==
                   0x084,
               "source_t.scriptStack offset mismatch");
_Static_assert(offsetof(source_t, tokens) ==
                   0x088,
               "source_t.tokens offset mismatch");
_Static_assert(offsetof(source_t, defines) ==
                   0x08c,
               "source_t.defines offset mismatch");
_Static_assert(offsetof(source_t, defineHash) ==
                   0x090,
               "source_t.defineHash offset mismatch");
_Static_assert(offsetof(source_t, indentStack) ==
                   0x094,
               "source_t.indentStack offset mismatch");
_Static_assert(offsetof(source_t, skip) ==
                   0x098,
               "source_t.skip offset mismatch");
_Static_assert(offsetof(source_t, token) ==
                   0x09c,
               "source_t.token offset mismatch");
_Static_assert(offsetof(define_t, name) ==
                   0x00,
               "define_t.name offset mismatch");
_Static_assert(offsetof(define_t, flags) ==
                   0x04,
               "define_t.flags offset mismatch");
_Static_assert(offsetof(define_t, builtin) ==
                   0x08,
               "define_t.builtin offset mismatch");
_Static_assert(offsetof(define_t, numParms) ==
                   0x0c,
               "define_t.numParms offset mismatch");
_Static_assert(offsetof(define_t, parms) ==
                   0x10,
               "define_t.parms offset mismatch");
_Static_assert(offsetof(define_t, tokens) ==
                   0x14,
               "define_t.tokens offset mismatch");
_Static_assert(offsetof(define_t, next) ==
                   0x18,
               "define_t.next offset mismatch");
_Static_assert(offsetof(define_t, hashNext) ==
                   0x1c,
               "define_t.hashNext offset mismatch");
_Static_assert(offsetof(define_t, nameStorage) ==
                   0x20,
               "define_t.nameStorage offset mismatch");
_Static_assert(sizeof(define_t) == 0x20,
               "define_t header size mismatch");
_Static_assert(sizeof(coduo_pc_source_handle_table_t) ==
                    64 * sizeof(void *),
               "coduo_pc_source_handle_table_t size mismatch");
_Static_assert(sizeof(coduo_pc_define_hash_table_t) ==
                   (1024 * sizeof(define_t *)),
               "coduo_pc_define_hash_table_t size mismatch");
#endif
_Static_assert(sizeof(coduo_pc_base_folder_t) == 64,
               "coduo_pc_base_folder_t size mismatch");
_Static_assert(sizeof(coduo_msg_bitmask_table_t) ==
                   33 * 4,
               "coduo_msg_bitmask_table_t size mismatch");
_Static_assert(sizeof(coduo_cmd_token_buffer_t) ==
                   CODUO_CMD_TOKEN_BUFFER_SIZE,
               "coduo_cmd_token_buffer_t size mismatch");
_Static_assert(sizeof(coduo_sv_gametype_normalize_buffer_t) ==
                   64,
               "coduo_sv_gametype_normalize_buffer_t size mismatch");
_Static_assert(sizeof(coduo_com_error_message_t) ==
                   4096,
               "coduo_com_error_message_t size mismatch");
_Static_assert(sizeof(coduo_com_va_scratch_t) == 32000,
               "coduo_com_va_scratch_t size mismatch");
_Static_assert(sizeof(coduo_com_va_return_ring_t) ==
                   32000,
               "coduo_com_va_return_ring_t size mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_com_redirect_state_t) ==
                   0x0c,
               "coduo_com_redirect_state_t size mismatch");
_Static_assert(offsetof(coduo_com_redirect_state_t, buffer) ==
                   0x00,
               "coduo_com_redirect_state_t.buffer offset mismatch");
_Static_assert(offsetof(coduo_com_redirect_state_t, bufferSize) ==
                   0x04,
               "coduo_com_redirect_state_t.bufferSize offset mismatch");
_Static_assert(offsetof(coduo_com_redirect_state_t, flush) ==
                   0x08,
               "coduo_com_redirect_state_t.flush offset mismatch");
#endif
_Static_assert(sizeof(coduo_journal_event_record_t) == 0x18,
               "coduo_journal_event_record_t size mismatch");
_Static_assert(sizeof(coduo_binary_sys_event_queue_t) ==
                    256 * 0x18,
               "coduo_binary_sys_event_queue_t size mismatch");
_Static_assert(offsetof(coduo_journal_event_record_t, time) ==
                   0x00,
               "coduo_journal_event_record_t.time offset mismatch");
_Static_assert(offsetof(coduo_journal_event_record_t, type) ==
                   0x04,
               "coduo_journal_event_record_t.type offset mismatch");
_Static_assert(offsetof(coduo_journal_event_record_t, value) ==
                   0x08,
               "coduo_journal_event_record_t.value offset mismatch");
_Static_assert(offsetof(coduo_journal_event_record_t, value2) ==
                   0x0c,
               "coduo_journal_event_record_t.value2 offset mismatch");
_Static_assert(offsetof(coduo_journal_event_record_t, payloadLength) ==
                   0x10,
               "coduo_journal_event_record_t.payloadLength offset mismatch");
_Static_assert(offsetof(coduo_journal_event_record_t, payload) ==
                   0x14,
               "coduo_journal_event_record_t.payload offset mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(sysEvent_t) == 0x18,
               "sysEvent_t size mismatch");
_Static_assert(sizeof(coduo_sys_event_queue_t) == 256 * 0x18,
               "coduo_sys_event_queue_t size mismatch");
_Static_assert(offsetof(sysEvent_t, payload) ==
                   0x14,
               "sysEvent_t.payload offset mismatch");
#endif
_Static_assert(sizeof(coduo_info_value_buffer_table_t) ==
                    2 * 0x2000,
               "coduo_info_value_buffer_table_t size mismatch");
#endif

/*
 * Confirmed dynamic world-sector tree node.
 *
 * Evidence:
 * - CM_InitWorldSector at VA 0x805d8e6 initializes the root node at
 *   0x8459988 and links the free pool with a 0x28-byte stride through +0x1c.
 * - Sector allocation at VA 0x805d808 writes axis +0x00, split dist +0x10,
 *   and child sentinels +0x20/+0x24.
 * - SV_LinkEntityToWorldSector/SV_UnlinkEntityFromWorldSector maintain the
 *   entity aggregate contents +0x0c, entity-link head +0x14, parent/free-next
 *   slot +0x1c, and child pointers +0x20/+0x24.
 * - CM_LinkStaticModel at VA 0x805e02b maintains aggregate static-model
 *   masks +0x04/+0x08 and the static-model link head +0x18; those pointees are
 *   not host entity-link records and use their own next fields.
 */
struct worldSector_s {
    int32_t axis;
    int32_t staticModelContentsMask;
    int32_t sightTraceStaticModelContentsMask;
    int32_t entityContentsMask;
    float dist;
    struct svEntity_s *entityLinkHead;
    struct worldSectorAreaLink_s *staticModelLinkHead;
    struct worldSector_s *parent;
    struct worldSector_s *children[CODUO_WORLD_SECTOR_CHILD_COUNT];
};

typedef worldSector_t
    coduo_world_sector_pool_t[CODUO_WORLD_SECTOR_POOL_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(worldSector_t) == 0x28,
               "worldSector_t size mismatch");
_Static_assert(sizeof(coduo_world_sector_pool_t) ==
                   1024 *
                       sizeof(worldSector_t),
               "coduo_world_sector_pool_t size mismatch");
_Static_assert(offsetof(worldSector_t, axis) ==
                   0x00,
               "worldSector_t.axis offset mismatch");
_Static_assert(offsetof(worldSector_t, staticModelContentsMask) ==
                   0x04,
               "worldSector_t.staticModelContentsMask offset mismatch");
_Static_assert(offsetof(worldSector_t, sightTraceStaticModelContentsMask) ==
                   0x08,
               "worldSector_t.sightTraceStaticModelContentsMask offset mismatch");
_Static_assert(offsetof(worldSector_t, entityContentsMask) ==
                   0x0c,
               "worldSector_t.entityContentsMask offset mismatch");
_Static_assert(offsetof(worldSector_t, dist) ==
                   0x10,
               "worldSector_t.dist offset mismatch");
_Static_assert(offsetof(worldSector_t, entityLinkHead) ==
                   0x14,
               "worldSector_t.entityLinkHead offset mismatch");
_Static_assert(offsetof(worldSector_t, staticModelLinkHead) ==
                   0x18,
               "worldSector_t.staticModelLinkHead offset mismatch");
_Static_assert(offsetof(worldSector_t, parent) ==
                   0x1c,
               "worldSector_t.parent offset mismatch");
_Static_assert(offsetof(worldSector_t, children) ==
                   0x20,
               "worldSector_t.children offset mismatch");
_Static_assert(sizeof(((worldSector_t *)0)->children) ==
                   2 *
                       sizeof(struct worldSector_s *),
               "worldSector_t.children size mismatch");
#endif

/*
 * Confirmed core hunk allocator state block.
 *
 * Evidence:
 * - Hunk_Clear at VA 0x806c31c clears words from lowMark +0x00 through
 *   highTemp +0x1c.
 * - Hunk_InitMemory at VA 0x806c0c7 writes totalSize +0x20.
 * - Hunk_SetTempMark/Hunk_ClearToTempMark save/restore lowTemp through +0x04.
 * - Hunk_Alloc/Hunk_AllocLow and temp allocation paths update the low/high
 *   used/temp counters below and compare their sum against totalSize.
 */
struct coduo_hunk_state_s {
    size_t lowMark;
    size_t lowTempMark;
    size_t lowUsed;
    size_t lowTemp;
    size_t highMark;
    size_t highTempMark;
    size_t highUsed;
    size_t highTemp;
    size_t totalSize;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_hunk_state_t) == 0x24,
               "coduo_hunk_state_t size mismatch");
_Static_assert(offsetof(coduo_hunk_state_t, lowMark) ==
                   0x00,
               "coduo_hunk_state_t.lowMark offset mismatch");
_Static_assert(offsetof(coduo_hunk_state_t, lowTempMark) ==
                   0x04,
               "coduo_hunk_state_t.lowTempMark offset mismatch");
_Static_assert(offsetof(coduo_hunk_state_t, lowUsed) ==
                   0x08,
               "coduo_hunk_state_t.lowUsed offset mismatch");
_Static_assert(offsetof(coduo_hunk_state_t, lowTemp) ==
                   0x0c,
               "coduo_hunk_state_t.lowTemp offset mismatch");
_Static_assert(offsetof(coduo_hunk_state_t, highMark) ==
                   0x10,
               "coduo_hunk_state_t.highMark offset mismatch");
_Static_assert(offsetof(coduo_hunk_state_t, highTempMark) ==
                   0x14,
               "coduo_hunk_state_t.highTempMark offset mismatch");
_Static_assert(offsetof(coduo_hunk_state_t, highUsed) ==
                   0x18,
               "coduo_hunk_state_t.highUsed offset mismatch");
_Static_assert(offsetof(coduo_hunk_state_t, highTemp) ==
                   0x1c,
               "coduo_hunk_state_t.highTemp offset mismatch");
_Static_assert(offsetof(coduo_hunk_state_t, totalSize) ==
                   0x20,
               "coduo_hunk_state_t.totalSize offset mismatch");
#endif

/*
 * Consumer-proven hunk debug log block.
 *
 * Evidence:
 * - Hunk_Log at VA 0x806bd84 walks the head pointer at VA 0x8238544 through
 *   next +0x08, summing size +0x00 and counting records.
 * - Hunk_SmallLog at VA 0x806bedd first clears byte +0x04 on every record,
 *   then marks grouped duplicate records by writing 1 to +0x04.
 * - The grouping test compares sourceLine +0x14 first and then strcmp's the
 *   sourceFile pointers at +0x10, accumulating matching sizes.
 * - No direct producer for hunk_logBlocks has been identified in the current
 *   immediate-reference scan. Quake III's exact hunkblock_t layout names
 *   +0x0c `label`; it is inherited but unused by coduo_lnxded.
 */
struct coduo_hunk_log_block_s {
    size_t size;
    uint8_t printed;
    uint8_t padding05[3];
    struct coduo_hunk_log_block_s *next;
    const char *label;
    const char *sourceFile;
    int32_t sourceLine;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_hunk_log_block_t) ==
                   0x18,
               "coduo_hunk_log_block_t size mismatch");
_Static_assert(offsetof(coduo_hunk_log_block_t, size) ==
                   0x00,
               "coduo_hunk_log_block_t.size offset mismatch");
_Static_assert(offsetof(coduo_hunk_log_block_t, printed) ==
                   0x04,
               "coduo_hunk_log_block_t.printed offset mismatch");
_Static_assert(offsetof(coduo_hunk_log_block_t, next) ==
                   0x08,
               "coduo_hunk_log_block_t.next offset mismatch");
_Static_assert(offsetof(coduo_hunk_log_block_t, label) ==
                   0x0c,
               "coduo_hunk_log_block_t.label offset mismatch");
_Static_assert(offsetof(coduo_hunk_log_block_t, sourceFile) ==
                   0x10,
               "coduo_hunk_log_block_t.sourceFile offset mismatch");
_Static_assert(offsetof(coduo_hunk_log_block_t, sourceLine) ==
                   0x14,
               "coduo_hunk_log_block_t.sourceLine offset mismatch");
#endif

/*
 * Confirmed header prepended to temporary low-hunk allocations.
 *
 * Evidence:
 * The original i386 binary uses a 0x10-byte header with uint32_t magic at +0x00
 * and a 32-bit size delta at +0x04. The host runtime keeps the same conceptual
 * fields but uses size_t for the delta so the temporary hunk cursor can be
 * restored without truncating a native allocation span.
 */
struct coduo_hunk_temp_header_s {
    uint32_t magic;
    size_t sizeDelta;
#if UINTPTR_MAX == UINT32_MAX
    uint8_t padding08[ (0x10) - (0x08)];
#endif
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_hunk_temp_header_t) ==
                   0x10,
               "coduo_hunk_temp_header_t size mismatch");
_Static_assert(offsetof(coduo_hunk_temp_header_t, magic) ==
                   0U,
               "coduo_hunk_temp_header_t.magic offset mismatch");
_Static_assert(offsetof(coduo_hunk_temp_header_t, sizeDelta) ==
                   sizeof(size_t),
               "coduo_hunk_temp_header_t.sizeDelta offset mismatch");
#endif

/*
 * Confirmed registered command linked-list node.
 *
 * Evidence:
 * - Cmd_AddCommand at VA 0x8060272 walks the list head at VA 0x82360a0
 *   through entry +0x00, compares the requested name against entry +0x04,
 *   allocates 0x0c bytes for new entries, stores a copied name at +0x04,
 *   stores the command function pointer at +0x08, then links the entry into
 *   the head pointer.
 */
struct cmd_function_s {
    cmd_function_t *next;
    char *name;
    coduo_cmd_function_fn handler;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(cmd_function_t) == 0x0c,
               "cmd_function_t size mismatch");
_Static_assert(offsetof(cmd_function_t, next) ==
                   0x00,
               "cmd_function_t.next offset mismatch");
_Static_assert(offsetof(cmd_function_t, name) ==
                   0x04,
               "cmd_function_t.name offset mismatch");
_Static_assert(offsetof(cmd_function_t, handler) ==
                   0x08,
               "cmd_function_t.handler offset mismatch");
#endif

/*
 * Confirmed command-buffer text record.
 *
 * Evidence:
 * - Cbuf_Init at VA 0x805f9d7 writes the backing buffer pointer at +0x00,
 *   maxsize 65,536 at +0x04, and cursize 0 at +0x08.
 * - Cbuf_AddText/Cbuf_InsertText compare and update cursize +0x08 against
 *   maxsize +0x04 while copying through data +0x00.
 * - Cbuf_Execute reads the same data/cursize fields and drains pending text.
 */
struct coduo_cmd_text_s {
    char *data;
    int32_t maxsize;
    int32_t cursize;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_cbuf_text_buffer_t) == 65536,
               "coduo_cbuf_text_buffer_t size mismatch");
_Static_assert(sizeof(coduo_cmd_text_t) == 0x0c,
               "coduo_cmd_text_t size mismatch");
_Static_assert(offsetof(coduo_cmd_text_t, data) ==
                   0x00,
               "coduo_cmd_text_t.data offset mismatch");
_Static_assert(offsetof(coduo_cmd_text_t, maxsize) ==
                   0x04,
               "coduo_cmd_text_t.maxsize offset mismatch");
_Static_assert(offsetof(coduo_cmd_text_t, cursize) ==
                   0x08,
               "coduo_cmd_text_t.cursize offset mismatch");
#endif

/*
 * Confirmed host netadr_t layout.
 *
 * Evidence:
 * - NET_AdrToString at VA 0x80848f8 switches on type at +0x00.
 * - IPv4 address bytes are formatted from +0x04..+0x07.
 * - The port is read as a 16-bit value at +0x12 and byte-swapped.
 * - NET_SendPacket passes the by-value netadr payload to sockaddr conversion
 *   using five 32-bit words, proving a 0x14-byte copy width.
 */
struct netadr_s {
    coduo_netadr_type_t type;
    uint8_t ip[4];
    uint8_t ipx[10];
    uint16_t port;
};

enum {
    CODUO_NETADR_SIZE = 0x14
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(netsrc_t) == sizeof(int32_t),
               "netsrc_t size mismatch");
_Static_assert(sizeof(coduo_netadr_type_t) == sizeof(int32_t),
               "coduo_netadr_type_t size mismatch");
_Static_assert(sizeof(netadr_t) == 0x14,
               "netadr_t size mismatch");
_Static_assert(offsetof(netadr_t, type) == 0x00,
               "netadr_t.type offset mismatch");
_Static_assert(offsetof(netadr_t, ip) == 0x04,
               "netadr_t.ip offset mismatch");
_Static_assert(sizeof(((netadr_t *)0)->ip) == 4,
               "netadr_t.ip size mismatch");
_Static_assert(offsetof(netadr_t, ipx) == 0x08,
               "netadr_t.ipx offset mismatch");
_Static_assert(sizeof(((netadr_t *)0)->ipx) == 10,
               "netadr_t.ipx size mismatch");
_Static_assert(offsetof(netadr_t, port) == 0x12,
               "netadr_t.port offset mismatch");
_Static_assert(sizeof(((netadr_t *)0)->port) ==
                   sizeof(uint16_t),
               "netadr_t.port size mismatch");
#endif

/*
 * Compact trace result shared by server collision trace work records and
 * module-facing trace outputs.
 *
 * Evidence:
 * - SV_Trace at VA 0x809afc9 clears a 0x30-byte local trace result, passes it
 *   to CM_BoxTrace/CM_TransformedBoxTrace, tests the float at +0x00, and
 *   copies 0x30 bytes to the caller result.
 * - SV_ClipMoveToEntity at VA 0x809a594 compares the embedded result
 *   fraction at work +0x3c, then copies 0x30 bytes from its local result over
 *   that embedded record when a closer entity hit is found.
 * - The same callback ORs byte masks at embedded result offsets +0x2e/+0x2f
 *   when the new trace is not closer.
 * - The game module's trace_t uses the same i386 0x30-byte ABI:
 *   fraction, endpos, normal, surface flags, contents, the collision material
 *   name at +0x24, 16-bit entity/part-name/part-group fields, and byte
 *   allsolid/startsolid flags.
 *
 * CM_TraceThroughPatch stores the address of a dshader_t at +0x24. Its
 * first member is shader[64], so this is the same collision-material-name
 * address used and dereferenced as text by the Windows client.
 */
struct trace_s {
    float fraction;
    vec3_t endpos;
    vec3_t normal;
    int32_t surfaceFlags;
    int32_t contents;
    const char *material;
    uint16_t entityNum;
    uint16_t partName;
    uint16_t partGroup;
    uint8_t allsolid;
    uint8_t startsolid;
};

/*
 * Quake III supplies the inherited sphere_t identity and member spellings.
 * Both shipped CoD engines retain its exact 0x18-byte descriptor, passed as
 * CM_Trace/CM_SightTrace's final argument by transformed trace wrappers.
 *
 * Evidence:
 * - CM_TransformedBoxTrace at VA 0x805b38b..0x805b4f0 builds a stack record
 *   with use +0x00, radius +0x04, halfheight +0x08, and offset +0x0c before
 *   passing its address as CM_Trace argument 9.
 * - CM_TransformedBoxSightTrace repeats the same record shape at
 *   VA 0x805d682..0x805d7dd before calling CM_SightTrace.
 */
struct sphere_s {
    int32_t use;
    float radius;
    float halfheight;
    vec3_t offset;
};

/*
 * BSP leaf prefix used by CM_LeafCluster and CM_LeafArea.
 *
 * Evidence:
 * - CM_LeafCluster at VA 0x804bd73..0x804bd80 indexes cm.leafs with a
 *   0x10-byte stride and sign-extends the int16_t at +0x00.
 * - CM_LeafArea at VA 0x804bd89..0x804bd96 uses the same stride and
 *   sign-extends the int16_t at +0x02.
 * - CM_PointContents at VA 0x8057602..0x8057628 reads the uint16_t
 *   numLeafBrushes at +0x08 and adds the int32_t firstLeafBrush at +0x04
 *   before indexing cm.leafbrushes.
 * - CM_TraceThroughLeaf at VA 0x8059943..0x805996a reads the
 *   uint16_t numLeafTerrainPatches at +0x0c and uint16_t
 *   firstLeafTerrainPatch at +0x0a before indexing cm.leafsurfaces.
 */
typedef struct coduo_collision_leaf_s {
    int16_t cluster;
    int16_t area;
    int32_t firstLeafBrush;
    uint16_t numLeafBrushes;
    uint16_t firstLeafTerrainPatch;
    uint16_t numLeafTerrainPatches;
    int16_t cellnum;
} coduo_collision_leaf_t;

/*
 * BSP node and plane prefixes used by point-leaf traversal and brush planes.
 *
 * Evidence:
 * - CM_PointLeafnum_r at VA 0x8057196..0x80571a8 indexes cm.nodes by an
 *   0x08-byte 32-bit record containing a plane pointer at +0x00 and child
 *   node numbers at +0x04/+0x06.
 * - The same function reads plane type byte +0x10, plane dist +0x0c, and for
 *   non-axial planes reads normal floats at +0x00/+0x04/+0x08.
 * - CM_TestBoxInBrush at VA 0x80581e4..0x805823f reads plane signbits
 *   byte +0x11 to select one of the trace work box offsets.
 * - CM_PointContents at VA 0x80576c0..0x80576ff reads brush side plane
 *   normal/dist through the side pointer.
 */
typedef struct coduo_collision_brush_side_s {
    const cplane_t *plane;
    int32_t materialIndex;
} coduo_collision_brush_side_t;

/*
 * Collision model prefix returned by CM_ClipHandleToModel.
 *
 * Evidence:
 * - CM_ClipHandleToModel at VA 0x804bc8a..0x804bc97 indexes cm.cmodels with a
 *   0x28-byte stride.
 * - CM_ModelBounds at VA 0x804bf47..0x804bf92 copies three float words from
 *   offsets +0x00/+0x04/+0x08 into mins and three from +0x0c/+0x10/+0x14 into
 *   maxs.
 * - CM_PointContents at VA 0x80575c4..0x80575ca treats cmodel +0x18 as an
 *   embedded leaf record when the caller passes a nonzero clip handle.
 */
typedef struct coduo_collision_model_s {
    vec3_t mins;
    vec3_t maxs;
    coduo_collision_leaf_t leaf;
} coduo_collision_model_t;

/*
 * Collision brush prefix touched by the temporary box-hull helpers and point
 * contents brush tests.
 *
 * Evidence:
 * - CM_InitBoxHull at VA 0x804bd9d computes cm.brushes[cm.numBrushes] with a
 *   0x34-byte stride, writes contents +0x00 to -1, clears +0x1c/+0x20, and
 *   sets six axial material indices at +0x28..+0x32 to -1.
 * - CM_TempBoxModel at VA 0x804bea1..0x804bf0a copies mins to +0x04..+0x0c,
 *   maxs to +0x10..+0x18, and contents to +0x00.
 * - CM_PointContents at VA 0x80576a6..0x805770c reads numSides from +0x1c and
 *   a brush-side pointer from +0x20.
 * - CM_TraceThroughLeaf at VA 0x80598c8..0x80598e0 compares and writes
 *   checkcount at +0x24 against the global cm.checkcount before tracing a
 *   brush.
 * - CM_TraceThroughBrush at VA 0x805906c..0x8059083 and
 *   0x80594e3..0x80594fa reads the signed 16-bit axial material index from
 *   +0x28 + 2 * (boundsPass * 3 + axis), while brush-side hits read a 32-bit
 *   material index at side +0x04.
 */
typedef struct coduo_collision_brush_s {
    int32_t contents;
    vec3_t mins;
    vec3_t maxs;
    int32_t numSides;
    coduo_collision_brush_side_t *sides;
    int32_t checkcount;
    int16_t axialMaterialIndices[6];
} coduo_collision_brush_t;

/*
 * Terrain patch prefix used by leaf trace walkers.
 *
 * Evidence:
 * - CM_TraceThroughLeaf at VA 0x805996d..0x8059981 scales a
 *   cm.leafsurfaces entry by 0x2c to index cm.terrainPatches.
 * - The same function compares/writes checkcount at +0x00 and masks contents
 *   at +0x08 before calling CM_TraceThroughPatch.
 * - CM_TraceThroughPatch at VA 0x8058e36..0x8058e4a passes mins at
 *   +0x0c and maxs at +0x18 to the trace bounds helper, then uses the
 *   material index at +0x04 and backend pointers at +0x24/+0x28.
 * - CM_LoadTerrainPatches at VA 0x804ae51 stores the plane/segment terrain
 *   backend (CM_GeneratePatchCollide, a 0x10-byte record) at +0x24 for
 *   collisionMode == 0 and the inline triangle/patch backend
 *   (CM_GenerateTerrainCollide, a 0x04-byte original prefix plus per-triangle
 *   facets) at +0x28 for the alternate mode.
 * - CM_TraceThroughPatch at VA 0x8058e30 checks +0x24 first: non-null
 *   dispatches to the plane/segment tracer at VA 0x80503b2, otherwise +0x28
 *   dispatches to the inline triangle/patch tracer at VA 0x8056ff5.
 */
typedef struct coduo_collision_terrain_patch_s {
    int32_t checkcount;
    int32_t materialIndex;
    int32_t contents;
    vec3_t mins;
    vec3_t maxs;
    const patchCollide_t *terrainCollide;
    const coduo_patch_collide_t *patchCollide;
} coduo_collision_terrain_patch_t;

/*
 * Quake III dshader_t retained verbatim as the CoD BSP material record.
 *
 * Evidence:
 * - CM_TraceThroughPatch at VA 0x8058eb4..0x8058f02 indexes the
 *   material table with a 0x48-byte stride, copies the word at +0x40 into
 *   trace surfaceFlags, and stores the material-record address in trace
 *   material.
 * - CoDUOMP CMod_LoadShaders and renderer R_LoadShaders retain the same full
 *   64-byte shader name followed by surfaceFlags and contentFlags.
 */
typedef struct dshader_s {
    char shader[64];
    int32_t surfaceFlags;
    int32_t contentFlags;
} dshader_t;

/*
 * Area flood state used by area-portal connectivity.
 *
 * Evidence:
 * - FloodArea_r at VA 0x8057896..0x80578a2 indexes cm.areas with an 0x08
 *   stride, reads floodvalid at +0x04, and compares/writes floodnum at +0x00.
 * - CM_AreasConnected at VA 0x8057adc..0x8057b02 compares the +0x00 floodnum
 *   fields for two area records.
 */
typedef struct coduo_collision_area_s {
    int32_t floodnum;
    int32_t floodvalid;
} coduo_collision_area_t;

typedef struct coduo_collision_node_s {
    const cplane_t *plane;
    int16_t children[2];
} coduo_collision_node_t;

/*
 * Local DObj trace result prefix consumed by SV_SightTraceThroughEntity.
 *
 * Evidence:
 * - The non-clientmodel DObj branch at VA 0x809aa45 calls the helper at
 *   VA 0x80c7394 with an output stack buffer at ebp-0x98.
 * - The caller compares fraction +0x00 against the embedded sight trace
 *   fraction, copies surface flags +0x04 to the broader trace's +0x1c field,
 *   maps normal +0x08 through the caller's transform path, copies 16-bit hit
 *   fields at +0x14/+0x16, and maps byte solid flags at +0x18/+0x19 to the
 *   broader trace's startsolid/allsolid bytes.
 * - DObjTraceParts at VA 0x80c7404 clears +0x04 and VA 0x80c7b5d writes
 *   only fraction, hit ids, and normal for closer hits; DObjTraceModelParts
 *   copies model trace-state +0x1c into compact result +0x04 at VA 0x80c7cec.
 * - SV_SightTraceThroughEntity copies compact +0x18 into collision trace
 *   +0x2f and compact +0x19 into collision trace +0x2e, proving the compact
 *   byte order is startsolid then allsolid.
 * - This is not the module-facing 0x30-byte trace_t prefix: the vec3 at +0x08
 *   is a normal-like vector, not an endpos, and the 16-bit hit fields are
 *   packed earlier.
 */
struct coduo_dobj_trace_result_s {
    float fraction;
    int32_t surfaceFlags;
    vec3_t normal;
    uint16_t hitPartNameHandle;
    uint16_t hitPartStateIndex;
    uint8_t startsolid;
    uint8_t allsolid;
};

/*
 * Server box/capsule trace work buffer passed through world-sector callbacks.
 * CoDUOMP.exe has the identical complete record as cmClipMoveWork_t.
 *
 * Evidence:
 * - SV_ClipMoveToEntity at VA 0x809a594 consumes mins +0x00, maxs +0x0c,
 *   start +0x24, end +0x30, embedded best trace +0x3c, pass entity +0x6c,
 *   pass owner +0x70, contents mask +0x74, and capsule flag +0x78.
 * - SV_Trace at VA 0x809b272..0x809b37a computes the vector at +0x18 as
 *   ((maxs - mins) * 0.5f) + 1.0f.
 * - The sector walker calls SV_ClipMoveToEntity from VA 0x805ec33 with this
 *   work pointer after CM_Trace/CM_BoxTrace has seeded the embedded result.
 *   Its area-node recursion reads traceWork +0x18 + axis*4 as the split-axis
 *   extent/radius for branch pruning.
 */
struct cmClipMoveWork_s {
    vec3_t mins;
    vec3_t maxs;
    vec3_t expandedHalfSize;
    vec3_t start;
    vec3_t end;
    trace_t bestTrace;
    int32_t passEntityNum;
    int32_t passOwnerNum;
    int32_t contentsMask;
    qboolean capsule;
};

/*
 * Server point-trace work buffer passed through world-sector callbacks.
 * CoDUOMP.exe has the identical complete record as cmPointTraceWork_t.
 *
 * Evidence:
 * - SV_SightTraceThroughEntity at VA 0x809a72a consumes start +0x00,
 *   end +0x0c, embedded best trace +0x18, pass entity +0x48, pass owner
 *   +0x4c, contents mask +0x50, and the optional DObj trace flag at +0x54.
 *   The non-clientmodel DObj branch also reads the part-state pointer at
 *   +0x58 before calling DObjTraceParts at VA 0x80c7394.
 * - The sector walker calls SV_SightTraceThroughEntity from VA 0x805f2ac.
 */
struct cmPointTraceWork_s {
    vec3_t start;
    vec3_t end;
    trace_t bestTrace;
    int32_t passEntityNum;
    int32_t passOwnerNum;
    int32_t contentsMask;
    qboolean useDObj;
    const uint8_t *dobjTracePartState;
};

/*
 * Compact point-sight work record consumed by CM_SightTrace and its area-entity
 * fallback callback.  The type name is shared with CoDUOMP; the Mac PEF does
 * not expose the private type but independently names the owning functions
 * CM_PointSightTraceToEntities[_r].
 *
 * Evidence:
 * - SV_SightTrace at VA 0x809b5a3..0x809b663 constructs this record at
 *   ebp-0x48 when mins/maxs collapse to a point: start +0x00, end +0x0c,
 *   pass entity/owner +0x18/+0x1c, derived owner skips +0x20/+0x24, and
 *   contents mask +0x28 before calling CM_SightTrace at VA 0x805f58c.
 * - CM_SightTrace's collision-tree recursion at VA 0x805f302 filters through
 *   contents mask +0x28 and its linked-entity callback at VA 0x809ae1e uses
 *   the two direct skip entities and their owner skips at +0x18..+0x24.
 */
struct cmPointSightTraceWork_s {
    vec3_t start;
    vec3_t end;
    int32_t passEntityNum;
    int32_t passOwnerNum;
    int32_t passEntityOwnerNum;
    int32_t passOwnerOwnerNum;
    int32_t contentsMask;
};

/*
 * Box/capsule sight work record built by SV_SightTrace before walking world
 * sectors.  The type name is shared with CoDUOMP.  In particular, "Clip" is
 * preferred over the former Linux-only "swept" reconstruction name because
 * the Mac PEF independently names the owning functions
 * CM_ClipSightTraceToEntities[_r].
 *
 * Evidence:
 * - SV_SightTrace at VA 0x809b674..0x809b8b7 constructs this record at
 *   ebp-0xa8 for non-zero bounds: relative mins/maxs +0x00/+0x0c,
 *   expanded half-size +0x18 for sector branch pruning, center-shifted
 *   start/end +0x24/+0x30, two direct skip entities +0x3c/+0x40, their
 *   owner skips +0x44/+0x48, contents mask +0x4c, and capsule mode +0x50.
 * - The swept sight sector walker at VA 0x805ec86 reads contents +0x4c and
 *   expanded half-size +0x18 + axis*4, then invokes the linked-entity
 *   callback at VA 0x809ac6d with the same record.
 */
struct cmClipSightTraceWork_s {
    vec3_t mins;
    vec3_t maxs;
    vec3_t expandedHalfSize;
    vec3_t start;
    vec3_t end;
    int32_t passEntityNum;
    int32_t passOwnerNum;
    int32_t passEntityOwnerNum;
    int32_t passOwnerOwnerNum;
    int32_t contentsMask;
    qboolean capsule;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(offsetof(trace_t, fraction) ==
                   0x00,
               "trace_t.fraction offset mismatch");
_Static_assert(offsetof(trace_t, endpos) ==
                   0x04,
               "trace_t.endpos offset mismatch");
_Static_assert(offsetof(trace_t, normal) ==
                   0x10,
               "trace_t.normal offset mismatch");
_Static_assert(offsetof(trace_t, surfaceFlags) ==
                   0x1c,
               "trace_t.surfaceFlags offset mismatch");
_Static_assert(offsetof(trace_t, contents) ==
                   0x20,
               "trace_t.contents offset mismatch");
_Static_assert(offsetof(trace_t, material) ==
                   0x24,
               "trace_t.material offset mismatch");
_Static_assert(sizeof(trace_t) ==
                   0x30,
               "trace_t size mismatch");
_Static_assert(offsetof(trace_t, entityNum) ==
                   0x28,
               "trace_t.entityNum offset mismatch");
_Static_assert(offsetof(trace_t, partName) ==
                   0x2a,
               "trace_t.partName offset mismatch");
_Static_assert(offsetof(trace_t, partGroup) ==
                   0x2c,
               "trace_t.partGroup offset mismatch");
_Static_assert(offsetof(trace_t, allsolid) ==
                   0x2e,
               "trace_t.allsolid offset mismatch");
_Static_assert(offsetof(trace_t, startsolid) ==
                   0x2f,
               "trace_t.startsolid offset mismatch");
_Static_assert(sizeof(sphere_t) ==
                   0x18,
               "sphere_t size mismatch");
_Static_assert(offsetof(sphere_t, use) ==
                   0x00,
               "sphere_t.use offset mismatch");
_Static_assert(offsetof(sphere_t, radius) ==
                   0x04,
               "sphere_t.radius offset mismatch");
_Static_assert(offsetof(sphere_t, halfheight) ==
                   0x08,
               "sphere_t.halfheight offset mismatch");
_Static_assert(offsetof(sphere_t, offset) ==
                   0x0c,
               "sphere_t.offset offset mismatch");
_Static_assert(sizeof(((sphere_t *)0)->offset) ==
                   sizeof(vec3_t),
               "sphere_t.offset size mismatch");
_Static_assert(sizeof(coduo_collision_model_t) == 0x28,
               "coduo_collision_model_t size mismatch");
_Static_assert(offsetof(coduo_collision_model_t, mins) == 0x00,
               "coduo_collision_model_t.mins offset mismatch");
_Static_assert(offsetof(coduo_collision_model_t, maxs) == 0x0c,
               "coduo_collision_model_t.maxs offset mismatch");
_Static_assert(offsetof(coduo_collision_model_t, leaf) == 0x18,
               "coduo_collision_model_t.leaf offset mismatch");
_Static_assert(sizeof(((coduo_collision_model_t *)0)->mins) ==
                   sizeof(vec3_t),
               "coduo_collision_model_t.mins size mismatch");
_Static_assert(sizeof(((coduo_collision_model_t *)0)->maxs) ==
                   sizeof(vec3_t),
               "coduo_collision_model_t.maxs size mismatch");
_Static_assert(offsetof(coduo_collision_brush_t, contents) == 0x00,
               "coduo_collision_brush_t.contents offset mismatch");
_Static_assert(offsetof(coduo_collision_brush_t, mins) == 0x04,
               "coduo_collision_brush_t.mins offset mismatch");
_Static_assert(offsetof(coduo_collision_brush_t, maxs) == 0x10,
               "coduo_collision_brush_t.maxs offset mismatch");
_Static_assert(offsetof(coduo_collision_brush_t, numSides) == 0x1c,
               "coduo_collision_brush_t.numSides offset mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_collision_brush_t) == 0x34,
               "coduo_collision_brush_t size mismatch");
_Static_assert(offsetof(coduo_collision_brush_t, sides) == 0x20,
               "coduo_collision_brush_t.sides offset mismatch");
_Static_assert(offsetof(coduo_collision_brush_t, checkcount) == 0x24,
               "coduo_collision_brush_t.checkcount offset mismatch");
_Static_assert(offsetof(coduo_collision_brush_t, axialMaterialIndices) ==
                   0x28,
               "coduo_collision_brush_t.axialMaterialIndices mismatch");
#endif
_Static_assert(offsetof(coduo_collision_brush_side_t, plane) == 0x00,
               "coduo_collision_brush_side_t.plane offset mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_collision_brush_side_t) == 0x08,
               "coduo_collision_brush_side_t size mismatch");
_Static_assert(offsetof(coduo_collision_brush_side_t, materialIndex) == 0x04,
               "coduo_collision_brush_side_t.materialIndex mismatch");
#endif
_Static_assert(sizeof(coduo_collision_leaf_t) == 0x10,
               "coduo_collision_leaf_t size mismatch");
_Static_assert(offsetof(coduo_collision_leaf_t, cluster) == 0x00,
               "coduo_collision_leaf_t.cluster offset mismatch");
_Static_assert(offsetof(coduo_collision_leaf_t, area) == 0x02,
               "coduo_collision_leaf_t.area offset mismatch");
_Static_assert(offsetof(coduo_collision_leaf_t, firstLeafBrush) == 0x04,
               "coduo_collision_leaf_t.firstLeafBrush offset mismatch");
_Static_assert(offsetof(coduo_collision_leaf_t, numLeafBrushes) == 0x08,
               "coduo_collision_leaf_t.numLeafBrushes offset mismatch");
_Static_assert(offsetof(coduo_collision_leaf_t, firstLeafTerrainPatch) == 0x0a,
               "coduo_collision_leaf_t.firstLeafTerrainPatch offset mismatch");
_Static_assert(offsetof(coduo_collision_leaf_t, numLeafTerrainPatches) == 0x0c,
               "coduo_collision_leaf_t.numLeafTerrainPatches offset mismatch");
_Static_assert(offsetof(coduo_collision_terrain_patch_t, checkcount) == 0x00,
               "coduo_collision_terrain_patch_t.checkcount offset mismatch");
_Static_assert(offsetof(coduo_collision_terrain_patch_t, materialIndex) ==
                   0x04,
               "coduo_collision_terrain_patch_t.materialIndex mismatch");
_Static_assert(offsetof(coduo_collision_terrain_patch_t, contents) == 0x08,
               "coduo_collision_terrain_patch_t.contents offset mismatch");
_Static_assert(offsetof(coduo_collision_terrain_patch_t, mins) == 0x0c,
               "coduo_collision_terrain_patch_t.mins offset mismatch");
_Static_assert(offsetof(coduo_collision_terrain_patch_t, maxs) == 0x18,
               "coduo_collision_terrain_patch_t.maxs offset mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_collision_terrain_patch_t) == 0x2c,
               "coduo_collision_terrain_patch_t size mismatch");
_Static_assert(offsetof(coduo_collision_terrain_patch_t, terrainCollide) ==
                   0x24,
               "coduo_collision_terrain_patch_t.terrainCollide mismatch");
_Static_assert(offsetof(coduo_collision_terrain_patch_t, patchCollide) ==
                   0x28,
               "coduo_collision_terrain_patch_t.patchCollide mismatch");
#endif
_Static_assert(sizeof(dshader_t) == 0x48,
               "dshader_t size mismatch");
_Static_assert(offsetof(dshader_t, surfaceFlags) ==
                   0x40,
               "dshader_t.surfaceFlags mismatch");
_Static_assert(offsetof(dshader_t, contentFlags) == 0x44,
               "dshader_t.contentFlags mismatch");
_Static_assert(sizeof(coduo_collision_area_t) == 0x08,
               "coduo_collision_area_t size mismatch");
_Static_assert(offsetof(coduo_collision_area_t, floodnum) == 0x00,
               "coduo_collision_area_t.floodnum offset mismatch");
_Static_assert(offsetof(coduo_collision_area_t, floodvalid) == 0x04,
               "coduo_collision_area_t.floodvalid offset mismatch");
_Static_assert(sizeof(coduo_dobj_trace_result_t) ==
                   0x1c,
               "coduo_dobj_trace_result_t size mismatch");
_Static_assert(offsetof(coduo_dobj_trace_result_t, fraction) ==
                   0x00,
               "coduo_dobj_trace_result_t.fraction offset mismatch");
_Static_assert(offsetof(coduo_dobj_trace_result_t, surfaceFlags) ==
                   0x04,
               "coduo_dobj_trace_result_t.surfaceFlags offset mismatch");
_Static_assert(offsetof(coduo_dobj_trace_result_t, normal) ==
                   0x08,
               "coduo_dobj_trace_result_t.normal offset mismatch");
_Static_assert(offsetof(coduo_dobj_trace_result_t, hitPartNameHandle) ==
                   0x14,
               "coduo_dobj_trace_result_t.hitPartNameHandle offset mismatch");
_Static_assert(offsetof(coduo_dobj_trace_result_t, hitPartStateIndex) ==
                   0x16,
               "coduo_dobj_trace_result_t.hitPartStateIndex offset mismatch");
_Static_assert(offsetof(coduo_dobj_trace_result_t, startsolid) ==
                   0x18,
               "coduo_dobj_trace_result_t.startsolid offset mismatch");
_Static_assert(offsetof(coduo_dobj_trace_result_t, allsolid) ==
                   0x19,
               "coduo_dobj_trace_result_t.allsolid offset mismatch");
_Static_assert(0x19 +
                       sizeof(uint8_t) ==
                   0x1a,
               "coduo_dobj_trace_result_t field end mismatch");
_Static_assert(sizeof(cmClipMoveWork_t) == 0x7c,
               "cmClipMoveWork_t prefix size mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, mins) ==
                   0x00,
               "cmClipMoveWork_t.mins offset mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, maxs) ==
                   0x0c,
               "cmClipMoveWork_t.maxs offset mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, expandedHalfSize) ==
                   0x18,
               "cmClipMoveWork_t.expandedHalfSize offset mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, start) ==
                   0x24,
               "cmClipMoveWork_t.start offset mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, end) ==
                   0x30,
               "cmClipMoveWork_t.end offset mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, bestTrace) ==
                   0x3c,
               "cmClipMoveWork_t.bestTrace offset mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, passEntityNum) ==
                   0x6c,
               "cmClipMoveWork_t.passEntityNum offset mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, passOwnerNum) ==
                   0x70,
               "cmClipMoveWork_t.passOwnerNum offset mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, contentsMask) ==
                   0x74,
               "cmClipMoveWork_t.contentsMask offset mismatch");
_Static_assert(offsetof(cmClipMoveWork_t, capsule) ==
                   0x78,
               "cmClipMoveWork_t.capsule offset mismatch");
_Static_assert(sizeof(cmPointTraceWork_t) == 0x5c,
               "cmPointTraceWork_t size mismatch");
_Static_assert(offsetof(cmPointTraceWork_t, start) ==
                   0x00,
               "cmPointTraceWork_t.start offset mismatch");
_Static_assert(offsetof(cmPointTraceWork_t, end) ==
                   0x0c,
               "cmPointTraceWork_t.end offset mismatch");
_Static_assert(offsetof(cmPointTraceWork_t, bestTrace) ==
                   0x18,
               "cmPointTraceWork_t.bestTrace offset mismatch");
_Static_assert(offsetof(cmPointTraceWork_t, passEntityNum) ==
                   0x48,
               "cmPointTraceWork_t.passEntityNum offset mismatch");
_Static_assert(offsetof(cmPointTraceWork_t, passOwnerNum) ==
                   0x4c,
               "cmPointTraceWork_t.passOwnerNum offset mismatch");
_Static_assert(offsetof(cmPointTraceWork_t, contentsMask) ==
                   0x50,
               "cmPointTraceWork_t.contentsMask offset mismatch");
_Static_assert(offsetof(cmPointTraceWork_t, useDObj) ==
                   0x54,
               "cmPointTraceWork_t.useDObj offset mismatch");
_Static_assert(offsetof(cmPointTraceWork_t,
                       dobjTracePartState) ==
                   0x58,
               "cmPointTraceWork_t.dobjTracePartState mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(cmPointSightTraceWork_t) ==
                   0x2c,
               "cmPointSightTraceWork_t size mismatch");
_Static_assert(offsetof(cmPointSightTraceWork_t, start) ==
                   0x00,
               "cmPointSightTraceWork_t.start mismatch");
_Static_assert(offsetof(cmPointSightTraceWork_t, end) ==
                   0x0c,
               "cmPointSightTraceWork_t.end mismatch");
_Static_assert(offsetof(cmPointSightTraceWork_t,
                       passEntityNum) ==
                   0x18,
               "cmPointSightTraceWork_t.passEntityNum mismatch");
_Static_assert(offsetof(cmPointSightTraceWork_t,
                       passOwnerNum) ==
                   0x1c,
               "cmPointSightTraceWork_t.passOwnerNum mismatch");
_Static_assert(offsetof(cmPointSightTraceWork_t,
                       passEntityOwnerNum) ==
                   0x20,
               "cmPointSightTraceWork_t.passEntityOwnerNum mismatch");
_Static_assert(offsetof(cmPointSightTraceWork_t,
                       passOwnerOwnerNum) ==
                   0x24,
               "cmPointSightTraceWork_t.passOwnerOwnerNum mismatch");
_Static_assert(offsetof(cmPointSightTraceWork_t,
                       contentsMask) ==
                   0x28,
               "cmPointSightTraceWork_t.contentsMask mismatch");
_Static_assert(sizeof(cmClipSightTraceWork_t) ==
                   0x54,
               "cmClipSightTraceWork_t size mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t, mins) ==
                   0x00,
               "cmClipSightTraceWork_t.mins mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t, maxs) ==
                   0x0c,
               "cmClipSightTraceWork_t.maxs mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t,
                       expandedHalfSize) ==
                   0x18,
               "cmClipSightTraceWork_t.expandedHalfSize mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t, start) ==
                   0x24,
               "cmClipSightTraceWork_t.start mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t, end) ==
                   0x30,
               "cmClipSightTraceWork_t.end mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t,
                       passEntityNum) ==
                   0x3c,
               "cmClipSightTraceWork_t.passEntityNum mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t,
                       passOwnerNum) ==
                   0x40,
               "cmClipSightTraceWork_t.passOwnerNum mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t,
                       passEntityOwnerNum) ==
                   0x44,
               "cmClipSightTraceWork_t.passEntityOwnerNum mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t,
                       passOwnerOwnerNum) ==
                   0x48,
               "cmClipSightTraceWork_t.passOwnerOwnerNum mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t,
                       contentsMask) ==
                   0x4c,
               "cmClipSightTraceWork_t.contentsMask mismatch");
_Static_assert(offsetof(cmClipSightTraceWork_t, capsule) ==
                   0x50,
               "cmClipSightTraceWork_t.capsule mismatch");
#endif
#endif

/*
 * Confirmed host-side layout facts for coduo_lnxded server data.
 *
 * Named counts and ring/buffer capacities in this block are shared with
 * runtime indexing or wrap logic. Original i386 record extents are asserted
 * directly on their typed declarations instead of repeated as source constants.
 */
enum {
    CODUO_HOST_CLIENT_RELIABLE_COMMAND_COUNT = CODUO_MAX_RELIABLE_COMMANDS,
    CODUO_HOST_CLIENT_DOWNLOAD_NAME_SIZE = CODUO_MAX_QPATH,
    CODUO_HOST_CLIENT_DOWNLOAD_BLOCK_COUNT = CODUO_MAX_DOWNLOAD_WINDOW,
    CODUO_HOST_CLIENT_SNAPSHOT_FRAME_COUNT = 32,
    CODUO_SHARED_ENTITY_VECTOR_COMPONENTS = 3,
    CODUO_SHARED_ENTITY_SVFLAG_NOCLIENT = 0x00000001,
    CODUO_SHARED_ENTITY_SVFLAG_LOOPED_FX = 0x00000008,
    CODUO_SHARED_ENTITY_SVFLAG_VISIBILITY_BYPASS_10 = 0x00000010,
    CODUO_SHARED_ENTITY_SVFLAG_SINGLECLIENT = 0x00000800,
    CODUO_SHARED_ENTITY_SVFLAG_NOTSINGLECLIENT = 0x00002000,
    CODUO_SHARED_ENTITY_SVFLAG_VISIBILITY_BYPASS_MASK =
        CODUO_SHARED_ENTITY_SVFLAG_LOOPED_FX |
        CODUO_SHARED_ENTITY_SVFLAG_VISIBILITY_BYPASS_10,
    CODUO_HOST_CHALLENGE_COUNT = CODUO_MAX_CHALLENGES,
    CODUO_AUTHORIZE_GUID_CACHE_ENTRY_COUNT = 16,

    CODUO_HOST_ENTITY_LINK_COUNT = CODUO_MAX_GENTITIES,
    CODUO_HOST_ENTITY_LINK_CLUSTER_NUM_COUNT = CODUO_MAX_ENT_CLUSTERS,
    CODUO_HOST_ENTITY_LINK_LINK_BOUNDS_COMPONENT_COUNT = 2,

    CODUO_HOST_ENTITY_STATE_EVENT_COUNT = 4,
    CODUO_HOST_ENTITY_STATE_EVENT_PARM_COUNT = 4,
    CODUO_HOST_CLIENT_SNAPSHOT_ATTACH_MODEL_COUNT = 6,
    CODUO_HOST_CLIENT_SNAPSHOT_ATTACH_TAG_COUNT = 6,
    CODUO_HOST_CACHED_SNAPSHOT_ENTITY_RING_COUNT = 0x4000,
    CODUO_HOST_CACHED_SNAPSHOT_CLIENT_RING_COUNT = 0x1000,
    CODUO_HOST_CACHED_SNAPSHOT_FRAME_RING_COUNT = 0x200,
    CODUO_HOST_ARCHIVED_SNAPSHOT_FRAME_INDEX_COUNT = 0x4b0,
    CODUO_HOST_ARCHIVED_SNAPSHOT_BUFFER_SIZE = 0x2000000,
    CODUO_HOST_ARCHIVED_PACKET_ENTITY_RING_COUNT =
        CODUO_HOST_CACHED_SNAPSHOT_ENTITY_RING_COUNT,
    CODUO_HOST_SNAPSHOT_ENTITY_RING_COUNT =
        CODUO_HOST_CACHED_SNAPSHOT_ENTITY_RING_COUNT,

    CODUO_FS_HANDLE_TABLE_COUNT = 64,
    CODUO_FS_HANDLE_NAME_SIZE = 0x100,
    CODUO_HOST_CONFIGSTRING_COUNT = CODUO_MAX_CONFIGSTRINGS,
    CODUO_HOST_CONFIGSTRING_SERVERINFO_INDEX = 0,
    CODUO_HOST_CONFIGSTRING_SYSTEMINFO_INDEX = 1,
    CODUO_HOST_CONFIGSTRING_SYSTEMINFO_KV_BASE = 0x95,
    CODUO_HOST_CONFIGSTRING_SYSTEMINFO_KV_COUNT = 0x80
};

/*
 * Confirmed game/shared-entity sparse offsets consumed by the host.
 *
 * Evidence:
 * - SV_LinkEntity at VA 0x8099dee receives a module gentity pointer, derives
 *   the host entity-link record with SV_SvEntityForGentity, and separately
 *   reads/writes these gentity offsets for collision/linking state.
 * - SV_ClipHandleForEntity at VA 0x8099ca0 reads bmodel +0x104, svFlags
 *   +0x0f8, mins/maxs +0x108/+0x114, and contents +0x120.
 * - Snapshot paths at VA 0x8096d0d, VA 0x80992f5, and VA 0x8099730
 *   consume soundTime +0x100, force svFlags bit 0x8 while it is active, and
 *   clear positive expired values against svs.time.
 */

typedef char *
    coduo_host_configstring_table_t[CODUO_HOST_CONFIGSTRING_COUNT];
typedef uint8_t
    coduo_archived_snapshot_buffer_t
        [CODUO_HOST_ARCHIVED_SNAPSHOT_BUFFER_SIZE];
typedef char
    coduo_host_www_download_url_t
        [0x100];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_host_configstring_table_t) ==
                   2048 * sizeof(char *),
               "coduo_host_configstring_table_t size mismatch");
_Static_assert(sizeof(coduo_archived_snapshot_buffer_t) ==
                   0x2000000,
               "coduo_archived_snapshot_buffer_t size mismatch");
_Static_assert(sizeof(coduo_host_client_userinfo_t) ==
                   0x400,
               "coduo_host_client_userinfo_t size mismatch");
_Static_assert(sizeof(coduo_host_client_name_t) ==
                   32,
               "coduo_host_client_name_t size mismatch");
_Static_assert(sizeof(coduo_host_client_command_string_t) ==
                    1024,
               "coduo_host_client_command_string_t size mismatch");
_Static_assert(sizeof(coduo_host_download_name_t) ==
                   64,
               "coduo_host_download_name_t size mismatch");
_Static_assert(sizeof(coduo_host_www_download_url_t) ==
                   0x100,
               "coduo_host_www_download_url_t size mismatch");
#endif

/*
 * Confirmed `sv` prefix.
 *
 * Evidence:
 * - Map transition code writes state +0x00 as loading/game.
 * - Restart paths read restarting +0x04.
 * - Server-id cache reads/writes use +0x08 before the configstring table.
 * - SV_ParseUsercmds at VA 0x808d939 and SV_SendClientGameState at
 *   VA 0x808be90 use gamestateChecksumFeed +0x0c.
 */
struct coduo_host_sv_prefix_s {
    coduo_server_state_t state;
    qboolean restarting;
    int32_t serverId;
    int32_t gamestateChecksumFeed;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_host_sv_prefix_t) == 0x10,
               "coduo_host_sv_prefix_t size mismatch");
_Static_assert(offsetof(coduo_host_sv_prefix_t, state) ==
                   0x00,
               "coduo_host_sv_prefix_t.state offset mismatch");
_Static_assert(offsetof(coduo_host_sv_prefix_t, restarting) ==
                   0x04,
               "coduo_host_sv_prefix_t.restarting offset mismatch");
_Static_assert(offsetof(coduo_host_sv_prefix_t, serverId) ==
                   0x08,
               "coduo_host_sv_prefix_t.serverId offset mismatch");
_Static_assert(offsetof(coduo_host_sv_prefix_t, gamestateChecksumFeed) ==
                   0x0c,
               "coduo_host_sv_prefix_t.gamestateChecksumFeed offset mismatch");
#endif

/*
 * Confirmed SV_LocateGameData storage block.
 *
 * Evidence:
 * - LOCATE_GAME_DATA syscall ID 24 stores the game-module entity base,
 *   entity stride/count, game-client player-state base, and game-client stride
 *   here.
 * - SV_NumForGentity/SV_GentityNum/SV_GameClientNum consume these globals
 *   for pointer arithmetic at the engine/game boundary.
 */
struct coduo_host_game_data_globals_s {
    sharedEntity_t *gentities;
    int32_t gentitySize;
    int32_t numGEntities;
    playerState_t *clients;
    int32_t clientSize;
};

/*
 * Confirmed server-static header from svs base through the challenge table.
 *
 * Evidence:
 * - SV_Startup at VA 0x8091473 checks initialized +0x00, allocates clients
 *   into +0x10, stores live snapshot counts at +0x14/+0x18, and sets
 *   initialized when startup succeeds.
 * - SV_SpawnServer paths allocate live snapshot rings through +0x24/+0x28
 *   and reset next indexes +0x1c/+0x20.
 * - Archive/cached snapshot setup writes +0x34/+0x38 and +0x4c/+0x50/+0x54;
 *   status/heartbeat code uses +0x58/+0x5c.
 * - The challenge array begins immediately after this header at +0x60.
 */
struct coduo_host_svs_header_s {
    qboolean initialized;
    int32_t time;
    int32_t timeSecondary;
    int32_t snapFlagServerBit;
    struct client_s *clients;
    int32_t numEntityStateSnapshots;
    int32_t numClientSnapshots;
    int32_t nextEntityStateSnapshot;
    int32_t nextClientSnapshot;
    struct coduo_host_snapshot_entity_record_s *entityStateSnapshots;
    struct coduo_host_client_snapshot_s *clientSnapshots;
    qboolean archiveEnabled;
    int32_t nextArchivedSnapshotFrames;
    archivedSnapshotFrameIndex_t *archivedSnapshotFrames;
    uint8_t *archivedSnapshotBuffer;
    int32_t nextArchivedSnapshotBuffer;
    int32_t nextCachedSnapshotEntities;
    int32_t nextCachedSnapshotClients;
    int32_t nextCachedSnapshotFrames;
    struct coduo_host_snapshot_entity_s *cachedSnapshotEntities;
    struct serverCachedSnapshotClient_s *cachedSnapshotClients;
    struct serverCachedSnapshotFrame_s *cachedSnapshotFrames;
    int32_t nextHeartbeatTime;
    int32_t nextStatusResponseTime;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_host_svs_header_t) == 0x60,
               "coduo_host_svs_header_t size mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, initialized) ==
                   0x00,
               "coduo_host_svs_header_t.initialized offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, time) ==
                   0x04,
               "coduo_host_svs_header_t.time offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, timeSecondary) ==
                   0x08,
               "coduo_host_svs_header_t.timeSecondary offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, snapFlagServerBit) ==
                   0x0c,
               "coduo_host_svs_header_t.snapFlagServerBit offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, clients) ==
                   0x10,
               "coduo_host_svs_header_t.clients offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, numEntityStateSnapshots) ==
                   0x14,
               "coduo_host_svs_header_t.numEntityStateSnapshots mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, numClientSnapshots) ==
                   0x18,
               "coduo_host_svs_header_t.numClientSnapshots offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, nextEntityStateSnapshot) ==
                   0x1c,
               "coduo_host_svs_header_t.nextEntityStateSnapshot mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, nextClientSnapshot) ==
                   0x20,
               "coduo_host_svs_header_t.nextClientSnapshot offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, entityStateSnapshots) ==
                   0x24,
               "coduo_host_svs_header_t.entityStateSnapshots mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, clientSnapshots) ==
                   0x28,
               "coduo_host_svs_header_t.clientSnapshots offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, archiveEnabled) ==
                   0x2c,
               "coduo_host_svs_header_t.archiveEnabled offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t,
                       nextArchivedSnapshotFrames) ==
                   0x30,
               "coduo_host_svs_header_t.nextArchivedSnapshotFrames mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, archivedSnapshotFrames) ==
                   0x34,
               "coduo_host_svs_header_t.archivedSnapshotFrames mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, archivedSnapshotBuffer) ==
                   0x38,
               "coduo_host_svs_header_t.archivedSnapshotBuffer mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t,
                       nextArchivedSnapshotBuffer) ==
                   0x3c,
               "coduo_host_svs_header_t.nextArchivedSnapshotBuffer mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t,
                       nextCachedSnapshotEntities) ==
                   0x40,
               "coduo_host_svs_header_t.nextCachedSnapshotEntities mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, nextCachedSnapshotClients) ==
                   0x44,
               "coduo_host_svs_header_t.nextCachedSnapshotClients mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, nextCachedSnapshotFrames) ==
                   0x48,
               "coduo_host_svs_header_t.nextCachedSnapshotFrames mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, cachedSnapshotEntities) ==
                   0x4c,
               "coduo_host_svs_header_t.cachedSnapshotEntities mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, cachedSnapshotClients) ==
                   0x50,
               "coduo_host_svs_header_t.cachedSnapshotClients mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, cachedSnapshotFrames) ==
                   0x54,
               "coduo_host_svs_header_t.cachedSnapshotFrames mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, nextHeartbeatTime) ==
                   0x58,
               "coduo_host_svs_header_t.nextHeartbeatTime offset mismatch");
_Static_assert(offsetof(coduo_host_svs_header_t, nextStatusResponseTime) ==
                   0x5c,
               "coduo_host_svs_header_t.nextStatusResponseTime mismatch");
#endif

typedef struct trajectory_s {
    coduo_tr_type_t trType;
    int32_t trTime;
    int32_t trDuration;
    vec3_t trBase;
    vec3_t trDelta;
} trajectory_t;

typedef union coduo_host_entity_state_angles2_u {
    vec3_t raw;
    struct {
        float x;
        float y;
        float z;
    } vector;
    struct {
        float scale;
        float radius;
        float durationMs;
    } earthquake;
    struct {
        float primaryPitch;
        float primaryYaw;
        float gunnerPitch;
    } vehicleTurret;
    struct {
        float pitch;
        float yaw;
        float pitchCarry;
    } turret;
    struct {
        float cullDistance;
        float repeatDelayMs;
        float unused70;
    } loopedFx;
    struct {
        float unused68;
        float leanAmount;
        float unused70;
    } clientInfo;
} coduo_host_entity_state_angles2_t;

typedef union coduo_host_entity_anim_payload_u {
    struct {
        int32_t legsAnim;
        int32_t torsoAnim;
    } playerAnim;
    struct {
        int32_t weaponAnim;
        int32_t followClient;
    } surfaceImpact;
    int32_t raw[2];
} coduo_host_entity_anim_payload_t;

typedef struct coduo_host_entity_state_snapshot_s {
    int32_t s_number;
    int32_t s_eType;
    uint32_t s_flags;
    trajectory_t pos;
    trajectory_t apos;
    int32_t entityStateTime;
    int32_t entityStateTime2;
    vec3_t loopedFxForward;
    coduo_host_entity_state_angles2_t entityStateAngles2;
    int32_t vehicleEntityNum;
    int32_t vehicleSlot;
    int32_t groundEntityNum;
    uint32_t constantLight;
    int32_t clientSound;
    int32_t eventParm;
    int32_t itemIndex;
    int32_t dobjModelIndexCopy;
    int32_t clientNum;
    int32_t headIcon;
    int32_t headIconTeam;
    int32_t solid;
    int32_t tempEffectId;
    int32_t eventCount;
    int32_t events[CODUO_HOST_ENTITY_STATE_EVENT_COUNT];
    int32_t
        eventParms[CODUO_HOST_ENTITY_STATE_EVENT_PARM_COUNT];
    int32_t weapon;
    coduo_host_entity_anim_payload_t anim;
    float clientInfoLeanFraction;
    int32_t hintStringIndex;
    int32_t cursorHint;
    int32_t turretOverheatState;
    vec3_t entityAngles;
} coduo_host_entity_state_snapshot_t;

typedef struct coduo_host_client_snapshot_s {
    int32_t clientNum;
    int32_t sessionTeam;
    int32_t baseModelIndex;
    int32_t attachModelIndices[CODUO_HOST_CLIENT_SNAPSHOT_ATTACH_MODEL_COUNT];
    int32_t attachTagIndices[CODUO_HOST_CLIENT_SNAPSHOT_ATTACH_TAG_COUNT];
    char userInfoName[0x20];
} coduo_host_client_snapshot_t;

typedef playerState_t coduo_archived_client_info_player_state_t;
typedef coduo_host_client_snapshot_t coduo_archived_client_info_meta_t;

typedef struct coduo_host_snapshot_entity_s {
    coduo_host_entity_state_snapshot_t entityState;
    int32_t flags;
    int32_t ownerNum;
    float clipMins[3];
    float clipMaxs[3];
} coduo_host_snapshot_entity_t;

typedef coduo_host_snapshot_entity_t coduo_host_entity_baseline_t;

/*
 * Host-visible prefix of the game/shared entity record.
 *
 * Evidence:
 * - SV_CreateBaseline copies the 0xf4-byte entity-state prefix from the
 *   module gentity into host baselines.
 * - SV_LinkEntity at VA 0x8099dee reads/writes linked, currentOrigin,
 *   currentAngles, mins/maxs, absmin/absmax, and contents through these
 *   offsets on the module gentity pointer.
 * - SV_ClipHandleForEntity at VA 0x8099ca0 reads bmodel, svFlags, bounds,
 *   and contents at the offsets below.
 * - SV_CreateBaseline at VA 0x809127f copies ownerNum +0x0fc into the host
 *   baseline owner slot at VA 0x8091317, matching cached snapshot copies at
 *   VA 0x8099307 and VA 0x8099763.
 * - Snapshot paths at VA 0x8096d0d, VA 0x80992f5, and VA 0x8099730 consume
 *   soundTime +0x100, force svFlags bit 0x8 while it is active, and clear
 *   positive expired values against svs.time. SV_AddEntitiesVisibleFromPoint at
 *   VA 0x8096c7a filters bit 0x1 unconditionally, gates bit 0x800 to
 *   ownerNum == clientNum, gates bit 0x2000 to ownerNum != clientNum, and
 *   bypasses cluster/PVS checks for mask 0x18. The recovered game module names
 *   this field soundTime and writes it from playsound/playloopsound/
 *   stoploopsound script methods.
 * - SV_SightTrace at VA 0x809b5fa and VA 0x809b630 reads traceOwnerNum
 *   +0x154 for the pass-entity owner skip fields used by sight traces.
 */
struct sharedEntity_s {
    coduo_host_entity_state_snapshot_t entityState;
    qboolean linked;
    uint32_t svFlags;
    int32_t ownerNum;
    int32_t soundTime;
    qboolean bmodel;
    vec3_t mins;
    vec3_t maxs;
    int32_t contents;
    vec3_t absMin;
    vec3_t absMax;
    vec3_t currentOrigin;
    vec3_t currentAngles;
    int32_t traceOwnerNum;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(sharedEntity_t) ==
                   0x158,
               "sharedEntity_t host-visible size mismatch");
_Static_assert(offsetof(sharedEntity_t, entityState) ==
                   0x000,
               "sharedEntity_t.entityState offset mismatch");
_Static_assert(sizeof(((sharedEntity_t *)0)->entityState) ==
                   sizeof(coduo_host_entity_state_snapshot_t),
               "sharedEntity_t.entityState size mismatch");
_Static_assert(offsetof(sharedEntity_t, linked) ==
                   0x0f4,
               "sharedEntity_t.linked offset mismatch");
_Static_assert(offsetof(sharedEntity_t, svFlags) ==
                   0x0f8,
               "sharedEntity_t.svFlags offset mismatch");
_Static_assert(sizeof(((sharedEntity_t *)0)->svFlags) ==
                   sizeof(uint32_t),
               "sharedEntity_t.svFlags size mismatch");
_Static_assert(offsetof(sharedEntity_t, ownerNum) ==
                   0x0fc,
               "sharedEntity_t.ownerNum offset mismatch");
_Static_assert(offsetof(sharedEntity_t, soundTime) ==
                   0x100,
               "sharedEntity_t.soundTime offset mismatch");
_Static_assert(offsetof(sharedEntity_t, bmodel) ==
                   0x104,
               "sharedEntity_t.bmodel offset mismatch");
_Static_assert(offsetof(sharedEntity_t, mins) ==
                   0x108,
               "sharedEntity_t.mins offset mismatch");
_Static_assert(sizeof(((sharedEntity_t *)0)->mins) ==
                    3 * sizeof(float),
               "sharedEntity_t.mins size mismatch");
_Static_assert(offsetof(sharedEntity_t, maxs) ==
                   0x114,
               "sharedEntity_t.maxs offset mismatch");
_Static_assert(offsetof(sharedEntity_t, contents) ==
                   0x120,
               "sharedEntity_t.contents offset mismatch");
_Static_assert(offsetof(sharedEntity_t, absMin) ==
                   0x124,
               "sharedEntity_t.absMin offset mismatch");
_Static_assert(offsetof(sharedEntity_t, absMax) ==
                   0x130,
               "sharedEntity_t.absMax offset mismatch");
_Static_assert(offsetof(sharedEntity_t, currentOrigin) ==
                   0x13c,
               "sharedEntity_t.currentOrigin offset mismatch");
_Static_assert(offsetof(sharedEntity_t, currentAngles) ==
                   0x148,
               "sharedEntity_t.currentAngles offset mismatch");
_Static_assert(offsetof(sharedEntity_t, traceOwnerNum) ==
                   0x154,
               "sharedEntity_t.traceOwnerNum offset mismatch");
#endif

/*
 * Confirmed host-side entity-link record.
 *
 * Evidence:
 * - SV_SvEntityForGentity/SV_GEntityForSvEntity convert between game gentity
 *   numbers and the host svEntity_t array using a 0x180-byte stride.
 * - SV_UnlinkEntity and world-sector helpers consume world-sector links at
 *   +0x00/+0x04.
 * - SV_CreateBaseline copies 0xf4 bytes of game entity state to the baseline
 *   at +0x008, then copies svFlags/owner/bounds into the following 0x20
 *   bytes. This is the same 0x114-byte shape used by cached snapshot
 *   entities.
 * - SV_LinkEntity at VA 0x8099dee writes cluster/area fields through the
 *   SV_SvEntityForGentity result: numClusters +0x11c, clusterNums[n] at
 *   +0x120 + n * 4 capped at 16 entries, lastCluster +0x160, and area nums
 *   +0x164/+0x168. The linked/origin/bounds fields touched in the same
 *   function are on the game/shared entity pointer, not this host record.
 * - SV_LinkEntityToWorldSector at VA 0x805de1a caches the entity contents mask
 *   at +0x16c and the 2D mins/maxs used for world-sector placement at
 *   +0x170/+0x178. SV_UnlinkEntityFromWorldSector at VA 0x805d9df consumes the
 *   cached contents mask while recomputing parent-sector contents.
 */
struct svEntity_s {
    struct worldSector_s *worldSector;
    struct svEntity_s *nextInWorldSector;
    coduo_host_entity_baseline_t baseline;
    int32_t numClusters;
    int32_t
        clusterNums[CODUO_HOST_ENTITY_LINK_CLUSTER_NUM_COUNT];
    int32_t lastCluster;
    int32_t areaNum;
    int32_t areaNum2;
    int32_t contentsMask;
    float
        linkMins[CODUO_HOST_ENTITY_LINK_LINK_BOUNDS_COMPONENT_COUNT];
    float
        linkMaxs[CODUO_HOST_ENTITY_LINK_LINK_BOUNDS_COMPONENT_COUNT];
};

typedef svEntity_t
    coduo_host_entity_link_table_t[CODUO_HOST_ENTITY_LINK_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(svEntity_t) ==
                   0x180,
               "svEntity_t size mismatch");
_Static_assert(sizeof(coduo_host_entity_link_table_t) ==
                   1024 *
                       sizeof(svEntity_t),
               "coduo_host_entity_link_table_t size mismatch");
_Static_assert(offsetof(svEntity_t, worldSector) ==
                   0x000,
               "svEntity_t.worldSector offset mismatch");
_Static_assert(offsetof(svEntity_t, nextInWorldSector) ==
                   0x004,
               "svEntity_t.nextInWorldSector offset mismatch");
_Static_assert(offsetof(svEntity_t, baseline) ==
                   0x008,
               "svEntity_t.baseline offset mismatch");
_Static_assert(sizeof(((svEntity_t *)0)->baseline) ==
                   0x114,
               "svEntity_t.baseline size mismatch");
_Static_assert(offsetof(svEntity_t, numClusters) ==
                   0x11c,
               "svEntity_t.numClusters offset mismatch");
_Static_assert(offsetof(svEntity_t, clusterNums) ==
                   0x120,
               "svEntity_t.clusterNums offset mismatch");
_Static_assert(sizeof(((svEntity_t *)0)->clusterNums) ==
                   16 *
                       sizeof(int32_t),
               "svEntity_t.clusterNums size mismatch");
_Static_assert(offsetof(svEntity_t, lastCluster) ==
                   0x160,
               "svEntity_t.lastCluster offset mismatch");
_Static_assert(offsetof(svEntity_t, areaNum) ==
                   0x164,
               "svEntity_t.areaNum offset mismatch");
_Static_assert(offsetof(svEntity_t, areaNum2) ==
                   0x168,
               "svEntity_t.areaNum2 offset mismatch");
_Static_assert(offsetof(svEntity_t, contentsMask) ==
                   0x16c,
               "svEntity_t.contentsMask offset mismatch");
_Static_assert(offsetof(svEntity_t, linkMins) ==
                   0x170,
               "svEntity_t.linkMins offset mismatch");
_Static_assert(sizeof(((svEntity_t *)0)->linkMins) ==
                   2 *
                       sizeof(float),
               "svEntity_t.linkMins size mismatch");
_Static_assert(offsetof(svEntity_t, linkMaxs) ==
                   0x178,
               "svEntity_t.linkMaxs offset mismatch");
_Static_assert(sizeof(((svEntity_t *)0)->linkMaxs) ==
                   2 *
                       sizeof(float),
               "svEntity_t.linkMaxs size mismatch");
#endif

/*
 * Confirmed filesystem handle-table slot layout.
 *
 * Evidence:
 * - FS_FileForHandle at VA 0x80608d4 indexes fs_handleFiles by handle *
 *   the 0x120-byte slot stride and returns the IO object at +0x00.
 * - FS_FOpenFileByMode at VA 0x8065d85 fills position +0x0c, size +0x10,
 *   and sync +0x08.
 * - FS_Read/FS_Write at VA 0x8062853/0x8062983 use the IO object +0x00,
 *   pack-owner pointer +0x18, and sync flag +0x08.
 * - FS_FOpenFileRead at VA 0x8061a74 writes the pack-owner pointer +0x18
 *   and zip rewind offset +0x14. FS_Seek at VA 0x8062ad4 passes +0x14 to
 *   the zip stream rewind helper before replaying reads for backward seeks.
 * - FS_Seek at VA 0x8062ad4 toggles +0x1c around its seek callback thunk,
 *   making it a seek callback/reentry guard.
 * - FS_FCloseFile at VA 0x80610d6 checks seekCallbackGuard +0x1c,
 *   zipArchive +0x18, and uniqueObject +0x04 before clearing the full
 *   0x120-byte slot.
 * - Write/append open paths copy the opened path/name to +0x20 with a
 *   0x100-byte bound.
 */
typedef char coduo_fs_handle_name_t[CODUO_FS_HANDLE_NAME_SIZE];

struct fileHandleData_s {
    void *ioObject;
    qboolean uniqueObject;
    qboolean sync;
    long position;
    long size;
    int32_t zipRewindOffset;
    pack_t *zipArchive;
    qboolean seekCallbackGuard;
    coduo_fs_handle_name_t name;
};

typedef fileHandleData_t
    coduo_fs_handle_table_t[CODUO_FS_HANDLE_TABLE_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(fileHandleData_t) == 0x120,
               "fileHandleData_t size mismatch");
_Static_assert(sizeof(coduo_fs_handle_table_t) ==
                   64 * 0x120,
               "coduo_fs_handle_table_t size mismatch");
_Static_assert(offsetof(fileHandleData_t, ioObject) ==
                   0x00,
               "fileHandleData_t.ioObject offset mismatch");
_Static_assert(offsetof(fileHandleData_t, uniqueObject) ==
                   0x04,
               "fileHandleData_t.uniqueObject offset mismatch");
_Static_assert(offsetof(fileHandleData_t, sync) ==
                   0x08,
               "fileHandleData_t.sync offset mismatch");
_Static_assert(offsetof(fileHandleData_t, position) ==
                   0x0c,
               "fileHandleData_t.position offset mismatch");
_Static_assert(offsetof(fileHandleData_t, size) ==
                   0x10,
               "fileHandleData_t.size offset mismatch");
_Static_assert(offsetof(fileHandleData_t, zipRewindOffset) ==
                   0x14,
               "fileHandleData_t.zipRewindOffset offset mismatch");
_Static_assert(offsetof(fileHandleData_t, zipArchive) ==
                   0x18,
               "fileHandleData_t.zipArchive offset mismatch");
_Static_assert(offsetof(fileHandleData_t, seekCallbackGuard) ==
                   0x1c,
               "fileHandleData_t.seekCallbackGuard offset mismatch");
_Static_assert(sizeof(coduo_fs_handle_name_t) == 0x100,
               "coduo_fs_handle_name_t size mismatch");
_Static_assert(offsetof(fileHandleData_t, name) ==
                   0x20,
               "fileHandleData_t.name offset mismatch");
#endif

/*
 * Confirmed net profile allocation layout.
 *
 * Evidence:
 * - The net profile enable helper at VA 0x8083884 allocates and clears
 *   0x5e0 bytes for a profile object when net_profile is enabled.
 * - The sample append helper at VA 0x8083973 maintains a 60-entry ring:
 *   each 0x0c-byte sample stores timestamp +0x00, byte count +0x04, and a
 *   fragmented flag +0x08; the stream ring index is at +0x2d0.
 * - The stream summary helper at VA 0x8083b00 walks those 60 samples and
 *   writes derived counters/rates at +0x2d4..+0x2ec.
 * - Netchan transmit profiling passes the profile base as the send stream;
 *   receive profiling passes profile +0x2f0, proving the two-stream object.
 */
struct netProfileSample_s {
    int32_t time;
    int32_t bytes;
    qboolean fragmented;
};

struct netProfileStream_s {
    netProfileSample_t samples[CODUO_NET_PROFILE_SAMPLE_COUNT];
    int32_t ringIndex;
    int32_t bytesPerSecond;
    int32_t lastRateCalcTime;
    int32_t sampleCount;
    int32_t fragmentSampleCount;
    int32_t fragmentPercent;
    int32_t maxBytes;
    int32_t minBytes;
};

struct netProfileInfo_s {
    netProfileStream_t send;
    netProfileStream_t receive;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(netProfileSample_t) ==
                   0x0c,
               "netProfileSample_t size mismatch");
_Static_assert(offsetof(netProfileSample_t, time) ==
                   0x00,
               "netProfileSample_t.time offset mismatch");
_Static_assert(offsetof(netProfileSample_t, bytes) ==
                   0x04,
               "netProfileSample_t.bytes offset mismatch");
_Static_assert(offsetof(netProfileSample_t, fragmented) ==
                   0x08,
               "netProfileSample_t.fragmented offset mismatch");
_Static_assert(sizeof(netProfileStream_t) ==
                   0x2f0,
               "netProfileStream_t size mismatch");
_Static_assert(offsetof(netProfileStream_t, samples) ==
                   0x000,
               "netProfileStream_t.samples offset mismatch");
_Static_assert(sizeof(((netProfileStream_t *)0)->samples) ==
                   60 *
                       0x0c,
               "netProfileStream_t.samples size mismatch");
_Static_assert(offsetof(netProfileStream_t, ringIndex) ==
                   0x2d0,
               "netProfileStream_t.ringIndex offset mismatch");
_Static_assert(offsetof(netProfileStream_t, bytesPerSecond) ==
                   0x2d4,
               "netProfileStream_t.bytesPerSecond offset mismatch");
_Static_assert(offsetof(netProfileStream_t, lastRateCalcTime) ==
                   0x2d8,
               "netProfileStream_t.lastRateCalcTime offset mismatch");
_Static_assert(offsetof(netProfileStream_t, sampleCount) ==
                   0x2dc,
               "netProfileStream_t.sampleCount offset mismatch");
_Static_assert(offsetof(netProfileStream_t, fragmentSampleCount) ==
                   0x2e0,
               "netProfileStream_t.fragmentSampleCount mismatch");
_Static_assert(offsetof(netProfileStream_t, fragmentPercent) ==
                   0x2e4,
               "netProfileStream_t.fragmentPercent mismatch");
_Static_assert(offsetof(netProfileStream_t, maxBytes) ==
                   0x2e8,
               "netProfileStream_t.maxBytes offset mismatch");
_Static_assert(offsetof(netProfileStream_t, minBytes) ==
                   0x2ec,
               "netProfileStream_t.minBytes offset mismatch");
_Static_assert(sizeof(netProfileInfo_t) == 0x5e0,
               "netProfileInfo_t size mismatch");
_Static_assert(offsetof(netProfileInfo_t, send) ==
                   0x000,
               "netProfileInfo_t.send offset mismatch");
_Static_assert(offsetof(netProfileInfo_t, receive) ==
                   0x2f0,
               "netProfileInfo_t.receive offset mismatch");
#endif

/*
 * Loopback packet queues used by NET_GetLoopPacket and NET_SendLoopPacket.
 *
 * Evidence:
 * - NET_GetLoopPacket at VA 0x8084b49 selects
 *   net.loopbacks[sock * 0x57c8], clamps get to send - 16, indexes
 *   packet[get & 0x0f] with a 0x57c stride, copies the payload, and reads
 *   packet length from +0x578.
 * - NET_SendLoopPacket at VA 0x8084c4c writes to the opposite socket with the
 *   same 0x57c8 socket stride, packet[send & 0x0f] ring index, payload base
 *   at +0x000, and length at +0x578.
 */
struct loopmsg_s {
    uint8_t data[CODUO_NET_LOOPBACK_PACKET_BYTES];
    int32_t datalen;
};

struct loopback_s {
    loopmsg_t msgs[CODUO_NET_LOOPBACK_PACKET_COUNT];
    int32_t get;
    int32_t send;
};

typedef loopback_t
    loopback_table_t[CODUO_NET_LOOPBACK_SOCKET_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(loopmsg_t) ==
                   0x57c,
               "loopmsg_t size mismatch");
_Static_assert(offsetof(loopmsg_t, datalen) ==
                   0x578,
               "loopmsg_t.datalen offset mismatch");
_Static_assert(sizeof(loopback_t) == 0x57c8,
               "loopback_t size mismatch");
_Static_assert(offsetof(loopback_t, msgs) == 0,
               "loopback_t.msgs offset mismatch");
_Static_assert(sizeof(((loopback_t *)0)->msgs) ==
                    16 * sizeof(loopmsg_t),
               "loopback_t.msgs size mismatch");
_Static_assert(offsetof(loopback_t, get) ==
                    16 * sizeof(loopmsg_t),
               "loopback_t.get offset mismatch");
_Static_assert(offsetof(loopback_t, send) ==
                    16 * sizeof(loopmsg_t) +
                        sizeof(int32_t),
               "loopback_t.send offset mismatch");
_Static_assert(sizeof(loopback_table_t) ==
                    2 * sizeof(loopback_t),
               "loopback_table_t size mismatch");
#endif

/*
 * Confirmed host netchan_t layout.
 *
 * Evidence:
 * - Netchan_Setup at VA 0x8083f57 clears 0x10040 bytes,
 *   writes sock +0x00, the by-value netadr words at +0x08..+0x18, qport
 *   +0x1c, incomingSequence +0x20, outgoingSequence +0x24, and initializes
 *   the netProfileInfo_t pointer slot at +0x1003c.
 * - Netchan_Process reads incomingSequence at +0x20 and fragment assembly
 *   fields at +0x28/+0x2c/+0x30.
 * - Netchan_Transmit and Netchan_TransmitNextFragment use the unsent fragment
 *   state at +0x8030/+0x8034/+0x8038/+0x803c.
 * - Profiling helpers pass &netchan->profile to the enable/free helper and
 *   dereference it as netProfileInfo_t when recording send/receive sizes.
 */
struct netchan_s {
    netsrc_t sock;
    int32_t dropped;
    netadr_t remoteAddress;
    int32_t qport;
    int32_t incomingSequence;
    int32_t outgoingSequence;
    int32_t fragmentSequence;
    int32_t fragmentLength;
    uint8_t fragmentBuffer[CODUO_MAX_MSGLEN];
    qboolean unsentFragments;
    int32_t unsentFragmentStart;
    int32_t unsentLength;
    uint8_t unsentBuffer[CODUO_MAX_MSGLEN];
    netProfileInfo_t *profile;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(netchan_t) == 0x10040,
               "netchan_t size mismatch");
_Static_assert(offsetof(netchan_t, sock) ==
                   0x00,
               "netchan_t.sock offset mismatch");
_Static_assert(offsetof(netchan_t, dropped) ==
                   0x04,
               "netchan_t.dropped offset mismatch");
_Static_assert(offsetof(netchan_t, remoteAddress) ==
                   0x08,
               "netchan_t.remoteAddress offset mismatch");
_Static_assert(offsetof(netchan_t, qport) ==
                   0x1c,
               "netchan_t.qport offset mismatch");
_Static_assert(offsetof(netchan_t, incomingSequence) ==
                   0x20,
               "netchan_t.incomingSequence offset mismatch");
_Static_assert(offsetof(netchan_t, outgoingSequence) ==
                   0x24,
               "netchan_t.outgoingSequence offset mismatch");
_Static_assert(offsetof(netchan_t, fragmentSequence) ==
                   0x28,
               "netchan_t.fragmentSequence offset mismatch");
_Static_assert(offsetof(netchan_t, fragmentLength) ==
                   0x2c,
               "netchan_t.fragmentLength offset mismatch");
_Static_assert(offsetof(netchan_t, fragmentBuffer) ==
                   0x30,
               "netchan_t.fragmentBuffer offset mismatch");
_Static_assert(sizeof(((netchan_t *)0)->fragmentBuffer) ==
                   0x8000,
               "netchan_t.fragmentBuffer size mismatch");
_Static_assert(offsetof(netchan_t, unsentFragments) ==
                   0x8030,
               "netchan_t.unsentFragments offset mismatch");
_Static_assert(offsetof(netchan_t, unsentFragmentStart) ==
                   0x8034,
               "netchan_t.unsentFragmentStart offset mismatch");
_Static_assert(offsetof(netchan_t, unsentLength) ==
                   0x8038,
               "netchan_t.unsentLength offset mismatch");
_Static_assert(offsetof(netchan_t, unsentBuffer) ==
                   0x803c,
               "netchan_t.unsentBuffer offset mismatch");
_Static_assert(sizeof(((netchan_t *)0)->unsentBuffer) ==
                   0x8000,
               "netchan_t.unsentBuffer size mismatch");
_Static_assert(offsetof(netchan_t, profile) ==
                   0x1003c,
               "netchan_t.profile offset mismatch");
#endif

/*
 * Confirmed host client subrecords.
 *
 * Evidence:
 * - SV_AddServerCommand writes the reliable command ring at client +0x40c
 *   with a 0x408-byte stride: command text +0x000, timestamp +0x400, and
 *   reliable flag +0x404.
 * - Download paths use the contiguous client block from fileName
 *   +0x10a64 through the WWW download done/fallback flag at +0x10c10.
 * - SV_BuildClientSnapshot at VA 0x80982cf selects frame
 *   `client + 0x10c30 + ((netchan.outgoingSequence & 0x1f) * 0x4520)`,
 *   fills a 0x4504-byte player-state prefix, zeros numEntities +0x4504
 *   and numClients +0x4508, seeds firstEntity +0x450c and firstClient
 *   +0x4510 from the live snapshot ring counters, then increments the counts
 *   as it snapshots entity/client records.
 * - SV_SendClientSnapshot at VA 0x8098a23 writes messageSentTime +0x4514,
 *   initializes messageAckedTime +0x4518 to -1, stores the finalized packet
 *   byte count at messageSize +0x451c, and passes the same byte count to the
 *   packet-send helper.
 */
typedef struct serverReliableCommand_s {
    char commandText[CODUO_MAX_STRING_CHARS];
    int32_t enqueueTime;
    qboolean reliable;
} serverReliableCommand_t;

typedef usercmd_t coduo_host_client_usercmd_words_t;

typedef serverReliableCommand_t
    serverReliableCommandRing_t
        [CODUO_HOST_CLIENT_RELIABLE_COMMAND_COUNT];

struct clientSnapshot_s {
    coduo_archived_client_info_player_state_t playerState;
    int32_t numEntities;
    int32_t numClients;
    int32_t firstEntity;
    int32_t firstClient;
    int32_t messageSentTime;
    int32_t messageAckedTime;
    int32_t messageSize;
};

typedef clientSnapshot_t
    coduo_host_client_snapshot_frame_ring_t
        [CODUO_HOST_CLIENT_SNAPSHOT_FRAME_COUNT];

typedef struct serverClientDownload_s {
    coduo_host_download_name_t fileName;
    int32_t fileHandle;
    int32_t fileSize;
    int32_t bytesRead;
    int32_t nextAcknowledgmentBlock;
    int32_t nextBufferedBlock;
    int32_t nextTransmitBlock;
    uint8_t *blockData[CODUO_HOST_CLIENT_DOWNLOAD_BLOCK_COUNT];
    int32_t
        blockByteCounts[CODUO_HOST_CLIENT_DOWNLOAD_BLOCK_COUNT];
    qboolean eofBlockQueued;
    int32_t lastBlockActivityTime;
    qboolean redirectAllowedByClient;
    coduo_host_www_download_url_t redirectUrl;
    qboolean redirectActive;
    qboolean redirectAcknowledged;
    /* Also used as the fail/chkfail fallback flag before game-state resend. */
    qboolean redirectFailed;
} serverClientDownload_t;

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(serverReliableCommand_t) ==
                   0x408,
               "serverReliableCommand_t size mismatch");
_Static_assert(sizeof(serverReliableCommandRing_t) ==
                    64 * (0x408),
               "serverReliableCommandRing_t size mismatch");
_Static_assert(sizeof(coduo_host_client_usercmd_words_t) ==
                   0x18,
               "coduo_host_client_usercmd_words_t size mismatch");
_Static_assert(sizeof(clientSnapshot_t) ==
                   0x4520,
               "clientSnapshot_t size mismatch");
_Static_assert(sizeof(coduo_host_client_snapshot_frame_ring_t) ==
                    32 * (0x4520),
               "coduo_host_client_snapshot_frame_ring_t size mismatch");
_Static_assert(offsetof(clientSnapshot_t, playerState) ==
                   0x0000,
               "clientSnapshot_t.playerState mismatch");
_Static_assert(sizeof(((clientSnapshot_t *)0)->playerState) ==
                   sizeof(playerState_t),
               "clientSnapshot_t.playerState size mismatch");
_Static_assert(offsetof(clientSnapshot_t, numEntities) ==
                   0x4504,
               "clientSnapshot_t.numEntities mismatch");
_Static_assert(offsetof(clientSnapshot_t, numClients) ==
                   0x4508,
               "clientSnapshot_t.numClients mismatch");
_Static_assert(offsetof(clientSnapshot_t, firstEntity) ==
                   0x450c,
               "clientSnapshot_t.firstEntity mismatch");
_Static_assert(offsetof(clientSnapshot_t, firstClient) ==
                   0x4510,
               "clientSnapshot_t.firstClient mismatch");
_Static_assert(offsetof(clientSnapshot_t, messageSentTime) ==
                   0x4514,
               "clientSnapshot_t.messageSentTime mismatch");
_Static_assert(offsetof(clientSnapshot_t, messageAckedTime) ==
                   0x4518,
               "clientSnapshot_t.messageAckedTime mismatch");
_Static_assert(offsetof(clientSnapshot_t, messageSize) ==
                   0x451c,
               "clientSnapshot_t.messageSize mismatch");
_Static_assert(offsetof(usercmd_t, commandTime) ==
                   0x00,
               "usercmd_t.commandTime offset mismatch");
_Static_assert(offsetof(usercmd_t, buttons) ==
                   0x04,
               "usercmd_t.buttons offset mismatch");
_Static_assert(offsetof(usercmd_t, wbuttons) ==
                   0x05,
               "usercmd_t.wbuttons offset mismatch");
_Static_assert(offsetof(usercmd_t, weapon) ==
                   0x06,
               "usercmd_t.weapon offset mismatch");
_Static_assert(offsetof(usercmd_t, angles) ==
                   0x08,
               "usercmd_t.angles offset mismatch");
_Static_assert(sizeof(((usercmd_t *)0)->angles) ==
                   3 * sizeof(int32_t),
               "usercmd_t.angles size mismatch");
_Static_assert(offsetof(usercmd_t, forwardmove) ==
                   0x14,
               "usercmd_t.forwardmove offset mismatch");
_Static_assert(offsetof(usercmd_t, rightmove) ==
                   0x15,
               "usercmd_t.rightmove offset mismatch");
_Static_assert(offsetof(usercmd_t, upmove) ==
                   0x16,
               "usercmd_t.upmove offset mismatch");
_Static_assert(sizeof(coduo_packet_usercmd_batch_t) ==
                   (32 * 0x18),
               "coduo_packet_usercmd_batch_t size mismatch");
_Static_assert(offsetof(serverReliableCommand_t, enqueueTime) ==
                   0x400,
               "serverReliableCommand_t.enqueueTime offset mismatch");
_Static_assert(offsetof(serverReliableCommand_t, reliable) ==
                   0x404,
               "serverReliableCommand_t.reliable offset mismatch");
_Static_assert(sizeof(serverClientDownload_t) ==
                    (0x10c14) - (0x10a64),
               "serverClientDownload_t size mismatch");
_Static_assert(offsetof(serverClientDownload_t, fileName) == 0,
               "serverClientDownload_t.fileName offset mismatch");
_Static_assert(sizeof(((serverClientDownload_t *)0)->fileName) ==
                   64,
               "serverClientDownload_t.fileName size mismatch");
_Static_assert(offsetof(serverClientDownload_t, fileHandle) ==
                   0x10aa4 -
                       0x10a64,
               "serverClientDownload_t.fileHandle offset mismatch");
_Static_assert(offsetof(serverClientDownload_t, fileSize) ==
                   0x10aa8 -
                       0x10a64,
               "serverClientDownload_t.fileSize offset mismatch");
_Static_assert(offsetof(serverClientDownload_t, bytesRead) ==
                   0x10aac -
                       0x10a64,
               "serverClientDownload_t.bytesRead offset mismatch");
_Static_assert(offsetof(serverClientDownload_t, nextAcknowledgmentBlock) ==
                   0x10ab0 -
                       0x10a64,
               "serverClientDownload_t.nextAcknowledgmentBlock mismatch");
_Static_assert(offsetof(serverClientDownload_t, nextBufferedBlock) ==
                   0x10ab4 -
                       0x10a64,
               "serverClientDownload_t.nextBufferedBlock mismatch");
_Static_assert(offsetof(serverClientDownload_t, nextTransmitBlock) ==
                   0x10ab8 -
                       0x10a64,
               "serverClientDownload_t.nextTransmitBlock mismatch");
_Static_assert(offsetof(serverClientDownload_t, blockData) ==
                   0x10abc -
                       0x10a64,
               "serverClientDownload_t.blockData offset mismatch");
_Static_assert(sizeof(((serverClientDownload_t *)0)->blockData) ==
                   8 *
                       4,
               "serverClientDownload_t.blockData size mismatch");
_Static_assert(offsetof(serverClientDownload_t, blockByteCounts) ==
                   0x10adc -
                       0x10a64,
               "serverClientDownload_t.blockByteCounts offset mismatch");
_Static_assert(sizeof(((serverClientDownload_t *)0)->blockByteCounts) ==
                   8 *
                       sizeof(int32_t),
               "serverClientDownload_t.blockByteCounts size mismatch");
_Static_assert(offsetof(serverClientDownload_t, eofBlockQueued) ==
                   0x10afc -
                       0x10a64,
               "serverClientDownload_t.eofBlockQueued offset mismatch");
_Static_assert(offsetof(serverClientDownload_t, lastBlockActivityTime) ==
                   0x10b00 -
                       0x10a64,
               "serverClientDownload_t.lastBlockActivityTime mismatch");
_Static_assert(offsetof(serverClientDownload_t, redirectAllowedByClient) ==
                   0x10b04 -
                       0x10a64,
               "serverClientDownload_t.redirectAllowedByClient mismatch");
_Static_assert(offsetof(serverClientDownload_t, redirectUrl) ==
                   0x10b08 -
                       0x10a64,
               "serverClientDownload_t.redirectUrl offset mismatch");
_Static_assert(sizeof(((serverClientDownload_t *)0)->redirectUrl) ==
                   0x100,
               "serverClientDownload_t.redirectUrl size mismatch");
_Static_assert(offsetof(serverClientDownload_t, redirectActive) ==
                   0x10c08 -
                       0x10a64,
               "serverClientDownload_t.redirectActive mismatch");
_Static_assert(offsetof(serverClientDownload_t, redirectAcknowledged) ==
                   0x10c0c -
                       0x10a64,
               "serverClientDownload_t.redirectAcknowledged mismatch");
_Static_assert(offsetof(serverClientDownload_t, redirectFailed) ==
                   0x10c10 -
                       0x10a64,
               "serverClientDownload_t.redirectFailed offset mismatch");
#endif

/*
 * PunkBuster-facing client info record filled by the host helper at
 * VA 0x8094768.
 *
 * Evidence:
 * - The helper clears 0x68 bytes, then copies client name to +0x00,
 *   host-client PunkBuster GUID cache to +0x21, and printable address to
 *   +0x42. Each visible string slot is therefore 33 bytes; the remaining
 *   padding at +0x63 is only zeroed by the initial clear.
 */
struct coduo_punkbuster_client_info_s {
    coduo_punkbuster_info_string_t name;
    coduo_punkbuster_info_string_t guid;
    coduo_punkbuster_info_string_t address;
    uint8_t padding63[5];
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_punkbuster_client_info_t) ==
                   0x68,
               "coduo_punkbuster_client_info_t size mismatch");
_Static_assert(offsetof(coduo_punkbuster_client_info_t, name) ==
                   0x00,
               "coduo_punkbuster_client_info_t.name offset mismatch");
_Static_assert(offsetof(coduo_punkbuster_client_info_t, guid) ==
                   0x21,
               "coduo_punkbuster_client_info_t.guid offset mismatch");
_Static_assert(offsetof(coduo_punkbuster_client_info_t, address) ==
                   0x42,
               "coduo_punkbuster_client_info_t.address offset mismatch");
_Static_assert(offsetof(coduo_punkbuster_client_info_t, padding63) ==
                    (0x42) + (0x21),
               "coduo_punkbuster_client_info_t.padding63 offset mismatch");
_Static_assert(sizeof(((coduo_punkbuster_client_info_t *)0)->padding63) ==
                    0x68 - ( (0x42) + (0x21)),
               "coduo_punkbuster_client_info_t.padding63 size mismatch");
#endif

/*
 * Visible PunkBuster server object fragment at VA 0x8433fc0.
 *
 * Evidence:
 * - The initializer at VA 0x80b74a0 writes magic +0x00, copies
 *   "PunkBuster Server" to +0x14, clears or initializes +0x04, +0x08,
 *   +0x138, and the callback/opaque tail through +0x164.
 * - PB path helpers at VA 0x80b7914 and VA 0x80b7b5a use +0x34 as the
 *   server module base path buffer: query `fs_homepath` through the PB query
 *   callback, fall back to getcwd(..., 0xfb), append `/pb/`, and build module
 *   paths from that base.
 * - The 32-bit load-pending flag at +0x138 is initialized to 1, forces the
 *   next `sa`/`sb` dispatch through PB_LoadServerModule, and is cleared only
 *   after `pbsv.so` opens and both required exports resolve.
 * - Shutdown helpers at VA 0x80b756c, 0x80b7596, and 0x80b7606 dlclose
 *   non-null handles at +0x0c, +0x10, and +0x08 respectively.
 * - Callback setup at VA 0x80b72dc installs PB_ServerCommand at +0x13c,
 *   PB_ServerQuery at +0x140, PB_ServerOutput at +0x144,
 *   PB_ServerChecksum at +0x148, and PB_ServerPacket at +0x154.
 * - PB_CallServerSb at VA 0x80b7330 and PB_CallServerSa at VA 0x80b73f0
 *   call the module callbacks loaded from `sb` into +0x14c and `sa` into
 *   +0x150.
 * - The server module loader at VA 0x80b767a opens pbsv.so into +0x08 and
 *   resolves required exports `sa` and `sb`.
 * - Optional callback bridges at VA 0x80b6c80, 0x80b6cb0, and 0x80b6da8
 *   read +0x158, +0x15c, and +0x160 respectively. The first is invoked as
 *   (object, arg0, arg1), the second returns a pointer from
 *   (object, arg0, arg1, arg2), and PB_Print calls +0x160 as
 *   (object, text, severity) before appending to the console-capture buffer.
 */
struct coduo_punkbuster_server_s {
    int32_t magic;
    coduo_pb_server_opaque_slot_t opaque04;
    void *serverModuleHandle;
    void *moduleHandle0c;
    void *moduleHandle10;
    char title[CODUO_PUNKBUSTER_SERVER_TITLE_SIZE];
    char basePath[CODUO_PUNKBUSTER_SERVER_BASE_PATH_SIZE];
    int32_t loadPending;
    coduo_pb_command_bridge_fn commandCallback;
    coduo_pb_query_bridge_fn queryCallback;
    coduo_pb_output_bridge_fn outputCallback;
    coduo_pb_checksum_bridge_fn checksumCallback;
    coduo_pb_server_sb_fn serverSbCallback;
    coduo_pb_server_sa_fn serverSaCallback;
    coduo_pb_packet_bridge_fn packetCallback;
    /* coduo_pb_event_callback_fn called by PB_InvokeEventCallback. */
    coduo_pb_event_callback_fn eventCallback;
    /* coduo_pb_string_query_callback_fn called by PB_InvokeStringQueryCallback. */
    coduo_pb_string_query_callback_fn stringQueryCallback;
    /* coduo_pb_print_callback_fn called by PB_Print before console capture. */
    coduo_pb_print_callback_fn printCallback;
    coduo_pb_server_opaque_slot_t opaque164;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_punkbuster_server_t) ==
                   0x168,
               "coduo_punkbuster_server_t visible size mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, magic) ==
                   0x000,
               "coduo_punkbuster_server_t.magic offset mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, opaque04) ==
                   0x004,
               "coduo_punkbuster_server_t.opaque04 offset mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, serverModuleHandle) ==
                   0x008,
               "coduo_punkbuster_server_t.serverModuleHandle mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, moduleHandle0c) ==
                   0x00c,
               "coduo_punkbuster_server_t.moduleHandle0c mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, moduleHandle10) ==
                   0x010,
               "coduo_punkbuster_server_t.moduleHandle10 mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, title) ==
                   0x014,
               "coduo_punkbuster_server_t.title offset mismatch");
_Static_assert(sizeof(((coduo_punkbuster_server_t *)0)->title) ==
                   0x020,
               "coduo_punkbuster_server_t.title size mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, basePath) ==
                   0x034,
               "coduo_punkbuster_server_t.basePath offset mismatch");
_Static_assert(sizeof(((coduo_punkbuster_server_t *)0)->basePath) ==
                   0x104,
               "coduo_punkbuster_server_t.basePath size mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, loadPending) ==
                   0x138,
               "coduo_punkbuster_server_t.loadPending offset mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, commandCallback) ==
                   0x13c,
               "coduo_punkbuster_server_t.commandCallback mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, queryCallback) ==
                   0x140,
               "coduo_punkbuster_server_t.queryCallback mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, outputCallback) ==
                   0x144,
               "coduo_punkbuster_server_t.outputCallback mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, checksumCallback) ==
                   0x148,
               "coduo_punkbuster_server_t.checksumCallback mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, serverSbCallback) ==
                   0x14c,
               "coduo_punkbuster_server_t.serverSbCallback mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, serverSaCallback) ==
                   0x150,
               "coduo_punkbuster_server_t.serverSaCallback mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, packetCallback) ==
                   0x154,
               "coduo_punkbuster_server_t.packetCallback mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, eventCallback) ==
                   0x158,
               "coduo_punkbuster_server_t.eventCallback offset mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, stringQueryCallback) ==
                   0x15c,
               "coduo_punkbuster_server_t.stringQueryCallback offset mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, printCallback) ==
                   0x160,
               "coduo_punkbuster_server_t.printCallback offset mismatch");
_Static_assert(offsetof(coduo_punkbuster_server_t, opaque164) ==
                   0x164,
               "coduo_punkbuster_server_t.opaque164 offset mismatch");
#endif

/*
 * XAnim pool record at VA 0x8434140.
 *
 * Evidence:
 * - XAnimInit at VA 0x80b7d84 walks 2048 records with a 0x44-byte stride
 *   from raw base VA 0x8434140 and seeds 16-bit free-list links at +0x08/+0x0a.
 * - Allocation/free paths around VA 0x80bf990 and VA 0x80bb6d0 update those
 *   link words and the pool-used/high-water counters at VA 0x84567c4 and
 *   VA 0x84567c8.
 * - Free helper VA 0x80bb68c tests the 16-bit notify handle at raw node +0x04
 *   and releases it when nonzero before the node is put back on the free list.
 * - XAnim blend/output helpers address two 0x1c-byte payload slots at
 *   node +0x0c and node +0x28 using the selector global at VA 0x8456180.
 * - The helper at VA 0x80c0b1e initializes active-slot +0x00/+0x04 from
 *   the same floating-point argument and clears +0x08/+0x0a as 16-bit frame
 *   fields; VA 0x80c0ba8 copies the same leading quartet between slots.
 * - The update paths at VA 0x80bc456 and VA 0x80bd884 treat +0x00/+0x04
 *   as floating-point time values, +0x08/+0x0a as frame indices, and +0x18 as a
 *   floating-point rate scale multiplied into the incoming time delta.
 * - Weight setup at VA 0x80c05a2 writes targetWeight at +0x10, computes
 *   weightBlendTimeRemaining at +0x0c from the target/current delta and the
 *   caller blend argument, and snaps currentWeight at +0x14 when the blend
 *   window is negligible. Weight update at VA 0x80bc178 consumes +0x0c by
 *   moving +0x14 toward +0x10 and decrementing the remaining time.
 * - Debug print paths around VA 0x80be3ca pass +0x14 then +0x10 to format
 *   strings as `(weight) %f -> %f`; recursive evaluator VA 0x80be810 also
 *   selects between those two floats through xanim.evalPoolWeightSelector.
 */
struct XAnimState {
    float time;
    float oldTime;
    uint16_t cycleCount;
    uint16_t oldCycleCount;
    float weightBlendTimeRemaining;
    float targetWeight;
    float currentWeight;
    float rateScale;
};

/* Stock address arithmetic selects one of two 0x1c-byte XAnimState lanes.
 * The primary/secondary roles are proved by the dedicated update, copy, and
 * timing-clear paths. These are source-level indices, not an ABI enum. */
enum {
    XANIM_PRIMARY_POOL_PAYLOAD_SLOT = 0,
    XANIM_SECONDARY_POOL_PAYLOAD_SLOT = 1,
    XANIM_POOL_PAYLOAD_SLOT_COUNT = 2
};

struct XAnimInfo {
    uint16_t notifyChildIndex;
    int16_t notifyIndex;
    uint16_t notifyName;
    uint16_t notifyType;
    uint16_t freePrev;
    uint16_t freeNext;
    XAnimState states[XANIM_POOL_PAYLOAD_SLOT_COUNT];
};

typedef XAnimInfo
    coduo_xanim_pool_t[CODUO_XANIM_POOL_NODE_COUNT];

typedef enum coduo_script_anim_property_flag_e {
    CODUO_SCRIPT_ANIM_PROPERTY_LOOPSYNC = 1u << 0,
    CODUO_SCRIPT_ANIM_PROPERTY_NONLOOPSYNC = 1u << 1,
    CODUO_SCRIPT_ANIM_PROPERTY_COMPLETE = 1u << 3
} coduo_script_anim_property_flag_t;

typedef uint8_t *coduo_script_codepos_t;
typedef uintptr_t coduo_script_value_payload_t;
typedef uintptr_t coduo_script_yystype_word_t;

/*
 * NOT_FROM_ORIGINAL_SOURCE: the original VM stores script int payloads in a
 * 32-bit cell. Keep widened host payloads canonical so int equality, bit ops,
 * and saved stack values do not retain non-original high bits on 64-bit builds.
 */
#define SCRIPT_VALUE_INT_PAYLOAD(value) \
    ((coduo_script_value_payload_t)(uint32_t)(int32_t)(value))
#define SCRIPT_VALUE_U32_PAYLOAD(value) \
    ((coduo_script_value_payload_t)(uint32_t)(value))

/*
 * Script expression value stack entries.
 *
 * Evidence:
 * - Stack init at VA 0x80aa76c sets script.valueStackTop to VA 0x842fe00,
 *   script.valueStackLimit to VA 0x8433df8, and seeds the first entry type at
 *   VA 0x842fe04 to CODUO_SCRIPT_VAR_CODEPOS.
 * - Push helper VA 0x80af004 increments the top pointer by 8, increments the
 *   depth cell, and reports "stack overflow" when the top pointer passes the
 *   limit.
 * - Push sites at VA 0x80b0202..0x80b0442 write type values at entry +0x04
 *   and payloads at entry +0x00; bytecode loader VA 0x80ab589 uses the same
 *   8-byte stride.
 * - Recovered runtime payloads also carry host pointers for vectors, saved
 *   stacks, code buffers, and animation tree records, so maintained source uses
 *   a pointer-width payload while guarding original 32-bit layout asserts below.
 */
/* Exact Mac traceback spellings.  Mac-generated assignment operators prove a
 * one-dword VariableUnion and a two-dword VariableValue; Linux independently
 * proves payload/type at +0x00/+0x04.  Pointer-width storage is solely the
 * maintained native-host adaptation, guarded by the original i386 checks. */
union VariableUnion {
    coduo_script_value_payload_t payload;
    coduo_script_value_payload_t valuePayload;
    struct {
        uint16_t valueOrRefCount;
        uint16_t parentHandle;
    } halves;
};

struct VariableValue {
    union {
        VariableUnion u;
        coduo_script_value_payload_t payload;
    };
    coduo_script_variable_type_t type;
};

typedef VariableValue
    coduo_script_value_stack_t[CODUO_SCRIPT_VALUE_STACK_COUNT];
typedef coduo_script_codepos_t
    coduo_script_call_stack_codepos_t[CODUO_SCRIPT_CALL_STACK_COUNT];
typedef coduo_script_codepos_t
    coduo_script_frame_backup_codepos_t[CODUO_SCRIPT_CALL_STACK_COUNT];
typedef uint8_t
    coduo_script_frame_backup_opcode_t[CODUO_SCRIPT_CALL_STACK_COUNT];

/*
 * Flex YY_BUFFER_STATE used by the generated script parser scanner.
 *
 * Evidence:
 * - yy_create_buffer-matched VA 0x80b245f allocates 0x28 bytes, writes
 *   bufSize at +0x0c, chBuf at +0x04, and isOurBuffer at +0x14.
 * - yy_switch_to_buffer/yy_load_buffer_state at VA 0x80b23c3..0x80b245e
 *   save and restore bufPos +0x08, nChars +0x10, inputFile +0x00, and the
 *   held character byte through script.yyHoldChar.
 * - yy_init_buffer/yy_flush_buffer at VA 0x80b2528..0x80b25ea set inputFile,
 *   isInteractive +0x18, nChars +0x10, bufPos +0x08, atBol +0x1c,
 *   fillBuffer +0x20, and bufferStatus +0x24.
 */
struct coduo_script_yy_buffer_s {
    FILE *inputFile;
    char *chBuf;
    char *bufPos;
    int32_t bufSize;
    int32_t nChars;
    int32_t isOurBuffer;
    int32_t isInteractive;
    int32_t atBol;
    int32_t fillBuffer;
    int32_t bufferStatus;
};

/*
 * Opaque semantic value used by the generated yacc script parser.
 *
 * Evidence:
 * - The original 32-bit parser copies semantic values between yylval, yyval,
 *   and yyvs as two 32-bit words at VA 0x80b2a21..0x80b2a2e,
 *   VA 0x80b2c17..0x80b2c21, VA 0x80b5967..0x80b597f, and repeated reduce
 *   actions. Recovered source uses pointer-width semantic words because the
 *   same fields carry AST/list pointers in host memory.
 * - Lexer actions at VA 0x80b08e1, VA 0x80b09d6, VA 0x80b09de, and
 *   VA 0x80b0a01 write token semantic data into script.yylval.
 */
union sval_u {
    coduo_script_yystype_word_t words[2];
};

typedef int16_t
    coduo_script_yy_state_stack_t[CODUO_SCRIPT_YYSTACK_COUNT];
typedef sval_u
    coduo_script_yy_value_stack_t[CODUO_SCRIPT_YYSTACK_COUNT];
typedef int16_t
    coduo_script_yy_rule_table_t[CODUO_SCRIPT_YY_RULE_STORAGE_COUNT];
typedef int16_t
    coduo_script_yy_state_table_t[CODUO_SCRIPT_YY_STATE_TABLE_COUNT];
typedef int16_t
    coduo_script_yy_nonterm_table_t[CODUO_SCRIPT_YY_NONTERM_TABLE_COUNT];
typedef int16_t
    coduo_script_yy_parse_table_t[CODUO_SCRIPT_YYTABLE_STORAGE_COUNT];
typedef void *
    coduo_script_yy_action_table_t[CODUO_SCRIPT_YY_ACTION_COUNT];

/*
 * Script variable node records used by engine-side script object trees.
 *
 * Evidence:
 * - Helpers at VA 0x80a7b82, VA 0x80a7d0a, and VA 0x80a7aa4 index
 *   0x0832fde0 as `handle * 12`, then read +0x00, +0x04 & 0x1f, and
 *   +0x04 >> 8 respectively.
 * - Link maintenance around VA 0x80a5a3b, VA 0x80a5d97, and VA 0x80a5f88
 *   reads/writes the 16-bit link slots at +0x08 and +0x0a.
 * - 0x083efde0 is indexed as `handle * 4`; readers use the 16-bit node
 *   index at +0x00 and list maintenance writes a 16-bit link at +0x02.
 * - XAnim tree construction at VA 0x809c876 walks script variables before
 *   populating XAnim with XAnimSetLeafNode/XAnimSetParentNode.
 */
struct VariableValueInternal {
    VariableUnion u;
    uint32_t status;
};

struct coduo_script_variable_node_s {
    /* The original i386 first eight bytes match VariableValueInternal. */
    VariableUnion payload;
    uint32_t packedTypeIndex;
    uint16_t link08;
    uint16_t link0a;
};

struct Variable {
    uint16_t valueIndex;
    uint16_t previousSibling;
};

/* Each saved stack lane is packed as a type byte followed immediately by its
 * payload. The original i386 lane is five bytes and carries a four-byte code
 * pointer. The portable recovery widens only the payload byte array so normal
 * host pointers survive suspension, while code positions use base-relative
 * dwords and are reconstructed at live consumers. Representing the payload as
 * bytes keeps its +0x01 position valid without unaligned scalar access. */
typedef struct VariableStackBufferValue_s {
    uint8_t type;
    uint8_t payload[sizeof(coduo_script_value_payload_t)];
} VariableStackBufferValue;

/* Mac uses VariableStackBuffer for both the serializer and the suspended
 * notify/wait frame. Linux and Windows agree on this 12-byte header and the
 * packed values beginning at +0x0c. */
struct VariableStackBuffer {
    uint32_t time;
    uint32_t pos;
    uint16_t size;
    uint16_t localId;
    VariableStackBufferValue buf[];
};

typedef coduo_script_variable_node_t
    coduo_script_variable_node_table_t[CODUO_SCRIPT_VARIABLE_NODE_COUNT];
typedef Variable
    coduo_script_variable_indirection_table_t
        [CODUO_SCRIPT_VARIABLE_NODE_COUNT];
typedef uint16_t
    coduo_script_object_id_map_t[CODUO_SCRIPT_OBJECT_ID_MAP_COUNT];
typedef uint16_t
    coduo_script_variable_handle_map_t[CODUO_SCRIPT_OBJECT_ID_MAP_COUNT];
typedef const char *
    coduo_script_variable_type_name_table_t[CODUO_SCRIPT_VARIABLE_TYPE_COUNT];
typedef const char *
    coduo_script_anim_property_name_table_t
        [CODUO_SCRIPT_ANIM_PROPERTY_NAME_COUNT];
typedef XAnim *
    coduo_script_anim_tree_table_t
        [CODUO_SCRIPT_ANIM_SLOT_COUNT][CODUO_SCRIPT_ANIM_TREE_SLOT_COUNT];
typedef uint16_t
    coduo_script_anim_tree_handle_table_t
        [CODUO_SCRIPT_ANIM_SLOT_COUNT][CODUO_SCRIPT_ANIM_TREE_SLOT_COUNT];
typedef int32_t
    coduo_script_anim_tree_count_table_t[CODUO_SCRIPT_ANIM_SLOT_COUNT];

/*
 * Per-entity-type script variable usage records.
 *
 * Evidence:
 * - Initializer at VA 0x80a7e1a stores its table pointer/count arguments into
 *   script.entityTypeUsageRecords and script.entityTypeUsageCount, then writes
 *   a 16-bit root handle at entry +0x00 for each 8-byte record.
 * - Usage reporting at VA 0x80a5888 walks the same count, addresses records
 *   as base + index * 8, and reads a char pointer at +0x04 for the
 *   "ent type '%s'... count: %d, var usage: %d" message.
 * - The two padding bytes at +0x02 align the following pointer field.
 */
struct coduo_script_entity_type_usage_s {
    uint16_t rootHandle;
    uint8_t padding02[2];
    const char *name;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_script_variable_type_t) == sizeof(uint32_t),
               "coduo_script_variable_type_t size mismatch");
_Static_assert(sizeof(coduo_script_anim_property_flag_t) == sizeof(uint32_t),
               "coduo_script_anim_property_flag_t size mismatch");
_Static_assert(sizeof(coduo_script_codepos_t) == sizeof(uint8_t *),
               "coduo_script_codepos_t size mismatch");
_Static_assert(sizeof(coduo_script_value_payload_t) == sizeof(uintptr_t),
               "coduo_script_value_payload_t size mismatch");
_Static_assert(sizeof(coduo_script_yystype_word_t) == sizeof(uintptr_t),
               "coduo_script_yystype_word_t size mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(VariableUnion) == 0x04,
               "original i386 VariableUnion size changed");
_Static_assert(sizeof(VariableValue) == 0x08,
               "original i386 VariableValue size changed");
_Static_assert(sizeof(VariableValueInternal) == 0x08 &&
                   offsetof(VariableValueInternal, status) == 0x04,
               "original i386 VariableValueInternal layout changed");
_Static_assert(sizeof(VariableStackBuffer) == 0x0c &&
                   offsetof(VariableStackBuffer, time) == 0x00 &&
                   offsetof(VariableStackBuffer, pos) == 0x04 &&
                   offsetof(VariableStackBuffer, size) == 0x08 &&
                   offsetof(VariableStackBuffer, localId) == 0x0a &&
                   offsetof(VariableStackBuffer, buf) == 0x0c,
               "original i386 VariableStackBuffer layout changed");
_Static_assert(sizeof(VariableStackBufferValue) == 0x05 &&
                   offsetof(VariableStackBufferValue, payload) == 0x01,
               "original i386 VariableStackBufferValue layout changed");
#endif
_Static_assert(sizeof(coduo_script_call_stack_codepos_t) ==
                   32 *
                       sizeof(coduo_script_codepos_t),
               "coduo_script_call_stack_codepos_t size mismatch");
_Static_assert(sizeof(coduo_script_frame_backup_codepos_t) ==
                   32 *
                       sizeof(coduo_script_codepos_t),
               "coduo_script_frame_backup_codepos_t size mismatch");
_Static_assert(sizeof(coduo_script_frame_backup_opcode_t) ==
                   32 * sizeof(uint8_t),
               "coduo_script_frame_backup_opcode_t size mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_script_yy_buffer_t) ==
                   0x28,
               "coduo_script_yy_buffer_t size mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, inputFile) ==
                   0x00,
               "coduo_script_yy_buffer_t.inputFile offset mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, chBuf) ==
                   0x04,
               "coduo_script_yy_buffer_t.chBuf offset mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, bufPos) ==
                   0x08,
               "coduo_script_yy_buffer_t.bufPos offset mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, bufSize) ==
                   0x0c,
               "coduo_script_yy_buffer_t.bufSize offset mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, nChars) ==
                   0x10,
               "coduo_script_yy_buffer_t.nChars offset mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, isOurBuffer) ==
                   0x14,
               "coduo_script_yy_buffer_t.isOurBuffer offset mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, isInteractive) ==
                   0x18,
               "coduo_script_yy_buffer_t.isInteractive offset mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, atBol) ==
                   0x1c,
               "coduo_script_yy_buffer_t.atBol offset mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, fillBuffer) ==
                   0x20,
               "coduo_script_yy_buffer_t.fillBuffer offset mismatch");
_Static_assert(offsetof(coduo_script_yy_buffer_t, bufferStatus) ==
                   0x24,
               "coduo_script_yy_buffer_t.bufferStatus offset mismatch");
#endif
_Static_assert(sizeof(coduo_script_yy_state_stack_t) ==
                   500 *
                       sizeof(int16_t),
               "coduo_script_yy_state_stack_t size mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(sval_u) == 0x08,
               "sval_u size mismatch");
_Static_assert(offsetof(sval_u, words) ==
                   0x00,
               "sval_u.words[0] offset mismatch");
_Static_assert(offsetof(sval_u, words) +
                       sizeof(((sval_u *)0)->words[0]) ==
                   0x04,
               "sval_u.words[1] offset mismatch");
_Static_assert(sizeof(coduo_script_yy_value_stack_t) ==
                   500 *
                       0x08,
               "coduo_script_yy_value_stack_t size mismatch");
#endif
_Static_assert(sizeof(coduo_script_yy_rule_table_t) ==
                   128 *
                       sizeof(int16_t),
               "coduo_script_yy_rule_table_t size mismatch");
_Static_assert(sizeof(coduo_script_yy_state_table_t) ==
                   256 *
                       sizeof(int16_t),
               "coduo_script_yy_state_table_t size mismatch");
_Static_assert(sizeof(coduo_script_yy_nonterm_table_t) ==
                   32 *
                       sizeof(int16_t),
               "coduo_script_yy_nonterm_table_t size mismatch");
_Static_assert(sizeof(coduo_script_yy_parse_table_t) ==
                   1536 *
                       sizeof(int16_t),
               "coduo_script_yy_parse_table_t size mismatch");
_Static_assert(sizeof(coduo_script_yy_action_table_t) ==
                   (0x7c + 1) *
                       sizeof(void *),
               "coduo_script_yy_action_table_t size mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(offsetof(VariableValue, payload) ==
                   0x00,
               "VariableValue.payload offset mismatch");
_Static_assert(offsetof(VariableValue, type) ==
                   0x04,
               "VariableValue.type offset mismatch");
_Static_assert(sizeof(coduo_script_variable_node_t) ==
                   0x0c,
               "coduo_script_variable_node_t size mismatch");
_Static_assert(offsetof(coduo_script_variable_node_t, payload.valuePayload) ==
                   0x00,
               "coduo_script_variable_node_t.valuePayload offset mismatch");
_Static_assert(offsetof(coduo_script_variable_node_t,
                       payload.halves.valueOrRefCount) ==
                   0x00,
               "coduo_script_variable_node_t.valueOrRefCount offset mismatch");
_Static_assert(offsetof(coduo_script_variable_node_t,
                       payload.halves.parentHandle) ==
                   0x02,
               "coduo_script_variable_node_t.parentHandle offset mismatch");
_Static_assert(offsetof(coduo_script_variable_node_t, packedTypeIndex) ==
                   0x04,
               "coduo_script_variable_node_t.packedTypeIndex offset mismatch");
_Static_assert(offsetof(coduo_script_variable_node_t, link08) ==
                   0x08,
               "coduo_script_variable_node_t.link08 offset mismatch");
_Static_assert(offsetof(coduo_script_variable_node_t, link0a) ==
                   0x0a,
               "coduo_script_variable_node_t.link0a offset mismatch");
#endif
_Static_assert(sizeof(Variable) == 0x04,
               "Variable size mismatch");
_Static_assert(offsetof(Variable, valueIndex) ==
                   0x00,
               "Variable.valueIndex offset mismatch");
_Static_assert(offsetof(Variable, previousSibling) ==
                   0x02,
               "Variable.previousSibling offset mismatch");
_Static_assert(sizeof(coduo_script_variable_type_name_table_t) ==
                   19 *
                       sizeof(const char *),
               "coduo_script_variable_type_name_table_t size mismatch");
_Static_assert(sizeof(coduo_script_anim_property_name_table_t) ==
                    3 * sizeof(const char *),
               "coduo_script_anim_property_name_table_t size mismatch");
_Static_assert(sizeof(((coduo_script_entity_type_usage_t *)0)->padding02) ==
                   0x02,
               "coduo_script_entity_type_usage_t.padding02 size mismatch");
_Static_assert(sizeof(XAnimState) ==
                   0x1c,
               "XAnimState size mismatch");
_Static_assert(offsetof(XAnimState, time) ==
                   0x00,
               "XAnimState.time offset mismatch");
_Static_assert(offsetof(XAnimState, oldTime) ==
                   0x04,
               "XAnimState.oldTime offset mismatch");
_Static_assert(offsetof(XAnimState, cycleCount) ==
                   0x08,
               "XAnimState.cycleCount offset mismatch");
_Static_assert(offsetof(XAnimState, oldCycleCount) ==
                   0x0a,
               "XAnimState.oldCycleCount offset mismatch");
_Static_assert(offsetof(XAnimState,
                       weightBlendTimeRemaining) ==
                   0x0c,
               "XAnimState.weightBlendTimeRemaining "
               "offset mismatch");
_Static_assert(offsetof(XAnimState, targetWeight) ==
                   0x10,
               "XAnimState.targetWeight mismatch");
_Static_assert(offsetof(XAnimState, currentWeight) ==
                   0x14,
               "XAnimState.currentWeight mismatch");
_Static_assert(offsetof(XAnimState, rateScale) ==
                   0x18,
               "XAnimState.rateScale offset mismatch");
_Static_assert(sizeof(XAnimInfo) == 0x44,
               "XAnimInfo size mismatch");
_Static_assert(sizeof(coduo_xanim_pool_t) ==
                   2048 *
                       sizeof(XAnimInfo),
               "coduo_xanim_pool_t size mismatch");
_Static_assert(offsetof(XAnimInfo, notifyChildIndex) ==
                   0x00,
               "XAnimInfo.notifyChildIndex offset mismatch");
_Static_assert(sizeof(((XAnimInfo *)0)->notifyChildIndex) ==
                   sizeof(uint16_t),
               "XAnimInfo.notifyChildIndex size mismatch");
_Static_assert(offsetof(XAnimInfo, notifyIndex) ==
                   0x02,
               "XAnimInfo.notifyIndex offset mismatch");
_Static_assert(sizeof(((XAnimInfo *)0)->notifyIndex) ==
                   sizeof(int16_t),
               "XAnimInfo.notifyIndex size mismatch");
_Static_assert(offsetof(XAnimInfo, notifyName) ==
                   0x04,
               "XAnimInfo.notifyName offset mismatch");
_Static_assert(sizeof(((XAnimInfo *)0)->notifyName) ==
                   sizeof(uint16_t),
               "XAnimInfo.notifyName size mismatch");
_Static_assert(offsetof(XAnimInfo, notifyType) ==
                   0x06,
               "XAnimInfo.notifyType offset mismatch");
_Static_assert(sizeof(((XAnimInfo *)0)->notifyType) ==
                   sizeof(uint16_t),
               "XAnimInfo.notifyType size mismatch");
_Static_assert(offsetof(XAnimInfo, freePrev) ==
                   0x08,
               "XAnimInfo.freePrev offset mismatch");
_Static_assert(sizeof(((XAnimInfo *)0)->freePrev) ==
                   sizeof(uint16_t),
               "XAnimInfo.freePrev size mismatch");
_Static_assert(offsetof(XAnimInfo, freeNext) ==
                   0x0a,
               "XAnimInfo.freeNext offset mismatch");
_Static_assert(sizeof(((XAnimInfo *)0)->freeNext) ==
                   sizeof(uint16_t),
               "XAnimInfo.freeNext size mismatch");
_Static_assert(offsetof(XAnimInfo, states) ==
                   0x0c,
               "XAnimInfo.states offset mismatch");
_Static_assert(sizeof(((XAnimInfo *)0)->states) ==
                   2 * 0x1c,
               "XAnimInfo.states size mismatch");
#endif

/*
 * Parsed XAnim notetrack entry. Mac names the owning loader ReadNoteTracks;
 * both client and server consumers treat +0x00 as the notetrack-name handle
 * and +0x04 as normalized animation time, never as a child blend weight.
 *
 * Evidence:
 * - The parser at VA 0x80b8058 allocates `count * 8 + 10` bytes, writes the
 *   resulting table pointer to the caller record at +0x14, then advances the
 *   entry cursor by 8 bytes per notetrack.
 * - Each entry receives a 16-bit notetrack-name handle at +0x00 and a float
 *   normalized time at +0x04. The terminal `"end"` entry receives time 1.0
 *   and the following entry stores a zero name-handle sentinel.
 * - The two padding bytes at +0x02 align the following float field; this
 *   parser does not write them.
 */
struct xanim_notetrack_s {
    uint16_t nameHandle;
    uint8_t padding02[2];
    float time;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(xanim_notetrack_t) ==
                   0x08,
               "xanim_notetrack_t size mismatch");
_Static_assert(offsetof(xanim_notetrack_t, nameHandle) ==
                   0x00,
               "xanim_notetrack_t.nameHandle offset mismatch");
_Static_assert(offsetof(xanim_notetrack_t, padding02) ==
                   0x02,
               "xanim_notetrack_t.padding02 offset mismatch");
_Static_assert(sizeof(((xanim_notetrack_t *)0)->padding02) ==
                   2,
               "xanim_notetrack_t.padding02 size mismatch");
_Static_assert(offsetof(xanim_notetrack_t, time) ==
                   0x04,
               "xanim_notetrack_t.time offset mismatch");
#endif

struct xanim_int16_vec2_s {
    int16_t components[2];
};

struct xanim_int16_vec4_s {
    int16_t components[4];
};

union xanim_rotation_stream_data_u {
    xanim_int16_vec4_t *frames4;
    xanim_int16_vec2_t *frames2;
    struct {
        int16_t lane0;
        int16_t lane1;
    } inlinePrefix;
};

union xanim_rotation_stream_tail_u {
    struct {
        int16_t lane2;
        int16_t lane3;
    } inlineFull;
    uint8_t byteKeys[1];
    uint16_t shortKeys[1];
};

/* Both shipped i386 loaders allocate the complete inline quaternion form as
 * exactly 0x0a bytes. Pack(2) preserves the proved common source layout rather
 * than admitting a compiler-rounded 0x0c tail. The stream allocation remains
 * pointer-aligned, and every field after the pointer has only 2-byte alignment,
 * so this packing does not introduce an unaligned pointer access. */
#pragma pack(push, 2)
struct xanim_rotation_stream_s {
    xanim_rotation_stream_data_t data;
    uint16_t frameIndex;
    xanim_rotation_stream_tail_t tail;
};
#pragma pack(pop)

union xanim_translation_stream_data_u {
    vec3_t *frames;
    float inlineLane0;
};

union xanim_translation_stream_key_u {
    uint8_t byteKeys[1];
    uint16_t shortKeys[1];
};

struct xanim_translation_stream_inline_lanes_s {
    float lane1;
    float lane2;
};

/*
 * Translation streams use the bytes at +0x06 as key data for multi-frame keyed
 * streams, while single-frame inline streams store lane1/lane2 at +0x08/+0x0c.
 */
struct xanim_translation_stream_s {
    xanim_translation_stream_data_t data;
    uint16_t frameIndex;
    xanim_translation_stream_key_t key;
    xanim_translation_stream_inline_lanes_t inlineLanes;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(offsetof(xanim_rotation_stream_t, data) == 0,
               "xanim_rotation_stream_t.data offset mismatch");
_Static_assert(offsetof(xanim_rotation_stream_t, frameIndex) == 4,
               "xanim_rotation_stream_t.frameIndex offset mismatch");
_Static_assert(offsetof(xanim_rotation_stream_t, tail) == 6,
               "xanim_rotation_stream_t.tail offset mismatch");
_Static_assert(_Alignof(xanim_rotation_stream_t) == 2,
               "xanim_rotation_stream_t alignment mismatch");
_Static_assert(sizeof(xanim_rotation_stream_t) == 0x0a,
               "xanim_rotation_stream_t size mismatch");
_Static_assert(offsetof(xanim_translation_stream_t, data) == 0,
               "xanim_translation_stream_t.data offset mismatch");
_Static_assert(offsetof(xanim_translation_stream_t, frameIndex) == 4,
               "xanim_translation_stream_t.frameIndex offset mismatch");
_Static_assert(offsetof(xanim_translation_stream_t, key) ==
                   0x06,
               "xanim_translation_stream_t.key offset mismatch");
_Static_assert(offsetof(xanim_translation_stream_t, inlineLanes) ==
                   0x08,
               "xanim_translation_stream_t.inlineLanes offset mismatch");
#endif

/*
 * Per-part pair of pointers installed by XAnimLoadFile.
 *
 * Evidence:
 * - XAnimLoadFile allocates `partCount * 8` bytes and stores the pointer at
 *   loadedRecord +0x10.
 * - Rotation streams are parsed into +0x04 and translation streams into
 *   +0x00, matching the independently recovered Windows declaration.
 */
struct xanim_part_stream_pair_s {
    xanim_translation_stream_t *translation;
    xanim_rotation_stream_t *rotation;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(xanim_part_stream_pair_t) ==
                   0x08,
               "xanim_part_stream_pair_t size mismatch");
_Static_assert(offsetof(xanim_part_stream_pair_t, translation) ==
                   0x00,
               "xanim_part_stream_pair_t.translation offset mismatch");
_Static_assert(offsetof(xanim_part_stream_pair_t, rotation) ==
                   0x04,
               "xanim_part_stream_pair_t.rotation offset mismatch");
#endif

/*
 * Main loaded XAnim record created by XAnimLoadFile.
 *
 * Evidence:
 * - XAnimLoadFile at VA 0x80b816e allocates 0x20 bytes for this record and
 *   stores it into the asset cache entry at +0x04.
 * - The loader writes a frame-count-minus-one word at +0x00, the looped and
 *   delta-motion flags at +0x02/+0x03, frameRate at +0x04, frequency at
 *   +0x08, the part-name handle table at +0x0c, the part stream pair table at
 *   +0x10, notetracks at +0x14, delta-motion streams at +0x18, and the
 *   compressed-rotation bitset at +0x1c.
 * - The parsed 16-bit frame-rate value is converted to float at VA 0x80b835c
 *   and stored at +0x04. VA 0x80b83d5..0x80b8407 derives +0x08 as
 *   frameRate / frameCountMinusOne for multi-frame records.
 */
/* Exact retail type name recovered from Mac XAnimParts signatures. */
struct XAnimParts {
    uint16_t frameCountMinusOne;
    uint8_t looped;
    uint8_t hasDeltaMotion;
    float frameRate;
    float frequency;
    uint16_t *partNameHandles;
    xanim_part_stream_pair_t *partStreamPairs;
    xanim_notetrack_t *noteTracks;
    xanim_part_stream_pair_t *deltaMotion;
    uint8_t *compressedRotationBits;
};

/* Exact generic asset-wrapper tag recovered from Mac XAnimFreeMemory,
 * XModelFree, XModelPartsFree, and XModelSurfsFree signatures. */
union fileDataPayload_u {
    void *generic;
    XAnimParts *xanimParts;
    XModelInfo *xmodelInfo;
    XModelPartsData *xmodelParts;
    XModelSurfsData *xmodelSurfs;
};

struct fileData_s {
    const char *name;
    union fileDataPayload_u data;
    fileDataFree_t freeData;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(fileData_t) == 0x0c,
               "i386 fileData size changed");
_Static_assert(offsetof(fileData_t, name) == 0x00,
               "i386 fileData name moved");
_Static_assert(offsetof(fileData_t, data) == 0x04,
               "i386 fileData payload moved");
_Static_assert(offsetof(fileData_t, freeData) == 0x08,
               "i386 fileData callback moved");
_Static_assert(sizeof(XAnimParts) ==
                   0x20,
               "XAnimParts size mismatch");
_Static_assert(offsetof(XAnimParts, frameCountMinusOne) ==
                   0x00,
               "XAnimParts.frameCountMinusOne mismatch");
_Static_assert(offsetof(XAnimParts, looped) ==
                   0x02,
               "XAnimParts.looped offset mismatch");
_Static_assert(offsetof(XAnimParts, hasDeltaMotion) ==
                   0x03,
               "XAnimParts.hasDeltaMotion offset mismatch");
_Static_assert(offsetof(XAnimParts, frameRate) ==
                   0x04,
               "XAnimParts.frameRate offset mismatch");
_Static_assert(offsetof(XAnimParts, frequency) ==
                   0x08,
               "XAnimParts.frequency offset mismatch");
_Static_assert(offsetof(XAnimParts, partNameHandles) ==
                   0x0c,
               "XAnimParts.partNameHandles mismatch");
_Static_assert(offsetof(XAnimParts, partStreamPairs) ==
                   0x10,
               "XAnimParts.partStreamPairs mismatch");
_Static_assert(offsetof(XAnimParts, noteTracks) ==
                   0x14,
               "XAnimParts.noteTracks offset mismatch");
_Static_assert(offsetof(XAnimParts, deltaMotion) ==
                   0x18,
               "XAnimParts.deltaMotion offset mismatch");
_Static_assert(offsetof(XAnimParts, compressedRotationBits) ==
                   0x1c,
               "XAnimParts.compressedRotationBits offset mismatch");
#endif

/*
 * XAnim tree storage created by the construction helpers after XAnimLoadFile.
 * Mac symbols name this source tree XAnim_s and its entries XAnimEntry.
 *
 * Evidence:
 * - XAnimAllocTree at VA 0x80b966a allocates `nodeCount * 8 + 8`, writes the
 *   tree name pointer at +0x00, and writes nodeCount at +0x04.
 * - XAnimSetLeafNode at VA 0x80b9570 addresses `tree + index * 8 + 8`, clears
 *   the entry child count at +0x00, and stores the resolved xanim asset
 *   pointer at entry +0x04.
 * - XAnimSetParentNode at VA 0x80b95e2 writes entry childCount +0x00,
 *   parent payload words at +0x04/+0x06, and stamps each child entry's
 *   parentIndex at +0x02.
 * - The recursive animtree builder at VA 0x809c876 passes +0x00 from a
 *   first-child coduo_script_variable_node_t lookup into the parent payload word
 *   at entry +0x04, while +0x06 receives the first child tree-entry index.
 */
struct XAnimEntry {
    uint16_t childCount;
    uint16_t parentIndex;
    union {
        fileData_t *leafAsset;
        struct {
            uint16_t flags;
            uint16_t firstChildIndex;
        } parent;
    } payload;
};

struct XAnim_s {
    const char *name;
    uint32_t nodeCount;
    XAnimEntry entries[];
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(XAnimEntry) ==
                   0x08,
               "XAnimEntry size mismatch");
_Static_assert(offsetof(XAnimEntry, childCount) ==
                   0x00,
               "XAnimEntry.childCount offset mismatch");
_Static_assert(offsetof(XAnimEntry, parentIndex) ==
                   0x02,
               "XAnimEntry.parentIndex offset mismatch");
_Static_assert(offsetof(XAnimEntry, payload) ==
                   0x04,
               "XAnimEntry.payload offset mismatch");
_Static_assert(offsetof(XAnimEntry, payload.leafAsset) ==
                    (0x04),
               "XAnimEntry.payload.leafAsset mismatch");
_Static_assert(offsetof(XAnimEntry, payload.parent.flags) ==
                    (0x04),
               "XAnimEntry.payload.parent.flags mismatch");
_Static_assert(offsetof(XAnimEntry,
                       payload.parent.firstChildIndex) ==
                   0x06,
               "XAnimEntry.payload.parent.firstChildIndex mismatch");
_Static_assert(sizeof(XAnim) == 0x08,
               "XAnim header size mismatch");
_Static_assert(offsetof(XAnim, name) ==
                   0x00,
               "XAnim.name offset mismatch");
_Static_assert(offsetof(XAnim, nodeCount) ==
                   0x04,
               "XAnim.nodeCount offset mismatch");
_Static_assert(offsetof(XAnim, entries) ==
                   0x08,
               "XAnim.entries offset mismatch");
#endif

/*
 * Runtime XAnim tree wrapper used by evaluator traversal. Mac symbols name
 * this live wrapper XAnimTree_s, distinct from the source XAnim_s.
 *
 * Evidence:
 * - Allocator at VA 0x80b969a reads the construction-time source tree's
 *   nodeCount, allocates `nodeCount * 8 + 14`, zeros it, and stores the
 *   source tree pointer at +0x00.
 * - The allocator computes the byte size as a 0x0c-byte prefix, a
 *   nodeCount-entry 16-bit pool-node handle table, and a trailing
 *   `(3 * nodeCount + 1)` 16-bit word region. Copy helper VA 0x80b9700
 *   recomputes the same size before delegating to its caller-provided copy
 *   callback. The tail region is intentionally left semantic-neutral.
 * - The pool allocation/free helpers at VA 0x80bf9be and VA 0x80bb6ae
 *   increment/decrement the active pool-node count at +0x04 and write
 *   16-bit pool-node handles at +0x0c + nodeIndex * 2.
 * - Traversal helpers read +0x00 as a XAnim pointer, then use
 *   that source tree's entries while looking up runtime pool handles from
 *   this wrapper's +0x0c table.
 * - DObjConstructRecord at VA 0x80c667a uses +0x08 as a double-buffer
 *   selector for the runtime-tree part-remap handle tables and toggles it
 *   between 0 and 1 after binding state +0x0c to the selected table.
 *   DObjDestroyRecord at VA 0x80c6962 writes the same selector based on
 *   whether the state still references the tree's first cached table.
 */
struct XAnimTree_s {
    XAnim *sourceTree;
    int32_t activePoolNodeCount;
    int32_t partRemapTableSelector;
    uint16_t poolNodeHandles[];
};

struct coduo_xanim_runtime_tree_tail_span_s {
    uint16_t
        words[CODUO_XANIM_TREE_TAIL_WORDS_PER_NODE];
};

/* Same 12-byte deferred-notify queue record as the client. The server word at
 * +0x04 is specifically the script notify handle consumed by Scr_NotifyId;
 * the client view calls its context-specific value notifyType. */
struct xanim_deferred_notify_s {
    const char *name;
    uint16_t notifyHandle;
    uint8_t padding06[2];
    float timeFrac;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(XAnimTree) ==
                   0x0c,
               "XAnimTree prefix size mismatch");
_Static_assert(offsetof(XAnimTree, sourceTree) ==
                   0x00,
               "XAnimTree.sourceTree offset mismatch");
_Static_assert(offsetof(XAnimTree, activePoolNodeCount) ==
                   0x04,
               "XAnimTree.activePoolNodeCount offset mismatch");
_Static_assert(sizeof(((XAnimTree *)0)->activePoolNodeCount) ==
                   sizeof(int32_t),
               "XAnimTree.activePoolNodeCount size mismatch");
_Static_assert(offsetof(XAnimTree,
                        partRemapTableSelector) ==
                   0x08,
               "XAnimTree.partRemapTableSelector offset mismatch");
_Static_assert(sizeof(((XAnimTree *)0)
                          ->partRemapTableSelector) ==
                   sizeof(int32_t),
               "XAnimTree.partRemapTableSelector size mismatch");
_Static_assert(offsetof(XAnimTree, poolNodeHandles) ==
                   0x0c,
               "XAnimTree.poolNodeHandles offset mismatch");
_Static_assert(sizeof(((XAnimTree *)0)->poolNodeHandles[0]) ==
                   sizeof(uint16_t),
               "XAnimTree.poolNodeHandles stride mismatch");
_Static_assert(sizeof(uint16_t) ==
                   0x02,
               "uint16_t stride mismatch");
_Static_assert(sizeof(coduo_xanim_runtime_tree_tail_span_t) ==
                    3 * (0x02),
               "coduo_xanim_runtime_tree_tail_span_t stride mismatch");
_Static_assert(
    sizeof(((coduo_xanim_runtime_tree_tail_span_t *)0)->words[0]) ==
        sizeof(uint16_t),
    "coduo_xanim_runtime_tree_tail_span_t word stride mismatch");
#endif

/*
 * Counted XModel part-name handle table resolved by the collision payload.
 *
 * Evidence:
 * - XModelNumBones at VA 0x80c3f5e follows the model collision
 *   part-name chain and sign-extends the 16-bit count at table +0x00.
 * - XModelBoneNames at VA 0x80c3f76 returns table +0x02.
 * - XModelGetBoneIndex at VA 0x80c3f8e reverse-searches 16-bit handles from
 *   table +0x02 using the signed count.
 */
struct XModelPartNameTable_s {
    int16_t count;
    /* XModelPartsPrecache allocates sizeof(table) plus count - 1 handles.
     * This is the original one-element trailing-array idiom, not capacity one. */
    uint16_t handles[1];
};

/*
 * XModel part-name root chain.
 *
 * Evidence:
 * - XModelNumBones at VA 0x80c3f5e follows model +0x04,
 *   collision +0x00, root +0x04, payload +0x00, slot +0x00, then reads the
 *   part-name table count.
 * - The part-name root is the generic fileData_s asset wrapper named by the
 *   Mac XModelPartsFree(fileData_s *) signature: name at +0x00, parts data at
 *   +0x04, and its release callback at +0x08.
 * - XModelGetBasePose at VA 0x80c4658 reads payload +0x04 as the root-part
 *   count and payload +0x0c/+0x10 as packed base rotation/translation arrays.
 * - DObjCalcAnim at VA 0x80c5df6 uses the same root-part count and
 *   packed base-rotation pointer.
 */
struct XModelPartsData_s {
    XModelPartNameTableSlot *partNameTableSlot;
    int16_t rootPartCount;
    uint8_t padding06[2];
    XModelPartColl *partCollisions;
    xanim_int16_vec4_t *baseRotations;
    vec3_t *baseTranslations;
    uint8_t *partStateIndices;
};

struct XModelPartNameTableSlot_s {
    XModelPartNameTable *partNameTable;
    /* Each byte is the backward model-part delta to a non-root part's parent.
     * The stock childCount + 7 allocation is the i386 sizeof this record plus
     * childCount - 1 more bytes. */
    uint8_t parentPartDeltas[1];
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(XModelPartNameTable) ==
                   0x04,
               "XModelPartNameTable i386 size mismatch");
_Static_assert(offsetof(XModelPartNameTable, count) ==
                   0x00,
               "XModelPartNameTable.count offset mismatch");
_Static_assert(offsetof(XModelPartNameTable, handles) ==
                   0x02,
               "XModelPartNameTable.handles offset mismatch");
_Static_assert(sizeof(((XModelPartNameTable *)0)->handles[0]) ==
                   0x02,
               "XModelPartNameTable handle stride mismatch");
_Static_assert(sizeof(XModelPartsData) == 0x18,
               "XModelPartsData size mismatch");
_Static_assert(offsetof(XModelPartsData, partNameTableSlot) ==
                   0x00,
               "XModelPartsData.partNameTableSlot offset "
               "mismatch");
_Static_assert(offsetof(XModelPartsData, rootPartCount) ==
                   0x04,
               "XModelPartsData.rootPartCount offset "
               "mismatch");
_Static_assert(offsetof(XModelPartsData, padding06) ==
                   0x06,
               "XModelPartsData.padding06 offset mismatch");
_Static_assert(offsetof(XModelPartsData, partCollisions) ==
                   0x08,
               "XModelPartsData.partCollisions offset "
               "mismatch");
_Static_assert(offsetof(XModelPartsData, baseRotations) ==
                   0x0c,
               "XModelPartsData.baseRotations offset "
               "mismatch");
_Static_assert(offsetof(XModelPartsData, baseTranslations) ==
                   0x10,
               "XModelPartsData.baseTranslations offset "
               "mismatch");
_Static_assert(offsetof(XModelPartsData, partStateIndices) ==
                   0x14,
               "XModelPartsData.partStateIndices offset "
               "mismatch");
_Static_assert(offsetof(XModelPartNameTableSlot, partNameTable) ==
                   0x00,
               "XModelPartNameTableSlot.partNameTable offset "
               "mismatch");
_Static_assert(offsetof(XModelPartNameTableSlot,
                        parentPartDeltas) ==
                   0x04,
               "XModelPartNameTableSlot.parentPartDeltas offset "
               "mismatch");
_Static_assert(sizeof(XModelPartNameTableSlot) == 0x08,
               "XModelPartNameTableSlot i386 size mismatch");
#endif

/*
 * XModel base-pose rows are padded 0x40-byte affine matrices.
 *
 * Evidence:
 * - XModelGetBasePose at VA 0x80c4658 advances the caller output by 0x40
 *   per part, initializes root rows as identity axes, writes child axes from
 *   normalized quaternion data, and stores origins at row +0x30/+0x34/+0x38.
 * - XModelTraceLine at VA 0x80c4892 indexes basePose + partIndex * 0x40,
 *   subtracts row origin +0x30/+0x34/+0x38 from start/end, and projects by
 *   the padded axis rows through XSurfaceTransformVectorRows43.
 */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(DObjSkelMat) ==
                   0x40,
               "DObjSkelMat size mismatch");
_Static_assert(offsetof(DObjSkelMat, axis) ==
                   0x00,
               "DObjSkelMat.axis offset mismatch");
_Static_assert(offsetof(DObjSkelMat, origin) ==
                   0x30,
               "DObjSkelMat.origin offset mismatch");
#endif

/*
 * Complete XModel wrapper and model-info payload used by DObj/model helpers.
 *
 * Evidence:
 * - XModelGetName at VA 0x80c432a returns the pointer stored at model +0x00.
 * - XModelGetContents at VA 0x80c4334 follows model +0x04 and reads
 *   contents at collision payload +0x48.
 * - XModelGetBounds at VA 0x80c3ff0 follows model +0x04 and copies mins
 *   from +0x4c..+0x54 and maxs from +0x58..+0x60.
 * - XModelGetNumLods at VA 0x80c4512 reads the signed 16-bit count at
 *   collision payload +0x64. XModelGetLodForDist at VA 0x80c45ae uses the
 *   span starting at +0x04 as three 0x14-byte LOD records.
 * - XModel loader VA 0x80c382c writes LOD record distance/name/count/table
 *   fields at +0x04, +0x08, +0x0c, and +0x10 plus the loaded surfaces pointer
 *   at +0x14 for each record; helpers at VAs 0x80c4050 and 0x80c409e resolve
 *   those same surface and name-table fields.
 * - XModel collision parser VA 0x80c34b2 stores a collision-surface array
 *   pointer/count at payload +0x40/+0x44 and ORs per-surface contents into
 *   payload +0x48.
 * - The same parser allocates `surfaceCount * 0x2c` bytes and fills each
 *   `XModelCollSurf`: facet pointer/count at +0x00/+0x04,
 *   expanded mins/maxs at +0x08/+0x14, base-pose index +0x20, contents +0x24,
 *   and surface flags +0x28. `XModelTraceLine` at VA 0x80c4892 indexes the
 *   same records as `collisionSurfaces + surfaceIndex * 0x2c`.
 * - Facet records allocated from surface `facetCount * 0x30` bytes are three
 *   0x10-byte planes. Parser VA 0x80c34b2 writes twelve float lanes; trace VA
 *   0x80c4892 tests planes at offsets +0x00, +0x10, and +0x20 and copies the
 *   first plane normal into the collision trace result.
 * - XModelNumBones / XModelBoneNames / XModelGetBoneIndex at
 *   VAs 0x80c3f5e, 0x80c3f76, and 0x80c3f8e follow the collision payload
 *   +0x00 part-name root pointer before resolving the counted handle table.
 * - Accessor VA 0x80c4522 sign-extends payload +0x66. The loader copies this
 *   value from the parsed model-file header immediately after the three LOD
 *   distance/name records; no narrower semantic name is proven yet.
 */
struct XModel_s {
    const char *name;
    XModelInfo *info;
    fileDataFree_t freeData;
};

struct XModelSurfsData_s {
    /* Intrusive link used only by the arena-backed cloned-surfaces list. */
    XModelSurfsData *next;
    int16_t surfaceCount;
    uint8_t padding06[2];
    XSurface **surfaces;
};

/* Mac XModelSurfsCloneSurfs proves this is the outer asset wrapper, distinct
 * from the inner 0x0c XModelSurfsData record. */
struct XModelSurfs_s {
    const char *name;
    XModelSurfsData *surfs;
    fileDataFree_t freeData;
};

struct XModelLodInfo_s {
    float distance;
    const char *name;
    int16_t surfaceCount;
    uint8_t padding0a[2];
    uint16_t *surfaceNameTable;
    XModelSurfs *surfs;
};

struct XModelCollTriPlane_s {
    vec3_t normal;
    float distance;
};

struct XModelCollTri_s {
    XModelCollTriPlane
        planes[CODUO_XMODEL_COLLISION_FACET_PLANE_COUNT];
};

struct XModelCollSurf_s {
    XModelCollTri *collTris;
    int32_t numCollTris;
    vec3_t expandedMins;
    vec3_t expandedMaxs;
    int32_t basePoseIndex;
    int32_t contents;
    int32_t surfaceFlags;
};

struct XModelInfo_s {
    fileData_t *parts;
    XModelLodInfo
        lodRecords[CODUO_XMODEL_COLLISION_LOD_RECORD_COUNT];
    XModelCollSurf *collisionSurfaces;
    int32_t collisionSurfaceCount;
    int32_t contents;
    vec3_t mins;
    vec3_t maxs;
    int16_t lodCount;
    int16_t modelFileCount;
};

struct XModelConfigLod_s {
    char name[1024];
    float distance;
};

/* Exact type name recovered from Mac XModelLoadConfigFile. */
struct XModelConfig {
    XModelConfigLod lods[CODUO_XMODEL_COLLISION_LOD_RECORD_COUNT];
    vec3_t mins;
    vec3_t maxs;
    int32_t modelFileCount;
};

/* Exact tag recovered from Mac XSurfaceUnstrip(XStripInfo_s *, ...). */
struct XStripInfo_s {
    int32_t stripCount;
    const uint8_t *stripVertexCounts;
    const uint16_t *stripIndices;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(XModel) == 0x0c,
               "XModel size mismatch");
_Static_assert(offsetof(XModel, name) ==
                   0x00,
               "XModel.name offset mismatch");
_Static_assert(offsetof(XModel, info) ==
                   0x04,
               "XModel.info offset mismatch");
_Static_assert(offsetof(XModel, freeData) ==
                   0x08,
               "XModel.freeData offset mismatch");
_Static_assert(sizeof(XModelSurfsData) == 0x0c,
               "i386 XModelSurfsData size changed");
_Static_assert(offsetof(XModelSurfsData, next) == 0x00,
               "i386 XModelSurfsData link moved");
_Static_assert(offsetof(XModelSurfsData, surfaceCount) == 0x04,
               "i386 XModelSurfsData count moved");
_Static_assert(offsetof(XModelSurfsData, padding06) == 0x06,
               "i386 XModelSurfsData padding moved");
_Static_assert(offsetof(XModelSurfsData, surfaces) == 0x08,
               "i386 XModelSurfsData surfaces moved");
_Static_assert(sizeof(XModelSurfs) == 0x0c,
               "i386 XModelSurfs size changed");
_Static_assert(offsetof(XModelSurfs, name) == 0x00,
               "i386 XModelSurfs name moved");
_Static_assert(offsetof(XModelSurfs, surfs) == 0x04,
               "i386 XModelSurfs payload moved");
_Static_assert(offsetof(XModelSurfs, freeData) == 0x08,
               "i386 XModelSurfs callback moved");
_Static_assert(offsetof(XModelInfo,
                       parts) ==
                   0x00,
               "XModelInfo.parts mismatch");
_Static_assert(sizeof(XModelLodInfo) ==
                   0x14,
               "XModelLodInfo size mismatch");
_Static_assert(offsetof(XModelLodInfo, distance) ==
                   0x00,
               "XModelLodInfo.distance offset mismatch");
_Static_assert(offsetof(XModelLodInfo, name) ==
                   0x04,
               "XModelLodInfo.name offset mismatch");
_Static_assert(offsetof(XModelLodInfo, surfaceCount) ==
                   0x08,
               "XModelLodInfo.surfaceCount offset mismatch");
_Static_assert(offsetof(XModelLodInfo, padding0a) ==
                   0x0a,
               "XModelLodInfo.padding0a offset mismatch");
_Static_assert(sizeof(((XModelLodInfo *)0)->padding0a) ==
                   0x02,
               "XModelLodInfo.padding0a size mismatch");
_Static_assert(offsetof(XModelLodInfo, surfaceNameTable) ==
                   0x0c,
               "XModelLodInfo.surfaceNameTable mismatch");
_Static_assert(offsetof(XModelLodInfo, surfs) ==
                   0x10,
               "XModelLodInfo.surfs offset mismatch");
_Static_assert(sizeof(XModelCollTriPlane) ==
                   0x10,
               "XModelCollTriPlane size mismatch");
_Static_assert(offsetof(XModelCollTriPlane, normal) ==
                   0x00,
               "XModelCollTriPlane.normal mismatch");
_Static_assert(offsetof(XModelCollTriPlane, distance) ==
                   0x0c,
               "XModelCollTriPlane.distance mismatch");
_Static_assert(sizeof(XModelCollTri) ==
                    (0x10) * 3,
               "XModelCollTri size mismatch");
_Static_assert(sizeof(((XModelCollTri *)0)->planes) ==
                   3 *
                       0x10,
               "XModelCollTri.planes size mismatch");
_Static_assert(sizeof(XModelCollSurf) ==
                   0x2c,
               "XModelCollSurf size mismatch");
_Static_assert(offsetof(XModelCollSurf, collTris) ==
                   0x00,
               "XModelCollSurf.collTris mismatch");
_Static_assert(offsetof(XModelCollSurf, numCollTris) ==
                   0x04,
               "XModelCollSurf.numCollTris mismatch");
_Static_assert(offsetof(XModelCollSurf, expandedMins) ==
                   0x08,
               "XModelCollSurf.expandedMins mismatch");
_Static_assert(offsetof(XModelCollSurf, expandedMaxs) ==
                   0x14,
               "XModelCollSurf.expandedMaxs mismatch");
_Static_assert(offsetof(XModelCollSurf, basePoseIndex) ==
                   0x20,
               "XModelCollSurf.basePoseIndex mismatch");
_Static_assert(offsetof(XModelCollSurf, contents) ==
                   0x24,
               "XModelCollSurf.contents mismatch");
_Static_assert(offsetof(XModelCollSurf, surfaceFlags) ==
                   0x28,
               "XModelCollSurf.surfaceFlags mismatch");
_Static_assert(offsetof(XModelInfo,
                       lodRecords) ==
                   0x04,
               "XModelInfo.lodRecords mismatch");
_Static_assert(sizeof(((XModelInfo *)0)
                          ->lodRecords) ==
                   3 *
                       0x14,
               "XModelInfo.lodRecords size mismatch");
_Static_assert(offsetof(XModelInfo,
                       collisionSurfaces) ==
                   0x40,
               "XModelInfo.collisionSurfaces mismatch");
_Static_assert(offsetof(XModelInfo,
                       collisionSurfaceCount) ==
                   0x44,
               "XModelInfo.collisionSurfaceCount mismatch");
_Static_assert(offsetof(XModelInfo, contents) ==
                   0x48,
               "XModelInfo.contents mismatch");
_Static_assert(offsetof(XModelInfo, mins) ==
                   0x4c,
               "XModelInfo.mins offset mismatch");
_Static_assert(offsetof(XModelInfo, maxs) ==
                   0x58,
               "XModelInfo.maxs offset mismatch");
_Static_assert(offsetof(XModelInfo, lodCount) ==
                   0x64,
               "XModelInfo.lodCount mismatch");
_Static_assert(offsetof(XModelInfo,
                       modelFileCount) ==
                   0x66,
               "XModelInfo.modelFileCount mismatch");
_Static_assert(offsetof(XModelInfo,
                       modelFileCount) +
                       sizeof(((XModelInfo *)0)
                                  ->modelFileCount) ==
                   0x68,
               "XModelInfo proven end mismatch");
#endif

/*
 * Fixed XSurface header cloned and queried by the model collision helpers.
 *
 * Evidence:
 * - XSurfaceCloneSurface at VA 0x80c40f0 allocates 0x34 bytes, copies 13
 *   dwords from the source surface, zeros pointer slots at +0x2c/+0x30, then
 *   allocates and copies `vertexCount * 8` bytes for texcoord array +0x24.
 * - Accessors at VAs 0x80c417a, 0x80c4186, 0x80c4192, and 0x80c4296 read
 *   signed/byte scalar fields at +0x02, +0x04, +0x00, and +0x06.
 * - Geometry helpers at VAs 0x80c419e, 0x80c426a, 0x80c427e, 0x80c428a,
 *   0x80c42a2, and 0x80c4342 consume pointers at +0x1c, +0x20, +0x24,
 *   and +0x18.
 * - Model-surface loading populates the 16-byte bone-usage bitset at +0x08,
 *   and DObj part-bit queries consume it as packed words.
 * - XSurfaceGetVerts at VA 0x80c4342 walks the +0x20 payload as either
 *   0x18-byte rigid vertices or primary blended vertices, depending on whether
 *   rigid bone field +0x06 is -1. Blended primary records are 0x20 bytes when
 *   additive count +0x0c is zero, and 0x24 bytes when primary weight +0x20 is
 *   present. Blended vertices also consume 0x14-byte additive records from the
 *   +0x18 vertex-info stream.
 * - The range cleanup helper at VA 0x80c3e74 walks XSurface pointers from the
 *   owning XModel and clears unknown pointer slots +0x2c/+0x30 when either
 *   slot points into the invalidated address range.
 */
struct XSurfaceRigidVert_s {
    vec3_t normal;
    vec3_t position;
};

/* Exact tag recovered from
 * ReadBlend__FP10XSurface_sP18XSimpleBlendInfo_sRPc. */
struct XSimpleBlendInfo_s {
    vec3_t position;
    uint32_t boneMatrixOffset;
};

struct XSurfaceBlendVert_s {
    vec3_t normal;
    int32_t additiveWeightCount;
    XSimpleBlendInfo blend;
    float primaryWeight;
};

struct XSurfaceBlendVertNoWeight_s {
    vec3_t normal;
    int32_t additiveWeightCount;
    XSimpleBlendInfo blend;
};

struct XSurfaceWeightedPoint_s {
    XSimpleBlendInfo blend;
    float weight;
};

union XSurfaceVertexData_u {
    XSurfaceRigidVert *rigidVertices;
    uint8_t *blendPrimaryStream;
};

struct XSurface_s {
    uint8_t tileMode;
    uint8_t padding01;
    int16_t vertexCount;
    int16_t triangleCount;
    int16_t boneIndex;
    uint32_t boneUsage[CODUO_XANIM_PART_BITSET_WORD_COUNT];
    XSurfaceWeightedPoint *weightedPoints;
    uint16_t (*triangles)[CODUO_XSURFACE_TRIANGLE_INDEX_COUNT];
    XSurfaceVertexData vertexData;
    vec2_t *texCoords;
    XSurfaceOptimizedDataARB *optimizedDataARB;
    XSurfaceOptimizedDataATI *optimizedDataATI;
    XSurfaceOptimizedDataNV *optimizedDataNV;
};

struct XModelPartColl_s {
    vec3_t mins;
    vec3_t maxs;
    vec3_t center;
    float radiusSq;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(XSurfaceTriangle) ==
                    3 * sizeof(int16_t),
               "XSurfaceTriangle size mismatch");
_Static_assert(sizeof(XSurfaceTexCoord) ==
                   sizeof(vec2_t),
               "XSurfaceTexCoord size mismatch");
_Static_assert(sizeof(XSurfaceRigidVert) ==
                   0x18,
               "XSurfaceRigidVert size mismatch");
_Static_assert(offsetof(XSurfaceRigidVert, normal) ==
                   0x00,
               "XSurfaceRigidVert.normal offset mismatch");
_Static_assert(offsetof(XSurfaceRigidVert, position) ==
                   0x0c,
               "XSurfaceRigidVert.position offset mismatch");
_Static_assert(sizeof(XSurfaceBlendVert) ==
                   0x24,
               "XSurfaceBlendVert size mismatch");
_Static_assert(offsetof(XSurfaceBlendVert, normal) ==
                   0x00,
               "XSurfaceBlendVert.normal mismatch");
_Static_assert(offsetof(XSurfaceBlendVert,
                        additiveWeightCount) ==
                   0x0c,
               "XSurfaceBlendVert.count mismatch");
_Static_assert(offsetof(XSurfaceBlendVert, blend.position) ==
                   0x10,
               "XSurfaceBlendVert.position mismatch");
_Static_assert(offsetof(XSurfaceBlendVert,
                        blend.boneMatrixOffset) ==
                   0x1c,
               "XSurfaceBlendVert.matrix mismatch");
_Static_assert(offsetof(XSurfaceBlendVert,
                        primaryWeight) ==
                   0x20,
               "XSurfaceBlendVert.weight mismatch");
_Static_assert(sizeof(XSurfaceWeightedPoint) ==
                   0x14,
               "XSurfaceWeightedPoint size mismatch");
_Static_assert(offsetof(XSurfaceWeightedPoint, blend.position) ==
                   0x00,
               "XSurfaceWeightedPoint.position mismatch");
_Static_assert(offsetof(XSurfaceWeightedPoint,
                        blend.boneMatrixOffset) ==
                   0x0c,
               "XSurfaceWeightedPoint.matrix mismatch");
_Static_assert(offsetof(XSurfaceWeightedPoint, weight) ==
                   0x10,
               "XSurfaceWeightedPoint.weight mismatch");
_Static_assert(sizeof(XSurfaceWeightedPoint) ==
                    (0x14),
               "XSurfaceWeightedPoint size mismatch");
_Static_assert(offsetof(XSurfaceWeightedPoint, blend.position) ==
                    (0x00),
               "XSurfaceWeightedPoint.position mismatch");
_Static_assert(offsetof(XSurfaceWeightedPoint, blend.boneMatrixOffset) ==
                    (0x0c),
               "XSurfaceWeightedPoint.matrix mismatch");
_Static_assert(offsetof(XSurfaceWeightedPoint, weight) ==
                    (0x10),
               "XSurfaceWeightedPoint.weight mismatch");
#endif

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(XSurface) == 0x34,
               "XSurface size mismatch");
_Static_assert(offsetof(XSurface, tileMode) ==
                   0x00,
               "XSurface.tileMode offset mismatch");
_Static_assert(sizeof(((XSurface *)0)->tileMode) ==
                   sizeof(uint8_t),
               "XSurface.tileMode size mismatch");
_Static_assert(offsetof(XSurface, padding01) ==
                   0x01,
               "XSurface.padding01 offset mismatch");
_Static_assert(sizeof(((XSurface *)0)->padding01) ==
                   0x01,
               "XSurface.padding01 size mismatch");
_Static_assert(offsetof(XSurface, vertexCount) ==
                   0x02,
               "XSurface.vertexCount offset mismatch");
_Static_assert(sizeof(((XSurface *)0)->vertexCount) ==
                   sizeof(int16_t),
               "XSurface.vertexCount size mismatch");
_Static_assert(offsetof(XSurface, triangleCount) ==
                   0x04,
               "XSurface.triangleCount offset mismatch");
_Static_assert(sizeof(((XSurface *)0)->triangleCount) ==
                   sizeof(int16_t),
               "XSurface.triangleCount size mismatch");
_Static_assert(offsetof(XSurface, boneIndex) ==
                   0x06,
               "XSurface.boneIndex offset mismatch");
_Static_assert(sizeof(((XSurface *)0)->boneIndex) ==
                   sizeof(int16_t),
               "XSurface.boneIndex size mismatch");
_Static_assert(offsetof(XSurface, boneUsage) ==
                   0x08,
               "XSurface.boneUsage offset mismatch");
_Static_assert(sizeof(((XSurface *)0)->boneUsage) ==
                   16,
               "XSurface.boneUsage size mismatch");
_Static_assert(offsetof(XSurface, weightedPoints) ==
                   0x18,
               "XSurface.weightedPoints offset mismatch");
_Static_assert(offsetof(XSurface, triangles) ==
                   0x1c,
               "XSurface.triangles offset mismatch");
_Static_assert(offsetof(XSurface, vertexData) ==
                   0x20,
               "XSurface.vertexData offset mismatch");
_Static_assert(offsetof(XSurface, texCoords) ==
                   0x24,
               "XSurface.texCoords offset mismatch");
_Static_assert(offsetof(XSurface, optimizedDataARB) ==
                   0x28,
               "XSurface.optimizedDataARB offset mismatch");
_Static_assert(sizeof(((XSurface *)0)->optimizedDataARB) ==
                   0x04,
               "XSurface.optimizedDataARB size mismatch");
_Static_assert(offsetof(XSurface, optimizedDataATI) ==
                   0x2c,
               "XSurface.optimizedDataATI offset mismatch");
_Static_assert(offsetof(XSurface, optimizedDataNV) ==
                   0x30,
               "XSurface.optimizedDataNV offset mismatch");
#endif

typedef struct coduo_xmodel_test_lod_distance_s {
    float distance;
    uint8_t abiTail[16];
} coduo_xmodel_test_lod_distance_t;

typedef coduo_xmodel_test_lod_distance_t
    coduo_xmodel_test_lod_distance_table_t
        [CODUO_XMODEL_TEST_LOD_DISTANCE_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_xmodel_test_lod_distance_t) ==
                   0x14,
               "coduo_xmodel_test_lod_distance_t size mismatch");
_Static_assert(offsetof(coduo_xmodel_test_lod_distance_t, distance) ==
                   0x00,
               "coduo_xmodel_test_lod_distance_t.distance offset mismatch");
_Static_assert(offsetof(coduo_xmodel_test_lod_distance_t, abiTail) ==
                   0x04,
               "coduo_xmodel_test_lod_distance_t.abiTail offset mismatch");
_Static_assert(sizeof(((coduo_xmodel_test_lod_distance_t *)0)->abiTail) ==
                   0x10,
               "coduo_xmodel_test_lod_distance_t.abiTail size mismatch");
_Static_assert(sizeof(coduo_xmodel_test_lod_distance_table_t) ==
                   3 *
                       sizeof(coduo_xmodel_test_lod_distance_t),
               "coduo_xmodel_test_lod_distance_table_t size mismatch");
#endif

/*
 * Per-part XAnim evaluator accumulation record.
 *
 * Evidence:
 * - XAnimCalcPartsSmallIndices at VA 0x80b9b72 computes the output address as
 *   `out + partIndex * 0x20`. Its primary stream path accumulates either
 *   four lanes at +0x00..+0x0c or a compact two-lane source into +0x08/+0x0c.
 *   A missing compact source adds the incoming weight to +0x0c.
 * - The same function then accumulates a secondary three-lane source into
 *   +0x14/+0x18/+0x1c and finally adds the incoming contribution weight to
 *   +0x10. XAnimCalcNonLoopEnd at VA 0x80ba782 follows the same
 *   output layout for non-interpolated records.
 * - The same function reads XAnimParts.partStreamPairs and
 *   uses byte/short key search helpers to interpolate source streams into
 *   these lanes. Lane names stay neutral until quaternion/translation roles
 *   are proven against callers.
 */
struct DObjAnimMat_s {
    float primaryLane0;
    float primaryLane1;
    float primaryLane2;
    float primaryLane3;
    float accumulatedWeight;
    float secondaryLane0;
    float secondaryLane1;
    float secondaryLane2;
};

struct coduo_xanim_eval_part_span_s {
    DObjAnimMat slots[2];
};

union coduo_xanim_eval_storage_part_span_view_u {
    coduo_xanim_eval_part_span_t evalParts;
    DObjSkelMat basePose;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(DObjAnimMat) ==
                   0x20,
               "DObjAnimMat size mismatch");
_Static_assert(sizeof(coduo_xanim_eval_part_span_t) ==
                   0x40,
               "coduo_xanim_eval_part_span_t size mismatch");
_Static_assert(sizeof(coduo_xanim_eval_storage_part_span_view_t) ==
                   sizeof(coduo_xanim_eval_part_span_t),
               "coduo_xanim_eval_storage_part_span_view_t size mismatch");
_Static_assert(sizeof(((coduo_xanim_eval_part_span_t *)0)->slots[0]) ==
                   0x20,
               "coduo_xanim_eval_part_span_t slot size mismatch");
_Static_assert(sizeof(((coduo_xanim_eval_storage_part_span_view_t *)0)
                          ->evalParts) ==
                   sizeof(coduo_xanim_eval_part_span_t),
               "coduo_xanim_eval_storage_part_span_view_t evalParts mismatch");
_Static_assert(sizeof(((coduo_xanim_eval_storage_part_span_view_t *)0)
                          ->basePose) == 0x40,
               "coduo_xanim_eval_storage_part_span_view_t basePose mismatch");
_Static_assert(offsetof(DObjAnimMat, primaryLane0) ==
                   0x00,
               "DObjAnimMat.primaryLane0 offset mismatch");
_Static_assert(offsetof(DObjAnimMat, primaryLane1) ==
                   0x04,
               "DObjAnimMat.primaryLane1 offset mismatch");
_Static_assert(offsetof(DObjAnimMat, primaryLane2) ==
                   0x08,
               "DObjAnimMat.primaryLane2 offset mismatch");
_Static_assert(offsetof(DObjAnimMat, primaryLane3) ==
                   0x0c,
               "DObjAnimMat.primaryLane3 offset mismatch");
_Static_assert(offsetof(DObjAnimMat, accumulatedWeight) ==
                   0x10,
               "DObjAnimMat.accumulatedWeight offset mismatch");
_Static_assert(offsetof(DObjAnimMat, secondaryLane0) ==
                   0x14,
               "DObjAnimMat.secondaryLane0 offset mismatch");
_Static_assert(offsetof(DObjAnimMat, secondaryLane1) ==
                   0x18,
               "DObjAnimMat.secondaryLane1 offset mismatch");
_Static_assert(offsetof(DObjAnimMat, secondaryLane2) ==
                   0x1c,
               "DObjAnimMat.secondaryLane2 offset mismatch");
_Static_assert(sizeof(coduo_xanim_part_bitset_t) ==
                   (4 * sizeof(uint32_t)),
               "coduo_xanim_part_bitset_t size mismatch");
#endif

/*
 * Stack-built XAnim part remap buffer interned by XAnimSetModel.
 * The type name is exact from the Mac XAnimCalcData signature; Linux and
 * Windows independently prove the same +0x00 mask and +0x10 byte map.
 *
 * Evidence:
 * - XAnimSetModel at VA 0x80b9752 allocates `partCount + 0x10`
 *   bytes, zeroes four 32-bit words at +0x00..+0x0f, initializes one byte
 *   per target part at +0x10 to 0x7f, and writes matched source part indices
 *   into that byte map.
 * - The same loop sets source-part bits in the 16-byte prefix by byte index
 *   `(sourcePartIndex >> 3)` and mask `1 << (sourcePartIndex & 7)`, then
 *   interns exactly `0x10 + partCount` bytes through the handle helper at
 *   VA 0x80a4884.
 */
struct XAnimToXModel {
    coduo_xanim_part_bitset_t partBits;
    uint8_t boneIndex[];
};

/* The DObj duplicate-part trace record has the same byte boundary but a
 * different payload: one-based source/target pairs terminated by zero. */
struct DObjTracePartRemap_s {
    coduo_xanim_part_bitset_t sourcePartBits;
    uint8_t duplicatePairs[];
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(XAnimToXModel) ==
                   (((4 * sizeof(uint32_t)))),
               "XAnimToXModel prefix size mismatch");
_Static_assert(offsetof(XAnimToXModel, partBits) ==
                   0x00,
               "XAnimToXModel.partBits offset mismatch");
_Static_assert(sizeof(((XAnimToXModel *)0)->partBits) ==
                   (4 * sizeof(uint32_t)),
               "XAnimToXModel.partBits size mismatch");
_Static_assert(offsetof(XAnimToXModel, boneIndex) ==
                   ((4 * sizeof(uint32_t))),
               "XAnimToXModel.boneIndex offset mismatch");
_Static_assert(sizeof(((XAnimToXModel *)0)->boneIndex[0]) ==
                   sizeof(uint8_t),
               "XAnimToXModel.boneIndex stride mismatch");
_Static_assert(sizeof(DObjTracePartRemap) ==
                   (((4 * sizeof(uint32_t)))),
               "DObjTracePartRemap prefix size mismatch");
_Static_assert(offsetof(DObjTracePartRemap, sourcePartBits) ==
                   0x00,
               "DObjTracePartRemap.sourcePartBits offset mismatch");
_Static_assert(offsetof(DObjTracePartRemap, duplicatePairs) ==
                   ((4 * sizeof(uint32_t))),
               "DObjTracePartRemap.duplicatePairs offset mismatch");
#endif

/*
 * Dynamic XAnim evaluator storage pointed to by DObj.
 *
 * Evidence:
 * - DObjCalcAnim at VA 0x80bf2a8 reads state +0x04 as this pointer,
 *   merges the caller mask with the first 16-byte bitset at storage +0x00,
 *   then writes the merged requested bits back to that same bitset.
 * - DObjBindEvalStorage at VA 0x80c6ac4 clears three 16-byte bitsets at
 *   storage +0x00, +0x10, and +0x20. DObj rot/trans mark helpers at VAs
 *   0x80c6bf4 and 0x80c6c76 write the first two bitsets and test the third
 *   as a blocker before marking a requested part.
 * - The same setup path computes the seeded output record pointer as
 *   `storage + 0x30 + partCount * 0x40`, proving a 0x30-byte prefix followed
 *   by two 0x20-byte DObjAnimMat spans per part before that
 *   seeded output base. Individual span roles remain neutral until all
 *   accumulation callers are reconciled.
 * - DObj eval-storage size helper VA 0x80c6a24 returns
 *   `0x30 + partCount * 0x60`, proving a third 0x20-byte span per part after
 *   the seeded output base.
 */
struct coduo_xanim_eval_storage_s {
    coduo_xanim_part_bitset_t evaluatedPartBits;
    coduo_xanim_part_bitset_t controlPartBits;
    coduo_xanim_part_bitset_t blockedPartBits;
    coduo_xanim_eval_storage_part_span_view_t
        partSpans[];
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_xanim_eval_storage_t) ==
                   0x30,
               "coduo_xanim_eval_storage_t prefix size mismatch");
_Static_assert(offsetof(coduo_xanim_eval_storage_t, evaluatedPartBits) ==
                   0x00,
               "coduo_xanim_eval_storage_t.evaluatedPartBits offset mismatch");
_Static_assert(sizeof(((coduo_xanim_eval_storage_t *)0)->evaluatedPartBits) ==
                   (4 * sizeof(uint32_t)),
               "coduo_xanim_eval_storage_t.evaluatedPartBits size mismatch");
_Static_assert(offsetof(coduo_xanim_eval_storage_t, controlPartBits) ==
                    (4 * sizeof(uint32_t)),
               "coduo_xanim_eval_storage_t.controlPartBits offset mismatch");
_Static_assert(sizeof(((coduo_xanim_eval_storage_t *)0)->controlPartBits) ==
                   (4 * sizeof(uint32_t)),
               "coduo_xanim_eval_storage_t.controlPartBits size mismatch");
_Static_assert(offsetof(coduo_xanim_eval_storage_t, blockedPartBits) ==
                    ( (4 * sizeof(uint32_t))) + (4 * sizeof(uint32_t)),
               "coduo_xanim_eval_storage_t.blockedPartBits offset mismatch");
_Static_assert(sizeof(((coduo_xanim_eval_storage_t *)0)->blockedPartBits) ==
                   (4 * sizeof(uint32_t)),
               "coduo_xanim_eval_storage_t.blockedPartBits size mismatch");
_Static_assert(offsetof(coduo_xanim_eval_storage_t, partSpans) ==
                    (0x30),
               "coduo_xanim_eval_storage_t.partSpans offset mismatch");
_Static_assert(sizeof(((coduo_xanim_eval_storage_t *)0)->partSpans[0]) ==
                   sizeof(coduo_xanim_eval_storage_part_span_view_t),
               "coduo_xanim_eval_storage_t.partSpans element size mismatch");
#endif

/*
 * DObj XAnim evaluator-state prefix.
 *
 * Evidence:
 * - DObjCalcAnim at VA 0x80bf2a8 copies state +0x00 to
 *   xanim.currentTree, reads state +0x04 as a coduo_xanim_eval_storage_t
 *   pointer, copies the uint16_t at +0x12, reads byte-sized
 *   child/part counts from +0x16/+0x17, and treats state +0x1c as the inline
 *   child-reference array base.
 * - Evaluator output helper at VA 0x80bdbdc reads state +0x0c as a packed byte
 *   table containing 16-bit handles, caches XAnimSetModel results by part
 *   index, and resolves those handles through the handle table helper before
 *   using the remap bytes.
 * - The state +0x00 pointer is a XAnimTree, which in turn
 *   points to the construction-time XAnim. The gaps remain
 *   opaque until the intermediate builders prove their roles.
 * - DObjCalcAnim stores state +0x1c into xanim.evalChildRefs and then
 *   reads 4-byte child-ref entries through base + childIndex * 4.
 * - XAnim trace helper at VA 0x80c7394 resolves the 16-bit handle at state
 *   +0x14 and uses `XAnimToXModel.boneIndex` at +0x10
 *   while walking candidate children.
 * - XAnim trace helper at VA 0x80c7394 tests `(1 << childIndex)` against
 *   state +0x18 and skips candidate processing when that child bit is set.
 * - DObj skeleton setup wrappers at VAs 0x808ea25 and 0x808eaa2 compare the
 *   32-bit state +0x08 key with global dobj.skelCacheKey through helper
 *   VA 0x80c6a4a; mismatches clear storage and reset the key.
 * - DObj constructor VA 0x80c667a writes state fields at +0x0c, +0x12,
 *   +0x14, +0x16, +0x17, and +0x18. The intervening two bytes at +0x10 are
 *   cleared by DObjRefreshEvalStorageKey; their semantic role is not yet
 *   known.
 *
 * The fixed DObj record below owns this prefix.  Keeping a second C struct
 * with the same leading fields would not make accesses through both types
 * alias-safe.
 */

/*
 * Module-facing DObj model descriptor consumed by CODUO_SYSCALL_DOBJ_CREATE.
 *
 * Evidence:
 * - Syscall wrapper VA 0x808fff6 reads the syscall parameter block as
 *   models, modelCount, tree, entityNum, and gameId before calling the DObj
 *   allocation/create path.
 * - DObj constructor VA 0x80c667a walks the model array in 0x10-byte strides,
 *   copies descriptor +0x00 into childRefs, resolves a nonempty tag-name
 *   pointer at +0x04 into a parent part, copies the +0x08 halfword into the
 *   fixed DObj record at +0x3c, and tests the +0x0c ignore-collision dword
 *   before setting childSkipMask. The constructor skips descriptor +0x0a.
 * - The recovered game module's DObjModel has the same 0x10-byte i386 layout:
 *   XModel pointer, tag-name pointer, negative model index, reserved halfword,
 *   and ignore-collision dword.
 */
struct DObjModel_s {
    XModel *model;
    const char *tagName;
    int16_t negativeModelIndex;
    int16_t reserved_00a;
    int32_t ignoreCollision;
};

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(DObjModel) == 0x10,
               "DObjModel size mismatch");
_Static_assert(offsetof(DObjModel, model) ==
                   0x00,
               "DObjModel.model offset mismatch");
_Static_assert(offsetof(DObjModel, tagName) ==
                   0x04,
               "DObjModel.tagName offset mismatch");
_Static_assert(offsetof(DObjModel, negativeModelIndex) ==
                   0x08,
               "DObjModel.negativeModelIndex offset mismatch");
_Static_assert(sizeof(((DObjModel *)0)->negativeModelIndex) ==
                   sizeof(int16_t),
               "DObjModel.negativeModelIndex size mismatch");
_Static_assert(offsetof(DObjModel, reserved_00a) ==
                   0x0a,
               "DObjModel.reserved_00a offset mismatch");
_Static_assert(sizeof(((DObjModel *)0)->reserved_00a) ==
                   sizeof(int16_t),
               "DObjModel.reserved_00a size mismatch");
_Static_assert(offsetof(DObjModel, ignoreCollision) ==
                   0x0c,
               "DObjModel.ignoreCollision offset mismatch");
_Static_assert(sizeof(((DObjModel *)0)->ignoreCollision) ==
                   sizeof(int32_t),
               "DObjModel.ignoreCollision size mismatch");
#endif

/*
 * Fixed host DObj record stored in the server-side DObj pool.
 *
 * Evidence:
 * - DObj lookup helper VA 0x80725cb indexes 16-bit slot table
 *   `0x8252d00[entityNum]`, multiplies the nonzero slot by 0x5c, and returns
 *   `0x823b300 + slot * 0x5c`.
 * - The DObj create/free helpers at VAs 0x80726c5..0x807291d maintain
 *   two occupancy bits per pool slot in the byte table at 0x8252300 and pass
 *   the selected fixed record to constructor/destructor helpers.
 * - The record begins with the same XAnim evaluator-state prefix consumed by
 *   DObjCalcAnim and the DObj trace helper.
 * - DObj constructor VA 0x80c667a stores 8 packed child slots: child refs at
 *   +0x1c, module DObjModel.negativeModelIndex halfwords at +0x3c,
 *   parent-part indices at +0x4c, and per-child part-base bytes at +0x54.
 *   The parent-part array is initialized to 0xff and later overwritten with
 *   the resolved parent part index plus the previous child part base.
 */
struct DObj_s {
    XAnimTree *runtimeTree;
    coduo_xanim_eval_storage_t *storage;
    int32_t skelCacheKey;
    uint8_t *partRemapTableBytes;
    uint16_t unknownState10;
    uint16_t rootHandle;
    uint16_t tracePartRemapHandle;
    uint8_t childCount;
    uint8_t partCount;
    uint32_t childSkipMask;
    coduo_xanim_eval_child_ref_t childRefs[CODUO_DOBJ_CHILD_SLOT_COUNT];
    int16_t
        childModelIndices[CODUO_DOBJ_CHILD_SLOT_COUNT];
    uint8_t
        childParentPartIndices[CODUO_DOBJ_CHILD_SLOT_COUNT];
    uint8_t
        childPartBaseIndices[CODUO_DOBJ_CHILD_SLOT_COUNT];
};

typedef DObj coduo_dobj_pool_t[CODUO_DOBJ_POOL_COUNT];
typedef uint8_t
    coduo_dobj_occupancy_table_t[CODUO_DOBJ_OCCUPANCY_BYTE_COUNT];
typedef uint16_t
    coduo_dobj_primary_lookup_table_t[CODUO_DOBJ_PRIMARY_LOOKUP_COUNT];
typedef uint16_t
    coduo_dobj_secondary_lookup_table_t[CODUO_DOBJ_SECONDARY_LOOKUP_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(DObj) == 0x5c,
               "DObj size mismatch");
_Static_assert(sizeof(coduo_dobj_pool_t) ==
                   1024 * sizeof(DObj),
               "coduo_dobj_pool_t size mismatch");
_Static_assert(sizeof(coduo_dobj_occupancy_table_t) ==
                   (1024 / 4),
               "coduo_dobj_occupancy_table_t size mismatch");
_Static_assert(sizeof(coduo_dobj_primary_lookup_table_t) ==
                   1152 *
                       sizeof(uint16_t),
               "coduo_dobj_primary_lookup_table_t size mismatch");
_Static_assert(sizeof(coduo_dobj_secondary_lookup_table_t) ==
                   1024 *
                       sizeof(uint16_t),
               "coduo_dobj_secondary_lookup_table_t size mismatch");
_Static_assert(CODUO_DOBJ_CHILD_SLOT_COUNT == 8,
               "DObj child slot count mismatch");
_Static_assert(offsetof(DObj, runtimeTree) ==
                   0x00,
               "DObj.runtimeTree offset mismatch");
_Static_assert(offsetof(DObj, storage) ==
                   0x04,
               "DObj.storage offset mismatch");
_Static_assert(offsetof(DObj, skelCacheKey) ==
                   0x08,
               "DObj.skelCacheKey offset mismatch");
_Static_assert(offsetof(DObj, partRemapTableBytes) ==
                   0x0c,
               "DObj.partRemapTableBytes offset mismatch");
_Static_assert(offsetof(DObj, unknownState10) ==
                   0x10,
               "DObj.unknownState10 offset mismatch");
_Static_assert(sizeof(((DObj *)0)->unknownState10) ==
                   0x02,
               "DObj.unknownState10 size mismatch");
_Static_assert(offsetof(DObj, rootHandle) ==
                   0x12,
               "DObj.rootHandle offset mismatch");
_Static_assert(offsetof(DObj, tracePartRemapHandle) ==
                   0x14,
               "DObj.tracePartRemapHandle offset mismatch");
_Static_assert(offsetof(DObj, childCount) ==
                   0x16,
               "DObj.childCount offset mismatch");
_Static_assert(offsetof(DObj, partCount) ==
                   0x17,
               "DObj.partCount offset mismatch");
_Static_assert(offsetof(DObj, childSkipMask) ==
                   0x18,
               "DObj.childSkipMask offset mismatch");
_Static_assert(offsetof(DObj, childRefs) ==
                    (0x1c),
               "DObj.childRefs offset mismatch");
_Static_assert(sizeof(((DObj *)0)->childRefs) ==
                   8 *
                       sizeof(coduo_xanim_eval_child_ref_t),
               "DObj.childRefs size mismatch");
_Static_assert(offsetof(DObj, childModelIndices) ==
                   0x3c,
               "DObj.childModelIndices offset mismatch");
_Static_assert(sizeof(((DObj *)0)->childModelIndices) ==
                   8 *
                       sizeof(int16_t),
               "DObj.childModelIndices size mismatch");
_Static_assert(offsetof(DObj, childParentPartIndices) ==
                   0x4c,
               "DObj.childParentPartIndices offset mismatch");
_Static_assert(sizeof(((DObj *)0)->childParentPartIndices) ==
                   8 *
                       sizeof(uint8_t),
               "DObj.childParentPartIndices size mismatch");
_Static_assert(offsetof(DObj, childPartBaseIndices) ==
                   0x54,
               "DObj.childPartBaseIndices offset mismatch");
_Static_assert(sizeof(((DObj *)0)->childPartBaseIndices) ==
                   8 *
                       sizeof(uint8_t),
               "DObj.childPartBaseIndices size mismatch");
#endif

/*
 * Null-terminated client-command dispatch table used by
 * SV_ExecuteClientCommand.
 *
 * Evidence:
 * - SV_ExecuteClientCommand at VA 0x808d57a initializes its iterator with
 *   VA 0x80f4f80, compares Cmd_Argv(0) with entry +0x00, calls the function
 *   pointer at entry +0x04 with the host-client pointer, and advances by
 *   8 bytes until the null command sentinel.
 * - The data words at VA 0x80f4f80..0x80f4fd7 decode to ten command/handler
 *   pointer pairs followed by a null/null sentinel.
 */
struct coduo_sv_client_command_handler_s {
    const char *command;
    coduo_sv_client_command_handler_fn handler;
};

typedef coduo_sv_client_command_handler_t
    coduo_sv_client_command_handler_table_t[11];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(coduo_sv_client_command_handler_t) ==
                   0x08,
               "coduo_sv_client_command_handler_t size mismatch");
_Static_assert(offsetof(coduo_sv_client_command_handler_t, command) ==
                   0x00,
               "coduo_sv_client_command_handler_t.command offset mismatch");
_Static_assert(offsetof(coduo_sv_client_command_handler_t, handler) ==
                   0x04,
               "coduo_sv_client_command_handler_t.handler offset mismatch");
_Static_assert(sizeof(coduo_sv_client_command_handler_table_t) ==
                   11 *
                       sizeof(coduo_sv_client_command_handler_t),
               "coduo_sv_client_command_handler_table_t size mismatch");
#endif

/*
 * Sparse host client slot typed through the currently confirmed fields.
 *
 * Evidence:
 * - SV_Startup at VA 0x80914aa allocates sv_maxclients * 0xab0b4 bytes and
 *   stores the base pointer at svs+0x10.
 * - SV_BoundMaxClients at VA 0x80913e2 clamps sv_maxclients to <= 0x40
 *   before SV_Startup allocates the dynamic client table.
 * - VM_Call sites and client helper paths index that allocation with the same
 *   0xab0b4 stride.
 * - Userinfo, reliable command, usercmd, download, netchan, GUID/script ID,
 *   and timing offsets are confirmed by the individual subrecord comments
 *   above. SV_ClearClientScriptPers reads and clears scriptId as a 16-bit
 *   handle. Reserved spans preserve the full slot stride without naming
 *   unknown fields.
 * - SV_SetClientDeferredDropReason at VA 0x808bbff stores a string pointer at
 *   +0x08 only when the client is not already CS_ZOMBIE and no prior reason is
 *   set; SV_AddServerCommand calls it with "EXE_SERVERCOMMANDOVERFLOW", and
 *   SV_DropClient clears the slot at VA 0x808ba2b.
 * - Host-client state transitions are written directly at +0x00:
 *   SVC_DirectConnect sets CS_CONNECTED at VA 0x808b8d7, SV_SendClientGameState
 *   sets CS_PRIMED at VA 0x808bcad, SV_ClientEnterWorld sets CS_ACTIVE at
 *   VA 0x808bf52, and SV_DropClient exits early for CS_ZOMBIE at
 *   VA 0x808ba1e before setting CS_ZOMBIE at VA 0x808ba6a.
 * - The client-command parser at VA 0x808d629 reads a command sequence, stores
 *   it as lastClientCommand at +0x1063c, then formats the command text into a
 *   0x400-byte lastClientCommandString at +0x10640. The checksum decode helper
 *   at VA 0x8095700 uses the same string as a repeating byte stream.
 * - The timeout scan at VA 0x8094e0d increments and clears timeoutCount at
 *   +0x10c2c. Ping calculation at VA 0x8094cad loops 32 frames with a 0x4520
 *   stride and averages frame messageAckedTime - messageSentTime from subfields
 *   +0x4518 and +0x4514. The packet parse path at VA 0x808da83 stores
 *   svs.time into messageAckedTime for the acknowledged frame.
 * - Snapshot construction at VA 0x80982cf fills the frame playerState prefix
 *   and entity/client count/index trailer; SV_SendClientSnapshot at
 *   VA 0x8098a23 stores the outgoing message size at frame +0x451c and
 *   updates nextSnapshotTime at +0x10c24.
 * - Snapshot scheduling at VA 0x8098a23 writes rateDelayed +0x10c28 as a
 *   32-bit flag, and the snapshot writer at VA 0x8096673 ORs snapshot flag
 *   bit 0 when rateDelayed is nonzero.
 * - SV_AddTestClient at VA 0x808de54 stores one in bIsTestClient +0xab088;
 *   SV_AddServerCommand and SV_CheckTimeouts skip clients when it is nonzero.
 * - SV_PacketEvent at VA 0x8094b83 caches the packet server-ID byte in a
 *   32-bit slot at +0xab08c; later packet parsing and command decoding compare
 *   it with the global server ID at VA 0x80f5100.
 * - The PunkBuster client-info helper at VA 0x8094768 copies a 33-byte
 *   string from +0xab090 into the GUID slot of coduo_punkbuster_client_info_t.
 */
struct client_s {
    coduo_client_state_t state;
    int32_t sendAsActive;
    const char *deferredDropReason;
    coduo_host_client_userinfo_t userinfo;
    serverReliableCommandRing_t reliableCommands;
    int32_t reliableSequence;
    int32_t reliableAcknowledge;
    int32_t reliableSent;
    int32_t messageAcknowledge;
    int32_t gamestateMessageNum;
    int32_t challenge;
    coduo_host_client_usercmd_words_t usercmd;
    int32_t lastClientCommand;
    coduo_host_client_command_string_t lastClientCommandString;
    sharedEntity_t *gentity;
    coduo_host_client_name_t name;
    serverClientDownload_t download;
    int32_t deltaMessage;
    int32_t nextReliableTime;
    int32_t lastPacketTime;
    int32_t lastConnectTime;
    int32_t nextSnapshotTime;
    int32_t rateDelayed;
    int32_t timeoutCount;
    coduo_host_client_snapshot_frame_ring_t snapshotFrames;
    int32_t ping;
    int32_t rate;
    int32_t snapshotMsec;
    int32_t pureAuthState;
    netchan_t netchan;
    int32_t guid;
    uint16_t scriptId;
    uint8_t paddingAb086[ (0xab088) - ( (0xab084) + (0x02))];
    qboolean bIsTestClient;
    int32_t serverId;
    coduo_host_punkbuster_guid_t punkbusterGuid;
    uint8_t paddingAb0b1[3];
};

typedef client_t coduo_host_client_table_t[CODUO_MAX_CLIENTS];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(client_t) == 0xab0b4,
               "client_t size mismatch");
_Static_assert(sizeof(coduo_host_client_table_t) ==
                   64 * sizeof(client_t),
               "coduo_host_client_table_t size mismatch");
_Static_assert(offsetof(client_t, state) ==
                   0x00000,
               "client_t.state offset mismatch");
_Static_assert(offsetof(client_t, sendAsActive) ==
                   0x00004,
               "client_t.sendAsActive offset mismatch");
_Static_assert(sizeof(((client_t *)0)->sendAsActive) ==
                   sizeof(int32_t),
               "client_t.sendAsActive size mismatch");
_Static_assert(offsetof(client_t, deferredDropReason) ==
                   0x00008,
               "client_t.deferredDropReason offset mismatch");
_Static_assert(offsetof(client_t, userinfo) ==
                   0x0000c,
               "client_t.userinfo offset mismatch");
_Static_assert(offsetof(client_t, reliableCommands) ==
                   0x0040c,
               "client_t.reliableCommands offset mismatch");
_Static_assert(offsetof(client_t, reliableSequence) ==
                   0x1060c,
               "client_t.reliableSequence offset mismatch");
_Static_assert(offsetof(client_t, reliableAcknowledge) ==
                   0x10610,
               "client_t.reliableAcknowledge offset mismatch");
_Static_assert(offsetof(client_t, reliableSent) ==
                   0x10614,
               "client_t.reliableSent offset mismatch");
_Static_assert(offsetof(client_t, messageAcknowledge) ==
                   0x10618,
               "client_t.messageAcknowledge offset mismatch");
_Static_assert(offsetof(client_t, gamestateMessageNum) ==
                   0x1061c,
               "client_t.gamestateMessageNum offset mismatch");
_Static_assert(offsetof(client_t, challenge) ==
                   0x10620,
               "client_t.challenge offset mismatch");
_Static_assert(offsetof(client_t, usercmd) ==
                   0x10624,
               "client_t.usercmd offset mismatch");
_Static_assert(offsetof(client_t, lastClientCommand) ==
                   0x1063c,
               "client_t.lastClientCommand offset mismatch");
_Static_assert(offsetof(client_t, lastClientCommandString) ==
                   0x10640,
               "client_t.lastClientCommandString offset mismatch");
_Static_assert(sizeof(((client_t *)0)->lastClientCommandString) ==
                    1024,
               "client_t.lastClientCommandString size mismatch");
_Static_assert(offsetof(client_t, gentity) ==
                   0x10a40,
               "client_t.gentity offset mismatch");
_Static_assert(offsetof(client_t, name) ==
                   0x10a44,
               "client_t.name offset mismatch");
_Static_assert(offsetof(client_t, download) ==
                   0x10a64,
               "client_t.download offset mismatch");
_Static_assert(offsetof(client_t, deltaMessage) ==
                   0x10c14,
               "client_t.deltaMessage offset mismatch");
_Static_assert(offsetof(client_t, nextReliableTime) ==
                   0x10c18,
               "client_t.nextReliableTime offset mismatch");
_Static_assert(offsetof(client_t, lastPacketTime) ==
                   0x10c1c,
               "client_t.lastPacketTime offset mismatch");
_Static_assert(offsetof(client_t, lastConnectTime) ==
                   0x10c20,
               "client_t.lastConnectTime offset mismatch");
_Static_assert(offsetof(client_t, nextSnapshotTime) ==
                   0x10c24,
               "client_t.nextSnapshotTime offset mismatch");
_Static_assert(offsetof(client_t, rateDelayed) ==
                    (0x10c24) + sizeof(int32_t),
               "client_t.rateDelayed offset mismatch");
_Static_assert(sizeof(((client_t *)0)->rateDelayed) ==
                   sizeof(int32_t),
               "client_t.rateDelayed size mismatch");
_Static_assert(offsetof(client_t, timeoutCount) ==
                   0x10c2c,
               "client_t.timeoutCount offset mismatch");
_Static_assert(offsetof(client_t, snapshotFrames) ==
                   0x10c30,
               "client_t.snapshotFrames offset mismatch");
_Static_assert(sizeof(((client_t *)0)->snapshotFrames) ==
                    32 * (0x4520),
               "client_t.snapshotFrames size mismatch");
_Static_assert(offsetof(client_t, ping) ==
                   0x9b030,
               "client_t.ping offset mismatch");
_Static_assert(offsetof(client_t, rate) ==
                   0x9b034,
               "client_t.rate offset mismatch");
_Static_assert(offsetof(client_t, snapshotMsec) ==
                   0x9b038,
               "client_t.snapshotMsec offset mismatch");
_Static_assert(offsetof(client_t, pureAuthState) ==
                   0x9b03c,
               "client_t.pureAuthState offset mismatch");
_Static_assert(offsetof(client_t, netchan) ==
                   0x9b040,
               "client_t.netchan offset mismatch");
_Static_assert(offsetof(client_t, guid) ==
                   0xab080,
               "client_t.guid offset mismatch");
_Static_assert(offsetof(client_t, scriptId) ==
                   0xab084,
               "client_t.scriptId offset mismatch");
_Static_assert(sizeof(((client_t *)0)->scriptId) ==
                   0x02,
               "client_t.scriptId size mismatch");
_Static_assert(offsetof(client_t, paddingAb086) ==
                    (0xab084) + (0x02),
               "client_t.paddingAb086 offset mismatch");
_Static_assert(sizeof(((client_t *)0)->paddingAb086) ==
                    (0xab088) - ( (0xab084) + (0x02)),
               "client_t.paddingAb086 size mismatch");
_Static_assert(offsetof(client_t, bIsTestClient) ==
                   0xab088,
               "client_t.bIsTestClient offset mismatch");
_Static_assert(sizeof(((client_t *)0)->bIsTestClient) ==
                   sizeof(int32_t),
               "client_t.bIsTestClient size mismatch");
_Static_assert(offsetof(client_t, serverId) ==
                   0xab08c,
               "client_t.serverId offset mismatch");
_Static_assert(sizeof(((client_t *)0)->serverId) ==
                   sizeof(int32_t),
               "client_t.serverId size mismatch");
_Static_assert(offsetof(client_t, punkbusterGuid) ==
                   0xab090,
               "client_t.punkbusterGuid offset mismatch");
_Static_assert(sizeof(((client_t *)0)->punkbusterGuid) ==
                    (0x21),
               "client_t.punkbusterGuid size mismatch");
_Static_assert(offsetof(client_t, paddingAb0b1) ==
                    (0xab090) + ( (0x21)),
               "client_t.paddingAb0b1 offset mismatch");
_Static_assert(sizeof(((client_t *)0)->paddingAb0b1) ==
                    3,
               "client_t.paddingAb0b1 size mismatch");
#endif

/*
 * Confirmed live/cached/archive snapshot record layouts.
 *
 * Evidence:
 * - SV_SpawnServer allocates live entity-state snapshots as
 *   svs.numSnapshotEntities * 0xf4 bytes at svs+0x24 and live client
 *   snapshots as svs.numSnapshotClients * 0x5c bytes at svs+0x28.
 * - SV_ArchiveSnapshot copies 0xf4-byte live entity-state snapshots and
 *   0x5c-byte live client snapshots before advancing the live ring counters.
 * - SV_ArchiveSnapshot at VA 0x80996f2 indexes cachedSnapshotEntities with a
 *   0x114-byte stride, copies 0xf4 bytes of entity state, then writes flags,
 *   ownerNum, and clip bounds at +0xf4..+0x110.
 * - SV_ArchiveSnapshot at VA 0x80994fe indexes cachedSnapshotClients with a
 *   0x4564-byte stride, stores the player-state-valid flag at +0x00, copies
 *   the 0x5c-byte client snapshot at +0x04, and stores playerState at +0x60.
 * - SV_ArchiveSnapshot and SV_GetCachedSnapshotInternal index
 *   cachedSnapshotFrames
 *   with a 0x1c-byte stride and read/write fields at +0x00, +0x04, +0x08,
 *   +0x0c, +0x10, +0x14, and +0x18. SV_ArchiveSnapshot clears
 *   decodedFromDelta at VA 0x8099468; SV_GetCachedSnapshotInternal sets it at
 *   VA 0x80975d0 only when reconstructing a delta archive frame.
 * - The archived raw snapshot frame index at svs+0x34 uses 0x4b0 entries of
 *   8 bytes; SV_ArchiveSnapshot writes buffer offset +0x00 and byte count
 *   +0x04 before copying into the 0x2000000-byte circular buffer.
 */
typedef coduo_host_snapshot_entity_t coduo_cached_snapshot_entity_t;
typedef coduo_cached_snapshot_entity_t coduo_archived_packet_entity_t;

typedef struct coduo_host_snapshot_entity_record_s {
    coduo_host_entity_state_snapshot_t entityState;
} coduo_host_snapshot_entity_record_t;

typedef struct serverCachedSnapshotClient_s {
    qboolean playerStateValid;
    coduo_host_client_snapshot_t snapshot;
    coduo_archived_client_info_player_state_t playerState;
} serverCachedSnapshotClient_t;

typedef struct serverCachedSnapshotFrame_s {
    int32_t archivedFrameIndex;
    int32_t messageTime;
    int32_t numEntities;
    int32_t firstEntity;
    int32_t numClients;
    int32_t firstClient;
    qboolean decodedFromDelta;
} serverCachedSnapshotFrame_t;

typedef struct snapshotEntityNumbers_s {
    int32_t count;
    int32_t numbers[CODUO_SNAPSHOT_ENTITY_NUMBER_LIST_COUNT];
} snapshotEntityNumbers_t;

typedef struct archivedSnapshotFrameIndex_s {
    int32_t firstByte;
    int32_t byteCount;
} archivedSnapshotFrameIndex_t;

typedef coduo_cached_snapshot_entity_t
    coduo_cached_snapshot_entity_ring_t
        [CODUO_HOST_CACHED_SNAPSHOT_ENTITY_RING_COUNT];
typedef coduo_archived_packet_entity_t
    coduo_archived_packet_entity_ring_t
        [CODUO_HOST_ARCHIVED_PACKET_ENTITY_RING_COUNT];
typedef coduo_host_snapshot_entity_record_t
    coduo_host_snapshot_entity_ring_t
        [CODUO_HOST_SNAPSHOT_ENTITY_RING_COUNT];
typedef serverCachedSnapshotClient_t
    serverCachedSnapshotClientRing_t
        [CODUO_HOST_CACHED_SNAPSHOT_CLIENT_RING_COUNT];
typedef serverCachedSnapshotFrame_t
    serverCachedSnapshotFrameRing_t
        [CODUO_HOST_CACHED_SNAPSHOT_FRAME_RING_COUNT];
typedef archivedSnapshotFrameIndex_t
    archivedSnapshotFrameIndexTable_t
        [CODUO_HOST_ARCHIVED_SNAPSHOT_FRAME_INDEX_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(coduo_host_entity_state_snapshot_t) ==
                   0xf4,
               "coduo_host_entity_state_snapshot_t size mismatch");
_Static_assert(sizeof(trajectory_t) == 0x24,
               "trajectory_t size mismatch");
_Static_assert(offsetof(trajectory_t, trType) == 0x00,
               "trajectory_t.trType offset mismatch");
_Static_assert(offsetof(trajectory_t, trTime) == 0x04,
               "trajectory_t.trTime offset mismatch");
_Static_assert(sizeof(((trajectory_t *)0)->trTime) ==
                   sizeof(int32_t),
               "trajectory_t.trTime size mismatch");
_Static_assert(offsetof(trajectory_t, trDuration) == 0x08,
               "trajectory_t.trDuration offset mismatch");
_Static_assert(sizeof(((trajectory_t *)0)->trDuration) ==
                   sizeof(int32_t),
               "trajectory_t.trDuration size mismatch");
_Static_assert(offsetof(trajectory_t, trBase) == 0x0c,
               "trajectory_t.trBase offset mismatch");
_Static_assert(offsetof(trajectory_t, trDelta) == 0x18,
               "trajectory_t.trDelta offset mismatch");
_Static_assert(sizeof(coduo_host_entity_state_angles2_t) ==
                   sizeof(vec3_t),
               "coduo_host_entity_state_angles2_t size mismatch");
_Static_assert(sizeof(coduo_host_entity_anim_payload_t) == 0x08,
               "coduo_host_entity_anim_payload_t size mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, s_number) ==
                   0x000,
               "coduo_host_entity_state_snapshot_t.s_number mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, s_eType) ==
                   0x004,
               "coduo_host_entity_state_snapshot_t.s_eType mismatch");
_Static_assert(sizeof(((coduo_host_entity_state_snapshot_t *)0)->s_eType) ==
                   sizeof(int32_t),
               "coduo_host_entity_state_snapshot_t.s_eType size mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, s_flags) ==
                   0x008,
               "coduo_host_entity_state_snapshot_t.s_flags mismatch");
_Static_assert(sizeof(((coduo_host_entity_state_snapshot_t *)0)->s_flags) ==
                   sizeof(uint32_t),
               "coduo_host_entity_state_snapshot_t.s_flags size mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, pos) ==
                   0x00c,
               "coduo_host_entity_state_snapshot_t.pos mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, apos) ==
                   0x030,
               "coduo_host_entity_state_snapshot_t.apos mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       entityStateTime) ==
                   0x054,
               "coduo_host_entity_state_snapshot_t.entityStateTime mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       entityStateTime2) ==
                   0x058,
               "coduo_host_entity_state_snapshot_t.entityStateTime2 mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       loopedFxForward) ==
                   0x05c,
               "coduo_host_entity_state_snapshot_t.loopedFxForward mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       entityStateAngles2) ==
                   0x068,
               "coduo_host_entity_state_snapshot_t.entityStateAngles2 mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       vehicleEntityNum) ==
                   0x074,
               "coduo_host_entity_state_snapshot_t.vehicleEntityNum mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, vehicleSlot) ==
                   0x078,
               "coduo_host_entity_state_snapshot_t.vehicleSlot mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       groundEntityNum) ==
                   0x07c,
               "coduo_host_entity_state_snapshot_t.groundEntityNum mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, constantLight) ==
                   0x080,
               "coduo_host_entity_state_snapshot_t.constantLight mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, clientSound) ==
                   0x084,
               "coduo_host_entity_state_snapshot_t.clientSound mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, eventParm) ==
                   0x088,
               "coduo_host_entity_state_snapshot_t.eventParm mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, itemIndex) ==
                   0x08c,
               "coduo_host_entity_state_snapshot_t.itemIndex mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       dobjModelIndexCopy) ==
                   0x090,
               "coduo_host_entity_state_snapshot_t.dobjModelIndexCopy mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, clientNum) ==
                   0x094,
               "coduo_host_entity_state_snapshot_t.clientNum mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, headIcon) ==
                   0x098,
               "coduo_host_entity_state_snapshot_t.headIcon mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, headIconTeam) ==
                   0x09c,
               "coduo_host_entity_state_snapshot_t.headIconTeam mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, solid) ==
                   0x0a0,
               "coduo_host_entity_state_snapshot_t.solid mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, tempEffectId) ==
                   0x0a4,
               "coduo_host_entity_state_snapshot_t.tempEffectId mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, eventCount) ==
                   0x0a8,
               "coduo_host_entity_state_snapshot_t.eventCount mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, events) ==
                   0x0ac,
               "coduo_host_entity_state_snapshot_t.events mismatch");
_Static_assert(sizeof(((coduo_host_entity_state_snapshot_t *)0)->events) ==
                   4 *
                       sizeof(int32_t),
               "coduo_host_entity_state_snapshot_t.events size mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, eventParms) ==
                   0x0bc,
               "coduo_host_entity_state_snapshot_t.eventParms mismatch");
_Static_assert(sizeof(((coduo_host_entity_state_snapshot_t *)0)->eventParms) ==
                   4 *
                       sizeof(int32_t),
               "coduo_host_entity_state_snapshot_t.eventParms size mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, weapon) ==
                   0x0cc,
               "coduo_host_entity_state_snapshot_t.weapon mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, anim) ==
                   0x0d0,
               "coduo_host_entity_state_snapshot_t.anim mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       clientInfoLeanFraction) ==
                   0x0d8,
               "coduo_host_entity_state_snapshot_t.clientInfoLeanFraction mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       hintStringIndex) ==
                   0x0dc,
               "coduo_host_entity_state_snapshot_t.hintStringIndex mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, cursorHint) ==
                   0x0e0,
               "coduo_host_entity_state_snapshot_t.cursorHint mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t,
                       turretOverheatState) ==
                   0x0e4,
               "coduo_host_entity_state_snapshot_t.turretOverheatState mismatch");
_Static_assert(offsetof(coduo_host_entity_state_snapshot_t, entityAngles) ==
                   0x0e8,
               "coduo_host_entity_state_snapshot_t.entityAngles mismatch");
_Static_assert(sizeof(coduo_host_client_snapshot_t) ==
                   0x5c,
               "coduo_host_client_snapshot_t size mismatch");
_Static_assert(offsetof(coduo_host_client_snapshot_t, clientNum) ==
                   0x00,
               "coduo_host_client_snapshot_t.clientNum offset mismatch");
_Static_assert(offsetof(coduo_host_client_snapshot_t, sessionTeam) ==
                   0x04,
               "coduo_host_client_snapshot_t.sessionTeam offset mismatch");
_Static_assert(offsetof(coduo_host_client_snapshot_t, baseModelIndex) ==
                   0x08,
               "coduo_host_client_snapshot_t.baseModelIndex offset mismatch");
_Static_assert(offsetof(coduo_host_client_snapshot_t, attachModelIndices) ==
                   0x0c,
               "coduo_host_client_snapshot_t.attachModelIndices mismatch");
_Static_assert(sizeof(((coduo_host_client_snapshot_t *)0)->attachModelIndices) ==
                   6 *
                       sizeof(int32_t),
               "coduo_host_client_snapshot_t.attachModelIndices size mismatch");
_Static_assert(offsetof(coduo_host_client_snapshot_t, attachTagIndices) ==
                   0x24,
               "coduo_host_client_snapshot_t.attachTagIndices mismatch");
_Static_assert(sizeof(((coduo_host_client_snapshot_t *)0)->attachTagIndices) ==
                   6 *
                       sizeof(int32_t),
               "coduo_host_client_snapshot_t.attachTagIndices size mismatch");
_Static_assert(offsetof(coduo_host_client_snapshot_t, userInfoName) ==
                   0x3c,
               "coduo_host_client_snapshot_t.userInfoName offset mismatch");
_Static_assert(sizeof(((coduo_host_client_snapshot_t *)0)->userInfoName) ==
                   0x20,
               "coduo_host_client_snapshot_t.userInfoName size mismatch");
_Static_assert(sizeof(coduo_archived_client_info_player_state_t) ==
                   sizeof(playerState_t),
               "coduo_archived_client_info_player_state_t size mismatch");
_Static_assert(sizeof(coduo_archived_client_info_meta_t) ==
                    sizeof(coduo_host_client_snapshot_t),
               "coduo_archived_client_info_meta_t size mismatch");
_Static_assert(sizeof(coduo_cached_snapshot_entity_t) ==
                   0x114,
               "coduo_cached_snapshot_entity_t size mismatch");
_Static_assert(sizeof(coduo_cached_snapshot_entity_ring_t) ==
                   0x4000 *
                       sizeof(coduo_cached_snapshot_entity_t),
               "coduo_cached_snapshot_entity_ring_t size mismatch");
_Static_assert(sizeof(coduo_archived_packet_entity_t) ==
                    sizeof(coduo_cached_snapshot_entity_t),
               "coduo_archived_packet_entity_t size mismatch");
_Static_assert(sizeof(coduo_archived_packet_entity_ring_t) ==
                   0x4000 *
                        sizeof(coduo_archived_packet_entity_t),
               "coduo_archived_packet_entity_ring_t size mismatch");
_Static_assert(sizeof(coduo_host_snapshot_entity_record_t) ==
                    sizeof(coduo_host_entity_state_snapshot_t),
               "coduo_host_snapshot_entity_record_t size mismatch");
_Static_assert(sizeof(coduo_host_snapshot_entity_ring_t) ==
                   0x4000 *
                        sizeof(coduo_host_snapshot_entity_record_t),
               "coduo_host_snapshot_entity_ring_t size mismatch");
_Static_assert(offsetof(coduo_cached_snapshot_entity_t, entityState) ==
                   0x00,
               "coduo_cached_snapshot_entity_t.entityState offset mismatch");
_Static_assert(sizeof(((coduo_cached_snapshot_entity_t *)0)->entityState) ==
                   sizeof(coduo_host_entity_state_snapshot_t),
               "coduo_cached_snapshot_entity_t.entityState size mismatch");
_Static_assert(offsetof(coduo_cached_snapshot_entity_t, flags) ==
                   0xf4,
               "coduo_cached_snapshot_entity_t.flags offset mismatch");
_Static_assert(offsetof(coduo_cached_snapshot_entity_t, ownerNum) ==
                   0xf8,
               "coduo_cached_snapshot_entity_t.ownerNum offset mismatch");
_Static_assert(offsetof(coduo_cached_snapshot_entity_t, clipMins) ==
                   0xfc,
               "coduo_cached_snapshot_entity_t.clipMins offset mismatch");
_Static_assert(offsetof(coduo_cached_snapshot_entity_t, clipMaxs) ==
                   0x108,
               "coduo_cached_snapshot_entity_t.clipMaxs offset mismatch");
_Static_assert(sizeof(serverCachedSnapshotClient_t) ==
                   0x4564,
               "serverCachedSnapshotClient_t size mismatch");
_Static_assert(sizeof(serverCachedSnapshotClientRing_t) ==
                   0x1000 *
                       sizeof(serverCachedSnapshotClient_t),
               "serverCachedSnapshotClientRing_t size mismatch");
_Static_assert(offsetof(serverCachedSnapshotClient_t, playerStateValid) ==
                   0x00,
               "serverCachedSnapshotClient_t.playerStateValid offset mismatch");
_Static_assert(offsetof(serverCachedSnapshotClient_t, snapshot) ==
                   0x04,
               "serverCachedSnapshotClient_t.snapshot offset mismatch");
_Static_assert(sizeof(((serverCachedSnapshotClient_t *)0)->snapshot) ==
                   sizeof(coduo_host_client_snapshot_t),
               "serverCachedSnapshotClient_t.snapshot size mismatch");
_Static_assert(offsetof(serverCachedSnapshotClient_t, playerState) ==
                   0x60,
               "serverCachedSnapshotClient_t.playerState offset mismatch");
_Static_assert(sizeof(((serverCachedSnapshotClient_t *)0)->playerState) ==
                   sizeof(playerState_t),
               "serverCachedSnapshotClient_t.playerState size mismatch");
_Static_assert(sizeof(serverCachedSnapshotFrame_t) ==
                   0x1c,
               "serverCachedSnapshotFrame_t size mismatch");
_Static_assert(sizeof(snapshotEntityNumbers_t) ==
                    (0x04) + 1024 * sizeof(int32_t),
               "snapshotEntityNumbers_t size mismatch");
_Static_assert(offsetof(snapshotEntityNumbers_t, count) ==
                   0x00,
               "snapshotEntityNumbers_t.count mismatch");
_Static_assert(offsetof(snapshotEntityNumbers_t, numbers) ==
                   0x04,
               "snapshotEntityNumbers_t.numbers mismatch");
_Static_assert(sizeof(serverCachedSnapshotFrameRing_t) ==
                   0x200 *
                       sizeof(serverCachedSnapshotFrame_t),
               "serverCachedSnapshotFrameRing_t size mismatch");
_Static_assert(offsetof(serverCachedSnapshotFrame_t, archivedFrameIndex) ==
                   0x00,
               "serverCachedSnapshotFrame_t.archivedFrameIndex offset mismatch");
_Static_assert(offsetof(serverCachedSnapshotFrame_t, messageTime) ==
                   0x04,
               "serverCachedSnapshotFrame_t.messageTime offset mismatch");
_Static_assert(offsetof(serverCachedSnapshotFrame_t, numEntities) ==
                   0x08,
               "serverCachedSnapshotFrame_t.numEntities offset mismatch");
_Static_assert(offsetof(serverCachedSnapshotFrame_t, firstEntity) ==
                   0x0c,
               "serverCachedSnapshotFrame_t.firstEntity offset mismatch");
_Static_assert(offsetof(serverCachedSnapshotFrame_t, numClients) ==
                   0x10,
               "serverCachedSnapshotFrame_t.numClients offset mismatch");
_Static_assert(offsetof(serverCachedSnapshotFrame_t, firstClient) ==
                   0x14,
               "serverCachedSnapshotFrame_t.firstClient offset mismatch");
_Static_assert(offsetof(serverCachedSnapshotFrame_t, decodedFromDelta) ==
                   0x18,
               "serverCachedSnapshotFrame_t.decodedFromDelta offset mismatch");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(archivedSnapshotFrameIndex_t) ==
                   0x08,
               "archivedSnapshotFrameIndex_t size mismatch");
_Static_assert(sizeof(archivedSnapshotFrameIndexTable_t) ==
                   0x4b0 *
                       sizeof(archivedSnapshotFrameIndex_t),
               "archivedSnapshotFrameIndexTable_t size mismatch");
_Static_assert(offsetof(archivedSnapshotFrameIndex_t, firstByte) ==
                   0x00,
               "archivedSnapshotFrameIndex_t.firstByte offset mismatch");
_Static_assert(offsetof(archivedSnapshotFrameIndex_t, byteCount) ==
                   0x04,
               "archivedSnapshotFrameIndex_t.byteCount offset mismatch");
#endif
#endif

/*
 * Confirmed server challenge table slot.
 *
 * Evidence:
 * - SVC_GetChallenge at VA 0x80897d4 iterates 1024 slots at a 0x54-byte
 *   stride, copies the netadr at +0x00, writes challenge +0x14,
 *   firstTime +0x20, firstPing +0x24, connected +0x28, and time +0x18.
 * - SV_AuthorizeIpPacket at VA 0x808a1c5 finds a slot by challenge +0x14,
 *   refreshes pingTime +0x1c, parses the numeric GUID into +0x2c, and
 *   copies the 32-byte authGuid string to +0x30.
 * - SVC_DirectConnect copies the challenge GUID value at +0x2c into the
 *   host-client GUID cache at +0xab080.
 * - Rejection paths in SVC_DirectConnect clear the full 0x54-byte slot. The
 *   complete Linux/Windows access census finds no direct read or write at
 *   +0x50..+0x53; these four bytes are an unused tail, not alignment padding.
 */
typedef struct challenge_s {
    netadr_t adr;
    int32_t challenge;
    int32_t time;
    int32_t pingTime;
    int32_t firstTime;
    int32_t firstPing;
    qboolean connected;
    int32_t guid;
    char authGuid[32];
    uint8_t unusedTail[4];
} challenge_t;

typedef challenge_t coduo_challenge_table_t[CODUO_HOST_CHALLENGE_COUNT];

/*
 * Recent authorization GUID cache used by challenge/connection paths.
 *
 * Evidence:
 * - Helper at VA 0x8089ef9 selects an empty or oldest 16-entry slot under
 *   VA 0x850c08c, stores the passed GUID at +0x00, and stores svs.time at
 *   +0x04.
 * - Helper at VA 0x8089d79 searches the same table for a GUID and compares
 *   svs.time - time against a cvar-scaled timeout.
 * - Helper at VA 0x8089e9a returns an empty cache slot, or the slot with the
 *   oldest time when all entries are occupied. Helper at VA 0x8089dfc opens
 *   ban.txt and tokenizes integer GUID entries.
 * - SV_AuthorizeIpPacket and connection follow-up paths call those helpers
 *   with GUID values copied from challenge +0x2c and client +0xab080.
 */
typedef struct coduo_authorize_guid_cache_entry_s {
    int32_t guid;
    int32_t time;
} coduo_authorize_guid_cache_entry_t;

typedef coduo_authorize_guid_cache_entry_t
    coduo_authorize_guid_cache_table_t
        [CODUO_AUTHORIZE_GUID_CACHE_ENTRY_COUNT];

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
_Static_assert(sizeof(challenge_t) == 0x54,
               "challenge_t size mismatch");
_Static_assert(sizeof(coduo_challenge_table_t) ==
                   1024 * 0x54,
               "coduo_challenge_table_t size mismatch");
_Static_assert(offsetof(challenge_t, adr) ==
                   0x00,
               "challenge_t.adr offset mismatch");
_Static_assert(offsetof(challenge_t, challenge) ==
                   0x14,
               "challenge_t.challenge offset mismatch");
_Static_assert(offsetof(challenge_t, time) ==
                   0x18,
               "challenge_t.time offset mismatch");
_Static_assert(offsetof(challenge_t, pingTime) ==
                   0x1c,
               "challenge_t.pingTime offset mismatch");
_Static_assert(offsetof(challenge_t, firstTime) ==
                   0x20,
               "challenge_t.firstTime offset mismatch");
_Static_assert(offsetof(challenge_t, firstPing) ==
                   0x24,
               "challenge_t.firstPing offset mismatch");
_Static_assert(offsetof(challenge_t, connected) ==
                   0x28,
               "challenge_t.connected offset mismatch");
_Static_assert(offsetof(challenge_t, guid) ==
                   0x2c,
               "challenge_t.guid offset mismatch");
_Static_assert(offsetof(challenge_t, authGuid) ==
                   0x30,
               "challenge_t.authGuid offset mismatch");
_Static_assert(sizeof(((challenge_t *)0)->authGuid) ==
                   32,
               "challenge_t.authGuid size mismatch");
_Static_assert(offsetof(challenge_t, unusedTail) ==
                   0x50,
               "challenge_t.unusedTail offset mismatch");
_Static_assert(sizeof(((challenge_t *)0)->unusedTail) ==
                   4,
               "challenge_t.unusedTail size mismatch");
_Static_assert(sizeof(coduo_authorize_guid_cache_entry_t) ==
                   0x08,
               "coduo_authorize_guid_cache_entry_t size mismatch");
_Static_assert(offsetof(coduo_authorize_guid_cache_entry_t, guid) ==
                   0x00,
               "coduo_authorize_guid_cache_entry_t.guid offset mismatch");
_Static_assert(offsetof(coduo_authorize_guid_cache_entry_t, time) ==
                   0x04,
               "coduo_authorize_guid_cache_entry_t.time offset mismatch");
_Static_assert(sizeof(coduo_authorize_guid_cache_table_t) ==
                    16 * 0x08,
               "coduo_authorize_guid_cache_table_t size mismatch");
#endif

/*
 * Confirmed REAL_TIME syscall qtime record.
 *
 * Evidence:
 * - REAL_TIME syscall ID 61 at VA 0x808fbd5 passes its first argument to
 *   Com_RealTime at VA 0x806ba76.
 * - Com_RealTime copies nine consecutive 32-bit localtime fields into the
 *   output qtime record at offsets +0x00 through +0x20, then returns the
 *   Unix time value as an int.
 */
typedef struct qtime_s {
    int32_t tm_sec;
    int32_t tm_min;
    int32_t tm_hour;
    int32_t tm_mday;
    int32_t tm_mon;
    int32_t tm_year;
    int32_t tm_wday;
    int32_t tm_yday;
    int32_t tm_isdst;
} qtime_t;

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
    UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(qtime_t) == 0x24,
               "qtime_t size mismatch");
_Static_assert(offsetof(qtime_t, tm_sec) ==
                   0x00,
               "qtime_t.tm_sec offset mismatch");
_Static_assert(offsetof(qtime_t, tm_min) ==
                   0x04,
               "qtime_t.tm_min offset mismatch");
_Static_assert(offsetof(qtime_t, tm_hour) ==
                   0x08,
               "qtime_t.tm_hour offset mismatch");
_Static_assert(offsetof(qtime_t, tm_mday) ==
                   0x0c,
               "qtime_t.tm_mday offset mismatch");
_Static_assert(offsetof(qtime_t, tm_mon) ==
                   0x10,
               "qtime_t.tm_mon offset mismatch");
_Static_assert(offsetof(qtime_t, tm_year) ==
                   0x14,
               "qtime_t.tm_year offset mismatch");
_Static_assert(offsetof(qtime_t, tm_wday) ==
                   0x18,
               "qtime_t.tm_wday offset mismatch");
_Static_assert(offsetof(qtime_t, tm_yday) ==
                   0x1c,
               "qtime_t.tm_yday offset mismatch");
_Static_assert(offsetof(qtime_t, tm_isdst) ==
                   0x20,
               "qtime_t.tm_isdst offset mismatch");
#endif

#ifdef __cplusplus
}
#endif

#endif /* CODUO_ENGINE_STRUCTS_H */
