This commit is contained in:
恍兮惚兮 2024-11-06 21:39:52 +08:00
parent b13bcdc5aa
commit 810f333770
12 changed files with 457 additions and 373 deletions

View File

@ -221,7 +221,7 @@ bool adobelair3()
hp.filter_fun = [](TextBuffer *buffer, HookParam *hp) hp.filter_fun = [](TextBuffer *buffer, HookParam *hp)
{ {
// 若当前还有5个字符则这个句子会显示5次然后substr(1,len-1)直到结束总共显示5+4+3+2+1次 // 若当前还有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; static int leng = 0;
if (ws.length() <= leng) if (ws.length() <= leng)
{ {

View File

@ -55,7 +55,7 @@ namespace
{ {
StringFilter(buffer, "@1r", 3); StringFilter(buffer, "@1r", 3);
StringFilter(buffer, "@-1r", 4); StringFilter(buffer, "@-1r", 4);
if (!StringToWideString(buffer->strA(), 932).has_value()) if (!StringToWideString(buffer->viewA(), 932).has_value())
buffer->clear(); buffer->clear();
}; };
return NewHook(hp, "Aksys"); return NewHook(hp, "Aksys");

View File

@ -615,7 +615,7 @@ namespace
auto arg = (HookArgument *)s->stack[0]; // arg1 auto arg = (HookArgument *)s->stack[0]; // arg1
if (arg && arg->isValid()) if (arg && arg->isValid())
{ // && (quint8)arg->text[0] > 127) { // skip translate text beginning with ascii character { // && (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, prefix,
suffix, suffix,
trimmedText = trim(oldText, &prefix, &suffix); trimmedText = trim(oldText, &prefix, &suffix);
@ -664,7 +664,7 @@ namespace
auto arg = (HookArgument *)s->stack[0]; // arg1 auto arg = (HookArgument *)s->stack[0]; // arg1
if (arg && arg->isValid()) if (arg && arg->isValid())
{ // && (quint8)arg->text[0] > 127) { // skip translate text beginning with ascii character { // && (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, prefix,
suffix, suffix,
trimmedText = trim(oldText, &prefix, &suffix); trimmedText = trim(oldText, &prefix, &suffix);
@ -763,7 +763,7 @@ namespace
auto arg = (HookArgument *)s->stack[2]; // arg2 auto arg = (HookArgument *)s->stack[2]; // arg2
if (arg->isValid()) 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 auto split = s->stack[0]; // return address
buffer->from(oldText); buffer->from(oldText);
// std::wstring newText = EngineController::instance()->dispatchTextWSTD(oldText, role, sig); // std::wstring newText = EngineController::instance()->dispatchTextWSTD(oldText, role, sig);
@ -780,7 +780,7 @@ namespace
auto arg = (HookArgument *)s->stack[2]; // arg2 auto arg = (HookArgument *)s->stack[2]; // arg2
if (arg->isValid()) 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 auto split = s->stack[0]; // return address
std::wstring old = oldText; std::wstring old = oldText;

View File

@ -145,12 +145,12 @@ namespace
void commonfilter(TextBuffer *buffer, HookParam *hp) void commonfilter(TextBuffer *buffer, HookParam *hp)
{ {
auto str = buffer->strA(); auto str = buffer->viewA();
bool checkchaos = WideStringToString(StringToWideString(str)) != str; bool checkchaos = WideStringToString(StringToWideString(str)) != str;
if (checkchaos) if (checkchaos)
return buffer->clear(); return buffer->clear();
bool check1 = str.find("/") != str.npos || str.find("\\") != str.npos; bool check1 = str.find("/") != str.npos || str.find("\\") != str.npos;
auto hashsuffix = [str]() auto hashsuffix = [&]()
{ {
auto filterpath = { auto filterpath = {
".png", ".jpg", ".bmp", ".png", ".jpg", ".bmp",
@ -163,7 +163,7 @@ namespace
return false; return false;
}; };
bool check2 = hashsuffix(); bool check2 = hashsuffix();
bool check3 = all_ascii(str.c_str(), str.size()); bool check3 = all_ascii(str.data(), str.size());
if (check1 && (check2 || check3)) if (check1 && (check2 || check3))
return buffer->clear(); return buffer->clear();
} }

View File

@ -262,8 +262,7 @@ namespace
} }
void PCSG00776(TextBuffer *buffer, HookParam *hp) void PCSG00776(TextBuffer *buffer, HookParam *hp)
{ {
auto s = buffer->strA(); auto ws = StringToWideString(buffer->viewA(), 932).value();
auto ws = StringToWideString(s, 932).value();
strReplace(ws, L"\x02", L""); strReplace(ws, L"\x02", L"");
Trim(ws); Trim(ws);
buffer->from(WideStringToString(ws)); buffer->from(WideStringToString(ws));
@ -436,20 +435,16 @@ namespace
} }
void FPCSG00477(TextBuffer *buffer, HookParam *hp) void FPCSG00477(TextBuffer *buffer, HookParam *hp)
{ {
auto s = buffer->strA(); auto ws = StringToWideString(buffer->viewA(), 932).value();
auto ws = StringToWideString(s, 932).value();
ws = std::regex_replace(ws, std::wregex(LR"(#n\u3000*)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(#n\u3000*)"), L"");
ws = std::regex_replace(ws, std::wregex(LR"(#\w.+?])"), L""); ws = std::regex_replace(ws, std::wregex(LR"(#\w.+?])"), L"");
s = WideStringToString(ws, 932); buffer->from(WideStringToString(ws, 932));
buffer->from(s);
} }
void FPCSG00852(TextBuffer *buffer, HookParam *hp) void FPCSG00852(TextBuffer *buffer, HookParam *hp)
{ {
auto s = buffer->strA(); auto ws = StringToWideString(buffer->viewA(), 932).value();
auto ws = StringToWideString(s, 932).value();
ws = std::regex_replace(ws, std::wregex(LR"(\^)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(\^)"), L"");
s = WideStringToString(ws, 932); buffer->from(WideStringToString(ws, 932));
buffer->from(s);
} }
void FPCSG01066(TextBuffer *buffer, HookParam *hp) void FPCSG01066(TextBuffer *buffer, HookParam *hp)
{ {

View File

@ -638,8 +638,7 @@ namespace
s = std::regex_replace(s, std::wregex(L"#T2[^#]+"), L""); s = std::regex_replace(s, std::wregex(L"#T2[^#]+"), L"");
s = std::regex_replace(s, std::wregex(L"#T\\d"), L""); s = std::regex_replace(s, std::wregex(L"#T\\d"), L"");
} }
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
void F010093800DB1C000(TextBuffer *buffer, HookParam *hp) 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"\\#T2[^#]+"), L"");
s = std::regex_replace(s, std::wregex(L"\\#T\\d"), L""); s = std::regex_replace(s, std::wregex(L"\\#T\\d"), L"");
} }
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
void F0100F7E00DFC8000(TextBuffer *buffer, HookParam *hp) 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"#KW"), L"");
s = std::regex_replace(s, std::wregex(L"#C\\(TR,0xff0000ff\\)"), L""); s = std::regex_replace(s, std::wregex(L"#C\\(TR,0xff0000ff\\)"), L"");
s = std::regex_replace(s, std::wregex(L"#P\\(.*\\)"), L""); s = std::regex_replace(s, std::wregex(L"#P\\(.*\\)"), L"");
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
void F0100982015606000(TextBuffer *buffer, HookParam *hp) void F0100982015606000(TextBuffer *buffer, HookParam *hp)
@ -732,8 +729,7 @@ namespace
auto s = utf32_to_utf16(buffer->viewU()); auto s = utf32_to_utf16(buffer->viewU());
s = std::regex_replace(s, std::wregex(L"<[^>]+>"), L""); s = std::regex_replace(s, std::wregex(L"<[^>]+>"), L"");
s = std::regex_replace(s, std::wregex(L"\n+"), L" "); s = std::regex_replace(s, std::wregex(L"\n+"), L" ");
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
template <int index> template <int index>
void T01000BB01CB8A000(hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) void T01000BB01CB8A000(hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split)
@ -1121,11 +1117,9 @@ namespace
} }
void F0100E4000F616000(TextBuffer *buffer, HookParam *hp) void F0100E4000F616000(TextBuffer *buffer, HookParam *hp)
{ {
auto s = buffer->strA(); auto ws = StringToWideString(buffer->viewA(), 932).value();
auto ws = StringToWideString(s, 932).value();
ws = std::regex_replace(ws, std::wregex(LR"(\\\w)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(\\\w)"), L"");
s = WideStringToString(ws, 932); buffer->from(WideStringToString(ws, 932));
buffer->from(s);
} }
void F01005A401D766000(TextBuffer *buffer, HookParam *hp) void F01005A401D766000(TextBuffer *buffer, HookParam *hp)
{ {
@ -1225,8 +1219,7 @@ namespace
s = std::regex_replace(s, std::wregex(LR"(\#T\d)"), L""); s = std::regex_replace(s, std::wregex(LR"(\#T\d)"), L"");
if (s == L"  ") if (s == L"  ")
return buffer->clear(); return buffer->clear();
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
void F010021D01474E000(TextBuffer *buffer, HookParam *hp) void F010021D01474E000(TextBuffer *buffer, HookParam *hp)
{ {
@ -1238,8 +1231,7 @@ namespace
if (last == s) if (last == s)
return buffer->clear(); return buffer->clear();
last = s; last = s;
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
void F010021D01474E000_2(TextBuffer *buffer, HookParam *hp) void F010021D01474E000_2(TextBuffer *buffer, HookParam *hp)
{ {
@ -1250,8 +1242,7 @@ namespace
if (last == s) if (last == s)
return buffer->clear(); return buffer->clear();
last = s; last = s;
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
void F01002C00177AE000(TextBuffer *buffer, HookParam *hp) void F01002C00177AE000(TextBuffer *buffer, HookParam *hp)
{ {
@ -1262,8 +1253,7 @@ namespace
if (last == s) if (last == s)
return buffer->clear(); return buffer->clear();
last = s; last = s;
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
void F0100EA100DF92000(TextBuffer *buffer, HookParam *hp) void F0100EA100DF92000(TextBuffer *buffer, HookParam *hp)
{ {
@ -1582,8 +1572,7 @@ namespace
auto s = utf32_to_utf16(buffer->viewU()); auto s = utf32_to_utf16(buffer->viewU());
s = std::regex_replace(s, std::wregex(L"<rb>(.+?)</rb><rt>.+?</rt>"), L"$1"); s = std::regex_replace(s, std::wregex(L"<rb>(.+?)</rb><rt>.+?</rt>"), L"$1");
s = std::regex_replace(s, std::wregex(L"\n+"), L" "); s = std::regex_replace(s, std::wregex(L"\n+"), L" ");
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
void F0100771013FA8000(TextBuffer *buffer, HookParam *hp) 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"【SW】"), L"");
s = std::regex_replace(s, std::wregex(L"【SP】"), L""); s = std::regex_replace(s, std::wregex(L"【SP】"), L"");
s = std::regex_replace(s, std::wregex(L"#P\\(.*\\)"), L""); s = std::regex_replace(s, std::wregex(L"#P\\(.*\\)"), L"");
auto u32 = utf16_to_utf32(s.c_str(), s.size()); buffer->from(utf16_to_utf32(s));
buffer->from(u32);
} }
void F010061A01C1CE000(TextBuffer *buffer, HookParam *hp) void F010061A01C1CE000(TextBuffer *buffer, HookParam *hp)
{ {
@ -1854,15 +1842,13 @@ namespace
template <bool choice> template <bool choice>
void F0100E5200D1A2000(TextBuffer *buffer, HookParam *hp) void F0100E5200D1A2000(TextBuffer *buffer, HookParam *hp)
{ {
auto s = buffer->strA(); auto ws = StringToWideString(buffer->viewA(), 932).value();
auto ws = StringToWideString(s, 932).value();
ws = std::regex_replace(ws, std::wregex(LR"((\\n)+)"), L" "); 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"(\\d$|^\@[a-z]+|#.*?#|\$)"), L"");
ws = std::regex_replace(ws, std::wregex(LR"(\u3000+)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(\u3000+)"), L"");
if (choice) if (choice)
ws = std::regex_replace(ws, std::wregex(LR"(, ?\w+)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(, ?\w+)"), L"");
s = WideStringToString(ws, 932); buffer->from(WideStringToString(ws, 932));
buffer->from(s);
} }
void F010028D0148E6000_2(TextBuffer *buffer, HookParam *hp) void F010028D0148E6000_2(TextBuffer *buffer, HookParam *hp)
{ {
@ -1900,16 +1886,14 @@ namespace
template <bool choice> template <bool choice>
void F0100EFE0159C6000(TextBuffer *buffer, HookParam *hp) void F0100EFE0159C6000(TextBuffer *buffer, HookParam *hp)
{ {
auto s = buffer->strA(); auto ws = StringToWideString(buffer->viewA(), 932).value();
auto ws = StringToWideString(s, 932).value();
ws = std::regex_replace(ws, std::wregex(LR"((\\n)+)"), L" "); 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"(\\d$|^\@[a-z]+|#.*?#|\$)"), L"");
ws = std::regex_replace(ws, std::wregex(LR"(\u3000+)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(\u3000+)"), L"");
ws = std::regex_replace(ws, std::wregex(LR"(@w|\\c)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(@w|\\c)"), L"");
if (choice) if (choice)
ws = std::regex_replace(ws, std::wregex(LR"(, ?\w+)"), L""); ws = std::regex_replace(ws, std::wregex(LR"(, ?\w+)"), L"");
s = WideStringToString(ws, 932); buffer->from(WideStringToString(ws, 932));
buffer->from(s);
} }
void F0100FDB00AA80000(TextBuffer *buffer, HookParam *hp) void F0100FDB00AA80000(TextBuffer *buffer, HookParam *hp)

View File

@ -1,8 +1,10 @@
#include "mages/mages.h" #include "mages/mages.h"
namespace mages{ namespace mages
{
std::map<WORD, std::wstring> createTable(int _idx) { std::map<WORD, std::wstring> createTable(int _idx)
{
ConsoleOutput("%d", _idx); ConsoleOutput("%d", _idx);
auto compound_charsA = LoadResData(std::vector<const wchar_t *>{ auto compound_charsA = LoadResData(std::vector<const wchar_t *>{
L"compound_chars_default", L"compound_chars_default",
@ -12,7 +14,8 @@ namespace mages{
L"", L"",
L"", L"",
L"compound_chars_SGHD", L"compound_chars_SGHD",
}[_idx],L"COMPOUND_CHARS"); }[_idx],
L"COMPOUND_CHARS");
auto charsetA = LoadResData(std::vector<const wchar_t *>{ auto charsetA = LoadResData(std::vector<const wchar_t *>{
L"charset_default", L"charset_default",
L"charset_Robotics_Notes_Elite", L"charset_Robotics_Notes_Elite",
@ -21,9 +24,8 @@ namespace mages{
L"charset_SINce_Memories", L"charset_SINce_Memories",
L"charset_SG_My_Darlings_Embrace", L"charset_SG_My_Darlings_Embrace",
L"charset_SG_Linear_Bounded_Phenogram", L"charset_SG_Linear_Bounded_Phenogram",
L"charset_SGHD" L"charset_SGHD"}[_idx],
}[_idx],L"CHARSET"); L"CHARSET");
auto compound_chars = StringToWideString(compound_charsA); auto compound_chars = StringToWideString(compound_charsA);
auto charset = StringToWideString(charsetA); auto charset = StringToWideString(charsetA);
@ -31,25 +33,29 @@ namespace mages{
strReplace(charset, L"\r", L""); strReplace(charset, L"\r", L"");
std::map<WORD, std::wstring> table = {}; std::map<WORD, std::wstring> table = {};
for (auto line : strSplit(compound_chars, L"\n")) { for (auto line : strSplit(compound_chars, L"\n"))
{
auto pair = strSplit(line, L"="); 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 key = pair[0].substr(1, pair[0].size() - 2);
auto val = pair[1]; auto val = pair[1];
auto keys = strSplit(key, L"-"); auto keys = strSplit(key, L"-");
if (keys.size() == 1)keys.push_back(key); if (keys.size() == 1)
keys.push_back(key);
size_t _; size_t _;
auto start = std::stoi(keys[0], &_, 16); auto start = std::stoi(keys[0], &_, 16);
auto end = std::stoi(keys[1], &_, 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 auto charCode = ((i & 0xFF) << 8) | i >> 8; // swap endian
table[charCode] = val; table[charCode] = val;
} }
} }
WORD charCode; WORD charCode;
for (auto i = 0; i < charset.size(); i++) { for (auto i = 0; i < charset.size(); i++)
{
charCode = 0x8000 + i; charCode = 0x8000 + i;
charCode = ((charCode & 0xFF) << 8) | charCode >> 8; // swap endian (0x8001 -> 0x0180) charCode = ((charCode & 0xFF) << 8) | charCode >> 8; // swap endian (0x8001 -> 0x0180)
table[charCode] = charset[i]; table[charCode] = charset[i];
@ -57,70 +63,93 @@ namespace mages{
return table; return table;
} }
std::wstring mages_decode(WORD charCode,int _idx) { std::wstring mages_decode(WORD charCode, int _idx)
{
static auto table = createTable(_idx); static auto table = createTable(_idx);
if (table.find(charCode) == table.end()) { if (table.find(charCode) == table.end())
{
std::wstringstream _; std::wstringstream _;
_ << std::hex << charCode; _ << std::hex << charCode;
return L"[" + _.str() + L"]"; return L"[" + _.str() + L"]";
} }
else { else
{
return table[charCode]; return table[charCode];
} }
} }
std::wstring readString(uintptr_t address,int _idx) { std::wstring readString(uintptr_t address, int _idx)
{
auto edx = address; auto edx = address;
std::wstring s = L"", bottom = L""; std::wstring s = L"", bottom = L"";
while (1) { while (1)
{
auto c = *(BYTE *)edx; auto c = *(BYTE *)edx;
if (c == 0xff)break; // terminated if (c == 0xff)
if (c >= 0xb0) {// b4: next page? break; // terminated
if (c >= 0xb0)
{ // b4: next page?
edx += 1; edx += 1;
continue; continue;
} }
if (c >= 0x80) {// readChar if (c >= 0x80)
{ // readChar
auto charCode = *(WORD *)edx; auto charCode = *(WORD *)edx;
edx += 2; edx += 2;
s += mages_decode(charCode, _idx); s += mages_decode(charCode, _idx);
} }
else {// readControl else
{ // readControl
edx += 1; edx += 1;
if (c == 0) { if (c == 0)
{
s += L' '; s += L' ';
} }
else if (c == 1) {// speaker else if (c == 1)
{ // speaker
bottom = L""; bottom = L"";
while (1) while (1)
{ {
auto c2 = *(BYTE *)edx; auto c2 = *(BYTE *)edx;
if (c2 == 2) { if (c2 == 2)
edx += 1; break; {
edx += 1;
break;
} }
else if (c2 < 0x20)edx += 1; else if (c2 < 0x20)
else { edx += 1;
else
{
auto charCode = *(WORD *)edx; auto charCode = *(WORD *)edx;
edx += 2; edx += 2;
bottom += mages_decode(charCode, _idx); bottom += mages_decode(charCode, _idx);
} }
} }
if(bottom.size()) s = s + bottom + L": "; if (bottom.size())
s = s + bottom + L": ";
} }
else if (c == 2) { // line else if (c == 2)
{ // line
// do nothing -> back to readChar // do nothing -> back to readChar
} }
else if (c == 4 || c == 0x15) { // SetColor, EvaluateExpression => SKIP else if (c == 4 || c == 0x15)
{ // SetColor, EvaluateExpression => SKIP
////if (c !== 4) console.warn('Warning: ', c, hexdump(address)); ////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/SC3StringDecoder.cs#L98
// https://github.com/CommitteeOfZero/SciAdv.Net/blob/32489cd21921079975291dbdce9151ad66f1b06a/src/SciAdvNet.SC3/Text/StringSegmentCodes.cs#L3 // 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 // https://github.com/shiiion/steinsgate_textractor/blob/master/steinsgatetextractor/sg_text_extractor.cpp#L46
auto token = *(BYTE *)edx; // BYTE token = read_single<BYTE>(cur_index); auto token = *(BYTE *)edx; // BYTE token = read_single<BYTE>(cur_index);
if (!token) { if (!token)
{
edx += 1; // return cur_index + 1; edx += 1; // return cur_index + 1;
} }
else { else
do { {
if (token & 0x80) { do
switch (token & 0x60) { {
if (token & 0x80)
{
switch (token & 0x60)
{
case 0: case 0:
edx += 2; // cur_index += 2; edx += 2; // cur_index += 2;
break; break;
@ -137,7 +166,9 @@ std::wstring readString(uintptr_t address,int _idx) {
// impossible // impossible
break; break;
} }
} else { }
else
{
edx += 2; // cur_index += 2; edx += 2; // cur_index += 2;
} }
token = *(BYTE *)edx; // token = read_single<BYTE>(cur_index); token = *(BYTE *)edx; // token = read_single<BYTE>(cur_index);
@ -148,26 +179,34 @@ std::wstring readString(uintptr_t address,int _idx) {
|| c == 0x11 // SetTopMargin || c == 0x11 // SetTopMargin
|| c == 0x12 // SetLeftMargin || c == 0x12 // SetLeftMargin
|| c == 0x13 // STT_GetHardcodedValue: https://github.com/CommitteeOfZero/impacto/blob/master/src/text.cpp#L43 || c == 0x13 // STT_GetHardcodedValue: https://github.com/CommitteeOfZero/impacto/blob/master/src/text.cpp#L43
) { )
{
edx += 2; edx += 2;
} }
else if (c == 9) { // ruby (09_text_0A_rubi_0B) else if (c == 9)
{ // ruby (09_text_0A_rubi_0B)
std::wstring rubi = L""; std::wstring rubi = L"";
bottom = L""; bottom = L"";
while (true) { while (true)
{
auto c2 = *(BYTE *)edx; auto c2 = *(BYTE *)edx;
if (c2 == 0x0A) { // rubi if (c2 == 0x0A)
{ // rubi
edx += 1; edx += 1;
while (true) { while (true)
{
c2 = *(BYTE *)edx; c2 = *(BYTE *)edx;
if (c2 == 0x0B) { // end rubi if (c2 == 0x0B)
{ // end rubi
// address = address.add(1); // address = address.add(1);
break; // break lv2 loop break; // break lv2 loop
} }
else if (c2 < 0x20) { // another control else if (c2 < 0x20)
{ // another control
edx += 1; edx += 1;
} }
else { // rubi else
{ // rubi
auto charCode = *(WORD *)edx; auto charCode = *(WORD *)edx;
edx += 2; edx += 2;
@ -175,14 +214,17 @@ std::wstring readString(uintptr_t address,int _idx) {
} }
} // end while } // end while
} }
else if (c2 == 0x0B) { // end rubi else if (c2 == 0x0B)
{ // end rubi
edx += 1; edx += 1;
break; // break lv1 loop break; // break lv1 loop
} }
else if (c2 < 0x20) { // another control (color?) else if (c2 < 0x20)
{ // another control (color?)
edx += 1; edx += 1;
} }
else { // char (text) else
{ // char (text)
auto charCode = *(WORD *)edx; auto charCode = *(WORD *)edx;
edx += 2; edx += 2;
@ -191,12 +233,14 @@ std::wstring readString(uintptr_t address,int _idx) {
s += cc; s += cc;
} }
} }
if (rubi != L"") { if (rubi != L"")
{
// console.log('rubi: ', rubi); // console.log('rubi: ', rubi);
// console.log('char: ', bottom); // console.log('char: ', bottom);
} }
} }
else { else
{
// do nothing (one byte control) // do nothing (one byte control)
} }
} }
@ -206,7 +250,8 @@ std::wstring readString(uintptr_t address,int _idx) {
} }
namespace hookmages{ namespace hookmages
{
regs reg = regs::invalid; regs reg = regs::invalid;
int gametype = 0; int gametype = 0;
@ -218,68 +263,92 @@ void SpecialHookMAGES(hook_stack *stack, HookParam *hp, TextBuffer *buffer, uint
auto s = mages::readString(edx, gametype); auto s = mages::readString(edx, gametype);
if(filter){ if (filter)
{
static std::wstring last = L""; static std::wstring last = L"";
if(last==s)return; if (last == s)
return;
last = s; last = s;
} }
buffer->from(s); buffer->from(s);
} }
bool MAGES() { bool MAGES()
{
#ifndef _WIN64 #ifndef _WIN64
auto dialogSigOffset = 2; auto dialogSigOffset = 2;
BYTE dialogSig1[] = { 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 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); auto addr = MemDbg::findBytes(dialogSig1, sizeof(dialogSig1), processStartAddress, processStopAddress);
if(addr==0){ if (addr == 0)
{
dialogSigOffset = 3; dialogSigOffset = 3;
BYTE dialogSig2[] = { BYTE dialogSig2[] = {
0x57,0x85,XX,0x74,XX,0x83,XX,0x01,0x74,XX,0x83,XX,0x04 0x57, 0x85, XX, 0x74, XX, 0x83, XX, 0x01, 0x74, XX, 0x83, XX, 0x04};
};
addr = MemDbg::findBytes(dialogSig2, sizeof(dialogSig2), processStartAddress, processStopAddress); addr = MemDbg::findBytes(dialogSig2, sizeof(dialogSig2), processStartAddress, processStopAddress);
} }
if(addr==0)return false; if (addr == 0)
return false;
auto pos = addr + dialogSigOffset; auto pos = addr + dialogSigOffset;
//.text:00431D3F 74 16 jz short loc_431D57 //.text:00431D3F 74 16 jz short loc_431D57
auto jzoff = *(BYTE *)(pos + 1); auto jzoff = *(BYTE *)(pos + 1);
pos += jzoff + 2; pos += jzoff + 2;
auto hookaddr = pos; auto hookaddr = pos;
for(int i=0;i<0x200;i++){ for (int i = 0; i < 0x200; i++)
if(((*(BYTE*)(pos))==0x8a)){ {
if (((*(BYTE *)(pos)) == 0x8a))
{
switch(((*(BYTE*)(pos+1)))){ switch (((*(BYTE *)(pos + 1))))
{
// case 0:reg=pusha_eax_off;break; // case 0:reg=pusha_eax_off;break;
// YU-NO // YU-NO
//.text:00431D63 89 0D 20 A9 BF 00 mov dword_BFA920, ecx //.text:00431D63 89 0D 20 A9 BF 00 mov dword_BFA920, ecx
// 在加载到内存后有时变成89 0d 20 a9 8a 00导致崩溃且这个没有遇到过故注释掉。 // 在加载到内存后有时变成89 0d 20 a9 8a 00导致崩溃且这个没有遇到过故注释掉。
case 3:reg=regs::ebx;break; case 3:
case 1:reg=regs::ecx;break; reg = regs::ebx;
case 2:reg=regs::edx;break; break;
case 6:reg=regs::esi;break; case 1:
case 7:reg=regs::edi;break; reg = regs::ecx;
default:reg=regs::invalid; 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; if (reg != regs::invalid)
break;
} }
pos += 1; pos += 1;
} }
if(reg==regs::invalid)return false; if (reg == regs::invalid)
return false;
ConsoleOutput("%p", pos - processStartAddress); ConsoleOutput("%p", pos - processStartAddress);
switch(pos-processStartAddress){ switch (pos - processStartAddress)
{
case 0x6e69b: // SG My Darling's Embrace 破解版 case 0x6e69b: // SG My Darling's Embrace 破解版
case 0x6e77b: // SG My Darling's Embrace case 0x6e77b: // SG My Darling's Embrace
gametype=5;break; gametype = 5;
break;
case 0x4ef60: // STEINS;GATE: Linear Bounded Phenogram case 0x4ef60: // STEINS;GATE: Linear Bounded Phenogram
gametype=6;break; gametype = 6;
break;
case 0x498b0: // STEINS;GATE case 0x498b0: // STEINS;GATE
gametype=7;break; gametype = 7;
break;
case 0x9f723: // Robotics;Notes-Elite case 0x9f723: // Robotics;Notes-Elite
gametype=1;break; gametype = 1;
break;
case 0xf70a6: // Robotics;Notes-Dash case 0xf70a6: // Robotics;Notes-Dash
gametype=2;break; gametype = 2;
break;
default: default:
// YU-NO // YU-NO
@ -313,28 +382,32 @@ bool MAGES() {
auto dialogSigOffset = 2; auto dialogSigOffset = 2;
BYTE dialogSig1[] = { BYTE dialogSig1[] = {
0x85,XX,0x74,XX,0x41,0x83,XX,0x01,0x74,XX,0x41,0x83,XX,0x04,0x74,XX,0x41 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); auto addr = MemDbg::findBytes(dialogSig1, sizeof(dialogSig1), processStartAddress, processStopAddress);
ConsoleOutput("%p", addr); ConsoleOutput("%p", addr);
if(addr==0)return false; if (addr == 0)
return false;
auto pos = addr + dialogSigOffset; auto pos = addr + dialogSigOffset;
auto jzoff = *(BYTE *)(pos + 1); auto jzoff = *(BYTE *)(pos + 1);
pos += jzoff + 2; pos += jzoff + 2;
auto hookaddr = pos; auto hookaddr = pos;
// //
for(int i=0;i<0x200;i++){ for (int i = 0; i < 0x200; i++)
{
//.text:000000014004116B 0F B6 13 movzx edx, byte ptr [rbx] //.text:000000014004116B 0F B6 13 movzx edx, byte ptr [rbx]
//->rbx //->rbx
if((((*(DWORD*)(pos))&0xffffff)==0x13b60f)){ if ((((*(DWORD *)(pos)) & 0xffffff) == 0x13b60f))
{
reg = regs::rbx; // rbx reg = regs::rbx; // rbx
// ConsoleOutput("%p",pos-processStartAddress); // ConsoleOutput("%p",pos-processStartAddress);
break; break;
} }
pos += 1; pos += 1;
} }
if(reg==regs::invalid)return false; if (reg == regs::invalid)
switch(pos-processStartAddress){ return false;
switch (pos - processStartAddress)
{
default: default:
// CHAOS;HEAD_NOAH // CHAOS;HEAD_NOAH
@ -346,9 +419,7 @@ bool MAGES() {
hp.type = CODEC_UTF16 | USING_STRING | NO_CONTEXT; hp.type = CODEC_UTF16 | USING_STRING | NO_CONTEXT;
return NewHook(hp, "5pb_MAGES"); return NewHook(hp, "5pb_MAGES");
#endif #endif
} }
} }

View File

@ -88,8 +88,7 @@ namespace ppsspp
void NPJH50909_filter(TextBuffer *buffer, HookParam *hp) void NPJH50909_filter(TextBuffer *buffer, HookParam *hp)
{ {
std::string result = buffer->strA(); auto ws = StringToWideString(buffer->viewA(), 932).value();
auto ws = StringToWideString(result, 932).value();
// Remove single line markers // Remove single line markers
ws = std::regex_replace(ws, std::wregex(L"(\\%N)+"), L" "); ws = std::regex_replace(ws, std::wregex(L"(\\%N)+"), L" ");

View File

@ -165,14 +165,14 @@ std::wstring DynamicShiftJISCodecPrivate::decode(const char* data, size_t length
if (ch <= 127) if (ch <= 127)
ret.push_back(ch); ret.push_back(ch);
else if (ch >= 0xa1 && ch <= 0xdf) // size == 1 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 { else {
if (i + 1 == length) // no enough character if (i + 1 == length) // no enough character
return ret; return ret;
UINT8 ch2 = (UINT8)data[++i]; UINT8 ch2 = (UINT8)data[++i];
if ((ch >= 0x81 && ch <= 0x9f || ch >= 0xe0 && ch <= 0xef) if ((ch >= 0x81 && ch <= 0x9f || ch >= 0xe0 && ch <= 0xef)
&& (ch2 != 0x7f && ch2 >= 0x40 && ch2 <= 0xfc)) && (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)) { else if (wchar_t c = decodeChar(ch, ch2)) {
ret.push_back(c); ret.push_back(c);
if (dynamic) if (dynamic)

View File

@ -132,7 +132,7 @@ void LunaHost::on_proc_connect(DWORD pid)
std::string name = safequeryjson(savedhookcontext[u8procname], "name", std::string()); std::string name = safequeryjson(savedhookcontext[u8procname], "name", std::string());
if (startWith(name, "UserHook")) 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()); Host::InsertHook(pid, hp.value());
} }
} }

View File

@ -94,8 +94,12 @@ typedef HRESULT(WINAPI *CONVERTINETUNICODETOMULTIBYTE)(
LPINT lpnWideCharCount, LPINT lpnWideCharCount,
LPSTR lpDstStr, LPSTR lpDstStr,
LPINT lpnMultiCharCount); LPINT lpnMultiCharCount);
std::optional<std::wstring> StringToWideString(const std::string &text, UINT encoding) std::optional<std::wstring> StringToWideString(const std::string &text, UINT encoding)
{
return StringToWideString(std::string_view(text), encoding);
}
std::optional<std::wstring> StringToWideString(std::string_view text, UINT encoding)
{ {
std::vector<wchar_t> buffer(text.size() + 1); std::vector<wchar_t> buffer(text.size() + 1);
if (disable_mbwc) if (disable_mbwc)
@ -108,7 +112,7 @@ std::optional<std::wstring> StringToWideString(const std::string &text, UINT enc
auto ConvertINetMultiByteToUnicode = (CONVERTINETMULTIBYTETOUNICODE)GetProcAddress(h, "ConvertINetMultiByteToUnicode"); auto ConvertINetMultiByteToUnicode = (CONVERTINETMULTIBYTETOUNICODE)GetProcAddress(h, "ConvertINetMultiByteToUnicode");
if (ConvertINetMultiByteToUnicode == 0) if (ConvertINetMultiByteToUnicode == 0)
return {}; 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)) if (SUCCEEDED(hr))
{ {
return std::wstring(buffer.data(), _s2); return std::wstring(buffer.data(), _s2);
@ -118,7 +122,7 @@ std::optional<std::wstring> StringToWideString(const std::string &text, UINT enc
} }
else 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 std::wstring(buffer.data(), length - 1);
return {}; return {};
} }
@ -128,8 +132,30 @@ std::wstring StringToWideString(const std::string &text)
{ {
return StringToWideString(text, CP_UTF8).value(); return StringToWideString(text, CP_UTF8).value();
} }
std::wstring StringToWideString(std::string_view text)
{
return StringToWideString(text, CP_UTF8).value();
}
std::optional<std::wstring> 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) 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<char> buffer((text.size() + 1) * 4); std::vector<char> buffer((text.size() + 1) * 4);
if (disable_wcmb) if (disable_wcmb)
@ -142,7 +168,7 @@ std::string WideStringToString(const std::wstring &text, UINT cp)
auto ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddress(h, "ConvertINetUnicodeToMultiByte"); auto ConvertINetUnicodeToMultiByte = (CONVERTINETUNICODETOMULTIBYTE)GetProcAddress(h, "ConvertINetUnicodeToMultiByte");
if (ConvertINetUnicodeToMultiByte == 0) if (ConvertINetUnicodeToMultiByte == 0)
return {}; 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)) if (SUCCEEDED(hr))
{ {
return std::string(buffer.data(), _s2); return std::string(buffer.data(), _s2);
@ -152,7 +178,7 @@ std::string WideStringToString(const std::wstring &text, UINT cp)
} }
else 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(); return buffer.data();
} }
} }
@ -171,16 +197,16 @@ inline unsigned int convertUTF32ToUTF16(unsigned int cUTF32, unsigned int &h, un
return ret; return ret;
} }
std::basic_string<uint32_t> utf16_to_utf32(const wchar_t *u16str, size_t size) u32string utf16_to_utf32(std::wstring_view wsv)
{ {
std::basic_string<uint32_t> utf32String; u32string utf32String;
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < wsv.size(); i++)
{ {
auto u16c = u16str[i]; auto u16c = wsv[i];
if (u16c - 0xd800u < 2048u) 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; i += 1;
} }
else else
@ -188,12 +214,12 @@ std::basic_string<uint32_t> utf16_to_utf32(const wchar_t *u16str, size_t size)
// error invalid u16 char // error invalid u16 char
} }
else else
utf32String += u16str[i]; utf32String += wsv[i];
} }
return utf32String; return utf32String;
} }
std::wstring utf32_to_utf16(std::basic_string_view<uint32_t> sv) std::wstring utf32_to_utf16(u32string_view sv)
{ {
std::wstring u16str; std::wstring u16str;
for (auto i = 0; i < sv.size(); i++) for (auto i = 0; i < sv.size(); i++)
@ -284,9 +310,9 @@ std::optional<std::wstring> commonparsestring(void *data, size_t length, void *p
if (hp->type & CODEC_UTF16) if (hp->type & CODEC_UTF16)
return std::wstring((wchar_t *)data, length / sizeof(wchar_t)); return std::wstring((wchar_t *)data, length / sizeof(wchar_t));
else if (hp->type & CODEC_UTF32) else if (hp->type & CODEC_UTF32)
return (std::move(utf32_to_utf16(std::basic_string_view<uint32_t>((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))) 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 else
return {}; return {};
} }

View File

@ -1,6 +1,8 @@
#ifndef __LUNA_STRINGUILTS_H #ifndef __LUNA_STRINGUILTS_H
#define __LUNA_STRINGUILTS_H #define __LUNA_STRINGUILTS_H
using u32string = std::basic_string<uint32_t>;
using u32string_view = std::basic_string_view<uint32_t>;
enum enum
{ {
VNR_TEXT_CAPACITY = 1500 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::string_view &s, const std::string_view &s2);
bool endWith(const std::wstring_view &s, const std::wstring_view &s2); bool endWith(const std::wstring_view &s, const std::wstring_view &s2);
std::wstring utf32_to_utf16(std::basic_string_view<uint32_t> sv); std::wstring utf32_to_utf16(u32string_view sv);
std::basic_string<uint32_t> utf16_to_utf32(const wchar_t *u16str, size_t size); u32string utf16_to_utf32(std::wstring_view);
std::string WideStringToString(const std::wstring &text, UINT cp = CP_UTF8); 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(const std::string &text);
std::wstring StringToWideString(std::string_view);
std::wstring StringToWideString(const char *);
std::optional<std::wstring> StringToWideString(const std::string &text, UINT encoding); std::optional<std::wstring> StringToWideString(const std::string &text, UINT encoding);
std::optional<std::wstring> StringToWideString(std::string_view text, UINT encoding);
std::optional<std::wstring> StringToWideString(const char *, UINT encoding);
std::string wcasta(const std::wstring &x); std::string wcasta(const std::wstring &x);
std::wstring acastw(const std::string &x); std::wstring acastw(const std::string &x);