#include "game_types.h"

/* Math_FixedDiv @ 0x0801550C (real 196B) -- signed fixed-point divide with ror-bit loop. Mirrors src/matched/Math_FixedDiv.c. */
/* Truncating remainder with the sign of a (b is forced positive): nibble
   then bit normalize from 1<<28, unrolled subtract quartet with ror-placed
   fractional bits, Lfin rounding tail adding back y>>3/>>2/>>1 slices. Zero
   divisor calls the allocator stub and yields 0. Pairs with Math_Log2
   (quotient) in Printf_FormatInt, which uses this as the digit (remainder).
   ror32 rotates right (the fractional-bit placement idiom). */
extern void Mem_Alloc(void);

static unsigned ror32(unsigned v, unsigned n)
{
    n &= 31;
    return n == 0 ? v : (v >> n) | (v << (32 - n));
}

int Math_FixedDiv(int a, int b)
{
    unsigned x, y, q = 0;
    unsigned bit = 1, scale;
    int neg;
    if (b == 0) {
        Mem_Alloc();
        return 0;
    }
    neg = a < 0;
    x = neg ? -(unsigned)a : (unsigned)a;
    y = b < 0 ? -(unsigned)b : (unsigned)b;
    if (x < y)
        return 0;
    scale = 1u << 28;
    while (y < scale && y < x) {
        y <<= 4;
        bit <<= 4;
    }
    scale <<= 3;
    while (y < scale && y < x) {
        y <<= 1;
        bit <<= 1;
    }
    for (;;) {
        if (x >= y)
            x -= y; /* implicit leading bit, unrecorded */
        if (x >= (y >> 1)) {
            x -= y >> 1;
            q |= ror32(bit, 1);
        }
        if (x >= (y >> 2)) {
            x -= y >> 2;
            q |= ror32(bit, 2);
        }
        if (x >= (y >> 3)) {
            x -= y >> 3;
            q |= ror32(bit, 3);
        }
        if (x == 0 || (bit >>= 4) == 0)
            break;
        y >>= 4;
    }
    if ((q & 0xE0000000u) != 0) {
        if ((q & ror32(bit, 3)) != 0)
            x += y >> 3;
        if ((q & ror32(bit, 2)) != 0)
            x += y >> 2;
        if ((q & ror32(bit, 1)) != 0)
            x += y >> 1;
    }
    return neg ? -(int)x : (int)x;
}
