#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include "../core_runtime/core_runtime_private.h"
#include "../filesystem/fs_private.h"
#include "../model_assets/xmodel_asset_private.h"
#include "../scripting/script_memory_private.h"
#include "../scripting/script_runtime_private.h"
#include "../scripting/script_variable_private.h"
#include "coduo_engine_structs.h"
#include "coduo_native_x87.h"
#include "coduo_x87emu.h" /* defines EMULATE_X87; x87 shim when it is 1 */
#include "xanim_private.h"

/* x87 shim helpers for the animation blend math: each keeps the 80-bit
 * intermediate that stock does (dst += a*b MA, a/b divide, sum-of-4-squares dot)
 * with one float store; the #else forms are byte-identical to the originals so
 * the macro call sites need no per-site #if/#else. */
#if EMULATE_X87
#define XA_MADD(dst, a, b)                                                    \
    ((dst) = x87f_store_f32(x87f_add(                                         \
         x87f_mul(x87f_load_f32(a), x87f_load_f32(b)), x87f_load_f32(dst))))
#define XA_DIV(a, b)                                                          \
    x87f_store_f32(x87f_div(x87f_load_f32(a), x87f_load_f32(b)))
#define XA_SUMSQ4(a, b, c, d)                                                 \
    x87f_store_f32(x87f_add(                                                  \
        x87f_add(x87f_add(x87f_mul(x87f_load_f32(a), x87f_load_f32(a)),       \
                          x87f_mul(x87f_load_f32(b), x87f_load_f32(b))),      \
                 x87f_mul(x87f_load_f32(c), x87f_load_f32(c))),              \
        x87f_mul(x87f_load_f32(d), x87f_load_f32(d))))
#else
#define XA_MADD(dst, a, b) ((dst) += (a) * (b))
#define XA_DIV(a, b) ((a) / (b))
#define XA_SUMSQ4(a, b, c, d) ((a) * (a) + (b) * (b) + (c) * (c) + (d) * (d))
#endif

/* Objdump: .rodata VA 0x80ea3d4 bytes 00 01 00 38. */
#define XANIM_PACKED_SHORT_TO_FLOAT_SCALE 3.051851e-05f
#define XANIM_EVAL_SKIP_LAST_PART_BIT 0x80U
#define XANIM_EVAL_TREE_ROOT_NODE 0
#define XANIM_EVAL_TREE_FULL_WEIGHT 1.0f
#define XANIM_EVAL_TREE_CLEAR_OUTPUT 1
#define XANIM_EVAL_TREE_NO_NORMALIZE 0
#define XANIM_FILE_VERSION 14
#define XANIM_FILE_LOOPED_FLAG 0x01U
#define XANIM_FILE_DELTA_MOTION_FLAG 0x02U
#define XANIM_SMALL_FRAME_KEY_LIMIT 256U
#define XANIM_PART_NAME_STRING_TYPE 9
#define XANIM_COM_ERROR_DROP 1
#define XANIM_DELTA_ROTATION_SCALE 9.313794e-10f
#define XANIM_DELTA_DEFAULT_ROTATION_LANE1 32767.0f
#define XANIM_WEIGHT_EPSILON 1.0000001e-06f
#define XANIM_BLEND_TIME_EPSILON 0.001f
#define XANIM_PACKED_UNIT_VECTOR_REMAINDER 1073676289 /* 0x3fff0001 */
typedef struct coduo_xmodel_part_name_payload_view_s {
    XModelPartNameTable *partNameTable;
    int32_t rootPartCount;
    xanim_int16_vec4_t *baseRotations;
} coduo_xmodel_part_name_payload_view_t;

enum {
    CODUO_XANIM_PART_REMAP_STRING_TYPE = 11
};

void XAnimCalc(uint32_t nodeIndex, float weight,
               DObjAnimMat *part, qboolean clear,
               qboolean normalize);

void ReadQuat(const int16_t *packed,
              xanim_int16_vec4_t *out)
{
    int32_t remaining;

    out->components[0] = (int16_t)XModelLittleInt16(packed[0]);
    out->components[1] = (int16_t)XModelLittleInt16(packed[1]);
    out->components[2] = (int16_t)XModelLittleInt16(packed[2]);

    remaining = XANIM_PACKED_UNIT_VECTOR_REMAINDER -
                ((int32_t)out->components[0] * (int32_t)out->components[0] +
                 (int32_t)out->components[1] * (int32_t)out->components[1] +
                 (int32_t)out->components[2] * (int32_t)out->components[2]);

    if (remaining < 1) {
        out->components[3] = 0;
    } else {
        /* sqrt((double)remaining) + 0.5 kept 80-bit before floor -> shim. */
#if EMULATE_X87
        out->components[3] = (int16_t)(int32_t)floor(x87f_store_f64(x87f_add(
            x87f_load_f64(sqrt((double)remaining)), x87f_load_f32(0.5f))));
#elif defined(__x86_64__)
        static const float half = 0.5f;
        double rounded = floor(sqrt((double)remaining) + (double)half);
        out->components[3] = (int16_t)CODUO_X87_TRUNCATE_I32(
            (long double)rounded);
#else
        out->components[3] = (int16_t)(int32_t)floor(sqrt((double)remaining) + 0.5);
#endif
    }
}

