#include "../core_math/core_math_private.h"
#include "../core_runtime/core_runtime_private.h"
#include "coduo_int32_bits.h"
#include "coduo_native_x87.h"
#include "coduo_x87emu.h" /* defines EMULATE_X87; x87 shim when it is 1 */
#include "msg_private.h"
#include "netchan_private.h"

#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

enum {
    MSG_DELTA_DEFAULT_INT_BITS = 0,
    MSG_DELTA_ANGLE16_BITS = -100,
    MSG_DELTA_SMALL_INT_BIAS = 0x1000,
    MSG_DELTA_SMALL_INT_BITS = 5,
    MSG_DELTA_SMALL_INT_BYTE_SHIFT = 5,
    MSG_DELTA_SMALL_INT_RANGE = 0x2000,
    MSG_DELTA_BYTE_BITS = 8,
    MSG_DELTA_USERCMD_COMMAND_DELTA_MAX = 255,
    MSG_USERCMD_ACTIVE_PLAYER = 0x80000,
    MSG_USERCMD_SPRINTING = 0x10000,
    MSG_USERCMD_STANCE_CROUCHED = 0x20,
    MSG_USERCMD_STANCE_PRONE = 0x40,
    MSG_USERCMD_BUTTON_SPRINT = 0x08,
    MSG_USERCMD_BUTTON_WALK = 0x10,
    MSG_USERCMD_BUTTON_LEAN_LEFT = 0x10,
    MSG_USERCMD_BUTTON_LEAN_RIGHT = 0x20,
    MSG_USERCMD_BUTTON_PRONE = 0x40,
    MSG_USERCMD_BUTTON_CROUCH = 0x80,
    MSG_USERCMD_STANCE_UPMOVE = -127,
    MSG_DELTA_USERCMD_MOVE_NEGATIVE = -127,
    MSG_DELTA_USERCMD_MOVE_POSITIVE = 127,
    MSG_DELTA_SMALL_MOVE_LIMIT = 10,
    MSG_DELTA_SMALL_MOVE_POSITIVE_FLAG = 0x01,
    MSG_DELTA_SMALL_MOVE_NEGATIVE_FLAG = 0x02,
    MSG_DELTA_SMALL_MOVE_Y_POSITIVE_FLAG = 0x04,
    MSG_DELTA_SMALL_MOVE_Y_NEGATIVE_FLAG = 0x08,
    MSG_DELTA_ENTITY_NUM_BITS = 10,
    MSG_DELTA_ENTITY_ALTERNATE_TRAJECTORY_ETYPE = 12,
    MSG_DELTA_CLIENT_NUM_BITS = 6,
    MSG_DELTA_HUD_COUNT_BITS = 6,
    MSG_DELTA_HUD_LAST_FIELD_BITS = 5,
    MSG_DELTA_PLAYERSTATE_STATS_OFFSET = 0x11c,
    MSG_DELTA_PLAYERSTATE_STATS_COUNT = 6,
    MSG_DELTA_PLAYERSTATE_STATS_BITS = 6,
    MSG_DELTA_PLAYERSTATE_STATS_WEAPON_INDEX = 3,
    MSG_DELTA_PLAYERSTATE_STATS_WEAPON_BITS = 6,
    MSG_DELTA_PLAYERSTATE_AMMO_OFFSET = 0x134,
    MSG_DELTA_PLAYERSTATE_AMMO_CLIP_OFFSET = 0x334,
    MSG_DELTA_PLAYERSTATE_AMMO_GROUP_COUNT = 4,
    MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE = 0x10,
    MSG_DELTA_PLAYERSTATE_OBJECTIVE_STATE_BITS = 3,
    MSG_DELTA_CL_SHOWNET_ENTITY = 2,
    MSG_DELTA_CL_SHOWNET_PLAYERSTATE = -2,
    MSG_DELTA_CL_SHOWNET_VERBOSE = 4,
    NET_PROFILE_SAMPLE_WINDOW_MS = 1000,
    NET_PROFILE_RATE_CALC_INTERVAL_MS = 100,
    NET_PROFILE_EMPTY_MIN_BYTES = 9999,
    NET_SHOWPROFILE_PACKETS = 0x02
};

#define MSG_DELTA_USERCMD_ANGLE_SCALE 182.04445f

typedef void (*msg_delta_extra_writer_fn)(msg_t *msg,
                                          const void *to);

/* NOT_FROM_ORIGINAL_SOURCE: local typed access to descriptor-driven raw payloads. */
static int32_t coduomp_msg_delta_field_int(const void *base,
                                           const netField_t *field)
{
    int32_t value;

    memcpy(&value, (const uint8_t *)base + field->offset, sizeof(value));
    return value;
}

/* NOT_FROM_ORIGINAL_SOURCE: local typed access to descriptor-driven raw payloads. */
static void coduomp_msg_set_delta_field_int(void *base,
                                            const netField_t *field,
                                            int32_t value)
{
    memcpy((uint8_t *)base + field->offset, &value, sizeof(value));
}

/* NOT_FROM_ORIGINAL_SOURCE: preserves the original float-bit write semantics. */
static int32_t coduomp_msg_float_bits(float value)
{
    int32_t bits;

    memcpy(&bits, &value, sizeof(bits));
    return bits;
}

/* NOT_FROM_ORIGINAL_SOURCE: descriptor-table copy for unchanged fields. */
static void coduomp_msg_copy_delta_field(void *to, const void *from,
                                         const netField_t *field)
{
    int32_t value = coduomp_msg_delta_field_int(from, field);

    coduomp_msg_set_delta_field_int(to, field, value);
}

void MSG_WriteDeltaValue(msg_t *msg, int32_t oldValue,
                         int32_t newValue, int32_t bits)
{
    if (oldValue == newValue) {
        MSG_WriteBit0(msg);
        return;
    }

    MSG_WriteBit1(msg);
    MSG_WriteBits(msg, newValue, bits);
}

int32_t MSG_ReadDeltaValue(msg_t *msg, int32_t oldValue, int32_t bits)
{
    if (MSG_ReadBit(msg) == 0) {
        return oldValue;
    }

    return MSG_ReadBits(msg, bits);
}

void MSG_WriteDeltaKey(msg_t *msg, uint32_t key, int32_t oldValue,
                       int32_t newValue, int32_t bits)
{
    if (oldValue == newValue) {
        MSG_WriteBit0(msg);
        return;
    }

    MSG_WriteBit1(msg);
    MSG_WriteBits(msg, key ^ newValue, bits);
}

int32_t MSG_ReadDeltaKey(msg_t *msg, uint32_t key, int32_t oldValue,
                         int32_t bits)
{
    if (MSG_ReadBit(msg) == 0) {
        return oldValue;
    }

    return MSG_ReadBits(msg, bits) ^ (msg_bitmaskTable[bits] & key);
}

void MSG_WriteDeltaKeyChanged(msg_t *msg, uint32_t key,
                              int32_t newValue, int32_t bits)
{
    MSG_WriteBits(msg, key ^ newValue, bits);
}

int32_t MSG_ReadDeltaKeyChanged(msg_t *msg, uint32_t key,
                                int32_t bits)
{
    return MSG_ReadBits(msg, bits) ^ (msg_bitmaskTable[bits] & key);
}

void MSG_WriteDeltaKeyByte(msg_t *msg, uint32_t key, int8_t oldValue,
                           uint32_t newValue)
{
    if (oldValue == (int8_t)newValue) {
        MSG_WriteBit0(msg);
        return;
    }

    MSG_WriteBit1(msg);
    MSG_WriteByte(msg, key ^ newValue);
}

uint32_t MSG_ReadDeltaKeyByte(msg_t *msg, uint8_t key,
                              uint32_t oldValue)
{
    if (MSG_ReadBit(msg) == 0) {
        return oldValue;
    }

    return (uint8_t)(MSG_ReadByte(msg) ^ key);
}

void MSG_WriteDeltaKeyShort(msg_t *msg, uint32_t key, int16_t oldValue,
                            uint32_t newValue)
{
    if (oldValue == (int16_t)newValue) {
        MSG_WriteBit0(msg);
        return;
    }

    MSG_WriteBit1(msg);
    MSG_WriteShort(msg, key ^ newValue);
}

int32_t MSG_ReadDeltaKeyShort(msg_t *msg, uint16_t key,
                              int32_t oldValue)
{
    if (MSG_ReadBit(msg) == 0) {
        return oldValue;
    }

    return (int16_t)(key ^ (uint16_t)MSG_ReadShort(msg));
}

