前言
本游戏在国内知名度非常一般,而且在游戏领域也算是非常少见的厂商完全不考虑国际化的游戏系列,距今已有近30年的历史。
这次为了尝试对此游戏的贴图进行提取,我尝试下载了本游戏系列的大概所有版本,并尝试通过脱壳等手段找到贴图的提取函数,并想办法写出来提取用的脚本。
不过目前因为没人指导所以还处于停滞状态。。。慢慢来吧。
系列介绍
游戏系列最新作的9代和10代我还没找到能读取PE的方法,按照经验应该是有壳的……
前面几代最早的当然不用说,我下下来的版本就是没有壳的,当然也不排除免DVD补丁一类的已经把壳给去掉了。
文件介绍
游戏从第7代开始采用一种全平台的文件读取格式.UNB
和.UNH
,后者是前者的文件索引性质的东西,且在PC、PSP、PSV、PS3、PS4、NS多个平台通用。
为了找到文件的读取方法首先有必要找一下脱壳的exe文件。
当前进展
3代(练习用)
3代发售很早,里面需要打开的文件为KAODATA.WP3
。
用IDA打开以后搜索KAODATA
可以看到这样一小段调用:
sub_4A4F10(aAKaodataWp3, &unk_585268);
可以看到使用了sub_4A4F10
函数读取KAODATA.WP3
:
int __thiscall sub_4A4F10(_DWORD *this, int a2, int a3)
{
sub_487611(a2, 4);
this[10] = a3;
this[9] = sub_487884(0) >> 2;
this[8] = operator new(4 * this[9]);
return sub_4877AA(0, this[8]);
}
(待补)
8代2018版
目前比较新的已脱壳是8代2018年版本,脱壳以后可以发现都是以C++编写的(其实游戏启动器没有加壳,可以看到是VC++)
用IDA打开以后,复制了一下相关函数。
和UNB格式相关的函数sub_636280
如下:
int __thiscall sub_636280(void *this, char *Buffer, int a3, int a4, int a5, int a6)
{
char *v6; // esi
const char *v7; // eax
int result; // eax
const char *v9; // [esp-8h] [ebp-Ch]
int v10; // [esp-4h] [ebp-8h]
v6 = (char *)this + 124 * a4 + 968;
if ( (*(int (__thiscall **)(char *))(*(_DWORD *)v6 + 48))(v6) == 2 )
{
v7 = (const char *)(*(int (__thiscall **)(char *))(*(_DWORD *)v6 + 36))(v6);
sprintf(Buffer, "%s.UNB", v7);
*(_DWORD *)a3 = *(_DWORD *)a5;
result = *(_DWORD *)(a5 + 4);
*(_DWORD *)(a3 + 4) = result;
}
else
{
v9 = (const char *)(*(int (__thiscall **)(char *, _DWORD))(*(_DWORD *)v6 + 36))(v6, *(_DWORD *)(a5 + 8));
if ( a6 )
sprintf(Buffer, "%s/%s_COMP/%08X.UND", (const char *)a6, v9, v10);
else
sprintf(Buffer, "%s_COMP/%08X.UND", v9, v10);
result = a3;
*(_DWORD *)a3 = 0;
*(_DWORD *)(a3 + 4) = 0;
}
return result;
}
和UNH格式相关函数sub_636560
则如下:
int __thiscall sub_636560(int *this)
{
int v1; // eax
int *v2; // esi
int *v3; // edi
int v4; // ebx
int v6; // [esp+Ch] [ebp-44h]
const char *v7; // [esp+10h] [ebp-40h]
const char *v8; // [esp+14h] [ebp-3Ch]
int v9[13]; // [esp+18h] [ebp-38h] BYREF
v1 = *this;
v6 = this[1];
v7 = "DATA.UNH";
v8 = "DATA";
v9[0] = v1;
v9[1] = v6;
v9[2] = (int)"DATA2.UNH";
v9[3] = (int)"DATA";
v9[4] = v1;
v9[5] = 4;
v9[6] = (int)"DLC00.UNH";
v9[7] = (int)"DLC00";
v9[8] = 1;
v9[9] = v6;
v9[10] = (int)"PATCH.UNH";
v9[11] = (int)"PATCH";
v9[12] = 2;
v2 = v9;
v3 = this + 242;
v4 = 4;
do
{
if ( sub_638280(*(v2 - 3), *(v2 - 2)) || !*v2 )
(*(void (__thiscall **)(int *, _DWORD, _DWORD, _DWORD, int))(*v3 + 8))(v3, *(v2 - 3), *(v2 - 2), *(v2 - 1), *v2);
v2 += 4;
v3 += 31;
--v4;
}
while ( v4 );
sub_41C6D0();
return 0;
}
可以看到,UNB文件中调用了sprintf()函数,且本身处于sub_636280
函数中。而hash文件UNH则调用了刚才提到的sub_638280
和另一个sub_41C6D0
两个函数。
sub_41C6D0
函数如下:
int sub_41C6D0()
{
int v0; // eax
v0 = sub_62AFA0(&aWp8CmnMsgDat[0x80000000]);
return sub_62AE00(&unk_D1BCB8, &aWp8CmnMsgDat[0x80000000], 0, v0);
}
从此文件缩写大概可以判断应该是和command message相关的某个文件(实际上根目录确实有名为WP8MSG.DAT
的文件),也就是说while ( v4 );
这一段调用的内容可以忽略。
前面提到的sprintf()函数如下:
int sprintf(char *const Buffer, const char *const Format, ...)
{
int result; // eax
int v3; // eax
bool v4; // sf
int v5; // esi
FILE Stream; // [esp+8h] [ebp-20h] BYREF
va_list va; // [esp+38h] [ebp+10h] BYREF
va_start(va, Format);
Stream._ptr = 0;
memset(&Stream._cnt, 0, 0x1Cu);
if ( Format && Buffer )
{
Stream._base = Buffer;
Stream._ptr = Buffer;
Stream._cnt = 0x7FFFFFFF;
Stream._flag = 66;
v3 = sub_B11227((int)&Stream, (int)Format, 0, (int)va);
v4 = --Stream._cnt < 0;
v5 = v3;
if ( v4 )
sub_B110DA(0, &Stream);
else
*Stream._ptr = 0;
result = v5;
}
else
{
*_errno() = 22;
_invalid_parameter_noinfo();
result = -1;
}
return result;
}
问混元助手得到的回复:
这段代码是一个实现sprintf
功能的函数。sprintf
函数用于将格式化的数据写入一个字符串。这个函数接受三个参数:
char *const Buffer
:一个指向字符数组的指针,用于存储格式化后的字符串。const char *const Format
:一个指向格式字符串的指针,用于指定输出格式。...
:可变参数,用于提供要格式化的数据。
这个函数的工作原理如下:
- 首先,它使用
va_start
宏初始化一个va_list
变量,用于访问可变参数。 - 然后,它使用
memset
函数将Stream._cnt
设置为0。 - 如果
Format
和Buffer
都不为空,则执行以下操作:- 初始化一个
FILE
类型的变量Stream
,用于表示输出流。 - 设置
Stream
的一些成员变量,以便它可以将格式化的数据写入Buffer
。 - 调用
sub_B11227
函数,该函数实现了实际的格式化操作。 - 检查
Stream._cnt
是否小于0,如果是,则调用sub_B110DA
函数处理错误。否则,在字符串末尾添加一个空字符。 - 返回
sub_B11227
函数的结果。
- 初始化一个
- 如果
Format
或Buffer
为空,则设置errno
为22(表示无效参数),并调用_invalid_parameter_noinfo
函数处理错误。返回-1表示出错。
总之,这个函数实现了类似于C标准库中sprintf
函数的功能,用于将格式化的数据写入一个字符串。
可见sub_B11227
函数挺重要的,但是这个格式化函数就有点大了:
int __cdecl sub_B11227(int a1, int a2, struct localeinfo_struct *a3, int a4)
{
unsigned int v4; // ebx
int v5; // eax
_BYTE *v6; // edx
char *v7; // ecx
char v8; // cl
int v9; // edx
char *v10; // esi
char *v11; // eax
int v12; // eax
int v13; // edi
int v14; // eax
char v15; // al
int v16; // eax
int v17; // ecx
char *j; // eax
int v19; // eax
_DWORD *v20; // edi
__int16 *v21; // eax
_WORD *v22; // edi
int v23; // ecx
int v24; // edi
int v25; // edi
void *v26; // eax
int v27; // eax
int *v28; // edi
void (__cdecl *v29)(int *, char *, int, int, int, int, __crt_locale_pointers *); // eax
void (__cdecl *v30)(char *, __crt_locale_pointers *); // eax
void (__cdecl *v31)(char *, __crt_locale_pointers *); // eax
_DWORD *v32; // edi
int v33; // eax
int v34; // edx
char *i; // esi
unsigned __int64 v36; // rcx
int v37; // ecx
char *v38; // eax
char *k; // eax
int v40; // eax
int v41; // edi
int v42; // eax
wchar_t *v43; // ecx
int result; // eax
int v45; // [esp-14h] [ebp-2A0h]
int v46; // [esp-10h] [ebp-29Ch]
unsigned __int64 v47; // [esp-10h] [ebp-29Ch]
int v48; // [esp-Ch] [ebp-298h]
int v49; // [esp-8h] [ebp-294h]
int v50; // [esp-4h] [ebp-290h]
wchar_t v51; // [esp-4h] [ebp-290h]
int v52[2]; // [esp+Ch] [ebp-280h] BYREF
__crt_locale_pointers Locale; // [esp+14h] [ebp-278h] BYREF
int v54; // [esp+1Ch] [ebp-270h]
char v55; // [esp+20h] [ebp-26Ch]
int v56; // [esp+28h] [ebp-264h]
int v57; // [esp+2Ch] [ebp-260h]
int v58; // [esp+30h] [ebp-25Ch] BYREF
void *Block; // [esp+34h] [ebp-258h]
int v60; // [esp+38h] [ebp-254h]
int v61; // [esp+3Ch] [ebp-250h]
char v62[4]; // [esp+40h] [ebp-24Ch]
int v63; // [esp+44h] [ebp-248h]
int v64; // [esp+48h] [ebp-244h]
int v65; // [esp+4Ch] [ebp-240h]
int v66; // [esp+50h] [ebp-23Ch]
int v67; // [esp+54h] [ebp-238h]
int v68; // [esp+58h] [ebp-234h]
FILE *Stream; // [esp+5Ch] [ebp-230h]
int v70; // [esp+60h] [ebp-22Ch] BYREF
int v71; // [esp+64h] [ebp-228h]
int SizeConverted; // [esp+68h] [ebp-224h] BYREF
int v73; // [esp+6Ch] [ebp-220h] BYREF
int *v74; // [esp+70h] [ebp-21Ch]
unsigned int v75; // [esp+74h] [ebp-218h]
char v76; // [esp+7Bh] [ebp-211h]
char *v77; // [esp+7Ch] [ebp-210h]
char MbCh[511]; // [esp+80h] [ebp-20Ch] BYREF
char v79; // [esp+27Fh] [ebp-Dh] BYREF
char v80[8]; // [esp+280h] [ebp-Ch] BYREF
Stream = (FILE *)a1;
v4 = 0;
v77 = (char *)a2;
v74 = (int *)a4;
v61 = 0;
v75 = 0;
v67 = 0;
v71 = 0;
v68 = 0;
v63 = 0;
v66 = 0;
_LocaleUpdate::_LocaleUpdate((_LocaleUpdate *)&Locale, a3);
v60 = (int)_errno();
if ( Stream
&& ((Stream->_flag & 0x40) != 0
|| ((v5 = _fileno(Stream), v5 == -1) || v5 == -2 ? (v6 = &unk_D16CD0) : (v6 = (_BYTE *)(dword_EC1830[v5 >> 5]
+ ((v5 & 0x1F) << 6))),
(v6[36] & 0x7F) == 0
&& (v5 == -1 || v5 == -2 ? (v7 = (char *)&unk_D16CD0) : (v7 = (char *)(dword_EC1830[v5 >> 5] + ((v5 & 0x1F) << 6))),
v7[36] >= 0)))
&& a2 )
{
v8 = *(_BYTE *)a2;
v9 = 0;
v73 = 0;
SizeConverted = 0;
v64 = 0;
Block = 0;
v76 = v8;
v62[0] = v8;
if ( v8 )
{
v10 = (char *)v56;
v11 = v77;
while ( 2 )
{
v77 = v11 + 1;
if ( v9 < 0 )
break;
if ( (unsigned __int8)(v8 - 32) > 0x58u )
v12 = 0;
else
v12 = aE000[v8] & 0xF;
v13 = (int)v74;
v64 = byte_BF7288[8 * v12 + v64] >> 4;
switch ( v64 )
{
case 0:
goto LABEL_65;
case 1:
v71 = -1;
v4 = 0;
v57 = 0;
v63 = 0;
v67 = 0;
v68 = 0;
v75 = 0;
v66 = 0;
goto LABEL_220;
case 2:
switch ( v8 )
{
case ' ':
v4 |= 2u;
goto LABEL_30;
case '#':
v4 |= 0x80u;
goto LABEL_30;
case '+':
v4 |= 1u;
goto LABEL_30;
case '-':
v4 |= 4u;
goto LABEL_30;
}
v11 = v77;
if ( v8 != 48 )
goto LABEL_221;
v4 |= 8u;
goto LABEL_28;
case 3:
if ( v8 == 42 )
{
v14 = *v74++;
v67 = v14;
if ( v14 < 0 )
{
v4 |= 4u;
v75 = v4;
v67 = -v14;
}
}
else
{
v67 *= 10;
v67 = v8 + v67 - 48;
}
goto LABEL_220;
case 4:
v71 = 0;
goto LABEL_220;
case 5:
if ( v8 != 42 )
{
v71 = v8 + 10 * v71 - 48;
goto LABEL_219;
}
v71 = *v74;
v11 = v77;
++v74;
if ( v71 < 0 )
v71 = -1;
goto LABEL_221;
case 6:
if ( v8 == 73 )
{
v15 = *v77;
if ( *v77 == 54 && v77[1] == 52 )
{
v11 = v77 + 2;
v4 |= 0x8000u;
goto LABEL_28;
}
if ( v15 == 51 && v77[1] == 50 )
{
v11 = v77 + 2;
v4 &= 0xFFFF7FFF;
goto LABEL_28;
}
if ( v15 == 100 || v15 == 105 || v15 == 111 || v15 == 117 || v15 == 120 || v15 == 88 )
goto LABEL_220;
v64 = 0;
LABEL_65:
v66 = 0;
if ( _isleadbyte_l((unsigned __int8)v8, &Locale) )
{
write_char(v62[0], Stream, (int)&v73);
v62[0] = *v77++;
if ( !v62[0] )
goto LABEL_226;
}
write_char(v62[0], Stream, (int)&v73);
LABEL_219:
v9 = v73;
LABEL_220:
v11 = v77;
goto LABEL_221;
}
if ( v8 == 104 )
{
v4 |= 0x20u;
LABEL_30:
v75 = v4;
goto LABEL_220;
}
v11 = v77;
if ( v8 == 108 )
{
if ( *v77 == 108 )
{
v11 = v77 + 1;
v4 |= 0x1000u;
}
else
{
v4 |= 0x10u;
}
goto LABEL_28;
}
if ( v8 == 119 )
{
v4 |= 0x800u;
LABEL_28:
v75 = v4;
}
LABEL_221:
v8 = *v11;
v76 = v8;
v62[0] = v8;
if ( !v8 )
break;
continue;
case 7:
if ( v8 > 100 )
{
if ( v8 > 112 )
{
if ( v8 == 115 )
goto LABEL_83;
if ( v8 != 117 )
{
if ( v8 != 120 )
goto LABEL_189;
v50 = 39;
goto LABEL_150;
}
LABEL_123:
SizeConverted = 10;
goto LABEL_124;
}
if ( v8 == 112 )
{
v71 = 8;
LABEL_145:
v50 = 7;
LABEL_150:
v61 = v50;
SizeConverted = 16;
if ( (v4 & 0x80u) != 0 )
{
LOBYTE(v70) = 48;
BYTE1(v70) = v50 + 81;
v68 = 2;
}
goto LABEL_124;
}
if ( v8 < 101 )
goto LABEL_189;
if ( v8 <= 103 )
goto LABEL_77;
if ( v8 != 105 )
{
if ( v8 == 110 )
{
++v74;
v22 = *(_WORD **)v13;
if ( !_get_printf_count_output() )
goto LABEL_226;
if ( (v4 & 0x20) != 0 )
*v22 = v73;
else
*(_DWORD *)v22 = v73;
v63 = 1;
goto LABEL_216;
}
if ( v8 != 111 )
goto LABEL_189;
SizeConverted = 8;
if ( (v4 & 0x80u) != 0 )
{
v4 |= 0x200u;
v75 = v4;
}
LABEL_124:
if ( (v4 & 0x8000) != 0 || (v4 & 0x1000) != 0 )
{
v23 = *v74;
v74 += 2;
v24 = *(_DWORD *)(v13 + 4);
goto LABEL_160;
}
v32 = ++v74;
if ( (v4 & 0x20) != 0 )
{
if ( (v4 & 0x40) != 0 )
v33 = *((__int16 *)v32 - 2);
else
v33 = *((unsigned __int16 *)v32 - 2);
}
else
{
if ( (v4 & 0x40) == 0 )
{
v23 = *(v32 - 1);
v24 = 0;
LABEL_160:
if ( (v4 & 0x40) != 0 && v24 < 0 )
{
v23 = -v23;
v24 = (unsigned __int64)-__SPAIR64__(v24, v23) >> 32;
v4 |= 0x100u;
v75 = v4;
}
if ( (v4 & 0x9000) == 0 )
v24 = 0;
v34 = v71;
if ( v71 >= 0 )
{
v75 = v4 & 0xFFFFFFF7;
if ( v71 > 512 )
v34 = 512;
}
else
{
v34 = 1;
}
if ( !(v24 | v23) )
v68 = 0;
for ( i = &v79; ; --i )
{
v71 = v34 - 1;
if ( v34 <= 0 && !(v24 | v23) )
break;
v47 = __PAIR64__(v24, v23);
v36 = __PAIR64__(v24, v23) % SizeConverted;
v37 = v36 + 48;
v56 = HIDWORD(v36);
v24 = (v47 / SizeConverted) >> 32;
v65 = v47 / SizeConverted;
if ( v37 > 57 )
LOBYTE(v37) = v61 + v37;
v34 = v71;
*i = v37;
v23 = v65;
}
v4 = v75;
v38 = (char *)(&v79 - i);
v10 = i + 1;
SizeConverted = (int)v38;
if ( (v75 & 0x200) != 0 && (!v38 || *v10 != 48) )
{
--v10;
++SizeConverted;
*v10 = 48;
}
goto LABEL_189;
}
v33 = *(v32 - 1);
}
v24 = v33 >> 31;
v23 = v33;
goto LABEL_160;
}
}
else if ( v8 != 100 )
{
if ( v8 <= 83 )
{
if ( v8 != 83 )
{
if ( v8 == 65 )
{
LABEL_76:
v8 += 32;
v57 = 1;
v76 = v8;
goto LABEL_77;
}
if ( v8 != 67 )
{
if ( v8 == 69 || v8 == 71 )
goto LABEL_76;
LABEL_189:
if ( v63 )
goto LABEL_216;
if ( (v4 & 0x40) == 0 )
goto LABEL_198;
if ( (v4 & 0x100) != 0 )
{
LOBYTE(v70) = 45;
}
else if ( (v4 & 1) != 0 )
{
LOBYTE(v70) = 43;
}
else
{
if ( (v4 & 2) == 0 )
{
LABEL_198:
v40 = v68;
v41 = v67 - SizeConverted - v68;
if ( (v4 & 0xC) == 0 )
{
write_multi_char(32, v67 - SizeConverted - v68, Stream, (int)&v73);
v40 = v68;
}
write_string((int)&v70, v40, Stream, (int)&v73, v60);
if ( (v4 & 8) != 0 && (v4 & 4) == 0 )
write_multi_char(48, v41, Stream, (int)&v73);
v42 = SizeConverted;
if ( v66 && SizeConverted > 0 )
{
v43 = (wchar_t *)v10;
while ( 1 )
{
v65 = v42 - 1;
v51 = *v43;
v56 = (int)(v43 + 1);
if ( wctomb_s(&v58, v80, 6u, v51) || !v58 )
break;
write_string((int)v80, v58, Stream, (int)&v73, v60);
v42 = v65;
v43 = (wchar_t *)v56;
if ( !v65 )
goto LABEL_212;
}
v9 = -1;
v73 = -1;
}
else
{
write_string((int)v10, SizeConverted, Stream, (int)&v73, v60);
LABEL_212:
v9 = v73;
}
if ( v9 >= 0 && (v4 & 4) != 0 )
{
write_multi_char(32, v41, Stream, (int)&v73);
LABEL_216:
v9 = v73;
}
if ( !Block )
goto LABEL_220;
free(Block);
Block = 0;
goto LABEL_219;
}
LOBYTE(v70) = 32;
}
v68 = 1;
goto LABEL_198;
}
if ( (v4 & 0x830) == 0 )
{
v4 |= 0x800u;
v75 = v4;
}
LABEL_96:
v20 = ++v74;
if ( (v4 & 0x810) != 0 )
{
if ( wctomb_s(&SizeConverted, MbCh, 0x200u, *((_WORD *)v20 - 2)) )
v63 = 1;
}
else
{
MbCh[0] = *((_BYTE *)v20 - 4);
SizeConverted = 1;
}
v10 = MbCh;
goto LABEL_189;
}
if ( (v4 & 0x830) == 0 )
{
v4 |= 0x800u;
v75 = v4;
}
LABEL_83:
v17 = 0x7FFFFFFF;
if ( v71 != -1 )
v17 = v71;
v10 = (char *)*v74++;
if ( (v4 & 0x810) != 0 )
{
if ( !v10 )
v10 = (char *)off_D16BCC;
v66 = 1;
for ( j = v10; v17; j += 2 )
{
--v17;
if ( !*(_WORD *)j )
break;
}
v19 = (j - v10) >> 1;
}
else
{
if ( !v10 )
v10 = off_D16BC8;
for ( k = v10; v17; ++k )
{
--v17;
if ( !*k )
break;
}
v19 = k - v10;
}
goto LABEL_188;
}
if ( v8 != 88 )
{
if ( v8 == 90 )
{
v21 = (__int16 *)*v74++;
if ( v21 )
{
v10 = (char *)*((_DWORD *)v21 + 1);
if ( v10 )
{
v19 = *v21;
if ( (v4 & 0x800) != 0 )
{
v19 /= 2;
v66 = 1;
}
else
{
v66 = 0;
}
goto LABEL_188;
}
}
v10 = off_D16BC8;
LABEL_107:
v19 = strlen(v10);
LABEL_188:
SizeConverted = v19;
goto LABEL_189;
}
if ( v8 == 97 )
{
LABEL_77:
v16 = v71;
v4 |= 0x40u;
v75 = v4;
v10 = MbCh;
v65 = 512;
if ( v71 >= 0 )
{
if ( v71 )
{
if ( v71 > 512 )
{
v16 = 512;
v71 = 512;
}
if ( v16 > 163 )
{
v25 = v16 + 349;
v26 = (void *)_malloc_crt(v16 + 349);
v8 = v76;
Block = v26;
if ( v26 )
{
v10 = (char *)v26;
v65 = v25;
}
else
{
v71 = 163;
}
v13 = (int)v74;
}
}
else
{
v71 = v8 == 103;
}
}
else
{
v71 = 6;
}
v27 = *(_DWORD *)v13;
v28 = (int *)(v13 + 8);
v52[0] = v27;
v52[1] = *(v28 - 1);
v49 = v57;
v48 = v71;
v74 = v28;
v46 = v8;
v45 = v65;
v29 = (void (__cdecl *)(int *, char *, int, int, int, int, __crt_locale_pointers *))DecodePointer(off_D16B98);
v29(v52, v10, v45, v46, v48, v49, &Locale);
if ( (v4 & 0x80) != 0 && !v71 )
{
v30 = (void (__cdecl *)(char *, __crt_locale_pointers *))DecodePointer(off_D16BA4);
v30(v10, &Locale);
}
if ( v76 == 103 && (v4 & 0x80) == 0 )
{
v31 = (void (__cdecl *)(char *, __crt_locale_pointers *))DecodePointer(off_D16BA0);
v31(v10, &Locale);
}
if ( *v10 == 45 )
{
v4 |= 0x100u;
v75 = v4;
++v10;
}
goto LABEL_107;
}
if ( v8 != 99 )
goto LABEL_189;
goto LABEL_96;
}
goto LABEL_145;
}
v4 |= 0x40u;
v75 = v4;
goto LABEL_123;
default:
goto LABEL_220;
}
}
}
result = v9;
}
else
{
LABEL_226:
*_errno() = 22;
_invalid_parameter_noinfo();
result = -1;
}
if ( v55 )
*(_DWORD *)(v54 + 112) &= 0xFFFFFFFD;
return result;
}
里面调用了大量的Label作为跳转标签。反正把我看傻了……
(待补)