This commit is contained in:
恍兮惚兮 2024-10-03 14:53:59 +08:00
parent 1016b82df0
commit 163835bec9
61 changed files with 4928 additions and 3780 deletions

View File

@ -61,7 +61,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
include(generate_product_version)
set(VERSION_MAJOR 3)
set(VERSION_MINOR 13)
set(VERSION_MINOR 14)
set(VERSION_PATCH 0)
set(VERSION_REVISION 0)

View File

@ -1,6 +1,6 @@
include_directories(. util engines)
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
set(enginessrc MKXPZ Ryujinx livecaptions Kincaid vita3k rpcs3 yuzusuyu TYPEMOON ENTERGRAM AGES7 mono Godot 5pb lucasystem LightVN V8 pchooks Artemis KiriKiri YOX PPSSPP CMVS Suika2 )
set(enginessrc MKXPZ Ryujinx livecaptions Kincaid vita3k rpcs3 yuzu TYPEMOON ENTERGRAM AGES7 mono Godot 5pb lucasystem LightVN V8 pchooks Artemis KiriKiri YOX PPSSPP CMVS Suika2 )
set(enginepath "engine64")
set(collector "enginecollection64.cpp")
else()

View File

@ -1,18 +1,22 @@
#include "5pb.h"
#include "mages/mages.h"
namespace{
namespace
{
// https://vndb.org/v46553
// 新宿葬命
bool _strncat(){
bool _strncat()
{
HookParam hp;
hp.address = (uintptr_t)GetProcAddress(GetModuleHandleA("ucrtbase.dll"), "strncat");
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
*data = stack->ARG2;
*len = stack->ARG3;
*split = stack->ARG1;
};
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
strReplace(s, "%N", "\n");
// sub_140096E80
@ -22,7 +26,8 @@ namespace{
return NewHook(hp, "strncat");
}
}
bool _5pb::attach_function() {
bool _5pb::attach_function()
{
// CHAOS;HEAD_NOAH
bool b3 = hookmages::MAGES();
return b3 || _strncat();

View File

@ -1,13 +1,13 @@
class _5pb:public ENGINE{
class _5pb : public ENGINE
{
public:
_5pb(){
_5pb()
{
is_engine_certain = false;
check_by = CHECK_BY::FILE_ANY;
check_by_target = check_by_list{L"data\\*.cpk", L"*.cpk"};
};
bool attach_function();
};

View File

@ -1,22 +1,28 @@
#include "AGES7.h"
namespace{
namespace
{
// Muv-Luv Alternative - Total Eclipse
// https://vndb.org/v7052
bool _1(){
bool _1()
{
// HSN65001#-44@234699:te-win64vc14-release.exe
BYTE b1[] = {
//clang-format off
0x48, XX2, 0xb0, 0xfe, 0xff, 0xff,
0x4c, XX2, 0xb8, 0x01, 0x00, 0x00,
//clang-format on
};
auto addr = MemDbg::findBytes(b1, sizeof(b1), processStartAddress, processStopAddress);
if(addr==0)return false;
if (addr == 0)
return false;
HookParam hp;
hp.address = addr;
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
hp.offset = get_reg(regs::rdi);
auto succ = NewHook(hp, "Ages7_1");
if(addr=MemDbg::findEnclosingAlignedFunction(addr)){
if (addr = MemDbg::findEnclosingAlignedFunction(addr))
{
hp.address = addr;
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
hp.offset = get_reg(regs::rbx);
@ -24,22 +30,27 @@ namespace{
}
return succ;
}
bool _2(){
bool _2()
{
// HSN65001#-44@2346AC:te-win64vc14-release.exe
BYTE b1[] = {
//clang-format off
0x48, XX2, 0x10,
0x48, XX2, 0xb0, 0x01, 0x00, 0x00,
XX2, 0xc0, 0x08, 0x00, 0x00
//clang-format on
};
auto addr = MemDbg::findBytes(b1, sizeof(b1), processStartAddress, processStopAddress);
if(addr==0)return false;
if (addr == 0)
return false;
HookParam hp;
hp.address = addr;
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
hp.offset = get_reg(regs::rdi);
auto suc = NewHook(hp, "Ages7_2");
if(addr=MemDbg::findEnclosingAlignedFunction(addr)){
if (addr = MemDbg::findEnclosingAlignedFunction(addr))
{
hp.address = addr;
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
hp.offset = get_reg(regs::rbx);
@ -47,9 +58,11 @@ namespace{
}
return suc;
}
bool _3(){
bool _3()
{
// HSN65001#-14@3D9814:te-win64vc14-release.exe
BYTE b1[] = {
//clang-format off
0x48, 0x8b, 0x1b,
0x48, 0x8b, 0x01,
0x48, 0x8b, 0xd3,
@ -59,22 +72,26 @@ namespace{
0x48, 0x2b, 0xc1,
0x48, 0xc1, 0xf8, 0x03,
0x48, 0x85, 0xc0,
//clang-format on
};
auto addr = MemDbg::findBytes(b1, sizeof(b1), processStartAddress, processStopAddress);
if(addr==0)return false;
if (addr == 0)
return false;
HookParam hp;
hp.address = addr + 3;
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
hp.offset = get_reg(regs::rbx);
return NewHook(hp, "Ages7_4");
}
bool all(){
bool all()
{
auto _ = _1();
_ = _2() || _;
_ = _3() || _;
return _;
}
}
bool AGES7::attach_function(){
bool AGES7::attach_function()
{
return all();
}

View File

@ -1,12 +1,13 @@
class AGES7:public ENGINE{
class AGES7 : public ENGINE
{
public:
AGES7(){
AGES7()
{
check_by = CHECK_BY::FILE_ALL;
check_by_target = check_by_list{L"obb\\pack.bin", L"erc_nospfx.dll"};
};
bool attach_function();
};

View File

@ -1,8 +1,10 @@
class Artemis:public ENGINE{
class Artemis : public ENGINE
{
public:
Artemis(){
Artemis()
{
check_by = CHECK_BY::FILE;
check_by_target = L"*.pfs";

View File

@ -1,30 +1,38 @@
#include "CMVS.h"
namespace{
bool EMbed(){
namespace
{
bool EMbed()
{
// 有多个,但是只有最后一个是有效的
const uint8_t bytes[] = {
//clang-format off
0xB8, 0x42, 0x81, 0x00, 0x00,
0x66, XX2, 0x74, XX,
0xB8, 0x76, 0x81, 0x00, 0x00,
0x66, XX2, 0x74, XX,
0xB8, 0x78, 0x81, 0x00, 0x00,
0x66, XX2, 0x74, XX,
//clang-format on
};
bool res = false;
auto addr = processStartAddress;
std::vector<uintptr_t> already;
while(addr){
while (addr)
{
addr = MemDbg::findBytes(bytes, sizeof(bytes), addr + 1, processStopAddress);
if(addr==0)continue;
if (addr == 0)
continue;
auto f = MemDbg::findEnclosingAlignedFunction(addr);
if(f==0)continue;
if(std::find(already.begin(),already.end(),f)!=already.end())continue;
if (f == 0)
continue;
if (std::find(already.begin(), already.end(), f) != already.end())
continue;
already.push_back(f);
}
if(already.size()){
if (already.size())
{
HookParam hp;
hp.address = already.back();
hp.offset = get_reg(regs::rdx);
@ -36,11 +44,13 @@ bool EMbed(){
return res;
}
bool CMVSh() {
bool CMVSh()
{
DWORD align = 0xCCCCCCCC;
auto addr = MemDbg::findCallerAddress((uintptr_t)::GetGlyphOutlineA, align, processStartAddress, processStopAddress);
if (!addr) return false;
if (!addr)
return false;
HookParam hp;
hp.address = addr + 4;
@ -50,7 +60,8 @@ bool CMVSh() {
return NewHook(hp, "CMVS");
}
}
bool CMVS::attach_function(){
bool CMVS::attach_function()
{
bool b1 = CMVSh();
bool b2 = EMbed();
return b1 || b2;

View File

@ -1,13 +1,14 @@
class CMVS:public ENGINE{
class CMVS : public ENGINE
{
public:
CMVS(){
CMVS()
{
check_by = CHECK_BY::FILE;
check_by_target = L"data\\pack\\*.cpz";
// jichi 8/19/2013: DO NOT WORK for games like「ハピメア」
// if (wcsstr(str,L"cmvs32") || wcsstr(str,L"cmvs64")) {
// InsertCMVSHook();

View File

@ -1,10 +1,12 @@
#include "Godot.h"
bool InsertGodotHook_X64() {
bool InsertGodotHook_X64()
{
const BYTE bytes[] = {0x8B, 0x40, 0xFC, 0x83, 0xF8, 0x01, 0x83, 0xD0, 0xFF, 0x41, 0x39, 0xC6};
ULONG64 range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range)) {
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range))
{
HookParam myhp;
myhp.address = addr;
@ -16,7 +18,8 @@ bool InsertGodotHook_X64() {
{
*data = (stack->rax);
int len = *(int *)(*data - 4);
if(len!=wcslen((wchar_t*)*data))return;
if (len != wcslen((wchar_t *)*data))
return;
*count = len * 2;
};
char nameForUser[HOOK_NAME_SIZE] = "RichTextLabel_add_text";
@ -28,7 +31,8 @@ bool InsertGodotHook_X64() {
ConsoleOutput("Godot_x64: pattern not found");
return false;
}
bool InsertGodotHook2_X64() {
bool InsertGodotHook2_X64()
{
/*
* Sample games:
@ -45,7 +49,8 @@ bool InsertGodotHook2_X64() {
};
ULONG64 range = min(processStopAddress - processStartAddress, X64_MAX_REL_ADDR);
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range)) {
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range))
{
HookParam hp;
hp.address = addr;
hp.offset = get_reg(regs::rcx);
@ -57,7 +62,8 @@ bool InsertGodotHook2_X64() {
ConsoleOutput("Godot2_x64: pattern not found");
return false;
}
bool Godot::attach_function(){
bool Godot::attach_function()
{
auto _ = InsertGodotHook_X64();
_ = InsertGodotHook2_X64() || _;
return _;

View File

@ -1,8 +1,10 @@
class Godot:public ENGINE{
class Godot : public ENGINE
{
public:
Godot(){
Godot()
{
check_by = CHECK_BY::FILE;
check_by_target = L"*.pck";

View File

@ -1,6 +1,8 @@
#include "Kincaid.h"
namespace{
bool _1(){
namespace
{
bool _1()
{
// .text:0000000140230D80 mov rsi, rax
// .text:0000000140230D83 mov edx, 1
// .text:0000000140230D88 mov rcx, rdi
@ -17,15 +19,16 @@ namespace{
0x8d, 0x58, 0xff,
0xba, 0x02, 0x00, 0x00, 0x00,
0x48, 0x8b, 0xcf,
0xe8,XX4
};
0xe8, XX4};
auto addr = MemDbg::findBytes(b1, sizeof(b1), processStartAddress, processStopAddress);
if(addr==0)return false;
if (addr == 0)
return false;
HookParam hp;
hp.address = addr;
hp.type = USING_STRING | CODEC_UTF8;
hp.offset = get_reg(regs::rax);
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
*data = stack->rax;
if (stack->retaddr == (DWORD)-1)
*len = strlen((char *)*data);
@ -33,6 +36,7 @@ namespace{
return NewHook(hp, "Kincaid");
}
}
bool Kincaid::attach_function(){
bool Kincaid::attach_function()
{
return _1();
}

View File

@ -26,15 +26,17 @@
// }
// }
class Kincaid:public ENGINE{
class Kincaid : public ENGINE
{
public:
Kincaid(){
Kincaid()
{
check_by = CHECK_BY::CUSTOM;
check_by_target=[](){
check_by_target = []()
{
return Util::SearchResourceString(L"Cookiedraggy") || Util::SearchResourceString(L"The Adventures of Kincaid");
};
};
bool attach_function();
};

View File

@ -22,7 +22,8 @@ bool InsertKiriKiriZHook()
};
ULONG64 range = min(processStopAddress - processStartAddress, X64_MAX_REL_ADDR);
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range)) {
for (auto addr : Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStartAddress + range))
{
HookParam hp;
hp.address = addr + 1;
hp.offset = get_reg(regs::rcx);
@ -40,15 +41,16 @@ bool Insertkrkrz64Hook()
0x41, 0x0F, 0xB7, 0x44, 0x24, 0x06,
0x89, 0x43, 0x24,
0x41, 0x0F, 0xBF, 0x44, 0x24, 0x0C,
0x89,0x43,0x14
};
0x89, 0x43, 0x14};
auto addrs = Util::SearchMemory(BYTES, sizeof(BYTES), PAGE_EXECUTE_READ, processStartAddress, processStopAddress);
ConsoleOutput("%p %p", processStartAddress, processStopAddress);
for (auto addr : addrs) {
for (auto addr : addrs)
{
ConsoleOutput("krkrz64 %p", addr);
const BYTE funcstart[] = {0xcc, 0xcc, 0xcc, 0xcc};
addr = reverseFindBytes(funcstart, sizeof(funcstart), addr - 0x1000, addr);
if (addr == 0)continue;
if (addr == 0)
continue;
addr += 4;
HookParam hp;
hp.address = addr;
@ -62,7 +64,7 @@ bool Insertkrkrz64Hook()
ConsoleOutput("krkrz64 failed");
return false;
}
bool KiriKiri::attach_function() {
bool KiriKiri::attach_function()
{
return Insertkrkrz64Hook() || InsertKiriKiriZHook();
}

View File

@ -1,15 +1,17 @@
class KiriKiri:public ENGINE{
class KiriKiri : public ENGINE
{
public:
KiriKiri(){
KiriKiri()
{
check_by = CHECK_BY::CUSTOM;
is_engine_certain = false;
check_by_target=[](){
check_by_target = []()
{
return Util::CheckFile(L"*.xp3") || Util::SearchResourceString(L"TVP(KIRIKIRI)");
};
};
bool attach_function();
};

View File

@ -1,8 +1,10 @@
class LightVN:public ENGINE{
class LightVN : public ENGINE
{
public:
LightVN(){
LightVN()
{
check_by = CHECK_BY::FILE_ANY;
is_engine_certain = false;
@ -10,4 +12,3 @@ class LightVN:public ENGINE{
};
bool attach_function();
};

View File

@ -1,8 +1,10 @@
class PPSSPPengine:public ENGINE{
class PPSSPPengine : public ENGINE
{
public:
PPSSPPengine(){
PPSSPPengine()
{
check_by = CHECK_BY::FILE;
is_engine_certain = false;

View File

@ -44,6 +44,8 @@ namespace
}
bool Ryujinx::attach_function()
{
WarningOutput("not support ryuujinx, please use yuzu/sudachi instead.");
return true;
auto invokeCompileMethodHelper = processStartAddress + 0x84CC0;
getMethodNameFromMetadata = (decltype(getMethodNameFromMetadata))(processStartAddress + 0x7AED0);
HookParam hp;

View File

@ -1,18 +1,21 @@
#include "Suika2.h"
bool Suika2_msvcrt() {
bool Suika2_msvcrt()
{
auto msvcrt = GetModuleHandle(L"msvcrt.dll");
if(msvcrt==0)return 0;
if (msvcrt == 0)
return 0;
auto _strdup = GetProcAddress(msvcrt, "_strdup");
if(_strdup==0)return 0;
if (_strdup == 0)
return 0;
HookParam hp;
hp.address = (uintptr_t)_strdup;
hp.type = USING_STRING | CODEC_UTF8;
hp.offset = get_reg(regs::rcx);
return NewHook(hp, "Suika2_msvcrt");
}
bool Suika2::attach_function() {
bool Suika2::attach_function()
{
auto _1 = Suika2_msvcrt();
return _1;
}

View File

@ -1,8 +1,10 @@
class Suika2:public ENGINE{
class Suika2 : public ENGINE
{
public:
Suika2(){
Suika2()
{
is_engine_certain = false;
check_by = CHECK_BY::FILE_ANY;
check_by_target = check_by_list{L"suika.exe", L"conf/config.txt"};

View File

@ -1,17 +1,21 @@
#include "TYPEMOON.h"
namespace{
bool _h() {
namespace
{
bool _h()
{
// TYPE-MOON 魔法使いの夜 多国語版 中文-英文-日文
BYTE bytes[] = {
0xBA, 0x08, 0xFF, 0x00, 0x00,
0x41, 0xB8, 0x1C, 0x20, 0x00, 0x00,
0x66,0x90
};
0x66, 0x90};
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
ConsoleOutput("%p", addr);
if(addr==0)return false;
addr=MemDbg::findEnclosingAlignedFunction(addr);ConsoleOutput("%p",addr);
if(addr==0)return false;
if (addr == 0)
return false;
addr = MemDbg::findEnclosingAlignedFunction(addr);
ConsoleOutput("%p", addr);
if (addr == 0)
return false;
HookParam hp;
hp.address = addr;
hp.type = CODEC_UTF16 | USING_STRING | EMBED_ABLE | EMBED_AFTER_NEW | EMBED_BEFORE_SIMPLE;
@ -19,7 +23,7 @@ bool _h() {
return NewHook(hp, "typemoon");
}
}
bool TYPEMOON::attach_function() {
bool TYPEMOON::attach_function()
{
return _h();
}

View File

@ -1,8 +1,10 @@
class TYPEMOON:public ENGINE{
class TYPEMOON : public ENGINE
{
public:
TYPEMOON(){
TYPEMOON()
{
check_by = CHECK_BY::FILE;
is_engine_certain = false;
@ -10,4 +12,3 @@ class TYPEMOON:public ENGINE{
};
bool attach_function();
};

View File

@ -208,8 +208,8 @@ namespace{
}
#endif
bool V8::attach_function_() {
bool V8::attach_function_()
{
return tryhookv8();
}

View File

@ -1,12 +1,14 @@
class V8:public ENGINE{
class V8 : public ENGINE
{
public:
V8(){
V8()
{
check_by = CHECK_BY::CUSTOM;
check_by_target=[this](){return attach_function_();};
check_by_target = [this]()
{ return attach_function_(); };
};
bool attach_function_();
bool attach_function() { return true; }
};

View File

@ -3,12 +3,13 @@ bool YOX::attach_function()
{
const BYTE BYTES[] = {
0x48, 0x8B, 0x0F,
0x48,0x8d,0x54,0x24,0x50
};
0x48, 0x8d, 0x54, 0x24, 0x50};
auto addrs = Util::SearchMemory(BYTES, sizeof(BYTES), PAGE_EXECUTE_READ, processStartAddress, processStopAddress);
ConsoleOutput("%p %p", processStartAddress, processStopAddress);
for (auto addr : addrs) {
if (addr == 0)continue;
for (auto addr : addrs)
{
if (addr == 0)
continue;
HookParam hp;
hp.address = addr;
hp.type = USING_STRING;

View File

@ -1,8 +1,10 @@
class YOX:public ENGINE{
class YOX : public ENGINE
{
public:
YOX(){
YOX()
{
check_by = CHECK_BY::FILE;
is_engine_certain = false;
@ -10,4 +12,3 @@ class YOX:public ENGINE{
};
bool attach_function();
};

View File

@ -1,6 +1,5 @@
#include "livecaptions.h"
bool livecaptions::attach_function()
{
@ -14,16 +13,18 @@ bool livecaptions::attach_function()
// .text:0000000180001CAE retn
HookParam hp;
hp.address = (uintptr_t)GetProcAddress(GetModuleHandle(L"vcruntime140_app.dll"), "memmove");
hp.text_fun=[](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len){
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
BYTE sig[] = {
0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0xD9,
0xE8,XX4
};
0xE8, XX4};
auto a1 = stack->retaddr - sizeof(sig);
if ((stack->retaddr > (uintptr_t)GetModuleHandle(L"Microsoft.CognitiveServices.Speech.extension.embedded.sr.dll")))
if(memcmp((void*)a1,&sig,sizeof(sig)-4)==0){
if (memcmp((void *)a1, &sig, sizeof(sig) - 4) == 0)
{
static std::set<uintptr_t> once;
if(once.find(stack->retaddr)!=once.end())return;
if (once.find(stack->retaddr) != once.end())
return;
once.insert(stack->retaddr);
// hp->text_fun=nullptr;
// hp->type=HOOK_EMPTY;

View File

@ -1,8 +1,10 @@
class lucasystem:public ENGINE{
class lucasystem : public ENGINE
{
public:
lucasystem(){
lucasystem()
{
check_by = CHECK_BY::FILE;
is_engine_certain = false;
@ -10,4 +12,3 @@ class lucasystem:public ENGINE{
};
bool attach_function();
};

View File

@ -1,11 +1,14 @@
#include "mono.h"
#include "mono/monocommon.hpp"
namespace{
bool monobdwgc() {
namespace
{
bool monobdwgc()
{
HMODULE module = GetModuleHandleW(L"mono-2.0-bdwgc.dll");
if (module == 0)return false;
if (module == 0)
return false;
auto [minAddress, maxAddress] = Util::QueryModuleLimits(module);
BYTE bytes[] = {
0x81, 0xF9, 0x80, 0x00, 0x00, 0x00,
@ -39,26 +42,30 @@ _BYTE *__fastcall sub_18005B290(
};
auto addrs = Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, minAddress, maxAddress);
auto suc = false;
for (auto addr : addrs) {
for (auto addr : addrs)
{
const BYTE align[] = {0xCC, 0xCC, 0xCC, 0xCC};
addr = reverseFindBytes(align, sizeof(align), addr - 0x100, addr);
if(addr==0)continue;
if (addr == 0)
continue;
ConsoleOutput("monobdwgcdll %p", addr);
HookParam hp;
hp.address = addr + 4;
hp.offset = get_reg(regs::rcx);
hp.type = CODEC_UTF16 | USING_STRING;
hp.text_fun=[](auto, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
hp.text_fun = [](auto, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
std::wstring str = std::wstring((LPWSTR)*data);
*split = str.find(L"OnShowComplete") != str.npos;
*len = wcslen((wchar_t *)*data) * 2;
};
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
{
std::wstring str = std::wstring((LPWSTR)data, *len / 2);
if(str.find(L"OnShowComplete")!=str.npos){
if (str.find(L"OnShowComplete") != str.npos)
{
str = std::regex_replace(str, std::wregex(L"\n"), L"");
std::wregex reg1(L"\\((.*?)\\)");
std::wsmatch match;
@ -76,7 +83,8 @@ _BYTE *__fastcall sub_18005B290(
return suc;
}
}
bool mono::attach_function(){
bool mono::attach_function()
{
bool common = monocommon::hook_mono_il2cpp();
return common;
}

View File

@ -1,8 +1,10 @@
class mono:public ENGINE{
class mono : public ENGINE
{
public:
mono(){
mono()
{
check_by = CHECK_BY::ALL_TRUE;
};

View File

@ -1,10 +1,14 @@
#include "pchooks.h"
bool pchooks::attach_function() {
bool pchooks::attach_function()
{
for (std::wstring DXVersion : {L"d3dx9", L"d3dx10"})
if (HMODULE module = GetModuleHandleW(DXVersion.c_str())) PcHooks::hookD3DXFunctions(module);
else for (int i = 0; i < 50; ++i)
if (HMODULE module = GetModuleHandleW((DXVersion + L"_" + std::to_wstring(i)).c_str())) PcHooks::hookD3DXFunctions(module);
if (HMODULE module = GetModuleHandleW(DXVersion.c_str()))
PcHooks::hookD3DXFunctions(module);
else
for (int i = 0; i < 50; ++i)
if (HMODULE module = GetModuleHandleW((DXVersion + L"_" + std::to_wstring(i)).c_str()))
PcHooks::hookD3DXFunctions(module);
PcHooks::hookGDIFunctions();
PcHooks::hookGDIPlusFunctions();

View File

@ -1,8 +1,10 @@
class pchooks:public ENGINE{
class pchooks : public ENGINE
{
public:
pchooks(){
pchooks()
{
check_by = CHECK_BY::ALL_TRUE;
dontstop = true;

View File

@ -1,5 +1,6 @@
#include"rpcs3.h"
namespace{
#include "rpcs3.h"
namespace
{
#if 0 // only support0.0.20-0.0.27
int emoffset;
int jitoffset;
@ -115,7 +116,8 @@ namespace{
}
#endif
uintptr_t getDoJitAddress() {
uintptr_t getDoJitAddress()
{
// rpcs3/Emu/Cell/PPUThread.cpp
/*
extern void ppu_register_function_at(u32 addr, u32 size, ppu_intrp_func_t ptr = nullptr)
@ -141,40 +143,49 @@ namespace{
char log[] = "ppu_register_function_at(0x%x): empty range";
auto logstrptr = MemDbg::findBytes(log, sizeof(log), processStartAddress, processStopAddress);
ConsoleOutput("%p", logstrptr);
if(logstrptr==0)return 0;
if (logstrptr == 0)
return 0;
auto addr = MemDbg::findleaaddr(logstrptr, processStartAddress, processStopAddress);
ConsoleOutput("%p", addr);
if(addr==0)return 0;
if (addr == 0)
return 0;
// ff cc cc cc,find不到。。
BYTE start[] = {XX, 0xCC, 0xCC, 0xCC};
addr = reverseFindBytes(start, sizeof(start), addr - 0x200, addr, 4, true);
ConsoleOutput("%p", addr);
return addr;
}
struct emfuncinfo{
struct emfuncinfo
{
uint64_t type;
int argidx;int padding;
int argidx;
int padding;
void *hookfunc;
void *filterfun;
const char *_id;
};
std::unordered_map<uintptr_t, emfuncinfo> emfunctionhooks;
bool checkiscurrentgame(const emfuncinfo& em){
bool checkiscurrentgame(const emfuncinfo &em)
{
auto wininfos = get_proc_windows();
for(auto&& info:wininfos){
if(info.title.find(acastw(em._id))!=info.title.npos)return true;
for (auto &&info : wininfos)
{
if (info.title.find(acastw(em._id)) != info.title.npos)
return true;
}
return false;
}
static std::set<std::pair<uintptr_t, uintptr_t>> timeoutbreaks;
void dohookemaddr(uintptr_t em_address,uintptr_t ret){
void dohookemaddr(uintptr_t em_address, uintptr_t ret)
{
jitaddraddr(em_address, ret, JITTYPE::RPCS3);
if(emfunctionhooks.find(em_address)==emfunctionhooks.end())return;
if(!(checkiscurrentgame(emfunctionhooks.at(em_address))))return;
if (emfunctionhooks.find(em_address) == emfunctionhooks.end())
return;
if (!(checkiscurrentgame(emfunctionhooks.at(em_address))))
return;
timeoutbreaks.insert(std::make_pair(em_address, ret));
auto op = emfunctionhooks.at(em_address);
HookParam hpinternal;
@ -189,7 +200,8 @@ void dohookemaddr(uintptr_t em_address,uintptr_t ret){
NewHook(hpinternal, op._id);
}
bool unsafeinithooks(){
bool unsafeinithooks()
{
// rpcs0.0.30不知道为什么ppu_register_function_at不全。不过看代码得到映射表了直接弄吧。
// rpcs3/Emu/Cell/PPUThread.cpp
// Get pointer to executable cache
@ -204,48 +216,54 @@ bool unsafeinithooks(){
hp.address = 0x500000000;
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
for(auto [addr,info]:emfunctionhooks){
for (auto [addr, info] : emfunctionhooks)
{
auto table = addr * 2 + 0x500000000;
if(IsBadReadPtr((void*)table,sizeof(uintptr_t)))continue;
if (IsBadReadPtr((void *)table, sizeof(uintptr_t)))
continue;
auto funcaddr = *(uintptr_t *)table;
funcaddr &= 0x0000ffffffffffff;
if(!funcaddr)continue;
if (!funcaddr)
continue;
auto p = std::make_pair(addr, funcaddr);
if(timeoutbreaks.find(p)!=timeoutbreaks.end())continue;
if (timeoutbreaks.find(p) != timeoutbreaks.end())
continue;
dohookemaddr(addr, funcaddr);
delayinsertNewHook(addr);
}
};
return NewHook(hp, "g_exec_addr");
}
}
bool rpcs3::attach_function()
{
ConsoleOutput("[Compatibility] RPCS3");
auto DoJitPtr = getDoJitAddress();
if(DoJitPtr==0)return false;
if (DoJitPtr == 0)
return false;
unsafeinithooks();
spDefault.jittype = JITTYPE::RPCS3;
spDefault.minAddress = 0;
spDefault.maxAddress = -1;
HookParam hp;
hp.address = DoJitPtr;
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
auto em_address = stack->rcx; // *(uint32_t*)*(uintptr_t*)(stack->base+emoffset);
auto entrypoint = stack->r8; //*(uintptr_t*)*(uintptr_t*)(stack->base+jitoffset)-0x0008000000000000;
if(!em_address||!entrypoint)return;
if (!em_address || !entrypoint)
return;
dohookemaddr(em_address, entrypoint);
delayinsertNewHook(em_address);
};
return NewHook(hp, "vita3kjit");
}
namespace
{
namespace{
bool FBLJM61131(void* data, size_t* len, HookParam* hp){
bool FBLJM61131(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
std::regex pattern("\\[[^\\]]+.");
s = std::regex_replace(s, pattern, "");
@ -254,7 +272,8 @@ bool FBLJM61131(void* data, size_t* len, HookParam* hp){
s = std::regex_replace(s, std::regex("\\n+"), " ");
return write_string_overwrite(data, len, s);
}
auto _=[](){
auto _ = []()
{
emfunctionhooks = {
//'&' -Sora no Mukou de Sakimasu you ni-
{0x46328, {CODEC_UTF8, 1, 0, 0, FBLJM61131, "BLJM61131"}},

View File

@ -1,8 +1,10 @@
class rpcs3:public ENGINE{
class rpcs3 : public ENGINE
{
public:
rpcs3(){
rpcs3()
{
check_by = CHECK_BY::FILE;
is_engine_certain = false;
@ -10,4 +12,3 @@ class rpcs3:public ENGINE{
};
bool attach_function();
};

View File

@ -1,12 +1,15 @@
#include"vita3k.h"
namespace{
#include "vita3k.h"
namespace
{
auto isVirtual = true;
auto idxDescriptor = isVirtual == true ? 2 : 1;
auto idxEntrypoint = idxDescriptor + 1;
uintptr_t getDoJitAddress() {
uintptr_t getDoJitAddress()
{
auto RegisterBlockSig1 = "40 55 53 56 57 41 54 41 56 41 57 48 8D 6C 24 E9 48 81 EC 90 00 00 00 48 8B ?? ?? ?? ?? ?? 48 33 C4 48 89 45 07 4D 8B F1 49 8B F0 48 8B FA 48 8B D9 4C 8B 7D 77 48 8B 01 48 8D 55 C7 FF 50 10";
auto first = find_pattern(RegisterBlockSig1, processStartAddress, processStopAddress);
if (first) return first;
if (first)
return first;
/*
// DebugSymbol: RegisterBlock
// ?RegisterBlock@EmitX64@X64@Backend@Dynarmic@@IEAA?AUBlockDescriptor@1234@AEBVLocationDescriptor@IR@4@PEBX_K@Z <- new
@ -21,26 +24,32 @@ namespace{
*/
auto PatchBlockSig1 = "4C 8B DC 49 89 5B 10 49 89 6B 18 56 57 41 54 41 56 41 57"; // "4C 8B DC 49 89 5B ?? 49 89 6B ?? 56 57 41 54 41 56 41 57";
first = find_pattern(PatchBlockSig1, processStartAddress, processStopAddress);
if (first) {
if (first)
{
idxDescriptor = 1;
idxEntrypoint = 2;
return first;
}
return 0;
}
struct emfuncinfo{
struct emfuncinfo
{
uint64_t type;
int argidx;int padding;
int argidx;
int padding;
void *hookfunc;
void *filterfun;
const char *_id;
};
std::unordered_map<uintptr_t, emfuncinfo> emfunctionhooks;
bool checkiscurrentgame(const emfuncinfo& em){
bool checkiscurrentgame(const emfuncinfo &em)
{
auto wininfos = get_proc_windows();
for(auto&& info:wininfos){
if(info.title.find(acastw(em._id))!=info.title.npos)return true;
for (auto &&info : wininfos)
{
if (info.title.find(acastw(em._id)) != info.title.npos)
return true;
}
return false;
}
@ -50,24 +59,30 @@ bool vita3k::attach_function()
{
ConsoleOutput("[Compatibility] Vita3k 0.1.9 3520+");
auto DoJitPtr = getDoJitAddress();
if(DoJitPtr==0)return false;
if (DoJitPtr == 0)
return false;
ConsoleOutput("DoJitPtr %p", DoJitPtr);
spDefault.jittype = JITTYPE::VITA3K;
spDefault.minAddress = 0;
spDefault.maxAddress = -1;
HookParam hp;
hp.address = DoJitPtr;
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
auto descriptor = *argidx(stack, idxDescriptor + 1); // r8
auto entrypoint = *argidx(stack, idxEntrypoint + 1); // r9
auto em_address = *(uint32_t *)descriptor;
if(!entrypoint)return;
if (!entrypoint)
return;
// ConsoleOutput("%p",em_address);
jitaddraddr(em_address, entrypoint, JITTYPE::VITA3K);
[&](){
if(emfunctionhooks.find(em_address)==emfunctionhooks.end())return;
[&]()
{
if (emfunctionhooks.find(em_address) == emfunctionhooks.end())
return;
auto op = emfunctionhooks.at(em_address);
if(!(checkiscurrentgame(op)))return;
if (!(checkiscurrentgame(op)))
return;
HookParam hpinternal;
hpinternal.address = entrypoint;
@ -85,9 +100,10 @@ bool vita3k::attach_function()
return NewHook(hp, "vita3kjit");
}
namespace{
bool FPCSG01023(void* data, size_t* len, HookParam* hp){
namespace
{
bool FPCSG01023(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("<br>"), "");
s = std::regex_replace(s, std::regex("%CF11F"), "");
@ -98,35 +114,45 @@ bool FPCSG01023(void* data, size_t* len, HookParam* hp){
return write_string_overwrite(data, len, s);
}
template <int idx>
bool FPCSG01282(void* data, size_t* len, HookParam* hp){
bool FPCSG01282(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("(\\n)+"), " ");
s = std::regex_replace(s, std::regex("\\d$|^@[a-z]+|#.*?#|\\$"), "");
static std::string last;
if(last==s)return false;
if (last == s)
return false;
last = s;
return write_string_overwrite(data, len, s);
}
template <int index>
void ReadU16TextAndLenDW(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
void ReadU16TextAndLenDW(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
auto address = VITA3K::emu_arg(stack)[index];
*len = (*(DWORD *)(address + 0x8)) * 2;
*data = address + 0xC;
}
bool FPCSG00410(void* data, size_t* len, HookParam* hp){
bool FPCSG00410(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("#[A-Za-z]+\\[(\\d*[.])?\\d+\\]"), "");
s = std::regex_replace(s, std::regex("#Pos\\[[\\s\\S]*?\\]"), "");
s = std::regex_replace(s, std::regex("#n"), " ");
// .replaceAll("④", "!?").replaceAll("②", "!!").replaceAll("⑥", "。").replaceAll("⑪", "【")
// .replaceAll("⑫", "】").replaceAll("⑤", "、").replaceAll("①", "・・・")
strReplace(s,"\x87\x43","!?");strReplace(s,"\x87\x41","!!");strReplace(s,"\x87\x45","\x81\x42");strReplace(s,"\x87\x4a","\x81\x79");
strReplace(s,"\x87\x4b","\x81\x7a");strReplace(s,"\x87\x44","\x81\x41");strReplace(s,"\x87\x40","\x81\x45\x81\x45\x81\x45");
strReplace(s, "\x87\x43", "!?");
strReplace(s, "\x87\x41", "!!");
strReplace(s, "\x87\x45", "\x81\x42");
strReplace(s, "\x87\x4a", "\x81\x79");
strReplace(s, "\x87\x4b", "\x81\x7a");
strReplace(s, "\x87\x44", "\x81\x41");
strReplace(s, "\x87\x40", "\x81\x45\x81\x45\x81\x45");
return write_string_overwrite(data, len, s);
}
bool FPCSG00448(void* data, size_t* len, HookParam* hp){
bool FPCSG00448(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("[\\s]"), "");
s = std::regex_replace(s, std::regex("(#n)+"), "");
@ -134,35 +160,48 @@ bool FPCSG00448(void* data, size_t* len, HookParam* hp){
s = std::regex_replace(s, std::regex("#Pos[\\s\\S]*?\\]"), "");
return write_string_overwrite(data, len, s);
}
bool FPCSG01008(void* data, size_t* len, HookParam* hp){
bool FPCSG01008(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("#Ruby\\[([^,]+)\\.([^\\]]+)\\]."), "$1");
s = std::regex_replace(s, std::regex("(#n)+"), " ");
s = std::regex_replace(s, std::regex("#[A-Za-z]+\\[(\\d*[.])?\\d+\\]"), "");
return write_string_overwrite(data, len, s);
}
void TPCSG00903(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
void TPCSG00903(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
auto address = VITA3K::emu_arg(stack)[0];
*len = (*(DWORD *)(address + 0x14));
*data = address + 0x1C;
}
bool FPCSG00903(void* data, size_t* len, HookParam* hp){
bool FPCSG00903(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("\\\\n"), " ");
return write_string_overwrite(data, len, s);
}
bool FPCSG00839(void* data, size_t* len, HookParam* hp){
bool FPCSG01180(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex(R"(\\n)"), " ");
s = std::regex_replace(s, std::regex(R"(,.*$)"), " ");
return write_string_overwrite(data, len, s);
}
bool FPCSG00839(void *data, size_t *len, HookParam *hp)
{
auto s = std::wstring((wchar_t *)data, *len / 2);
s = std::regex_replace(s, std::wregex(L"\\[[^\\]]+."), L"");
s = std::regex_replace(s, std::wregex(L"\\\\k|\\\\x|%C|%B|%p-1;"), L"");
s = std::regex_replace(s, std::wregex(L"#[0-9a-fA-F]+;([^%#]+)(%r)?"), L"$1");
s = std::regex_replace(s, std::wregex(L"\\\\n"), L"");
static std::wstring last;
if(last.find(s)!=last.npos)return false;
if (last.find(s) != last.npos)
return false;
last = s;
return write_string_overwrite(data, len, s);
}
bool FPCSG00751(void* data, size_t* len, HookParam* hp){
bool FPCSG00751(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("[\\s]"), "");
s = std::regex_replace(s, std::regex("@[a-z]"), "");
@ -170,12 +209,28 @@ bool FPCSG00751(void* data, size_t* len, HookParam* hp){
strReplace(s, "\x81\x90", "");
return write_string_overwrite(data, len, s);
}
bool FPCSG00706(void* data, size_t* len, HookParam* hp){
bool FPCSG00401(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex(R"([\s])"), "");
s = std::regex_replace(s, std::regex(R"(\c)"), "");
s = std::regex_replace(s, std::regex(R"(\\n)"), "");
return write_string_overwrite(data, len, s);
}
bool FPCSG00912(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("%N"), "");
return write_string_overwrite(data, len, s);
}
bool FPCSG00706(void *data, size_t *len, HookParam *hp)
{
auto s = std::wstring((wchar_t *)data, *len / 2);
s = std::regex_replace(s, std::wregex(L"<br>"), L"");
return write_string_overwrite(data, len, s);
}
bool FPCSG00696(void* data, size_t* len, HookParam* hp){
bool FPCSG00696(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
//.replace(/㌔/g, '⁉')
//.replace(/㍉/g, '!!')
@ -183,7 +238,8 @@ bool FPCSG00696(void* data, size_t* len, HookParam* hp){
strReplace(s, "\x87\x5f", "");
return write_string_overwrite(data, len, s);
}
bool FPCSG00389(void* data, size_t* len, HookParam* hp){
bool FPCSG00389(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("[\\s]"), "");
s = std::regex_replace(s, std::regex("(#n)+"), "");
@ -191,7 +247,8 @@ bool FPCSG00389(void* data, size_t* len, HookParam* hp){
s = std::regex_replace(s, std::regex("#Pos\\[[\\s\\S]*?\\]"), "");
return write_string_overwrite(data, len, s);
}
bool FPCSG00216(void* data, size_t* len, HookParam* hp){
bool FPCSG00216(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("[\\s]"), "");
s = std::regex_replace(s, std::regex("(#n)+"), "");
@ -199,46 +256,52 @@ bool FPCSG00216(void* data, size_t* len, HookParam* hp){
s = std::regex_replace(s, std::regex("#Pos\\[[\\s\\S]*?\\]"), "");
return write_string_overwrite(data, len, s);
}
bool FPCSG00405(void* data, size_t* len, HookParam* hp){
bool FPCSG00405(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex("[\\s]"), "");
return write_string_overwrite(data, len, s);
}
bool PCSG00776(void* data, size_t* len, HookParam* hp){
bool PCSG00776(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
auto ws = StringToWideString(s, 932).value();
strReplace(ws, L"\x02", L"");
Trim(ws);
return write_string_overwrite(data, len, WideStringToString(ws));
}
void PCSG00911(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
void PCSG00912(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
auto address = VITA3K::emu_arg(stack)[1];
std::string final_string = "";
BYTE pattern[] = {0x47, 0xff, 0xff};
auto results = MemDbg::findBytes(pattern, sizeof(pattern), address, address + 0x50);
if (!results) return;
if (!results)
return;
address = results + 5;
while (true) {
while (true)
{
std::string text = (char *)address;
final_string += text;
address = address + (text.size() + 1);
auto bytes = (BYTE *)address;
if (!(bytes[0] == 0x48 && bytes[1] == 0xFF && bytes[2] == 0xFF)) break;
if (!(bytes[0] == 0x48 && bytes[1] == 0xFF && bytes[2] == 0xFF))
break;
address = address + (3);
bytes = (BYTE *)address;
if (!(bytes[0] == 0x47 && bytes[1] == 0xFF && bytes[2] == 0xFF)) break;
if (!(bytes[0] == 0x47 && bytes[1] == 0xFF && bytes[2] == 0xFF))
break;
address = address + (5);
}
write_string_new(data, len, final_string);
}
void TPCSG00291(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
void TPCSG00291(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
auto a2 = VITA3K::emu_arg(stack)[0];
auto vm = *(DWORD *)(a2 + (0x28));
@ -247,7 +310,8 @@ void TPCSG00291(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* sp
uintptr_t address = VITA3K::emu_addr(stack, vm);
auto len1 = *(DWORD *)(address + 4);
auto p = address + 0x20;
if(len1>4 && *(WORD*)(p+2)==0){
if (len1 > 4 && *(WORD *)(p + 2) == 0)
{
auto p1 = *(DWORD *)(address + 8);
vm = *(DWORD *)VITA3K::emu_addr(stack, vm);
vm = *(DWORD *)VITA3K::emu_addr(stack, vm + 0xC);
@ -256,49 +320,142 @@ void TPCSG00291(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* sp
static int fm = 0;
static std::string pre;
auto b = fm;
auto s=[](uintptr_t address){
auto s = [](uintptr_t address)
{
auto frist = *(WORD *)address;
auto lo = frist & 0xFF; // uppercase: 41->5A
auto hi = frist >> 8;
if (hi == 0 && (lo > 0x5a || lo < 0x41) /* T,W,? */) {
if (hi == 0 && (lo > 0x5a || lo < 0x41) /* T,W,? */)
{
return std::string();
}
std::string s ;int i = 0;WORD c;
std::string s;
int i = 0;
WORD c;
char buf[3] = {0};
while ((c = *(WORD*)(address+i)) != 0) {
while ((c = *(WORD *)(address + i)) != 0)
{
// reverse endian: ShiftJIS BE => LE
buf[0] = c >> 8;
buf[1] = c & 0xFF;
if (c == 0x815e /* */) {
if (c == 0x815e /* */)
{
s += ' '; // single line
}
else if (buf[0] == 0) {
else if (buf[0] == 0)
{
//// UTF16 LE turned BE: 5700=>0057, 3100, 3500
//// 4e00 6d00=>PLAYER
// do nothing
if (buf[1] == 0x4e) {
if (buf[1] == 0x4e)
{
s += "PLAYER";
fm++;
}
}
else {
else
{
s += buf;
}
i += 2;
}
return s;
}(p);
if(b>0){
if (b > 0)
{
fm--;
return;
}
if(s==pre)return ;
if (s == pre)
return;
pre = s;
write_string_new(data, len, s);
}
auto _=[](){
bool FPCSG00468(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex(R"(\\n\u3000*|\\k)"), "");
s = std::regex_replace(s, std::regex(R"(\[|\*[^\]]+])"), "");
s = std::regex_replace(s, std::regex(u8"×"), "");
return write_string_overwrite(data, len, s);
}
bool FPCSG00808(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex(R"(^\s+|\s+$)"), "");
s = std::regex_replace(s, std::regex(R"(\s*(#n)*\s*)"), "");
s = std::regex_replace(s, std::regex(R"(#\w+(\[.+?\])?)"), "");
return write_string_overwrite(data, len, s);
}
bool FPCSG00855(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex(R"(#n\u3000*)"), "");
s = std::regex_replace(s, std::regex(R"(#\w.+?])"), "");
return write_string_overwrite(data, len, s);
}
template <int idx>
bool FPCSG00855_2(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
static std::string last;
if (last == s)
return false;
last = s;
strReplace(s, u8"Χ", u8"");
strReplace(s, u8"Δ", u8"");
strReplace(s, u8"Λ", u8"");
strReplace(s, u8"", u8"");
strReplace(s, u8"", u8"");
strReplace(s, u8"", u8"");
strReplace(s, u8"", u8"");
strReplace(s, u8"", u8"");
strReplace(s, u8"", u8"");
strReplace(s, u8"П", u8"");
strReplace(s, u8"Ц", u8"");
if (write_string_overwrite(data, len, s))
return FPCSG00855(data, len, hp);
else
return false;
}
bool FPCSG00477(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
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"(#\w.+?])"), L"");
s = WideStringToString(ws, 932);
return write_string_overwrite(data, len, s);
}
bool FPCSG00852(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
auto ws = StringToWideString(s, 932).value();
ws = std::regex_replace(ws, std::wregex(LR"(\^)"), L"");
s = WideStringToString(ws, 932);
return write_string_overwrite(data, len, s);
}
bool FPCSG01066(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
s = std::regex_replace(s, std::regex(R"(\n\u3000*)"), "");
return write_string_overwrite(data, len, s);
}
bool FPCSG01075(void *data, size_t *len, HookParam *hp)
{
if (!FPCSG00808(data, len, hp))
return false;
auto s = std::string((char *)data, *len);
static std::string last;
if (last == s)
return false;
last = s;
return true;
}
auto _ = []()
{
emfunctionhooks = {
// Tsuihou Senkyo
{0x8002e176, {0, 0, 0, 0, FPCSG01023, "PCSG01023"}}, // dialogue+name,sjis
@ -316,8 +473,6 @@ auto _=[](){
// Marginal #4 Road to Galaxy
{0x8002ff90, {CODEC_UTF8, 0, 0, 0, FPCSG01008, "PCSG01008"}}, // text
// BLACK WOLVES SAGA -Weiβ und Schwarz-
// {0x8004ed22,{CODEC_UTF8,0,0,0,FPCSG01008,"PCSG00935"}},//name
// {0x8006d202,{CODEC_UTF8,1,2,0,FPCSG01008,"PCSG00935"}},//text
{0x800581a2, {CODEC_UTF8, 0, 0, 0, FPCSG01008, "PCSG00935"}}, // text
// New Game! The Challenge Stage!
{0x8012674c, {CODEC_UTF8, 0, 0, TPCSG00903, FPCSG00903, "PCSG00903"}},
@ -341,8 +496,7 @@ auto _=[](){
// Nekketsu Inou Bukatsu-tan Trigger Kiss
{0x8004e44a, {0, 0, 0, 0, FPCSG00410, "PCSG00410"}}, // dialogue,sjis
// バイナリースター Binary Star
{0x80058608,{0,1,0,0,FPCSG00389,"PCSG00389"}},//dialogue,sjis
{0x80021292,{0,0,0,0,FPCSG00389,"PCSG00389"}},//name
{0x80058606, {0, 1, 0xd, 0, FPCSG00389, "PCSG00389"}}, // dialogue,sjis
// Amagami
{0x80070658, {0, 0, 0, TPCSG00291, 0, "PCSG00291"}},
// Rui wa Tomo o Yobu
@ -355,9 +509,56 @@ auto _=[](){
// Re:Birthday Song ~Koi o Utau Shinigami~
{0x80033af6, {0, 0, 2, 0, 0, "PCSG00911"}}, // dialogue
// Un:Birthday Song ~Ai o Utau Shinigami~
{0x80038538,{0,0,0,PCSG00911,0,"PCSG00911"}},
{0x80004b52,{0,3,5,0,0,"PCSG00911"}},
{0x80038538, {0, 0, 0, PCSG00912, 0, "PCSG00912"}},
{0x80033d66, {0, 3, 4, 0, FPCSG00912, "PCSG00912"}},
// Sora*yume
{0x8000bad4, {0, 1, 0, 0, FPCSG00401, "PCSG00401"}},
// Tengai ni Mau, Iki na Hana
{0x8006808e, {CODEC_UTF8, 0, 0, 0, FPCSG01180, "PCSG01180"}},
{0x80089408, {CODEC_UTF8, 0, 0, 0, FPCSG01180, "PCSG01180"}},
// Kokuchou no Psychedelica (黒蝶のサイケデリカ)
{0x80043538, {CODEC_UTF8, 1, 0, 0, FPCSG00468, "PCSG00468"}},
// Haitaka no Psychedelica (灰鷹のサイケデリカ)
{0x80022c06, {CODEC_UTF8, 4, 0, 0, FPCSG00468, "PCSG00812"}},
// Yuukyuu no Tierblade -Lost Chronicle- (悠久のティアブレイド -Lost Chronicle-)
{0x8003542a, {CODEC_UTF8, 10, 0, 0, FPCSG00808, "PCSG00808"}},
{0x8002a95a, {CODEC_UTF8, 6, 0, 0, FPCSG00808, "PCSG00808"}},
{0x801a98aa, {CODEC_UTF8, 9, 0, 0, FPCSG00808, "PCSG00808"}},
{0x801a42bc, {CODEC_UTF8, 9, 0, 0, FPCSG00808, "PCSG00808"}},
{0x801a42d0, {CODEC_UTF8, 7, 0, 0, FPCSG00808, "PCSG00808"}},
// Yuukyuu no Tierblade -Fragments of Memory- (悠久のティアブレイド -Fragments of Memory-)
{0x80035f44, {CODEC_UTF8, 10, 0, 0, FPCSG01075, "PCSG01075"}},
{0x8000d868, {CODEC_UTF8, 9, 0, 0, FPCSG01075, "PCSG01075"}},
{0x8004598e, {CODEC_UTF8, 0, 0, 0, FPCSG01075, "PCSG01075"}},
{0x801b1d16, {CODEC_UTF8, 9, 0, 0, FPCSG01075, "PCSG01075"}},
{0x801ac31e, {CODEC_UTF8, 9, 0, 0, FPCSG01075, "PCSG01075"}},
{0x801ac33a, {CODEC_UTF8, 7, 0, 0, FPCSG01075, "PCSG01075"}},
{0x801b879a, {CODEC_UTF8, 5, 0, 0, FPCSG01075, "PCSG01075"}},
{0x8009f570, {CODEC_UTF8, 5, 0, 0, FPCSG01075, "PCSG01075"}},
// Magic Kyun! Renaissance (マジきゅんっ!ルネッサンス)
{0x8008375a, {0, 1, 0, 0, FPCSG00852, "PCSG00852"}},
{0x8001c194, {0, 1, 0, 0, FPCSG00852, "PCSG00852"}},
// Chouchou Jiken Lovesodic / Chouchou Jiken Rhapsodic (蝶々事件ラブソディック)
{0x8008dea2, {CODEC_UTF8, 4, 0, 0, FPCSG01066, "PCSG01066"}},
{0x8008eb38, {CODEC_UTF8, 0, 0, 0, FPCSG01066, "PCSG01066"}},
// Hyakka Yakou (百華夜光)
{0x80032b30, {0, 8, 0, 0, 0, "PCSG00477"}},
{0x80019c5a, {0, 5, 0, 0, 0, "PCSG00477"}},
{0x80031a46, {0, 6, 0, 0, 0, "PCSG00477"}},
{0x8003a49a, {0, 0, 0, 0, FPCSG00477, "PCSG00477"}},
{0x80182532, {0, 7, 0, 0, FPCSG00477, "PCSG00477"}},
{0x8017d1da, {0, 5, 0, 0, 0, "PCSG00477"}},
{0x8017d478, {0, 4, 0, 0, 0, "PCSG00477"}},
{0x8017a6aa, {0, 6, 0, 0, 0, "PCSG00477"}},
// Hana Oboro ~Sengoku-den Ranki~ (花朧 ~戦国伝乱奇~)
{0x80037600, {CODEC_UTF8, 6, 0, 0, FPCSG00855, "PCSG00855"}},
{0x80036580, {CODEC_UTF8, 6, 0, 0, FPCSG00855, "PCSG00855"}},
{0x801a2ada, {CODEC_UTF8, 0, 0, 0, FPCSG00855_2<0>, "PCSG00855"}},
{0x801a2ba8, {CODEC_UTF8, 0, 0, 0, FPCSG00855_2<1>, "PCSG00855"}},
{0x801a2d9e, {CODEC_UTF8, 0, 0, 0, FPCSG00855_2<2>, "PCSG00855"}},
{0x801a2e68, {CODEC_UTF8, 0, 0, 0, FPCSG00855_2<3>, "PCSG00855"}},
};
return 1;
}();

View File

@ -1,8 +1,10 @@
class vita3k:public ENGINE{
class vita3k : public ENGINE
{
public:
vita3k(){
vita3k()
{
check_by = CHECK_BY::FILE;
is_engine_certain = false;
@ -10,4 +12,3 @@ class vita3k:public ENGINE{
};
bool attach_function();
};

2904
LunaHook/engine64/yuzu.cpp Normal file

File diff suppressed because it is too large Load Diff

17
LunaHook/engine64/yuzu.h Normal file
View File

@ -0,0 +1,17 @@
class yuzu : public ENGINE
{
public:
yuzu()
{
is_engine_certain = false;
check_by = CHECK_BY::CUSTOM;
check_by_target = []()
{
return (wcscmp(processName_lower, L"suyu.exe") == 0 || wcscmp(processName_lower, L"yuzu.exe") == 0 || wcscmp(processName_lower, L"sudachi.exe") == 0);
};
};
bool attach_function();
};

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +0,0 @@
class yuzusuyu:public ENGINE{
public:
yuzusuyu(){
is_engine_certain=false;
check_by=CHECK_BY::CUSTOM;
check_by_target=[](){
return (wcscmp(processName_lower, L"suyu.exe")==0 || wcscmp(processName_lower, L"yuzu.exe")==0|| wcscmp(processName_lower, L"sudachi.exe")==0);
};
};
bool attach_function();
};

View File

@ -16,7 +16,7 @@
#include "engine64/TYPEMOON.h"
#include "engine64/Kincaid.h"
#include "engine64/LightVN.h"
#include "engine64/yuzusuyu.h"
#include "engine64/yuzu.h"
#include "engine64/Ryujinx.h"
#include "engine64/vita3k.h"
#include "engine64/rpcs3.h"
@ -42,7 +42,7 @@ std::vector<ENGINE *> check_engines()
new _5pb,
new TYPEMOON,
new ENTERGRAM,
new yuzusuyu,
new yuzu,
new PPSSPPengine,
new vita3k,
new rpcs3,

View File

@ -1,8 +1,10 @@
#include <queue>
#include "emujitarg.hpp"
namespace ppsspp{
bool ULJS00403_filter(void* data, size_t* len, HookParam* hp){
namespace ppsspp
{
bool ULJS00403_filter(void *data, size_t *len, HookParam *hp)
{
std::string result = std::string((char *)data, *len);
std::regex newlinePattern(R"((\\n)+)");
result = std::regex_replace(result, newlinePattern, " ");
@ -11,8 +13,8 @@ bool ULJS00403_filter(void* data, size_t* len, HookParam* hp){
return write_string_overwrite(data, len, result);
}
void ULJS00339(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
void ULJS00339(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
auto a2 = PPSSPP::emu_arg(stack)[0];
auto vm = *(DWORD *)(a2 + (0x28));
@ -21,7 +23,8 @@ void ULJS00339(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* spl
uintptr_t address = PPSSPP::emu_addr(stack, vm);
auto len1 = *(DWORD *)(address + 4);
auto p = address + 0x20;
if(len1>4 && *(WORD*)(p+2)==0){
if (len1 > 4 && *(WORD *)(p + 2) == 0)
{
auto p1 = *(DWORD *)(address + 8);
vm = *(DWORD *)PPSSPP::emu_addr(stack, vm);
vm = *(DWORD *)PPSSPP::emu_addr(stack, vm + 0xC);
@ -30,50 +33,61 @@ void ULJS00339(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* spl
static int fm = 0;
static std::string pre;
auto b = fm;
auto s=[](uintptr_t address){
auto s = [](uintptr_t address)
{
auto frist = *(WORD *)address;
auto lo = frist & 0xFF; // uppercase: 41->5A
auto hi = frist >> 8;
if (hi == 0 && (lo > 0x5a || lo < 0x41) /* T,W,? */) {
if (hi == 0 && (lo > 0x5a || lo < 0x41) /* T,W,? */)
{
return std::string();
}
std::string s ;int i = 0;WORD c;
std::string s;
int i = 0;
WORD c;
char buf[3] = {0};
while ((c = *(WORD*)(address+i)) != 0) {
while ((c = *(WORD *)(address + i)) != 0)
{
// reverse endian: ShiftJIS BE => LE
buf[0] = c >> 8;
buf[1] = c & 0xFF;
if (c == 0x815e /* */) {
if (c == 0x815e /* */)
{
s += ' '; // single line
}
else if (buf[0] == 0) {
else if (buf[0] == 0)
{
//// UTF16 LE turned BE: 5700=>0057, 3100, 3500
//// 4e00 6d00=>PLAYER
// do nothing
if (buf[1] == 0x4e) {
if (buf[1] == 0x4e)
{
s += "PLAYER";
fm++;
}
}
else {
else
{
s += buf;
}
i += 2;
}
return s;
}(p);
if(b>0){
if (b > 0)
{
fm--;
return;
}
if(s==pre)return ;
if (s == pre)
return;
pre = s;
write_string_new(data, len, s);
}
bool NPJH50909_filter(void* data, size_t* len, HookParam* hp){
bool NPJH50909_filter(void *data, size_t *len, HookParam *hp)
{
std::string result = std::string((char *)data, *len);
auto ws = StringToWideString(result, 932).value();
// Remove single line markers
@ -84,7 +98,8 @@ bool NPJH50909_filter(void* data, size_t* len, HookParam* hp){
// Reformat name
std::wsmatch match;
if (std::regex_search(ws, match, std::wregex(L"(^[^「]+)「"))) {
if (std::regex_search(ws, match, std::wregex(L"(^[^「]+)「")))
{
std::wstring name = match[1].str();
ws = std::regex_replace(ws, std::wregex(L"^[^「]+"), L"");
ws = name + L"\n" + ws;
@ -92,7 +107,8 @@ bool NPJH50909_filter(void* data, size_t* len, HookParam* hp){
return write_string_overwrite(data, len, WideStringToString(ws, 932));
}
bool ULJM06119_filter(void* data, size_t* len, HookParam* hp){
bool ULJM06119_filter(void *data, size_t *len, HookParam *hp)
{
std::string s = std::string((char *)data, *len);
std::regex pattern(R"(/\[[^\]]+./g)");
@ -109,7 +125,8 @@ bool ULJM06119_filter(void* data, size_t* len, HookParam* hp){
return write_string_overwrite(data, len, s);
}
bool ULJM06036_filter(void* data, size_t* len, HookParam* hp){
bool ULJM06036_filter(void *data, size_t *len, HookParam *hp)
{
std::wstring result = std::wstring((wchar_t *)data, *len / 2);
std::wregex pattern(LR"(<R([^\/]+).([^>]+).>)");
result = std::regex_replace(result, pattern, L"$2");
@ -118,16 +135,23 @@ bool ULJM06036_filter(void* data, size_t* len, HookParam* hp){
return write_string_overwrite(data, len, result);
}
namespace Corda{
std::string readBinaryString(uintptr_t address,bool* haveName){
namespace Corda
{
std::string readBinaryString(uintptr_t address, bool *haveName)
{
*haveName = false;
if ((*(WORD*)address & 0xF0FF) == 0x801b) {
if ((*(WORD *)address & 0xF0FF) == 0x801b)
{
*haveName = true;
address = address + 2; // (1)
}
std::string s;int i=0;uint8_t c;
while ((c = *(uint8_t*)(address+i)) != 0) {
if (c == 0x1b) {
std::string s;
int i = 0;
uint8_t c;
while ((c = *(uint8_t *)(address + i)) != 0)
{
if (c == 0x1b)
{
if (*haveName)
return s; // (1) skip junk after name
@ -137,15 +161,18 @@ namespace Corda{
else
i += 2;
}
else if (c == 0x0a) {
else if (c == 0x0a)
{
s += '\n';
i += 1;
}
else if (c == 0x20) {
else if (c == 0x20)
{
s += ' ';
i += 1;
}
else {
else
{
auto len = 1 + (IsDBCSLeadByteEx(932, *(BYTE *)(address + i)));
s += std::string((char *)(address + i), len);
i += len; // encoder.encode(c).byteLength;
@ -155,7 +182,8 @@ namespace Corda{
}
}
void ULJM05428(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
void ULJM05428(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
auto address = PPSSPP::emu_arg(stack)[1];
bool haveNamve;
auto s = Corda::readBinaryString(address, &haveNamve);
@ -163,10 +191,13 @@ void ULJM05428(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* spl
write_string_new(data, len, s);
}
void ULJM05054(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
if (hp->emu_addr != 0x886162c) {
void ULJM05054(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
if (hp->emu_addr != 0x886162c)
{
auto addr = PPSSPP::emu_arg(stack)[0] + 0x3c;
*data=addr;*len=strlen((char*)addr);
*data = addr;
*len = strlen((char *)addr);
return;
}
auto address = PPSSPP::emu_arg(stack)[1];
@ -176,8 +207,8 @@ void ULJM05054(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* spl
write_string_new(data, len, s);
}
bool ULJM05943F(void* data, size_t* len, HookParam* hp){
bool ULJM05943F(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
std::regex pattern1("#n+");
std::string replacement1 = " ";
@ -199,7 +230,8 @@ bool FULJM05603(LPVOID data, size_t* size, HookParam*)
return true;
}
namespace NPJH50530{
namespace NPJH50530
{
std::string current;
bool T(LPVOID data, size_t *size, HookParam *)
{
@ -212,12 +244,20 @@ bool N(LPVOID data, size_t* size, HookParam*)
return current != current1;
}
}
bool FNPJH50243(LPVOID data, size_t *size, HookParam *)
{
auto s = std::wstring((wchar_t *)data, *size / 2);
s = std::regex_replace(s, std::wregex(LR"(<(.*?)\|(.*?)>)"), L"$1");
return write_string_overwrite(data, size, s);
}
bool FULJM05889(LPVOID data, size_t *size, HookParam *)
{
auto text = reinterpret_cast<LPSTR>(data);
auto len = reinterpret_cast<size_t *>(size);
for(size_t i=0;i<*len;){
if(IsDBCSLeadByteEx(932,(text[i]))){
for (size_t i = 0; i < *len;)
{
if (IsDBCSLeadByteEx(932, (text[i])))
{
i += 2;
continue;
}
@ -229,7 +269,8 @@ bool FULJM05889(LPVOID data, size_t* size, HookParam*)
return true;
}
bool NPJH50619F(void* data, size_t* len, HookParam* hp){
bool NPJH50619F(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
std::regex pattern1("[\\r\\n]+");
std::string replacement1 = "";
@ -246,8 +287,8 @@ bool NPJH50619F(void* data, size_t* len, HookParam* hp){
return write_string_overwrite(data, len, result4);
}
bool NPJH50505F(void* data, size_t* len, HookParam* hp){
bool NPJH50505F(void *data, size_t *len, HookParam *hp)
{
auto s = std::string((char *)data, *len);
std::regex pattern2("#RUBS(#[A-Z0-9]+)*[^#]+");
@ -273,13 +314,16 @@ bool NPJH50505F(void* data, size_t* len, HookParam* hp){
return write_string_overwrite(data, len, result6);
}
void QNPJH50909(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
void QNPJH50909(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
{
uintptr_t addr = PPSSPP::emu_addr(stack, 0x08975110);
*data = addr + 0x20;
*len = *(DWORD *)(addr + 0x14) * 2;
if(0x6e87==*(WORD*)*data)*len=0;
if(0x000a==*(WORD*)*data)*len=0;
if (0x6e87 == *(WORD *)*data)
*len = 0;
if (0x000a == *(WORD *)*data)
*len = 0;
}
std::unordered_map<uintptr_t, emfuncinfo> emfunctionhooks = {
// Shinigami to Shoujo
@ -324,6 +368,10 @@ std::unordered_map<uintptr_t,emfuncinfo>emfunctionhooks= {
// シャイニング・ブレイド
{0x8AA3B70, {0, 0xC, 0, 0, NPJH50530::T, "NPJH50530"}}, // text only
{0x884DB44, {0, 1, 0, 0, NPJH50530::N, "NPJH50530"}}, // text+name
// ティアーズ・トゥ・ティアラ 外伝 アヴァロンの謎
{0x890A4BC, {CODEC_UTF16, 1, 0, 0, FNPJH50243, "NPJH50243"}},
// 薔薇ノ木ニ薔薇ノ花咲ク
{0x881E560, {0, 1, 0, 0, 0, "ULJM05802"}},
};
}

View File

@ -222,7 +222,6 @@ void SafeSendJitVeh(hook_stack *stack, uintptr_t address, uintptr_t em_addr, JIT
}
}
std::unordered_map<uintptr_t, uint64_t> addresscalledtime;
bool safeautoleaveveh = false;
bool SendJitVeh(PCONTEXT context, uintptr_t address, uintptr_t em_addr, JITTYPE jittype)
{
if (safeautoleaveveh)
@ -295,7 +294,7 @@ void SearchForHooks_Return()
if (!records[i].em_addr)
continue;
hp.emu_addr = records[i].em_addr;
hp.type = CODEC_UTF16 | USING_STRING | BREAK_POINT;
hp.type = CODEC_UTF16 | USING_STRING | BREAK_POINT | NO_CONTEXT;
hp.argidx = records[i].argidx;
}
NotifyHookFound(hp, (wchar_t *)records[i].text);

View File

@ -101,6 +101,15 @@ void ConsoleOutput(LPCSTR text, ...)
vsnprintf(buffer.message, MESSAGE_SIZE, text, args);
WriteFile(hookPipe, &buffer, sizeof(buffer), DUMMY, nullptr);
}
void WarningOutput(LPCSTR text, ...)
{
WarningNotif buffer;
va_list args;
va_start(args, text);
vsnprintf(buffer.message, MESSAGE_SIZE, text, args);
WriteFile(hookPipe, &buffer, sizeof(buffer), DUMMY, nullptr);
}
Synchronized<std::unordered_map<uintptr_t, std::wstring>> modulecache;
std::wstring &querymodule(uintptr_t addr)
{

View File

@ -6,6 +6,7 @@
void TextOutput(const ThreadParam &tp, const HookParam &hp, TextOutput_T(*buffer), int len);
void ConsoleOutput(LPCSTR text, ...);
void WarningOutput(LPCSTR text, ...);
void NotifyHookFound(HookParam hp, wchar_t *text);
void NotifyHookRemove(uint64_t addr, LPCSTR name);
bool NewHook(HookParam hp, LPCSTR name);
@ -27,6 +28,6 @@ void context_set(hook_stack *, PCONTEXT);
inline std::map<uintptr_t, std::pair<std::string, HookParam>> delayinserthook;
void delayinsertadd(HookParam, std::string);
void delayinsertNewHook(uintptr_t);
inline bool safeautoleaveveh = false;
inline bool dont_detach = false;
inline bool host_connected = false;

View File

@ -127,7 +127,13 @@ bool TextHook::Insert(HookParam hp)
if (hp.type & DIRECT_READ)
return InsertReadCode();
if (hp.type & BREAK_POINT)
return InsertBreakPoint();
{
if (InsertBreakPoint())
return true;
if (safeautoleaveveh)
return InsertBreakPoint(); // 搜索特殊码后不会释放导致virtualprotect查询失败重试。
return false;
}
return InsertHookCode();
}
uintptr_t win64find0000(uintptr_t addr)

View File

@ -292,12 +292,16 @@ LunaHost::LunaHost()
hooksearchwindow->show();
};
Host::Start(
Host::StartEx(
std::bind(&LunaHost::on_proc_connect, this, std::placeholders::_1),
std::bind(&LunaHost::on_proc_disconnect, this, std::placeholders::_1),
std::bind(&LunaHost::on_thread_create, this, std::placeholders::_1),
std::bind(&LunaHost::on_thread_delete, this, std::placeholders::_1),
std::bind(&LunaHost::on_text_recv, this, std::placeholders::_1, std::placeholders::_2));
std::bind(&LunaHost::on_text_recv, this, std::placeholders::_1, std::placeholders::_2),
{},
{},
{},
std::bind(&LunaHost::on_warning, this, std::placeholders::_1));
mainlayout = new gridlayout();
mainlayout->addcontrol(g_selectprocessbutton, 0, 0);
@ -448,6 +452,10 @@ bool LunaHost::on_text_recv(TextThread &thread, std::wstring &output)
}
return true;
}
void LunaHost::on_warning(const std::wstring &warning)
{
MessageBoxW(winId, warning.c_str(), L"warning", 0);
}
void LunaHost::on_thread_create(TextThread &thread)
{
wchar_t buff[65535];

View File

@ -116,6 +116,7 @@ class LunaHost : public mainwindow
void on_thread_delete(TextThread &thread);
void on_proc_connect(DWORD pid);
void on_proc_disconnect(DWORD pid);
void on_warning(const std::wstring &);
void showtext(const std::wstring &text, bool clear);
void updatelisttext(const std::wstring &text, LONG_PTR data);

View File

@ -2,7 +2,6 @@
#include <io.h>
#include <fcntl.h>
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
@ -22,51 +21,65 @@ int main()
output.c_str()
);
fflush(stdout);
return false;
});
return false; });
wchar_t input[500] = {};
SearchParam sp = {};
sp.codepage = Host::defaultCodepage;
sp.length = 0;
while (fgetws(input, 500, stdin))
{
if(wcslen(input)<=1)continue;//\r\n第二行会直接只有一个\n
if (wcslen(input) <= 1)
continue; //\r\n第二行会直接只有一个\n
wchar_t command[500] = {};
DWORD processId = 0;
int split;
for (split = wcslen(input) - 1; split >= 1; split--) {
if (input[split] == L'P' && input[split-1]=='-') {
for (split = wcslen(input) - 1; split >= 1; split--)
{
if (input[split] == L'P' && input[split - 1] == '-')
{
processId = _wtoi(input + split + 1);
break;
}
}
if (split == 1)continue;// ExitProcess(0);
if (split == 1)
continue; // ExitProcess(0);
split -= 2;
while (split > 0 && input[split] == L' ')split -= 1;
if (split == 0)continue;//ExitProcess(0);
while (split > 0 && input[split] == L' ')
split -= 1;
if (split == 0)
continue; // ExitProcess(0);
input[split + 1] = 0;
wcscpy(command, input);
// if (swscanf(input, L"%500s -P%d", command, &processId) != 2) ExitProcess(0);
if (_wcsicmp(command, L"attach") == 0) Host::InjectProcess(processId);
else if (_wcsicmp(command, L"detach") == 0) { Host::DetachProcess(processId); }
else if (_wcsicmp(command, L"find") == 0) {
if (_wcsicmp(command, L"attach") == 0)
Host::InjectProcess(processId);
else if (_wcsicmp(command, L"detach") == 0)
{
Host::DetachProcess(processId);
}
else if (_wcsicmp(command, L"find") == 0)
{
std::shared_ptr<std::vector<std::wstring>> hooks = std::make_shared<std::vector<std::wstring>>();
try
{
Host::FindHooks(processId, sp,
[hooks](HookParam hp, std::wstring text) {
[hooks](HookParam hp, std::wstring text)
{
// if (std::regex_search(text, std::wregex(L"[\u3000-\ua000]"))) {
if (std::regex_search(text, std::wregex(L"[\u3000-\ua000]"))) {
if (std::regex_search(text, std::wregex(L"[\u3000-\ua000]")))
{
hooks->push_back(std::wstring(hp.hookcode) + L"=>" + text + L"\n");
// *hooks << sanitize(S(HookCode::Generate(hp) + L" => " + text));
}
});
}
catch (wchar_t c) { std::wcout << c; }
catch (wchar_t c)
{
std::wcout << c;
}
std::thread([hooks]
{
for (int lastSize = 0; hooks->size() == 0 || hooks->size() != lastSize; Sleep(2000)) lastSize = hooks->size();
@ -76,34 +89,40 @@ int main()
fwrite(hook.c_str(), wcslen(hook.c_str()) * sizeof(wchar_t), 1, out);
}
fclose(out);
}).detach();
fclose(out); })
.detach();
}
else {
if (command[0] == L'-') {
else
{
if (command[0] == L'-')
{
try
{
unsigned long long address;
swscanf_s(command, L"-%llu", &address);
Host::RemoveHook(processId, address);
}
catch (std::out_of_range) {}
catch (std::out_of_range)
{
}
else if (command[0] == L'=') {
}
else if (command[0] == L'=')
{
int codepage;
swscanf_s(command, L"=%d", &codepage);
Host::defaultCodepage = codepage;
}
else if (command[0] == L'+') {
else if (command[0] == L'+')
{
int flushDelay;
swscanf_s(command, L"+%d", &flushDelay);
TextThread::flushDelay = flushDelay;
}
else if (auto hp = HookCode::Parse(command)) Host::InsertHook(processId, hp.value());
else ExitProcess(0);
else if (auto hp = HookCode::Parse(command))
Host::InsertHook(processId, hp.value());
else
ExitProcess(0);
}
}
ExitProcess(0);

View File

@ -26,7 +26,7 @@ typedef void (*EmbedCallback)(const wchar_t *, ThreadParam);
wchar_t hookcode[HOOKCODE_LEN]; \
wcscpy_s(hookcode, HOOKCODE_LEN, thread.hp.hookcode); \
strcpy_s(name, HOOK_NAME_SIZE, thread.hp.name);
C_LUNA_API void Luna_Start(ProcessEvent Connect, ProcessEvent Disconnect, ThreadEvent Create, ThreadEvent Destroy, OutputCallback Output, ConsoleHandler console, HookInsertHandler hookinsert, EmbedCallback embed)
C_LUNA_API void Luna_Start(ProcessEvent Connect, ProcessEvent Disconnect, ThreadEvent Create, ThreadEvent Destroy, OutputCallback Output, ConsoleHandler console, HookInsertHandler hookinsert, EmbedCallback embed, ConsoleHandler Warning)
{
Host::StartEx(
Connect,
@ -56,6 +56,10 @@ C_LUNA_API void Luna_Start(ProcessEvent Connect, ProcessEvent Disconnect, Thread
[=](const std::wstring &output, const ThreadParam &tp)
{
embed(output.c_str(), tp);
},
[=](const std::wstring &output)
{
Warning(output.c_str());
});
}
C_LUNA_API void Luna_Inject(DWORD pid, LPCWSTR basepath)

View File

@ -7,8 +7,7 @@ namespace
class ProcessRecord
{
public:
ProcessRecord(DWORD processId, HANDLE pipe) :
pipe(pipe),
ProcessRecord(DWORD processId, HANDLE pipe) : pipe(pipe),
mappedFile2(OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, (EMBED_SHARED_MEM + std::to_wstring(processId)).c_str())),
viewMutex(ITH_HOOKMAN_MUTEX_ + std::to_wstring(processId))
@ -27,9 +26,8 @@ namespace
{
static_assert(sizeof(data) < PIPE_BUFFER_SIZE);
std::thread([=]
{
WriteFile(pipe, &data, sizeof(data), DUMMY, nullptr);
}).detach();
{ WriteFile(pipe, &data, sizeof(data), DUMMY, nullptr); })
.detach();
}
Host::HookEventHandler OnHookFound = [](HookParam hp, std::wstring text)
@ -37,8 +35,8 @@ namespace
Host::AddConsoleOutput(std::wstring(hp.hookcode) + L": " + text);
};
EmbedSharedMem *embedsharedmem;
private:
HANDLE pipe;
AutoHandle<> mappedFile2;
@ -52,12 +50,15 @@ namespace
Host::ProcessEventHandler OnConnect, OnDisconnect;
Host::ThreadEventHandler OnCreate, OnDestroy;
Host::ConsoleHandler OnConsole = 0;
Host::ConsoleHandler OnWarning = 0;
Host::HookInsertHandler HookInsert = 0;
Host::EmbedCallback embedcallback = 0;
void RemoveThreads(std::function<bool(ThreadParam)> removeIf)
{
std::vector<TextThread *> threadsToRemove;
for (auto& [tp, thread] : textThreadsByParams.Acquire().contents) if (removeIf(tp)) threadsToRemove.push_back(&thread);
for (auto &[tp, thread] : textThreadsByParams.Acquire().contents)
if (removeIf(tp))
threadsToRemove.push_back(&thread);
for (auto thread : threadsToRemove)
{
OnDestroy(*thread);
@ -141,6 +142,12 @@ namespace
Host::AddConsoleOutput(StringToWideString(info.message));
}
break;
case HOST_NOTIFICATION_WARNING:
{
auto info = *(WarningNotif*)buffer;
Host::Warning(StringToWideString(info.message));
}
break;
default:
{
auto data=(TextOutput_T*)buffer;
@ -179,8 +186,8 @@ namespace
RemoveThreads([&](ThreadParam tp) { return tp.processId == processId; });
OnDisconnect(processId);
Host::AddConsoleOutput(FormatString(PROC_DISCONN,processId));
processRecordsByIds->erase(processId);
}).detach();
processRecordsByIds->erase(processId); })
.detach();
}
}
@ -191,34 +198,47 @@ namespace Host
std::mutex procmutex;
void Start(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output, bool createconsole)
{
OnConnect = [=](auto &&...args){std::lock_guard _(procmutex);Connect(std::forward<decltype(args)>(args)...);};
OnDisconnect = [=](auto &&...args){std::lock_guard _(procmutex);Disconnect(std::forward<decltype(args)>(args)...);};
OnCreate = [=](TextThread& thread) {{std::lock_guard _(threadmutex); Create(thread);} thread.Start(); };
OnDestroy = [=](TextThread& thread) {thread.Stop(); {std::lock_guard _(threadmutex); Destroy(thread);} };
TextThread::Output = [=](auto &&...args){std::lock_guard _(outputmutex);return Output(std::forward<decltype(args)>(args)...);};
OnConnect = [=](auto &&...args)
{std::lock_guard _(procmutex);Connect(std::forward<decltype(args)>(args)...); };
OnDisconnect = [=](auto &&...args)
{std::lock_guard _(procmutex);Disconnect(std::forward<decltype(args)>(args)...); };
OnCreate = [=](TextThread &thread)
{{std::lock_guard _(threadmutex); Create(thread);} thread.Start(); };
OnDestroy = [=](TextThread &thread)
{thread.Stop(); {std::lock_guard _(threadmutex); Destroy(thread);} };
TextThread::Output = [=](auto &&...args)
{std::lock_guard _(outputmutex);return Output(std::forward<decltype(args)>(args)...); };
if(createconsole){
if (createconsole)
{
OnCreate(textThreadsByParams->try_emplace(console, console, HookParam{}, CONSOLE).first->second);
Host::AddConsoleOutput(ProjectHomePage);
}
// CreatePipe();
}
void StartEx(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output,ConsoleHandler console,HookInsertHandler hookinsert,EmbedCallback embed){
Start(Connect,Disconnect,Create,Destroy,Output,false);
OnConsole=[=](auto &&...args){std::lock_guard _(outputmutex);console(std::forward<decltype(args)>(args)...);};
HookInsert=[=](auto &&...args){std::lock_guard _(threadmutex);hookinsert(std::forward<decltype(args)>(args)...);};
embedcallback=[=](auto &&...args){std::lock_guard _(outputmutex);embed(std::forward<decltype(args)>(args)...);};
void StartEx(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output, std::optional<ConsoleHandler> console, std::optional<HookInsertHandler> hookinsert, std::optional<EmbedCallback> embed, std::optional<ConsoleHandler> warning)
{
Start(Connect, Disconnect, Create, Destroy, Output, !console.has_value());
if (warning.has_value())
OnWarning = warning.value();
if (console.has_value())
OnConsole = [=](auto &&...args)
{std::lock_guard _(outputmutex);console.value()(std::forward<decltype(args)>(args)...); };
if (hookinsert.has_value())
HookInsert = [=](auto &&...args)
{std::lock_guard _(threadmutex);hookinsert.value()(std::forward<decltype(args)>(args)...); };
if (embed.has_value())
embedcallback = [=](auto &&...args)
{std::lock_guard _(outputmutex);embed.value()(std::forward<decltype(args)>(args)...); };
}
constexpr auto PROCESS_INJECT_ACCESS=(
PROCESS_CREATE_THREAD |
constexpr auto PROCESS_INJECT_ACCESS = (PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE |
PROCESS_VM_READ);
bool SafeInject(HANDLE process,const std::wstring &location){
bool SafeInject(HANDLE process, const std::wstring &location)
{
// #ifdef _WIN64
#if 0
BOOL invalidProcess = FALSE;
@ -229,51 +249,66 @@ namespace Host
if (LPVOID remoteData = VirtualAllocEx(process, nullptr, (location.size() + 1) * sizeof(wchar_t), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))
{
WriteProcessMemory(process, remoteData, location.c_str(), (location.size() + 1) * sizeof(wchar_t), nullptr);
if (AutoHandle<> thread = CreateRemoteThread(process, nullptr, 0, (LPTHREAD_START_ROUTINE)LoadLibraryW, remoteData, 0, nullptr)){
if (AutoHandle<> thread = CreateRemoteThread(process, nullptr, 0, (LPTHREAD_START_ROUTINE)LoadLibraryW, remoteData, 0, nullptr))
{
WaitForSingleObject(thread, INFINITE);
succ = true;
}
else if (GetLastError() == ERROR_ACCESS_DENIED){
else if (GetLastError() == ERROR_ACCESS_DENIED)
{
AddConsoleOutput(NEED_64_BIT); // https://stackoverflow.com/questions/16091141/createremotethread-access-denied
succ = false;
}
VirtualFreeEx(process, remoteData, 0, MEM_RELEASE);
}
return succ;
}
bool UnSafeInject(HANDLE process,const std::wstring &location){
bool UnSafeInject(HANDLE process, const std::wstring &location)
{
DWORD64 injectedDll;
yapi::YAPICall LoadLibraryW(process, _T("kernel32.dll"), "LoadLibraryW");
if(x64)injectedDll = LoadLibraryW.Dw64()(location.c_str());
else injectedDll = LoadLibraryW(location.c_str());
if(injectedDll)return true;
if (x64)
injectedDll = LoadLibraryW.Dw64()(location.c_str());
else
injectedDll = LoadLibraryW(location.c_str());
if (injectedDll)
return true;
return false;
}
bool CheckProcess(DWORD processId)
{
if (processId == GetCurrentProcessId())
return false;
}
bool CheckProcess(DWORD processId){
if (processId == GetCurrentProcessId()) return false;
WinMutex(ITH_HOOKMAN_MUTEX_ + std::to_wstring(processId));
if (GetLastError() == ERROR_ALREADY_EXISTS){AddConsoleOutput(ALREADY_INJECTED); return false;}
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
AddConsoleOutput(ALREADY_INJECTED);
return false;
}
return true;
}
bool InjectDll(DWORD processId,const std::wstring locationX){
bool InjectDll(DWORD processId, const std::wstring locationX)
{
AutoHandle<> process = OpenProcess(PROCESS_INJECT_ACCESS, FALSE, processId);
if(!process)return false;
if (!process)
return false;
bool proc64 = Is64BitProcess(process);
auto dllname = proc64 ? LUNA_HOOK_DLL_64 : LUNA_HOOK_DLL_32;
std::wstring location = locationX.size() ? (locationX + L"\\" + dllname) : std::filesystem::path(getModuleFilename().value()).replace_filename(dllname);
AddConsoleOutput(location);
if(proc64==x64){
if (proc64 == x64)
{
return (SafeInject(process, location));
}
else{
else
{
return (UnSafeInject(process, location));
}
}
bool CreatePipeAndCheck(DWORD processId){
bool CreatePipeAndCheck(DWORD processId)
{
CreatePipe(processId);
return CheckProcess(processId);
}
@ -281,41 +316,47 @@ namespace Host
{
auto check = CreatePipeAndCheck(processId);
if(check==false)return;
if (check == false)
return;
std::thread([=]
{
if(InjectDll(processId,locationX))return ;
AddConsoleOutput(INJECT_FAILED);
}).detach();
AddConsoleOutput(INJECT_FAILED); })
.detach();
}
void DetachProcess(DWORD processId)
{
auto &prs = processRecordsByIds.Acquire().contents;
if(prs.find(processId)==prs.end())return;
if (prs.find(processId) == prs.end())
return;
prs.at(processId).Send(HOST_COMMAND_DETACH);
}
void InsertHook(DWORD processId, HookParam hp)
{
auto &prs = processRecordsByIds.Acquire().contents;
if(prs.find(processId)==prs.end())return;
if (prs.find(processId) == prs.end())
return;
prs.at(processId).Send(InsertHookCmd(hp));
}
void RemoveHook(DWORD processId, uint64_t address)
{
auto &prs = processRecordsByIds.Acquire().contents;
if(prs.find(processId)==prs.end())return;
if (prs.find(processId) == prs.end())
return;
prs.at(processId).Send(RemoveHookCmd(address));
}
void FindHooks(DWORD processId, SearchParam sp, HookEventHandler HookFound)
{
auto &prs = processRecordsByIds.Acquire().contents;
if(prs.find(processId)==prs.end())return;
if (HookFound) prs.at(processId).OnHookFound = HookFound;
if (prs.find(processId) == prs.end())
return;
if (HookFound)
prs.at(processId).OnHookFound = HookFound;
prs.at(processId).Send(FindHookCmd(sp));
}
@ -326,12 +367,16 @@ namespace Host
TextThread *GetThread(int64_t handle)
{
for (auto& [tp, thread] : textThreadsByParams.Acquire().contents) if (thread.handle == handle) return &thread;
for (auto &[tp, thread] : textThreadsByParams.Acquire().contents)
if (thread.handle == handle)
return &thread;
return nullptr;
}
EmbedSharedMem* GetEmbedSharedMem(DWORD processId){
EmbedSharedMem *GetEmbedSharedMem(DWORD processId)
{
auto &prs = processRecordsByIds.Acquire().contents;
if(prs.find(processId)==prs.end())return 0;
if (prs.find(processId) == prs.end())
return 0;
return prs.at(processId).embedsharedmem;
}
void AddConsoleOutput(std::wstring text)
@ -341,4 +386,10 @@ namespace Host
else
GetThread(console).AddSentence(std::move(text));
}
void Warning(std::wstring text)
{
if (OnWarning)
OnWarning(text);
AddConsoleOutput(L"[Warning] " + text);
}
}

View File

@ -10,7 +10,7 @@ namespace Host
using HookInsertHandler = std::function<void(uint64_t, const std::wstring &)>;
using EmbedCallback = std::function<void(const std::wstring &, const ThreadParam &)>;
void Start(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output, bool createconsole = true);
void StartEx(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output,ConsoleHandler console,HookInsertHandler hookinsert,EmbedCallback embed);
void StartEx(ProcessEventHandler Connect, ProcessEventHandler Disconnect, ThreadEventHandler Create, ThreadEventHandler Destroy, TextThread::OutputCallback Output, std::optional<ConsoleHandler> console, std::optional<HookInsertHandler> hookinsert, std::optional<EmbedCallback> embed, std::optional<ConsoleHandler> warning);
void InjectProcess(DWORD processId, const std::wstring locationX = L"");
bool CreatePipeAndCheck(DWORD processId);
@ -24,6 +24,7 @@ namespace Host
TextThread &GetThread(ThreadParam tp);
void AddConsoleOutput(std::wstring text);
void Warning(std::wstring text);
inline int defaultCodepage = SHIFT_JIS;

View File

@ -12,16 +12,17 @@ static bool RemoveRepetition(std::wstring& text)
return false;
}
TextThread::TextThread(ThreadParam tp, HookParam hp, std::optional<std::wstring> name) :
handle(threadCounter++),
TextThread::TextThread(ThreadParam tp, HookParam hp, std::optional<std::wstring> name) : handle(threadCounter++),
name(name.value_or(StringToWideString(hp.name))),
tp(tp),
hp(hp)
{}
{
}
void TextThread::Start()
{
CreateTimerQueueTimer(&timer, NULL, [](void* This, auto) { ((TextThread*)This)->Flush(); }, this, 10, 10, WT_EXECUTELONGFUNCTION);
CreateTimerQueueTimer(&timer, NULL, [](void *This, auto)
{ ((TextThread *)This)->Flush(); }, this, 10, 10, WT_EXECUTELONGFUNCTION);
}
void TextThread::Stop()
@ -36,7 +37,8 @@ void TextThread::AddSentence(std::wstring sentence)
void TextThread::Push(BYTE *data, int length)
{
if (length < 0) return;
if (length < 0)
return;
std::scoped_lock lock(bufferMutex);
BYTE doubleByteChar[2];
@ -60,15 +62,19 @@ void TextThread::Push(BYTE* data, int length)
if (converted)
{
buffer.append(converted.value());
if (hp.type & FULL_STRING && converted.value().size()>1) buffer.push_back(L'\n');
if (hp.type & FULL_STRING && converted.value().size() > 1)
buffer.push_back(L'\n');
}
else Host::AddConsoleOutput(INVALID_CODEPAGE);
else
Host::AddConsoleOutput(INVALID_CODEPAGE);
lastPushTime = GetTickCount64();
if (filterRepetition)
{
if (std::all_of(buffer.begin(), buffer.end(), [&](wchar_t ch) { return repeatingChars.find(ch) != repeatingChars.end(); })) buffer.clear();
if (std::all_of(buffer.begin(), buffer.end(), [&](wchar_t ch)
{ return repeatingChars.find(ch) != repeatingChars.end(); }))
buffer.clear();
if (RemoveRepetition(buffer)) // sentence repetition detected, which means the entire sentence has already been received
{
repeatingChars = std::unordered_set(buffer.begin(), buffer.end());
@ -96,7 +102,8 @@ void TextThread::Flush()
{
{
auto storage = this->storage.Acquire();
if (storage->size() > maxHistorySize) storage->erase(0, storage->size() - maxHistorySize); // https://github.com/Artikash/Textractor/issues/127#issuecomment-486882983
if (storage->size() > maxHistorySize)
storage->erase(0, storage->size() - maxHistorySize); // https://github.com/Artikash/Textractor/issues/127#issuecomment-486882983
}
std::vector<std::wstring> sentences;
@ -106,11 +113,13 @@ void TextThread::Flush()
{
totalSize += sentence.size();
sentence.erase(std::remove(sentence.begin(), sentence.end(), 0), sentence.end());
if (Output(*this, sentence)) storage->append(sentence+L"\n");
if (Output(*this, sentence))
storage->append(sentence + L"\n");
}
std::scoped_lock lock(bufferMutex);
if (buffer.empty()) return;
if (buffer.empty())
return;
if (buffer.size() > maxBufferSize || GetTickCount64() - lastPushTime > flushDelay)
{
AddSentence(std::move(buffer));

View File

@ -1,6 +1,5 @@
#pragma once
class TextThread
{
public:
@ -37,6 +36,9 @@ private:
std::mutex bufferMutex;
DWORD64 lastPushTime = 0;
Synchronized<std::vector<std::wstring>> queuedSentences;
struct TimerDeleter { void operator()(HANDLE h) { DeleteTimerQueueTimer(NULL, h, INVALID_HANDLE_VALUE); } };
struct TimerDeleter
{
void operator()(HANDLE h) { DeleteTimerQueueTimer(NULL, h, INVALID_HANDLE_VALUE); }
};
AutoHandle<TimerDeleter> timer = NULL;
};

View File

@ -38,7 +38,8 @@ enum HostNotificationType
HOST_NOTIFICATION_FOUND_HOOK,
HOST_NOTIFICATION_RMVHOOK,
HOST_NOTIFICATION_INSERTING_HOOK,
HOST_SETTEXTTHREADTYPE
HOST_SETTEXTTHREADTYPE,
HOST_NOTIFICATION_WARNING
};
#define NEXT_MASK(x) \
DUMMY1_##x, \

View File

@ -183,6 +183,12 @@ struct ConsoleOutputNotif // From dll
HostNotificationType command = HOST_NOTIFICATION_TEXT;
char message[MESSAGE_SIZE] = {};
};
struct WarningNotif // From dll
{
WarningNotif(std::string message = "") { strncpy_s(this->message, message.c_str(), MESSAGE_SIZE - 1); }
HostNotificationType command = HOST_NOTIFICATION_WARNING;
char message[MESSAGE_SIZE] = {};
};
struct HookFoundNotif // From dll
{