void MSG_WriteReliableCommandToBuffer(const char *in, char *out,
                                      int32_t outSize)
{
    int32_t index;
    char *cursor;
    size_t length = strlen(in);

    if (outSize <= (int32_t)length) {
        Com_Printf("WARNING: Reliable command is too long (%i/%i) and will be truncated: '%s'\n",
                   (int32_t)length, outSize, in);
    }
    if (length == 0) {
        Com_Printf("WARNING: Empty reliable command\n");
    }

    cursor = out;
    for (index = 0; index < outSize && in[index] != '\0'; ++index) {
        *cursor = (char)Q_CleanCharacter((int8_t)in[index]);
        if (*cursor == '%') {
            *cursor = '.';
        }
        ++cursor;
    }

    /* ORIGINAL_BINARY_BUG: a nonpositive output extent reaches the else arm
     * and writes before the destination.  Preserved from
     * 0x08080df7..0x08080e11; see
     * original-bugs/coduomp-zero-size-string-output-underwrites.md. */
    if (index < outSize) {
        out[index] = '\0';
    } else {
        out[outSize - 1] = '\0';
    }
}

void MSG_SetDefaultUserCmd(const playerState_t *playerState, usercmd_t *cmd)
{
    memset(cmd, 0, sizeof(*cmd));
    cmd->weapon = (uint8_t)playerState->currentWeapon;

    for (int axis = 0; axis < 2; ++axis) {
        static const float angleScale = MSG_DELTA_USERCMD_ANGLE_SCALE;
        /* 0x08080e6c..0x08080e85: the product stays live in x87 through the
         * truncating fistp; a native float expression would round it first. */
#if EMULATE_X87
        int32_t packedAngle = x87f_store_i32_trunc(x87f_mul(
            x87f_load_f32(playerState->viewAngles[axis]),
            x87f_load_f32(angleScale)));
#elif defined(__x86_64__)
        int32_t packedAngle = CODUO_X87_TRUNCATE_I32(
            (long double)playerState->viewAngles[axis] *
            (long double)angleScale);
#else
        int32_t packedAngle =
            (int32_t)(playerState->viewAngles[axis] *
                      angleScale);
#endif
        cmd->angles[axis] =
            ((packedAngle & UINT16_MAX) -
             playerState->deltaAngles[axis]) &
            UINT16_MAX;
    }

    if ((playerState->playerStateFlags & MSG_USERCMD_ACTIVE_PLAYER) != 0) {
        if ((playerState->entityStateFlags & MSG_USERCMD_STANCE_PRONE) != 0) {
            cmd->wbuttons |= MSG_USERCMD_BUTTON_PRONE;
            cmd->upmove = MSG_USERCMD_STANCE_UPMOVE;
        } else if ((playerState->entityStateFlags &
                    MSG_USERCMD_STANCE_CROUCHED) != 0) {
            cmd->wbuttons |= MSG_USERCMD_BUTTON_CROUCH;
            cmd->upmove = MSG_USERCMD_STANCE_UPMOVE;
        }

        if (playerState->leanFraction > 0.0f) {
            cmd->wbuttons |= MSG_USERCMD_BUTTON_LEAN_RIGHT;
        } else if (playerState->leanFraction < 0.0f) {
            cmd->wbuttons |= MSG_USERCMD_BUTTON_LEAN_LEFT;
        }
        if (playerState->adsFraction != 0.0f) {
            cmd->buttons |= MSG_USERCMD_BUTTON_WALK;
        }
        if ((playerState->playerStateFlags & MSG_USERCMD_SPRINTING) != 0) {
            cmd->buttons |= MSG_USERCMD_BUTTON_SPRINT;
        }
    }
}

int32_t MSG_HorMoveFrom(int32_t x, int32_t y)
{
    int32_t flags = 0;

    if (x > MSG_DELTA_SMALL_MOVE_LIMIT) {
        flags = MSG_DELTA_SMALL_MOVE_POSITIVE_FLAG;
    } else if (x < -MSG_DELTA_SMALL_MOVE_LIMIT) {
        flags = MSG_DELTA_SMALL_MOVE_NEGATIVE_FLAG;
    }
    if (y > MSG_DELTA_SMALL_MOVE_LIMIT) {
        flags |= MSG_DELTA_SMALL_MOVE_Y_POSITIVE_FLAG;
    } else if (y < -MSG_DELTA_SMALL_MOVE_LIMIT) {
        flags |= MSG_DELTA_SMALL_MOVE_Y_NEGATIVE_FLAG;
    }

    return flags;
}

int32_t MSG_VertMoveFrom(int32_t value)
{
    if (value > MSG_DELTA_SMALL_MOVE_LIMIT) {
        return MSG_DELTA_SMALL_MOVE_POSITIVE_FLAG;
    }
    if (value < -MSG_DELTA_SMALL_MOVE_LIMIT) {
        return MSG_DELTA_SMALL_MOVE_NEGATIVE_FLAG;
    }
    return 0;
}

void MSG_HorMoveTo(int32_t flags, int8_t *x, int8_t *y)
{
    if ((flags & MSG_DELTA_SMALL_MOVE_POSITIVE_FLAG) != 0) {
        *x = MSG_DELTA_USERCMD_MOVE_POSITIVE;
    } else if ((flags & MSG_DELTA_SMALL_MOVE_NEGATIVE_FLAG) != 0) {
        *x = MSG_DELTA_USERCMD_MOVE_NEGATIVE;
    } else {
        *x = 0;
    }

    if ((flags & MSG_DELTA_SMALL_MOVE_Y_POSITIVE_FLAG) != 0) {
        *y = MSG_DELTA_USERCMD_MOVE_POSITIVE;
    } else if ((flags & MSG_DELTA_SMALL_MOVE_Y_NEGATIVE_FLAG) != 0) {
        *y = MSG_DELTA_USERCMD_MOVE_NEGATIVE;
    } else {
        *y = 0;
    }
}

void MSG_VertMoveTo(int32_t flags, int8_t *value)
{
    if ((flags & MSG_DELTA_SMALL_MOVE_POSITIVE_FLAG) != 0) {
        *value = MSG_DELTA_USERCMD_MOVE_POSITIVE;
    } else if ((flags & MSG_DELTA_SMALL_MOVE_NEGATIVE_FLAG) != 0) {
        *value = MSG_DELTA_USERCMD_MOVE_NEGATIVE;
    } else {
        *value = 0;
    }
}

void MSG_WriteDeltaUsercmdKey(msg_t *msg, uint32_t key,
                              const usercmd_t *from,
                              const usercmd_t *to)
{
    int32_t newMove2;
    int32_t oldMove2;
    int32_t newMove1;
    int32_t oldMove1;

    if ((uint32_t)(to->commandTime - from->commandTime) <
        MSG_DELTA_USERCMD_COMMAND_DELTA_MAX + 1U) {
        MSG_WriteBit1(msg);
        MSG_WriteByte(msg, to->commandTime - from->commandTime);
    } else {
        MSG_WriteBit0(msg);
        MSG_WriteLong(msg, to->commandTime);
    }

    /* 0x080810f9..0x08081154: stock emits command time before deriving these
     * summaries, then calls the two-axis and one-axis packers in to/from
     * order.  Keep that ordering explicit because the ABI does not make the
     * input records non-aliasing. */
    newMove2 = MSG_HorMoveFrom(to->forwardmove, to->rightmove);
    oldMove2 = MSG_HorMoveFrom(from->forwardmove, from->rightmove);
    newMove1 = MSG_VertMoveFrom(to->upmove);
    oldMove1 = MSG_VertMoveFrom(from->upmove);

    if (((from->buttons >> 1) == (to->buttons >> 1)) &&
        from->wbuttons == to->wbuttons &&
        from->weapon == to->weapon &&
        from->angles[2] == to->angles[2] &&
        oldMove1 == newMove1) {
        if (from->angles[0] == to->angles[0] &&
            from->angles[1] == to->angles[1] &&
            (from->buttons & 0x01) == (to->buttons & 0x01) &&
            oldMove2 == newMove2) {
            MSG_WriteDeltaKeyChanged(msg, key, 0, 1);
            return;
        }

        MSG_WriteDeltaKeyChanged(msg, key, 1, 1);
        MSG_WriteDeltaKeyChanged(msg, key, 0, 1);
        key ^= (uint32_t)to->commandTime;
        MSG_WriteDeltaKeyChanged(msg, key, to->buttons & 0x01, 1);
        MSG_WriteDeltaKeyShort(msg, key, from->angles[0],
                               to->angles[0]);
        MSG_WriteDeltaKeyShort(msg, key, from->angles[1],
                               to->angles[1]);
        MSG_WriteDeltaKey(msg, key, oldMove2, newMove2, 4);
        return;
    }

    MSG_WriteDeltaKeyChanged(msg, key, 1, 1);
    MSG_WriteDeltaKeyChanged(msg, key, 1, 1);
    MSG_WriteDeltaKeyChanged(msg, key, to->buttons & 0x01, 1);
    MSG_WriteDeltaKeyShort(msg, key, from->angles[0], to->angles[0]);
    MSG_WriteDeltaKeyShort(msg, key, from->angles[1], to->angles[1]);
    MSG_WriteDeltaKey(msg, key, oldMove2, newMove2, 4);
    key ^= (uint32_t)to->commandTime;
    MSG_WriteDeltaKeyShort(msg, key, from->angles[2], to->angles[2]);
    MSG_WriteDeltaKey(msg, key, from->buttons >> 1,
                      to->buttons >> 1, 6);
    MSG_WriteDeltaKeyByte(msg, key, from->wbuttons, to->wbuttons);
    MSG_WriteDeltaKey(msg, key, oldMove1, newMove1, 2);
    MSG_WriteDeltaKey(msg, key, from->weapon, to->weapon, 7);
}

