Update CatSystem.cpp

This commit is contained in:
恍兮惚兮 2024-08-30 04:51:31 +08:00
parent 5fa33f740c
commit 067b0c288b

View File

@ -156,10 +156,17 @@ bool InsertCatSystemHook()
// hp.type =CODEC_ANSI_BE|DATA_INDIRECT|USING_SPLIT|SPLIT_INDIRECT; // hp.type =CODEC_ANSI_BE|DATA_INDIRECT|USING_SPLIT|SPLIT_INDIRECT;
// hp.length_offset=1; // hp.length_offset=1;
enum { beg = 0xff6acccc }; // jichi 7/12/2014: beginning of the function enum
enum { addr_offset = 2 }; // skip two leading 0xcc {
beg = 0xff6acccc
}; // jichi 7/12/2014: beginning of the function
enum
{
addr_offset = 2
}; // skip two leading 0xcc
ULONG addr = MemDbg::findCallerAddress((ULONG)::GetTextMetricsA, beg, processStartAddress, processStopAddress); ULONG addr = MemDbg::findCallerAddress((ULONG)::GetTextMetricsA, beg, processStartAddress, processStopAddress);
if (!addr) { if (!addr)
{
ConsoleOutput("CatSystem2: pattern not exist"); ConsoleOutput("CatSystem2: pattern not exist");
return false; return false;
} }
@ -170,7 +177,8 @@ bool InsertCatSystemHook()
// jichi 12/23/2014: Modify split for new catsystem // jichi 12/23/2014: Modify split for new catsystem
bool newEngine = Util::CheckFile(L"cs2conf.dll"); bool newEngine = Util::CheckFile(L"cs2conf.dll");
if (newEngine) { if (newEngine)
{
// hp.text_fun = SpecialHookCatSystem3; // type not needed // hp.text_fun = SpecialHookCatSystem3; // type not needed
// NewHook(hp, "CatSystem3"); // NewHook(hp, "CatSystem3");
// ConsoleOutput("INSERT CatSystem3"); // ConsoleOutput("INSERT CatSystem3");
@ -178,7 +186,9 @@ bool InsertCatSystemHook()
hp.split = get_reg(regs::esi); hp.split = get_reg(regs::esi);
ConsoleOutput("INSERT CatSystem3new"); ConsoleOutput("INSERT CatSystem3new");
return NewHook(hp, "CatSystem3new"); return NewHook(hp, "CatSystem3new");
} else { }
else
{
hp.type = CODEC_ANSI_BE | USING_SPLIT; hp.type = CODEC_ANSI_BE | USING_SPLIT;
hp.split = get_reg(regs::edx); hp.split = get_reg(regs::edx);
ConsoleOutput("INSERT CatSystem2"); ConsoleOutput("INSERT CatSystem2");
@ -205,8 +215,8 @@ bool InsertCatSystem2Hook()
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR); ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range); ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
if (!addr) { if (!addr)
ConsoleOutput("CatSystem2new: pattern not found"); {
return false; return false;
} }
@ -214,14 +224,21 @@ bool InsertCatSystem2Hook()
hp.address = addr; hp.address = addr;
hp.offset = get_reg(regs::eax); hp.offset = get_reg(regs::eax);
hp.type = USING_STRING | CODEC_UTF8; hp.type = USING_STRING | CODEC_UTF8;
ConsoleOutput("INSERT CatSystem2new"); hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
{
static std::regex rx(R"(\[(.+?)/.+\])");
auto _ = std::regex_replace(std::string((char *)data, *len), rx, "$1");
return write_string_overwrite(data, len, _);
};
return NewHook(hp, "CatSystem2new"); return NewHook(hp, "CatSystem2new");
} }
namespace { // unnamed namespace
namespace Patch { { // unnamed
namespace Patch
{
namespace Private { namespace Private
{
// String in ecx // String in ecx
// bool __fastcall isLeadByteChar(const char *s, DWORD edx) // bool __fastcall isLeadByteChar(const char *s, DWORD edx)
// bool isLeadByteChar(hook_stack*s,void* data, size_t* len,uintptr_t*role) // bool isLeadByteChar(hook_stack*s,void* data, size_t* len,uintptr_t*role)
@ -411,13 +428,15 @@ template <typename strT>
strT ltrim(strT text) strT ltrim(strT text)
{ {
strT lastText = nullptr; strT lastText = nullptr;
while (*text && text != lastText) { while (*text && text != lastText)
{
lastText = text; lastText = text;
if (text[0] == 0x20) if (text[0] == 0x20)
text++; text++;
if ((UINT8)text[0] == 0x81 && (UINT8)text[1] == 0x40) // skip space \u3000 (0x8140 in sjis) if ((UINT8)text[0] == 0x81 && (UINT8)text[1] == 0x40) // skip space \u3000 (0x8140 in sjis)
text += 2; text += 2;
if (text[0] == '\\') { if (text[0] == '\\')
{
text++; text++;
while (::islower(text[0]) || text[0] == '@') while (::islower(text[0]) || text[0] == '@')
text++; text++;
@ -437,8 +456,10 @@ size_t rtrim(LPCSTR text)
return size; return size;
} }
namespace ScenarioHook { namespace ScenarioHook
namespace Private { {
namespace Private
{
bool isOtherText(LPCSTR text) bool isOtherText(LPCSTR text)
{ {
@ -473,33 +494,48 @@ static bool containsNamePunct_(const char *text)
{ {
static const char *puncts[] = { static const char *puncts[] = {
"\x81\x41" /* 、 */ "\x81\x41" /* 、 */
, "\x81\x43" /* */ ,
, "\x81\x42" /* 。 */ "\x81\x43" /* */
,
"\x81\x42" /* 。 */
//, "\x81\x48" /* */ //, "\x81\x48" /* */
, "\x81\x49" /* */ ,
, "\x81\x63" /* … */ "\x81\x49" /* */
, "\x81\x64" /* ‥ */ ,
"\x81\x63" /* … */
,
"\x81\x64" /* ‥ */
//, "\x81\x79" /* 【 */ //, "\x81\x79" /* 【 */
//, "\x81\x7a" /* 】 */ //, "\x81\x7a" /* 】 */
, "\x81\x75" /* 「 */ ,
, "\x81\x76" /* 」 */ "\x81\x75" /* 「 */
, "\x81\x77" /* 『 */ ,
, "\x81\x78" /* 』 */ "\x81\x76" /* 」 */
,
"\x81\x77" /* 『 */
,
"\x81\x78" /* 』 */
//, "\x81\x69" /* */ //, "\x81\x69" /* */
//, "\x81\x6a" /* */ //, "\x81\x6a" /* */
//, "\x81\x6f" /* */ //, "\x81\x6f" /* */
//, "\x81\x70" /* */ //, "\x81\x70" /* */
//, "\x81\x71" /* 〈 */ //, "\x81\x71" /* 〈 */
//, "\x81\x72" /* 〉 */ //, "\x81\x72" /* 〉 */
, "\x81\x6d" /* */ ,
, "\x81\x6e" /* */ "\x81\x6d" /* */
,
"\x81\x6e" /* */
//, "\x81\x83", /* */ //, "\x81\x83", /* */
//, "\x81\x84", /* */ //, "\x81\x84", /* */
, "\x81\x65" /* */ ,
, "\x81\x66" /* */ "\x81\x65" /* */
, "\x81\x67" /* “ */ ,
, "\x81\x68" /* ” */ "\x81\x66" /* */
,
"\x81\x67" /* “ */
,
"\x81\x68" /* ” */
}; };
for (size_t i = 0; i < sizeof(puncts) / sizeof(*puncts); i++) for (size_t i = 0; i < sizeof(puncts) / sizeof(*puncts); i++)
if (::strstr(text, puncts[i])) if (::strstr(text, puncts[i]))
@ -512,12 +548,16 @@ static bool containsNamePunct_(const char *text)
} }
bool guessIsNameText(const char *text, size_t size) bool guessIsNameText(const char *text, size_t size)
{ {
enum { MaximumNameSize = 0x10 }; enum
{
MaximumNameSize = 0x10
};
if (!size) if (!size)
size = ::strlen(text); size = ::strlen(text);
return size < MaximumNameSize && !containsNamePunct_(text); return size < MaximumNameSize && !containsNamePunct_(text);
} }
LPSTR trimmedText;size_t trimmedSize; LPSTR trimmedText;
size_t trimmedSize;
bool hookBefore(hook_stack *s, void *data, size_t *len, uintptr_t *role) bool hookBefore(hook_stack *s, void *data, size_t *len, uintptr_t *role)
{ {
// static std::unordered_set<uint64_t> hashes_; // static std::unordered_set<uint64_t> hashes_;
@ -556,7 +596,8 @@ static bool containsNamePunct_(const char *text)
static ULONG minimumGroupId_ = -1; // I assume scenario thread to have minimum groupId static ULONG minimumGroupId_ = -1; // I assume scenario thread to have minimum groupId
// if (session_.addText(groupId, Engine::hashCharArray(text))) { // if (session_.addText(groupId, Engine::hashCharArray(text))) {
if (groupId <= minimumGroupId_) { if (groupId <= minimumGroupId_)
{
minimumGroupId_ = groupId; minimumGroupId_ = groupId;
*role = Engine::ScenarioRole; *role = Engine::ScenarioRole;
@ -567,7 +608,6 @@ static bool containsNamePunct_(const char *text)
else if (trimmedText == text && !trimmedText[trimmedSize] // no prefix and suffix else if (trimmedText == text && !trimmedText[trimmedSize] // no prefix and suffix
&& guessIsNameText(trimmedText, trimmedSize)) && guessIsNameText(trimmedText, trimmedSize))
*role = Engine::NameRole; *role = Engine::NameRole;
} }
} }
@ -575,7 +615,8 @@ static bool containsNamePunct_(const char *text)
return write_string_overwrite(data, len, oldData); return write_string_overwrite(data, len, oldData);
} }
void hookafter(hook_stack*s,void* data, size_t len){ void hookafter(hook_stack *s, void *data, size_t len)
{
auto newData = std::string((char *)data, len); auto newData = std::string((char *)data, len);
if (trimmedText[trimmedSize]) if (trimmedText[trimmedSize])
@ -749,7 +790,7 @@ static bool containsNamePunct_(const char *text)
* 004985CC CC INT3 * 004985CC CC INT3
* 004985CD CC INT3 * 004985CD CC INT3
*/ */
bool attach(ULONG startAddress, ULONG stopAddress) bool attach(ULONG startAddress, ULONG stopAddress, HookParamType code)
{ {
const uint8_t bytes[] = { const uint8_t bytes[] = {
0xe8, XX4, // 004b00dc e8 7f191300 call .005e1a60 ; jichi: hook after here 0xe8, XX4, // 004b00dc e8 7f191300 call .005e1a60 ; jichi: hook after here
@ -759,15 +800,20 @@ bool attach(ULONG startAddress, ULONG stopAddress)
// XX2, XX, 0x00,0x00,0x00 // 004b00ea 8d9b 00000000 lea ebx,dword ptr ds:[ebx] // XX2, XX, 0x00,0x00,0x00 // 004b00ea 8d9b 00000000 lea ebx,dword ptr ds:[ebx]
}; };
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress); ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
if(addr==0)return false; if (addr == 0)
return false;
HookParam hp; HookParam hp;
hp.address = addr + 5; hp.address = addr + 5;
hp.type=USING_STRING|EMBED_ABLE|EMBED_DYNA_SJIS; hp.type = USING_STRING | EMBED_ABLE;
if (code)
hp.type |= code;
else
hp.type |= EMBED_DYNA_SJIS;
hp.hook_before = Private::hookBefore; hp.hook_before = Private::hookBefore;
hp.hook_after = Private::hookafter; hp.hook_after = Private::hookafter;
hp.hook_font = F_GetGlyphOutlineA; hp.hook_font = F_GetGlyphOutlineA;
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){ hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
{
static std::regex rx(R"(\[(.+?)/.+\])"); static std::regex rx(R"(\[(.+?)/.+\])");
auto _ = std::regex_replace(std::string((char *)data, *len), rx, "$1"); auto _ = std::regex_replace(std::string((char *)data, *len), rx, "$1");
return write_string_overwrite(data, len, _); return write_string_overwrite(data, len, _);
@ -775,20 +821,31 @@ bool attach(ULONG startAddress, ULONG stopAddress)
static ULONG p; static ULONG p;
p = Patch::patchEncoding(startAddress, stopAddress); p = Patch::patchEncoding(startAddress, stopAddress);
if(p){ if (p)
{
hp.type |= EMBED_DYNA_SJIS; hp.type |= EMBED_DYNA_SJIS;
hp.hook_font = F_GetGlyphOutlineA; hp.hook_font = F_GetGlyphOutlineA;
patch_fun=[](){ patch_fun = []()
{
ReplaceFunction((PVOID *)&p, (PVOID)(ULONG)Patch::Private::isLeadByteChar); ReplaceFunction((PVOID *)&p, (PVOID)(ULONG)Patch::Private::isLeadByteChar);
}; };
} }
return NewHook(hp, "EmbedCS2"); return NewHook(hp, "EmbedCS2");
} }
} }
} // namespace ScenarioHook } // namespace ScenarioHook
bool CatSystem::attach_function() { bool CatSystem::attach_function()
auto embed=ScenarioHook::attach(processStartAddress,processStopAddress); {
return InsertCatSystemHook()||InsertCatSystem2Hook()||embed; HookParamType code = CODEC_ANSI_LE;
auto b1 = InsertCatSystemHook();
if (!b1)
{
b1 |= InsertCatSystem2Hook();
code = CODEC_UTF8;
}
auto embed = ScenarioHook::attach(processStartAddress, processStopAddress, code);
b1 |= embed;
return b1;
} }