void ReadQuat2(const int16_t *packed,
               xanim_int16_vec2_t *out)
{
    int32_t remaining;

    out->components[0] = (int16_t)XModelLittleInt16(packed[0]);

    remaining = XANIM_PACKED_UNIT_VECTOR_REMAINDER -
                (int32_t)out->components[0] * (int32_t)out->components[0];

    if (remaining < 1) {
        out->components[1] = 0;
    } else {
#if EMULATE_X87
        out->components[1] = (int16_t)(int32_t)floor(x87f_store_f64(x87f_add(
            x87f_load_f64(sqrt((double)remaining)), x87f_load_f32(0.5f))));
#elif defined(__x86_64__)
        static const float half = 0.5f;
        double rounded = floor(sqrt((double)remaining) + (double)half);
        out->components[1] = (int16_t)CODUO_X87_TRUNCATE_I32(
            (long double)rounded);
#else
        out->components[1] = (int16_t)(int32_t)floor(sqrt((double)remaining) + 0.5);
#endif
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local loaded-record access for leaf entries. */
static XAnimParts *coduo_engine_xanim_entry_loaded_record(
    XAnimEntry *entry)
{
    fileData_t *asset = entry->payload.leafAsset;

    return asset->data.xanimParts;
}

/* NOT_FROM_ORIGINAL_SOURCE: readable wrapper for packed part-bit byte tests. */
static qboolean coduo_engine_xanim_part_bit_is_set(const uint8_t *partBits, int32_t partIndex)
{
    return (partBits[partIndex >> 3] & (1U << (partIndex & 7))) != 0;
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static uint16_t coduo_engine_xanim_load_file_read_header_short(uint8_t **pos)
{
    int16_t raw;

    memcpy(&raw, *pos, sizeof(raw));
    *pos += sizeof(raw);
    return (uint16_t)XAnimSignExtendShort(raw);
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static uint16_t coduo_engine_xanim_load_file_read_stream_count(uint8_t **pos)
{
    uint16_t count;

    memcpy(&count, *pos, sizeof(count));
    *pos += sizeof(count);
    return count;
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static float coduo_engine_xanim_load_file_read_float(uint8_t **pos)
{
    float value;

    memcpy(&value, *pos, sizeof(value));
    *pos += sizeof(value);
    return value;
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static void coduo_engine_xanim_load_file_read_vec2(uint8_t **pos, qboolean negate,
                                  xanim_int16_vec2_t *out)
{
    int16_t packed;

    memcpy(&packed, *pos, sizeof(packed));
    ReadQuat2(&packed, out);
    *pos += sizeof(packed);

    if (negate) {
        out->components[0] = (int16_t)-out->components[0];
        out->components[1] = (int16_t)-out->components[1];
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static void coduo_engine_xanim_load_file_read_vec4(uint8_t **pos, qboolean negate,
                                  xanim_int16_vec4_t *out)
{
    int16_t packed[3];

    memcpy(packed, *pos, sizeof(packed));
    ReadQuat(packed, out);
    *pos += sizeof(packed);

    if (negate) {
        out->components[0] = (int16_t)-out->components[0];
        out->components[1] = (int16_t)-out->components[1];
        out->components[2] = (int16_t)-out->components[2];
        out->components[3] = (int16_t)-out->components[3];
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static void coduo_engine_xanim_load_file_fix_vec2_continuity(xanim_int16_vec2_t *frames,
                                           uint16_t frameCount)
{
    for (int32_t frameIndex = 1; frameIndex < (int32_t)frameCount;
         ++frameIndex) {
        xanim_int16_vec2_t *current = &frames[frameIndex];
        xanim_int16_vec2_t *previous = &frames[frameIndex - 1];
        int32_t dot = (int32_t)previous->components[1] * (int32_t)current->components[1] +
                      (int32_t)current->components[0] * (int32_t)previous->components[0];

        if (dot < 0) {
            current->components[0] = (int16_t)-current->components[0];
            current->components[1] = (int16_t)-current->components[1];
        }
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static void coduo_engine_xanim_load_file_fix_vec4_continuity(xanim_int16_vec4_t *frames,
                                           uint16_t frameCount)
{
    for (int32_t frameIndex = 1; frameIndex < (int32_t)frameCount;
         ++frameIndex) {
        xanim_int16_vec4_t *current = &frames[frameIndex];
        xanim_int16_vec4_t *previous = &frames[frameIndex - 1];
        int32_t dot = (int32_t)previous->components[2] * (int32_t)current->components[2] +
                      (int32_t)previous->components[3] * (int32_t)current->components[3] +
                      (int32_t)current->components[0] * (int32_t)previous->components[0] +
                      (int32_t)current->components[1] * (int32_t)previous->components[1];

        if (dot < 0) {
            current->components[0] = (int16_t)-current->components[0];
            current->components[1] = (int16_t)-current->components[1];
            current->components[2] = (int16_t)-current->components[2];
            current->components[3] = (int16_t)-current->components[3];
        }
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static size_t coduo_engine_xanim_load_file_rotation_stream_size(uint16_t frameCount,
                                             uint16_t totalFrameCount,
                                             qboolean smallFrameKeys)
{
    size_t streamSize = offsetof(xanim_rotation_stream_t, tail) +
                        sizeof(((xanim_rotation_stream_t *)0)
                                   ->tail.shortKeys);

    if (frameCount < totalFrameCount) {
        size_t keyedSize;

        if (smallFrameKeys) {
            keyedSize = offsetof(xanim_rotation_stream_t, tail) +
                        sizeof(((xanim_rotation_stream_t *)0)
                                   ->tail.byteKeys) +
                        frameCount;
        } else {
            keyedSize = offsetof(xanim_rotation_stream_t, tail) +
                        (size_t)frameCount *
                            sizeof(((xanim_rotation_stream_t *)0)
                                       ->tail.shortKeys);
        }

        if (keyedSize > streamSize) {
            streamSize = keyedSize;
        }
    }

    return streamSize;
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static size_t coduo_engine_xanim_load_file_rotation_inline_stream_size(qboolean compressedVec2)
{
    if (compressedVec2) {
        return offsetof(xanim_rotation_stream_t, tail) +
               sizeof(((xanim_rotation_stream_t *)0)->tail.shortKeys);
    }

    return offsetof(xanim_rotation_stream_t, tail) +
           sizeof(((xanim_rotation_stream_t *)0)->tail.inlineFull);
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static size_t coduo_engine_xanim_load_file_translation_stream_size(uint16_t frameCount,
                                               uint16_t totalFrameCount,
                                               qboolean smallFrameKeys)
{
    size_t streamSize = offsetof(xanim_translation_stream_t, key) +
                        sizeof(((xanim_translation_stream_t *)0)
                                   ->key.shortKeys);

    if (frameCount < totalFrameCount) {
        size_t keyedSize;

        if (smallFrameKeys) {
            keyedSize = offsetof(xanim_translation_stream_t, key) +
                        sizeof(((xanim_translation_stream_t *)0)
                                   ->key.byteKeys) +
                        frameCount;
        } else {
            keyedSize = offsetof(xanim_translation_stream_t, key) +
                        (size_t)frameCount *
                            sizeof(((xanim_translation_stream_t *)0)
                                       ->key.shortKeys);
        }

        if (keyedSize > streamSize) {
            streamSize = keyedSize;
        }
    }

    return streamSize;
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static size_t coduo_engine_xanim_load_file_translation_inline_stream_size(void)
{
    return offsetof(xanim_translation_stream_t, inlineLanes) +
           sizeof(((xanim_translation_stream_t *)0)->inlineLanes);
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for optional delta sampling. */
static void coduo_engine_xanim_sample_optional_rotation_last_frame(
    const xanim_rotation_stream_t *primary, vec2_t rotation)
{
    if (primary == NULL) {
        rotation[0] = 0.0f;
        rotation[1] = XANIM_DELTA_DEFAULT_ROTATION_LANE1;
    } else if (primary->frameIndex == 0) {
        rotation[0] = (float)primary->data.inlinePrefix.lane0;
        rotation[1] = (float)primary->data.inlinePrefix.lane1;
    } else {
        const xanim_int16_vec2_t *frame =
            &primary->data.frames2[primary->frameIndex];

        rotation[0] = (float)frame->components[0];
        rotation[1] = (float)frame->components[1];
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for optional delta sampling. */
static void coduo_engine_xanim_sample_optional_translation_last_frame(
    const xanim_translation_stream_t *secondary, vec3_t move)
{
    if (secondary == NULL) {
        move[0] = 0.0f;
        move[1] = 0.0f;
        move[2] = 0.0f;
    } else if (secondary->frameIndex == 0) {
        move[0] = secondary->data.inlineLane0;
        move[1] = secondary->inlineLanes.lane1;
        move[2] = secondary->inlineLanes.lane2;
    } else {
        const float *frame = secondary->data.frames[secondary->frameIndex];

        move[0] = frame[0];
        move[1] = frame[1];
        move[2] = frame[2];
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for optional delta sampling. */
static float coduo_engine_xanim_byte_key_frame_frac(float time, float frameTime,
                                   const uint8_t *keys, int32_t keyCount,
                                   int32_t targetKey, int32_t *frameIndex)
{
    *frameIndex = XAnimFindByteKey(time, keys, keyCount, targetKey);
    return (frameTime - (float)keys[*frameIndex]) /
           (float)((int32_t)keys[*frameIndex + 1] -
                   (int32_t)keys[*frameIndex]);
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for optional delta sampling. */
static float coduo_engine_xanim_short_key_frame_frac(float time, float frameTime,
                                    const uint16_t *keys, int32_t keyCount,
                                    int32_t targetKey, int32_t *frameIndex)
{
    *frameIndex = XAnimFindShortKey(time, keys, keyCount, targetKey);
    return (frameTime - (float)keys[*frameIndex]) /
           (float)((int32_t)keys[*frameIndex + 1] -
                   (int32_t)keys[*frameIndex]);
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for optional delta sampling. */
static void coduo_engine_xanim_sample_optional_rotation(
    const xanim_rotation_stream_t *primary, int32_t frameCount,
    float time, float frameTime, int32_t roundedFrame, qboolean useShortKeys,
    vec2_t rotation)
{
    int32_t frameIndex = roundedFrame;
    float frameFrac;

    if (primary == NULL) {
        rotation[0] = 0.0f;
        rotation[1] = XANIM_DELTA_DEFAULT_ROTATION_LANE1;
    } else if (primary->frameIndex == 0) {
        rotation[0] = (float)primary->data.inlinePrefix.lane0;
        rotation[1] = (float)primary->data.inlinePrefix.lane1;
    } else {
        if (primary->frameIndex < frameCount) {
            if (useShortKeys) {
                frameFrac = coduo_engine_xanim_short_key_frame_frac(
                    time, frameTime, primary->tail.shortKeys,
                    primary->frameIndex, roundedFrame, &frameIndex);
            } else {
                frameFrac = coduo_engine_xanim_byte_key_frame_frac(
                    time, frameTime, primary->tail.byteKeys,
                    primary->frameIndex, roundedFrame, &frameIndex);
            }
        } else {
            frameFrac = frameTime - (float)roundedFrame;
        }

        const xanim_int16_vec2_t *frame =
            &primary->data.frames2[frameIndex];
        const xanim_int16_vec2_t *nextFrame =
            &primary->data.frames2[frameIndex + 1];

        rotation[0] =
            (float)((int32_t)nextFrame->components[0] - (int32_t)frame->components[0]) *
                frameFrac +
            (float)frame->components[0];
        rotation[1] =
            (float)((int32_t)nextFrame->components[1] - (int32_t)frame->components[1]) *
                frameFrac +
            (float)frame->components[1];
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for optional delta sampling. */
static void coduo_engine_xanim_sample_optional_translation(
    const xanim_translation_stream_t *secondary, int32_t frameCount,
    float time, float frameTime, int32_t roundedFrame, qboolean useShortKeys,
    vec3_t move)
{
    int32_t frameIndex = roundedFrame;
    float frameFrac;

    if (secondary == NULL) {
        move[0] = 0.0f;
        move[1] = 0.0f;
        move[2] = 0.0f;
    } else if (secondary->frameIndex == 0) {
        move[0] = secondary->data.inlineLane0;
        move[1] = secondary->inlineLanes.lane1;
        move[2] = secondary->inlineLanes.lane2;
    } else {
        if (secondary->frameIndex < frameCount) {
            if (useShortKeys) {
                frameFrac = coduo_engine_xanim_short_key_frame_frac(
                    time, frameTime, secondary->key.shortKeys,
                    secondary->frameIndex, roundedFrame, &frameIndex);
            } else {
                frameFrac = coduo_engine_xanim_byte_key_frame_frac(
                    time, frameTime, secondary->key.byteKeys,
                    secondary->frameIndex, roundedFrame, &frameIndex);
            }
        } else {
            frameFrac = frameTime - (float)roundedFrame;
        }

        const float *frame = secondary->data.frames[frameIndex];
        const float *nextFrame = secondary->data.frames[frameIndex + 1];

        move[0] = (nextFrame[0] - frame[0]) * frameFrac + frame[0];
        move[1] = (nextFrame[1] - frame[1]) * frameFrac + frame[1];
        move[2] = (nextFrame[2] - frame[2]) * frameFrac + frame[2];
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static void coduo_engine_xanim_load_file_copy_rotation_keys(xanim_rotation_stream_t *stream,
                                         uint8_t **pos, uint16_t frameCount,
                                         uint16_t totalFrameCount,
                                         qboolean smallFrameKeys)
{
    if (frameCount >= totalFrameCount) {
        return;
    }

    if (smallFrameKeys) {
        memcpy(stream->tail.byteKeys, *pos, frameCount);
        *pos += frameCount;
    } else {
        size_t keyBytes = (size_t)frameCount * sizeof(uint16_t);

        memcpy(stream->tail.shortKeys, *pos, keyBytes);
        *pos += keyBytes;
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static void
coduo_engine_xanim_load_file_copy_translation_keys(xanim_translation_stream_t *stream,
                               uint8_t **pos, uint16_t frameCount,
                               uint16_t totalFrameCount,
                               qboolean smallFrameKeys)
{
    if (frameCount >= totalFrameCount) {
        return;
    }

    if (smallFrameKeys) {
        memcpy(stream->key.byteKeys, *pos, frameCount);
        *pos += frameCount;
    } else {
        size_t keyBytes = (size_t)frameCount * sizeof(uint16_t);

        memcpy(stream->key.shortKeys, *pos, keyBytes);
        *pos += keyBytes;
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static void coduo_engine_xanim_load_file_parse_rotation_stream(
    uint8_t **pos, xanim_rotation_stream_t **streamOut,
    uint16_t totalFrameCount, qboolean smallFrameKeys, qboolean compressedVec2,
    qboolean negate, coduo_xanim_load_alloc_callback_t alloc)
{
    uint16_t frameCount = coduo_engine_xanim_load_file_read_stream_count(pos);
    xanim_rotation_stream_t *stream;

    if (frameCount == 0) {
        *streamOut = NULL;
        return;
    }

    if (frameCount == 1) {
        if (compressedVec2) {
            xanim_int16_vec2_t frame;

            coduo_engine_xanim_load_file_read_vec2(pos, negate, &frame);
            stream = alloc(coduo_engine_xanim_load_file_rotation_inline_stream_size(
                qtrue));
            stream->data.inlinePrefix.lane0 = frame.components[0];
            stream->data.inlinePrefix.lane1 = frame.components[1];
        } else {
            xanim_int16_vec4_t frame;

            coduo_engine_xanim_load_file_read_vec4(pos, negate, &frame);
            stream = alloc(coduo_engine_xanim_load_file_rotation_inline_stream_size(
                qfalse));
            stream->data.inlinePrefix.lane0 = frame.components[0];
            stream->data.inlinePrefix.lane1 = frame.components[1];
            stream->tail.inlineFull.lane2 = frame.components[2];
            stream->tail.inlineFull.lane3 = frame.components[3];
        }

        stream->frameIndex = 0;
        *streamOut = stream;
        return;
    }

    stream = alloc(coduo_engine_xanim_load_file_rotation_stream_size(
        frameCount, totalFrameCount, smallFrameKeys));
    coduo_engine_xanim_load_file_copy_rotation_keys(stream, pos, frameCount, totalFrameCount,
                                 smallFrameKeys);

    if (compressedVec2) {
        xanim_int16_vec2_t *frames =
            alloc((size_t)frameCount * sizeof(*frames));

        stream->data.frames2 = frames;
        for (int32_t frameIndex = 0; frameIndex < (int32_t)frameCount;
             ++frameIndex) {
            coduo_engine_xanim_load_file_read_vec2(
                pos, frameIndex == 0 ? negate : qfalse,
                &frames[frameIndex]);
        }
        coduo_engine_xanim_load_file_fix_vec2_continuity(frames, frameCount);
    } else {
        xanim_int16_vec4_t *frames =
            alloc((size_t)frameCount * sizeof(*frames));

        stream->data.frames4 = frames;
        for (int32_t frameIndex = 0; frameIndex < (int32_t)frameCount;
             ++frameIndex) {
            coduo_engine_xanim_load_file_read_vec4(
                pos, frameIndex == 0 ? negate : qfalse,
                &frames[frameIndex]);
        }
        coduo_engine_xanim_load_file_fix_vec4_continuity(frames, frameCount);
    }

    stream->frameIndex = (uint16_t)(frameCount - 1U);
    *streamOut = stream;
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimLoadFile's byte stream. */
static void coduo_engine_xanim_load_file_parse_translation_stream(
    uint8_t **pos, xanim_translation_stream_t **streamOut,
    uint16_t totalFrameCount, qboolean smallFrameKeys,
    coduo_xanim_load_alloc_callback_t alloc)
{
    uint16_t frameCount = coduo_engine_xanim_load_file_read_stream_count(pos);
    xanim_translation_stream_t *stream;

    if (frameCount == 0) {
        *streamOut = NULL;
        return;
    }

    if (frameCount == 1) {
        stream = alloc(coduo_engine_xanim_load_file_translation_inline_stream_size());
        stream->data.inlineLane0 = coduo_engine_xanim_load_file_read_float(pos);
        stream->frameIndex = 0;
        stream->inlineLanes.lane1 = coduo_engine_xanim_load_file_read_float(pos);
        stream->inlineLanes.lane2 = coduo_engine_xanim_load_file_read_float(pos);
        *streamOut = stream;
        return;
    }

    stream = alloc(coduo_engine_xanim_load_file_translation_stream_size(
        frameCount, totalFrameCount, smallFrameKeys));
    coduo_engine_xanim_load_file_copy_translation_keys(stream, pos, frameCount, totalFrameCount,
                                   smallFrameKeys);

    vec3_t *frames = alloc((size_t)frameCount * sizeof(*frames));

    stream->data.frames = frames;
    for (int32_t frameIndex = 0; frameIndex < (int32_t)frameCount;
         ++frameIndex) {
        (*frames)[0] = coduo_engine_xanim_load_file_read_float(pos);
        (*frames)[1] = coduo_engine_xanim_load_file_read_float(pos);
        (*frames)[2] = coduo_engine_xanim_load_file_read_float(pos);
        frames++;
    }

    stream->frameIndex = (uint16_t)(frameCount - 1U);
    *streamOut = stream;
}

/* NOT_FROM_ORIGINAL_SOURCE: typed local access to the model part-name payload. */
static XModelPartsData *
coduo_engine_xanim_model_part_name_payload_record(XModel *model)
{
    return model->info->parts->data.xmodelParts;
}

/* NOT_FROM_ORIGINAL_SOURCE: local typed access to the model part-name table. */
static XModelPartNameTable *coduo_engine_xanim_model_part_name_table(
    XModel *model)
{
    XModelPartsData *payload =
        coduo_engine_xanim_model_part_name_payload_record(model);
    XModelPartNameTableSlot *tableSlot =
        payload->partNameTableSlot;

    return tableSlot->partNameTable;
}

/* NOT_FROM_ORIGINAL_SOURCE: typed local view over the model part-name payload. */
static coduo_xmodel_part_name_payload_view_t
coduo_engine_xanim_model_part_name_payload(XModel *model)
{
    XModelPartsData *payload;
    XModelPartNameTableSlot *tableSlot;
    coduo_xmodel_part_name_payload_view_t view;

    payload = coduo_engine_xanim_model_part_name_payload_record(model);
    tableSlot = payload->partNameTableSlot;

    view.partNameTable = tableSlot->partNameTable;
    view.rootPartCount = payload->rootPartCount;
    view.baseRotations = payload->baseRotations;

    return view;
}

/* Exact source identity from XAnimFreeMemory__FP10fileData_s. */
void XAnimFreeMemory(fileData_t *entry)
{
    XAnimParts *loadedRecord = entry->data.xanimParts;

    if (xanim_rootTreeHandle != 0) {
        uint16_t nameHandle;

        nameHandle = SL_GetLowercaseString_(entry->name, 0, 7);
        GetVariable(xanim_rootTreeHandle, nameHandle);
        SL_RemoveRefToString(nameHandle);
    }

    uint16_t *partNameHandles =
        loadedRecord->partNameHandles;
    int16_t partNameCount = (int16_t)partNameHandles[0];

    for (int32_t partIndex = 0; partIndex < partNameCount; ++partIndex) {
        SL_RemoveRefToString(partNameHandles[partIndex + 1]);
    }

    xanim_notetrack_t *noteTrack = loadedRecord->noteTracks;

    if (noteTrack != NULL) {
        while (noteTrack->nameHandle != 0) {
            SL_RemoveRefToString(noteTrack->nameHandle);
            noteTrack++;
        }
    }
}

/* Exact source name and four-argument signature from the Mac symbol
 * ReadNoteTracks__FPCcPcP10XAnimPartsPFi_Pv. */
uint8_t *ReadNoteTracks(const char *animName, uint8_t *pos,
                        XAnimParts *loadedRecord,
                        void *(*alloc)(size_t size))
{
    uint8_t noteTrackCount;
    xanim_notetrack_t *noteTracks;

    (void)animName;

    noteTrackCount = *pos;
    pos++;

    noteTracks = alloc((size_t)(noteTrackCount + 1U) *
                           sizeof(*noteTracks) +
                       sizeof(noteTracks->nameHandle));
    loadedRecord->noteTracks = noteTracks;

    for (int32_t noteTrackIndex = 0; noteTrackIndex < noteTrackCount;
         ++noteTrackIndex) {
        uint16_t frameIndex;

        noteTracks->nameHandle = SL_GetString_((const char *)pos, 0, 3);
        pos += strlen((const char *)pos) + 1U;
        /* Stock VA 0x080b80d1 reads one word immediately after a variable-
         * length string; that cursor is not guaranteed to be word-aligned. */
        memcpy(&frameIndex, pos, sizeof(frameIndex));
        pos += sizeof(frameIndex);

        if (loadedRecord->frameCountMinusOne == 0) {
            noteTracks->time = 0.0f;
        } else {
            noteTracks->time =
                (float)frameIndex /
                (float)loadedRecord->frameCountMinusOne;
        }

        noteTracks++;
    }

    noteTracks->nameHandle = SL_GetString_("end", 0, 3);
    noteTracks->time = 1.0f;
    noteTracks++;
    noteTracks->nameHandle = 0;

    return pos;
}

void XAnimCalcDeltaParts(XAnimParts *loadedRecord,
                              vec2_t rotation, vec3_t move, float time)
{
    int32_t frameCount = loadedRecord->frameCountMinusOne;
    xanim_part_stream_pair_t *deltaMotion =
        loadedRecord->deltaMotion;
    xanim_rotation_stream_t *primary = deltaMotion->rotation;
    xanim_translation_stream_t *secondary = deltaMotion->translation;

    if (time == 1.0f || frameCount == 0) {
        coduo_engine_xanim_sample_optional_rotation_last_frame(primary, rotation);
        coduo_engine_xanim_sample_optional_translation_last_frame(secondary, move);
        return;
    }

    float frameTime = time * (float)frameCount;
#if defined(__x86_64__)
    int32_t roundedFrame =
        CODUO_X87_TRUNCATE_I32((long double)frameTime);
#else
    int32_t roundedFrame = (int32_t)frameTime;
#endif
    qboolean useShortKeys =
        frameCount > (int32_t)(XANIM_SMALL_FRAME_KEY_LIMIT - 1U);

    coduo_engine_xanim_sample_optional_rotation(primary, frameCount, time, frameTime,
                               roundedFrame, useShortKeys, rotation);
    coduo_engine_xanim_sample_optional_translation(secondary, frameCount, time, frameTime,
                                 roundedFrame, useShortKeys, move);
}

void TransformToQuatRefFrame(const vec2_t rotation, vec2_t vector)
{
    float lane0Squared = rotation[0] * rotation[0]; /* single mul -> native */
    /* lane0Squared(stored) + rotation[1]^2 kept 80-bit, one store -> shim. */
#if EMULATE_X87
    float lengthSquared = x87f_store_f32(x87f_add(
        x87f_load_f32(lane0Squared),
        x87f_mul(x87f_load_f32(rotation[1]), x87f_load_f32(rotation[1]))));
#else
    float lengthSquared = lane0Squared + rotation[1] * rotation[1];
#endif

    if (lengthSquared != 0.0f) {
        float inverseScale = XA_DIV(2.0f, lengthSquared);
        float reflection00 = lane0Squared * inverseScale; /* single mul native */
        float oldLane1 = vector[1];
#if EMULATE_X87
        /* (rotation[0]*rotation[1])*inverseScale, 2 muls one store. */
        float reflection01 = x87f_store_f32(x87f_mul(
            x87f_mul(x87f_load_f32(rotation[0]), x87f_load_f32(rotation[1])),
            x87f_load_f32(inverseScale)));
        /* vector[1] - (reflection00*vector[1] + reflection01*vector[0]). */
        vector[1] = x87f_store_f32(x87f_sub(
            x87f_load_f32(vector[1]),
            x87f_add(x87f_mul(x87f_load_f32(reflection00), x87f_load_f32(vector[1])),
                     x87f_mul(x87f_load_f32(reflection01), x87f_load_f32(vector[0])))));
        /* reflection01*oldLane1 + (1-reflection00)*vector[0]. */
        vector[0] = x87f_store_f32(x87f_add(
            x87f_mul(x87f_load_f32(reflection01), x87f_load_f32(oldLane1)),
            x87f_mul(x87f_sub(x87f_load_f32(1.0f), x87f_load_f32(reflection00)),
                     x87f_load_f32(vector[0]))));
#else
        float reflection01 = rotation[0] * rotation[1] * inverseScale;

        vector[1] -= reflection00 * vector[1] + reflection01 * vector[0];
        vector[0] = reflection01 * oldLane1 +
                    (1.0f - reflection00) * vector[0];
#endif
    }
}

void XAnimCalcRelDeltaParts(XAnimParts *loadedRecord,
                                  float weight, float *accumulatedDelta,
                                  float startTime, float endTime)
{
    vec2_t startRotation;
    vec2_t endRotation;
    vec3_t startMove;
    vec3_t endMove;
    vec3_t moveDelta;

    XAnimCalcDeltaParts(loadedRecord, startRotation, startMove,
                             startTime);
    XAnimCalcDeltaParts(loadedRecord, endRotation, endMove, endTime);

    if (loadedRecord->looped != 0 && endTime < startTime) {
        xanim_translation_stream_t *secondary =
            loadedRecord->deltaMotion->translation;

        if (secondary != NULL) {
            if (secondary->frameIndex == 0) {
                endMove[0] += secondary->data.inlineLane0;
                endMove[1] += secondary->inlineLanes.lane1;
                endMove[2] += secondary->inlineLanes.lane2;
            } else {
                const float *lastFrame =
                    secondary->data.frames[secondary->frameIndex];

                endMove[0] += lastFrame[0];
                endMove[1] += lastFrame[1];
                endMove[2] += lastFrame[2];
            }
        }
    }

    float scaledWeight = weight * XANIM_DELTA_ROTATION_SCALE;

    accumulatedDelta[0] +=
        (endRotation[0] * startRotation[1] -
         endRotation[1] * startRotation[0]) *
        scaledWeight;
    accumulatedDelta[1] +=
        (endRotation[1] * startRotation[1] +
         endRotation[0] * startRotation[0]) *
        scaledWeight;

    moveDelta[0] = endMove[0] - startMove[0];
    moveDelta[1] = endMove[1] - startMove[1];
    moveDelta[2] = endMove[2] - startMove[2];
    TransformToQuatRefFrame(endRotation, moveDelta);

    accumulatedDelta[2] += weight;
    XA_MADD(accumulatedDelta[3], weight, moveDelta[0]);
    XA_MADD(accumulatedDelta[4], weight, moveDelta[1]);
    XA_MADD(accumulatedDelta[5], weight, moveDelta[2]);
}

void XAnimLoadFile(const char *animName,
                   coduo_xanim_load_alloc_callback_t alloc)
{
    fileData_t *entry;
    char filePath[CODUO_MAX_STRING_CHARS];
    void *fileBuffer;
    uint8_t *pos;
    int32_t version;
    uint16_t fileFrameCount;
    int16_t partNameCount;
    uint32_t partNameHandleBytes;
    uint16_t *partNameHandles;
    uint8_t flags;
    uint8_t looped;
    uint8_t hasDeltaMotion;
    int16_t frameRate;
    XAnimParts *loadedRecord;
    uint16_t totalFrameCount;
    qboolean smallFrameKeys;
    uint32_t bitsetBytes;
    uint32_t partStreamBytes;
    uint8_t *signBitset;
    uint8_t *primaryBitset;

    entry = FS_GetDataForFile("xanim", animName, "");
    if (entry == NULL) {
        Com_Error(XANIM_COM_ERROR_DROP,
                  "\x15" "Cannot precache 'xanim/%s'.", animName);
        return;
    }

    if (entry->data.xanimParts != NULL) {
        return;
    }

    /* ORIGINAL_BINARY_BUG: stock uses unbounded sprintf into this 1,024-byte
     * stack pathname (VA 0x080b81c8..0x080b81d7). */
    sprintf(filePath, "xanim/%s", animName);
    if (FS_ReadFile(filePath, &fileBuffer) < 0) {
        Com_Error(XANIM_COM_ERROR_DROP, "\x15" "Cannot find 'xanim/%s'.",
                  animName);
        return;
    }

    /* ORIGINAL_BINARY_BUG: stock retains no end pointer or file length after
     * FS_ReadFile, so every serialized read below is unchecked. */
    pos = fileBuffer;
    version = (int16_t)coduo_engine_xanim_load_file_read_header_short(&pos);
    if (version != XANIM_FILE_VERSION) {
        FS_FreeFile(fileBuffer);
        Com_Error(XANIM_COM_ERROR_DROP,
                  "\x15" "xanim '%s' out of date (version %d, expecting %d)",
                  animName, version, XANIM_FILE_VERSION);
        return;
    }

    fileFrameCount = coduo_engine_xanim_load_file_read_header_short(&pos);
    partNameCount = (int16_t)coduo_engine_xanim_load_file_read_header_short(&pos);

    /* Serialized signed-count arithmetic is target-dword arithmetic at
     * VA 0x080b82c0..0x080b82cc, including malformed negative counts. */
    partNameHandleBytes =
        (uint32_t)((int32_t)partNameCount *
                       (int32_t)sizeof(partNameHandles[0]) +
                   (int32_t)sizeof(*partNameHandles));
    partNameHandles = alloc((size_t)partNameHandleBytes);
    partNameHandles[0] = (uint16_t)partNameCount;

    flags = *pos;
    pos++;
    looped = (uint8_t)(flags & XANIM_FILE_LOOPED_FLAG);
    hasDeltaMotion = (uint8_t)((flags & XANIM_FILE_DELTA_MOTION_FLAG)
                                              >> 1);
    frameRate = (int16_t)coduo_engine_xanim_load_file_read_header_short(&pos);

    loadedRecord = alloc(sizeof(*loadedRecord));
    loadedRecord->partNameHandles = partNameHandles;
    loadedRecord->frameRate = (float)frameRate;
    loadedRecord->looped = looped;
    loadedRecord->hasDeltaMotion = hasDeltaMotion;

    totalFrameCount = fileFrameCount;
    if (looped != 0) {
        totalFrameCount = (uint16_t)(totalFrameCount + 1U);
    }

    smallFrameKeys = totalFrameCount <= XANIM_SMALL_FRAME_KEY_LIMIT;
    loadedRecord->frameCountMinusOne = (uint16_t)(totalFrameCount - 1U);
    if (loadedRecord->frameCountMinusOne == 0) {
        loadedRecord->frequency = 0.0f;
    } else {
        loadedRecord->frequency =
            loadedRecord->frameRate /
            (float)loadedRecord->frameCountMinusOne;
    }

    if (hasDeltaMotion != 0) {
        xanim_part_stream_pair_t *optionalStreams =
            alloc(sizeof(*optionalStreams));

        loadedRecord->deltaMotion = optionalStreams;
        coduo_engine_xanim_load_file_parse_rotation_stream(&pos, &optionalStreams->rotation,
                                        totalFrameCount, smallFrameKeys, qtrue,
                                        qfalse, alloc);
        coduo_engine_xanim_load_file_parse_translation_stream(&pos, &optionalStreams->translation,
                                          totalFrameCount, smallFrameKeys,
                                          alloc);
    }

    bitsetBytes =
        (uint32_t)((((int32_t)partNameCount - 1) >> 3) + 1);
    signBitset = pos;
    pos += bitsetBytes;

    primaryBitset = alloc(bitsetBytes);
    memcpy(primaryBitset, pos, bitsetBytes);
    pos += bitsetBytes;
    loadedRecord->compressedRotationBits = primaryBitset;

    for (int32_t partIndex = 0; partIndex < partNameCount; ++partIndex) {
        size_t nameLength = strlen((const char *)pos) + 1U;

        partNameHandles[partIndex + 1] =
            SL_GetStringOfLen((const char *)pos, 0, nameLength,
                                     XANIM_PART_NAME_STRING_TYPE);
        pos += nameLength;
    }

    partStreamBytes =
        (uint32_t)((int32_t)partNameCount *
                   (int32_t)sizeof(loadedRecord->partStreamPairs[0]));
    loadedRecord->partStreamPairs = alloc((size_t)partStreamBytes);

    for (int32_t partIndex = 0; partIndex < partNameCount; ++partIndex) {
        qboolean negate = coduo_engine_xanim_part_bit_is_set(signBitset, partIndex);
        qboolean compressedVec2 = coduo_engine_xanim_part_bit_is_set(primaryBitset, partIndex);
        xanim_part_stream_pair_t *streamPair =
            &loadedRecord->partStreamPairs[partIndex];

        coduo_engine_xanim_load_file_parse_rotation_stream(&pos, &streamPair->rotation,
                                        totalFrameCount, smallFrameKeys,
                                        compressedVec2, negate, alloc);
        coduo_engine_xanim_load_file_parse_translation_stream(&pos, &streamPair->translation,
                                          totalFrameCount, smallFrameKeys,
                                          alloc);
    }

    pos = ReadNoteTracks(animName, pos, loadedRecord, alloc);
    (void)pos;

    FS_FreeFile(fileBuffer);
    entry->data.xanimParts = loadedRecord;
    entry->freeData = XAnimFreeMemory;
}

uint16_t
XAnimSetModel(XAnimEntry *entry, XModel **models,
                    int32_t modelCount)
{
    XAnimParts *loadedRecord;
    uint16_t *animPartNameTable;
    uint16_t *animPartNames;
    int32_t animPartCount;
    uint32_t remapSize;

    loadedRecord = coduo_engine_xanim_entry_loaded_record(entry);
    animPartNameTable = loadedRecord->partNameHandles;
    animPartCount = (int16_t)animPartNameTable[0];
    animPartNames = animPartNameTable + 1;
    /* VA 0x080b9770..0x080b9788 sign-extends the serialized count and
     * performs this size calculation in the original target dword. */
    remapSize =
        (uint32_t)(animPartCount + (int32_t)sizeof(XAnimToXModel));

    uint32_t remapStorage[((size_t)remapSize + sizeof(uint32_t) - 1U) /
                          sizeof(uint32_t)];
    XAnimToXModel *remap =
        (XAnimToXModel *)remapStorage;

    for (int32_t wordIndex = 0; wordIndex < CODUO_XANIM_PART_BITSET_WORD_COUNT;
         ++wordIndex) {
        remap->partBits[wordIndex] = 0;
    }

    for (int32_t animPartIndex = animPartCount - 1; animPartIndex >= 0;
         --animPartIndex) {
        remap->boneIndex[animPartIndex] =
            CODUO_XANIM_PART_REMAP_SENTINEL;
    }

    int32_t sourcePartIndex = 0;

    for (int32_t modelIndex = 0; modelIndex < modelCount; ++modelIndex) {
        XModelPartNameTable *modelPartNameTable =
            coduo_engine_xanim_model_part_name_table(models[modelIndex]);
        int32_t modelPartCount = modelPartNameTable->count;

        for (int32_t modelPartIndex = 0; modelPartIndex < modelPartCount;
             ++modelPartIndex) {
            uint16_t modelPartName =
                modelPartNameTable->handles[modelPartIndex];

            for (int32_t animPartIndex = animPartCount - 1; animPartIndex >= 0;
                 --animPartIndex) {
                if (modelPartName != animPartNames[animPartIndex]) {
                    continue;
                }

                if (remap->boneIndex[animPartIndex] ==
                    CODUO_XANIM_PART_REMAP_SENTINEL) {
                    remap->boneIndex[animPartIndex] =
                        (uint8_t)sourcePartIndex;
                    remap->partBits[sourcePartIndex >> 5] |=
                        1U << (sourcePartIndex & 31);
                }
                break;
            }

            sourcePartIndex++;
        }
    }

    return SL_GetStringOfLen((const char *)remap, 0, remapSize,
                             CODUO_XANIM_PART_REMAP_STRING_TYPE);
}

void XAnimCalcPartsSmallIndices(XAnimParts *loadedRecord,
                                const uint8_t *targetToSourcePart,
                                float time, float weight,
                                DObjAnimMat *part)
{
    const uint8_t *evalSkipBytes = (const uint8_t *)xanim_evalSkipBits;
    int32_t frameCount = loadedRecord->frameCountMinusOne;
    float scaledWeight = weight * XANIM_PACKED_SHORT_TO_FLOAT_SCALE;
    float frameTime = time * (float)frameCount;
#if defined(__x86_64__)
    int32_t roundedFrame =
        CODUO_X87_TRUNCATE_I32((long double)frameTime);
#else
    int32_t roundedFrame = (int32_t)frameTime;
#endif
    uint8_t *bitsetBytes = loadedRecord->compressedRotationBits;
    int16_t partNameCount = (int16_t)loadedRecord->partNameHandles[0];

    for (int32_t targetPart = 0; targetPart < partNameCount; ++targetPart) {
        uint8_t sourcePart =
            targetToSourcePart[targetPart];

        if (coduo_engine_xanim_part_bit_is_set(evalSkipBytes, sourcePart)) {
            continue;
        }

        DObjAnimMat *evalPart = &part[sourcePart];
        xanim_part_stream_pair_t *streamPair =
            &loadedRecord->partStreamPairs[targetPart];
        xanim_rotation_stream_t *primary = streamPair->rotation;
        int32_t frameIndex = roundedFrame;
        float frameFrac;

        if (coduo_engine_xanim_part_bit_is_set(bitsetBytes, targetPart)) {
            if (primary == NULL) {
                evalPart->primaryLane3 += weight;
            } else if (primary->frameIndex == 0) {
                evalPart->primaryLane2 +=
                    (float)primary->data.inlinePrefix.lane0 * scaledWeight;
                evalPart->primaryLane3 +=
                    (float)primary->data.inlinePrefix.lane1 * scaledWeight;
            } else {
                const uint8_t *primaryKeys = primary->tail.byteKeys;

                if (primary->frameIndex < frameCount) {
                    frameIndex = XAnimFindByteKey(time, primaryKeys,
                                                  primary->frameIndex,
                                                  roundedFrame);
                    frameFrac =
                        (frameTime - (float)primaryKeys[frameIndex]) /
                        (float)((int32_t)primaryKeys[frameIndex + 1] -
                                (int32_t)primaryKeys[frameIndex]);
                } else {
                    frameFrac = frameTime - (float)roundedFrame;
                }

                xanim_int16_vec2_t *frame =
                    &primary->data.frames2[frameIndex];
                xanim_int16_vec2_t *nextFrame =
                    &primary->data.frames2[frameIndex + 1];

                evalPart->primaryLane2 +=
                    ((float)((int32_t)nextFrame->components[0] -
                             (int32_t)frame->components[0]) *
                         frameFrac +
                     (float)frame->components[0]) *
                    scaledWeight;
                evalPart->primaryLane3 +=
                    ((float)((int32_t)nextFrame->components[1] -
                             (int32_t)frame->components[1]) *
                         frameFrac +
                     (float)frame->components[1]) *
                    scaledWeight;
            }
        } else if (primary->frameIndex == 0) {
            evalPart->primaryLane0 +=
                (float)primary->data.inlinePrefix.lane0 * scaledWeight;
            evalPart->primaryLane1 +=
                (float)primary->data.inlinePrefix.lane1 * scaledWeight;
            evalPart->primaryLane2 +=
                (float)primary->tail.inlineFull.lane2 * scaledWeight;
            evalPart->primaryLane3 +=
                (float)primary->tail.inlineFull.lane3 * scaledWeight;
        } else {
            const uint8_t *primaryKeys = primary->tail.byteKeys;

            if (primary->frameIndex < frameCount) {
                frameIndex = XAnimFindByteKey(time, primaryKeys,
                                              primary->frameIndex,
                                              roundedFrame);
                frameFrac =
                    (frameTime - (float)primaryKeys[frameIndex]) /
                    (float)((int32_t)primaryKeys[frameIndex + 1] -
                            (int32_t)primaryKeys[frameIndex]);
            } else {
                frameFrac = frameTime - (float)roundedFrame;
            }

            xanim_int16_vec4_t *frame =
                &primary->data.frames4[frameIndex];
            xanim_int16_vec4_t *nextFrame =
                &primary->data.frames4[frameIndex + 1];

            evalPart->primaryLane0 +=
                ((float)((int32_t)nextFrame->components[0] - (int32_t)frame->components[0]) *
                     frameFrac +
                 (float)frame->components[0]) *
                scaledWeight;
            evalPart->primaryLane1 +=
                ((float)((int32_t)nextFrame->components[1] - (int32_t)frame->components[1]) *
                     frameFrac +
                 (float)frame->components[1]) *
                scaledWeight;
            evalPart->primaryLane2 +=
                ((float)((int32_t)nextFrame->components[2] - (int32_t)frame->components[2]) *
                     frameFrac +
                 (float)frame->components[2]) *
                scaledWeight;
            evalPart->primaryLane3 +=
                ((float)((int32_t)nextFrame->components[3] - (int32_t)frame->components[3]) *
                     frameFrac +
                 (float)frame->components[3]) *
                scaledWeight;
        }

        xanim_translation_stream_t *secondary = streamPair->translation;
        if (secondary != NULL) {
            if (secondary->frameIndex == 0) {
                evalPart->secondaryLane0 +=
                    weight * secondary->data.inlineLane0;
                evalPart->secondaryLane1 +=
                    weight * secondary->inlineLanes.lane1;
                evalPart->secondaryLane2 +=
                    weight * secondary->inlineLanes.lane2;
            } else {
                const uint8_t *secondaryKeys = secondary->key.byteKeys;

                if (secondary->frameIndex < frameCount) {
                    frameIndex = XAnimFindByteKey(time, secondaryKeys,
                                                  secondary->frameIndex,
                                                  roundedFrame);
                    frameFrac =
                        (frameTime - (float)secondaryKeys[frameIndex]) /
                        (float)((int32_t)secondaryKeys[frameIndex + 1] -
                                (int32_t)secondaryKeys[frameIndex]);
                } else {
                    frameIndex = roundedFrame;
                    frameFrac = frameTime - (float)roundedFrame;
                }

                float *frame = secondary->data.frames[frameIndex];
                float *nextFrame = secondary->data.frames[frameIndex + 1];

                evalPart->secondaryLane0 +=
                    ((nextFrame[0] - frame[0]) * frameFrac + frame[0]) *
                    weight;
                evalPart->secondaryLane1 +=
                    ((nextFrame[1] - frame[1]) * frameFrac + frame[1]) *
                    weight;
                evalPart->secondaryLane2 +=
                    ((nextFrame[2] - frame[2]) * frameFrac + frame[2]) *
                    weight;
            }
        }

        evalPart->accumulatedWeight += weight;
    }
}

void XAnimCalcPartsLargeIndices(
    XAnimParts *loadedRecord,
    const uint8_t *targetToSourcePart, float time,
    float weight, DObjAnimMat *part)
{
    const uint8_t *evalSkipBytes = (const uint8_t *)xanim_evalSkipBits;
    int32_t frameCount = loadedRecord->frameCountMinusOne;
    float scaledWeight = weight * XANIM_PACKED_SHORT_TO_FLOAT_SCALE;
    float frameTime = time * (float)frameCount;
#if defined(__x86_64__)
    int32_t roundedFrame =
        CODUO_X87_TRUNCATE_I32((long double)frameTime);
#else
    int32_t roundedFrame = (int32_t)frameTime;
#endif
    uint8_t *bitsetBytes = loadedRecord->compressedRotationBits;
    int16_t partNameCount = (int16_t)loadedRecord->partNameHandles[0];

    for (int32_t targetPart = 0; targetPart < partNameCount; ++targetPart) {
        uint8_t sourcePart =
            targetToSourcePart[targetPart];

        if (coduo_engine_xanim_part_bit_is_set(evalSkipBytes, sourcePart)) {
            continue;
        }

        DObjAnimMat *evalPart = &part[sourcePart];
        xanim_part_stream_pair_t *streamPair =
            &loadedRecord->partStreamPairs[targetPart];
        xanim_rotation_stream_t *primary = streamPair->rotation;
        int32_t frameIndex = roundedFrame;
        float frameFrac;

        if (coduo_engine_xanim_part_bit_is_set(bitsetBytes, targetPart)) {
            if (primary == NULL) {
                evalPart->primaryLane3 += weight;
            } else if (primary->frameIndex == 0) {
                evalPart->primaryLane2 +=
                    (float)primary->data.inlinePrefix.lane0 * scaledWeight;
                evalPart->primaryLane3 +=
                    (float)primary->data.inlinePrefix.lane1 * scaledWeight;
            } else {
                const uint16_t *primaryKeys = primary->tail.shortKeys;

                if (primary->frameIndex < frameCount) {
                    frameIndex = XAnimFindShortKey(time, primaryKeys,
                                                   primary->frameIndex,
                                                   roundedFrame);
                    frameFrac =
                        (frameTime - (float)primaryKeys[frameIndex]) /
                        (float)((int32_t)primaryKeys[frameIndex + 1] -
                                (int32_t)primaryKeys[frameIndex]);
                } else {
                    frameFrac = frameTime - (float)roundedFrame;
                }

                xanim_int16_vec2_t *frame =
                    &primary->data.frames2[frameIndex];
                xanim_int16_vec2_t *nextFrame =
                    &primary->data.frames2[frameIndex + 1];

                evalPart->primaryLane2 +=
                    ((float)((int32_t)nextFrame->components[0] -
                             (int32_t)frame->components[0]) *
                         frameFrac +
                     (float)frame->components[0]) *
                    scaledWeight;
                evalPart->primaryLane3 +=
                    ((float)((int32_t)nextFrame->components[1] -
                             (int32_t)frame->components[1]) *
                         frameFrac +
                     (float)frame->components[1]) *
                    scaledWeight;
            }
        } else if (primary->frameIndex == 0) {
            evalPart->primaryLane0 +=
                (float)primary->data.inlinePrefix.lane0 * scaledWeight;
            evalPart->primaryLane1 +=
                (float)primary->data.inlinePrefix.lane1 * scaledWeight;
            evalPart->primaryLane2 +=
                (float)primary->tail.inlineFull.lane2 * scaledWeight;
            evalPart->primaryLane3 +=
                (float)primary->tail.inlineFull.lane3 * scaledWeight;
        } else {
            const uint16_t *primaryKeys = primary->tail.shortKeys;

            if (primary->frameIndex < frameCount) {
                frameIndex = XAnimFindShortKey(time, primaryKeys,
                                               primary->frameIndex,
                                               roundedFrame);
                frameFrac =
                    (frameTime - (float)primaryKeys[frameIndex]) /
                    (float)((int32_t)primaryKeys[frameIndex + 1] -
                            (int32_t)primaryKeys[frameIndex]);
            } else {
                frameFrac = frameTime - (float)roundedFrame;
            }

            xanim_int16_vec4_t *frame =
                &primary->data.frames4[frameIndex];
            xanim_int16_vec4_t *nextFrame =
                &primary->data.frames4[frameIndex + 1];

            evalPart->primaryLane0 +=
                ((float)((int32_t)nextFrame->components[0] - (int32_t)frame->components[0]) *
                     frameFrac +
                 (float)frame->components[0]) *
                scaledWeight;
            evalPart->primaryLane1 +=
                ((float)((int32_t)nextFrame->components[1] - (int32_t)frame->components[1]) *
                     frameFrac +
                 (float)frame->components[1]) *
                scaledWeight;
            evalPart->primaryLane2 +=
                ((float)((int32_t)nextFrame->components[2] - (int32_t)frame->components[2]) *
                     frameFrac +
                 (float)frame->components[2]) *
                scaledWeight;
            evalPart->primaryLane3 +=
                ((float)((int32_t)nextFrame->components[3] - (int32_t)frame->components[3]) *
                     frameFrac +
                 (float)frame->components[3]) *
                scaledWeight;
        }

        xanim_translation_stream_t *secondary = streamPair->translation;
        if (secondary != NULL) {
            if (secondary->frameIndex == 0) {
                evalPart->secondaryLane0 +=
                    weight * secondary->data.inlineLane0;
                evalPart->secondaryLane1 +=
                    weight * secondary->inlineLanes.lane1;
                evalPart->secondaryLane2 +=
                    weight * secondary->inlineLanes.lane2;
            } else {
                const uint16_t *secondaryKeys =
                    secondary->key.shortKeys;

                if (secondary->frameIndex < frameCount) {
                    frameIndex = XAnimFindShortKey(time, secondaryKeys,
                                                   secondary->frameIndex,
                                                   roundedFrame);
                    frameFrac =
                        (frameTime - (float)secondaryKeys[frameIndex]) /
                        (float)((int32_t)secondaryKeys[frameIndex + 1] -
                                (int32_t)secondaryKeys[frameIndex]);
                } else {
                    frameIndex = roundedFrame;
                    frameFrac = frameTime - (float)roundedFrame;
                }

                float *frame = secondary->data.frames[frameIndex];
                float *nextFrame = secondary->data.frames[frameIndex + 1];

                evalPart->secondaryLane0 +=
                    ((nextFrame[0] - frame[0]) * frameFrac + frame[0]) *
                    weight;
                evalPart->secondaryLane1 +=
                    ((nextFrame[1] - frame[1]) * frameFrac + frame[1]) *
                    weight;
                evalPart->secondaryLane2 +=
                    ((nextFrame[2] - frame[2]) * frameFrac + frame[2]) *
                    weight;
            }
        }

        evalPart->accumulatedWeight += weight;
    }
}

void XAnimCalcNonLoopEnd(
    XAnimParts *loadedRecord,
    const uint8_t *targetToSourcePart, float weight,
    DObjAnimMat *part)
{
    const uint8_t *evalSkipBytes = (const uint8_t *)xanim_evalSkipBits;
    float scaledWeight = weight * XANIM_PACKED_SHORT_TO_FLOAT_SCALE;
    uint8_t *bitsetBytes = loadedRecord->compressedRotationBits;
    int16_t partNameCount = (int16_t)loadedRecord->partNameHandles[0];

    for (int32_t targetPart = 0; targetPart < partNameCount; ++targetPart) {
        uint8_t sourcePart =
            targetToSourcePart[targetPart];

        if (coduo_engine_xanim_part_bit_is_set(evalSkipBytes, sourcePart)) {
            continue;
        }

        DObjAnimMat *evalPart = &part[sourcePart];
        xanim_part_stream_pair_t *streamPair =
            &loadedRecord->partStreamPairs[targetPart];
        xanim_rotation_stream_t *primary = streamPair->rotation;

        if (coduo_engine_xanim_part_bit_is_set(bitsetBytes, targetPart)) {
            if (primary == NULL) {
                evalPart->primaryLane3 += weight;
            } else if (primary->frameIndex == 0) {
                evalPart->primaryLane2 +=
                    (float)primary->data.inlinePrefix.lane0 * scaledWeight;
                evalPart->primaryLane3 +=
                    (float)primary->data.inlinePrefix.lane1 * scaledWeight;
            } else {
                xanim_int16_vec2_t *frame =
                    &primary->data.frames2[primary->frameIndex];

                XA_MADD(evalPart->primaryLane2, (float)frame->components[0], scaledWeight);
                XA_MADD(evalPart->primaryLane3, (float)frame->components[1], scaledWeight);
            }
        } else if (primary->frameIndex == 0) {
            evalPart->primaryLane0 +=
                (float)primary->data.inlinePrefix.lane0 * scaledWeight;
            evalPart->primaryLane1 +=
                (float)primary->data.inlinePrefix.lane1 * scaledWeight;
            evalPart->primaryLane2 +=
                (float)primary->tail.inlineFull.lane2 * scaledWeight;
            evalPart->primaryLane3 +=
                (float)primary->tail.inlineFull.lane3 * scaledWeight;
        } else {
            xanim_int16_vec4_t *frame =
                &primary->data.frames4[primary->frameIndex];

            XA_MADD(evalPart->primaryLane0, (float)frame->components[0], scaledWeight);
            XA_MADD(evalPart->primaryLane1, (float)frame->components[1], scaledWeight);
            XA_MADD(evalPart->primaryLane2, (float)frame->components[2], scaledWeight);
            XA_MADD(evalPart->primaryLane3, (float)frame->components[3], scaledWeight);
        }

        xanim_translation_stream_t *secondary = streamPair->translation;
        if (secondary != NULL) {
            if (secondary->frameIndex == 0) {
                evalPart->secondaryLane0 +=
                    weight * secondary->data.inlineLane0;
                evalPart->secondaryLane1 +=
                    weight * secondary->inlineLanes.lane1;
                evalPart->secondaryLane2 +=
                    weight * secondary->inlineLanes.lane2;
            } else {
                vec3_t *frame =
                    &secondary->data.frames[secondary->frameIndex];

                XA_MADD(evalPart->secondaryLane0, weight, (*frame)[0]);
                XA_MADD(evalPart->secondaryLane1, weight, (*frame)[1]);
                XA_MADD(evalPart->secondaryLane2, weight, (*frame)[2]);
            }
        }

        evalPart->accumulatedWeight += weight;
    }
}

void XAnimCalcData(fileData_t *entry,
                               XAnimToXModel *partRemap,
                               float weight, DObjAnimMat *part,
                               float time)
{
    XAnimParts *loadedRecord = entry->data.xanimParts;

    for (int32_t wordIndex = 0; wordIndex < CODUO_XANIM_PART_BITSET_WORD_COUNT;
         ++wordIndex) {
        xanim_evalPartBits[wordIndex] |=
            partRemap->partBits[wordIndex] &
            ~xanim_evalSkipBits[wordIndex];
    }

    if (time == 1.0f || loadedRecord->frameCountMinusOne == 0) {
        XAnimCalcNonLoopEnd(loadedRecord,
                                        partRemap->boneIndex, weight,
                                        part);
    } else if (loadedRecord->frameCountMinusOne <
               XANIM_SMALL_FRAME_KEY_LIMIT) {
        XAnimCalcPartsSmallIndices(loadedRecord, partRemap->boneIndex, time,
                             weight, part);
    } else {
        XAnimCalcPartsLargeIndices(loadedRecord,
                                      partRemap->boneIndex, time,
                                      weight, part);
    }
}

void XAnimCalcAbsDeltaParts(
    XAnimParts *loadedRecord, float weight,
    float *delta, float time)
{
    vec2_t rotation;
    vec3_t move;

    XAnimCalcDeltaParts(loadedRecord, rotation, move, time);

    /* The binary rounds weight*scale to float once (fstp at 0x80bb601) and
     * reuses it for both lanes; keeping it in the lane expressions would skip
     * that rounding. */
    float scaledWeight = weight * XANIM_PACKED_SHORT_TO_FLOAT_SCALE;

    XA_MADD(delta[0], scaledWeight, rotation[0]);
    XA_MADD(delta[1], scaledWeight, rotation[1]);
    delta[2] += weight; /* single add -> native */
    XA_MADD(delta[3], weight, move[0]);
    XA_MADD(delta[4], weight, move[1]);
    XA_MADD(delta[5], weight, move[2]);
}

void XAnimClearServerInfo(XAnimInfo *node)
{
    if (node->notifyName != 0) {
        SL_RemoveRefToString(node->notifyName);
    }
}

void XAnimFreeInfo(XAnimTree *runtimeTree,
                       uint16_t handle)
{
    XAnimInfo *node = &xanim_pool[handle];

    XAnimClearServerInfo(node);
    node->notifyChildIndex = 0;
    node->freeNext = xanim_pool[0].freeNext;
    xanim_pool[xanim_pool[0].freeNext].freePrev = handle;
    xanim_poolUsedCount--;
    xanim_pool[0].freeNext = handle;
    runtimeTree->activePoolNodeCount--;
}

float XAnimGetAverageRateFrequency(uint32_t nodeIndex)
{
    XAnimEntry *entry =
        &xanim_currentTree->sourceTree->entries[nodeIndex];

    if (entry->childCount == 0) {
        return coduo_engine_xanim_entry_loaded_record(entry)->frequency;
    }

    float weightSum = 0.0f;
    float frequencySum = 0.0f;

    for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
        int32_t childIndex = entry->payload.parent.firstChildIndex + child;
        uint16_t handle =
            xanim_currentTree->poolNodeHandles[childIndex];

        if (handle != 0) {
            XAnimState *slot =
                &xanim_pool[handle]
                     .states[xanim_activePoolPayloadSlot];
            float noteTrack = slot->currentWeight;

            if (noteTrack != 0.0f) {
                float childFrequency = XAnimGetAverageRateFrequency(childIndex);

                if (childFrequency != 0.0f) {
                    weightSum += noteTrack;
                    frequencySum +=
                        childFrequency * noteTrack * slot->rateScale;
                }
            }
        }
    }

    if (weightSum != 0.0f) {
        return XA_DIV(frequencySum, weightSum);
    }

    return 0.0f;
}

qboolean XAnimUpdateInfoNoWeightClient(uint32_t nodeIndex)
{
    uint16_t handle = xanim_currentTree->poolNodeHandles[nodeIndex];

    if (handle == 0) {
        return qfalse;
    }

    XAnimInfo *node = &xanim_pool[handle];
    XAnimState *slot =
        &node->states[0];

    slot->currentWeight = slot->targetWeight;
    slot->weightBlendTimeRemaining = 0.0f;

    XAnimEntry *entry =
        &xanim_currentTree->sourceTree->entries[nodeIndex];
    if (entry->childCount == 0) {
        if (slot->currentWeight == 0.0f && slot->targetWeight == 0.0f &&
            node->states[1].currentWeight == 0.0f &&
            node->states[1].targetWeight == 0.0f) {
            XAnimFreeInfo(xanim_currentTree, handle);
            xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
            return qfalse;
        }

        return qtrue;
    }

    qboolean hasLiveChild = qfalse;
    for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
        if (XAnimUpdateInfoNoWeightClient(
                entry->payload.parent.firstChildIndex + child)) {
            hasLiveChild = qtrue;
        }
    }

    if (hasLiveChild || slot->currentWeight != 0.0f ||
        slot->targetWeight != 0.0f ||
        node->states[1].currentWeight != 0.0f ||
        node->states[1].targetWeight != 0.0f) {
        return qtrue;
    }

    XAnimFreeInfo(xanim_currentTree, handle);
    xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
    return qfalse;
}

uint16_t XAnimGetNextNotifyTime(XAnimEntry *entry,
                                XAnimInfo *node,
                                float time)
{
    (void)node;

    xanim_notetrack_t *notetrack =
        coduo_engine_xanim_entry_loaded_record(entry)->noteTracks;
    xanim_notetrack_t *best = NULL;
    float bestTime = 2.0f;

    for (xanim_notetrack_t *cursor = notetrack; cursor->nameHandle != 0;
         ++cursor) {
        if (time <= cursor->time && cursor->time < bestTime) {
            best = cursor;
            bestTime = cursor->time;
        }
    }

    if (best == NULL) {
        /*
         * ORIGINAL_BINARY_BUG: VA 0x080bbaa4..0x080bbaaa subtracts the live
         * i386 notetrack address from NULL, arithmetically shifts the target
         * dword by three, and returns its low word.  Reproduce those defined
         * target-width operations without invalid C pointer subtraction.
         */
        uint32_t byteDelta =
            UINT32_C(0) - (uint32_t)(uintptr_t)(const void *)notetrack;
        uint32_t shifted = byteDelta >> 3;

        if ((byteDelta & UINT32_C(0x80000000)) != 0) {
            shifted |= UINT32_C(0xe0000000);
        }
        return (uint16_t)shifted;
    }

    return (uint16_t)(best - notetrack);
}

float XAnimGetNotifyFracLeaf(float notifyTime)
{
    if (xanim_evalWindowTime == 1.0f) {
        return 1.0f;
    }

    if (xanim_evalCurrentTime < xanim_evalWindowTime) {
        if (notifyTime < xanim_evalCurrentTime) {
            return ((notifyTime - xanim_evalStartTime) +
                    (float)((int16_t)xanim_evalWindowFrame -
                            (int16_t)xanim_evalStartFrame + 1)) /
                   xanim_evalTimeStep;
        }

        if (xanim_evalWindowTime <= notifyTime) {
            return ((notifyTime - xanim_evalStartTime) +
                    (float)((int16_t)xanim_evalWindowFrame -
                            (int16_t)xanim_evalStartFrame)) /
                   xanim_evalTimeStep;
        }

        return 1.0f;
    }

    if ((xanim_evalCurrentTime <= notifyTime &&
         xanim_evalCurrentTime != 1.0f) ||
        notifyTime < xanim_evalWindowTime) {
        return 1.0f;
    }

    return ((notifyTime - xanim_evalStartTime) +
            (float)((int16_t)xanim_evalWindowFrame -
                    (int16_t)xanim_evalStartFrame)) /
           xanim_evalTimeStep;
}

float XAnimGetNotifyFracServer(XAnimInfo *node,
                                     XAnimEntry *entry)
{
    float notifyTime;

    if (xanim_evalRootHandle == 0 || node->notifyName == 0) {
        return 1.0f;
    }

    if (entry->childCount != 0) {
        if (node->notifyChildIndex == 0) {
            return XAnimGetNotifyFracLeaf(1.0f);
        }

        entry = &xanim_currentTree->sourceTree->entries[node->notifyChildIndex];
    }

    if (node->notifyIndex < 0) {
        notifyTime = 1.0f;
    } else {
        notifyTime =
            coduo_engine_xanim_entry_loaded_record(entry)->noteTracks[node->notifyIndex]
                .time;
    }

    return XAnimGetNotifyFracLeaf(notifyTime);
}

void XAnimAddClientNotify(XAnimInfo *node,
                          XAnimEntry *entry,
                          uint16_t nameHandle,
                          float timeFrac,
                          uint16_t notifyHandle)
{
    (void)node;
    (void)entry;

    /*
     * ORIGINAL_BINARY_BUG: VA 0x080bbcf6..0x080bbdac never checks the
     * 128-record queue capacity before shifting and inserting.
     */
    int32_t insertIndex = xanim_deferredNotifyCount;

    while (--insertIndex >= 0) {
        if (xanim_deferredNotifies[insertIndex].timeFrac <= timeFrac) {
            break;
        }

        xanim_deferredNotifies[insertIndex + 1] =
            xanim_deferredNotifies[insertIndex];
    }

    insertIndex++;
    xanim_deferredNotifies[insertIndex].name =
        SL_ConvertToString(nameHandle);
    xanim_deferredNotifies[insertIndex].timeFrac = timeFrac;
    xanim_deferredNotifies[insertIndex].notifyHandle = notifyHandle;
    xanim_deferredNotifyCount++;
}

void XAnimSetClientTime(XAnimInfo *node,
                                    XAnimEntry *entry,
                                    uint16_t notifyHandle)
{
    node->states[0].oldTime = xanim_evalStartTime;
    node->states[0].oldCycleCount = xanim_evalStartFrame;
    node->states[0].time = xanim_evalCurrentTime;
    node->states[0].cycleCount =
        xanim_evalCurrentFrame;

    if (notifyHandle == 0 || xanim_evalTimeStep == 0.0f) {
        return;
    }

    xanim_evalWindowTime = xanim_evalStartTime;
    xanim_evalWindowFrame = xanim_evalStartFrame;

    if (xanim_evalStartTime == 1.0f) {
        XAnimAddClientNotify(node, entry, xanim_endNotifyHandle,
                                 XAnimGetNotifyFracLeaf(1.0f), notifyHandle);
        return;
    }

    if (entry->childCount != 0) {
        if (xanim_evalCurrentTime < xanim_evalStartTime ||
            xanim_evalCurrentTime == 1.0f) {
            XAnimAddClientNotify(node, entry, xanim_endNotifyHandle,
                                     XAnimGetNotifyFracLeaf(1.0f),
                                     notifyHandle);
        }

        return;
    }

    XAnimParts *loadedRecord = coduo_engine_xanim_entry_loaded_record(entry);
    xanim_notetrack_t *notify =
        &loadedRecord->noteTracks[XAnimGetNextNotifyTime(
            entry, node, xanim_evalStartTime)];

    if (xanim_evalCurrentTime < xanim_evalStartTime) {
        if (notify->time < xanim_evalCurrentTime) {
            do {
                XAnimAddClientNotify(node, entry, notify->nameHandle,
                                         XAnimGetNotifyFracLeaf(notify->time),
                                         notifyHandle);
                ++notify;
                if (notify->nameHandle == 0) {
                    return;
                }
            } while (notify->time < xanim_evalCurrentTime);
        } else if (!(xanim_evalStartTime > notify->time)) {
            do {
                XAnimAddClientNotify(node, entry, notify->nameHandle,
                                         XAnimGetNotifyFracLeaf(notify->time),
                                         notifyHandle);
                ++notify;
            } while (notify->nameHandle != 0);

            /*
             * ORIGINAL_BINARY_BUG: VA 0x080bc06c advances by 16 bytes even
             * though a notetrack row is eight bytes, skipping alternating
             * rows in the wrapped segment.
             */
            for (notify = loadedRecord->noteTracks;
                 notify->time < xanim_evalCurrentTime; notify += 2) {
                XAnimAddClientNotify(
                    node, entry, notify->nameHandle,
                    XAnimGetNotifyFracLeaf(notify->time), notifyHandle);
            }
        }
    } else if (xanim_evalCurrentTime == 1.0f) {
        if (!(xanim_evalStartTime > notify->time)) {
            do {
                XAnimAddClientNotify(node, entry, notify->nameHandle,
                                         XAnimGetNotifyFracLeaf(notify->time),
                                         notifyHandle);
                ++notify;
            } while (notify->nameHandle != 0);
        }
    } else if (!(notify->time >= xanim_evalCurrentTime) &&
               !(xanim_evalStartTime > notify->time)) {
        do {
            XAnimAddClientNotify(node, entry, notify->nameHandle,
                                     XAnimGetNotifyFracLeaf(notify->time),
                                     notifyHandle);
            ++notify;
            if (notify->nameHandle == 0) {
                return;
            }
        } while (notify->time < xanim_evalCurrentTime);
    }
}

void XAnimUpdateClientInfoSyncInternal(uint32_t nodeIndex, qboolean notify)
{
    uint16_t handle = xanim_currentTree->poolNodeHandles[nodeIndex];

    if (handle == 0) {
        return;
    }

    XAnimInfo *node = &xanim_pool[handle];
    XAnimState *slot =
        &node->states[0];
    qboolean allowNotify = notify;

    if (slot->targetWeight == 0.0f) {
        allowNotify = qfalse;
    }

    if (slot->weightBlendTimeRemaining < xanim_evalTime +
                                             XANIM_BLEND_TIME_EPSILON) {
        slot->currentWeight = slot->targetWeight;
        slot->weightBlendTimeRemaining = 0.0f;
    } else {
        slot->currentWeight +=
            ((slot->targetWeight - slot->currentWeight) * xanim_evalTime) /
            slot->weightBlendTimeRemaining;
        if (slot->currentWeight < XANIM_WEIGHT_EPSILON) {
            slot->currentWeight = slot->targetWeight * 0.001f;
        }
        slot->weightBlendTimeRemaining -= xanim_evalTime;
    }

    XAnimEntry *entry = &xanim_currentTree->sourceTree->entries[nodeIndex];
    XAnimSetClientTime(
        node, entry, allowNotify ? node->notifyType : 0);

    if (entry->childCount == 0) {
        if (slot->currentWeight == 0.0f && slot->targetWeight == 0.0f &&
            node->states[1].currentWeight == 0.0f &&
            node->states[1].targetWeight == 0.0f) {
            XAnimFreeInfo(xanim_currentTree, handle);
            xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
        }
    } else if (slot->currentWeight == 0.0f && slot->targetWeight == 0.0f) {
        qboolean hasLiveChild = qfalse;

        for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
            if (XAnimUpdateInfoNoWeightClient(
                    entry->payload.parent.firstChildIndex + child)) {
                hasLiveChild = qtrue;
            }
        }

        if (!hasLiveChild &&
            node->states[1].currentWeight == 0.0f &&
            node->states[1].targetWeight == 0.0f) {
            XAnimFreeInfo(xanim_currentTree, handle);
            xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
        }
    } else {
        for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
            XAnimUpdateClientInfoSyncInternal(
                entry->payload.parent.firstChildIndex + child, allowNotify);
        }
    }
}

void XAnimUpdateClientInfoInternal(uint32_t nodeIndex, float delta,
                                   qboolean notify)
{
    uint16_t handle = xanim_currentTree->poolNodeHandles[nodeIndex];

    if (handle == 0) {
        return;
    }

    XAnimInfo *node = &xanim_pool[handle];
    XAnimState *slot =
        &node->states[0];
    qboolean allowNotify = notify;

    if (slot->targetWeight == 0.0f) {
        allowNotify = qfalse;
    }

    if (slot->weightBlendTimeRemaining < xanim_evalTime +
                                             XANIM_BLEND_TIME_EPSILON) {
        slot->currentWeight = slot->targetWeight;
        slot->weightBlendTimeRemaining = 0.0f;
    } else {
        slot->currentWeight +=
            ((slot->targetWeight - slot->currentWeight) * xanim_evalTime) /
            slot->weightBlendTimeRemaining;
        if (slot->currentWeight < XANIM_WEIGHT_EPSILON) {
            slot->currentWeight = slot->targetWeight * 0.001f;
        }
        slot->weightBlendTimeRemaining -= xanim_evalTime;
    }

    XAnimEntry *entry = &xanim_currentTree->sourceTree->entries[nodeIndex];

    if (entry->childCount == 0) {
        if (slot->currentWeight == 0.0f && slot->targetWeight == 0.0f) {
            if (node->states[1].currentWeight == 0.0f &&
                node->states[1].targetWeight == 0.0f) {
                XAnimFreeInfo(xanim_currentTree, handle);
                xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
            }
            return;
        }

        XAnimParts *loadedRecord = coduo_engine_xanim_entry_loaded_record(entry);
        xanim_evalTimeStep = (slot->rateScale * loadedRecord->frequency) *
                             delta;
        float currentTime = slot->time + xanim_evalTimeStep;
        uint16_t currentFrame = slot->cycleCount;

        if (1.0f <= currentTime) {
            if (loadedRecord->looped == 0) {
                currentTime = 1.0f;
            } else {
                do {
                    currentTime -= 1.0f;
                    currentFrame++;
                } while (1.0f <= currentTime);
            }
        }

        xanim_evalStartTime = slot->time;
        xanim_evalStartFrame = slot->cycleCount;
        xanim_evalCurrentTime = currentTime;
        xanim_evalCurrentFrame = currentFrame;
        XAnimSetClientTime(
            node, entry, allowNotify ? node->notifyType : 0);
        return;
    }

    if (slot->currentWeight == 0.0f && slot->targetWeight == 0.0f) {
        qboolean hasLiveChild = qfalse;

        for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
            if (XAnimUpdateInfoNoWeightClient(
                    entry->payload.parent.firstChildIndex + child)) {
                hasLiveChild = qtrue;
            }
        }

        if (!hasLiveChild &&
            node->states[1].currentWeight == 0.0f &&
            node->states[1].targetWeight == 0.0f) {
            XAnimFreeInfo(xanim_currentTree, handle);
            xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
        }
    } else if ((entry->payload.parent.flags &
                (CODUO_SCRIPT_ANIM_PROPERTY_LOOPSYNC |
                 CODUO_SCRIPT_ANIM_PROPERTY_NONLOOPSYNC)) == 0) {
        for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
            XAnimUpdateClientInfoInternal(
                entry->payload.parent.firstChildIndex + child,
                delta * slot->rateScale, allowNotify);
        }
    } else {
        xanim_evalTimeStep =
            (XAnimGetAverageRateFrequency(nodeIndex) * slot->rateScale) * delta;
        float currentTime = slot->time + xanim_evalTimeStep;
        uint16_t currentFrame = slot->cycleCount;

        if (1.0f <= currentTime) {
            if ((entry->payload.parent.flags &
                 CODUO_SCRIPT_ANIM_PROPERTY_NONLOOPSYNC) == 0) {
                do {
                    currentTime -= 1.0f;
                    currentFrame++;
                } while (1.0f <= currentTime);
            } else {
                currentTime = 1.0f;
            }
        }

        xanim_evalStartTime = slot->time;
        xanim_evalStartFrame = slot->cycleCount;
        xanim_evalCurrentTime = currentTime;
        xanim_evalCurrentFrame = currentFrame;
        XAnimSetClientTime(
            node, entry, allowNotify ? node->notifyType : 0);

        xanim_evalStartTime = slot->oldTime;
        xanim_evalStartFrame = slot->oldCycleCount;
        xanim_evalCurrentTime = slot->time;
        xanim_evalCurrentFrame = slot->cycleCount;

        for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
            XAnimUpdateClientInfoSyncInternal(
                entry->payload.parent.firstChildIndex + child, allowNotify);
        }
    }
}

void XAnimUpdateOldServerTime(uint32_t nodeIndex)
{
    uint16_t handle = xanim_currentTree->poolNodeHandles[nodeIndex];

    if (handle == 0) {
        return;
    }

    XAnimInfo *node = &xanim_pool[handle];

    node->states[0].time =
        node->states[1].oldTime;
    node->states[0].cycleCount =
        node->states[1].oldCycleCount;
    node->states[0].targetWeight =
        node->states[1].targetWeight;
    node->states[0].rateScale =
        node->states[1].rateScale;
    node->states[0].weightBlendTimeRemaining =
        node->states[1].weightBlendTimeRemaining;
    node->states[0].currentWeight =
        node->states[1].currentWeight;

    XAnimEntry *entry = &xanim_currentTree->sourceTree->entries[nodeIndex];
    for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
        XAnimUpdateOldServerTime(
            entry->payload.parent.firstChildIndex + child);
    }
}

qboolean XAnimUpdateOldServerTimeNoWeight(uint32_t nodeIndex)
{
    uint16_t handle = xanim_currentTree->poolNodeHandles[nodeIndex];

    if (handle == 0) {
        return qfalse;
    }

    XAnimInfo *node = &xanim_pool[handle];
    XAnimState *slot =
        &node->states[1];

    slot->currentWeight = slot->targetWeight;
    slot->weightBlendTimeRemaining = 0.0f;

    XAnimEntry *entry = &xanim_currentTree->sourceTree->entries[nodeIndex];
    if (entry->childCount == 0) {
        if (slot->currentWeight == 0.0f && slot->targetWeight == 0.0f &&
            node->states[0].currentWeight == 0.0f &&
            node->states[0].targetWeight == 0.0f) {
            XAnimFreeInfo(xanim_currentTree, handle);
            xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
            return qfalse;
        }

        return qtrue;
    }

    qboolean hasLiveChild = qfalse;
    for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
        if (XAnimUpdateOldServerTimeNoWeight(
                entry->payload.parent.firstChildIndex + child)) {
            hasLiveChild = qtrue;
        }
    }

    if (hasLiveChild || slot->currentWeight != 0.0f ||
        slot->targetWeight != 0.0f ||
        node->states[0].currentWeight != 0.0f ||
        node->states[0].targetWeight != 0.0f) {
        return qtrue;
    }

    XAnimFreeInfo(xanim_currentTree, handle);
    xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
    return qfalse;
}

void XAnimUpdateServerInfoSyncInternal(uint32_t nodeIndex)
{
    uint16_t handle = xanim_currentTree->poolNodeHandles[nodeIndex];

    if (handle == 0) {
        return;
    }

    XAnimInfo *node = &xanim_pool[handle];
    XAnimState *slot =
        &node->states[1];

    slot->oldTime = slot->time;
    slot->oldCycleCount = slot->cycleCount;

    if (slot->weightBlendTimeRemaining < xanim_evalTime +
                                             XANIM_BLEND_TIME_EPSILON) {
        slot->currentWeight = slot->targetWeight;
        slot->weightBlendTimeRemaining = 0.0f;
    } else {
        slot->currentWeight +=
            ((slot->targetWeight - slot->currentWeight) * xanim_evalTime) /
            slot->weightBlendTimeRemaining;
        if (slot->currentWeight < XANIM_WEIGHT_EPSILON) {
            slot->currentWeight = slot->targetWeight * 0.001f;
        }
        slot->weightBlendTimeRemaining -= xanim_evalTime;
    }

    XAnimEntry *entry = &xanim_currentTree->sourceTree->entries[nodeIndex];
    if (entry->childCount == 0) {
        if (slot->currentWeight == 0.0f && slot->targetWeight == 0.0f &&
            node->states[0].currentWeight == 0.0f &&
            node->states[0].targetWeight == 0.0f) {
            XAnimFreeInfo(xanim_currentTree, handle);
            xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
        }
    } else if (slot->currentWeight == 0.0f && slot->targetWeight == 0.0f) {
        qboolean hasLiveChild = qfalse;

        for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
            if (XAnimUpdateOldServerTimeNoWeight(
                    entry->payload.parent.firstChildIndex + child)) {
                hasLiveChild = qtrue;
            }
        }

        if (!hasLiveChild &&
            node->states[0].currentWeight == 0.0f &&
            node->states[0].targetWeight == 0.0f) {
            XAnimFreeInfo(xanim_currentTree, handle);
            xanim_currentTree->poolNodeHandles[nodeIndex] = 0;
        }
    } else {
        for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
            XAnimUpdateServerInfoSyncInternal(
                entry->payload.parent.firstChildIndex + child);
        }
    }
}

void XAnimClearServerNotify(XAnimInfo *node)
{
    if (node->notifyName != 0) {
        SL_RemoveRefToString(node->notifyName);
        node->notifyName = 0;
    }

    node->notifyIndex = -1;
}

void NotifyServerNotetrack(uint16_t rootHandle,
                     uint16_t notifyHandle,
                     uint16_t nameHandle)
{
    Scr_AddConstString(nameHandle);
    Scr_NotifyId(rootHandle, notifyHandle, 1);
}

float XAnimGetServerNotifyFracSyncTotal(XAnimInfo *node,
                                         XAnimEntry *entry)
{
    float earliest = XAnimGetNotifyFracServer(node, entry);

    for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
        int32_t childIndex = entry->payload.parent.firstChildIndex + child;
        uint16_t handle =
            xanim_currentTree->poolNodeHandles[childIndex];

        if (handle != 0) {
            XAnimInfo *childNode = &xanim_pool[handle];

            if (childNode->states[1].currentWeight !=
                    0.0f &&
                childNode->states[1].targetWeight !=
                    0.0f) {
                float childFrac =
                    XAnimGetServerNotifyFracSyncTotal(
                        childNode,
                        &xanim_currentTree->sourceTree->entries[childIndex]);
                if (childFrac < earliest) {
                    earliest = childFrac;
                }
            }
        }
    }

    return earliest;
}

float XAnimFindServerNoteTrack(uint32_t nodeIndex, float delta)
{
    uint16_t handle = xanim_currentTree->poolNodeHandles[nodeIndex];

    if (handle == 0) {
        return 1.0f;
    }

    XAnimInfo *node = &xanim_pool[handle];
    XAnimState *slot =
        &node->states[1];

    if (slot->currentWeight == 0.0f || slot->targetWeight == 0.0f) {
        return 1.0f;
    }

    XAnimEntry *entry = &xanim_currentTree->sourceTree->entries[nodeIndex];
    if (entry->childCount == 0) {
        XAnimParts *loadedRecord = coduo_engine_xanim_entry_loaded_record(entry);
        float timeStep = (slot->rateScale * loadedRecord->frequency) *
                         delta;

        if (timeStep == 0.0f) {
            return 1.0f;
        }

        float currentTime = slot->oldTime + timeStep;
        uint16_t currentFrame = slot->oldCycleCount;

        if (loadedRecord->looped == 0) {
            if (1.0f <= currentTime) {
                currentTime = 1.0f;
            }
        } else {
            for (; 1.0f <= currentTime; currentTime -= 1.0f) {
                currentFrame++;
            }
        }

        if ((float)((int32_t)(int16_t)currentFrame -
                    (int32_t)(int16_t)slot->cycleCount) <
            slot->time - currentTime) {
            return 1.0f;
        }

        xanim_evalStartTime = slot->oldTime;
        xanim_evalStartFrame = slot->oldCycleCount;
        xanim_evalCurrentTime = currentTime;
        xanim_evalWindowTime = slot->time;
        xanim_evalWindowFrame = slot->cycleCount;
        xanim_evalTimeStep = timeStep;
        return XAnimGetNotifyFracServer(node, entry);
    }

    if ((entry->payload.parent.flags &
         (CODUO_SCRIPT_ANIM_PROPERTY_LOOPSYNC |
          CODUO_SCRIPT_ANIM_PROPERTY_NONLOOPSYNC)) == 0) {
        float childDelta = delta * slot->rateScale;
        if (childDelta == 0.0f) {
            return 1.0f;
        }

        float earliest = 1.0f;
        for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
            float childFrac = XAnimFindServerNoteTrack(
                entry->payload.parent.firstChildIndex + child, childDelta);

            if (childFrac < earliest) {
                earliest = childFrac;
            }
        }

        return earliest;
    }

    float timeStep =
        (XAnimGetAverageRateFrequency(nodeIndex) * slot->rateScale) * delta;
    if (timeStep == 0.0f) {
        return 1.0f;
    }

    float currentTime = slot->oldTime + timeStep;
    uint16_t currentFrame = slot->oldCycleCount;

    if ((entry->payload.parent.flags &
         CODUO_SCRIPT_ANIM_PROPERTY_NONLOOPSYNC) == 0) {
        for (; 1.0f <= currentTime; currentTime -= 1.0f) {
            currentFrame++;
        }
    } else if (1.0f <= currentTime) {
        currentTime = 1.0f;
    }

    if ((float)((int32_t)(int16_t)currentFrame -
                (int32_t)(int16_t)slot->cycleCount) <
        slot->time - currentTime) {
        return 1.0f;
    }

    xanim_evalStartTime = slot->oldTime;
    xanim_evalStartFrame = slot->oldCycleCount;
    xanim_evalCurrentTime = currentTime;
    xanim_evalWindowTime = slot->time;
    xanim_evalWindowFrame = slot->cycleCount;
    xanim_evalTimeStep = timeStep;
    return XAnimGetServerNotifyFracSyncTotal(node, entry);
}

void XAnimProcessServerNotify(XAnimInfo *node,
                                   XAnimEntry *entry)
{
    if (xanim_evalRootHandle == 0 || node->notifyName == 0) {
        return;
    }

    if (xanim_evalStartTime == 1.0f) {
        Scr_AddConstString(xanim_endNotifyHandle);
        Scr_NotifyId(xanim_evalRootHandle, node->notifyName, 1);
        return;
    }

    if (entry->childCount != 0) {
        if (node->notifyChildIndex == 0) {
            if (!(xanim_evalStartTime > xanim_evalCurrentTime ||
                  xanim_evalCurrentTime == 1.0f)) {
                return;
            }

            Scr_AddConstString(xanim_endNotifyHandle);
            Scr_NotifyId(xanim_evalRootHandle, node->notifyName, 1);
            return;
        }

        entry = &xanim_currentTree->sourceTree->entries[node->notifyChildIndex];
    }

    XAnimParts *loadedRecord = coduo_engine_xanim_entry_loaded_record(entry);
    xanim_notetrack_t *notify =
        &loadedRecord->noteTracks[node->notifyIndex];

    if (xanim_evalCurrentTime < xanim_evalStartTime) {
        if (notify->time < xanim_evalCurrentTime) {
            do {
                NotifyServerNotetrack(xanim_evalRootHandle, node->notifyName,
                                notify->nameHandle);
                ++notify;
                if (notify->nameHandle == 0) {
                    break;
                }
            } while (notify->time < xanim_evalCurrentTime);

            node->notifyIndex =
                (int16_t)XAnimGetNextNotifyTime(entry, node,
                                                   xanim_evalCurrentTime);
        } else if (!(xanim_evalStartTime > notify->time)) {
            do {
                NotifyServerNotetrack(xanim_evalRootHandle, node->notifyName,
                                notify->nameHandle);
                ++notify;
            } while (notify->nameHandle != 0);

            for (notify = loadedRecord->noteTracks;
                 notify->time < xanim_evalCurrentTime; ++notify) {
                NotifyServerNotetrack(xanim_evalRootHandle, node->notifyName,
                                notify->nameHandle);
            }

            node->notifyIndex =
                (int16_t)XAnimGetNextNotifyTime(entry, node,
                                                   xanim_evalCurrentTime);
        }
    } else if (xanim_evalCurrentTime == 1.0f) {
        if (!(xanim_evalStartTime > notify->time)) {
            do {
                NotifyServerNotetrack(xanim_evalRootHandle, node->notifyName,
                                notify->nameHandle);
                ++notify;
            } while (notify->nameHandle != 0);
        }
    } else if (!(notify->time >= xanim_evalCurrentTime) &&
               !(xanim_evalStartTime > notify->time)) {
        do {
            NotifyServerNotetrack(xanim_evalRootHandle, node->notifyName,
                            notify->nameHandle);
            ++notify;
            if (notify->nameHandle == 0) {
                break;
            }
        } while (notify->time < xanim_evalCurrentTime);

        node->notifyIndex =
            (int16_t)XAnimGetNextNotifyTime(entry, node,
                                              xanim_evalCurrentTime);
    }
}

void XAnimProcessServerNotify_r(XAnimInfo *node,
                                              XAnimEntry *entry)
{
    XAnimProcessServerNotify(node, entry);

    for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
        int32_t childIndex = entry->payload.parent.firstChildIndex + child;
        uint16_t handle =
            xanim_currentTree->poolNodeHandles[childIndex];

        if (handle != 0) {
            XAnimInfo *childNode = &xanim_pool[handle];

            if (childNode->states[1].currentWeight !=
                    0.0f &&
                childNode->states[1].targetWeight !=
                    0.0f) {
                XAnimProcessServerNotify_r(
                    childNode,
                    &xanim_currentTree->sourceTree->entries[childIndex]);
            }
        }
    }
}

void XAnimStampSecondaryWindowStart(int32_t nodeIndex)
{
    uint16_t handle = xanim_currentTree->poolNodeHandles[nodeIndex];

    if (handle == 0) {
        return;
    }

    XAnimInfo *node = &xanim_pool[handle];
    node->states[1].time = xanim_evalCurrentTime;
    node->states[1].cycleCount =
        xanim_evalCurrentFrame;

    XAnimEntry *entry = &xanim_currentTree->sourceTree->entries[nodeIndex];
    for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
        XAnimStampSecondaryWindowStart(
            entry->payload.parent.firstChildIndex + child);
    }
}

void XAnimUpdateServerInfoInternal(uint32_t nodeIndex, float delta,
                                  qboolean notify)
{
    uint16_t handle = xanim_currentTree->poolNodeHandles[nodeIndex];

    if (handle == 0) {
        return;
    }

    XAnimInfo *node = &xanim_pool[handle];
    XAnimState *slot =
        &node->states[1];
    qboolean allowNotify = notify;

    if (slot->currentWeight == 0.0f) {
        return;
    }

    if (slot->targetWeight == 0.0f) {
        allowNotify = qfalse;
    }

    XAnimEntry *entry = &xanim_currentTree->sourceTree->entries[nodeIndex];
    if (entry->childCount == 0) {
        XAnimParts *loadedRecord = coduo_engine_xanim_entry_loaded_record(entry);
        float currentTime = slot->oldTime +
                            delta * slot->rateScale *
                                loadedRecord->frequency;
        uint16_t currentFrame = slot->oldCycleCount;

        if (loadedRecord->looped == 0) {
            if (1.0f <= currentTime) {
                currentTime = 1.0f;
            } else if (currentTime <= 0.0f) {
                return;
            }
        } else {
            for (; currentTime < 0.0f; currentTime += 1.0f) {
                currentFrame--;
            }
            for (; 1.0f <= currentTime; currentTime -= 1.0f) {
                currentFrame++;
            }
        }

        if (slot->time - currentTime <=
            (float)((int32_t)(int16_t)currentFrame -
                    (int32_t)(int16_t)slot->cycleCount)) {
            if (allowNotify) {
                xanim_evalCurrentTime = currentTime;
                xanim_evalStartTime = slot->time;
                xanim_evalStartFrame = slot->cycleCount;
                XAnimProcessServerNotify(node, entry);
            }

            slot->time = currentTime;
            slot->cycleCount = currentFrame;
        }

        return;
    }

    if ((entry->payload.parent.flags &
         (CODUO_SCRIPT_ANIM_PROPERTY_LOOPSYNC |
          CODUO_SCRIPT_ANIM_PROPERTY_NONLOOPSYNC)) == 0) {
        for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
            XAnimUpdateServerInfoInternal(
                entry->payload.parent.firstChildIndex + child,
                delta * slot->rateScale, allowNotify);
        }
        return;
    }

    /* The binary rounds the step product to float (fstp at 0x80bda80) before
     * adding oldTime; folding it into one expression would skip that
     * rounding. */
    float timeStep =
        (XAnimGetAverageRateFrequency(nodeIndex) * slot->rateScale) * delta;
    float currentTime = slot->oldTime + timeStep;
    uint16_t currentFrame = slot->oldCycleCount;

    if ((entry->payload.parent.flags &
         CODUO_SCRIPT_ANIM_PROPERTY_NONLOOPSYNC) == 0) {
        for (; currentTime < 0.0f; currentTime += 1.0f) {
            currentFrame--;
        }
        for (; 1.0f <= currentTime; currentTime -= 1.0f) {
            currentFrame++;
        }
    } else if (1.0f <= currentTime) {
        currentTime = 1.0f;
    } else if (currentTime <= 0.0f) {
        return;
    }

    if (slot->time - currentTime <=
        (float)((int32_t)(int16_t)currentFrame -
                (int32_t)(int16_t)slot->cycleCount)) {
        xanim_evalCurrentTime = currentTime;
        if (allowNotify) {
            xanim_evalStartTime = slot->time;
            xanim_evalStartFrame = slot->cycleCount;
            XAnimProcessServerNotify_r(node, entry);
        }

        xanim_evalCurrentFrame = currentFrame;
        XAnimStampSecondaryWindowStart(nodeIndex);
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimCalc output merge. */
static void coduo_engine_xanim_normalize_eval_parts(DObjAnimMat *part)
{
    for (int32_t partIndex = 0; partIndex < xanim_evalPartCount;
         ++partIndex, ++part) {
        if (!coduo_engine_xanim_part_bit_is_set((const uint8_t *)xanim_evalSkipBits,
                               partIndex) &&
            part->accumulatedWeight != 0.0f) {
            float scale = XA_DIV(1.0f, part->accumulatedWeight);

            /* *= scale are single muls -> native. */
            part->primaryLane0 *= scale;
            part->primaryLane1 *= scale;
            part->primaryLane2 *= scale;
            part->primaryLane3 *= scale;
            part->secondaryLane0 *= scale;
            part->secondaryLane1 *= scale;
            part->secondaryLane2 *= scale;
        }
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimCalc output merge. */
static void coduo_engine_xanim_merge_normalized_child_parts(DObjAnimMat *out,
                                           DObjAnimMat *child,
                                           float weight)
{
    for (int32_t partIndex = 0; partIndex < xanim_evalPartCount;
         ++partIndex, ++out, ++child) {
        if (coduo_engine_xanim_part_bit_is_set((const uint8_t *)xanim_evalSkipBits,
                              partIndex)) {
            continue;
        }

        float primaryLengthSq =
            XA_SUMSQ4(child->primaryLane0, child->primaryLane1,
                      child->primaryLane2, child->primaryLane3);
        if (primaryLengthSq != 0.0f) {
            float scale = XA_DIV(weight, (float)sqrt((double)primaryLengthSq));

            XA_MADD(out->primaryLane0, child->primaryLane0, scale);
            XA_MADD(out->primaryLane1, child->primaryLane1, scale);
            XA_MADD(out->primaryLane2, child->primaryLane2, scale);
            XA_MADD(out->primaryLane3, child->primaryLane3, scale);
        }

        if (child->accumulatedWeight != 0.0f) {
            float scale = XA_DIV(weight, child->accumulatedWeight);

            out->accumulatedWeight += weight; /* single add -> native */
            XA_MADD(out->secondaryLane0, child->secondaryLane0, scale);
            XA_MADD(out->secondaryLane1, child->secondaryLane1, scale);
            XA_MADD(out->secondaryLane2, child->secondaryLane2, scale);
        }
    }
}

/* NOT_FROM_ORIGINAL_SOURCE: local factoring for XAnimCalc output merge. */
static void coduo_engine_xanim_scale_normalized_parts(DObjAnimMat *part,
                                      float weight)
{
    for (int32_t partIndex = 0; partIndex < xanim_evalPartCount;
         ++partIndex, ++part) {
        if (coduo_engine_xanim_part_bit_is_set((const uint8_t *)xanim_evalSkipBits,
                              partIndex)) {
            continue;
        }

        float primaryLengthSq =
            XA_SUMSQ4(part->primaryLane0, part->primaryLane1,
                      part->primaryLane2, part->primaryLane3);
        if (primaryLengthSq != 0.0f) {
            float scale = XA_DIV(weight, (float)sqrt((double)primaryLengthSq));

            /* *= scale single muls -> native. */
            part->primaryLane0 *= scale;
            part->primaryLane1 *= scale;
            part->primaryLane2 *= scale;
            part->primaryLane3 *= scale;
        }

        if (part->accumulatedWeight != 0.0f) {
            float scale = XA_DIV(weight, part->accumulatedWeight);

            part->accumulatedWeight = weight;
            part->secondaryLane0 *= scale;
            part->secondaryLane1 *= scale;
            part->secondaryLane2 *= scale;
        }
    }
}

void XAnimCalc(uint32_t nodeIndex, float weight,
               DObjAnimMat *part, qboolean clear,
               qboolean normalize)
{
    XAnimEntry *entry = &xanim_currentTree->sourceTree->entries[nodeIndex];

    if (entry->childCount == 0) {
        if (clear) {
            XAnimClearData(part);
        }

        uint8_t *remapTableBytes =
            xanim_currentEvalState->partRemapTableBytes;
        uint8_t *remapGeneration =
            coduo_engine_xanim_part_remap_generation_bytes(
                remapTableBytes, xanim_currentTree->sourceTree->nodeCount);
        uint16_t remapHandle =
            coduo_engine_xanim_part_remap_handle_load(remapTableBytes,
                                                      (size_t)nodeIndex);

        if (remapHandle == 0) {
            remapGeneration[nodeIndex + 1] = remapGeneration[0];
            remapHandle = XAnimSetModel(entry, xanim_evalChildRefs,
                                              xanim_evalChildCount);
            coduo_engine_xanim_part_remap_handle_store(
                remapTableBytes, (size_t)nodeIndex, remapHandle);
        } else if (remapGeneration[nodeIndex + 1] != remapGeneration[0]) {
            XAnimParts *loadedRecord =
                coduo_engine_xanim_entry_loaded_record(entry);
            remapGeneration[nodeIndex + 1] = remapGeneration[0];
            uint32_t remapSize =
                (uint32_t)((int32_t)(int16_t)
                               loadedRecord->partNameHandles[0] +
                           CODUO_XANIM_PART_REMAP_PREFIX_SIZE);

            SL_RemoveRefToStringOfLen(remapHandle, remapSize);
            remapHandle = XAnimSetModel(entry, xanim_evalChildRefs,
                                              xanim_evalChildCount);
            coduo_engine_xanim_part_remap_handle_store(
                remapTableBytes, (size_t)nodeIndex, remapHandle);
        }

        XAnimToXModel *partRemap =
            (XAnimToXModel *)SL_ConvertToString(
                remapHandle);
        uint16_t handle =
            xanim_currentTree->poolNodeHandles[nodeIndex];
        float time =
            xanim_pool[handle]
                .states[xanim_activePoolPayloadSlot]
                .time;
        XAnimCalcData(entry->payload.leafAsset, partRemap, weight,
                                  part, time);
        return;
    }

    int32_t firstActiveChild = -1;
    float firstWeight = 0.0f;

    for (int32_t child = 0; child < (int32_t)entry->childCount; ++child) {
        int32_t childIndex = entry->payload.parent.firstChildIndex + child;
        uint16_t handle =
            xanim_currentTree->poolNodeHandles[childIndex];

        if (handle != 0) {
            float noteTrack =
                xanim_pool[handle]
                    .states[xanim_activePoolPayloadSlot]
                    .currentWeight;

            if (noteTrack != 0.0f) {
                firstActiveChild = child;
                firstWeight = noteTrack;
                break;
            }
        }
    }

    if (firstActiveChild < 0) {
        if (clear) {
            XAnimClearData(part);
        }
        return;
    }

    int32_t secondActiveChild = -1;
    float secondWeight = 0.0f;

    for (int32_t child = firstActiveChild + 1;
         child < (int32_t)entry->childCount; ++child) {
        int32_t childIndex = entry->payload.parent.firstChildIndex + child;
        uint16_t handle =
            xanim_currentTree->poolNodeHandles[childIndex];

        if (handle != 0) {
            float noteTrack =
                xanim_pool[handle]
                    .states[xanim_activePoolPayloadSlot]
                    .currentWeight;

            if (noteTrack != 0.0f) {
                secondActiveChild = child;
                secondWeight = noteTrack;
                break;
            }
        }
    }

    if (secondActiveChild < 0) {
        XAnimCalc(entry->payload.parent.firstChildIndex +
                              firstActiveChild,
                          weight, part, clear, normalize);
        return;
    }

    DObjAnimMat scratch[xanim_evalPartCount];
    DObjAnimMat *blendParts = clear ? part : scratch;

    XAnimCalc(entry->payload.parent.firstChildIndex + firstActiveChild,
                      firstWeight, blendParts, qtrue, qtrue);
    XAnimCalc(entry->payload.parent.firstChildIndex + secondActiveChild,
                      secondWeight, blendParts, qfalse, qtrue);

    for (int32_t child = secondActiveChild + 1;
         child < (int32_t)entry->childCount; ++child) {
        int32_t childIndex = entry->payload.parent.firstChildIndex + child;
        uint16_t handle =
            xanim_currentTree->poolNodeHandles[childIndex];

        if (handle != 0) {
            float noteTrack =
                xanim_pool[handle]
                    .states[xanim_activePoolPayloadSlot]
                    .currentWeight;

            if (noteTrack != 0.0f) {
                XAnimCalc(childIndex, noteTrack, blendParts, qfalse,
                                  qtrue);
            }
        }
    }

    if (!normalize) {
        coduo_engine_xanim_normalize_eval_parts(part);
    } else if (!clear) {
        coduo_engine_xanim_merge_normalized_child_parts(part, blendParts, weight);
    } else {
        coduo_engine_xanim_scale_normalized_parts(part, weight);
    }
}

void DObjCalcAnim(DObj *state,
                         const uint32_t *partBits)
{
    coduo_xanim_eval_storage_t *storage;
    qboolean allEvaluated;

    storage = state->storage;
    allEvaluated = 1;

    for (int32_t wordIndex = 0; wordIndex < CODUO_XANIM_PART_BITSET_WORD_COUNT;
         ++wordIndex) {
        xanim_evalPartBits[wordIndex] =
            ~partBits[wordIndex] | storage->evaluatedPartBits[wordIndex];
        if (xanim_evalPartBits[wordIndex] != UINT32_MAX) {
            allEvaluated = 0;
        }
    }

    if (allEvaluated != 0) {
        return;
    }

    for (int32_t wordIndex = 0; wordIndex < CODUO_XANIM_PART_BITSET_WORD_COUNT;
         ++wordIndex) {
        storage->evaluatedPartBits[wordIndex] |= partBits[wordIndex];
        xanim_evalSkipBits[wordIndex] = xanim_evalPartBits[wordIndex];
    }

    xanim_currentEvalState = state;
    xanim_currentTree = state->runtimeTree;
    xanim_evalChildCount = state->childCount;
    xanim_evalChildRefs = state->childRefs;
    xanim_evalPartCount = state->partCount;

    DObjAnimMat *output =
        &storage->partSpans[state->partCount].evalParts.slots[0];

    if (xanim_currentTree != NULL) {
        xanim_evalPartBytes =
            state->partCount * sizeof(DObjAnimMat);

        ((uint8_t *)xanim_evalSkipBits)[CODUO_XANIM_PART_BITSET_SIZE - 1U] |=
            XANIM_EVAL_SKIP_LAST_PART_BIT;
        XAnimCalc(XANIM_EVAL_TREE_ROOT_NODE,
                          XANIM_EVAL_TREE_FULL_WEIGHT, output,
                          XANIM_EVAL_TREE_CLEAR_OUTPUT,
                          XANIM_EVAL_TREE_NO_NORMALIZE);
    }

    const uint8_t *evalPartBytes = (const uint8_t *)xanim_evalPartBits;
    int32_t globalPart = 0;

    for (int32_t childIndex = 0; childIndex < xanim_evalChildCount;
         ++childIndex) {
        XModel *model = xanim_evalChildRefs[childIndex];
        coduo_xmodel_part_name_payload_view_t modelParts =
            coduo_engine_xanim_model_part_name_payload(model);

        for (int32_t remaining = modelParts.rootPartCount; remaining != 0;
             --remaining) {
            if (!coduo_engine_xanim_part_bit_is_set(evalPartBytes, globalPart)) {
                output->primaryLane0 = 0.0f;
                output->primaryLane1 = 0.0f;
                output->primaryLane2 = 0.0f;
                output->primaryLane3 = 1.0f;
                output->secondaryLane2 = 0.0f;
                output->secondaryLane1 = 0.0f;
                output->secondaryLane0 = 0.0f;
            }

            output++;
            globalPart++;
        }

        xanim_int16_vec4_t *baseRotation = modelParts.baseRotations;
        for (int32_t remaining =
                 modelParts.partNameTable->count - modelParts.rootPartCount;
             remaining != 0; --remaining) {
            if (!coduo_engine_xanim_part_bit_is_set(evalPartBytes, globalPart)) {
                output->primaryLane0 =
                    (float)baseRotation->components[0] *
                    XANIM_PACKED_SHORT_TO_FLOAT_SCALE;
                output->primaryLane1 =
                    (float)baseRotation->components[1] *
                    XANIM_PACKED_SHORT_TO_FLOAT_SCALE;
                output->primaryLane2 =
                    (float)baseRotation->components[2] *
                    XANIM_PACKED_SHORT_TO_FLOAT_SCALE;
                output->primaryLane3 =
                    (float)baseRotation->components[3] *
                    XANIM_PACKED_SHORT_TO_FLOAT_SCALE;
                output->secondaryLane2 = 0.0f;
                output->secondaryLane1 = 0.0f;
                output->secondaryLane0 = 0.0f;
            }

            output++;
            globalPart++;
            baseRotation++;
        }
    }
}

#undef XA_MADD
#undef XA_DIV
#undef XA_SUMSQ4