void MSG_ReadDeltaUsercmdKey(msg_t *msg, uint32_t key,
                             const usercmd_t *from,
                             usercmd_t *to)
{
    memcpy(to, from, sizeof(*to));

    if (MSG_ReadBit(msg) == 0) {
        to->commandTime = MSG_ReadLong(msg);
    } else {
        to->commandTime = from->commandTime + MSG_ReadByte(msg);
    }

    if (MSG_ReadDeltaKeyChanged(msg, key, 1) == 0) {
        return;
    }

    to->buttons &= 0xfe;
    if (MSG_ReadDeltaKeyChanged(msg, key, 1) == 0) {
        key ^= (uint32_t)to->commandTime;
        to->buttons |= MSG_ReadDeltaKeyChanged(msg, key, 1);
        to->angles[0] =
            MSG_ReadDeltaKeyShort(msg, key, from->angles[0]) & UINT16_MAX;
        to->angles[1] =
            MSG_ReadDeltaKeyShort(msg, key, from->angles[1]) & UINT16_MAX;
        MSG_HorMoveTo(
            MSG_ReadDeltaKey(msg, key,
                             MSG_HorMoveFrom(from->forwardmove,
                                             from->rightmove),
                             4),
            &to->forwardmove, &to->rightmove);
        return;
    }

    to->buttons |= MSG_ReadDeltaKeyChanged(msg, key, 1);
    to->angles[0] =
        MSG_ReadDeltaKeyShort(msg, key, from->angles[0]) & UINT16_MAX;
    to->angles[1] =
        MSG_ReadDeltaKeyShort(msg, key, from->angles[1]) & UINT16_MAX;
    MSG_HorMoveTo(
        MSG_ReadDeltaKey(msg, key,
                         MSG_HorMoveFrom(from->forwardmove,
                                         from->rightmove),
                         4),
        &to->forwardmove, &to->rightmove);
    key ^= (uint32_t)to->commandTime;
    to->angles[2] =
        MSG_ReadDeltaKeyShort(msg, key, from->angles[2]) & UINT16_MAX;
    /* 0x08081766..0x080817ad: stock publishes the retained low button bit
     * before consuming the six-bit upper payload. */
    to->buttons &= 0x01;
    to->buttons =
        (uint8_t)((MSG_ReadDeltaKey(msg, key, from->buttons >> 1, 6)
                   << 1) |
                  to->buttons);
    to->wbuttons =
        (uint8_t)MSG_ReadDeltaKeyByte(msg, key, from->wbuttons);
    MSG_VertMoveTo(
        MSG_ReadDeltaKey(msg, key,
                         MSG_VertMoveFrom(from->upmove), 2),
        &to->upmove);
    to->weapon =
        (uint8_t)MSG_ReadDeltaKey(msg, key, from->weapon, 7);
}

void MSG_WriteDeltaField(msg_t *msg, const void *from, const void *to,
                         const netField_t *field)
{
    int32_t newValue = coduomp_msg_delta_field_int(to, field);
    int32_t oldValue = coduomp_msg_delta_field_int(from, field);

    if (oldValue == newValue) {
        MSG_WriteBit0(msg);
        return;
    }

    MSG_WriteBit1(msg);
    if (field->bits == MSG_DELTA_DEFAULT_INT_BITS) {
        float newFloat;
        int32_t rounded;

        memcpy(&newFloat, &newValue, sizeof(newFloat));
#if defined(__x86_64__)
        rounded = CODUO_X87_TRUNCATE_I32((long double)newFloat);
#else
        rounded = (int32_t)newFloat;
#endif

        if (newFloat == 0.0f) {
            MSG_WriteBit0(msg);
        } else {
            MSG_WriteBit1(msg);
            /* no (float) cast on rounded: stock compares the bare fild
             * against newFloat with no intermediate float store (0x80818f2) */
            if (rounded == newFloat &&
                rounded + MSG_DELTA_SMALL_INT_BIAS >= 0 &&
                rounded + MSG_DELTA_SMALL_INT_BIAS < MSG_DELTA_SMALL_INT_RANGE) {
                MSG_WriteBit0(msg);
                MSG_WriteBits(msg, rounded + MSG_DELTA_SMALL_INT_BIAS,
                              MSG_DELTA_SMALL_INT_BITS);
                MSG_WriteByte(msg,
                              (rounded + MSG_DELTA_SMALL_INT_BIAS) >>
                                  MSG_DELTA_SMALL_INT_BYTE_SHIFT);
            } else {
                MSG_WriteBit1(msg);
                MSG_WriteLong(msg, coduomp_msg_float_bits(newFloat));
            }
        }
    } else if (field->bits == MSG_DELTA_ANGLE16_BITS) {
        if (newValue == 0) {
            MSG_WriteBit0(msg);
        } else {
            float newFloat;

            memcpy(&newFloat, &newValue, sizeof(newFloat));
            MSG_WriteBit1(msg);
            MSG_WriteAngle16(msg, newFloat);
        }
    } else {
        uint32_t bitCount = (uint32_t)field->bits;
        /* Stock uses SAR between emitted low chunks. Logical shifts of the raw
         * dword preserve every emitted low bit/byte; only discarded sign fill
         * differs, avoiding implementation-defined C behavior. */
        uint32_t valueBits = coduo_int32_bits(newValue);
        uint32_t remaining;
        uint32_t lowBits;

        if (newValue == 0) {
            MSG_WriteBit0(msg);
            return;
        }

        MSG_WriteBit1(msg);
        if (field->bits < 0) {
            /* Stock NEG is modulo 2^32 even for INT32_MIN. */
            bitCount = UINT32_C(0) - (uint32_t)field->bits;
        }
        remaining = bitCount;
        lowBits = bitCount & 0x07;
        if (lowBits != 0) {
            MSG_WriteBits(msg, coduo_int32_from_bits(valueBits),
                          (int32_t)lowBits);
            remaining = bitCount - lowBits;
            valueBits >>= lowBits;
        }
        while (remaining != 0) {
            MSG_WriteByte(msg, (int32_t)(valueBits & UINT32_C(0xff)));
            valueBits >>= MSG_DELTA_BYTE_BITS;
            remaining -= MSG_DELTA_BYTE_BITS;
        }
    }
}

void MSG_WriteDeltaFields(msg_t *msg, const void *from,
                          const void *to, qboolean force, int32_t count,
                          const netField_t *fields)
{
    qboolean changed = force;

    if (force == qfalse) {
        for (int32_t index = 0; index < count; ++index) {
            if (coduomp_msg_delta_field_int(from, &fields[index]) !=
                coduomp_msg_delta_field_int(to, &fields[index])) {
                changed = qtrue;
                break;
            }
        }
        if (changed == qfalse) {
            MSG_WriteBit0(msg);
            return;
        }
    }

    MSG_WriteBit1(msg);
    for (int32_t index = 0; index < count; ++index) {
        MSG_WriteDeltaField(msg, from, to, &fields[index]);
    }
}

