From ef338fea756ee3b9c5172c8a58e95042cf5d7713 Mon Sep 17 00:00:00 2001 From: Connor Date: Mon, 15 May 2017 18:45:05 -0700 Subject: [PATCH 1/2] --- wc3hash.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 wc3hash.c diff --git a/wc3hash.c b/wc3hash.c new file mode 100644 index 0000000..5db4d00 --- /dev/null +++ b/wc3hash.c @@ -0,0 +1,90 @@ +#ifdef _WIN64 +#define FMT64 "%016I64X" +#else +#ifdef __unix +#define FMT64 "%016lX" +#else +#define FMT64 "%016llX" +#endif +#endif + +#include +#include +#include +#include + +typedef uint8_t u8; +typedef uint32_t u32; +typedef uint64_t u64; + +const u64 table[16] = { + // magic numbers for each possible value of a nybble. + 0x486E26EEDCAA16B3, 0xE1918EEF202DAFDB, + 0x341C7DC71C365303, 0x40EF2D3765FD5E49, + 0xD6057177904ECE93, 0x1C38024F98FD323B, + 0xE3061AE7A39B0FA1, 0x9797F25FE4444563, + 0xCD2EC20C8DC1B898, 0x31759633799A306D, + 0x8C2063852E6E9627, 0x79237D9973922C66, + 0x8728628D28628824, 0x8F1F7E9625887795, + 0x296E3281389C0D60, 0x6F4893CA61636542 +}; + +u64 wc3hash(const char *key, size_t len, u64 hash, bool isPath) { + // technically there doesn't seem to be a + // length argument in the original function, + // I'm just adding it so you can hash strings with '\0' in them. + + if (key == NULL) + return 0; + + if (hash == 0) + hash = 0x7FED7FED7FED7FED; + + u64 state = 0xEEEEEEEEEEEEEEEE; + + for (size_t i = 0; i < len; i++) { + u8 v; + if (isPath) { + char c = key[i]; + if (c >= 'a' && c <= 'z') + c -= 'a' - 'A'; // uppercase + if (c == '/') + c = '\\'; // DOS-style paths + + v = (u8)c; + } else { + v = (u8)key[i]; + } + + hash += state; + hash ^= table[v >> 4] + table[v & 0xF]; + state += state << 5; + state += hash + v + 3; + } + + if (hash == 0) + return 1; + + return hash; +} + +u64 wc3hashC(const char *key) { + // simple interface that only takes a null-terminated string. + return wc3hash(key, strlen(key), 0, true); +} + +int main(int argc, char **argv) { + if (argc == 1) { + const char str[] = "IseeDeadPeople"; + u64 hash = wc3hashC(str); + fprintf(stderr, FMT64 " should equal 701EA16D47F385FC\n", hash); + return hash != 0x701EA16D47F385FC; + } + + for (int i = 1; i < argc; i++) { + u64 hash = wc3hashC(argv[i]); + u32 hash32 = (hash >> 32) ^ hash; + printf(FMT64 "\t%08X\n", hash, hash32); + } + return 0; +} From 309749f0db010a9a5b3405a8ac9371886c727df3 Mon Sep 17 00:00:00 2001 From: Connor Date: Tue, 16 May 2017 21:02:45 -0700 Subject: [PATCH 2/2] --- wc3hash.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/wc3hash.c b/wc3hash.c index 5db4d00..163e89e 100644 --- a/wc3hash.c +++ b/wc3hash.c @@ -1,17 +1,8 @@ -#ifdef _WIN64 -#define FMT64 "%016I64X" -#else -#ifdef __unix -#define FMT64 "%016lX" -#else -#define FMT64 "%016llX" -#endif -#endif - #include #include #include #include +#include typedef uint8_t u8; typedef uint32_t u32; @@ -77,14 +68,14 @@ int main(int argc, char **argv) { if (argc == 1) { const char str[] = "IseeDeadPeople"; u64 hash = wc3hashC(str); - fprintf(stderr, FMT64 " should equal 701EA16D47F385FC\n", hash); + fprintf(stderr, "%" PRIX64 " should equal 701EA16D47F385FC\n", hash); return hash != 0x701EA16D47F385FC; } for (int i = 1; i < argc; i++) { u64 hash = wc3hashC(argv[i]); u32 hash32 = (hash >> 32) ^ hash; - printf(FMT64 "\t%08X\n", hash, hash32); + printf("%" PRIX64 "\t%08X\n", hash, hash32); } return 0; }