mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2025-01-13 15:43:53 +08:00
.
This commit is contained in:
parent
e8accb3ca2
commit
a7f98301a1
@ -23,16 +23,15 @@ namespace
|
|||||||
}
|
}
|
||||||
void embed_fun(hook_context *s, TextBuffer buffer)
|
void embed_fun(hook_context *s, TextBuffer buffer)
|
||||||
{
|
{
|
||||||
static std::string ts;
|
auto ts = allocateString(buffer.viewA());
|
||||||
ts = buffer.viewA();
|
|
||||||
|
|
||||||
if (_type == 1)
|
if (_type == 1)
|
||||||
{
|
{
|
||||||
s->stack[1] = (DWORD)ts.c_str();
|
s->stack[1] = (DWORD)ts;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s->ecx = (DWORD)ts.c_str();
|
s->ecx = (DWORD)ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool InsertDebonosuScenarioHook()
|
bool InsertDebonosuScenarioHook()
|
||||||
|
@ -211,7 +211,6 @@ namespace
|
|||||||
char nameText[1]; // +4*10+4*3, could be bad address though
|
char nameText[1]; // +4*10+4*3, could be bad address though
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string data_;
|
|
||||||
TextArgument *scenarioArg_,
|
TextArgument *scenarioArg_,
|
||||||
*nameArg_;
|
*nameArg_;
|
||||||
LPCSTR scenarioText_;
|
LPCSTR scenarioText_;
|
||||||
@ -265,10 +264,9 @@ namespace
|
|||||||
auto text = arg->scenarioText;
|
auto text = arg->scenarioText;
|
||||||
if (!Engine::isAddressReadable(text))
|
if (!Engine::isAddressReadable(text))
|
||||||
return;
|
return;
|
||||||
data_ = newData;
|
|
||||||
scenarioArg_ = arg;
|
scenarioArg_ = arg;
|
||||||
scenarioText_ = arg->scenarioText;
|
scenarioText_ = arg->scenarioText;
|
||||||
arg->scenarioText = (LPCSTR)data_.c_str();
|
arg->scenarioText = (LPCSTR)allocateString(newData);
|
||||||
}
|
}
|
||||||
else if (arg->nameFlag == 0)
|
else if (arg->nameFlag == 0)
|
||||||
{
|
{
|
||||||
|
@ -218,12 +218,11 @@ namespace
|
|||||||
}
|
}
|
||||||
void embed_fun(hook_context *s, TextBuffer buffer)
|
void embed_fun(hook_context *s, TextBuffer buffer)
|
||||||
{
|
{
|
||||||
static std::string data_;
|
auto data_ = buffer.strA();
|
||||||
data_ = buffer.strA();
|
|
||||||
auto arg = (HookArgument *)s->stack[1];
|
auto arg = (HookArgument *)s->stack[1];
|
||||||
if (trimmedText != arg->text)
|
if (trimmedText != arg->text)
|
||||||
data_.insert(0, std::string(arg->text, trimmedText - arg->text));
|
data_.insert(0, std::string(arg->text, trimmedText - arg->text));
|
||||||
arg->text = data_.c_str();
|
arg->text = allocateString(data_);
|
||||||
}
|
}
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
bool InsertEscudeHook()
|
bool InsertEscudeHook()
|
||||||
|
@ -176,10 +176,9 @@ namespace
|
|||||||
}
|
}
|
||||||
void hookafter1(hook_context *s, TextBuffer buffer)
|
void hookafter1(hook_context *s, TextBuffer buffer)
|
||||||
{
|
{
|
||||||
static std::string newData;
|
auto newData = buffer.strA();
|
||||||
newData = buffer.strA();
|
cache_.put(newData);
|
||||||
newData = cache_.put(newData).first;
|
s->stack[1] = (ULONG)allocateString(newData); // arg1
|
||||||
s->stack[1] = (ULONG)newData.c_str(); // arg1
|
|
||||||
}
|
}
|
||||||
} // namespace Private
|
} // namespace Private
|
||||||
|
|
||||||
|
@ -1113,7 +1113,6 @@ namespace
|
|||||||
// I need a cache retainer here to make sure same text result in same result
|
// I need a cache retainer here to make sure same text result in same result
|
||||||
void hookafter(hook_context *s, TextBuffer buffer)
|
void hookafter(hook_context *s, TextBuffer buffer)
|
||||||
{
|
{
|
||||||
static std::string data_;
|
|
||||||
static std::unordered_set<uint64_t> hashes_;
|
static std::unordered_set<uint64_t> hashes_;
|
||||||
auto text = (LPCWSTR)s->stack[1];
|
auto text = (LPCWSTR)s->stack[1];
|
||||||
if (!text || !*text || !(text[0] == 0x7 && text[1] == 0x8) && all_ascii(text))
|
if (!text || !*text || !(text[0] == 0x7 && text[1] == 0x8) && all_ascii(text))
|
||||||
@ -1171,10 +1170,8 @@ namespace
|
|||||||
data.push_back(0);
|
data.push_back(0);
|
||||||
data.push_back(0);
|
data.push_back(0);
|
||||||
data.push_back(0);
|
data.push_back(0);
|
||||||
data_ = data;
|
|
||||||
text = (LPCWSTR)data_.c_str();
|
|
||||||
|
|
||||||
s->stack[1] = (ULONG)text;
|
s->stack[1] = (ULONG)allocateString(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void hookBefore(hook_context *s, HookParam *hp, TextBuffer *buffer, uintptr_t *role)
|
void hookBefore(hook_context *s, HookParam *hp, TextBuffer *buffer, uintptr_t *role)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include"Mink.h"
|
#include "Mink.h"
|
||||||
/** 12/23/2014 jichi: Mink games (not sure the engine name)
|
/** 12/23/2014 jichi: Mink games (not sure the engine name)
|
||||||
* Sample game:
|
* Sample game:
|
||||||
* - [130111] [Mink EGO] お<EFBFBD>ちも<EFBFBD>にはぜったい言えなぁ<EFBFBD>ぁ<EFBFBD>つなこと<EFBFBD>-- /HB-4*0:64@45164A
|
* - [130111] [Mink EGO] お<EFBFBD>ちも<EFBFBD>にはぜったい言えなぁ<EFBFBD>ぁ<EFBFBD>つなこと<EFBFBD>-- /HB-4*0:64@45164A
|
||||||
@ -136,7 +136,7 @@ static bool InsertMinkDynamicHook(LPVOID fun, DWORD frame, DWORD stack)
|
|||||||
|
|
||||||
static void SpecialHookMink(hook_context *context, HookParam *hp, TextBuffer *buffer, uintptr_t *split)
|
static void SpecialHookMink(hook_context *context, HookParam *hp, TextBuffer *buffer, uintptr_t *split)
|
||||||
{
|
{
|
||||||
//DWORD addr = *(DWORD *)(esp_base + hp->offset); // default value
|
// DWORD addr = *(DWORD *)(esp_base + hp->offset); // default value
|
||||||
DWORD addr = context->eax;
|
DWORD addr = context->eax;
|
||||||
if (!IthGetMemoryRange((LPVOID)(addr), 0, 0))
|
if (!IthGetMemoryRange((LPVOID)(addr), 0, 0))
|
||||||
return;
|
return;
|
||||||
@ -154,64 +154,110 @@ static void SpecialHookMink(hook_context *context, HookParam *hp, TextBuffer *bu
|
|||||||
bool InsertMinkHook()
|
bool InsertMinkHook()
|
||||||
{
|
{
|
||||||
const BYTE bytes[] = {
|
const BYTE bytes[] = {
|
||||||
0x38,0x18, // 00451648 3818 cmp byte ptr ds:[eax],bl
|
0x38, 0x18, // 00451648 3818 cmp byte ptr ds:[eax],bl
|
||||||
0x75, 0x14, // 0045164a 75 14 jnz short .00451660 ; jichi: hook here
|
0x75, 0x14, // 0045164a 75 14 jnz short .00451660 ; jichi: hook here
|
||||||
0x38,0x5d, 0xf4, // 0045164c 385d f4 cmp byte ptr ss:[ebp-0xc],bl
|
0x38, 0x5d, 0xf4, // 0045164c 385d f4 cmp byte ptr ss:[ebp-0xc],bl
|
||||||
0x74, 0x07, // 0045164f 74 07 je short .00451658
|
0x74, 0x07, // 0045164f 74 07 je short .00451658
|
||||||
0x8b,0x45, 0xf0, // 00451651 8b45 f0 mov eax,dword ptr ss:[ebp-0x10]
|
0x8b, 0x45, 0xf0, // 00451651 8b45 f0 mov eax,dword ptr ss:[ebp-0x10]
|
||||||
0x83,0x60, 0x70, 0xfd, // 00451654 8360 70 fd and dword ptr ds:[eax+0x70],0xfffffffd
|
0x83, 0x60, 0x70, 0xfd, // 00451654 8360 70 fd and dword ptr ds:[eax+0x70],0xfffffffd
|
||||||
0x8b,0x45, 0x08 // 00451658 8b45 08 mov eax,dword ptr ss:[ebp+0x8]
|
0x8b, 0x45, 0x08 // 00451658 8b45 08 mov eax,dword ptr ss:[ebp+0x8]
|
||||||
|
};
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
addr_offset = 2
|
||||||
};
|
};
|
||||||
enum { addr_offset = 2 };
|
|
||||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||||||
//ULONG addr = 0x45164a;
|
// ULONG addr = 0x45164a;
|
||||||
//ULONG addr = 0x451648;
|
// ULONG addr = 0x451648;
|
||||||
//ULONG addr = 0x4521a8;
|
// ULONG addr = 0x4521a8;
|
||||||
//GROWL_DWORD(addr);
|
// GROWL_DWORD(addr);
|
||||||
if (!addr) {
|
if (!addr)
|
||||||
|
{
|
||||||
ConsoleOutput("Mink: pattern not found");
|
ConsoleOutput("Mink: pattern not found");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
HookParam hp;
|
HookParam hp;
|
||||||
hp.address = addr + addr_offset;
|
hp.address = addr + addr_offset;
|
||||||
hp.offset=regoffset(eax); // -8
|
hp.offset = regoffset(eax); // -8
|
||||||
hp.split = 0x64;
|
hp.split = 0x64;
|
||||||
hp.type = USING_SPLIT|DATA_INDIRECT|USING_CHAR; // 0x18
|
hp.type = USING_SPLIT | DATA_INDIRECT | USING_CHAR; // 0x18
|
||||||
hp.text_fun = SpecialHookMink;
|
hp.text_fun = SpecialHookMink;
|
||||||
ConsoleOutput("INSERT Mink");
|
ConsoleOutput("INSERT Mink");
|
||||||
return NewHook(hp, "Mink");
|
return NewHook(hp, "Mink");
|
||||||
|
|
||||||
//ConsoleOutput("Mink: disable GDI hooks");
|
// ConsoleOutput("Mink: disable GDI hooks");
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mink2::attach_function() {
|
bool Mink2::attach_function()
|
||||||
|
{
|
||||||
const BYTE pattern[] = {
|
const BYTE pattern[] = {
|
||||||
//破談屋
|
// 破談屋
|
||||||
//https://vndb.org/v2719
|
// https://vndb.org/v2719
|
||||||
0xF7,0xC7,0x03,0x00,0x00,0x00,
|
0xF7, 0xC7, 0x03, 0x00, 0x00, 0x00,
|
||||||
0x75,XX,
|
0x75, XX,
|
||||||
0xC1,0xE9,0x02,
|
0xC1, 0xE9, 0x02,
|
||||||
0x83,0xE2,0x03,
|
0x83, 0xE2, 0x03,
|
||||||
0x83,0xF9,0x08,
|
0x83, 0xF9, 0x08,
|
||||||
0x72,XX
|
0x72, XX};
|
||||||
};
|
bool found = false;
|
||||||
bool found=false;
|
|
||||||
for (auto addr : Util::SearchMemory(pattern, sizeof(pattern), PAGE_EXECUTE, processStartAddress, processStopAddress))
|
for (auto addr : Util::SearchMemory(pattern, sizeof(pattern), PAGE_EXECUTE, processStartAddress, processStopAddress))
|
||||||
{
|
{
|
||||||
addr = MemDbg::findEnclosingAlignedFunction(addr,0x100);
|
addr = MemDbg::findEnclosingAlignedFunction(addr, 0x100);
|
||||||
if (addr == 0)return false;
|
if (addr == 0)
|
||||||
|
return false;
|
||||||
HookParam hp;
|
HookParam hp;
|
||||||
hp.address = addr;
|
hp.address = addr;
|
||||||
hp.offset=stackoffset(2);
|
hp.offset = stackoffset(2);
|
||||||
hp.length_offset=3;
|
hp.length_offset = 3;
|
||||||
hp.type = USING_STRING;
|
hp.type = USING_STRING;
|
||||||
found|=NewHook(hp, "Mink");
|
found |= NewHook(hp, "Mink");
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
bool Mink::attach_function() {
|
bool Mink::attach_function()
|
||||||
|
{
|
||||||
|
|
||||||
return InsertMinkHook();
|
return InsertMinkHook();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Mink3::attach_function()
|
||||||
|
{
|
||||||
|
const BYTE pattern[] = {
|
||||||
|
// 夜勤病棟 復刻版+
|
||||||
|
0xff, 0x15, XX4,
|
||||||
|
0x33, 0xdb,
|
||||||
|
0x89, 0x44, 0x24, XX,
|
||||||
|
0x85, 0xc0,
|
||||||
|
0x7e, XX,
|
||||||
|
0x8a, 0x07,
|
||||||
|
0x8d, 0x4c, 0x24, 0x10,
|
||||||
|
0x50,
|
||||||
|
0xe8, XX4,
|
||||||
|
0x83, 0xf8, 0x02,
|
||||||
|
0x75, 0x08,
|
||||||
|
0x03, 0xd8,
|
||||||
|
0x03, 0xf8,
|
||||||
|
0x03, 0xf0,
|
||||||
|
0xeb, XX,
|
||||||
|
0x57,
|
||||||
|
0x8b, 0xcd,
|
||||||
|
0xe8, XX4,
|
||||||
|
0x25, 0xff, 0x00, 0x00, 0x00,
|
||||||
|
0x83, 0xe8, 0x00};
|
||||||
|
auto addr = MemDbg::findBytes(pattern, sizeof(pattern), processStartAddress, processStopAddress);
|
||||||
|
if (!addr)
|
||||||
|
return false;
|
||||||
|
addr = MemDbg::findEnclosingAlignedFunction(addr, 0x100);
|
||||||
|
if (!addr)
|
||||||
|
return false;
|
||||||
|
HookParam hp;
|
||||||
|
hp.address = addr;
|
||||||
|
hp.offset = stackoffset(1);
|
||||||
|
hp.type = USING_STRING | EMBED_ABLE | EMBED_AFTER_OVERWRITE | EMBED_DYNA_SJIS;
|
||||||
|
hp.embed_hook_font = F_TextOutA;
|
||||||
|
hp.lineSeparator = L"\\n";
|
||||||
|
PcHooks::hookGDIFunctions(TextOutA);
|
||||||
|
return NewHook(hp, "Mink");
|
||||||
|
}
|
@ -1,22 +1,38 @@
|
|||||||
|
|
||||||
|
|
||||||
class Mink:public ENGINE{
|
class Mink : public ENGINE
|
||||||
public:
|
{
|
||||||
Mink(){
|
public:
|
||||||
|
Mink()
|
||||||
|
{
|
||||||
|
|
||||||
check_by=CHECK_BY::FILE;
|
check_by = CHECK_BY::FILE;
|
||||||
check_by_target=L"*.at2";//Mink, sample files: voice.at2, voice.det, voice.nme
|
check_by_target = L"*.at2"; // Mink, sample files: voice.at2, voice.det, voice.nme
|
||||||
};
|
};
|
||||||
bool attach_function();
|
bool attach_function();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Mink2:public ENGINE{
|
class Mink2 : public ENGINE
|
||||||
public:
|
{
|
||||||
Mink2(){
|
public:
|
||||||
|
Mink2()
|
||||||
|
{
|
||||||
|
|
||||||
check_by=CHECK_BY::FILE;
|
check_by = CHECK_BY::FILE;
|
||||||
check_by_target=L"Scr\\*.sc";
|
check_by_target = L"Scr\\*.sc";
|
||||||
is_engine_certain=false;
|
is_engine_certain = false;
|
||||||
|
};
|
||||||
|
bool attach_function();
|
||||||
|
};
|
||||||
|
class Mink3 : public ENGINE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mink3()
|
||||||
|
{
|
||||||
|
// 夜勤病棟 復刻版+
|
||||||
|
check_by = CHECK_BY::FILE_ALL;
|
||||||
|
check_by_target = check_by_list{L"voice*.dat", L"tpd.dat", L"tms.dat", L"thm.dat", L"se.dat", L"scr.dat", L"rec.dat", L"bgm.dat", L"cgm.dat", L"gpd.dat", L"gpdtp.dat", L"mov.dat", L"msk.dat", L"msktp.dat", L"read.dat"};
|
||||||
|
is_engine_certain = false;
|
||||||
};
|
};
|
||||||
bool attach_function();
|
bool attach_function();
|
||||||
};
|
};
|
@ -746,10 +746,8 @@ namespace
|
|||||||
newData = newData + "[n]";
|
newData = newData + "[n]";
|
||||||
else if (endtype == 2)
|
else if (endtype == 2)
|
||||||
newData = newData + "[c]";
|
newData = newData + "[c]";
|
||||||
static std::string data_;
|
s->edx = (ULONG)allocateString(newData); // reset arg1
|
||||||
data_ = newData;
|
*(DWORD *)(s->edx - 4) = newData.size();
|
||||||
s->edx = (ULONG)data_.c_str(); // reset arg1
|
|
||||||
*(DWORD *)(s->edx - 4) = data_.size();
|
|
||||||
// arg->size = data_.size(); // no idea why this will crash ...
|
// arg->size = data_.size(); // no idea why this will crash ...
|
||||||
|
|
||||||
//*(DWORD *)(s->edx - 4) = newData.size() + trimmedText - text;
|
//*(DWORD *)(s->edx - 4) = newData.size() + trimmedText - text;
|
||||||
|
@ -1764,11 +1764,7 @@ namespace
|
|||||||
void hookafter(hook_context *s, TextBuffer buffer)
|
void hookafter(hook_context *s, TextBuffer buffer)
|
||||||
{
|
{
|
||||||
auto arg = (TextUnionW *)(type_ == Type1 ? s->ecx : s->stack[1]);
|
auto arg = (TextUnionW *)(type_ == Type1 ? s->ecx : s->stack[1]);
|
||||||
auto argValue = *arg;
|
|
||||||
arg->setText(buffer.viewW());
|
arg->setText(buffer.viewW());
|
||||||
|
|
||||||
// Restoring is indispensible, and as a result, the default hook does not work
|
|
||||||
//*arg = argValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool attach(ULONG startAddress, ULONG stopAddress) // attach scenario
|
bool attach(ULONG startAddress, ULONG stopAddress) // attach scenario
|
||||||
@ -1794,8 +1790,6 @@ namespace OtherHook
|
|||||||
namespace Private
|
namespace Private
|
||||||
{
|
{
|
||||||
|
|
||||||
TextUnionW *arg_,
|
|
||||||
argValue_;
|
|
||||||
void hookBefore(hook_context *s, HookParam *hp, TextBuffer *buffer, uintptr_t *role)
|
void hookBefore(hook_context *s, HookParam *hp, TextBuffer *buffer, uintptr_t *role)
|
||||||
{
|
{
|
||||||
static std::wstring text_;
|
static std::wstring text_;
|
||||||
@ -1833,8 +1827,6 @@ namespace OtherHook
|
|||||||
void hookafter2(hook_context *s, TextBuffer buffer)
|
void hookafter2(hook_context *s, TextBuffer buffer)
|
||||||
{
|
{
|
||||||
auto arg = (TextUnionW *)s->stack[0];
|
auto arg = (TextUnionW *)s->stack[0];
|
||||||
arg_ = arg;
|
|
||||||
argValue_ = *arg;
|
|
||||||
arg->setText(buffer.viewW());
|
arg->setText(buffer.viewW());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,13 +211,11 @@ namespace
|
|||||||
}
|
}
|
||||||
void hookafter(hook_context *s, TextBuffer buffer)
|
void hookafter(hook_context *s, TextBuffer buffer)
|
||||||
{
|
{
|
||||||
static std::string data_;
|
|
||||||
std::string newData = buffer.strA();
|
std::string newData = buffer.strA();
|
||||||
data_ = newData;
|
|
||||||
int capacity = s->stack[1]; // arg 2, should always be 0x1000
|
int capacity = s->stack[1]; // arg 2, should always be 0x1000
|
||||||
if (data_.size() >= capacity)
|
if (newData.size() >= capacity)
|
||||||
data_ = data_.substr(0, capacity - 1);
|
newData = newData.substr(0, capacity - 1);
|
||||||
s->stack[2] = (ULONG)data_.c_str(); // arg 3
|
s->stack[2] = (ULONG)allocateString(newData); // arg 3
|
||||||
}
|
}
|
||||||
} // namespace Private
|
} // namespace Private
|
||||||
|
|
||||||
|
@ -575,9 +575,8 @@ namespace
|
|||||||
|
|
||||||
void hookafter(hook_context *s, TextBuffer buffer)
|
void hookafter(hook_context *s, TextBuffer buffer)
|
||||||
{
|
{
|
||||||
static std::string data_;
|
auto data_ = buffer.strA();
|
||||||
data_ = buffer.strA();
|
s->stack[1] = (ULONG)allocateString(data_);
|
||||||
s->stack[1] = (ULONG)data_.c_str();
|
|
||||||
s->stack[2] = data_.size();
|
s->stack[2] = data_.size();
|
||||||
}
|
}
|
||||||
} // namespace Private
|
} // namespace Private
|
||||||
|
@ -834,7 +834,7 @@ namespace
|
|||||||
if (suffixSize)
|
if (suffixSize)
|
||||||
newText.append(std::wstring(trimmedText + trimmedSize, suffixSize));
|
newText.append(std::wstring(trimmedText + trimmedSize, suffixSize));
|
||||||
info->text_ = newText;
|
info->text_ = newText;
|
||||||
s->stack[info->stackIndex_] = (ULONG)info->text_.c_str();
|
s->stack[info->stackIndex_] = (ULONG)allocateString(info->text_);
|
||||||
}
|
}
|
||||||
// explicit TextHookW(int hookStackIndex, int role = Engine::UnknownRole) : stackIndex_(hookStackIndex), role_(role) {}
|
// explicit TextHookW(int hookStackIndex, int role = Engine::UnknownRole) : stackIndex_(hookStackIndex), role_(role) {}
|
||||||
template <int _type>
|
template <int _type>
|
||||||
|
@ -428,6 +428,7 @@ std::vector<ENGINE *> check_engines()
|
|||||||
new DAC,
|
new DAC,
|
||||||
new AbogadoPowers,
|
new AbogadoPowers,
|
||||||
new e_Erekiteru,
|
new e_Erekiteru,
|
||||||
new H_do_C
|
new H_do_C,
|
||||||
|
new Mink3,
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
set(VERSION_MAJOR 6)
|
set(VERSION_MAJOR 6)
|
||||||
set(VERSION_MINOR 17)
|
set(VERSION_MINOR 17)
|
||||||
set(VERSION_PATCH 4)
|
set(VERSION_PATCH 5)
|
||||||
set(VERSION_REVISION 0)
|
set(VERSION_REVISION 0)
|
||||||
set(LUNA_VERSION "{${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_REVISION}}")
|
set(LUNA_VERSION "{${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_REVISION}}")
|
||||||
add_library(VERSION_DEF ${CMAKE_CURRENT_LIST_DIR}/version_def.cpp)
|
add_library(VERSION_DEF ${CMAKE_CURRENT_LIST_DIR}/version_def.cpp)
|
||||||
|
@ -245,4 +245,8 @@ The following commands remove the OCR pack for "en-US":
|
|||||||
|
|
||||||
https://learn.microsoft.com/en-us/windows/powertoys/text-extractor#supported-languages
|
https://learn.microsoft.com/en-us/windows/powertoys/text-extractor#supported-languages
|
||||||
|
|
||||||
|
#### **Tesseract5**
|
||||||
|
|
||||||
|
https://github.com/tesseract-ocr/tesseract/releases
|
||||||
|
|
||||||
<!-- tabs:end -->
|
<!-- tabs:end -->
|
@ -246,4 +246,8 @@ State : NotPresent
|
|||||||
|
|
||||||
https://learn.microsoft.com/ja-jp/windows/powertoys/text-extractor#supported-languages
|
https://learn.microsoft.com/ja-jp/windows/powertoys/text-extractor#supported-languages
|
||||||
|
|
||||||
|
#### **Tesseract5**
|
||||||
|
|
||||||
|
https://github.com/tesseract-ocr/tesseract/releases
|
||||||
|
|
||||||
<!-- tabs:end -->
|
<!-- tabs:end -->
|
||||||
|
@ -281,5 +281,9 @@ State : NotPresent
|
|||||||
|
|
||||||
https://learn.microsoft.com/zh-cn/windows/powertoys/text-extractor#supported-languages
|
https://learn.microsoft.com/zh-cn/windows/powertoys/text-extractor#supported-languages
|
||||||
|
|
||||||
|
#### **Tesseract5**
|
||||||
|
|
||||||
|
https://github.com/tesseract-ocr/tesseract/releases
|
||||||
|
|
||||||
<!-- tabs:end -->
|
<!-- tabs:end -->
|
||||||
|
|
||||||
|
@ -294,7 +294,10 @@ def delayloadlinks(key, lay):
|
|||||||
else:
|
else:
|
||||||
for link in source["links"]:
|
for link in source["links"]:
|
||||||
__grid.append(
|
__grid.append(
|
||||||
[link["name"], (makehtml(link["link"]), 2, "link")]
|
[
|
||||||
|
link["name"],
|
||||||
|
(makehtml(link["link"], link.get("vis", None)), 2, "link"),
|
||||||
|
]
|
||||||
+ ([link.get("about")] if link.get("about") else [])
|
+ ([link.get("about")] if link.get("about") else [])
|
||||||
)
|
)
|
||||||
grid.append(
|
grid.append(
|
||||||
|
@ -1,37 +1,110 @@
|
|||||||
import os, uuid, gobject
|
import os, uuid, gobject, winreg
|
||||||
from myutils.config import _TR, ocrsetting
|
from myutils.config import _TR, globalconfig
|
||||||
from ocrengines.baseocrclass import baseocr
|
from ocrengines.baseocrclass import baseocr
|
||||||
from myutils.subproc import subproc_w
|
from myutils.subproc import subproc_w
|
||||||
|
from language import Languages
|
||||||
|
|
||||||
def list_langs():
|
|
||||||
path = ocrsetting["tesseract5"]["args"]["路径"]
|
|
||||||
if os.path.exists(path) == False:
|
|
||||||
return []
|
|
||||||
res = subproc_w(
|
|
||||||
'"{}" --list-langs'.format(path), needstdio=True, run=True, encoding="utf8"
|
|
||||||
).stdout
|
|
||||||
return res.split("\n")[1:-1]
|
|
||||||
|
|
||||||
|
|
||||||
class OCR(baseocr):
|
class OCR(baseocr):
|
||||||
|
|
||||||
|
def findts__(self):
|
||||||
|
k = winreg.OpenKeyEx(
|
||||||
|
winreg.HKEY_LOCAL_MACHINE,
|
||||||
|
r"SOFTWARE\Tesseract-OCR",
|
||||||
|
0,
|
||||||
|
winreg.KEY_QUERY_VALUE,
|
||||||
|
)
|
||||||
|
base = winreg.QueryValueEx(k, "Path")[0]
|
||||||
|
winreg.CloseKey(k)
|
||||||
|
return base
|
||||||
|
|
||||||
|
def findts(self):
|
||||||
|
try:
|
||||||
|
_ = self.findts__()
|
||||||
|
_ = os.path.join(_, "tesseract.exe")
|
||||||
|
return _
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
|
||||||
|
def list_langs(self):
|
||||||
|
if not (self.path and os.path.exists(self.path)):
|
||||||
|
raise Exception(_TR("路径不存在"))
|
||||||
|
res = subproc_w(
|
||||||
|
'"{}" --list-langs'.format(self.path),
|
||||||
|
needstdio=True,
|
||||||
|
run=True,
|
||||||
|
encoding="utf8",
|
||||||
|
).stdout
|
||||||
|
return res.split("\n")[1:-1]
|
||||||
|
|
||||||
|
def langmap(self):
|
||||||
|
# https://github.com/tesseract-ocr/tessdoc/blob/main/tess3/Data-Files.md
|
||||||
|
return {
|
||||||
|
Languages.Chinese: "chi_sim",
|
||||||
|
Languages.TradChinese: "chi_tra",
|
||||||
|
Languages.Japanese: "jpn",
|
||||||
|
Languages.English: "eng",
|
||||||
|
Languages.Russian: "rus",
|
||||||
|
Languages.Korean: "kor",
|
||||||
|
Languages.Arabic: "ara",
|
||||||
|
Languages.Italian: "ita",
|
||||||
|
Languages.Polish: "pol",
|
||||||
|
Languages.Spanish: "spa",
|
||||||
|
Languages.Swedish: "swe",
|
||||||
|
Languages.Ukrainian: "ukr",
|
||||||
|
Languages.Vietnamese: "vie",
|
||||||
|
Languages.French: "fra",
|
||||||
|
Languages.Turkish: "tur",
|
||||||
|
Languages.German: "deu",
|
||||||
|
Languages.Dutch: "nld",
|
||||||
|
Languages.Portuguese: "por",
|
||||||
|
Languages.Czech: "ces",
|
||||||
|
Languages.Hungarian: "hun",
|
||||||
|
Languages.Thai: "tha",
|
||||||
|
Languages.Latin: "lat",
|
||||||
|
}
|
||||||
|
|
||||||
def initocr(self):
|
def initocr(self):
|
||||||
self.langs = list_langs()
|
self.path = self.findts()
|
||||||
|
self.langs = self.list_langs()
|
||||||
|
print(self.langs)
|
||||||
|
|
||||||
def ocr(self, imagebinary):
|
def ocr(self, imagebinary):
|
||||||
self.checkempty(["路径"])
|
if not (self.path and os.path.exists(self.path)):
|
||||||
path = self.config["路径"]
|
raise Exception(_TR("not installed"))
|
||||||
if os.path.exists(path) == False:
|
self.raise_cant_be_auto_lang()
|
||||||
raise Exception(_TR("路径不存在"))
|
lang = self.srclang
|
||||||
|
psm = 6
|
||||||
|
imgfile = None
|
||||||
|
if globalconfig["verticalocr"] == 0:
|
||||||
|
pass
|
||||||
|
elif globalconfig["verticalocr"] == 1:
|
||||||
|
lang += "_vert"
|
||||||
|
psm = 5
|
||||||
|
elif globalconfig["verticalocr"] == 2:
|
||||||
fname = gobject.gettempdir(str(uuid.uuid4()) + ".png")
|
fname = gobject.gettempdir(str(uuid.uuid4()) + ".png")
|
||||||
with open(fname, "wb") as ff:
|
with open(fname, "wb") as ff:
|
||||||
ff.write(imagebinary)
|
ff.write(imagebinary)
|
||||||
imgfile = os.path.abspath(fname)
|
imgfile = os.path.abspath(fname)
|
||||||
_ = subproc_w(
|
_ = subproc_w(
|
||||||
'"{}" "{}" - -l {} {}'.format(
|
'"{}" "{}" stdout -l osd --psm 0'.format(self.path, imgfile),
|
||||||
path, imgfile, self.langs[self.config["语言"]], self.config["附加参数"]
|
needstdio=True,
|
||||||
),
|
encoding="utf8",
|
||||||
|
run=True,
|
||||||
|
)
|
||||||
|
err = _.stderr
|
||||||
|
if len(err):
|
||||||
|
pass
|
||||||
|
elif "Orientation in degrees: 0" not in _.stdout:
|
||||||
|
lang += "_vert"
|
||||||
|
psm = 5
|
||||||
|
if not imgfile:
|
||||||
|
fname = gobject.gettempdir(str(uuid.uuid4()) + ".png")
|
||||||
|
with open(fname, "wb") as ff:
|
||||||
|
ff.write(imagebinary)
|
||||||
|
imgfile = os.path.abspath(fname)
|
||||||
|
_ = subproc_w(
|
||||||
|
'"{}" "{}" - -l {} --psm {}'.format(self.path, imgfile, lang, psm),
|
||||||
needstdio=True,
|
needstdio=True,
|
||||||
encoding="utf8",
|
encoding="utf8",
|
||||||
run=True,
|
run=True,
|
||||||
|
@ -150,27 +150,6 @@
|
|||||||
"Secret Access Key": ""
|
"Secret Access Key": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tesseract5": {
|
|
||||||
"args": {
|
|
||||||
"路径": "",
|
|
||||||
"语言": 0,
|
|
||||||
"附加参数": "--psm 6"
|
|
||||||
},
|
|
||||||
"argstype": {
|
|
||||||
"路径": {
|
|
||||||
"type": "file",
|
|
||||||
"dir": false,
|
|
||||||
"filter": "tesseract.exe"
|
|
||||||
},
|
|
||||||
"语言": {
|
|
||||||
"type": "combo",
|
|
||||||
"list_function": [
|
|
||||||
"ocrengines.tesseract5",
|
|
||||||
"list_langs"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"googlecloudvision": {
|
"googlecloudvision": {
|
||||||
"args": {
|
"args": {
|
||||||
"key": ""
|
"key": ""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user