void MSG_WriteDeltaStruct(msg_t *msg, const void *from, const void *to,
                          qboolean force, int32_t count, int32_t numBits,
                          const netField_t *fields,
                          msg_delta_extra_writer_fn extraWriter,
                          qboolean writeForceBit)
{
    int32_t lastChanged;

    if (to == NULL) {
        if (cl_shownet != NULL &&
            (cl_shownet->integer > 1 ||
             cl_shownet->integer == -1)) {
            Com_Printf("W|%3i: #%-3i remove\n", msg->cursize,
                       *(const int32_t *)from);
        }
        if (writeForceBit != qfalse) {
            MSG_WriteBit1(msg);
        }
        MSG_WriteBits(msg, *(const int32_t *)from, numBits);
        if (extraWriter != NULL) {
            extraWriter(msg, NULL);
        }
        MSG_WriteBit1(msg);
        return;
    }

    lastChanged = 0;
    for (int32_t index = 0; index < count; ++index) {
        if (coduomp_msg_delta_field_int(from, &fields[index]) !=
            coduomp_msg_delta_field_int(to, &fields[index])) {
            lastChanged = index + 1;
        }
    }

    if (lastChanged == 0) {
        if (force != qfalse) {
            if (writeForceBit != qfalse) {
                MSG_WriteBit1(msg);
            }
            MSG_WriteBits(msg, *(const int32_t *)to, numBits);
            if (extraWriter != NULL) {
                extraWriter(msg, to);
            }
            MSG_WriteBit0(msg);
            MSG_WriteBit0(msg);
        }
        return;
    }

    if (writeForceBit != qfalse) {
        MSG_WriteBit1(msg);
    }
    MSG_WriteBits(msg, *(const int32_t *)to, numBits);
    if (extraWriter != NULL) {
        extraWriter(msg, to);
    }
    MSG_WriteBit0(msg);
    MSG_WriteBit1(msg);
    MSG_WriteByte(msg, lastChanged);
    for (int32_t index = 0; index < lastChanged; ++index) {
        MSG_WriteDeltaField(msg, from, to, &fields[index]);
    }
}

void MSG_WriteDeltaEntity_ChangedCallback(msg_t *msg, const void *entity)
{
    if (entity == NULL) {
        MSG_WriteBit0(msg);
    } else if (((const coduo_host_entity_state_snapshot_t *)entity)->s_eType ==
               MSG_DELTA_ENTITY_ALTERNATE_TRAJECTORY_ETYPE) {
        MSG_WriteBit1(msg);
    } else {
        MSG_WriteBit0(msg);
    }
}

void MSG_WriteDeltaEntity(msg_t *msg,
                          const coduo_host_entity_state_snapshot_t *from,
                          const coduo_host_entity_state_snapshot_t *to,
                          qboolean force)
{
    if (to == NULL) {
        MSG_WriteDeltaStruct(msg, from, NULL, force, MSG_DELTA_ENTITY_FIELD_COUNT,
                             MSG_DELTA_ENTITY_NUM_BITS,
                             msg_entityDefaultNetFields,
                             MSG_WriteDeltaEntity_ChangedCallback, qfalse);
    } else if (to->s_eType == MSG_DELTA_ENTITY_ALTERNATE_TRAJECTORY_ETYPE) {
        MSG_WriteDeltaStruct(msg, from, to, force, MSG_DELTA_ENTITY_FIELD_COUNT,
                             MSG_DELTA_ENTITY_NUM_BITS,
                             msg_entityAltTrajectoryNetFields,
                             MSG_WriteDeltaEntity_ChangedCallback, qfalse);
    } else {
        MSG_WriteDeltaStruct(msg, from, to, force, MSG_DELTA_ENTITY_FIELD_COUNT,
                             MSG_DELTA_ENTITY_NUM_BITS,
                             msg_entityDefaultNetFields,
                             MSG_WriteDeltaEntity_ChangedCallback, qfalse);
    }
}

void MSG_WriteDeltaArchivedEntity(msg_t *msg,
                                  const coduo_host_entity_baseline_t *from,
                                  const coduo_cached_snapshot_entity_t *to,
                                  qboolean force)
{
    MSG_WriteDeltaStruct(msg, from, to, force, MSG_DELTA_ENTITY_BASE_FIELD_COUNT,
                         MSG_DELTA_ENTITY_NUM_BITS, msg_entityBaselineNetFields,
                         NULL, qfalse);
}

void MSG_WriteDeltaClient(msg_t *msg,
                          const coduo_host_client_snapshot_t *from,
                          const coduo_host_client_snapshot_t *to,
                          qboolean force)
{
    coduo_host_client_snapshot_t nullClient;

    if (from == NULL) {
        memset(&nullClient, 0, sizeof(nullClient));
        from = &nullClient;
    }

    MSG_WriteDeltaStruct(msg, from, to, force, MSG_DELTA_CLIENT_FIELD_COUNT,
                         MSG_DELTA_CLIENT_NUM_BITS, msg_clientNetFields, NULL,
                         qtrue);
}

