Here is a fix for the ANI_FORMAT_ERROR for the Metin1 client.
You need to compile local.dll from this source code and then copy the resulting file, replacing the existing one in the client.
[Hidden Content]
Please test the fix and provide feedback
----
P.S Alternatively, you have at least two more options.
The client has 3 name search modes:
1. As is (used by default)
2. conv_name.dat (mapping)
3. crc (in this case, file search will be performed using the path pack/crc<hex_hash>)
char *__cdecl sub_49ABA0(char *FileName)
{
char *v1; // ecx
bool v2; // sf
char v3; // al
int v5; // eax
FILE *v6; // eax
FILE *v7; // edi
int v8; // eax
_DWORD v9[2]; // [esp+4h] [ebp-10h] BYREF
_BYTE v10[8]; // [esp+Ch] [ebp-8h] BYREF
if ( byte_509C08 && !_access(FileName, 4) )
return FileName;
v1 = FileName;
v2 = *FileName < 0;
if ( !*FileName )
return FileName;
while ( !v2 )
{
v3 = *++v1;
v2 = v3 < 0;
if ( !v3 )
return FileName;
}
if ( !dword_509C0C )
return FileName;
if ( dword_509C0C != 1 )
{
if ( dword_509C0C != 2 )
return (char *)&byte_4EB13F;
v5 = sub_49B970(FileName, strlen(FileName));
sprintf(byte_509C38, "pack/crc%x", v5);
return byte_509C38;
}
if ( byte_4FA67D )
{
byte_4FA67D = 0;
sub_49AA20("conv_name.dat");
}
if ( !dword_509C2C || !(unsigned __int8)sub_49A8E0(FileName) )
return FileName;
v9[0] = sub_49A880(FileName);
sub_42E0D0(v10, v9);
v9[1] = dword_509C28;
v9[0] = dword_509C10;
if ( (unsigned __int8)sub_42E190(v10) )
{
v6 = (FILE *)sub_4857F5("error_file_name.txt", "w");
v7 = v6;
if ( v6 )
{
fprintf(v6, "NOT_FOUND: [%s]", FileName);
fclose(v7);
}
return FileName;
}
else
{
v8 = sub_42E160(v10) + 4;
if ( *(_DWORD *)(v8 + 24) < 0x10u )
return (char *)(v8 + 4);
else
return *(char **)(v8 + 4);
}
}
Diff to activate mode 2:
This difference file is created by IDA Pro
mts.exe
0002D161: 33 6A
0002D162: F6 01
0002D163: 56 90
You can probably use an even better option - conv_name.dat
This file, as I understand it, allows you to map Chinese names to your names, for example, English ones.
XOR Key for conv_name.dat (0x4DF194)
21 BE C6 25 C7 D8 23 BE DF 31 BB E7 B7 A1 B1 E4
26 23 24 23 B9 E7 C0 BB BE F0 C1 A6 33 39 32 34
38 B0 A5 B7 C1 C7 CF B3 C4 B4 A2 3F
You will need to implement reading and writing functionality for your utility.
Here is pseudocode showing how the data is decrypted using XOR.
char __cdecl sub_49AA20(char *Source)
{
char v1; // bl
FILE *v2; // eax
FILE *v3; // ebp
unsigned int v5; // esi
_DWORD *v6; // edi
signed int v7; // kr00_4
int v8; // ecx
int v9; // edx
int v10; // ebx
int v11; // esi
size_t v12; // ebp
int v13; // esi
size_t v14; // esi
size_t v15; // ebp
FILE *v16; // [esp+8h] [ebp-214h]
char v17[260]; // [esp+10h] [ebp-20Ch] BYREF
char v18[260]; // [esp+114h] [ebp-108h] BYREF
v1 = 0;
v2 = (FILE *)sub_4857F5(Source, "rb");
v3 = v2;
v16 = v2;
if ( !v2 )
return 0;
fseek(v2, 0, 2);
v5 = ftell(v3);
fseek(v3, 0, 0);
v6 = operator new[](v5);
fread(v6, v5, 1u, v3);
v7 = strlen(byte_4DF194);
v8 = 0;
if ( v5 )
{
do
{
v9 = v8 % v7;
*((_BYTE *)v6 + v8++) ^= byte_4DF194[v9];
}
while ( v8 != v5 );
}
if ( *v6 == 1919251557 )
{
v10 = v6[1];
v11 = 8;
if ( v10 )
{
do
{
v12 = *((unsigned __int8 *)v6 + v11);
v13 = v11 + 1;
memcpy(v18, (char *)v6 + v13, v12);
v14 = v12 + v13;
v18[v12] = 0;
v15 = *((unsigned __int8 *)v6 + v14);
memcpy(v17, (char *)v6 + ++v14, v15);
v11 = v15 + v14;
v17[v15] = 0;
sub_49A920((int)v18, v17);
printf("%s %s\n", v18, v17);
--v10;
}
while ( v10 );
v3 = v16;
}
v1 = 1;
}
operator delete[](v6);
fclose(v3);
return v1;
}
conv_name.dat File Structure
[Header]
[Magic: 4 bytes] = 0x7665636E ("ncve" in little-endian)
[Count: 4 bytes] = number of entries
[Entries...]
[Len1: 1 byte] = length of original filename
[Name1: Len1 bytes] = original filename (Chinese)
[Len2: 1 byte] = length of replacement filename
[Name2: Len2 bytes] = replacement filename (ASCII)
That is, you will literally have to find all the Chinese file names and map them to names you understand, and then add them to the .dat file.
Most likely, this even applies to files inside tar archives.
As you can see, this might be a more correct method, but it is very time-consuming and tedious, so for most people, simply replacing local.dll will suffice.