From 0b74ded7ba08dda75c798b4c6a1c44e0b222b7a7 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Fri, 1 Nov 2024 19:17:45 -0700 Subject: [PATCH] Match and link CScriptMailbox and strtold --- config/GM8E01_00/symbols.txt | 4 +- configure.py | 4 +- include/Kyoto/Animation/CPoseAsTransforms.hpp | 7 +- include/MetroidPrime/CWorld.hpp | 2 +- libc/float.h | 8 +- libc/limits.h | 2 + libc/locale.h | 1 + libc/math.h | 5 + libc/stdio.h | 2 + .../Player/CPlayerStuckTracker.cpp | 1 + src/Runtime/strtold.c | 547 ++++++++++++++++++ 11 files changed, 574 insertions(+), 9 deletions(-) create mode 100644 src/Runtime/strtold.c diff --git a/config/GM8E01_00/symbols.txt b/config/GM8E01_00/symbols.txt index d948e83d..413a8898 100644 --- a/config/GM8E01_00/symbols.txt +++ b/config/GM8E01_00/symbols.txt @@ -15235,8 +15235,8 @@ GetTransformMinusOffset__17CPoseAsTransformsCFRC6CSegId = .text:0x80368F7C; // t GetRotation__17CPoseAsTransformsCFRC6CSegId = .text:0x80368F9C; // type:function size:0x20 scope:global Insert__17CPoseAsTransformsFRC6CSegIdRC9CMatrix3fRC9CVector3f = .text:0x80368FBC; // type:function size:0x74 scope:global __ct__17CPoseAsTransformsFUc = .text:0x80369030; // type:function size:0x130 scope:global -Insert__58TSegIdMapVariableSizeFRC6CSegIdRCQ217CPoseAsTransforms12CElementType = .text:0x80369160; // type:function size:0xAC scope:global -Clear__58TSegIdMapVariableSizeFv = .text:0x8036920C; // type:function size:0x44 scope:global +Insert__58TSegIdMapVariableSizeFRC6CSegIdRCQ217CPoseAsTransforms12CElementType = .text:0x80369160; // type:function size:0xAC scope:weak +Clear__58TSegIdMapVariableSizeFv = .text:0x8036920C; // type:function size:0x44 scope:weak CreateRumbleHandle__12CRumbleVoiceFUs = .text:0x80369250; // type:function size:0x4C scope:global OwnsSustained__12CRumbleVoiceCFs = .text:0x8036929C; // type:function size:0x38 scope:global GetIntensity__12CRumbleVoiceCFv = .text:0x803692D4; // type:function size:0x4C scope:global diff --git a/configure.py b/configure.py index 5b65d8a7..d125f138 100755 --- a/configure.py +++ b/configure.py @@ -466,7 +466,7 @@ config.libs = [ Object(Matching, "MetroidPrime/Weapons/CPowerBeam.cpp"), Object(NonMatching, "MetroidPrime/Weapons/CWaveBeam.cpp"), Object(NonMatching, "MetroidPrime/Weapons/CIceBeam.cpp"), - Object(NonMatching, "MetroidPrime/CScriptMailbox.cpp"), + Object(Matching, "MetroidPrime/CScriptMailbox.cpp"), Object(Matching, "MetroidPrime/ScriptObjects/CScriptRelay.cpp"), Object(NonMatching, "MetroidPrime/ScriptObjects/CScriptSpawnPoint.cpp"), Object(NonMatching, "MetroidPrime/ScriptObjects/CScriptRandomRelay.cpp"), @@ -1228,7 +1228,7 @@ config.libs = [ Object(Matching, "Runtime/sscanf.c"), Object(Matching, "Runtime/string.c"), Object(Matching, "Runtime/float.c"), - Object(NonMatching, "Runtime/strtold.c"), + Object(Matching, "Runtime/strtold.c"), Object(Matching, "Runtime/uart_console_io.c"), Object(Matching, "Runtime/wchar_io.c"), Object(Matching, "Runtime/e_acos.c"), diff --git a/include/Kyoto/Animation/CPoseAsTransforms.hpp b/include/Kyoto/Animation/CPoseAsTransforms.hpp index 63873ac4..006d799d 100644 --- a/include/Kyoto/Animation/CPoseAsTransforms.hpp +++ b/include/Kyoto/Animation/CPoseAsTransforms.hpp @@ -3,8 +3,7 @@ #include "types.h" -#include "MetroidPrime/TGameTypes.hpp" - +#include "Kyoto/Animation/CSegId.hpp" #include "Kyoto/Math/CTransform4f.hpp" #include "rstl/reserved_vector.hpp" @@ -12,6 +11,10 @@ class CPoseAsTransforms { public: + class CElementType { + + }; + const CMatrix3f& GetRotation(const CSegId& id) const; private: CSegId x0_nextId; diff --git a/include/MetroidPrime/CWorld.hpp b/include/MetroidPrime/CWorld.hpp index 08f2f2ce..8ef2a3e9 100644 --- a/include/MetroidPrime/CWorld.hpp +++ b/include/MetroidPrime/CWorld.hpp @@ -46,7 +46,7 @@ public: explicit CRelay(CInputStream& in); const TEditorId& GetRelayId() const { return x0_relay; } const TEditorId& GetTargetId() const { return x4_target; } - ushort GetMessage() const { return x8_msg; } + const ushort& GetMessage() const { return x8_msg; } bool GetActive() const { return xa_active; } static rstl::vector< CRelay > ReadMemoryRelays(CInputStream& in); // name? diff --git a/libc/float.h b/libc/float.h index f3a4f133..a40466bc 100644 --- a/libc/float.h +++ b/libc/float.h @@ -11,12 +11,16 @@ extern "C" { #define FLT_MIN 1.175494351e-38f #define DBL_DIG 6 -#define DBL_MIN 5.8774717e-39 -#define DBL_MAX (* (double *) __double_max) +#define DBL_MIN (*(double*)__double_min) +#define DBL_MAX (*(double*)__double_max) #define DBL_EPSILON 1.1920929e-07 #define DBL_MANT_DIG 53 +#define LDBL_MAX (*(long double*)__extended_max) +#define LDBL_EPSILON (*(long double*)__extended_epsilon) +#define LDBL_MIN (*(long double*)__extended_min) + #ifdef __cplusplus } #endif diff --git a/libc/limits.h b/libc/limits.h index e4bb3108..c595fda0 100644 --- a/libc/limits.h +++ b/libc/limits.h @@ -13,6 +13,8 @@ #endif #define SHRT_MAX 0x7fff +#define SHRT_MIN (~SHRT_MAX) + #define USHRT_MAX 0xffffU #define INT_MAX 0x7fffffff diff --git a/libc/locale.h b/libc/locale.h index ba79c678..4fbf1a65 100644 --- a/libc/locale.h +++ b/libc/locale.h @@ -32,6 +32,7 @@ struct lconv { char int_n_sign_posn; }; +extern struct lconv __lconv; #ifdef __cplusplus } #endif diff --git a/libc/math.h b/libc/math.h index 8d69b046..9805c2f6 100644 --- a/libc/math.h +++ b/libc/math.h @@ -56,6 +56,10 @@ extern _INT32 __float_huge[]; extern _INT32 __float_nan[]; extern _INT32 __double_huge[]; extern _INT32 __extended_huge[]; +extern _INT32 __extended_min[]; +extern _INT32 __extended_max[]; +extern _INT32 __extended_epsilon[]; +extern _INT32 __double_min[]; extern _INT32 __double_max[]; #define HUGE_VAL (*(double*)__double_huge) @@ -217,6 +221,7 @@ static inline double scalbn(double x, int n) { return ldexp(x, n); } static inline float scalbnf(float x, int n) { return (float)ldexpf(x, n); } double nextafter(double, double); + #ifdef __cplusplus } #endif diff --git a/libc/stdio.h b/libc/stdio.h index d688e162..f6bc8c72 100644 --- a/libc/stdio.h +++ b/libc/stdio.h @@ -128,6 +128,8 @@ size_t fwrite(const void*, size_t memb_size, size_t num_memb, FILE*); int fseek(FILE* file, long offset, int mode); size_t __fwrite(const void*, size_t, size_t, FILE*); +int __StringRead(void* isc, int ch, int Action); + #ifdef __cplusplus } #endif diff --git a/src/MetroidPrime/Player/CPlayerStuckTracker.cpp b/src/MetroidPrime/Player/CPlayerStuckTracker.cpp index 2d8c41b9..f0381696 100644 --- a/src/MetroidPrime/Player/CPlayerStuckTracker.cpp +++ b/src/MetroidPrime/Player/CPlayerStuckTracker.cpp @@ -56,6 +56,7 @@ bool CPlayer::CPlayerStuckTracker::IsPlayerStuck() { max1 = *_getElementBoundsCheck(x148_, 0); CAABox box1(min1, max1); CAABox box(*_getElementBoundsCheck(x148_, 0), *_getElementBoundsCheck(x148_, 0)); + return true; } void CPlayer::CPlayerStuckTracker::ResetStats() { diff --git a/src/Runtime/strtold.c b/src/Runtime/strtold.c new file mode 100644 index 00000000..d673c83e --- /dev/null +++ b/src/Runtime/strtold.c @@ -0,0 +1,547 @@ +#include "ansi_fp.h" +#include +#include +#include +#include +#include +#include +#include + +enum scan_states { + start = 0x0001, + sig_start = 0x0002, + leading_sig_zeroes = 0x0004, + int_digit_loop = 0x0008, + frac_start = 0x0010, + frac_digit_loop = 0x0020, + sig_end = 0x0040, + exp_start = 0x0080, + leading_exp_digit = 0x0100, + leading_exp_zeroes = 0x0200, + exp_digit_loop = 0x0400, + finished = 0x0800, + failure = 0x1000, + nan_state = 0x2000, + infin_state = 0x4000, + hex_state = 0x8000 +}; + +enum hex_scan_states { + not_hex = 0x0000, + hex_start = 0x0001, + hex_leading_sig_zeroes = 0x0002, + hex_int_digit_loop = 0x0004, + hex_frac_digit_loop = 0x0008, + hex_sig_end = 0x0010, + hex_exp_start = 0x0020, + hex_leading_exp_digit = 0x0040, + hex_leading_exp_zeroes = 0x0080, + hex_exp_digit_loop = 0x0100 +}; + +#define MAX_SIG_DIG 20 + +#define FINAL_STATE(scan_state) (scan_state & (finished | failure)) + +#define SUCCESS(scan_state) \ + (scan_state & (leading_sig_zeroes | int_digit_loop | frac_digit_loop | leading_exp_zeroes | \ + exp_digit_loop | finished)) + +#define FETCH() (count++, (*ReadProc)(ReadProcArg, 0, __GetChar)) +#define UNFETCH(c) (*ReadProc)(ReadProcArg, c, __UngetChar) + +long double __strtold(int max_width, int (*ReadProc)(void*, int, int), void* ReadProcArg, + int* chars_scanned, int* overflow) { + int scan_state = start; + int hex_scan_state = not_hex; + int count = 0; + int spaces = 0; + int c; + decimal d = {0, 0, 0, {0, ""}}; + int sig_negative = 0; + int exp_negative = 0; + long exp_value = 0; + int exp_adjust = 0; + long double result; + int sign_detected = 0; + + unsigned char* chptr = (unsigned char*)&result; + unsigned char uch, uch1; + int ui; + int chindex; + int NibbleIndex; + int expsign = 0; + int exp_digits = 0; + int intdigits = 0; + int RadixPointFound = 0; + short exponent = 0; + int dot; + dot = *(unsigned char*)__lconv.decimal_point; + *overflow = 0; + c = FETCH(); + + while (count <= max_width && c != EOF && !FINAL_STATE(scan_state)) { + + switch (scan_state) { + case start: + if (isspace(c)) { + c = FETCH(); + count--; + spaces++; + break; + } + + switch (toupper(c)) { + case '-': + sig_negative = 1; + + case '+': + c = FETCH(); + sign_detected = 1; + break; + + case 'I': + c = FETCH(); + scan_state = infin_state; + break; + + case 'N': + c = FETCH(); + scan_state = nan_state; + break; + + default: + scan_state = sig_start; + break; + } + break; + + case infin_state: { + int i = 1; + char model[] = "INFINITY"; + while ((i < 8) && (toupper(c) == model[i])) { + i++; + c = FETCH(); + } + if ((i == 3) || (i == 8)) { + if (sig_negative) + result = -INFINITY; + else + result = INFINITY; + *chars_scanned = spaces + i + sign_detected; + return (result); + } else + scan_state = failure; + break; + } + + case nan_state: { + int i = 1, j = 0; + char model[] = "NAN("; + char nan_arg[32] = ""; + while ((i < 4) && (toupper(c) == model[i])) { + i++; + c = FETCH(); + } + if ((i == 3) || (i == 4)) { + if (i == 4) { + while ((j < 32) && (isdigit(c) || isalpha(c))) { + nan_arg[j++] = c; + c = FETCH(); + } + if (c != ')') { + scan_state = failure; + break; + } else + j++; + } + nan_arg[j] = '\0'; + + if (sig_negative) + result = -NAN; + else + result = NAN; + *chars_scanned = spaces + i + j + sign_detected; + return (result); + } else + scan_state = failure; + break; + } + + case sig_start: + if (c == dot) { + scan_state = frac_start; + c = FETCH(); + break; + } + if (!isdigit(c)) { + scan_state = failure; + break; + } + if (c == '0') { + c = FETCH(); + if (toupper(c) == 'X') { + scan_state = hex_state; + hex_scan_state = hex_start; + } else + scan_state = leading_sig_zeroes; + break; + } + scan_state = int_digit_loop; + break; + + case leading_sig_zeroes: + + if (c == '0') { + c = FETCH(); + + break; + } + scan_state = int_digit_loop; + break; + + case int_digit_loop: + if (!isdigit(c)) { + if (c == dot) { + scan_state = frac_digit_loop; + c = FETCH(); + } else + scan_state = sig_end; + break; + } + if (d.sig.length < MAX_SIG_DIG) + d.sig.text[d.sig.length++] = c; + else + exp_adjust++; + c = FETCH(); + break; + + case frac_start: + if (!isdigit(c)) { + scan_state = failure; + break; + } + scan_state = frac_digit_loop; + break; + + case frac_digit_loop: + if (!isdigit(c)) { + scan_state = sig_end; + break; + } + if (d.sig.length < MAX_SIG_DIG) + { + if (c != '0' || d.sig.length) + d.sig.text[d.sig.length++] = c; + exp_adjust--; + } + c = FETCH(); + break; + + case sig_end: + if (toupper(c) == 'E') { + scan_state = exp_start; + c = FETCH(); + break; + } + scan_state = finished; + break; + + case exp_start: + if (c == '+') + c = FETCH(); + else if (c == '-') { + c = FETCH(); + exp_negative = 1; + } + scan_state = leading_exp_digit; + break; + + case leading_exp_digit: + if (!isdigit(c)) { + scan_state = failure; + break; + } + if (c == '0') { + scan_state = leading_exp_zeroes; + c = FETCH(); + break; + } + scan_state = exp_digit_loop; + break; + + case leading_exp_zeroes: + if (c == '0') { + c = FETCH(); + break; + } + scan_state = exp_digit_loop; + break; + + case exp_digit_loop: + if (!isdigit(c)) { + scan_state = finished; + break; + } + exp_value = exp_value * 10 + (c - '0'); + if (exp_value > SHRT_MAX) + *overflow = 1; + c = FETCH(); + break; + + case hex_state: { + switch (hex_scan_state) { + case hex_start: + for (chindex = 0; chindex < 8; chindex++) + *(chptr + chindex) = '\0'; + NibbleIndex = 2; + hex_scan_state = hex_leading_sig_zeroes; + c = FETCH(); + break; + + case hex_leading_sig_zeroes: + if (c == '0') { + c = FETCH(); + break; + } + hex_scan_state = hex_int_digit_loop; + + break; + + case hex_int_digit_loop: + if (!isxdigit(c)) { + if (c == dot) { + hex_scan_state = hex_frac_digit_loop; + c = FETCH(); + } else + hex_scan_state = hex_sig_end; + break; + } + if (NibbleIndex < 17) { + intdigits++; + uch = *(chptr + NibbleIndex / 2); + ui = toupper(c); + if (ui >= 'A') + ui = ui - 'A' + 10; + else + ui -= '0'; + uch1 = ui; + if ((NibbleIndex % 2) != 0) + uch |= uch1; + else + uch |= uch1 << 4; + *(chptr + NibbleIndex++ / 2) = uch; + c = FETCH(); + } else + c = FETCH(); + + break; + + case hex_frac_digit_loop: + if (!isxdigit(c)) { + hex_scan_state = hex_sig_end; + break; + } + if (NibbleIndex < 17) { + uch = *(chptr + NibbleIndex / 2); + ui = toupper(c); + if (ui >= 'A') + ui = ui - 'A' + 10; + else + ui -= '0'; + uch1 = ui; + if ((NibbleIndex % 2) != 0) + uch |= uch1; + else + uch |= uch1 << 4; + *(chptr + NibbleIndex++ / 2) = uch; + c = FETCH(); + } else + c = FETCH(); + break; + + case hex_sig_end: + if (toupper(c) == 'P') { + hex_scan_state = hex_exp_start; + exp_digits++; + c = FETCH(); + } else + scan_state = finished; + break; + + case hex_exp_start: + exp_digits++; + if (c == '-') + expsign = 1; + else if (c != '+') { + c = UNFETCH(c); + exp_digits--; + } + hex_scan_state = hex_leading_exp_digit; + c = FETCH(); + break; + + case hex_leading_exp_digit: + + if (!isdigit(c)) { + scan_state = failure; + break; + } + if (c == '0') { + exp_digits++; + hex_scan_state = hex_leading_exp_zeroes; + c = FETCH(); + break; + } + hex_scan_state = hex_exp_digit_loop; + break; + + case hex_exp_digit_loop: + if (!isdigit(c)) { + scan_state = finished; + break; + } + exponent = exponent * 10 + (c - '0'); + if (exp_value > SHRT_MAX) + *overflow = 1; + exp_digits++; + c = FETCH(); + + break; + } + } break; + } + } + + if (!SUCCESS(scan_state)) { + count = 0; + *chars_scanned = 0; + } else { + count--; + *chars_scanned = count + spaces; + } + + UNFETCH(c); + + if (hex_scan_state == not_hex) { + + if (exp_negative) + exp_value = -exp_value; + + { + int n = d.sig.length; + unsigned char* p = &d.sig.text[n]; + + while (n-- && *--p == '0') + exp_adjust++; + + d.sig.length = n + 1; + + if (d.sig.length == 0) + d.sig.text[d.sig.length++] = '0'; + } + + exp_value += exp_adjust; + + if (exp_value < SHRT_MIN || exp_value > SHRT_MAX) + *overflow = 1; + + if (*overflow) { + if (exp_negative) { + return 0.0; + } else { + return sig_negative ? -HUGE_VAL : HUGE_VAL; + } + } + + d.exp = exp_value; + + result = __dec2num(&d); + + if (result != 0.0 && result < LDBL_MIN) { + *overflow = 1; + } else if (result > LDBL_MAX) { + *overflow = 1; + result = HUGE_VAL; + } + + if (sig_negative && SUCCESS(scan_state)) + result = -result; + + return (result); + } else { + unsigned long long * uptr = (unsigned long long *)&result; + + if (result) { + if (expsign) { + exponent = -exponent; + } + while ((*(short*)(&result) & 0x00f0) != 0x0010) { + *uptr >>= 1; + exponent++; + } + exponent += 4 * (intdigits - 1); + *(short*)&result &= 0x000f; + *(short*)(&result) |= ((exponent + 1023) << 4); + + *chars_scanned = spaces + sign_detected + NibbleIndex + 1 + exp_digits; + if (result != 0.0 && result < LDBL_MIN) { + *overflow = 1; + result = 0.0; + } else if (result > LDBL_MAX) { + *overflow = 1; + result = HUGE_VAL; + } + if (sig_negative) { + *(short*)(&result) |= 0x8000; + } + } else { + result = 0.0; + } + return result; + } +} + +long double strtold(const char* nptr, char** endptr) { + long double value, abs_value; + int count, overflow; + + __InStrCtrl isc; + isc.NextChar = (char*)nptr; + isc.NullCharDetected = 0; + + value = __strtold(INT_MAX, &__StringRead, (void*)&isc, &count, &overflow); + + if (endptr) + *endptr = (char*)nptr + count; + + abs_value = fabs(value); + + if (overflow || (value != 0.0 && (abs_value < DBL_MIN || abs_value > DBL_MAX))) + errno = ERANGE; + + return value; +} + +double strtod(const char* str, char** end) { + long double value, abs_value; + int count, overflow; + + __InStrCtrl isc; + isc.NextChar = (char*)str; + isc.NullCharDetected = 0; + + value = __strtold(INT_MAX, &__StringRead, (void*)&isc, &count, &overflow); + + if (end) + *end = (char*)str + count; + + abs_value = fabs(value); + + if (overflow || (value != 0.0 && (abs_value < DBL_MIN || abs_value > DBL_MAX))) + errno = ERANGE; + + return (value); +} + +double atof(const char* str) { return (strtod(str, NULL)); }