#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;
}