void MSG_ReadDeltaField(msg_t *msg, const void *from, void *to,
                        const netField_t *field, qboolean print)
{
    float value;

    if (MSG_ReadBit(msg) == 0) {
        coduomp_msg_copy_delta_field(to, from, field);
        return;
    }

    if (field->bits == MSG_DELTA_DEFAULT_INT_BITS) {
        if (MSG_ReadBit(msg) == 0) {
            value = 0.0f;
        } else {
            if (MSG_ReadBit(msg) == 0) {
                uint32_t smallBits =
                    (uint32_t)MSG_ReadBits(msg, MSG_DELTA_SMALL_INT_BITS);
                int32_t small;

                smallBits +=
                    (uint32_t)MSG_ReadByte(msg)
                    << MSG_DELTA_SMALL_INT_BYTE_SHIFT;
                smallBits -= MSG_DELTA_SMALL_INT_BIAS;
                small = (int32_t)smallBits;
                value = (float)small;
                memcpy((uint8_t *)to + field->offset, &value, sizeof(value));
                if (print != qfalse) {
                    Com_Printf("%s:%i ", field->name, small);
                }
            } else {
                int32_t bits = MSG_ReadLong(msg);

                memcpy(&value, &bits, sizeof(value));
                memcpy((uint8_t *)to + field->offset, &value, sizeof(value));
                if (print != qfalse) {
                    Com_Printf("%s:%f ", field->name, (double)value);
                }
            }
            return;
        }
        memcpy((uint8_t *)to + field->offset, &value, sizeof(value));
        return;
    }

    if (field->bits == MSG_DELTA_ANGLE16_BITS) {
        value = MSG_ReadBit(msg) == 0 ? 0.0f : MSG_ReadAngle16(msg);
        memcpy((uint8_t *)to + field->offset, &value, sizeof(value));
        return;
    }

    if (MSG_ReadBit(msg) == 0) {
        int32_t zero = 0;

        coduomp_msg_set_delta_field_int(to, field, zero);
        return;
    }

    int32_t bitCount = field->bits;
    uint32_t lowBits;
    uint32_t valueBits;

    if (bitCount < 0) {
        /* Stock keeps the NEG result and the byte-loop bound signed. */
        bitCount = -bitCount;
    }
    lowBits = (uint32_t)bitCount & 0x07;
    valueBits = lowBits == 0 ? 0 : (uint32_t)MSG_ReadBits(msg, lowBits);
    for (int32_t bit = (int32_t)lowBits; bit < bitCount;
         bit += MSG_DELTA_BYTE_BITS) {
        valueBits |= (uint32_t)MSG_ReadByte(msg) <<
                     ((uint32_t)bit & 0x1f);
    }
    memcpy((uint8_t *)to + field->offset, &valueBits, sizeof(valueBits));
    if (print != qfalse) {
        Com_Printf("%s:%i ", field->name, valueBits);
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: playerstate fields inline this non-generic encoding. */
static void coduomp_msg_write_delta_playerstate_field(
    msg_t *msg, const void *from, const void *to,
    const netField_t *field)
{
    int32_t newValue = coduomp_msg_delta_field_int(to, field);
    int32_t oldValue = coduomp_msg_delta_field_int(from, field);

    if (oldValue == newValue) {
        MSG_WriteBit0(msg);
        return;
    }

    MSG_WriteBit1(msg);
    if (field->bits == MSG_DELTA_DEFAULT_INT_BITS) {
        float newFloat;
        int32_t rounded;

        memcpy(&newFloat, &newValue, sizeof(newFloat));
#if defined(__x86_64__)
        rounded = CODUO_X87_TRUNCATE_I32((long double)newFloat);
#else
        rounded = (int32_t)newFloat;
#endif
        /* no (float) cast on rounded: stock compares the bare fild against
         * newFloat with no intermediate float store (0x80829a9) */
        if (rounded == newFloat &&
            rounded + MSG_DELTA_SMALL_INT_BIAS >= 0 &&
            rounded + MSG_DELTA_SMALL_INT_BIAS < MSG_DELTA_SMALL_INT_RANGE) {
            MSG_WriteBit0(msg);
            MSG_WriteBits(msg, rounded + MSG_DELTA_SMALL_INT_BIAS,
                          MSG_DELTA_SMALL_INT_BITS);
            MSG_WriteByte(msg,
                          (rounded + MSG_DELTA_SMALL_INT_BIAS) >>
                              MSG_DELTA_SMALL_INT_BYTE_SHIFT);
        } else {
            MSG_WriteBit1(msg);
            MSG_WriteLong(msg, coduomp_msg_float_bits(newFloat));
        }
    } else if (field->bits == MSG_DELTA_ANGLE16_BITS) {
        if (newValue == 0) {
            MSG_WriteBit0(msg);
        } else {
            float newFloat;

            memcpy(&newFloat, &newValue, sizeof(newFloat));
            MSG_WriteBit1(msg);
            MSG_WriteAngle16(msg, newFloat);
        }
    } else {
        uint32_t bitCount = (uint32_t)field->bits;
        uint32_t valueBits = coduo_int32_bits(newValue);
        uint32_t remaining;
        uint32_t lowBits;

        if (field->bits < 0) {
            /* Stock NEG is a modulo-dword operation. */
            bitCount = UINT32_C(0) - (uint32_t)field->bits;
        }
        remaining = bitCount;
        lowBits = bitCount & 0x07;
        if (lowBits != 0) {
            MSG_WriteBits(msg, coduo_int32_from_bits(valueBits),
                          (int32_t)lowBits);
            remaining = bitCount - lowBits;
            valueBits >>= lowBits;
        }
        while (remaining != 0) {
            MSG_WriteByte(msg, (int32_t)(valueBits & UINT32_C(0xff)));
            valueBits >>= MSG_DELTA_BYTE_BITS;
            remaining -= MSG_DELTA_BYTE_BITS;
        }
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: playerstate fields inline this non-generic encoding. */
static void coduomp_msg_read_delta_playerstate_field(
    msg_t *msg, const void *from, void *to,
    const netField_t *field, qboolean print)
{
    float value;

    if (MSG_ReadBit(msg) == 0) {
        coduomp_msg_copy_delta_field(to, from, field);
        return;
    }

    if (field->bits == MSG_DELTA_DEFAULT_INT_BITS) {
        if (MSG_ReadBit(msg) == 0) {
            int32_t small = MSG_ReadBits(msg, MSG_DELTA_SMALL_INT_BITS);
            small += MSG_ReadByte(msg) << MSG_DELTA_SMALL_INT_BYTE_SHIFT;
            small -= MSG_DELTA_SMALL_INT_BIAS;
            value = (float)small;
            if (print != qfalse) {
                Com_Printf("%s:%i ", field->name, small);
            }
        } else {
            int32_t bits = MSG_ReadLong(msg);

            memcpy(&value, &bits, sizeof(value));
            if (print != qfalse) {
                Com_Printf("%s:%f ", field->name, (double)value);
            }
        }
        memcpy((uint8_t *)to + field->offset, &value, sizeof(value));
        return;
    }

    if (field->bits == MSG_DELTA_ANGLE16_BITS) {
        value = MSG_ReadBit(msg) == 0 ? 0.0f : MSG_ReadAngle16(msg);
        memcpy((uint8_t *)to + field->offset, &value, sizeof(value));
        return;
    }

    int32_t bitCount = field->bits;
    uint32_t lowBits;
    uint32_t valueBits;

    if (bitCount < 0) {
        /* Stock keeps the NEG result and the byte-loop bound signed. */
        bitCount = -bitCount;
    }
    lowBits = (uint32_t)bitCount & 0x07;
    valueBits = lowBits == 0 ? 0 : (uint32_t)MSG_ReadBits(msg, lowBits);
    for (int32_t bit = (int32_t)lowBits; bit < bitCount;
         bit += MSG_DELTA_BYTE_BITS) {
        valueBits |= (uint32_t)MSG_ReadByte(msg) <<
                     ((uint32_t)bit & 0x1f);
    }
    memcpy((uint8_t *)to + field->offset, &valueBits, sizeof(valueBits));
    if (print != qfalse) {
        Com_Printf("%s:%i ", field->name, valueBits);
    }
}

void MSG_ReadDeltaFields(msg_t *msg, const void *from, void *to,
                         int32_t count, const netField_t *fields)
{
    if (MSG_ReadBit(msg) == 0) {
        for (int32_t index = 0; index < count; ++index) {
            coduomp_msg_copy_delta_field(to, from, &fields[index]);
        }
        return;
    }

    for (int32_t index = 0; index < count; ++index) {
        MSG_ReadDeltaField(msg, from, to, &fields[index], qfalse);
    }
}

qboolean MSG_ReadDeltaStruct(msg_t *msg, const void *from, void *to,
                             int32_t number, int32_t count, int32_t numBits,
                             const netField_t *fields)
{
    qboolean removed;
    int32_t lastChanged;
    qboolean print;

    if (MSG_ReadBit(msg) == 1) {
        if (cl_shownet != NULL &&
            (cl_shownet->integer > 1 ||
             cl_shownet->integer == -1)) {
            Com_Printf("%3i: #%-3i remove\n", msg->readcount, number);
        }
        return qtrue;
    }

    if (MSG_ReadBit(msg) == 0) {
        /* Stock finishes the copy extent in EAX before the host call. */
        uint32_t copyLength =
            (uint32_t)count * (uint32_t)sizeof(int32_t) +
            (uint32_t)sizeof(int32_t);

        memcpy(to, from, (size_t)copyLength);
        return qfalse;
    }

    lastChanged = MSG_ReadByte(msg);
    /* ORIGINAL_BINARY_BUG: the upper clamp does not handle the -1
     * end-of-message sentinel; the trailing copy can therefore begin at
     * fields[-1].  Preserved from 0x080822ec..0x080823f4; see
     * original-bugs/coduomp-message-delta-descriptor-bounds.md. */
    if (lastChanged > count) {
        lastChanged = count;
    }

    print = qfalse;
    if (cl_shownet != NULL &&
        (cl_shownet->integer >=
             MSG_DELTA_CL_SHOWNET_ENTITY ||
         cl_shownet->integer == -1)) {
        print = qtrue;
        /* ORIGINAL_BINARY_BUG: stock prints the destination's previous first
         * dword before installing number below.  Preserved from
         * 0x08082323..0x08082358; see
         * original-bugs/coduomp-message-delta-shownet-stale-number.md. */
        Com_Printf("%3i: #%-3i ", msg->readcount, *(int32_t *)to);
    }

    *(int32_t *)to = number;
    removed = qfalse;
    (void)removed;
    (void)numBits;
    for (int32_t index = 0; index < lastChanged; ++index) {
        MSG_ReadDeltaField(msg, from, to, &fields[index], print);
    }
    for (int32_t index = lastChanged; index < count; ++index) {
        coduomp_msg_copy_delta_field(to, from, &fields[index]);
    }

    return qfalse;
}

qboolean MSG_ReadDeltaEntity(msg_t *msg, const void *from, void *to,
                             int32_t number)
{
    if (MSG_ReadBit(msg) == 1) {
        return MSG_ReadDeltaStruct(msg, from, to, number,
                                   MSG_DELTA_ENTITY_FIELD_COUNT,
                                   MSG_DELTA_ENTITY_NUM_BITS,
                                   msg_entityAltTrajectoryNetFields);
    }

    return MSG_ReadDeltaStruct(msg, from, to, number,
                               MSG_DELTA_ENTITY_FIELD_COUNT,
                               MSG_DELTA_ENTITY_NUM_BITS,
                               msg_entityDefaultNetFields);
}

qboolean MSG_ReadDeltaArchivedEntity(msg_t *msg, const void *from,
                                     void *to, int32_t number)
{
    return MSG_ReadDeltaStruct(msg, from, to, number,
                               MSG_DELTA_ENTITY_BASE_FIELD_COUNT,
                               MSG_DELTA_ENTITY_NUM_BITS,
                               msg_entityBaselineNetFields);
}

void MSG_ReadDeltaClient(msg_t *msg,
                         const coduo_host_client_snapshot_t *from,
                         coduo_host_client_snapshot_t *to,
                         int32_t clientNum)
{
    coduo_host_client_snapshot_t nullClient;

    if (from == NULL) {
        memset(&nullClient, 0, sizeof(nullClient));
        from = &nullClient;
    }

    (void)MSG_ReadDeltaStruct(msg, from, to, clientNum,
                              MSG_DELTA_CLIENT_FIELD_COUNT,
                              MSG_DELTA_CLIENT_NUM_BITS, msg_clientNetFields);
}

void MSG_WriteDeltaHudElems(msg_t *msg, const hudElem_t *from,
                            const hudElem_t *to, int32_t maxHudElems)
{
    int32_t hudElemCount;

    for (hudElemCount = 0;
         hudElemCount < maxHudElems &&
         to[hudElemCount].type != 0;
         ++hudElemCount) {
    }

    MSG_WriteBits(msg, hudElemCount, MSG_DELTA_HUD_COUNT_BITS);
    for (int32_t elem = 0; elem < hudElemCount; ++elem) {
        int32_t lastChanged = 0;
        const uint8_t *oldElem = (const uint8_t *)&from[elem];
        const uint8_t *newElem = (const uint8_t *)&to[elem];

        for (int32_t field = 0; field < CODUO_HUD_ELEM_NET_FIELD_COUNT;
             ++field) {
            if (coduomp_msg_delta_field_int(
                    oldElem, &msg_hudElemNetFields[field]) !=
                coduomp_msg_delta_field_int(
                    newElem, &msg_hudElemNetFields[field])) {
                lastChanged = field;
            }
        }

        MSG_WriteBits(msg, lastChanged, MSG_DELTA_HUD_LAST_FIELD_BITS);
        for (int32_t field = 0; field <= lastChanged; ++field) {
            MSG_WriteDeltaField(msg, oldElem, newElem,
                                &msg_hudElemNetFields[field]);
        }
    }
}

void MSG_ReadDeltaHudElems(msg_t *msg, const hudElem_t *from, hudElem_t *to,
                           int32_t maxHudElems)
{
    int32_t hudElemCount = MSG_ReadBits(msg, MSG_DELTA_HUD_COUNT_BITS);

    for (int32_t elem = 0; elem < hudElemCount; ++elem) {
        /* ORIGINAL_BINARY_BUG: five wire bits admit descriptor indexes 30
         * and 31 although the HUD table has only 30 rows.  Preserved from
         * 0x080826f8..0x080827dc; see
         * original-bugs/coduomp-message-delta-descriptor-bounds.md. */
        int32_t lastChanged = MSG_ReadBits(msg, MSG_DELTA_HUD_LAST_FIELD_BITS);
        const uint8_t *oldElem = (const uint8_t *)&from[elem];
        uint8_t *newElem = (uint8_t *)&to[elem];

        for (int32_t field = 0; field <= lastChanged; ++field) {
            MSG_ReadDeltaField(msg, oldElem, newElem,
                               &msg_hudElemNetFields[field], qfalse);
        }
        for (int32_t field = lastChanged + 1;
             field < CODUO_HUD_ELEM_NET_FIELD_COUNT; ++field) {
            coduomp_msg_copy_delta_field(
                newElem, oldElem, &msg_hudElemNetFields[field]);
        }
    }

    {
        /* Stock finishes the clear extent in EAX before the host call. */
        uint32_t clearLength =
            ((uint32_t)maxHudElems - (uint32_t)hudElemCount) *
            (uint32_t)sizeof(*to);

        memset(&to[hudElemCount], 0, (size_t)clearLength);
    }
}

void MSG_WriteDeltaPlayerstate(msg_t *msg,
                               const playerState_t *from,
                               const playerState_t *to)
{
    playerState_t nullState;
    const uint8_t *oldState;
    const uint8_t *newState = (const uint8_t *)to;
    int32_t lastChanged = 0;
    uint32_t statBits = 0;
    uint32_t ammoBits[MSG_DELTA_PLAYERSTATE_AMMO_GROUP_COUNT];

    if (from == NULL) {
        memset(&nullState, 0, sizeof(nullState));
        from = &nullState;
    }
    oldState = (const uint8_t *)from;

    for (int32_t field = 0; field < MSG_DELTA_PLAYERSTATE_FIELD_COUNT;
         ++field) {
        if (coduomp_msg_delta_field_int(
                oldState, &msg_playerStateNetFields[field]) !=
            coduomp_msg_delta_field_int(
                newState, &msg_playerStateNetFields[field])) {
            lastChanged = field + 1;
        }
    }

    MSG_WriteByte(msg, lastChanged);
    for (int32_t field = 0; field < lastChanged; ++field) {
        coduomp_msg_write_delta_playerstate_field(
            msg, oldState, newState, &msg_playerStateNetFields[field]);
    }

    for (int32_t stat = 0; stat < MSG_DELTA_PLAYERSTATE_STATS_COUNT; ++stat) {
        if (coduomp_msg_delta_field_int(
                newState,
                &(netField_t){NULL,
                              MSG_DELTA_PLAYERSTATE_STATS_OFFSET + stat * 4,
                              0}) !=
            coduomp_msg_delta_field_int(
                oldState,
                &(netField_t){NULL,
                              MSG_DELTA_PLAYERSTATE_STATS_OFFSET + stat * 4,
                              0})) {
            statBits |= 1U << stat;
        }
    }
    if (statBits == 0) {
        MSG_WriteBit0(msg);
    } else {
        MSG_WriteBit1(msg);
        MSG_WriteBits(msg, statBits, MSG_DELTA_PLAYERSTATE_STATS_BITS);
        for (int32_t stat = 0; stat < MSG_DELTA_PLAYERSTATE_STATS_COUNT;
             ++stat) {
            if ((statBits & (1U << stat)) == 0) {
                continue;
            }
            int32_t value;
            memcpy(&value,
                   newState + MSG_DELTA_PLAYERSTATE_STATS_OFFSET + stat * 4,
                   sizeof(value));
            if (stat == MSG_DELTA_PLAYERSTATE_STATS_WEAPON_INDEX) {
                MSG_WriteBits(msg, value,
                              MSG_DELTA_PLAYERSTATE_STATS_WEAPON_BITS);
            } else if (stat == MSG_DELTA_PLAYERSTATE_STATS_COUNT - 1) {
                MSG_WriteByte(msg, value);
            } else {
                MSG_WriteShort(msg, value);
            }
        }
    }

    for (int32_t group = 0; group < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_COUNT;
         ++group) {
        ammoBits[group] = 0;
        for (int32_t item = 0; item < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE;
             ++item) {
            int32_t offset = MSG_DELTA_PLAYERSTATE_AMMO_OFFSET +
                             (group * MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE +
                              item) *
                                 4;
            if (memcmp(oldState + offset, newState + offset, sizeof(int32_t)) !=
                0) {
                ammoBits[group] |= 1U << item;
            }
        }
    }
    if (ammoBits[0] == 0 && ammoBits[1] == 0 && ammoBits[2] == 0 &&
        ammoBits[3] == 0) {
        MSG_WriteBit0(msg);
    } else {
        MSG_WriteBit1(msg);
        for (int32_t group = 0; group < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_COUNT;
             ++group) {
            if (ammoBits[group] == 0) {
                MSG_WriteBit0(msg);
                continue;
            }
            MSG_WriteBit1(msg);
            MSG_WriteShort(msg, ammoBits[group]);
            for (int32_t item = 0; item < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE;
                 ++item) {
                if ((ammoBits[group] & (1U << item)) != 0) {
                    int32_t value;
                    memcpy(&value,
                           newState + MSG_DELTA_PLAYERSTATE_AMMO_OFFSET +
                               (group *
                                    MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE +
                                item) *
                                   4,
                           sizeof(value));
                    MSG_WriteShort(msg, value);
                }
            }
        }
    }

    for (int32_t group = 0; group < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_COUNT;
         ++group) {
        uint32_t clipBits = 0;

        for (int32_t item = 0; item < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE;
             ++item) {
            int32_t offset = MSG_DELTA_PLAYERSTATE_AMMO_CLIP_OFFSET +
                             (group * MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE +
                              item) *
                                 4;
            if (memcmp(oldState + offset, newState + offset, sizeof(int32_t)) !=
                0) {
                clipBits |= 1U << item;
            }
        }
        if (clipBits == 0) {
            MSG_WriteBit0(msg);
            continue;
        }
        MSG_WriteBit1(msg);
        MSG_WriteShort(msg, clipBits);
        for (int32_t item = 0; item < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE;
             ++item) {
            if ((clipBits & (1U << item)) != 0) {
                int32_t value;
                memcpy(&value,
                       newState + MSG_DELTA_PLAYERSTATE_AMMO_CLIP_OFFSET +
                           (group * MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE +
                            item) *
                               4,
                       sizeof(value));
                MSG_WriteShort(msg, value);
            }
        }
    }

    if (memcmp(from->objectives, to->objectives,
               sizeof(to->objectives)) == 0) {
        MSG_WriteBit0(msg);
    } else {
        MSG_WriteBit1(msg);
        for (int32_t index = 0; index < PLAYERSTATE_OBJECTIVE_COUNT;
             ++index) {
            MSG_WriteBits(msg, to->objectives[index].state,
                          MSG_DELTA_PLAYERSTATE_OBJECTIVE_STATE_BITS);
            MSG_WriteDeltaFields(msg, &from->objectives[index],
                                 &to->objectives[index], qfalse,
                                 CODUO_OBJECTIVE_NET_FIELD_COUNT,
                                 msg_objectiveNetFields);
        }
    }

    /* The original makes one comparison across both adjacent HUD arrays.
     * Derive the byte span from the enclosing playerState_t so the access
     * remains within that object's representation in strictly conforming C. */
    if (memcmp((const uint8_t *)from +
                   offsetof(playerState_t, hudCurrent),
               (const uint8_t *)to +
                   offsetof(playerState_t, hudCurrent),
               sizeof(to->hudCurrent) + sizeof(to->hudArchival)) == 0) {
        MSG_WriteBit0(msg);
    } else {
        MSG_WriteBit1(msg);
        MSG_WriteDeltaHudElems(msg, from->hudArchival, to->hudArchival,
                               PLAYERSTATE_HUD_ELEM_COUNT);
        MSG_WriteDeltaHudElems(msg, from->hudCurrent, to->hudCurrent,
                               PLAYERSTATE_HUD_ELEM_COUNT);
    }
}

void MSG_ReadDeltaPlayerstate(msg_t *msg, const playerState_t *from,
                              playerState_t *to)
{
    playerState_t nullState;
    const uint8_t *oldState;
    uint8_t *newState = (uint8_t *)to;
    qboolean print = qfalse;
    int32_t lastChanged;

    if (from == NULL) {
        memset(&nullState, 0, sizeof(nullState));
        from = &nullState;
    }
    oldState = (const uint8_t *)from;

    memcpy(to, from, sizeof(*to));
    if (cl_shownet != NULL &&
        (cl_shownet->integer >=
             MSG_DELTA_CL_SHOWNET_ENTITY ||
         cl_shownet->integer ==
             MSG_DELTA_CL_SHOWNET_PLAYERSTATE)) {
        print = qtrue;
        Com_Printf("%3i: playerstate ", msg->readcount);
    }

    /* ORIGINAL_BINARY_BUG: the byte-sized wire count is not bounded to the
     * 114-row playerstate descriptor table.  Preserved from
     * 0x08083435..0x0808345e; see
     * original-bugs/coduomp-message-delta-descriptor-bounds.md. */
    lastChanged = MSG_ReadByte(msg);
    for (int32_t field = 0; field < lastChanged; ++field) {
        coduomp_msg_read_delta_playerstate_field(
            msg, oldState, newState,
            &msg_playerStateNetFields[field], print);
    }

    if (MSG_ReadBit(msg) != 0) {
        uint32_t statBits =
            (uint32_t)MSG_ReadBits(msg, MSG_DELTA_PLAYERSTATE_STATS_BITS);

        if (cl_shownet != NULL &&
            cl_shownet->integer ==
                MSG_DELTA_CL_SHOWNET_VERBOSE) {
            Com_Printf("%s ", "PS_STATS");
        }
        for (int32_t stat = 0; stat < MSG_DELTA_PLAYERSTATE_STATS_COUNT;
             ++stat) {
            if ((statBits & (1U << stat)) == 0) {
                continue;
            }
            int32_t value;

            if (stat == MSG_DELTA_PLAYERSTATE_STATS_WEAPON_INDEX) {
                value = MSG_ReadBits(msg,
                                     MSG_DELTA_PLAYERSTATE_STATS_WEAPON_BITS);
            } else if (stat == MSG_DELTA_PLAYERSTATE_STATS_COUNT - 1) {
                value = MSG_ReadByte(msg);
            } else {
                value = MSG_ReadShort(msg);
            }
            memcpy(newState + MSG_DELTA_PLAYERSTATE_STATS_OFFSET + stat * 4,
                   &value, sizeof(value));
        }
    }

    if (MSG_ReadBit(msg) != 0) {
        for (int32_t group = 0;
             group < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_COUNT; ++group) {
            if (MSG_ReadBit(msg) == 0) {
                continue;
            }
            if (cl_shownet != NULL &&
                cl_shownet->integer ==
                    MSG_DELTA_CL_SHOWNET_VERBOSE) {
                Com_Printf("%s ", "PS_AMMO");
            }
            uint32_t ammoBits = (uint32_t)MSG_ReadShort(msg);

            for (int32_t item = 0; item < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE;
                 ++item) {
                if ((ammoBits & (1U << item)) != 0) {
                    int32_t value = MSG_ReadShort(msg);

                    memcpy(newState + MSG_DELTA_PLAYERSTATE_AMMO_OFFSET +
                               (group *
                                    MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE +
                                item) *
                                   4,
                           &value, sizeof(value));
                }
            }
        }
    }

    for (int32_t group = 0; group < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_COUNT;
         ++group) {
        if (MSG_ReadBit(msg) == 0) {
            continue;
        }
        if (cl_shownet != NULL &&
            cl_shownet->integer ==
                MSG_DELTA_CL_SHOWNET_VERBOSE) {
            Com_Printf("%s ", "PS_AMMOCLIP");
        }
        uint32_t clipBits = (uint32_t)MSG_ReadShort(msg);

        for (int32_t item = 0; item < MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE;
             ++item) {
            if ((clipBits & (1U << item)) != 0) {
                int32_t value = MSG_ReadShort(msg);

                memcpy(newState + MSG_DELTA_PLAYERSTATE_AMMO_CLIP_OFFSET +
                           (group * MSG_DELTA_PLAYERSTATE_AMMO_GROUP_SIZE +
                            item) *
                               4,
                       &value, sizeof(value));
            }
        }
    }

    if (MSG_ReadBit(msg) != 0) {
        for (int32_t index = 0; index < PLAYERSTATE_OBJECTIVE_COUNT;
             ++index) {
            to->objectives[index].state =
                MSG_ReadBits(msg,
                             MSG_DELTA_PLAYERSTATE_OBJECTIVE_STATE_BITS);
            MSG_ReadDeltaFields(
                msg, &from->objectives[index], &to->objectives[index],
                CODUO_OBJECTIVE_NET_FIELD_COUNT,
                msg_objectiveNetFields);
        }
    }

    if (MSG_ReadBit(msg) != 0) {
        MSG_ReadDeltaHudElems(msg, from->hudArchival, to->hudArchival,
                              PLAYERSTATE_HUD_ELEM_COUNT);
        MSG_ReadDeltaHudElems(msg, from->hudCurrent, to->hudCurrent,
                              PLAYERSTATE_HUD_ELEM_COUNT);
    }
}

int16_t LittleShort(int16_t value)
{
    return value;
}

int32_t LittleLong(int32_t value)
{
    return value;
}

void NetProf_PrepProfiling(netProfileInfo_t **profile)
{
    if (net_profile->integer == 0) {
        if (net_profileActiveMode != CODUO_NET_PROFILE_OFF) {
            net_profileActiveMode = CODUO_NET_PROFILE_OFF;
            Com_Printf("Net Profiling turned off\n");
        }
        if (*profile != NULL) {
            free(*profile);
            *profile = NULL;
        }
        return;
    }

    if (net_profileActiveMode == CODUO_NET_PROFILE_OFF) {
        if (host_cvar_sv_running_pointer_slot->integer == 0 ||
            (host_cvar_cl_running_pointer_slot->integer != 0 &&
             net_profile->integer ==
                 CODUO_NET_PROFILE_SERVER)) {
            net_profileActiveMode = CODUO_NET_PROFILE_CLIENT;
        } else {
            net_profileActiveMode = CODUO_NET_PROFILE_SERVER;
        }
        Com_Printf("Net Profiling turned on: %s\n",
                   net_profileSocketNames[net_profileActiveMode -
                                          CODUO_NET_PROFILE_CLIENT]);
    }

    if (*profile == NULL) {
        /* ORIGINAL_BINARY_BUG: stock clears the allocation without checking
         * for failure.  Preserved from 0x08083900..0x08083929; see
         * original-bugs/coduomp-net-profile-allocation-null-dereference.md. */
        *profile = malloc(sizeof(**profile));
        memset(*profile, 0, sizeof(**profile));
    }
}

void NetProf_AddPacket(netProfileStream_t *stream,
                       int32_t bytes,
                       qboolean fragmented)
{
    int32_t nextIndex = stream->ringIndex + 1;

    stream->ringIndex = nextIndex % CODUO_NET_PROFILE_SAMPLE_COUNT;
    stream->samples[stream->ringIndex].time = Sys_Milliseconds();
    stream->samples[stream->ringIndex].bytes = bytes;
    stream->samples[stream->ringIndex].fragmented = fragmented;
}

void NetProf_NewSendPacket(netchan_t *chan,
                           int32_t bytes,
                           qboolean fragmented)
{
    if (net_profileActiveMode != CODUO_NET_PROFILE_OFF) {
        NetProf_AddPacket(&chan->profile->send, bytes, fragmented);
        if ((net_showprofile->integer & NET_SHOWPROFILE_PACKETS) != 0) {
            Com_Printf("%s send%s: %i\n", net_profileSocketNames[chan->sock],
                       fragmented ? " fragment" : "", bytes);
        }
    }
}

void NetProf_NewRecievePacket(netchan_t *chan,
                              int32_t bytes,
                              qboolean fragmented)
{
    if (net_profileActiveMode != CODUO_NET_PROFILE_OFF) {
        NetProf_AddPacket(&chan->profile->receive, bytes, fragmented);
        if ((net_showprofile->integer & NET_SHOWPROFILE_PACKETS) != 0) {
            Com_Printf("%s recieve%s: %i\n", net_profileSocketNames[chan->sock],
                       fragmented ? " fragment" : "", bytes);
        }
    }
}

void NetProf_UpdateStatistics(netProfileStream_t *stream)
{
    int32_t sampleCount = 0;
    int32_t fragmentCount = 0;
    int32_t oldestIndex = -1;
    int32_t oldestTime = Sys_Milliseconds();
    int32_t totalBytes = 0;
    int32_t minBytes = NET_PROFILE_EMPTY_MIN_BYTES;
    int32_t maxBytes = 0;

    for (int32_t index = 0; index < CODUO_NET_PROFILE_SAMPLE_COUNT; ++index) {
        netProfileSample_t *sample = &stream->samples[index];

        if (sample->time != 0 &&
            Sys_Milliseconds() <=
                sample->time + NET_PROFILE_SAMPLE_WINDOW_MS) {
            ++sampleCount;
            if (sample->fragmented != qfalse) {
                ++fragmentCount;
            }
            if (sample->time < oldestTime) {
                oldestIndex = index;
                oldestTime = sample->time;
            }
            totalBytes += sample->bytes;
            if (sample->bytes < minBytes) {
                minBytes = sample->bytes;
            }
            if (maxBytes < sample->bytes) {
                maxBytes = sample->bytes;
            }
        }
    }

    if (sampleCount == 0) {
        stream->bytesPerSecond = 0;
        stream->lastRateCalcTime = 0;
        stream->sampleCount = 0;
        stream->fragmentSampleCount = 0;
        stream->fragmentPercent = 0;
        stream->maxBytes = 0;
        stream->minBytes = 0;
        return;
    }

    stream->fragmentPercent =
        fragmentCount == 0 ? 0 : (fragmentCount * 100) / sampleCount;
    stream->maxBytes = maxBytes;
    stream->minBytes = minBytes;

    if (stream->lastRateCalcTime + NET_PROFILE_RATE_CALC_INTERVAL_MS <
        Sys_Milliseconds()) {
        int32_t now = Sys_Milliseconds();

        if (oldestIndex != -1) {
            totalBytes -= stream->samples[oldestIndex].bytes;
            --sampleCount;
            if (stream->samples[oldestIndex].fragmented != qfalse) {
                --fragmentCount;
            }
        }
        if (now - oldestTime < 1 || sampleCount == 0 || totalBytes == 0) {
            stream->bytesPerSecond = 0;
        } else {
            static const float secondsPerMillisecond = 0.001f;
            /* Stock feeds both integers through bare fild and keeps the
             * fmul/fdiv chain live until fistp (0x8083ddd..0x8083dff). */
#if EMULATE_X87
            stream->bytesPerSecond = x87f_store_i32_trunc(x87f_div(
                x87f_load_i32(totalBytes),
                x87f_mul(x87f_load_i32(now - oldestTime),
                         x87f_load_f32(secondsPerMillisecond))));
#elif defined(__x86_64__)
            stream->bytesPerSecond = CODUO_X87_TRUNCATE_I32(
                (long double)totalBytes /
                ((long double)(now - oldestTime) *
                 (long double)secondsPerMillisecond));
#else
            stream->bytesPerSecond =
                (int32_t)(totalBytes /
                          ((now - oldestTime) * secondsPerMillisecond));
#endif
        }
        stream->lastRateCalcTime = Sys_Milliseconds();
    }

    stream->sampleCount = sampleCount;
    stream->fragmentSampleCount = fragmentCount;
}

int32_t NET_CompareBaseAdrSigned(const netadr_t *a,
                                 const netadr_t *b)
{
    if (a->type != b->type) {
        return a->type - b->type;
    }
    if (a->type == CODUO_NA_LOOPBACK) {
        return 0;
    }
    if (a->type == CODUO_NA_BAD) {
        return (int32_t)(uint16_t)a->port - (int32_t)(uint16_t)b->port;
    }
    if (a->type == CODUO_NA_IP) {
        return memcmp(a->ip, b->ip, sizeof(a->ip));
    }
    if (a->type == CODUO_NA_IPX) {
        return memcmp(a->ipx, b->ipx, sizeof(a->ipx));
    }

    Com_Printf("NET_CompareBaseAdrSigned: bad address type\n");
    return 0;
}

qboolean NET_CompareBaseAdr(netadr_t a, netadr_t b)
{
    return NET_CompareBaseAdrSigned(&a, &b) == 0 ? qtrue : qfalse;
}

int32_t NET_CompareAdrSigned(const netadr_t *a, const netadr_t *b)
{
    if (a->type != b->type) {
        return a->type - b->type;
    }
    if (a->type == CODUO_NA_LOOPBACK) {
        return 0;
    }
    if (a->type == CODUO_NA_IP) {
        if (a->port != b->port) {
            return (int32_t)(uint16_t)a->port - (int32_t)(uint16_t)b->port;
        }
        return memcmp(a->ip, b->ip, sizeof(a->ip));
    }
    if (a->type == CODUO_NA_IPX) {
        if (a->port != b->port) {
            return (int32_t)(uint16_t)a->port - (int32_t)(uint16_t)b->port;
        }
        return memcmp(a->ipx, b->ipx, sizeof(a->ipx));
    }

    Com_Printf("NET_CompareAdrSigned: bad address type\n");
    return 0;
}

qboolean NET_CompareAdr(netadr_t a, netadr_t b)
{
    return NET_CompareAdrSigned(&a, &b) == 0 ? qtrue : qfalse;
}

qboolean NET_IsLocalAddress(netadr_t adr)
{
    return adr.type == CODUO_NA_LOOPBACK || adr.type == CODUO_NA_BAD
               ? qtrue
               : qfalse;
}
