SARC: Difference between revisions

729 bytes added ,  3 years ago
m
imported>Leoetlino
 
(8 intermediate revisions by 2 users not shown)
Line 5: Line 5:


=== Hash algorithm ===
=== Hash algorithm ===
The algorithm given on the MK8 wiki is not fully correct: it fails to account for the fact that Nintendo's algorithm uses an unsigned 32-bit integer for the hash variable, and a '''''signed'' char variable'''.
Nintendo's algorithm uses an unsigned 32-bit integer for the hash variable. Also note that Nintendo iterates over each byte, not each string character.


Here is more accurate implementation of the algorithm, written in C++:
Here is an accurate implementation of the algorithm, written in C++:


<source lang="c++">
<source lang="c++">
  const uint32_t multiplier = 0x65;
// key is equal to 0x65
  const char* string = "月クッパ戦Lv3(クリア後).baglshpp";
u32 calcHash32(const sead::SafeString& str, u32 key)
  uint32_t hash = 0;
{
  int i = 0;
    const char* str_ = str.cstr();
  while (true) {
 
     char c = string[i++]; // *signed* char
    u32 result = 0;
    if (!c)
    // Each character must be treated as a signed value.
      break;
    // The cast to s8 (not s32) is necessary to avoid unsigned conversions.
     hash = hash * multiplier + c;
     for (s32 i = 0; str_[i] != '\0'; i++)
  }
        result = result * key + s8(str_[i]);
 
     return result;
}
</source>
</source>


It appears that Nintendo's compiler treats a char as a signed type.
Note that in older versions of sead, characters were not explicitly casted to <code>s8</code> so the end result would depend on the signedness of <code>char</code> (which is implementation-defined). For GHS compiled code on the Wii U, <code>char</code> is unsigned whereas it's signed with Clang (AArch64 target). PC tools most likely use a signed <code>char</code> as that is the default signedness for x86 targets.
 
In newer versions of sead, an explicit cast to <code>signed char</code>, aka <code>std::int8_t</code>, aka <code>s8</code>, was added to ensure hashes are the same regardless of the target platform. Without the cast, non-ASCII characters (e.g. Japanese UTF-8 bytes) would result in hashes being different across platforms.


== Usage in ''Breath of the Wild'' ==
== Usage in ''Breath of the Wild'' ==