From ddbe526e27d89a66d004c8d4d5a486f476dfa0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <1173718158@qq.com> Date: Mon, 23 Dec 2024 14:24:12 +0800 Subject: [PATCH] . --- cpp/LunaHook/LunaHook/engine64/vita3k.cpp | 23 +++ cpp/shareddllproxy/Atlas.cpp | 6 +- cpp/shareddllproxy/CMakeLists.txt | 2 +- cpp/shareddllproxy/dreye.cpp | 9 +- cpp/shareddllproxy/eztrans.cpp | 6 +- cpp/shareddllproxy/jbj7.cpp | 6 +- cpp/shareddllproxy/lec.cpp | 227 ++++++++++++++++++++++ cpp/shareddllproxy/neospeech.cpp | 6 +- cpp/shareddllproxy/shareddllproxy.cpp | 2 + cpp/version.cmake | 2 +- py/LunaTranslator/translator/atlas.py | 71 +++---- py/LunaTranslator/translator/dreye.py | 7 +- py/LunaTranslator/translator/kingsoft.py | 2 +- py/LunaTranslator/translator/lec.py | 62 ++++++ py/files/defaultconfig/config.json | 6 + 15 files changed, 370 insertions(+), 67 deletions(-) create mode 100644 cpp/shareddllproxy/lec.cpp create mode 100644 py/LunaTranslator/translator/lec.py diff --git a/cpp/LunaHook/LunaHook/engine64/vita3k.cpp b/cpp/LunaHook/LunaHook/engine64/vita3k.cpp index 1143a1a0..08ae77d7 100644 --- a/cpp/LunaHook/LunaHook/engine64/vita3k.cpp +++ b/cpp/LunaHook/LunaHook/engine64/vita3k.cpp @@ -276,6 +276,20 @@ namespace { CharFilter(buffer, '\n'); } + void PCSG01068(TextBuffer *buffer, HookParam *hp) + { + StringCharReplacer(buffer, "\\\\", 2, '\n'); + CharFilter(buffer, '\\'); + auto s = buffer->viewA(); + if (endWith(s, u8"。!")) + buffer->from(s.substr(0, s.size() - 1)); + } + void PCSG01167(TextBuffer *buffer, HookParam *hp) + { + auto s = buffer->strA(); + s = std::regex_replace(s, std::regex(u8R"(<(.*?)>(.*?)\|)"), "$2"); + buffer->from(s); + } void PCSG00917(TextBuffer *buffer, HookParam *hp) { auto s = buffer->strA(); @@ -772,6 +786,15 @@ namespace {0x8001701C, {CODEC_UTF8, 1, 0, 0, PCSG00787, "PCSG00561"}}, // ハートの国のアリス~Wonderful Wonder World~ {0x8100F0CA, {CODEC_UTF8, 1, 0, 0, PCSG00787, "PCSG00614"}}, // 手动解压 + {0x800173F4, {CODEC_UTF8, 1, 0, 0, PCSG00787, "PCSG00614"}}, + // 新装版魔法使いとご主人様~Wizard and The Master~ + {0x8001733C, {CODEC_UTF8, 1, 0, 0, PCSG00787, "PCSG00580"}}, + // 円環のメモーリア -カケラ灯し- + {0x80029AB2, {0, 0, 0, 0, PCSG01167, "PCSG01167"}}, + // ネオ アンジェリーク 天使の涙 + {0x8005426C, {CODEC_UTF8, 0, 0, 0, PCSG01068, "PCSG01068"}}, + // スカーレッドライダーゼクス Rev. + {0x800BEE38, {CODEC_UTF8, 0, 0, 0, PCSG00787, "PCSG00745"}}, }; return 1; }(); diff --git a/cpp/shareddllproxy/Atlas.cpp b/cpp/shareddllproxy/Atlas.cpp index f160f628..dedf10c9 100644 --- a/cpp/shareddllproxy/Atlas.cpp +++ b/cpp/shareddllproxy/Atlas.cpp @@ -538,10 +538,8 @@ int atlaswmain(int argc, wchar_t *argv[]) HANDLE hPipe = CreateNamedPipe(argv[1], PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65535, 65535, NMPWAIT_WAIT_FOREVER, 0); SetEvent(CreateEvent(&allAccess, FALSE, FALSE, argv[2])); - if (ConnectNamedPipe(hPipe, NULL) != NULL) - { - DWORD len = 0; - } + if (!ConnectNamedPipe(hPipe, NULL)) + return 0; while (true) { wchar_t src[4096] = {0}; diff --git a/cpp/shareddllproxy/CMakeLists.txt b/cpp/shareddllproxy/CMakeLists.txt index 6a425732..83b1756e 100644 --- a/cpp/shareddllproxy/CMakeLists.txt +++ b/cpp/shareddllproxy/CMakeLists.txt @@ -17,7 +17,7 @@ if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) add_executable(shareddllproxy ${shareddllproxy_common}) else() - add_executable(shareddllproxy ${shareddllproxy_common} Atlas.cpp eztrans.cpp dreye.cpp jbj7.cpp kingsoft.cpp neospeech.cpp ../implsapi.cpp) + add_executable(shareddllproxy ${shareddllproxy_common} lec.cpp Atlas.cpp eztrans.cpp dreye.cpp jbj7.cpp kingsoft.cpp neospeech.cpp ../implsapi.cpp) add_subdirectory(voiceroid2) endif() diff --git a/cpp/shareddllproxy/dreye.cpp b/cpp/shareddllproxy/dreye.cpp index 8b56008d..f1993a2a 100644 --- a/cpp/shareddllproxy/dreye.cpp +++ b/cpp/shareddllproxy/dreye.cpp @@ -4,7 +4,6 @@ extern "C" typedef int(__stdcall *TranTextFlowCJ)(char *src, char *dest, int, int); } - int dreyewmain(int argc, wchar_t *argv[]) { SetCurrentDirectory(argv[1]); @@ -30,12 +29,10 @@ int dreyewmain(int argc, wchar_t *argv[]) _MTInitCJ(_wtoi(argv[3])); HANDLE hPipe = CreateNamedPipe(argv[4], PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65535, 65535, NMPWAIT_WAIT_FOREVER, 0); - + SetEvent(CreateEvent(&allAccess, FALSE, FALSE, argv[5])); - if (ConnectNamedPipe(hPipe, NULL) != NULL) - { - DWORD len = 0; - } + if (!ConnectNamedPipe(hPipe, NULL)) + return 0; while (true) { char src[4096] = {0}; diff --git a/cpp/shareddllproxy/eztrans.cpp b/cpp/shareddllproxy/eztrans.cpp index 0e4be9bb..dbac9471 100644 --- a/cpp/shareddllproxy/eztrans.cpp +++ b/cpp/shareddllproxy/eztrans.cpp @@ -690,10 +690,8 @@ int eztrans(int argc, wchar_t *argv[]) TransEngine->Init(_p); SetEvent(CreateEvent(&allAccess, FALSE, FALSE, argv[3])); - if (ConnectNamedPipe(hPipe, NULL) != NULL) - { - DWORD len = 0; - } + if (!ConnectNamedPipe(hPipe, NULL)) + return 0; WCHAR buff[6000]; while (true) { diff --git a/cpp/shareddllproxy/jbj7.cpp b/cpp/shareddllproxy/jbj7.cpp index ddb77477..395c8136 100644 --- a/cpp/shareddllproxy/jbj7.cpp +++ b/cpp/shareddllproxy/jbj7.cpp @@ -38,10 +38,8 @@ int jbjwmain(int argc, wchar_t *argv[]) wchar_t *buf = new wchar_t[3000]; SetEvent(CreateEvent(&allAccess, FALSE, FALSE, argv[3])); - if (ConnectNamedPipe(hPipe, NULL) != NULL) - { - DWORD len = 0; - } + if (!ConnectNamedPipe(hPipe, NULL)) + return 0; unsigned char intcache[4]; while (true) { diff --git a/cpp/shareddllproxy/lec.cpp b/cpp/shareddllproxy/lec.cpp new file mode 100644 index 00000000..84ff0b72 --- /dev/null +++ b/cpp/shareddllproxy/lec.cpp @@ -0,0 +1,227 @@ +// https://github.com/uyjulian/LECTranslate + +// #if 1 +// // Jp->En engine +// #define CODEPAGE 932 +// #define PATH "Nova\\JaEn\\EngineDll_je.dll" +// #else +// // Ko->En engine +// #define CODEPAGE 949 +// #define PATH "Nova\\KoEn\\keeglib.dll" +// #endif +int CODEPAGE; +char *PATH; +typedef int(__cdecl *eg_init_t)(const char *path); +typedef int(__cdecl *eg_init2_t)(const char *path, int); +typedef int(__cdecl *eg_end_t)(); +typedef int(__cdecl *eg_translate_multi_t)(int, const char *in, size_t out_size, char *out); +// typedef int(__cdecl *eg_translate_one_t)(int, const char *in, const char *, size_t out_size, char *out, void*, void*); +// typedef int(__cdecl *eg_setcallback_t)(int(__cdecl *callback)()); +HMODULE hLEC; +eg_end_t eg_end; +eg_translate_multi_t eg_translate_multi; +int lecState; // 0 - not initialized, 1 - ready, -1 - not available; + +wchar_t *LECTranslateFull(wchar_t *src) +{ + size_t src_size = wcslen(src) + 1, dst_size; + // direct engine call doesn't handle those characters well + // better handling would be manual sentence splitting with + // brackets content replacement with signle symbol which is + // replaced back after independent translation of content + for (size_t i = 0; i < src_size; i++) + { + switch (src[i]) + { + case L'『': // src[i] = L'{'; break; + case L'「': + case L'「': + src[i] = L'['; + break; + case L'』': // src[i] = L'}'; break; + case L'」': + case L'」': + src[i] = L']'; + break; + case L'≪': + case L'(': + src[i] = L'('; + break; + case L'≫': + case L')': + src[i] = L')'; + break; + case L'…': + src[i] = L' '; + break; + case L':': + src[i] = L'¦'; + break; + case L'・': + src[i] = L'.'; + break; + } + } + char *src_buf = (char *)malloc(src_size * 2); + WideCharToMultiByte(CODEPAGE, 0, src, src_size, src_buf, src_size * 2, "_", NULL); + + // we have no idea how much buffer we actually need here + // src_size*3 looks like a good guess, but let's play it a bit more safe + char *dst_buf = NULL; + for (size_t size = src_size * 4 + 0x100;;) + { + char *d = (char *)realloc(dst_buf, size); + if (!d) + break; + dst_buf = d; + // window_->eg_translate_one(0, src_buf, NULL, size, dst_buf, NULL, NULL); + eg_translate_multi(0, src_buf, size, dst_buf); + dst_size = strlen(dst_buf) + 1; + if (dst_size < size) + break; + size *= 2; + } + free(src_buf); + + wchar_t *dst = (wchar_t *)malloc(dst_size * sizeof(wchar_t)); + MultiByteToWideChar(CODEPAGE, 0, dst_buf, dst_size, dst, dst_size); + free(dst_buf); + + return dst; +} + +bool LoadLECFromPath(char *path) +{ + strcat(path, PATH); + if (hLEC = LoadLibraryA(path)) + { + eg_init_t eg_init; + eg_init2_t eg_init2 = (eg_init2_t)GetProcAddress(hLEC, "eg_init2"); + if (!eg_init2) + eg_init = (eg_init_t)GetProcAddress(hLEC, "eg_init"); + eg_end = (eg_end_t)GetProcAddress(hLEC, "eg_end"); + eg_translate_multi = (eg_translate_multi_t)GetProcAddress(hLEC, "eg_translate_multi"); + if ((eg_init2 || eg_init) && eg_end && eg_translate_multi) + { + path[strlen(path) - strlen(PATH) + 10] = 0; + if (eg_init2 ? !eg_init2(path, 0) : !eg_init(path)) + { + lecState = 1; + return true; + } + } + FreeLibrary(hLEC); + hLEC = NULL; + } + return false; +} + +void SetUpLEC() +{ + char path[MAX_PATH + 7 + sizeof(PATH)]; + path[GetModuleFileNameA(NULL, path, MAX_PATH)] = 0; + if (char *p = strrchr(path, '\\')) + p[1] = 0; + strcat(path, "Plugins\\"); + if (LoadLECFromPath(path)) + return; + + lecState = -1; + + HKEY key; + if (!RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\LogoMedia\\LEC Power Translator 15\\Configuration", 0, KEY_QUERY_VALUE, &key)) + { + DWORD size = MAX_PATH; + if (!RegQueryValueExA(key, "ApplicationPath", NULL, NULL, (LPBYTE)path, &size)) + { + if (size && !path[size - 1]) + size--; + if (size && path[size - 1] == '\\') + size--; + for (; size && path[size - 1] != '\\'; size--) + ; + if (size) + { + path[size] = 0; + LoadLECFromPath(path); + } + } + RegCloseKey(key); + } +} +static void writestring(wchar_t *text, HANDLE hPipe) +{ + DWORD _; + auto len = 2 * wcslen(text); + if (!WriteFile(hPipe, &len, 4, &_, NULL)) + return; + if (!WriteFile(hPipe, text, len, &_, NULL)) + return; +} +static wchar_t *readstring(HANDLE hPipe) +{ + DWORD _; + int len; + if (!ReadFile(hPipe, &len, 4, &_, NULL)) + return nullptr; + wchar_t *otext = new wchar_t[len / 2 + 1]; + if (!ReadFile(hPipe, otext, len, &_, NULL)) + return nullptr; + otext[len / 2] = 0; + return otext; +} +int lecwmain(int argc, wchar_t *argv[]) +{ + HANDLE hPipe = CreateNamedPipe(argv[1], PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65535, 65535, NMPWAIT_WAIT_FOREVER, 0); + + SetEvent(CreateEvent(&allAccess, FALSE, FALSE, argv[2])); + if (!ConnectNamedPipe(hPipe, NULL)) + return 0; + std::wstring src = argv[3]; + std::wstring tgt = argv[4]; + if (src == L"ja" && tgt == L"en") + { + CODEPAGE = 932; + PATH = "Nova\\JaEn\\EngineDll_je.dll"; + } + else if (src == L"ko" && tgt == L"en") + { + CODEPAGE = 949; + PATH = "Nova\\KoEn\\keeglib.dll"; + } + else + { + CODEPAGE = 932; + PATH = "Nova\\JaEn\\EngineDll_je.dll"; + } + DWORD _; + wchar_t __[] = L"not installed"; + while (true) + { + wchar_t *otext = readstring(hPipe); + if (!otext) + break; + + if (!lecState) + { + SetUpLEC(); + if (lecState < 0) + { + writestring(__, hPipe); + continue; + } + } + + if (lecState < 0) + { + writestring(__, hPipe); + continue; + } + wchar_t *text = LECTranslateFull(otext); + delete[] otext; + writestring(text, hPipe); + delete[] text; + } + + return 0; +} \ No newline at end of file diff --git a/cpp/shareddllproxy/neospeech.cpp b/cpp/shareddllproxy/neospeech.cpp index 0fceacf6..7605a8fb 100644 --- a/cpp/shareddllproxy/neospeech.cpp +++ b/cpp/shareddllproxy/neospeech.cpp @@ -35,10 +35,8 @@ int neospeech(int argc, wchar_t *argv[]) memset(mapview, 0, 1024 * 1024 * 10); SetEvent(CreateEvent(&allAccess, FALSE, FALSE, argv[2])); - if (ConnectNamedPipe(hPipe, NULL) != NULL) - { - DWORD len = 0; - } + if (!ConnectNamedPipe(hPipe, NULL)) + return 0; wchar_t text[10000]; DWORD _; while (true) diff --git a/cpp/shareddllproxy/shareddllproxy.cpp b/cpp/shareddllproxy/shareddllproxy.cpp index 60ca7d1e..65e33f90 100644 --- a/cpp/shareddllproxy/shareddllproxy.cpp +++ b/cpp/shareddllproxy/shareddllproxy.cpp @@ -4,6 +4,7 @@ int dllinjectwmain(int argc, wchar_t *argv[]); int updatewmain(int argc, wchar_t *wargv[]); bool checkisapatch(); #ifndef _WIN64 +int lecwmain(int argc, wchar_t *argv[]); int jbjwmain(int argc, wchar_t *argv[]); int dreyewmain(int argc, wchar_t *argv[]); int kingsoftwmain(int argc, wchar_t *argv[]); @@ -61,6 +62,7 @@ int wmain(int argc, wchar_t *argv[]) {L"listpm", listprocessmodule}, {L"update", updatewmain}, #ifndef _WIN64 + {L"lec", lecwmain}, {L"jbj7", jbjwmain}, {L"dreye", dreyewmain}, {L"kingsoft", kingsoftwmain}, diff --git a/cpp/version.cmake b/cpp/version.cmake index 2397a57e..067b283e 100644 --- a/cpp/version.cmake +++ b/cpp/version.cmake @@ -1,7 +1,7 @@ set(VERSION_MAJOR 6) set(VERSION_MINOR 14) -set(VERSION_PATCH 12) +set(VERSION_PATCH 13) set(VERSION_REVISION 0) set(LUNA_VERSION "{${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_REVISION}}") add_library(VERSION_DEF ${CMAKE_CURRENT_LIST_DIR}/version_def.cpp) diff --git a/py/LunaTranslator/translator/atlas.py b/py/LunaTranslator/translator/atlas.py index ba7ff90f..4376ee11 100644 --- a/py/LunaTranslator/translator/atlas.py +++ b/py/LunaTranslator/translator/atlas.py @@ -12,51 +12,44 @@ class TS(basetrans): self.checkpath() def checkpath(self): - - t = time.time() - t = str(t) - pipename = "\\\\.\\Pipe\\dreye_" + t - waitsignal = "dreyewaitload_" + t - self.engine = autoproc( - subproc_w( - './files/plugins/shareddllproxy32.exe atlaswmain {} {} '.format( - pipename, waitsignal - ), - name="atlaswmain", - ) - ) - windows.WaitForSingleObject( - windows.AutoHandle(windows.CreateEvent(False, False, waitsignal)), - windows.INFINITE, + t = time.time() + t = str(t) + pipename = "\\\\.\\Pipe\\dreye_" + t + waitsignal = "dreyewaitload_" + t + self.engine = autoproc( + subproc_w( + "./files/plugins/shareddllproxy32.exe atlaswmain {} {} ".format( + pipename, waitsignal + ), + name="atlaswmain", ) - windows.WaitNamedPipe(pipename, windows.NMPWAIT_WAIT_FOREVER) - self.hPipe = windows.AutoHandle( - windows.CreateFile( - pipename, - windows.GENERIC_READ | windows.GENERIC_WRITE, - 0, - None, - windows.OPEN_EXISTING, - windows.FILE_ATTRIBUTE_NORMAL, - None, - ) + ) + + windows.WaitForSingleObject( + windows.AutoHandle(windows.CreateEvent(False, False, waitsignal)), + windows.INFINITE, + ) + windows.WaitNamedPipe(pipename, windows.NMPWAIT_WAIT_FOREVER) + self.hPipe = windows.AutoHandle( + windows.CreateFile( + pipename, + windows.GENERIC_READ | windows.GENERIC_WRITE, + 0, + None, + windows.OPEN_EXISTING, + windows.FILE_ATTRIBUTE_NORMAL, + None, ) - return True + ) + return True def x64(self, content): + self.checkpath() - if self.checkpath() == False: - raise Exception(_TR("翻译器加载失败")) - ress = [] - for line in content.split("\n"): - if len(line) == 0: - continue - windows.WriteFile(self.hPipe, content.encode('utf-16-le')) - ress.append( - windows.ReadFile(self.hPipe, 4096).decode('utf-16-le') - ) - return "\n".join(ress) + windows.WriteFile(self.hPipe, content.encode("utf-16-le")) + + return windows.ReadFile(self.hPipe, 4096).decode("utf-16-le") def translate(self, content): return self.x64(content) diff --git a/py/LunaTranslator/translator/dreye.py b/py/LunaTranslator/translator/dreye.py index 34f5ee26..ee1f5250 100644 --- a/py/LunaTranslator/translator/dreye.py +++ b/py/LunaTranslator/translator/dreye.py @@ -11,6 +11,9 @@ class TS(basetrans): self.pair = None self.checkpath() + def langmap(self): + return {"auto": "ja"} + def checkpath(self): if self.config["path"] == "": return False @@ -69,9 +72,7 @@ class TS(basetrans): if len(line) == 0: continue windows.WriteFile(self.hPipe, line.encode(codes[self.srclang])) - ress.append( - windows.ReadFile(self.hPipe, 4096).decode(codes[self.tgtlang]) - ) + ress.append(windows.ReadFile(self.hPipe, 4096).decode(codes[self.tgtlang])) return "\n".join(ress) def translate(self, content): diff --git a/py/LunaTranslator/translator/kingsoft.py b/py/LunaTranslator/translator/kingsoft.py index abb8c2f8..66d242e4 100644 --- a/py/LunaTranslator/translator/kingsoft.py +++ b/py/LunaTranslator/translator/kingsoft.py @@ -81,4 +81,4 @@ class TS(basetrans): return self.x64(content) def langmap(self): - return {"zh": "SChinese", "cht": "TChinese", "en": "English", "ja": "Japanese"} + return {"zh": "SChinese", "cht": "TChinese", "en": "English", "ja": "Japanese", "auto": "Japanese"} diff --git a/py/LunaTranslator/translator/lec.py b/py/LunaTranslator/translator/lec.py new file mode 100644 index 00000000..f51765e7 --- /dev/null +++ b/py/LunaTranslator/translator/lec.py @@ -0,0 +1,62 @@ +from myutils.subproc import subproc_w, autoproc +from translator.basetranslator import basetrans +import ctypes, time +import windows + + +class TS(basetrans): + def inittranslator(self): + self.path = None + self.pair = None + self.checkpath() + + def langmap(self): + return {"auto": "ja"} + + def checkpath(self): + + pairs = (self.srclang, self.tgtlang) + if pairs == self.pair: + return + self.pair = pairs + t = time.time() + t = str(t) + pipename = "\\\\.\\Pipe\\dreye_" + t + waitsignal = "dreyewaitload_" + t + self.engine = autoproc( + subproc_w( + "./files/plugins/shareddllproxy32.exe lec {} {} {} {}".format( + pipename, waitsignal, self.srclang, self.tgtlang + ), + name="lec", + ) + ) + + windows.WaitForSingleObject( + windows.AutoHandle(windows.CreateEvent(False, False, waitsignal)), + windows.INFINITE, + ) + windows.WaitNamedPipe(pipename, windows.NMPWAIT_WAIT_FOREVER) + self.hPipe = windows.AutoHandle( + windows.CreateFile( + pipename, + windows.GENERIC_READ | windows.GENERIC_WRITE, + 0, + None, + windows.OPEN_EXISTING, + windows.FILE_ATTRIBUTE_NORMAL, + None, + ) + ) + + def x64(self, content: str): + + self.checkpath() + l = content.encode("utf-16-le") + windows.WriteFile(self.hPipe, bytes(ctypes.c_int(len(l)))) + windows.WriteFile(self.hPipe, l) + size = ctypes.c_int.from_buffer_copy(windows.ReadFile(self.hPipe, 4)).value + return windows.ReadFile(self.hPipe, size).decode("utf-16-le") + + def translate(self, content): + return self.x64(content) diff --git a/py/files/defaultconfig/config.json b/py/files/defaultconfig/config.json index dfcf43c4..4ab9dab4 100644 --- a/py/files/defaultconfig/config.json +++ b/py/files/defaultconfig/config.json @@ -1702,6 +1702,12 @@ "color": "#1839f0", "name": "Atlas" }, + "lec": { + "type": "offline", + "use": false, + "color": "#1839f0", + "name": "LEC" + }, "sougou2": { "use": false, "color": "blue",