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)
{
// 若当前还有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)
{

View File

@ -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");

View File

@ -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;

View File

@ -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();
}

View File

@ -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)
{

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"#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 <int index>
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"<rb>(.+?)</rb><rt>.+?</rt>"), 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 <bool choice>
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 <bool choice>
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)

View File

@ -1,354 +1,425 @@
#include"mages/mages.h"
#include "mages/mages.h"
namespace mages{
std::map<WORD, std::wstring> createTable(int _idx) {
ConsoleOutput("%d",_idx);
auto compound_charsA=LoadResData(std::vector<const wchar_t*>{
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<const wchar_t*>{
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<WORD, std::wstring> createTable(int _idx)
{
ConsoleOutput("%d", _idx);
auto compound_charsA = LoadResData(std::vector<const wchar_t *>{
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<const wchar_t *>{
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<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"=");
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<BYTE>(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<BYTE>(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<BYTE>(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<BYTE>(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<int filter>
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 <int filter>
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
}
}
}

View File

@ -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();
}
}

View File

@ -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)

View File

@ -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());
}
}

View File

@ -94,8 +94,12 @@ typedef HRESULT(WINAPI *CONVERTINETUNICODETOMULTIBYTE)(
LPINT lpnWideCharCount,
LPSTR lpDstStr,
LPINT lpnMultiCharCount);
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);
if (disable_mbwc)
@ -108,7 +112,7 @@ std::optional<std::wstring> 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<std::wstring> 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<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)
{
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);
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<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;
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<uint32_t> 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<uint32_t> 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<std::wstring> 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>((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 {};
}

View File

@ -1,6 +1,8 @@
#ifndef __LUNA_STRINGUILTS_H
#define __LUNA_STRINGUILTS_H
using u32string = std::basic_string<uint32_t>;
using u32string_view = std::basic_string_view<uint32_t>;
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<uint32_t> sv);
std::basic_string<uint32_t> 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<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::wstring acastw(const std::string &x);