Open 213cy opened 7 years ago
// Blizzard MPQ hash
#include <stdio.h>
void prepareCryptTable();
void displayCryptTable();
unsigned long HashString(char *lpszFileName, unsigned long dwHashType);
void displayHash(char *lpszFileName);
unsigned long cryptTable[0x500];
int main () {
int len;
len = sizeof cryptTable;
printf("Length: 0x%04x\n", len/8);
prepareCryptTable();
//displayCryptTable();
displayHash("arr\\units.dat");
//4108764829 0xf4e6c69d arr\units.dat
displayHash("unit\\neutral\\acritter.grp");
//2724227059 0xa26067f3 unit\neutral\acritter.grp
displayHash("udg_OSP");
displayHash("saber碎片:");
return 1;
}
void displayHash(char *lpszFileName)
{
unsigned long r;
r = HashString(lpszFileName, 0);
printf("%u 0x%x %s\n", r, r ,lpszFileName);
}
void displayCryptTable(){
int len;
len = sizeof cryptTable;
printf("Length: %d --- 0x%04x\n", len/8, len/8);
int i,j,k;
for (i = 0; i < 5; i++ ){
k = 0x10*i;
// printf("%#x ", k );
for (j = 1; j < 0x11; j++ ,k++){
//printf("%4d", k );
printf("0x%08x ", cryptTable[k] );
}
printf("\n" );
}
cryptTable[25] = 0;
printf("Length: %d --- 0x%04x\n\n", sizeof cryptTable /8, sizeof cryptTable /8);
}
void prepareCryptTable()
{
unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;
for(index1 = 0; index1 < 0x100; index1++)
{
for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
{
unsigned long temp1, temp2;
seed = (seed * 125 + 3) % 0x2AAAAB;
temp1 = (seed & 0xFFFF) << 0x10;
seed = (seed * 125 + 3) % 0x2AAAAB;
temp2 = (seed & 0xFFFF);
cryptTable[index2] = (temp1 | temp2);
}
}
}
unsigned long HashString(char *lpszFileName, unsigned long dwHashType)
{
unsigned char *key = (unsigned char *)lpszFileName;
unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
int ch;
while(*key != 0)
{
ch = toupper(*key++);
seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
return seed1;
}
//warcraft3 map jass stringhash
#include <stdint.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
namespace detail {
// #define uint32_t unsigned int
#define STRING_TO_LONG(s) (*((s) + 0) + ((*((s) + 1) + ((*((s) + 2) + (*((s) + 3) << 8)) << 8)) << 8))
#define T1(A, B, C) \
(A) = ((C)>>13)^((A)-(B)-(C)); \
(B) = ((A)<< 8)^((B)-(C)-(A)); \
(C) = ((B)>>13)^((C)-(A)-(B)); \
(A) = ((C)>>12)^((A)-(B)-(C)); \
(B) = ((A)<<16)^((B)-(C)-(A)); \
(C) = ((B)>> 5)^((C)-(A)-(B)); \
(A) = ((C)>> 3)^((A)-(B)-(C)); \
(B) = ((A)<<10)^((B)-(C)-(A)); \
(C) = ((B)>>15)^((C)-(A)-(B)); \
#define T2(A, B, C) \
(C) = ((C)^((B)>>15))+(B)+(A); \
(B) = ((B)^((A)<<10))+(A)+(C); \
(A) = ((A)^((C)>> 3))+(C)+(B); \
(C) = ((C)^((B)>> 5))+(B)+(A); \
(B) = ((B)^((A)<<16))+(A)+(C); \
(A) = ((A)^((C)>>12))+(C)+(B); \
(C) = ((C)^((B)>>13))+(B)+(A); \
(B) = ((B)^((A)<< 8))+(A)+(C); \
(A) = ((A)^((C)>>13))+(C)+(B); \
unsigned int string_hash_ex(const char* str, size_t size, uint32_t prev)
{
unsigned char* p = (unsigned char*)str;
size_t len = size;
uint32_t A = 0x9E3779B9;
uint32_t B = 0x9E3779B9;
uint32_t C = prev;
if (len >= 12)
{
size_t step = len / 12;
do
{
A += STRING_TO_LONG(p+0);
B += STRING_TO_LONG(p+4);
C += STRING_TO_LONG(p+8);
T1(A, B, C);
p += 12;
len -= 12;
}
while (--step != 0);
}
C = C + size;
switch (len)
{
case 11: C += p[10]<<24;
case 10: C += p[9]<<16;
case 9: C += p[8]<<8;
case 8: B += p[7]<<24;
case 7: B += p[6]<<16;
case 6: B += p[5]<<8;
case 5: B += p[4];
case 4: A += p[3]<<24;
case 3: A += p[2]<<16;
case 2: A += p[1]<<8;
case 1: A += p[0];
break;
default:
break;
}
T1(A, B, C);
return C;
}
#undef T1
#undef T2
#undef STRING_TO_LONG
uint32_t string_hash(const char* str)
{
char buffer[0x400];
size_t len = 0;
while (str[len] != '\0')
{
if (len >= 0x3FF) break;
if ('a' <= str[len] && str[len] <= 'z')
buffer[len] = str[len] - 'a' + 'A';
else if (str[len] == '/')
buffer[len] = '\\';
else
buffer[len] = str[len];
len++;
}
return string_hash_ex(buffer, len, 0);
}
void display_hash(const char* str)
{
int32_t hashValue = string_hash( str );
cout.width(10);
cout << dec ;
cout << (unsigned int) hashValue << " 0x";
cout.width(8);
cout.fill('0');
cout << hex;
// cout << showbase;
cout << hashValue << " ";
cout << str << endl;
}
}
int main() {
detail::display_hash("udg_OSP");
//2007669754 0x77aa9bfa
detail::display_hash("Trig_____________uActions");
//1443748040 0x560dd8c8
detail::display_hash("MOVE");
detail::display_hash("aaaabbbbccccdez");
detail::display_hash("aaaabbbbccccfgz");
cout.width(10);
cout << dec ;
cout << (unsigned int) -1 << " 0x";
cout.width(8);
cout.fill('0');
cout << hex;
// cout << showbase;
cout << 123 << " ";
cout << "456" << endl;
return 0;
}
2楼是 用 C 实现的 MPQ's hash table
https://sfsrealm.hopto.org/inside_mopaq/chapter2.htm 3楼是 用 C++ 实现的 native StringHash takes string s returns integer
https://github.com/actboy168/YDWE/blob/master/Development/Core/ydwar3/warcraft3/detail/string_hash.cpp