// Port helper (no game counterpart): float -> integer conversions exactly as gcc 4.0 codes them for i386 with SSE // in the game's objects, where a plain C++ cast on the 64-bit host can give a different result outside the // target type's range. #ifndef GAME_SSECONV_H #define GAME_SSECONV_H #include // (uint32_t)double: minsd/maxsd clamp to [0, 4294967295] (a NaN takes the upper bound), 2^31 subtracted when the // unclamped value is >= 2^31 (cmplesd mask), cvttpd2dq, bit 31 restored. Constants in the game's __const, e.g. // @0x00192700 = {2147483648.0, 0.0, 4294967295.0, 0.0}. So < 0 -> 0, > 4294967295 -> 0xFFFFFFFF, NaN -> 0x80000000 // (cvttpd2dq of 4294967295.0 is the integer indefinite). inline uint32_t SseDoubleToUInt32(double d) { bool big = (2147483648.0 <= d); // cmplesd double x = d; if (!(x < 4294967295.0)) x = 4294967295.0; // minsd x, 4294967295.0 if (!(x > 0.0)) x = 0.0; // maxsd x, 0.0 if (big) x -= 2147483648.0; // subsd (mask & 2^31) int32_t t = (x > -2147483649.0 && x < 2147483648.0) ? (int32_t)x : (int32_t)0x80000000u; // cvttpd2dq return (uint32_t)t ^ (big ? 0x80000000u : 0u); } // (int32_t)double / (int32_t)float: cvttsd2si / cvttss2si; out of range and NaN give the integer indefinite. inline int32_t SseDoubleToInt32(double d) { return (d > -2147483649.0 && d < 2147483648.0) ? (int32_t)d : (int32_t)0x80000000u; } #endif