2024-09-07 21:34:41 +08:00
|
|
|
|
#include "TACTICS.h"
|
|
|
|
|
// 鈴がうたう日
|
|
|
|
|
// https://vndb.org/v8528
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
不同的速度有不同的函数,但这几个函数核心完全一样,且都是读一个固定的全局指针
|
|
|
|
|
__int16 sub_40488C()
|
|
|
|
|
{
|
|
|
|
|
UINT v0; // ebx
|
|
|
|
|
|
|
|
|
|
if ( !word_4ABF8E )
|
|
|
|
|
{
|
|
|
|
|
word_4ABF8E = 1;
|
|
|
|
|
word_4ABF88 = strlen(&Str) + 1;
|
|
|
|
|
word_4ABF8A = 0;
|
|
|
|
|
word_4ABF8C = 0;
|
|
|
|
|
dword_43ACE4 = 0;
|
|
|
|
|
}
|
|
|
|
|
LABEL_35:
|
|
|
|
|
while ( word_4ABF8E < word_4ABF88 )
|
|
|
|
|
{
|
|
|
|
|
if ( IsDBCSLeadByteEx(0, *(&Str + word_4ABF8E)) )
|
|
|
|
|
{
|
|
|
|
|
v0 = (unsigned __int8)byte_4ABB89[word_4ABF8E] + ((unsigned __int8)*(&Str + word_4ABF8E) << 8);
|
|
|
|
|
word_4ABF8E += 2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
v0 = *(&Str + word_4ABF8E++);
|
|
|
|
|
}
|
|
|
|
|
switch ( v0 )
|
|
|
|
|
{
|
|
|
|
|
case 0u:
|
|
|
|
|
if ( !dword_43ACE4 )
|
|
|
|
|
sub_401334(v0);
|
|
|
|
|
return 3;
|
|
|
|
|
case 1u:
|
|
|
|
|
word_4ABF8A = word_4ABF8C;
|
|
|
|
|
word_4ABF90 = word_438956 + 19 * word_4ABF8C;
|
|
|
|
|
word_4ABF92 += 28;
|
|
|
|
|
goto LABEL_35;
|
|
|
|
|
case 2u:
|
|
|
|
|
sub_4012B4(v0);
|
|
|
|
|
sub_4150CC(&unk_48966C, 50);
|
|
|
|
|
word_4ABF90 = word_438956;
|
|
|
|
|
word_4ABF92 = 343;
|
|
|
|
|
goto LABEL_35;
|
|
|
|
|
case 3u:
|
|
|
|
|
goto LABEL_35;
|
|
|
|
|
case 4u:
|
|
|
|
|
dword_43ACE4 = 1;
|
|
|
|
|
goto LABEL_35;
|
|
|
|
|
case 5u:
|
|
|
|
|
sub_401334(v0);
|
|
|
|
|
dword_43ACE4 = 1;
|
|
|
|
|
goto LABEL_35;
|
|
|
|
|
case 0x11u:
|
|
|
|
|
strcpy(byte_4ABD88, &Str + word_4ABF8E);
|
|
|
|
|
strcat(&Str, byte_4ABD88);
|
|
|
|
|
word_4ABF88 = strlen(&Str) + 1;
|
|
|
|
|
goto LABEL_35;
|
|
|
|
|
default:
|
|
|
|
|
if ( v0 == 33141 || v0 == 33156 )
|
|
|
|
|
word_4ABF8C = word_4ABF8A + 1;
|
|
|
|
|
if ( v0 == 33142 || v0 == 33156 )
|
|
|
|
|
{
|
|
|
|
|
word_4ABF8C = 0;
|
|
|
|
|
dword_43ACDC = 0;
|
|
|
|
|
}
|
|
|
|
|
if ( v0 == 33155 )
|
|
|
|
|
v0 = 33129;
|
|
|
|
|
if ( v0 == 33156 )
|
|
|
|
|
v0 = 33130;
|
|
|
|
|
if ( word_438958 >= ++word_4ABF8A )
|
|
|
|
|
goto LABEL_34;
|
|
|
|
|
if ( (unsigned __int16)v0 > 0x816Au )
|
|
|
|
|
{
|
|
|
|
|
if ( (unsigned __int16)v0 != 33142 && (unsigned __int16)v0 != 33144 )
|
|
|
|
|
{
|
|
|
|
|
LABEL_33:
|
|
|
|
|
word_4ABF8A = word_4ABF8C + 1;
|
|
|
|
|
word_4ABF90 = word_438956 + 19 * word_4ABF8C;
|
|
|
|
|
word_4ABF92 += 28;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ( (unsigned __int16)v0 != 33130
|
|
|
|
|
&& (unsigned __int16)v0 != 41
|
|
|
|
|
&& (unsigned int)(unsigned __int16)v0 - 33089 >= 2 )
|
|
|
|
|
{
|
|
|
|
|
goto LABEL_33;
|
|
|
|
|
}
|
|
|
|
|
LABEL_34:
|
|
|
|
|
sub_4155DC((int)&unk_4BC804, dword_47D52C, word_4ABF90, word_4ABF92, v0, 1);
|
|
|
|
|
sub_4155DC((int)&unk_4BC804, dword_48967C, word_4ABF90 - 45, word_4ABF92 - 322, v0, 1);
|
|
|
|
|
word_4ABF90 += 19;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
bool TACTICSattach_function1()
|
|
|
|
|
{
|
|
|
|
|
BYTE sig[] = {
|
|
|
|
|
0x0f, 0xbf, 0x05, XX4,
|
|
|
|
|
0X33, 0XD2,
|
|
|
|
|
0X8A, 0x98, XX4,
|
|
|
|
|
0x80, 0xe3, 0xff,
|
|
|
|
|
0x8a, 0x80, XX4,
|
|
|
|
|
0x81, 0xe3, 0xff, 0x00, 0x00, 0x00,
|
|
|
|
|
0x24, 0xff,
|
|
|
|
|
0xc1, 0xe3, 0x08,
|
|
|
|
|
0x8a, 0xd0,
|
|
|
|
|
0x03, 0xda,
|
|
|
|
|
0x66, 0x83, 0x05, XX4, 0x02,
|
|
|
|
|
0xeb, 0x15,
|
|
|
|
|
0x0f, 0xbf, 0x0d, XX4,
|
|
|
|
|
0x0f, 0xbe, 0x99, XX4,
|
|
|
|
|
0x66, 0xff, 0x05, XX4};
|
|
|
|
|
auto addr = MemDbg::findBytes(sig, sizeof(sig), processStartAddress, processStopAddress);
|
|
|
|
|
if (!addr)
|
|
|
|
|
return false;
|
|
|
|
|
addr = addr + 7 + 2 + 6 + 3 + 2;
|
|
|
|
|
|
|
|
|
|
HookParam hp;
|
|
|
|
|
hp.address = *(DWORD *)addr;
|
|
|
|
|
hp.type = USING_STRING | DIRECT_READ;
|
|
|
|
|
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
|
|
|
|
{
|
|
|
|
|
CharFilter((char *)data, len, 1);
|
|
|
|
|
CharFilter((char *)data, len, 2);
|
|
|
|
|
CharFilter((char *)data, len, 3);
|
|
|
|
|
CharFilter((char *)data, len, 4);
|
|
|
|
|
CharFilter((char *)data, len, 5);
|
|
|
|
|
CharFilter((char *)data, len, 0x11);
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
return NewHook(hp, "TACTICS_R");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TACTICSattach_function2()
|
|
|
|
|
{
|
|
|
|
|
BYTE sig[] = {
|
|
|
|
|
// clang-format off
|
|
|
|
|
0x2d,0x40,0x81,0x00,0x00,
|
|
|
|
|
0x89,0x83,XX,0x00,0x00,0x00,
|
|
|
|
|
0x3d,0x57,0x02,0x00,0x00,
|
|
|
|
|
0x0f,0x82,XX4,
|
|
|
|
|
0xbf,0x57,0x02,0x00,0x00,
|
|
|
|
|
// clang-format on
|
|
|
|
|
};
|
|
|
|
|
auto addr = MemDbg::findBytes(sig, sizeof(sig), processStartAddress, processStopAddress);
|
|
|
|
|
if (!addr)
|
|
|
|
|
return false;
|
|
|
|
|
HookParam hp;
|
|
|
|
|
hp.address = addr;
|
|
|
|
|
hp.type = USING_CHAR | CODEC_ANSI_BE;
|
|
|
|
|
hp.offset = get_reg(regs::eax);
|
|
|
|
|
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
|
|
|
|
{
|
|
|
|
|
static int idx = 0;
|
|
|
|
|
return 0 == ((idx++) % 2);
|
|
|
|
|
};
|
|
|
|
|
return NewHook(hp, "TACTICS_H");
|
|
|
|
|
}
|
2024-09-11 10:43:02 +08:00
|
|
|
|
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
// https://vndb.org/v2274
|
|
|
|
|
//[010119][Tactics] Cheerio! ~ちぇりお~ (bin+cue)
|
|
|
|
|
bool h3()
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
if ( a5 != 33088 )
|
|
|
|
|
{
|
|
|
|
|
v6 = a5 - 33088;
|
|
|
|
|
if ( a5 - 33088 < 0 || v6 > 597 )
|
|
|
|
|
{
|
|
|
|
|
v6 = 598;
|
|
|
|
|
sub_417F5C(a1, a5, 598);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
BYTE sig[] = {
|
|
|
|
|
// clang-format off
|
|
|
|
|
0x3d,0x40,0x81,0x00,0x00,
|
|
|
|
|
0x0f,0x84,XX4,
|
|
|
|
|
0x8b,0xf0,
|
|
|
|
|
0x81,0xee,0x40,0x81,0x00,0x00,
|
|
|
|
|
0x85,0xf6,
|
|
|
|
|
0x7c,0x08,
|
|
|
|
|
0x81,0xfe,0x55,0x02,0x00,0x00,
|
|
|
|
|
0x7e,XX,
|
|
|
|
|
0xbe,0x56,0x02,0x00,0x00
|
|
|
|
|
// clang-format on
|
|
|
|
|
};
|
|
|
|
|
auto addr = MemDbg::findBytes(sig, sizeof(sig), processStartAddress, processStopAddress);
|
|
|
|
|
if (!addr)
|
|
|
|
|
return false;
|
|
|
|
|
addr = findfuncstart(addr, 0x20); // v1.0不对齐
|
|
|
|
|
if (!addr)
|
|
|
|
|
return false;
|
|
|
|
|
HookParam hp;
|
|
|
|
|
hp.address = addr;
|
|
|
|
|
hp.type = USING_CHAR | CODEC_ANSI_BE | NO_CONTEXT;
|
|
|
|
|
hp.offset = get_stack(5);
|
|
|
|
|
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
|
|
|
|
{
|
|
|
|
|
static int idx = 0;
|
|
|
|
|
return 0 == ((idx++) % 2);
|
|
|
|
|
};
|
|
|
|
|
return NewHook(hp, "TACTICS_2");
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-07 21:34:41 +08:00
|
|
|
|
bool TACTICS::attach_function()
|
|
|
|
|
{
|
2024-09-11 10:43:02 +08:00
|
|
|
|
return (TACTICSattach_function1() | TACTICSattach_function2()) || h3();
|
2024-09-07 21:34:41 +08:00
|
|
|
|
}
|