From ab47f1f5f616313f58c705eef6c87a14a72e22f5 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 16 Feb 2025 09:15:13 +1100 Subject: [PATCH] GBA: Fix missing sqrt function --- misc/32x/main_32x.c | 26 --------------- src/ExtMath.c | 22 +++---------- third_party/fix16_sqrt.c | 70 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 44 deletions(-) delete mode 100644 misc/32x/main_32x.c create mode 100644 third_party/fix16_sqrt.c diff --git a/misc/32x/main_32x.c b/misc/32x/main_32x.c deleted file mode 100644 index d05c505de..000000000 --- a/misc/32x/main_32x.c +++ /dev/null @@ -1,26 +0,0 @@ -#include - -int32_t fix16_sqrt(int32_t value) -{ - uint32_t t; - uint32_t r = value; - uint32_t b = 0x40000000; - uint32_t q = 0; - - while (b > 0x40) { - t = q + b; - - if (r >= t) { - r -= t; - q = t + b; /* Equivalent to q += 2 * b */ - } - - r <<= 1; - b >>= 1; - } - - q >>= 8; - - return q; -} - diff --git a/src/ExtMath.c b/src/ExtMath.c index 7be151ed9..58626063a 100644 --- a/src/ExtMath.c +++ b/src/ExtMath.c @@ -81,27 +81,13 @@ static int abs(int x) { return x < 0 ? -x : x; } #include #endif -/* Sega 32x is missing these intrinsics */ -#if defined CC_BUILD_32X -#include -extern int32_t fix16_sqrt(int32_t value); +/* 32x/Saturn/GBA is missing these intrinsics */ +#if defined CC_BUILD_32X || defined CC_BUILD_SATURN || defined CC_BUILD_GBA +#include "../third_party/fix16_sqrt.c" float sqrtf(float x) { int32_t fp_x = (int32_t)(x * (1 << 16)); - fp_x = fix16_sqrt(fp_x); - return (float)fp_x / (1 << 16); -} -#endif - - -/* Sega saturn is missing these intrinsics */ -#if defined CC_BUILD_SATURN -#include -extern int32_t fix16_sqrt(int32_t value); - -float sqrtf(float x) { - int32_t fp_x = (int32_t)(x * (1 << 16)); - fp_x = fix16_sqrt(fp_x); + fp_x = sqrt_fix16(fp_x); return (float)fp_x / (1 << 16); } #endif diff --git a/third_party/fix16_sqrt.c b/third_party/fix16_sqrt.c new file mode 100644 index 000000000..3d475d9a7 --- /dev/null +++ b/third_party/fix16_sqrt.c @@ -0,0 +1,70 @@ +#include +/*- + * Copyright (c) 2019 Christophe Meessen + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ + +/*- + * Computing the square root of an integer or a fixed point integer into a fixed + * point integer. A fixed point is a 32 bit value with the comma between the + * bits 15 and 16, where bit 0 is the less significant bit of the value. + * + * The algorithm uses the property that computing x² is trivial compared to the + * sqrt. It will thus search the biggest x so that x² <= v, assuming we compute + * sqrt(v). + * + * The algorithm tests each bit of x starting with the most significant toward + * the less significant. It tests if the bit must be set or not. + * + * The algorithm uses the relation (x + a)² = x² + 2ax + a² to add the bit + * efficiently. Instead of computing x² it keeps track of (x + a)² - x². + * + * When computing sqrt(v), r = v - x², q = 2ax, b = a² and t = 2ax + a2. + * + * Note that the input integers are signed and that the sign bit is used in the + * computation. To accept unsigned integer as input, unfolding the initial loop + * is required to handle this particular case. See the usenet discussion for the + * proposed solution. + * + * Algorithm and code Author Christophe Meessen 1993. */ + +static int32_t sqrt_fix16(int32_t value) +{ + uint32_t t; + uint32_t r = value; + uint32_t b = 0x40000000; + uint32_t q = 0; + + while (b > 0x40) { + t = q + b; + + if (r >= t) { + r -= t; + q = t + b; /* Equivalent to q += 2 * b */ + } + + r <<= 1; + b >>= 1; + } + + q >>= 8; + + return q; +} +