Friday, March 25, 2022

 #include <iostream>

#include <cmath>


// fixed point, 16.16, signed (sign bit in the whole part), fraction always positive

struct FixedPoint {

    FixedPoint() {}

    FixedPoint(const FixedPoint& other) : m_value(other.m_value) {}

    constexpr FixedPoint(int value, bool raw = false) : m_value(raw ? value : value << 16) {}

    constexpr FixedPoint(unsigned value) : m_value(value) {}

    constexpr FixedPoint(int whole, int fraction) : m_value((whole << 16) | fraction) {}

    

    static FixedPoint fromFloat(float value) {

        float whole, fraction = std::modf(value, &whole);

        if (value >= 0)

            return FixedPoint(static_cast<int>(whole), static_cast<int>(fraction * 0xffff));

        else

            return FixedPoint(static_cast<int>(whole - 1), static_cast<int>((1 - fabs(fraction)) * 0xffff));

    }

    

    float asFloat() const {

        return *this;

    }

    

    FixedPoint& operator=(const FixedPoint& other) {

        m_value = other.m_value;

        return *this;

    }

    FixedPoint& operator=(int value) {

        m_value = value << 16;

        return *this;

    }

    void set(int whole, int fraction) {

        m_value = (whole << 16) | fraction;

    }

    int32_t raw() const {

        return m_value;

    }

    void setRaw(int32_t value) {

        m_value = value;

    }

    int16_t whole() const {

        return m_value >> 16;

    }

    uint16_t fraction() const {

        return m_value & 0xffff;

    }

    int rounded() const {

        return whole() + (fraction() > 0x8000);

    }

    int truncated() const {

        return whole() + (sgn() < 0 && fraction());

    }

    int sgn() const {

        return m_value < 0 ? -1 : 1;

    }

    operator float() const {

        return static_cast<float>(m_value & 0xffff) / 0x10000 + (m_value >> 16);

    }

    explicit operator bool() const {

        return m_value != 0;

    }

    bool operator<(const FixedPoint& other) const {

        return m_value < other.m_value;

    }

    bool operator<(int value) const {

        return whole() < value;

    }

    bool operator<=(int value) const {

        return !operator>(value);

    }

    bool operator>(const FixedPoint& other) const {

        return m_value > other.m_value;

    }

    bool operator>(int value) const {

        return whole() > value || whole() == value && fraction();

    }

    bool operator>(int16_t value) const {

        return operator>(static_cast<int>(value));

    }

    bool operator>=(int value) const {

        return whole() >= value;

    }

    FixedPoint operator+(const FixedPoint& other) const {

        return FixedPoint(m_value + other.m_value, true);

    }

    FixedPoint operator+(int value) const {

        return FixedPoint(m_value + (value << 16), true);

    }

    FixedPoint operator-() const {

        return FixedPoint(-m_value, true);

    }

    FixedPoint operator-(const FixedPoint& other) const {

        return FixedPoint(m_value - other.m_value, true);

    }

    FixedPoint operator-(int value) const {

        return FixedPoint(m_value - (value << 16), true);

    }

    FixedPoint operator/(int value) const {

        return FixedPoint(m_value / value, true);

    }

    FixedPoint& operator+=(int value) {

        m_value += value << 16;

        return *this;

    }

    FixedPoint& operator+=(const FixedPoint& other) {

        m_value += other.m_value;

        return *this;

    }

    FixedPoint& operator-=(int value) {

        m_value -= (value << 16);

        return *this;

    }

    FixedPoint& operator-=(const FixedPoint& other) {

        m_value -= other.m_value;

        return *this;

    }

    FixedPoint& operator>>=(int count) {

        m_value >>= count;

        return *this;

    }


private:

    int32_t m_value;

};


static inline FixedPoint operator+(int value, const FixedPoint& fixed)

{

    return FixedPoint(value) + fixed;

}

static inline FixedPoint operator-(int value, const FixedPoint& fixed)

{

    return FixedPoint(value) - fixed;

}


FixedPoint setFixedPoint(int32_t baseRaw, int style)

{

    float fBase;

    FixedPoint fixed;

    

    fBase = FixedPoint(baseRaw, true).asFloat();    

    if (style == 0 || style == 1)

        return fixed.fromFloat(fBase * 1.0);

    else

        return fixed.fromFloat(fBase * 50.0 / 60.0);    

}


int main(int argc, char** argv) 

{

    int r;

    float f;

    FixedPoint fixed;

    

    //

    /*

    f = -2.625;    

    fixed = fixed.fromFloat(f);

    printf("%5.3f\n", fixed.asFloat());

    */

    

    fixed = FixedPoint(0x14000, true);  // ballKickingDeltaZ

    printf("%5.3f\n", fixed.asFloat());


    fixed = FixedPoint(0x0A000, true);  // ballKickingDeltaZ_2

    printf("%5.3f\n", fixed.asFloat());

    

    fixed = FixedPoint(0x16000, true);  // normalKickDeltaZ

    printf("%5.3f\n", fixed.asFloat());


    fixed = FixedPoint(0x20000, true);  // highKickDeltaZ

    printf("%5.3f\n", fixed.asFloat());


    fixed = FixedPoint(0x0C000, true);  // dseg_110601

    printf("%5.3f\n", fixed.asFloat());


    fixed = FixedPoint(0x20000, true);  // dseg_17E23C

    printf("%5.3f\n", fixed.asFloat());


    fixed = FixedPoint(0x24000, true);  // kPlayerStaticHeaderJumpHeight

    printf("%5.3f\n", fixed.asFloat());


    printf("\n");


    fixed = fixed.fromFloat(1.250);     // ballKickingDeltaZ

    printf("%08X\n", fixed.raw());


    fixed = fixed.fromFloat(0.625);     // ballKickingDeltaZ_2

    printf("%08X\n", fixed.raw());

    

    fixed = fixed.fromFloat(1.375);     // normalKickDeltaZ

    printf("%08X\n", fixed.raw());


    fixed = fixed.fromFloat(2.000);     // highKickDeltaZ

    printf("%08X\n", fixed.raw());

    

    fixed = fixed.fromFloat(0.750);     // dseg_110601

    printf("%08X\n", fixed.raw());


    fixed = fixed.fromFloat(2.000);     // dseg_17E23C

    printf("%08X\n", fixed.raw());


    fixed = fixed.fromFloat(2.250);     // kPlayerStaticHeaderJumpHeight

    printf("%08X\n", fixed.raw());


    printf("\n");


    //

    FixedPoint ballKickingDeltaZ, ballKickingDeltaZ_2, normalKickDeltaZ, highKickDeltaZ;


    ballKickingDeltaZ = setFixedPoint(0x14000, 2);

    printf("ballKickingDeltaZ.asFloat() = %5.3f\n", ballKickingDeltaZ.asFloat());


    return 0;

}