From 810f33377075e729bfec83d286136eddbcb47ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <1173718158@qq.com> Date: Wed, 6 Nov 2024 21:39:52 +0800 Subject: [PATCH] views --- cpp/LunaHook/LunaHook/engine32/AdobeAir.cpp | 2 +- cpp/LunaHook/LunaHook/engine32/Aksys.cpp | 2 +- .../LunaHook/engine32/RPGMakerRGSS3.cpp | 8 +- cpp/LunaHook/LunaHook/engine32/Wolf.cpp | 6 +- cpp/LunaHook/LunaHook/engine64/vita3k.cpp | 15 +- cpp/LunaHook/LunaHook/engine64/yuzu.cpp | 48 +- cpp/LunaHook/LunaHook/engines/mages/mages.cpp | 669 ++++++++++-------- .../LunaHook/engines/ppsspp/specialgames.hpp | 5 +- .../LunaHook/util/dyncodec/dynsjiscodec.cc | 4 +- cpp/LunaHook/LunaHost/GUI/LunaHost.cpp | 2 +- cpp/LunaHook/include/stringutils.cpp | 56 +- cpp/LunaHook/include/stringutils.h | 13 +- 12 files changed, 457 insertions(+), 373 deletions(-) diff --git a/cpp/LunaHook/LunaHook/engine32/AdobeAir.cpp b/cpp/LunaHook/LunaHook/engine32/AdobeAir.cpp index 6fef2a54..6643041f 100644 --- a/cpp/LunaHook/LunaHook/engine32/AdobeAir.cpp +++ b/cpp/LunaHook/LunaHook/engine32/AdobeAir.cpp @@ -221,7 +221,7 @@ bool adobelair3() hp.filter_fun = [](TextBuffer *buffer, HookParam *hp) { // 若当前还有5个字符,则这个句子会显示5次,然后substr(1,len-1),直到结束,总共显示5+4+3+2+1次 - auto ws = StringToWideString(buffer->strA()); + auto ws = StringToWideString(buffer->viewA()); static int leng = 0; if (ws.length() <= leng) { diff --git a/cpp/LunaHook/LunaHook/engine32/Aksys.cpp b/cpp/LunaHook/LunaHook/engine32/Aksys.cpp index 9ff8411e..026521b6 100644 --- a/cpp/LunaHook/LunaHook/engine32/Aksys.cpp +++ b/cpp/LunaHook/LunaHook/engine32/Aksys.cpp @@ -55,7 +55,7 @@ namespace { StringFilter(buffer, "@1r", 3); StringFilter(buffer, "@-1r", 4); - if (!StringToWideString(buffer->strA(), 932).has_value()) + if (!StringToWideString(buffer->viewA(), 932).has_value()) buffer->clear(); }; return NewHook(hp, "Aksys"); diff --git a/cpp/LunaHook/LunaHook/engine32/RPGMakerRGSS3.cpp b/cpp/LunaHook/LunaHook/engine32/RPGMakerRGSS3.cpp index c3ba8ba2..32b5d67c 100644 --- a/cpp/LunaHook/LunaHook/engine32/RPGMakerRGSS3.cpp +++ b/cpp/LunaHook/LunaHook/engine32/RPGMakerRGSS3.cpp @@ -615,7 +615,7 @@ namespace auto arg = (HookArgument *)s->stack[0]; // arg1 if (arg && arg->isValid()) { // && (quint8)arg->text[0] > 127) { // skip translate text beginning with ascii character - std::wstring oldText = StringToWideString(std::string(arg->text, arg->size), CP_UTF8).value(), // QString::fromUtf8(arg->text, arg->size), + std::wstring oldText = StringToWideString(std::string_view(arg->text, arg->size), CP_UTF8).value(), // QString::fromUtf8(arg->text, arg->size), prefix, suffix, trimmedText = trim(oldText, &prefix, &suffix); @@ -664,7 +664,7 @@ namespace auto arg = (HookArgument *)s->stack[0]; // arg1 if (arg && arg->isValid()) { // && (quint8)arg->text[0] > 127) { // skip translate text beginning with ascii character - std::wstring oldText = StringToWideString(std::string(arg->text, arg->size), CP_UTF8).value(), // QString::fromUtf8(arg->text, arg->size), + std::wstring oldText = StringToWideString(std::string_view(arg->text, arg->size), CP_UTF8).value(), // QString::fromUtf8(arg->text, arg->size), prefix, suffix, trimmedText = trim(oldText, &prefix, &suffix); @@ -763,7 +763,7 @@ namespace auto arg = (HookArgument *)s->stack[2]; // arg2 if (arg->isValid()) { - auto oldText = StringToWideString(std::string(arg->text), CP_UTF8).value(); + auto oldText = StringToWideString(std::string_view(arg->text), CP_UTF8).value(); auto split = s->stack[0]; // return address buffer->from(oldText); // std::wstring newText = EngineController::instance()->dispatchTextWSTD(oldText, role, sig); @@ -780,7 +780,7 @@ namespace auto arg = (HookArgument *)s->stack[2]; // arg2 if (arg->isValid()) { - auto oldText = StringToWideString(std::string(arg->text), CP_UTF8).value(); + auto oldText = StringToWideString(std::string_view(arg->text), CP_UTF8).value(); auto split = s->stack[0]; // return address std::wstring old = oldText; diff --git a/cpp/LunaHook/LunaHook/engine32/Wolf.cpp b/cpp/LunaHook/LunaHook/engine32/Wolf.cpp index accbb348..3733463b 100644 --- a/cpp/LunaHook/LunaHook/engine32/Wolf.cpp +++ b/cpp/LunaHook/LunaHook/engine32/Wolf.cpp @@ -145,12 +145,12 @@ namespace void commonfilter(TextBuffer *buffer, HookParam *hp) { - auto str = buffer->strA(); + auto str = buffer->viewA(); bool checkchaos = WideStringToString(StringToWideString(str)) != str; if (checkchaos) return buffer->clear(); bool check1 = str.find("/") != str.npos || str.find("\\") != str.npos; - auto hashsuffix = [str]() + auto hashsuffix = [&]() { auto filterpath = { ".png", ".jpg", ".bmp", @@ -163,7 +163,7 @@ namespace return false; }; bool check2 = hashsuffix(); - bool check3 = all_ascii(str.c_str(), str.size()); + bool check3 = all_ascii(str.data(), str.size()); if (check1 && (check2 || check3)) return buffer->clear(); } diff --git a/cpp/LunaHook/LunaHook/engine64/vita3k.cpp b/cpp/LunaHook/LunaHook/engine64/vita3k.cpp index 826b0e8e..fcb89217 100644 --- a/cpp/LunaHook/LunaHook/engine64/vita3k.cpp +++ b/cpp/LunaHook/LunaHook/engine64/vita3k.cpp @@ -262,8 +262,7 @@ namespace } void PCSG00776(TextBuffer *buffer, HookParam *hp) { - auto s = buffer->strA(); - auto ws = StringToWideString(s, 932).value(); + auto ws = StringToWideString(buffer->viewA(), 932).value(); strReplace(ws, L"\x02", L""); Trim(ws); buffer->from(WideStringToString(ws)); @@ -436,20 +435,16 @@ namespace } void FPCSG00477(TextBuffer *buffer, HookParam *hp) { - auto s = buffer->strA(); - auto ws = StringToWideString(s, 932).value(); + auto ws = StringToWideString(buffer->viewA(), 932).value(); ws = std::regex_replace(ws, std::wregex(LR"(#n\u3000*)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(#\w.+?])"), L""); - s = WideStringToString(ws, 932); - buffer->from(s); + buffer->from(WideStringToString(ws, 932)); } void FPCSG00852(TextBuffer *buffer, HookParam *hp) { - auto s = buffer->strA(); - auto ws = StringToWideString(s, 932).value(); + auto ws = StringToWideString(buffer->viewA(), 932).value(); ws = std::regex_replace(ws, std::wregex(LR"(\^)"), L""); - s = WideStringToString(ws, 932); - buffer->from(s); + buffer->from(WideStringToString(ws, 932)); } void FPCSG01066(TextBuffer *buffer, HookParam *hp) { diff --git a/cpp/LunaHook/LunaHook/engine64/yuzu.cpp b/cpp/LunaHook/LunaHook/engine64/yuzu.cpp index 2c806317..fabf3323 100644 --- a/cpp/LunaHook/LunaHook/engine64/yuzu.cpp +++ b/cpp/LunaHook/LunaHook/engine64/yuzu.cpp @@ -638,8 +638,7 @@ namespace s = std::regex_replace(s, std::wregex(L"#T2[^#]+"), L""); s = std::regex_replace(s, std::wregex(L"#T\\d"), L""); } - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } void F010093800DB1C000(TextBuffer *buffer, HookParam *hp) { @@ -651,8 +650,7 @@ namespace s = std::regex_replace(s, std::wregex(L"\\#T2[^#]+"), L""); s = std::regex_replace(s, std::wregex(L"\\#T\\d"), L""); } - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } void F0100F7E00DFC8000(TextBuffer *buffer, HookParam *hp) { @@ -661,8 +659,7 @@ namespace s = std::regex_replace(s, std::wregex(L"#KW"), L""); s = std::regex_replace(s, std::wregex(L"#C\\(TR,0xff0000ff\\)"), L""); s = std::regex_replace(s, std::wregex(L"#P\\(.*\\)"), L""); - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } void F0100982015606000(TextBuffer *buffer, HookParam *hp) @@ -732,8 +729,7 @@ namespace auto s = utf32_to_utf16(buffer->viewU()); s = std::regex_replace(s, std::wregex(L"<[^>]+>"), L""); s = std::regex_replace(s, std::wregex(L"\n+"), L" "); - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } template void T01000BB01CB8A000(hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) @@ -1121,11 +1117,9 @@ namespace } void F0100E4000F616000(TextBuffer *buffer, HookParam *hp) { - auto s = buffer->strA(); - auto ws = StringToWideString(s, 932).value(); + auto ws = StringToWideString(buffer->viewA(), 932).value(); ws = std::regex_replace(ws, std::wregex(LR"(\\\w)"), L""); - s = WideStringToString(ws, 932); - buffer->from(s); + buffer->from(WideStringToString(ws, 932)); } void F01005A401D766000(TextBuffer *buffer, HookParam *hp) { @@ -1225,8 +1219,7 @@ namespace s = std::regex_replace(s, std::wregex(LR"(\#T\d)"), L""); if (s == L"  ") return buffer->clear(); - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } void F010021D01474E000(TextBuffer *buffer, HookParam *hp) { @@ -1238,8 +1231,7 @@ namespace if (last == s) return buffer->clear(); last = s; - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } void F010021D01474E000_2(TextBuffer *buffer, HookParam *hp) { @@ -1250,8 +1242,7 @@ namespace if (last == s) return buffer->clear(); last = s; - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } void F01002C00177AE000(TextBuffer *buffer, HookParam *hp) { @@ -1262,8 +1253,7 @@ namespace if (last == s) return buffer->clear(); last = s; - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } void F0100EA100DF92000(TextBuffer *buffer, HookParam *hp) { @@ -1582,8 +1572,7 @@ namespace auto s = utf32_to_utf16(buffer->viewU()); s = std::regex_replace(s, std::wregex(L"(.+?).+?"), L"$1"); s = std::regex_replace(s, std::wregex(L"\n+"), L" "); - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } void F0100771013FA8000(TextBuffer *buffer, HookParam *hp) { @@ -1768,8 +1757,7 @@ namespace s = std::regex_replace(s, std::wregex(L"【SW】"), L""); s = std::regex_replace(s, std::wregex(L"【SP】"), L""); s = std::regex_replace(s, std::wregex(L"#P\\(.*\\)"), L""); - auto u32 = utf16_to_utf32(s.c_str(), s.size()); - buffer->from(u32); + buffer->from(utf16_to_utf32(s)); } void F010061A01C1CE000(TextBuffer *buffer, HookParam *hp) { @@ -1854,15 +1842,13 @@ namespace template void F0100E5200D1A2000(TextBuffer *buffer, HookParam *hp) { - auto s = buffer->strA(); - auto ws = StringToWideString(s, 932).value(); + auto ws = StringToWideString(buffer->viewA(), 932).value(); ws = std::regex_replace(ws, std::wregex(LR"((\\n)+)"), L" "); ws = std::regex_replace(ws, std::wregex(LR"(\\d$|^\@[a-z]+|#.*?#|\$)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(\u3000+)"), L""); if (choice) ws = std::regex_replace(ws, std::wregex(LR"(, ?\w+)"), L""); - s = WideStringToString(ws, 932); - buffer->from(s); + buffer->from(WideStringToString(ws, 932)); } void F010028D0148E6000_2(TextBuffer *buffer, HookParam *hp) { @@ -1900,16 +1886,14 @@ namespace template void F0100EFE0159C6000(TextBuffer *buffer, HookParam *hp) { - auto s = buffer->strA(); - auto ws = StringToWideString(s, 932).value(); + auto ws = StringToWideString(buffer->viewA(), 932).value(); ws = std::regex_replace(ws, std::wregex(LR"((\\n)+)"), L" "); ws = std::regex_replace(ws, std::wregex(LR"(\\d$|^\@[a-z]+|#.*?#|\$)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(\u3000+)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(@w|\\c)"), L""); if (choice) ws = std::regex_replace(ws, std::wregex(LR"(, ?\w+)"), L""); - s = WideStringToString(ws, 932); - buffer->from(s); + buffer->from(WideStringToString(ws, 932)); } void F0100FDB00AA80000(TextBuffer *buffer, HookParam *hp) diff --git a/cpp/LunaHook/LunaHook/engines/mages/mages.cpp b/cpp/LunaHook/LunaHook/engines/mages/mages.cpp index 1b7ecf06..b1e88ba7 100644 --- a/cpp/LunaHook/LunaHook/engines/mages/mages.cpp +++ b/cpp/LunaHook/LunaHook/engines/mages/mages.cpp @@ -1,354 +1,425 @@ -#include"mages/mages.h" +#include "mages/mages.h" -namespace mages{ - - std::map createTable(int _idx) { - ConsoleOutput("%d",_idx); - auto compound_charsA=LoadResData(std::vector{ - L"compound_chars_default", - L"compound_chars_Robotics_Notes_Elite", - L"compound_chars_Robotics_Notes_Dash", - L"", - L"", - L"", - L"compound_chars_SGHD", - }[_idx],L"COMPOUND_CHARS"); - auto charsetA=LoadResData(std::vector{ - L"charset_default", - L"charset_Robotics_Notes_Elite", - L"charset_Robotics_Notes_Dash", - L"charset_Famicom_Tantei_Club", - L"charset_SINce_Memories", - L"charset_SG_My_Darlings_Embrace", - L"charset_SG_Linear_Bounded_Phenogram", - L"charset_SGHD" - }[_idx],L"CHARSET"); +namespace mages +{ - - auto compound_chars=StringToWideString(compound_charsA); - auto charset=StringToWideString(charsetA); - strReplace(charset,L"\n",L""); - strReplace(charset,L"\r",L""); + std::map createTable(int _idx) + { + ConsoleOutput("%d", _idx); + auto compound_charsA = LoadResData(std::vector{ + L"compound_chars_default", + L"compound_chars_Robotics_Notes_Elite", + L"compound_chars_Robotics_Notes_Dash", + L"", + L"", + L"", + L"compound_chars_SGHD", + }[_idx], + L"COMPOUND_CHARS"); + auto charsetA = LoadResData(std::vector{ + L"charset_default", + L"charset_Robotics_Notes_Elite", + L"charset_Robotics_Notes_Dash", + L"charset_Famicom_Tantei_Club", + L"charset_SINce_Memories", + L"charset_SG_My_Darlings_Embrace", + L"charset_SG_Linear_Bounded_Phenogram", + L"charset_SGHD"}[_idx], + L"CHARSET"); + + auto compound_chars = StringToWideString(compound_charsA); + auto charset = StringToWideString(charsetA); + strReplace(charset, L"\n", L""); + strReplace(charset, L"\r", L""); std::map table = {}; - - for (auto line : strSplit(compound_chars, L"\n")) { + + for (auto line : strSplit(compound_chars, L"\n")) + { auto pair = strSplit(line, L"="); - if (pair.size() != 2) continue; + if (pair.size() != 2) + continue; auto key = pair[0].substr(1, pair[0].size() - 2); auto val = pair[1]; auto keys = strSplit(key, L"-"); - if (keys.size() == 1)keys.push_back(key); + if (keys.size() == 1) + keys.push_back(key); size_t _; auto start = std::stoi(keys[0], &_, 16); auto end = std::stoi(keys[1], &_, 16); - for (auto i = start; i <= end; i++) { + for (auto i = start; i <= end; i++) + { auto charCode = ((i & 0xFF) << 8) | i >> 8; // swap endian table[charCode] = val; } } - - + WORD charCode; - for (auto i = 0; i < charset.size(); i++) { + for (auto i = 0; i < charset.size(); i++) + { charCode = 0x8000 + i; charCode = ((charCode & 0xFF) << 8) | charCode >> 8; // swap endian (0x8001 -> 0x0180) table[charCode] = charset[i]; } return table; } - -std::wstring mages_decode(WORD charCode,int _idx) { - static auto table = createTable(_idx); - if (table.find(charCode) == table.end()) { - std::wstringstream _; - _ << std::hex << charCode; - return L"[" + _.str() + L"]"; - } - else { - return table[charCode]; - } -} -std::wstring readString(uintptr_t address,int _idx) { - auto edx=address; - std::wstring s = L"", bottom = L""; - while (1) { - auto c = *(BYTE*)edx; - if (c == 0xff)break; // terminated - if (c >= 0xb0) {// b4: next page? - edx += 1; - continue; + + std::wstring mages_decode(WORD charCode, int _idx) + { + static auto table = createTable(_idx); + if (table.find(charCode) == table.end()) + { + std::wstringstream _; + _ << std::hex << charCode; + return L"[" + _.str() + L"]"; } - if (c >= 0x80) {// readChar - auto charCode = *(WORD*)edx; - edx += 2; - s += mages_decode(charCode,_idx); + else + { + return table[charCode]; } - else {// readControl - edx += 1; - if (c == 0) { - s += L' '; + } + std::wstring readString(uintptr_t address, int _idx) + { + auto edx = address; + std::wstring s = L"", bottom = L""; + while (1) + { + auto c = *(BYTE *)edx; + if (c == 0xff) + break; // terminated + if (c >= 0xb0) + { // b4: next page? + edx += 1; + continue; } - else if (c == 1) {// speaker - bottom = L""; - while (1) + if (c >= 0x80) + { // readChar + auto charCode = *(WORD *)edx; + edx += 2; + s += mages_decode(charCode, _idx); + } + else + { // readControl + edx += 1; + if (c == 0) { - auto c2 = *(BYTE*)edx; - if (c2 == 2) { - edx += 1; break; + s += L' '; + } + else if (c == 1) + { // speaker + bottom = L""; + while (1) + { + auto c2 = *(BYTE *)edx; + if (c2 == 2) + { + edx += 1; + break; + } + else if (c2 < 0x20) + edx += 1; + else + { + auto charCode = *(WORD *)edx; + edx += 2; + bottom += mages_decode(charCode, _idx); + } } - else if (c2 < 0x20)edx += 1; - else { - auto charCode = *(WORD*)edx; - edx += 2; - bottom += mages_decode(charCode,_idx); + if (bottom.size()) + s = s + bottom + L": "; + } + else if (c == 2) + { // line + // do nothing -> back to readChar + } + else if (c == 4 || c == 0x15) + { // SetColor, EvaluateExpression => SKIP + ////if (c !== 4) console.warn('Warning: ', c, hexdump(address)); + // https://github.com/CommitteeOfZero/SciAdv.Net/blob/32489cd21921079975291dbdce9151ad66f1b06a/src/SciAdvNet.SC3/Text/SC3StringDecoder.cs#L98 + // https://github.com/CommitteeOfZero/SciAdv.Net/blob/32489cd21921079975291dbdce9151ad66f1b06a/src/SciAdvNet.SC3/Text/StringSegmentCodes.cs#L3 + // https://github.com/shiiion/steinsgate_textractor/blob/master/steinsgatetextractor/sg_text_extractor.cpp#L46 + auto token = *(BYTE *)edx; // BYTE token = read_single(cur_index); + if (!token) + { + edx += 1; // return cur_index + 1; + } + else + { + do + { + if (token & 0x80) + { + switch (token & 0x60) + { + case 0: + edx += 2; // cur_index += 2; + break; + case 0x20: + edx += 3; // cur_index += 3; + break; + case 0x40: + edx += 4; // cur_index += 4; + break; + case 0x60: + edx += 5; // cur_index += 5; + break; + default: + // impossible + break; + } + } + else + { + edx += 2; // cur_index += 2; + } + token = *(BYTE *)edx; // token = read_single(cur_index); + } while (token); } } - if(bottom.size()) s = s + bottom + L": "; - } - else if (c == 2) { // line - // do nothing -> back to readChar - } - else if (c == 4 || c == 0x15) { // SetColor, EvaluateExpression => SKIP - ////if (c !== 4) console.warn('Warning: ', c, hexdump(address)); - // https://github.com/CommitteeOfZero/SciAdv.Net/blob/32489cd21921079975291dbdce9151ad66f1b06a/src/SciAdvNet.SC3/Text/SC3StringDecoder.cs#L98 - // https://github.com/CommitteeOfZero/SciAdv.Net/blob/32489cd21921079975291dbdce9151ad66f1b06a/src/SciAdvNet.SC3/Text/StringSegmentCodes.cs#L3 - // https://github.com/shiiion/steinsgate_textractor/blob/master/steinsgatetextractor/sg_text_extractor.cpp#L46 - auto token = *(BYTE*)edx; // BYTE token = read_single(cur_index); - if (!token) { - edx +=1; // return cur_index + 1; - } - else { - do { - if (token & 0x80) { - switch (token & 0x60) { - case 0: - edx +=2 ; //cur_index += 2; - break; - case 0x20: - edx +=3; //cur_index += 3; - break; - case 0x40: - edx +=4; //cur_index += 4; - break; - case 0x60: - edx +=5; //cur_index += 5; - break; - default: - // impossible - break; - } - } else { - edx +=2; //cur_index += 2; - } - token = *(BYTE*)edx; //token = read_single(cur_index); - } while (token); - } - } - else if (c == 0x0C // SetFontSize - || c == 0x11 // SetTopMargin - || c == 0x12 // SetLeftMargin - || c == 0x13 // STT_GetHardcodedValue: https://github.com/CommitteeOfZero/impacto/blob/master/src/text.cpp#L43 - ) { - edx+=2; - } - else if (c == 9) { // ruby (09_text_0A_rubi_0B) - std::wstring rubi = L""; - bottom = L""; - while (true) { - auto c2 = *(BYTE*)edx; - if (c2 == 0x0A) { // rubi - edx+=1; - while (true) { - c2 = *(BYTE*)edx; - if (c2 == 0x0B) { // end rubi - // address = address.add(1); - break; // break lv2 loop - } - else if (c2 < 0x20) { // another control - edx+=1; - } - else { // rubi - auto charCode = *(WORD*)edx; - edx+=2; + else if (c == 0x0C // SetFontSize + || c == 0x11 // SetTopMargin + || c == 0x12 // SetLeftMargin + || c == 0x13 // STT_GetHardcodedValue: https://github.com/CommitteeOfZero/impacto/blob/master/src/text.cpp#L43 + ) + { + edx += 2; + } + else if (c == 9) + { // ruby (09_text_0A_rubi_0B) + std::wstring rubi = L""; + bottom = L""; + while (true) + { + auto c2 = *(BYTE *)edx; + if (c2 == 0x0A) + { // rubi + edx += 1; + while (true) + { + c2 = *(BYTE *)edx; + if (c2 == 0x0B) + { // end rubi + // address = address.add(1); + break; // break lv2 loop + } + else if (c2 < 0x20) + { // another control + edx += 1; + } + else + { // rubi + auto charCode = *(WORD *)edx; + edx += 2; - rubi += mages_decode(charCode,_idx); + rubi += mages_decode(charCode, _idx); + } + } // end while } - } // end while - } - else if (c2 == 0x0B) { // end rubi - edx+=1; - break; // break lv1 loop - } - else if (c2 < 0x20) { // another control (color?) - edx+=1; - } - else { // char (text) - auto charCode = *(WORD*)edx; - edx+=2; + else if (c2 == 0x0B) + { // end rubi + edx += 1; + break; // break lv1 loop + } + else if (c2 < 0x20) + { // another control (color?) + edx += 1; + } + else + { // char (text) + auto charCode = *(WORD *)edx; + edx += 2; - auto cc = mages_decode(charCode,_idx); - bottom += cc; - s += cc; + auto cc = mages_decode(charCode, _idx); + bottom += cc; + s += cc; + } + } + if (rubi != L"") + { + // console.log('rubi: ', rubi); + // console.log('char: ', bottom); + } + } + else + { + // do nothing (one byte control) } } - if (rubi != L"") { - //console.log('rubi: ', rubi); - //console.log('char: ', bottom); - } - } - else { - // do nothing (one byte control) } + return s; } - } - return s; -} } -namespace hookmages{ - - regs reg=regs::invalid; - int gametype=0; - -template -void SpecialHookMAGES(hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) +namespace hookmages { - auto edx = regof(reg,stack);//regof(edx, esp_base); - - auto s=mages::readString(edx,gametype); - if(filter){ - static std::wstring last=L""; - if(last==s)return; - last=s; + regs reg = regs::invalid; + int gametype = 0; + + template + void SpecialHookMAGES(hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) + { + auto edx = regof(reg, stack); // regof(edx, esp_base); + + auto s = mages::readString(edx, gametype); + + if (filter) + { + static std::wstring last = L""; + if (last == s) + return; + last = s; + } + buffer->from(s); } - buffer->from(s); -} -bool MAGES() { + bool MAGES() + { #ifndef _WIN64 - auto dialogSigOffset = 2; - BYTE dialogSig1 []={ - 0x85,XX,0x74,XX,0x83,XX,0x01,0x74,XX,0x83,XX,0x04,0x74,XX,0xc7,0x05,XX,XX,XX,XX,0x01,0x00,0x00,0x00 - }; - auto addr=MemDbg::findBytes(dialogSig1,sizeof(dialogSig1),processStartAddress,processStopAddress); - if(addr==0){ - dialogSigOffset = 3; - BYTE dialogSig2 []={ - 0x57,0x85,XX,0x74,XX,0x83,XX,0x01,0x74,XX,0x83,XX,0x04 - }; - addr=MemDbg::findBytes(dialogSig2,sizeof(dialogSig2),processStartAddress,processStopAddress); - - } - if(addr==0)return false; - auto pos = addr+dialogSigOffset; - //.text:00431D3F 74 16 jz short loc_431D57 - auto jzoff=*(BYTE*)(pos+1); - pos+=jzoff+2; - auto hookaddr=pos; - for(int i=0;i<0x200;i++){ - if(((*(BYTE*)(pos))==0x8a)){ - - switch(((*(BYTE*)(pos+1)))){ - // case 0:reg=pusha_eax_off;break; - //YU-NO - //.text:00431D63 89 0D 20 A9 BF 00 mov dword_BFA920, ecx - //在加载到内存后,有时变成89 0d 20 a9 8a 00,导致崩溃,且这个没有遇到过,故注释掉。 - case 3:reg=regs::ebx;break; - case 1:reg=regs::ecx;break; - case 2:reg=regs::edx;break; - case 6:reg=regs::esi;break; - case 7:reg=regs::edi;break; - default:reg=regs::invalid; + auto dialogSigOffset = 2; + BYTE dialogSig1[] = { + 0x85, XX, 0x74, XX, 0x83, XX, 0x01, 0x74, XX, 0x83, XX, 0x04, 0x74, XX, 0xc7, 0x05, XX, XX, XX, XX, 0x01, 0x00, 0x00, 0x00}; + auto addr = MemDbg::findBytes(dialogSig1, sizeof(dialogSig1), processStartAddress, processStopAddress); + if (addr == 0) + { + dialogSigOffset = 3; + BYTE dialogSig2[] = { + 0x57, 0x85, XX, 0x74, XX, 0x83, XX, 0x01, 0x74, XX, 0x83, XX, 0x04}; + addr = MemDbg::findBytes(dialogSig2, sizeof(dialogSig2), processStartAddress, processStopAddress); } - if(reg!=regs::invalid)break; + if (addr == 0) + return false; + auto pos = addr + dialogSigOffset; + //.text:00431D3F 74 16 jz short loc_431D57 + auto jzoff = *(BYTE *)(pos + 1); + pos += jzoff + 2; + auto hookaddr = pos; + for (int i = 0; i < 0x200; i++) + { + if (((*(BYTE *)(pos)) == 0x8a)) + { + + switch (((*(BYTE *)(pos + 1)))) + { + // case 0:reg=pusha_eax_off;break; + // YU-NO + //.text:00431D63 89 0D 20 A9 BF 00 mov dword_BFA920, ecx + // 在加载到内存后,有时变成89 0d 20 a9 8a 00,导致崩溃,且这个没有遇到过,故注释掉。 + case 3: + reg = regs::ebx; + break; + case 1: + reg = regs::ecx; + break; + case 2: + reg = regs::edx; + break; + case 6: + reg = regs::esi; + break; + case 7: + reg = regs::edi; + break; + default: + reg = regs::invalid; + } + if (reg != regs::invalid) + break; + } + pos += 1; } - pos+=1; - } - if(reg==regs::invalid)return false; - ConsoleOutput("%p",pos-processStartAddress); - switch(pos-processStartAddress){ - case 0x6e69b://SG My Darling's Embrace 破解版 - case 0x6e77b://SG My Darling's Embrace - gametype=5;break; - case 0x4ef60://STEINS;GATE: Linear Bounded Phenogram - gametype=6;break; - case 0x498b0://STEINS;GATE - gametype=7;break; - case 0x9f723://Robotics;Notes-Elite - gametype=1;break; - case 0xf70a6://Robotics;Notes-Dash - gametype=2;break; - + if (reg == regs::invalid) + return false; + ConsoleOutput("%p", pos - processStartAddress); + switch (pos - processStartAddress) + { + case 0x6e69b: // SG My Darling's Embrace 破解版 + case 0x6e77b: // SG My Darling's Embrace + gametype = 5; + break; + case 0x4ef60: // STEINS;GATE: Linear Bounded Phenogram + gametype = 6; + break; + case 0x498b0: // STEINS;GATE + gametype = 7; + break; + case 0x9f723: // Robotics;Notes-Elite + gametype = 1; + break; + case 0xf70a6: // Robotics;Notes-Dash + gametype = 2; + break; + default: - //YU-NO - //测试无效: - //Steins;Gate-0 - //Steins;Gate - //未测试: - //Steins;Gate-Elite - //Chaos;Child - //CHAOS;HEAD_NOAH - //Memories_Off_-Innocent_Fille - //Memories_Off_-Innocent_Fille-_for_Dearest - gametype=0; - } - //ConsoleOutput("%x",pos-processStartAddress); - HookParam hp; - //hp.address = hookaddr; - hp.address=hookaddr; - //想い出にかわる君 ~メモリーズオフ~ 想君:秋之回忆3在hookaddr上无法正确读取。 - //hookaddr上是没有重复的,pos上是都能读到但有重复。 - hp.text_fun = SpecialHookMAGES<0>; - hp.type = CODEC_UTF16 | USING_STRING|NO_CONTEXT; - auto _=NewHook(hp, "5pb_MAGES"); - hp.address=pos; - hp.text_fun = SpecialHookMAGES<1>; - _|=NewHook(hp, "5pb_MAGES"); - ConsoleOutput("%p %p",hookaddr,pos); - return _; + // YU-NO + // 测试无效: + // Steins;Gate-0 + // Steins;Gate + // 未测试: + // Steins;Gate-Elite + // Chaos;Child + // CHAOS;HEAD_NOAH + // Memories_Off_-Innocent_Fille + // Memories_Off_-Innocent_Fille-_for_Dearest + gametype = 0; + } + // ConsoleOutput("%x",pos-processStartAddress); + HookParam hp; + // hp.address = hookaddr; + hp.address = hookaddr; + // 想い出にかわる君 ~メモリーズオフ~ 想君:秋之回忆3在hookaddr上无法正确读取。 + // hookaddr上是没有重复的,pos上是都能读到但有重复。 + hp.text_fun = SpecialHookMAGES<0>; + hp.type = CODEC_UTF16 | USING_STRING | NO_CONTEXT; + auto _ = NewHook(hp, "5pb_MAGES"); + hp.address = pos; + hp.text_fun = SpecialHookMAGES<1>; + _ |= NewHook(hp, "5pb_MAGES"); + ConsoleOutput("%p %p", hookaddr, pos); + return _; #else - auto dialogSigOffset = 2; - BYTE dialogSig1 []={ - 0x85,XX,0x74,XX,0x41,0x83,XX,0x01,0x74,XX,0x41,0x83,XX,0x04,0x74,XX,0x41 - }; - auto addr=MemDbg::findBytes(dialogSig1,sizeof(dialogSig1),processStartAddress,processStopAddress); - ConsoleOutput("%p",addr); - if(addr==0)return false; - auto pos = addr+dialogSigOffset; - auto jzoff=*(BYTE*)(pos+1); - pos+=jzoff+2; - auto hookaddr=pos; - // - for(int i=0;i<0x200;i++){ - //.text:000000014004116B 0F B6 13 movzx edx, byte ptr [rbx] - //->rbx - if((((*(DWORD*)(pos))&0xffffff)==0x13b60f)){ - reg=regs::rbx;//rbx - //ConsoleOutput("%p",pos-processStartAddress); - break; + auto dialogSigOffset = 2; + BYTE dialogSig1[] = { + 0x85, XX, 0x74, XX, 0x41, 0x83, XX, 0x01, 0x74, XX, 0x41, 0x83, XX, 0x04, 0x74, XX, 0x41}; + auto addr = MemDbg::findBytes(dialogSig1, sizeof(dialogSig1), processStartAddress, processStopAddress); + ConsoleOutput("%p", addr); + if (addr == 0) + return false; + auto pos = addr + dialogSigOffset; + auto jzoff = *(BYTE *)(pos + 1); + pos += jzoff + 2; + auto hookaddr = pos; + // + for (int i = 0; i < 0x200; i++) + { + //.text:000000014004116B 0F B6 13 movzx edx, byte ptr [rbx] + //->rbx + if ((((*(DWORD *)(pos)) & 0xffffff) == 0x13b60f)) + { + reg = regs::rbx; // rbx + // ConsoleOutput("%p",pos-processStartAddress); + break; + } + pos += 1; } - pos+=1; - } - if(reg==regs::invalid)return false; - switch(pos-processStartAddress){ - - default: - //CHAOS;HEAD_NOAH - gametype=0; - } - HookParam hp; - hp.address=hookaddr; - hp.text_fun = SpecialHookMAGES<0>; - hp.type = CODEC_UTF16 | USING_STRING|NO_CONTEXT; - return NewHook(hp, "5pb_MAGES"); + if (reg == regs::invalid) + return false; + switch (pos - processStartAddress) + { + default: + // CHAOS;HEAD_NOAH + gametype = 0; + } + HookParam hp; + hp.address = hookaddr; + hp.text_fun = SpecialHookMAGES<0>; + hp.type = CODEC_UTF16 | USING_STRING | NO_CONTEXT; + return NewHook(hp, "5pb_MAGES"); #endif -} - + } } \ No newline at end of file diff --git a/cpp/LunaHook/LunaHook/engines/ppsspp/specialgames.hpp b/cpp/LunaHook/LunaHook/engines/ppsspp/specialgames.hpp index 35acf9e6..43cc0009 100644 --- a/cpp/LunaHook/LunaHook/engines/ppsspp/specialgames.hpp +++ b/cpp/LunaHook/LunaHook/engines/ppsspp/specialgames.hpp @@ -88,8 +88,7 @@ namespace ppsspp void NPJH50909_filter(TextBuffer *buffer, HookParam *hp) { - std::string result = buffer->strA(); - auto ws = StringToWideString(result, 932).value(); + auto ws = StringToWideString(buffer->viewA(), 932).value(); // Remove single line markers ws = std::regex_replace(ws, std::wregex(L"(\\%N)+"), L" "); @@ -240,7 +239,7 @@ namespace ppsspp void N(TextBuffer *buffer, HookParam *) { auto current1 = buffer->strA(); - if(current == current1) + if (current == current1) buffer->clear(); } } diff --git a/cpp/LunaHook/LunaHook/util/dyncodec/dynsjiscodec.cc b/cpp/LunaHook/LunaHook/util/dyncodec/dynsjiscodec.cc index 04d9f144..329d1b14 100644 --- a/cpp/LunaHook/LunaHook/util/dyncodec/dynsjiscodec.cc +++ b/cpp/LunaHook/LunaHook/util/dyncodec/dynsjiscodec.cc @@ -165,14 +165,14 @@ std::wstring DynamicShiftJISCodecPrivate::decode(const char* data, size_t length if (ch <= 127) ret.push_back(ch); else if (ch >= 0xa1 && ch <= 0xdf) // size == 1 - ret.append(StringToWideString(std::string(data + 1, 1), codepage).value()); + ret.append(StringToWideString(std::string_view(data + 1, 1), codepage).value()); else { if (i + 1 == length) // no enough character return ret; UINT8 ch2 = (UINT8)data[++i]; if ((ch >= 0x81 && ch <= 0x9f || ch >= 0xe0 && ch <= 0xef) && (ch2 != 0x7f && ch2 >= 0x40 && ch2 <= 0xfc)) - ret.append(StringToWideString(std::string(data + i - 1, 2), codepage).value()); + ret.append(StringToWideString(std::string_view(data + i - 1, 2), codepage).value()); else if (wchar_t c = decodeChar(ch, ch2)) { ret.push_back(c); if (dynamic) diff --git a/cpp/LunaHook/LunaHost/GUI/LunaHost.cpp b/cpp/LunaHook/LunaHost/GUI/LunaHost.cpp index 6c70c82f..4c6a6f5c 100644 --- a/cpp/LunaHook/LunaHost/GUI/LunaHost.cpp +++ b/cpp/LunaHook/LunaHost/GUI/LunaHost.cpp @@ -132,7 +132,7 @@ void LunaHost::on_proc_connect(DWORD pid) std::string name = safequeryjson(savedhookcontext[u8procname], "name", std::string()); if (startWith(name, "UserHook")) { - if (auto hp = HookCode::Parse(StringToWideString(savedhookcontext[u8procname]["hookcode"]))) + if (auto hp = HookCode::Parse(StringToWideString(std::string_view(savedhookcontext[u8procname]["hookcode"])))) Host::InsertHook(pid, hp.value()); } } diff --git a/cpp/LunaHook/include/stringutils.cpp b/cpp/LunaHook/include/stringutils.cpp index 94f1919d..fbc6ca24 100644 --- a/cpp/LunaHook/include/stringutils.cpp +++ b/cpp/LunaHook/include/stringutils.cpp @@ -94,8 +94,12 @@ typedef HRESULT(WINAPI *CONVERTINETUNICODETOMULTIBYTE)( LPINT lpnWideCharCount, LPSTR lpDstStr, LPINT lpnMultiCharCount); - std::optional StringToWideString(const std::string &text, UINT encoding) +{ + return StringToWideString(std::string_view(text), encoding); +} + +std::optional StringToWideString(std::string_view text, UINT encoding) { std::vector buffer(text.size() + 1); if (disable_mbwc) @@ -108,7 +112,7 @@ std::optional StringToWideString(const std::string &text, UINT enc auto ConvertINetMultiByteToUnicode = (CONVERTINETMULTIBYTETOUNICODE)GetProcAddress(h, "ConvertINetMultiByteToUnicode"); if (ConvertINetMultiByteToUnicode == 0) return {}; - auto hr = ConvertINetMultiByteToUnicode(0, encoding, text.c_str(), &_s, buffer.data(), &_s2); + auto hr = ConvertINetMultiByteToUnicode(0, encoding, text.data(), &_s, buffer.data(), &_s2); if (SUCCEEDED(hr)) { return std::wstring(buffer.data(), _s2); @@ -118,7 +122,7 @@ std::optional StringToWideString(const std::string &text, UINT enc } else { - if (int length = MultiByteToWideChar(encoding, 0, text.c_str(), text.size() + 1, buffer.data(), buffer.size())) + if (int length = MultiByteToWideChar(encoding, 0, text.data(), text.size() + 1, buffer.data(), buffer.size())) return std::wstring(buffer.data(), length - 1); return {}; } @@ -128,8 +132,30 @@ std::wstring StringToWideString(const std::string &text) { return StringToWideString(text, CP_UTF8).value(); } +std::wstring StringToWideString(std::string_view text) +{ + return StringToWideString(text, CP_UTF8).value(); +} +std::optional StringToWideString(const char *text, UINT encoding) +{ + return StringToWideString(std::string_view(text), encoding); +} + +std::wstring StringToWideString(const char *text) +{ + return StringToWideString(std::string_view(text)); +} std::string WideStringToString(const std::wstring &text, UINT cp) +{ + return WideStringToString(std::wstring_view(text), cp); +} + +std::string WideStringToString(const wchar_t *text, UINT cp) +{ + return WideStringToString(std::wstring_view(text), cp); +} +std::string WideStringToString(std::wstring_view text, UINT cp) { std::vector buffer((text.size() + 1) * 4); if (disable_wcmb) @@ -142,7 +168,7 @@ std::string WideStringToString(const std::wstring &text, UINT cp) auto ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddress(h, "ConvertINetUnicodeToMultiByte"); if (ConvertINetUnicodeToMultiByte == 0) return {}; - auto hr = ConvertINetUnicodeToMultiByte(0, cp, text.c_str(), &_s, buffer.data(), &_s2); + auto hr = ConvertINetUnicodeToMultiByte(0, cp, text.data(), &_s, buffer.data(), &_s2); if (SUCCEEDED(hr)) { return std::string(buffer.data(), _s2); @@ -152,7 +178,7 @@ std::string WideStringToString(const std::wstring &text, UINT cp) } else { - WideCharToMultiByte(cp, 0, text.c_str(), -1, buffer.data(), buffer.size(), nullptr, nullptr); + WideCharToMultiByte(cp, 0, text.data(), -1, buffer.data(), buffer.size(), nullptr, nullptr); return buffer.data(); } } @@ -171,16 +197,16 @@ inline unsigned int convertUTF32ToUTF16(unsigned int cUTF32, unsigned int &h, un return ret; } -std::basic_string utf16_to_utf32(const wchar_t *u16str, size_t size) +u32string utf16_to_utf32(std::wstring_view wsv) { - std::basic_string utf32String; - for (size_t i = 0; i < size; i++) + u32string utf32String; + for (size_t i = 0; i < wsv.size(); i++) { - auto u16c = u16str[i]; + auto u16c = wsv[i]; if (u16c - 0xd800u < 2048u) - if ((u16c & 0xfffffc00 == 0xd800) && (i < size - 1) && (u16str[i + 1] & 0xfffffc00 == 0xdc00)) + if ((u16c & 0xfffffc00 == 0xd800) && (i < wsv.size() - 1) && (wsv[i + 1] & 0xfffffc00 == 0xdc00)) { - utf32String += (u16c << 10) + u16str[i + 1] - 0x35fdc00; + utf32String += (u16c << 10) + wsv[i + 1] - 0x35fdc00; i += 1; } else @@ -188,12 +214,12 @@ std::basic_string utf16_to_utf32(const wchar_t *u16str, size_t size) // error invalid u16 char } else - utf32String += u16str[i]; + utf32String += wsv[i]; } return utf32String; } -std::wstring utf32_to_utf16(std::basic_string_view sv) +std::wstring utf32_to_utf16(u32string_view sv) { std::wstring u16str; for (auto i = 0; i < sv.size(); i++) @@ -284,9 +310,9 @@ std::optional commonparsestring(void *data, size_t length, void *p if (hp->type & CODEC_UTF16) return std::wstring((wchar_t *)data, length / sizeof(wchar_t)); else if (hp->type & CODEC_UTF32) - return (std::move(utf32_to_utf16(std::basic_string_view((uint32_t *)data, length / sizeof(uint32_t))))); + return utf32_to_utf16(u32string_view((uint32_t *)data, length / sizeof(uint32_t))); else if (auto converted = StringToWideString(std::string((char *)data, length), (hp->type & CODEC_UTF8) ? CP_UTF8 : (hp->codepage ? hp->codepage : df))) - return (converted.value()); + return converted.value(); else return {}; } \ No newline at end of file diff --git a/cpp/LunaHook/include/stringutils.h b/cpp/LunaHook/include/stringutils.h index 3c57b5b2..03a58fb3 100644 --- a/cpp/LunaHook/include/stringutils.h +++ b/cpp/LunaHook/include/stringutils.h @@ -1,6 +1,8 @@ #ifndef __LUNA_STRINGUILTS_H #define __LUNA_STRINGUILTS_H +using u32string = std::basic_string; +using u32string_view = std::basic_string_view; enum { VNR_TEXT_CAPACITY = 1500 @@ -26,12 +28,19 @@ bool startWith(const std::wstring_view &s, const std::wstring_view &s2); bool endWith(const std::string_view &s, const std::string_view &s2); bool endWith(const std::wstring_view &s, const std::wstring_view &s2); -std::wstring utf32_to_utf16(std::basic_string_view sv); -std::basic_string utf16_to_utf32(const wchar_t *u16str, size_t size); +std::wstring utf32_to_utf16(u32string_view sv); +u32string utf16_to_utf32(std::wstring_view); std::string WideStringToString(const std::wstring &text, UINT cp = CP_UTF8); +std::string WideStringToString(std::wstring_view text, UINT cp = CP_UTF8); +std::string WideStringToString(const wchar_t *, UINT cp = CP_UTF8); + std::wstring StringToWideString(const std::string &text); +std::wstring StringToWideString(std::string_view); +std::wstring StringToWideString(const char *); std::optional StringToWideString(const std::string &text, UINT encoding); +std::optional StringToWideString(std::string_view text, UINT encoding); +std::optional StringToWideString(const char *, UINT encoding); std::string wcasta(const std::wstring &x); std::wstring acastw(const std::string &x);