forked from Public-Mirror/Textractor
Compare commits
3 Commits
x221Mod
...
appveyor_t
Author | SHA1 | Date | |
---|---|---|---|
|
1d1dadaba3 | ||
|
a676619054 | ||
|
5fd646ee1d |
@ -35,10 +35,6 @@ target_precompile_headers(pch PUBLIC include/common.h)
|
|||||||
file(GLOB ASSETS assets/*)
|
file(GLOB ASSETS assets/*)
|
||||||
file(COPY ${ASSETS} DESTINATION ${CMAKE_FINAL_OUTPUT_DIRECTORY})
|
file(COPY ${ASSETS} DESTINATION ${CMAKE_FINAL_OUTPUT_DIRECTORY})
|
||||||
|
|
||||||
include(QtUtils)
|
|
||||||
msvc_registry_search()
|
|
||||||
find_qt5(Core Widgets WinExtras WebSockets)
|
|
||||||
|
|
||||||
add_library(text text.cpp)
|
add_library(text text.cpp)
|
||||||
target_compile_definitions(text PRIVATE ${TEXT_LANGUAGE})
|
target_compile_definitions(text PRIVATE ${TEXT_LANGUAGE})
|
||||||
link_libraries(text)
|
link_libraries(text)
|
||||||
|
@ -4,29 +4,25 @@
|
|||||||
"name": "x86-Debug",
|
"name": "x86-Debug",
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
"configurationType": "Debug",
|
"configurationType": "Debug",
|
||||||
"cmakeCommandArgs": "-DQT_ROOT=/Qt",
|
|
||||||
"inheritEnvironments": [ "msvc_x86" ]
|
"inheritEnvironments": [ "msvc_x86" ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "x86-RelWithDebInfo",
|
"name": "x86-RelWithDebInfo",
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
"configurationType": "RelWithDebInfo",
|
"configurationType": "RelWithDebInfo",
|
||||||
"cmakeCommandArgs": "-DQT_ROOT=/Qt",
|
|
||||||
"inheritEnvironments": [ "msvc_x86" ]
|
"inheritEnvironments": [ "msvc_x86" ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "x64-Debug",
|
"name": "x64-Debug",
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
"configurationType": "Debug",
|
"configurationType": "Debug",
|
||||||
"cmakeCommandArgs": "-DQT_ROOT=/Qt",
|
|
||||||
"inheritEnvironments": [ "msvc_x64" ]
|
"inheritEnvironments": [ "msvc_x64" ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "x64-RelWithDebInfo",
|
"name": "x64-RelWithDebInfo",
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
"configurationType": "RelWithDebInfo",
|
"configurationType": "RelWithDebInfo",
|
||||||
"cmakeCommandArgs": "-DQT_ROOT=/Qt",
|
|
||||||
"inheritEnvironments": [ "msvc_x64" ]
|
"inheritEnvironments": [ "msvc_x64" ]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
include(QtUtils)
|
||||||
|
msvc_registry_search()
|
||||||
|
find_qt5(Core Widgets WinExtras)
|
||||||
|
|
||||||
add_executable(Textractor WIN32
|
add_executable(Textractor WIN32
|
||||||
main.cpp
|
main.cpp
|
||||||
exception.cpp
|
exception.cpp
|
||||||
|
@ -88,8 +88,6 @@ namespace
|
|||||||
TextThread* current = nullptr;
|
TextThread* current = nullptr;
|
||||||
MainWindow* This = nullptr;
|
MainWindow* This = nullptr;
|
||||||
|
|
||||||
void FindHooks();
|
|
||||||
|
|
||||||
QString TextThreadString(TextThread& thread)
|
QString TextThreadString(TextThread& thread)
|
||||||
{
|
{
|
||||||
return QString("%1:%2:%3:%4:%5: %6").arg(
|
return QString("%1:%2:%3:%4:%5: %6").arg(
|
||||||
@ -276,8 +274,7 @@ namespace
|
|||||||
void AddHook(QString hook)
|
void AddHook(QString hook)
|
||||||
{
|
{
|
||||||
if (QString hookCode = QInputDialog::getText(This, ADD_HOOK, CODE_INFODUMP, QLineEdit::Normal, hook, &ok, Qt::WindowCloseButtonHint); ok)
|
if (QString hookCode = QInputDialog::getText(This, ADD_HOOK, CODE_INFODUMP, QLineEdit::Normal, hook, &ok, Qt::WindowCloseButtonHint); ok)
|
||||||
if (hookCode.startsWith("S") || hookCode.startsWith("/S")) FindHooks(); // backwards compatibility for old hook search UX
|
if (auto hp = HookCode::Parse(S(hookCode))) try { Host::InsertHook(selectedProcessId, hp.value()); } catch (std::out_of_range) {}
|
||||||
else if (auto hp = HookCode::Parse(S(hookCode))) try { Host::InsertHook(selectedProcessId, hp.value()); } catch (std::out_of_range) {}
|
|
||||||
else Host::AddConsoleOutput(INVALID_CODE);
|
else Host::AddConsoleOutput(INVALID_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
![How it looks](screenshot.png)
|
![How it looks](screenshot.png)
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
**Textractor** (a.k.a. NextHooker) is an open-source x86/x64 video game text hooker for Windows 7+ (and Wine) based off of [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
**Textractor** (a.k.a. NextHooker) is an open-source x86/x64 video game text hooker for Windows 7+ (and Wine) based off of [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
||||||
Watch the [tutorial video](docs/TUTORIAL.md) for a quick rundown on using it.
|
Watch the [tutorial video](docs/TUTORIAL.md) for a quick rundown on using it.
|
||||||
@ -34,7 +34,7 @@ See the extensions folder for examples of what extensions can do.
|
|||||||
|
|
||||||
All contributions are appreciated! Please email me at akashmozumdar@gmail.com if you have any questions about the codebase.<br>
|
All contributions are appreciated! Please email me at akashmozumdar@gmail.com if you have any questions about the codebase.<br>
|
||||||
You should use the standard process of making a pull request (fork, branch, commit changes, make PR from your branch to my master).<br>
|
You should use the standard process of making a pull request (fork, branch, commit changes, make PR from your branch to my master).<br>
|
||||||
Contributing a translation is easy: [text.cpp](text.cpp) contains all of the text strings that you need to translate. Translations of this README or the tutorial video transcript are also welcome.
|
Contributing a translation is easy: text.cpp contains all of the text strings that you need to translate. Translations of this README or the tutorial video transcript are also welcome.
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
Before compiling Textractor, you need Qt version 5.13 and Visual Studio with CMake support.
|
Before compiling Textractor, you need Qt version 5.13 and Visual Studio with CMake support.
|
||||||
|
52
README_DE.md
52
README_DE.md
@ -1,52 +0,0 @@
|
|||||||
# Textractor
|
|
||||||
|
|
||||||
![Wie es aussieht](screenshot.png)
|
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
|
||||||
|
|
||||||
**Textractor** (a.b.a. NextHooker) ist ein open-source x86/x64 Video spiel Text hooker für Windows 7+ (und Wine) basierend auf [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
|
||||||
Schau das [Tutorial Video](docs/TUTORIAL.md) (auf Englisch) an für einen schnellen Überblick wie du Textractor verwendest.
|
|
||||||
## Download
|
|
||||||
|
|
||||||
Der offizielle Release ist [hier](https://github.com/Artikash/Textractor/releases) zu finden.<br>
|
|
||||||
Der letzte Release von ITHVNR ist [hier](https://drive.google.com/open?id=13aHF4uIXWn-3YML_k2YCDWhtGgn5-tnO).<br>
|
|
||||||
Der experimentelle Release von Textractor (mit debug Informationen) ist [hier](https://ci.appveyor.com/project/Artikash/textractor/history) in der 'Artifacts'
|
|
||||||
Kategorie des jeweiligen Jobs.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Modular und Anpassbar
|
|
||||||
- Automatischen 'hooken' von mehreren Engines (einige davon welche keine VNR Support haben!)
|
|
||||||
- Text 'hooken' mithilfe von /H "hook" Codes (die meisten AGTH codes funktionieren)
|
|
||||||
- Automatische suche nach funktionierenden Hook's
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
Wenn ihr irgendwelche Fehler, Spiele bei denen Textractor nicht funktioniert, oder Fragen/Anmerkungen habt lasst es mich bitte wissen.<br>
|
|
||||||
Falls ihr Probleme mit einem Spiel habt, schickt mir einen kostenlosen download Link von dem Spiel oder schenkt es mir auf [Steam](https://steamcommunity.com/profiles/76561198097566313/).
|
|
||||||
|
|
||||||
## Erweiterungen
|
|
||||||
|
|
||||||
Siehe [Example Extension project](https://github.com/Artikash/ExampleExtension) für Anleitungen, wie man eine Erweiterung erstellt.<br>
|
|
||||||
Im 'Extensions' Ordner sind Beispiele für Erweiterungen.
|
|
||||||
|
|
||||||
## Unterstützen
|
|
||||||
|
|
||||||
Ich bin dankbar für alle Unterstützungen! Schickt mir eine E-Mail an akashmozumdar@gmail.com falls ihr Fragen zur Codebasis habt.<br>
|
|
||||||
Verwendet bitte als Standard eine pull Request (fork, branch, commit) zum Master Release.<br>
|
|
||||||
Zu Übersetzungen beizutragen ist einfach: [text.cpp](text.cpp) enthält alle text Strings welche übersetzt werden sollen. Übersetzungen der README oder des Tutorial Video Transkripts sind ebenfalls willkommen.
|
|
||||||
|
|
||||||
## Compiling
|
|
||||||
Zum Compilen braucht ihr Qt Version 5.13 und Visual Studio mit CMake Unterstützung.
|
|
||||||
Erstellt einen Clone vom Quellcode und initialisiert die submodule mit 'git clone https://github.com/Artikash/Textractor.git' und 'git submodule update --init'.
|
|
||||||
Ihr solltet danach in der Lage sein, den Quellordner in Visual Studio zu öffnen und anzufangen.
|
|
||||||
|
|
||||||
## Projekt Architektur
|
|
||||||
|
|
||||||
Der Host injiziert texthooks in den ziel Prozess und verbindet ihn mit 2 Pipe Dateien.
|
|
||||||
Texthook wartet auf die Pipe und injiziert Instruktionen für den Text Output (z.b. TextOut, GetGlyphOutline) welche durch die Pipe gesendet werden.<br>
|
|
||||||
Weitere Informationen werden durch geteilten Speicher ausgetauscht.<br>
|
|
||||||
Der Text, welchen der Host durch die Pipe erhält, wird dann verarbeitet, bevor er wieder an die GUI gesendet wird.<br>
|
|
||||||
Zu guter Letzt, sendet die GUI den Text an die Erweiterung, welche einen lesbaren Output anzeigt.
|
|
||||||
|
|
||||||
## [Entwickler](docs/CREDITS.md)
|
|
@ -1,6 +1,6 @@
|
|||||||
# Textractor
|
# Textractor
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
## [Video tutorial](docs/TUTORIAL.md)
|
## [Video tutorial](docs/TUTORIAL.md)
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
![À quoi ça ressemble](screenshot.png)
|
![À quoi ça ressemble](screenshot.png)
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
**Textractor** (a.k.a. NextHooker) est un traducteur de jeux-videos basé surtout sur du texte en open source x86/x64 pour Windows/Wine [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
**Textractor** (a.k.a. NextHooker) est un traducteur de jeux-videos basé surtout sur du texte en open source x86/x64 pour Windows/Wine [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
||||||
Regarde le [tutorial video](docs/TUTORIAL.md) pour un aperçu rapide de son utilisation.
|
Regarde le [tutorial video](docs/TUTORIAL.md) pour un aperçu rapide de son utilisation.
|
||||||
@ -32,7 +32,7 @@ Voir le dossier des extensions pour des exemples de ce que les extensions peuven
|
|||||||
|
|
||||||
Toutes les contributions sont appréciées! Veuillez m'envoyer un e-mail À akashmozumdar@gmail.com si vous avez des questions sur la base de code. <br>
|
Toutes les contributions sont appréciées! Veuillez m'envoyer un e-mail À akashmozumdar@gmail.com si vous avez des questions sur la base de code. <br>
|
||||||
Vous devez utiliser le processus standard de création d'une demande d'extraction (fork, branch, commit changes, make PR from your branch to my master). <br>
|
Vous devez utiliser le processus standard de création d'une demande d'extraction (fork, branch, commit changes, make PR from your branch to my master). <br>
|
||||||
Contribuer à une traduction est simple: il suffit de traduire les chaînes dans [text.cpp](text.cpp) ainsi que ce fichier README.
|
Contribuer à une traduction est simple: il suffit de traduire les chaînes dans text.cpp ainsi que ce fichier README.
|
||||||
|
|
||||||
## Compilation
|
## Compilation
|
||||||
|
|
||||||
|
31
README_ID.md
31
README_ID.md
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
![How it looks](screenshot.png)
|
![How it looks](screenshot.png)
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
**Textractor** (a.k.a NextHooker) adalah teks hooker video game untuk Windows/Wine x86/x64 berbasis open-source yang didasari oleh [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
**Textractor** (a.k.a NextHooker) adalah text hooker video game untuk Windows/Wine x86/x64 berbasis open-source yang didasari oleh [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
||||||
Lihat [video tutorial](docs/TUTORIAL.md) untuk mengetahui bagaimana cara menggunakannya.
|
Lihat [video tutorial](docs/TUTORIAL.md) untuk mengetahui bagaimana cara menggunakannya.
|
||||||
|
|
||||||
## Pengunduhan
|
## Pengunduhan
|
||||||
@ -21,33 +21,36 @@ Rilisan Terakhir ITHVNR dapat diunduh [disini](https://drive.google.com/open?id=
|
|||||||
|
|
||||||
## Dukungan
|
## Dukungan
|
||||||
|
|
||||||
Tolong beritahu saya jika kamu menemukan kutu, game yang tidak dapat di tempel oleh Textractor, permintaan fitur, atau usulan lain.<br>
|
Please let me know of any bugs, games that Textractor has trouble hooking, feature requests, or other suggestions.<br>
|
||||||
Jika kamu memiliki masalah dalam menempelkan kedalam game tolong email saya link agar saya dapat mengunduh game tersebut, atau hadiahkan game tersebut di [Steam](https://steamcommunity.com/profiles/76561198097566313/).
|
If you have trouble hooking a game please email me a place where I can freely download it, or gift it to me on [Steam](https://steamcommunity.com/profiles/76561198097566313/).
|
||||||
|
|
||||||
|
Tolong beritahu saya jika kamu menemukan bug, game yang tidak dapat di tempel oleh Textractor, permintaan fitur, atau usulan lain.<br>
|
||||||
|
Jika kamu memiliki masalah dalam menempelkan kedalam game tolong email saya link agar saya dapat mendownload game tersebut, atau gift game tersebut di [Steam](https://steamcommunity.com/profiles/76561198097566313/).
|
||||||
|
|
||||||
## Ekstensi
|
## Ekstensi
|
||||||
|
|
||||||
Lihat [project sampel ekstensi saya](https://github.com/Artikash/ExampleExtension) untuk melihat bagaimana cara membuat ekstensi.<br>
|
Lihat [project sampel ekstensi saya](https://github.com/Artikash/ExampleExtension) untuk melihat bagaimana cara membuat ekstensi.<br>
|
||||||
Lihat ekstensi folder untuk melihat sampel ekstensi.
|
Lihat folder extensions untuk melihat sampel ekstensi.
|
||||||
|
|
||||||
## Kontribusi
|
## Kontribusi
|
||||||
|
|
||||||
Seluruh kontribusi diapresiasi! Tolong email saya di akashmozumdar@gmail.com jika kamu memiliki pertanyaan mengenai kode dasar nya.<br>
|
Seluruh kontribusi diapresiasi! Tolong email saya di akashmozumdar@gmail.com jika kamu memiliki pertanyaan mengenai codebase nya.<br>
|
||||||
Kamu harus menggunakan proses standar dalam membuat permintaan pull(fork, cabang, perubahan commit, membuat PR dari cabang kamu ke master saya).<br>
|
Kamu harus menggunakan proses standar dalam membuat permintaan pull(fork, branch, commit changes, membuat PR dari branch kamu ke master saya).<br>
|
||||||
Berkontribusi dalam penerjemahan dapat dilakukan dengan mudah : cukup terjemahkan string dari [text.cpp](text.cpp) lalu terjemahkan README ini.
|
Berkontribusi dalam penerjemahan dapat dilakukan dengan mudah : cukup terjemahkan string dari text.cpp lalu terjemahkan README ini.
|
||||||
|
|
||||||
## Mengcompile
|
## Compiling
|
||||||
|
|
||||||
Sebelum melakukan proses compile *Textractor*, kamu harus memiliki Visual Studio dengan dukungan Cmake, juga dengan Qt version 5.13<br>
|
Sebelum melakukan proses compile *Textractor*, kamu harus memiliki Visual Studio dengan dukungan Cmake, juga dengan Qt version 5.13<br>
|
||||||
Lalu kamu dapat membuka folder di Visual Studio, dan build. Jalankan Textractor.exe.
|
Lalu kamu dapat membuka folder di Visual Studio, dan build. Run Textractor.exe.
|
||||||
|
|
||||||
|
|
||||||
## Arsitektur Project
|
## Arsitektur Project
|
||||||
|
|
||||||
Host (lihat folder host) menyuntikan texthook.dll (dibuat dari folder texthook) kedalam target proses dan disambungkan lewat 2 file pipe.<br>
|
Host (lihat folder host) menginject texthook.dll (dibuat dari folder texthook) kedalam target process dan disambungkan lewat 2 file pipe.<br>
|
||||||
Host menulis ke hostPipe, texthook menulis ke hookPipe.<br>
|
Host menulis ke hostPipe, texthook menulis ke hookPipe.<br>
|
||||||
texthook menunggu pipe tersambung, lalu menyuntikan beberapa instruksi ke teks yang menghasilkan fungsi (contoh: TextOut, GetGlyphOutline) yang membuat input dikirim melewati pipa.<br>
|
texthook menunggu pipe tersambung, lalu menginject beberapa instruksi ke teks yang menghasilkan fungsi (contoh: TextOut, GetGlyphOutline) yang membuat input dikirim melewati pipa.<br>
|
||||||
Informasi tambahan tentang hook dipindahkan melewati shared memory.<br>
|
Informasi tambahan tentang hook dipindahkan melewati shared memory.<br>
|
||||||
Teks yang diterima host melewati pipe lalu diproses lagi sebelum dikembalikan ke GUI.<br>
|
Text yang diterima host melewati pipe lalu diproses lagi sebelum dikembalikan ke GUI.<br>
|
||||||
Dan pada akhirnya, GUI melepas teks ke ekstensi sebelum menampilkan teks.
|
Dan pada akhirnya, GUI melepas text ke ekstensi sebelum menampilkan teks.
|
||||||
|
|
||||||
## [Pengembang](docs/CREDITS.md)
|
## [Pengembang](docs/CREDITS.md)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
![Come si vede](screenshot.png)
|
![Come si vede](screenshot.png)
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
**Textractor** (a.k.a. NextHooker) è un agganciatore di testi di videogiochi open-source per Windows/Wine basato su[ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
**Textractor** (a.k.a. NextHooker) è un agganciatore di testi di videogiochi open-source per Windows/Wine basato su[ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
||||||
Guarda il [video tutorial](docs/TUTORIAL.md) per una sintesi veloce sul suo utilizzo.
|
Guarda il [video tutorial](docs/TUTORIAL.md) per una sintesi veloce sul suo utilizzo.
|
||||||
@ -33,7 +33,7 @@ Guardate la cartella delle estenzioni per esempi di cosa possono fare le estenzi
|
|||||||
|
|
||||||
Tutti i contributi sono apprezzati! Inviatemi un email a akashmozumdar@gmail.com se avete delle domande sul codebase.<br>
|
Tutti i contributi sono apprezzati! Inviatemi un email a akashmozumdar@gmail.com se avete delle domande sul codebase.<br>
|
||||||
Dovreste usare il processo standard di creare una pull request (fork, branch, commit changes, crea PR dal vostro ramo al mio master).<br>
|
Dovreste usare il processo standard di creare una pull request (fork, branch, commit changes, crea PR dal vostro ramo al mio master).<br>
|
||||||
Contribuire alla traduzione è semplice: traduci le stringhe in [text.cpp](text.cpp) cosi come questo README.
|
Contribuire alla traduzione è semplice: traduci le stringhe in text.cpp cosi come questo README.
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Textractor
|
# Textractor
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
**Textractor** はビジュアルノベル文字抽出プログラム。
|
**Textractor** はビジュアルノベル文字抽出プログラム。
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
![How it looks](screenshot.png)
|
![How it looks](screenshot.png)
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
**Textractor** (a.k.a. NextHooker)는 Windows/Wine에서 작동하는 [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine)을 기반으로 한 오픈소스 x86/x64 비디오게임 텍스트 후커 입니다.<br>
|
**Textractor** (a.k.a. NextHooker)는 Windows/Wine에서 작동하는 [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine)을 기반으로 한 오픈소스 x86/x64 비디오게임 텍스트 후커 입니다.<br>
|
||||||
빠른 사용법의 이해를 위해 [tutorial video](docs/TUTORIAL.md) 를 참고하세요.
|
빠른 사용법의 이해를 위해 [tutorial video](docs/TUTORIAL.md) 를 참고하세요.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
![Como se Parece](screenshot.png)
|
![Como se Parece](screenshot.png)
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
**Textractor** (também conhecido como NextHooker) é um extrator de textos de video-games x86/x64 para Windows/Wine baseado no [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
**Textractor** (também conhecido como NextHooker) é um extrator de textos de video-games x86/x64 para Windows/Wine baseado no [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
||||||
Assista ao [vídeo tutorial](docs/TUTORIAL.md) para uma rápida apresentação de como utilizá-lo.
|
Assista ao [vídeo tutorial](docs/TUTORIAL.md) para uma rápida apresentação de como utilizá-lo.
|
||||||
@ -33,7 +33,7 @@ Veja a pasta de extensões para mais exemplos do que as extensões são capazes
|
|||||||
|
|
||||||
Todas contribuições são bem-vindas! Por favor, me mande um e-mail no endereço akashmozumdar@gmail.com caso tenha alguma dúvida quanto ao codebase.<br>
|
Todas contribuições são bem-vindas! Por favor, me mande um e-mail no endereço akashmozumdar@gmail.com caso tenha alguma dúvida quanto ao codebase.<br>
|
||||||
Você deve seguir o processo padrão de fazer um pull request (fork, branch, realizar mudanças, realizar o PR do seu branch para o meu master).<br>
|
Você deve seguir o processo padrão de fazer um pull request (fork, branch, realizar mudanças, realizar o PR do seu branch para o meu master).<br>
|
||||||
Contribuir com uma tradução é fácil: basta traduzir as linhas do [text.cpp](text.cpp) assim como esse README.
|
Contribuir com uma tradução é fácil: basta traduzir as linhas do text.cpp assim como esse README.
|
||||||
|
|
||||||
## Compilando
|
## Compilando
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
![Как это выглядит](screenshot.png)
|
![Как это выглядит](screenshot.png)
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
**Textractor** (a.k.a. NextHooker) это проект x86/x64 Windows/Wine программы для захвата текста из видеоигр, основанный на [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
**Textractor** (a.k.a. NextHooker) это проект x86/x64 Windows/Wine программы для захвата текста из видеоигр, основанный на [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
||||||
Смотреть [обучающее видео](docs/TUTORIAL.md) для быстрого ознакомления.
|
Смотреть [обучающее видео](docs/TUTORIAL.md) для быстрого ознакомления.
|
||||||
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
Любой вклад приветствуется! Пишите мне(автору) на akashmozumdar@gmail.com, если у вас есть любые вопросы о кодовой базе.<br>
|
Любой вклад приветствуется! Пишите мне(автору) на akashmozumdar@gmail.com, если у вас есть любые вопросы о кодовой базе.<br>
|
||||||
Используйте стандартные действия для создания pull request (fork, branch, commit changes, создайте PR из своей ветки branch на мой master).<br>
|
Используйте стандартные действия для создания pull request (fork, branch, commit changes, создайте PR из своей ветки branch на мой master).<br>
|
||||||
Вклад в перевод совсем не сложен: просто переведите строки в [text.cpp](text.cpp), также, как и этот README.
|
Вклад в перевод совсем не сложен: просто переведите строки в text.cpp, также, как и этот README.
|
||||||
|
|
||||||
## Компиляция
|
## Компиляция
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Textractor
|
# Textractor
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
## 概述
|
## 概述
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ Textractor 的发行版可以在[这里](https://github.com/Artikash/Textractor/
|
|||||||
|
|
||||||
欢迎一切贡献!如有任何关于代码的疑问,请向 akashmozumdar@gmail.com 发邮件.<br>
|
欢迎一切贡献!如有任何关于代码的疑问,请向 akashmozumdar@gmail.com 发邮件.<br>
|
||||||
你应当使用创建 PR 的标准过程 (分岔 (fork), 分支 (branch), 提交变化, 创建从你的分支到我的 master 分支的 PR).<br>
|
你应当使用创建 PR 的标准过程 (分岔 (fork), 分支 (branch), 提交变化, 创建从你的分支到我的 master 分支的 PR).<br>
|
||||||
提供翻译贡献很简单: 只需翻译 [text.cpp](text.cpp) 中的字符串和这份 README 即可.
|
提供翻译贡献很简单: 只需翻译 text.cpp 中的字符串和这份 README 即可.
|
||||||
|
|
||||||
## 编译
|
## 编译
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
![How it looks](screenshot.png)
|
![How it looks](screenshot.png)
|
||||||
|
|
||||||
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md) ● [Deutsch](README_DE.md)
|
[English](README.md) ● [Español](README_ES.md) ● [简体中文](README_SC.md) ● [Русский](README_RU.md) ● [한국어](README_KR.md) ● [ภาษาไทย](README_TH.md) ● [Français](README_FR.md) ● [Italiano](README_IT.md) ● [日本語](README_JP.md) ● [Bahasa Indonesia](README_ID.md) ● [Português](README_PT.md)
|
||||||
|
|
||||||
**Textractor**
|
**Textractor**
|
||||||
(หรือ NextHooker) คือโปรแกรมโอเพนซอร์ซสำหรับปฏิบัติการที่มีหน้าที่เพื่อเชื่อมกับตัวอักษรกับเกมจากที่มาจากระบบปฏิบัติการ Window/Wine โดยมีแบบดังเดิมมาจาก [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
(หรือ NextHooker) คือโปรแกรมโอเพนซอร์ซสำหรับปฏิบัติการที่มีหน้าที่เพื่อเชื่อมกับตัวอักษรกับเกมจากที่มาจากระบบปฏิบัติการ Window/Wine โดยมีแบบดังเดิมมาจาก [ITHVNR](https://web.archive.org/web/20160202084144/http://www.hongfire.com/forum/showthread.php/438331-ITHVNR-ITH-with-the-VNR-engine).<br>
|
||||||
|
@ -1,24 +1,49 @@
|
|||||||
macro(msvc_registry_search)
|
macro(msvc_registry_search)
|
||||||
if(NOT DEFINED Qt5_DIR)
|
if(NOT DEFINED Qt5_DIR)
|
||||||
if (NOT EXISTS ${QT_ROOT})
|
# look for user-registry pointing to qtcreator
|
||||||
# look for user-registry pointing to qtcreator
|
get_filename_component(QT_BIN [HKEY_CURRENT_USER\\Software\\Classes\\Applications\\QtProject.QtCreator.pro\\shell\\Open\\Command] PATH)
|
||||||
get_filename_component(QT_ROOT [HKEY_CURRENT_USER\\Software\\Classes\\Applications\\QtProject.QtCreator.pro\\shell\\Open\\Command] PATH)
|
|
||||||
|
|
||||||
# get root path
|
# get root path so we can search for 5.3, 5.4, 5.5, etc
|
||||||
string(REPLACE "/Tools" ";" QT_ROOT "${QT_ROOT}")
|
string(REPLACE "/Tools" ";" QT_BIN "${QT_BIN}")
|
||||||
list(GET QT_ROOT 0 QT_ROOT)
|
list(GET QT_BIN 0 QT_BIN)
|
||||||
|
file(GLOB QT_VERSIONS "${QT_BIN}/5.1*")
|
||||||
|
list(SORT QT_VERSIONS)
|
||||||
|
|
||||||
|
# assume the latest version will be last alphabetically
|
||||||
|
list(REVERSE QT_VERSIONS)
|
||||||
|
|
||||||
|
list(GET QT_VERSIONS 0 QT_VERSION)
|
||||||
|
|
||||||
|
# fix any double slashes which seem to be common
|
||||||
|
string(REPLACE "//" "/" QT_VERSION "${QT_VERSION}")
|
||||||
|
|
||||||
|
if(MSVC_VERSION GREATER_EQUAL 1920)
|
||||||
|
set(QT_MSVC 2019)
|
||||||
|
elseif(MSVC_VERSION GREATER_EQUAL 1910)
|
||||||
|
set(QT_MSVC 2017)
|
||||||
|
elseif(MSVC_VERSION GREATER_EQUAL 1900)
|
||||||
|
set(QT_MSVC 2015)
|
||||||
|
else()
|
||||||
|
message(WARNING "Unsupported MSVC toolchain version")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(QT_VERSION 5.13.2)
|
|
||||||
set(QT_MSVC 2019)
|
|
||||||
|
|
||||||
if(QT_MSVC)
|
if(QT_MSVC)
|
||||||
if(CMAKE_CL_64)
|
if(CMAKE_CL_64)
|
||||||
SET(QT_SUFFIX "_64")
|
SET(QT_SUFFIX "_64")
|
||||||
else()
|
else()
|
||||||
set(QT_SUFFIX "")
|
set(QT_SUFFIX "")
|
||||||
endif()
|
endif()
|
||||||
set(Qt5_DIR "${QT_VERSION}/msvc2017${QT_SUFFIX}/lib/cmake/Qt5")
|
|
||||||
|
# MSVC 2015+ is only backwards compatible
|
||||||
|
if(EXISTS "${QT_VERSION}/msvc${QT_MSVC}${QT_SUFFIX}")
|
||||||
|
set(Qt5_DIR "${QT_VERSION}/msvc${QT_MSVC}${QT_SUFFIX}/lib/cmake/Qt5")
|
||||||
|
elseif(QT_MSVC GREATER_EQUAL 2019 AND EXISTS "${QT_VERSION}/msvc2017${QT_SUFFIX}")
|
||||||
|
set(Qt5_DIR "${QT_VERSION}/msvc2017${QT_SUFFIX}/lib/cmake/Qt5")
|
||||||
|
elseif(QT_MSVC GREATER_EQUAL 2017 AND EXISTS "${QT_VERSION}/msvc2015${QT_SUFFIX}")
|
||||||
|
set(Qt5_DIR "${QT_VERSION}/msvc2015${QT_SUFFIX}/lib/cmake/Qt5")
|
||||||
|
else()
|
||||||
|
message(WARNING "Required QT5 toolchain is not installed")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
@ -28,11 +53,6 @@ macro(find_qt5)
|
|||||||
#set(CMAKE_AUTOMOC ON)
|
#set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
#add_definitions(-DQT_DEPRECATED_WARNINGS -DQT_DISABLE_DEPRECATED_BEFORE=0x060000)
|
#add_definitions(-DQT_DEPRECATED_WARNINGS -DQT_DISABLE_DEPRECATED_BEFORE=0x060000)
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(Qt5_DIR "C:/Qt/Qt5.13.2/5.13.2/msvc2017_64/lib/cmake/Qt5")
|
|
||||||
else()
|
|
||||||
set(Qt5_DIR "C:/Qt/Qt5.13.2/5.13.2/msvc2017/lib/cmake/Qt5")
|
|
||||||
endif()
|
|
||||||
find_package(Qt5 COMPONENTS ${ARGN})
|
find_package(Qt5 COMPONENTS ${ARGN})
|
||||||
|
|
||||||
if(Qt5_FOUND)
|
if(Qt5_FOUND)
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
- French translation by [Racky](mailto:maitrenoah@gmail.com) and [Gratusfr](https://github.com/Gratusfr)
|
- French translation by [Racky](mailto:maitrenoah@gmail.com) and [Gratusfr](https://github.com/Gratusfr)
|
||||||
- Spanish translation by [scese250](https://github.com/scese250)
|
- Spanish translation by [scese250](https://github.com/scese250)
|
||||||
- Turkish translation by [niisokusu](https://reddit.com/u/niisokusu)
|
- Turkish translation by [niisokusu](https://reddit.com/u/niisokusu)
|
||||||
- Simplified Chinese translation by [tinyAdapter](https://github.com/tinyAdapter), [lgztx96](https://github.com/lgztx96) and [chinanoahli](https://github.com/chinanoahli)
|
- Simplified Chinese translation by [tinyAdapter](https://github.com/tinyAdapter) and [lgztx96](https://github.com/lgztx96)
|
||||||
- Russian translation by [TokcDK](https://github.com/TokcDK)
|
- Russian translation by [TokcDK](https://github.com/TokcDK)
|
||||||
- Indonesian translation by [Hawxone](https://github.com/Hawxone)
|
- Indonesian translation by [Hawxone](https://github.com/Hawxone)
|
||||||
- Portuguese translation by [TsumiHokiro](https://github.com/TsumiHokiro)
|
- Portuguese translation by [TsumiHokiro](https://github.com/TsumiHokiro)
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
include(QtUtils)
|
||||||
|
msvc_registry_search()
|
||||||
|
find_qt5(Core Widgets WebSockets)
|
||||||
cmake_policy(SET CMP0037 OLD)
|
cmake_policy(SET CMP0037 OLD)
|
||||||
|
|
||||||
add_library(Bing\ Translate MODULE bingtranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
add_library(Bing\ Translate MODULE bingtranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
||||||
|
@ -9,119 +9,92 @@ const char* TRANSLATION_PROVIDER = "DeepL Translate";
|
|||||||
const char* GET_API_KEY_FROM = "https://www.deepl.com/pro.html#developer";
|
const char* GET_API_KEY_FROM = "https://www.deepl.com/pro.html#developer";
|
||||||
extern const QStringList languagesTo
|
extern const QStringList languagesTo
|
||||||
{
|
{
|
||||||
"Arabic",
|
|
||||||
"Bulgarian",
|
"Bulgarian",
|
||||||
|
"Chinese (Simplified)",
|
||||||
"Czech",
|
"Czech",
|
||||||
"Danish",
|
"Danish",
|
||||||
"German",
|
"Dutch",
|
||||||
"Greek",
|
|
||||||
"English (backward compatibility)",
|
|
||||||
"English (British)",
|
|
||||||
"English (American)",
|
"English (American)",
|
||||||
"Spanish",
|
"English (British)",
|
||||||
"Estonian",
|
"Estonian",
|
||||||
"Finnish",
|
"Finnish",
|
||||||
"French",
|
"French",
|
||||||
|
"German",
|
||||||
|
"Greek",
|
||||||
"Hungarian",
|
"Hungarian",
|
||||||
"Indonesian",
|
|
||||||
"Italian",
|
"Italian",
|
||||||
"Japanese",
|
"Japanese",
|
||||||
"Korean",
|
|
||||||
"Lithuanian",
|
|
||||||
"Latvian",
|
"Latvian",
|
||||||
"Norwegian Bokmål",
|
"Lithuanian",
|
||||||
"Dutch",
|
|
||||||
"Polish",
|
"Polish",
|
||||||
"Portuguese (backward compatibility)",
|
"Portuguese (Brazil)",
|
||||||
"Portuguese (Brazilian)",
|
"Portuguese (Portugal)",
|
||||||
"Portuguese (all Portuguese variants excluding Brazilian Portuguese)",
|
|
||||||
"Romanian",
|
"Romanian",
|
||||||
"Russian",
|
"Russian",
|
||||||
"Slovak",
|
"Slovak",
|
||||||
"Slovenian",
|
"Slovenian",
|
||||||
"Swedish",
|
"Spanish",
|
||||||
"Turkish",
|
"Swedish"
|
||||||
"Ukrainian",
|
|
||||||
"Chinese (backward compatibility)",
|
|
||||||
"Chinese (simplified)",
|
|
||||||
"Chinese (traditional)"
|
|
||||||
},
|
},
|
||||||
languagesFrom
|
languagesFrom
|
||||||
{
|
{
|
||||||
"Arabic",
|
|
||||||
"Bulgarian",
|
"Bulgarian",
|
||||||
"Chinese (all Chinese variants)",
|
"Chinese",
|
||||||
"Czech",
|
"Czech",
|
||||||
"Danish",
|
"Danish",
|
||||||
"Dutch",
|
"Dutch",
|
||||||
"English (all English variants)",
|
"English",
|
||||||
"Estonian",
|
"Estonian",
|
||||||
"Finnish",
|
"Finnish",
|
||||||
"French",
|
"French",
|
||||||
"German",
|
"German",
|
||||||
"Greek",
|
"Greek",
|
||||||
"Hungarian",
|
"Hungarian",
|
||||||
"Indonesian",
|
|
||||||
"Italian",
|
"Italian",
|
||||||
"Japanese",
|
"Japanese",
|
||||||
"Korean",
|
|
||||||
"Latvian",
|
"Latvian",
|
||||||
"Lithuanian",
|
"Lithuanian",
|
||||||
"Norwegian Bokmål",
|
|
||||||
"Polish",
|
"Polish",
|
||||||
"Portuguese (all Portuguese variants)",
|
"Portuguese",
|
||||||
"Romanian",
|
"Romanian",
|
||||||
"Russian",
|
"Russian",
|
||||||
"Slovak",
|
"Slovak",
|
||||||
"Slovenian",
|
"Slovenian",
|
||||||
"Spanish",
|
"Spanish",
|
||||||
"Swedish",
|
"Swedish"
|
||||||
"Turkish",
|
|
||||||
"Ukrainian"
|
|
||||||
};
|
};
|
||||||
extern const std::unordered_map<std::wstring, std::wstring> codes
|
extern const std::unordered_map<std::wstring, std::wstring> codes
|
||||||
{
|
{
|
||||||
{ { L"Arabic" }, { L"AR" } },
|
|
||||||
{ { L"Bulgarian" }, { L"BG" } },
|
{ { L"Bulgarian" }, { L"BG" } },
|
||||||
|
{ { L"Chinese" }, { L"ZH" } },
|
||||||
|
{ { L"Chinese (Simplified)" }, { L"ZH" } },
|
||||||
{ { L"Czech" }, { L"CS" } },
|
{ { L"Czech" }, { L"CS" } },
|
||||||
{ { L"Danish" }, { L"DA" } },
|
{ { L"Danish" }, { L"DA" } },
|
||||||
{ { L"German" }, { L"DE" } },
|
{ { L"Dutch" }, { L"NL" } },
|
||||||
{ { L"Greek" }, { L"EL" } },
|
{ { L"English" }, { L"EN" } },
|
||||||
{ { L"English (all English variants)" }, { L"EN" } },
|
|
||||||
{ { L"English (backward compatibility)" }, { L"EN" } },
|
|
||||||
{ { L"English (British)" }, { L"EN-GB" } },
|
|
||||||
{ { L"English (American)" }, { L"EN-US" } },
|
{ { L"English (American)" }, { L"EN-US" } },
|
||||||
{ { L"Spanish" }, { L"ES" } },
|
{ { L"English (British)" }, { L"EN-GB" } },
|
||||||
{ { L"Estonian" }, { L"ET" } },
|
{ { L"Estonian" }, { L"ET" } },
|
||||||
{ { L"Finnish" }, { L"FI" } },
|
{ { L"Finnish" }, { L"FI" } },
|
||||||
{ { L"French" }, { L"FR" } },
|
{ { L"French" }, { L"FR" } },
|
||||||
|
{ { L"German" }, { L"DE" } },
|
||||||
|
{ { L"Greek" }, { L"EL" } },
|
||||||
{ { L"Hungarian" }, { L"HU" } },
|
{ { L"Hungarian" }, { L"HU" } },
|
||||||
{ { L"Indonesian" }, { L"ID" } },
|
|
||||||
{ { L"Italian" }, { L"IT" } },
|
{ { L"Italian" }, { L"IT" } },
|
||||||
{ { L"Japanese" }, { L"JA" } },
|
{ { L"Japanese" }, { L"JA" } },
|
||||||
{ { L"Korean" }, { L"KO" } },
|
|
||||||
{ { L"Lithuanian" }, { L"LT" } },
|
|
||||||
{ { L"Latvian" }, { L"LV" } },
|
{ { L"Latvian" }, { L"LV" } },
|
||||||
{ { L"Norwegian Bokmål" }, { L"NB" } },
|
{ { L"Lithuanian" }, { L"LT" } },
|
||||||
{ { L"Dutch" }, { L"NL" } },
|
|
||||||
{ { L"Polish" }, { L"PL" } },
|
{ { L"Polish" }, { L"PL" } },
|
||||||
{ { L"Portuguese (all Portuguese variants)" }, { L"PT" } },
|
{ { L"Portuguese" }, { L"PT" } },
|
||||||
{ { L"Portuguese (backward compatibility)" }, { L"PT" } },
|
{ { L"Portuguese (Brazil)" }, { L"PT-BR" } },
|
||||||
{ { L"Portuguese (Brazilian)" }, { L"PT-BR" } },
|
{ { L"Portuguese (Portugal)" }, { L"PT-PT" } },
|
||||||
{ { L"Portuguese (all Portuguese variants excluding Brazilian Portuguese)" }, { L"PT-PT" } },
|
|
||||||
{ { L"Romanian" }, { L"RO" } },
|
{ { L"Romanian" }, { L"RO" } },
|
||||||
{ { L"Russian" }, { L"RU" } },
|
{ { L"Russian" }, { L"RU" } },
|
||||||
{ { L"Slovak" }, { L"SK" } },
|
{ { L"Slovak" }, { L"SK" } },
|
||||||
{ { L"Slovenian" }, { L"SL" } },
|
{ { L"Slovenian" }, { L"SL" } },
|
||||||
|
{ { L"Spanish" }, { L"ES" } },
|
||||||
{ { L"Swedish" }, { L"SV" } },
|
{ { L"Swedish" }, { L"SV" } },
|
||||||
{ { L"Turkish" }, { L"TR" } },
|
|
||||||
{ { L"Ukrainian" }, { L"UK" } },
|
|
||||||
{ { L"Chinese (all Chinese variants)" }, { L"ZH" } },
|
|
||||||
{ { L"Chinese (backward compatibility)" }, { L"ZH" } },
|
|
||||||
{ { L"Chinese (simplified)" }, { L"ZH-HANS" } },
|
|
||||||
{ { L"Chinese (traditional)" }, { L"ZH-HANT" } },
|
|
||||||
{ { L"?" }, { L"auto" } }
|
{ { L"?" }, { L"auto" } }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool translateSelectedOnly = true, useRateLimiter = true, rateLimitSelected = true, useCache = true, useFilter = true;
|
bool translateSelectedOnly = true, useRateLimiter = true, rateLimitSelected = true, useCache = true, useFilter = true;
|
||||||
|
@ -36,11 +36,11 @@ namespace
|
|||||||
if (process) DevTools::Close();
|
if (process) DevTools::Close();
|
||||||
|
|
||||||
auto args = FormatString(
|
auto args = FormatString(
|
||||||
L"%s --proxy-server=direct:// --disable-extensions --disable-gpu --no-first-run --user-data-dir=\"%s\\devtoolscache\" --remote-debugging-port=9222",
|
L"%s --proxy-server=direct:// --disable-extensions --disable-gpu --user-data-dir=%s\\devtoolscache --remote-debugging-port=9222",
|
||||||
chromePath,
|
chromePath,
|
||||||
std::filesystem::current_path().wstring()
|
std::filesystem::current_path().wstring()
|
||||||
);
|
);
|
||||||
args += headless ? L" --window-size=1920,1080 --headless" : L" --window-size=850,900";
|
if (headless) args += L" --headless";
|
||||||
DWORD exitCode = 0;
|
DWORD exitCode = 0;
|
||||||
STARTUPINFOW DUMMY = { sizeof(DUMMY) };
|
STARTUPINFOW DUMMY = { sizeof(DUMMY) };
|
||||||
PROCESS_INFORMATION processInfo = {};
|
PROCESS_INFORMATION processInfo = {};
|
||||||
@ -93,7 +93,7 @@ namespace DevTools
|
|||||||
if (chromePath.isEmpty())
|
if (chromePath.isEmpty())
|
||||||
{
|
{
|
||||||
for (auto [_, process] : GetAllProcesses())
|
for (auto [_, process] : GetAllProcesses())
|
||||||
if (process && (process->find(L"\\chrome.exe") != std::string::npos || process->find(L"\\msedge.exe") != std::string::npos)) chromePath = S(process.value());
|
if (process && process->find(L"\\chrome.exe") != std::string::npos) chromePath = S(process.value());
|
||||||
wchar_t programFiles[MAX_PATH + 100] = {};
|
wchar_t programFiles[MAX_PATH + 100] = {};
|
||||||
for (auto folder : { CSIDL_PROGRAM_FILESX86, CSIDL_PROGRAM_FILES, CSIDL_LOCAL_APPDATA })
|
for (auto folder : { CSIDL_PROGRAM_FILESX86, CSIDL_PROGRAM_FILES, CSIDL_LOCAL_APPDATA })
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
extern const char* LOAD_SCRIPT;
|
extern const char* LOAD_SCRIPT;
|
||||||
|
|
||||||
constexpr auto STYLE_SAVE_FILE = u8"Textractor.qss";
|
constexpr auto STYLE_SAVE_FILE = u8"Textractor.css";
|
||||||
|
|
||||||
class Window : public QDialog, Localizer
|
class Window : public QDialog, Localizer
|
||||||
{
|
{
|
||||||
@ -13,8 +13,7 @@ public:
|
|||||||
{
|
{
|
||||||
connect(&loadButton, &QPushButton::clicked, this, &Window::LoadScript);
|
connect(&loadButton, &QPushButton::clicked, this, &Window::LoadScript);
|
||||||
|
|
||||||
if (scriptEditor.toPlainText().isEmpty())
|
if (scriptEditor.toPlainText().isEmpty()) scriptEditor.setPlainText("/*https://doc.qt.io/qt-5/stylesheet-syntax.html*/");
|
||||||
scriptEditor.setPlainText("/*\nhttps://www.google.com/search?q=Qt+stylesheet+gallery\nhttps://doc.qt.io/qt-5/stylesheet-syntax.html\n*/");
|
|
||||||
layout.addWidget(&scriptEditor);
|
layout.addWidget(&scriptEditor);
|
||||||
layout.addWidget(&loadButton);
|
layout.addWidget(&loadButton);
|
||||||
|
|
||||||
|
@ -18,8 +18,6 @@ extern const char* MAX_TRANSLATIONS_IN_TIMESPAN;
|
|||||||
extern const char* TIMESPAN;
|
extern const char* TIMESPAN;
|
||||||
extern const char* MAX_SENTENCE_SIZE;
|
extern const char* MAX_SENTENCE_SIZE;
|
||||||
extern const char* API_KEY;
|
extern const char* API_KEY;
|
||||||
extern const wchar_t* SENTENCE_TOO_LARGE_TO_TRANS;
|
|
||||||
extern const wchar_t* TRANSLATION_ERROR;
|
|
||||||
extern const wchar_t* TOO_MANY_TRANS_REQUESTS;
|
extern const wchar_t* TOO_MANY_TRANS_REQUESTS;
|
||||||
|
|
||||||
extern const char* TRANSLATION_PROVIDER;
|
extern const char* TRANSLATION_PROVIDER;
|
||||||
@ -36,6 +34,7 @@ namespace
|
|||||||
{
|
{
|
||||||
Synchronized<TranslationParam> tlp;
|
Synchronized<TranslationParam> tlp;
|
||||||
Synchronized<std::unordered_map<std::wstring, std::wstring>> translationCache;
|
Synchronized<std::unordered_map<std::wstring, std::wstring>> translationCache;
|
||||||
|
int savedSize = 0;
|
||||||
|
|
||||||
std::string CacheFile()
|
std::string CacheFile()
|
||||||
{
|
{
|
||||||
@ -47,6 +46,7 @@ namespace
|
|||||||
for (const auto& [sentence, translation] : translationCache.Acquire().contents)
|
for (const auto& [sentence, translation] : translationCache.Acquire().contents)
|
||||||
allTranslations.append(L"|SENTENCE|").append(sentence).append(L"|TRANSLATION|").append(translation).append(L"|END|\r\n");
|
allTranslations.append(L"|SENTENCE|").append(sentence).append(L"|TRANSLATION|").append(translation).append(L"|END|\r\n");
|
||||||
std::ofstream(CacheFile(), std::ios::binary | std::ios::trunc).write((const char*)allTranslations.c_str(), allTranslations.size() * sizeof(wchar_t));
|
std::ofstream(CacheFile(), std::ios::binary | std::ios::trunc).write((const char*)allTranslations.c_str(), allTranslations.size() * sizeof(wchar_t));
|
||||||
|
savedSize = translationCache->size();
|
||||||
}
|
}
|
||||||
void LoadCache()
|
void LoadCache()
|
||||||
{
|
{
|
||||||
@ -59,6 +59,7 @@ namespace
|
|||||||
auto& [sentence, translation] = read.value();
|
auto& [sentence, translation] = read.value();
|
||||||
translationCache->try_emplace(std::move(sentence), std::move(translation));
|
translationCache->try_emplace(std::move(sentence), std::move(translation));
|
||||||
}
|
}
|
||||||
|
savedSize = translationCache->size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +141,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void SaveTranslateTo(QString language)
|
void SaveTranslateTo(QString language)
|
||||||
{
|
{
|
||||||
SaveCache();
|
if (translationCache->size() > savedSize) SaveCache();
|
||||||
settings.setValue(TRANSLATE_TO, S(tlp->translateTo = S(language)));
|
settings.setValue(TRANSLATE_TO, S(tlp->translateTo = S(language)));
|
||||||
LoadCache();
|
LoadCache();
|
||||||
}
|
}
|
||||||
@ -152,7 +153,7 @@ private:
|
|||||||
|
|
||||||
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||||
{
|
{
|
||||||
if (sentenceInfo["text number"] == 0) return false;
|
if (sentenceInfo["text number"] == 0 || sentence.size() > maxSentenceSize) return false;
|
||||||
|
|
||||||
static class
|
static class
|
||||||
{
|
{
|
||||||
@ -174,6 +175,12 @@ bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
|||||||
concurrency::concurrent_priority_queue<DWORD64, std::greater<DWORD64>> tokens;
|
concurrency::concurrent_priority_queue<DWORD64, std::greater<DWORD64>> tokens;
|
||||||
} rateLimiter;
|
} rateLimiter;
|
||||||
|
|
||||||
|
auto Trim = [](std::wstring& text)
|
||||||
|
{
|
||||||
|
text.erase(text.begin(), std::find_if_not(text.begin(), text.end(), iswspace));
|
||||||
|
text.erase(std::find_if_not(text.rbegin(), text.rend(), iswspace).base(), text.end());
|
||||||
|
};
|
||||||
|
|
||||||
bool cache = false;
|
bool cache = false;
|
||||||
std::wstring translation;
|
std::wstring translation;
|
||||||
if (useFilter)
|
if (useFilter)
|
||||||
@ -182,7 +189,6 @@ bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
|||||||
sentence.erase(std::remove_if(sentence.begin(), sentence.end(), [](wchar_t ch) { return ch < ' ' && ch != '\n'; }), sentence.end());
|
sentence.erase(std::remove_if(sentence.begin(), sentence.end(), [](wchar_t ch) { return ch < ' ' && ch != '\n'; }), sentence.end());
|
||||||
}
|
}
|
||||||
if (sentence.empty()) return true;
|
if (sentence.empty()) return true;
|
||||||
if (sentence.size() > maxSentenceSize) translation = SENTENCE_TOO_LARGE_TO_TRANS;
|
|
||||||
if (useCache)
|
if (useCache)
|
||||||
{
|
{
|
||||||
auto translationCache = ::translationCache.Acquire();
|
auto translationCache = ::translationCache.Acquire();
|
||||||
@ -191,12 +197,12 @@ bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
|||||||
if (translation.empty() && (!translateSelectedOnly || sentenceInfo["current select"]))
|
if (translation.empty() && (!translateSelectedOnly || sentenceInfo["current select"]))
|
||||||
if (rateLimiter.Request() || !useRateLimiter || (!rateLimitSelected && sentenceInfo["current select"])) std::tie(cache, translation) = Translate(sentence, tlp.Copy());
|
if (rateLimiter.Request() || !useRateLimiter || (!rateLimitSelected && sentenceInfo["current select"])) std::tie(cache, translation) = Translate(sentence, tlp.Copy());
|
||||||
else translation = TOO_MANY_TRANS_REQUESTS;
|
else translation = TOO_MANY_TRANS_REQUESTS;
|
||||||
if (cache) translationCache->operator[](sentence) = translation;
|
|
||||||
|
|
||||||
if (useFilter) Trim(translation);
|
if (useFilter) Trim(translation);
|
||||||
|
if (cache) translationCache->try_emplace(sentence, translation);
|
||||||
|
if (cache && translationCache->size() > savedSize + 50) SaveCache();
|
||||||
|
|
||||||
for (int i = 0; i < translation.size(); ++i) if (translation[i] == '\r' && translation[i + 1] == '\n') translation[i] = 0x200b; // for some reason \r appears as newline - no need to double
|
for (int i = 0; i < translation.size(); ++i) if (translation[i] == '\r' && translation[i + 1] == '\n') translation[i] = 0x200b; // for some reason \r appears as newline - no need to double
|
||||||
if (translation.empty()) translation = TRANSLATION_ERROR;
|
if (!translation.empty()) (sentence += L"\x200b \n") += translation;
|
||||||
(sentence += L"\x200b \n") += translation;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,9 +276,7 @@ namespace HookCode
|
|||||||
{
|
{
|
||||||
std::optional<HookParam> Parse(std::wstring code)
|
std::optional<HookParam> Parse(std::wstring code)
|
||||||
{
|
{
|
||||||
if (code[0] == L'/') code.erase(0, 1);
|
if (code[0] == L'/') code.erase(0, 1); // legacy/AGTH compatibility
|
||||||
code.erase(std::find(code.begin(), code.end(), L'/'), code.end()); // legacy/AGTH compatibility
|
|
||||||
Trim(code);
|
|
||||||
if (code[0] == L'R') return ParseRCode(code.erase(0, 1));
|
if (code[0] == L'R') return ParseRCode(code.erase(0, 1));
|
||||||
else if (code[0] == L'H') return ParseHCode(code.erase(0, 1));
|
else if (code[0] == L'H') return ParseHCode(code.erase(0, 1));
|
||||||
return {};
|
return {};
|
||||||
@ -294,7 +292,6 @@ namespace HookCode
|
|||||||
assert(HexString(-12) == L"-C"),
|
assert(HexString(-12) == L"-C"),
|
||||||
assert(HexString(12) == L"C"),
|
assert(HexString(12) == L"C"),
|
||||||
assert(Parse(L"/HQN936#-c*C:C*1C@4AA:gdi.dll:GetTextOutA")),
|
assert(Parse(L"/HQN936#-c*C:C*1C@4AA:gdi.dll:GetTextOutA")),
|
||||||
assert(Parse(L"/HQN936#-c*C:C*1C@4AA:gdi.dll:GetTextOutA /KF")),
|
|
||||||
assert(Parse(L"HB4@0")),
|
assert(Parse(L"HB4@0")),
|
||||||
assert(Parse(L"/RS65001#@44")),
|
assert(Parse(L"/RS65001#@44")),
|
||||||
assert(Parse(L"HQ@4")),
|
assert(Parse(L"HQ@4")),
|
||||||
|
@ -88,7 +88,7 @@ void SpawnThread(const F& f) // works in DllMain unlike std thread
|
|||||||
}, copy, 0, nullptr));
|
}, copy, 0, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline struct
|
static struct // should be inline but MSVC (linker) is bugged
|
||||||
{
|
{
|
||||||
inline static BYTE DUMMY[100];
|
inline static BYTE DUMMY[100];
|
||||||
template <typename T> operator T*() { static_assert(sizeof(T) < sizeof(DUMMY)); return (T*)DUMMY; }
|
template <typename T> operator T*() { static_assert(sizeof(T) < sizeof(DUMMY)); return (T*)DUMMY; }
|
||||||
@ -120,12 +120,6 @@ inline std::wstring FormatString(const wchar_t* format, const Args&... args)
|
|||||||
}
|
}
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
inline void Trim(std::wstring& text)
|
|
||||||
{
|
|
||||||
text.erase(text.begin(), std::find_if_not(text.begin(), text.end(), iswspace));
|
|
||||||
text.erase(std::find_if_not(text.rbegin(), text.rend(), iswspace).base(), text.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::optional<std::wstring> StringToWideString(const std::string& text, UINT encoding)
|
inline std::optional<std::wstring> StringToWideString(const std::string& text, UINT encoding)
|
||||||
{
|
{
|
||||||
std::vector<wchar_t> buffer(text.size() + 1);
|
std::vector<wchar_t> buffer(text.size() + 1);
|
||||||
|
118
text.cpp
118
text.cpp
@ -143,7 +143,6 @@ const char* RATE_LIMIT_SELECTED_THREAD = u8"Rate limit selected text thread";
|
|||||||
const char* USE_TRANS_CACHE = u8"Use translation cache";
|
const char* USE_TRANS_CACHE = u8"Use translation cache";
|
||||||
const char* MAX_TRANSLATIONS_IN_TIMESPAN = u8"Max translation requests in timespan";
|
const char* MAX_TRANSLATIONS_IN_TIMESPAN = u8"Max translation requests in timespan";
|
||||||
const char* TIMESPAN = u8"Timespan (ms)";
|
const char* TIMESPAN = u8"Timespan (ms)";
|
||||||
const wchar_t* SENTENCE_TOO_LARGE_TO_TRANS = L"Sentence too large to translate";
|
|
||||||
const wchar_t* TOO_MANY_TRANS_REQUESTS = L"Rate limit exceeded: refuse to make more translation requests";
|
const wchar_t* TOO_MANY_TRANS_REQUESTS = L"Rate limit exceeded: refuse to make more translation requests";
|
||||||
const wchar_t* TRANSLATION_ERROR = L"Error while translating";
|
const wchar_t* TRANSLATION_ERROR = L"Error while translating";
|
||||||
const char* USE_PREV_SENTENCE_CONTEXT = u8"Use previous sentence as context";
|
const char* USE_PREV_SENTENCE_CONTEXT = u8"Use previous sentence as context";
|
||||||
@ -354,30 +353,28 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
|||||||
SETTINGS = u8"设置";
|
SETTINGS = u8"设置";
|
||||||
EXTENSIONS = u8"扩展";
|
EXTENSIONS = u8"扩展";
|
||||||
SELECT_PROCESS = u8"选择进程";
|
SELECT_PROCESS = u8"选择进程";
|
||||||
ATTACH_INFO = u8R"(如果没看见想要附加的进程,请尝试使用管理员权限运行Textractor
|
ATTACH_INFO = u8R"(如果没看见想要附加的进程,尝试使用管理员权限运行
|
||||||
也可以手动输入进程ID)";
|
也可以手动输入进程ID)";
|
||||||
SELECT_PROCESS_INFO = u8"如果手动输入游戏名,请使用绝对路径";
|
SELECT_PROCESS_INFO = u8"如果手动输入游戏名,请使用绝对路径";
|
||||||
FROM_COMPUTER = u8"从资源管理器中选择";
|
FROM_COMPUTER = u8"从计算机中选择";
|
||||||
PROCESSES = u8"可执行文件 (*.exe)";
|
PROCESSES = u8"进程 (*.exe)";
|
||||||
SAVE_SETTINGS = u8"保存设置";
|
SAVE_SETTINGS = u8"保存设置";
|
||||||
EXTEN_WINDOW_INSTRUCTIONS = u8R"(在列表中单击右键以添加或移除扩展
|
EXTEN_WINDOW_INSTRUCTIONS = u8R"(从计算机拖拽扩展 (.dll) 文件到这里来添加
|
||||||
在列表中拖拽扩展可以调整插件的执行顺序, 扩展会从上往下依次执行
|
(如果使用超级管理员运行,则无法工作)
|
||||||
排在下方的扩展只能接收到由排在上方的扩展处理过后的文本)";
|
在列表中拖拽来重新排序
|
||||||
|
使用 delete 键移除选中的扩展)";
|
||||||
ADD_EXTENSION = u8"添加扩展";
|
ADD_EXTENSION = u8"添加扩展";
|
||||||
REMOVE_EXTENSION = u8"移除扩展";
|
|
||||||
INVALID_EXTENSION = u8"%1 是一个无效扩展";
|
INVALID_EXTENSION = u8"%1 是一个无效扩展";
|
||||||
CONFIRM_EXTENSION_OVERWRITE = u8"此扩展的另一个版本已启用,是否删除并覆盖它?";
|
CONFIRM_EXTENSION_OVERWRITE = u8"此扩展的另一个版本已启用,是否删除并覆盖它?";
|
||||||
EXTENSION_WRITE_ERROR = u8"保存扩展失败";
|
EXTENSION_WRITE_ERROR = u8"保存扩展失败";
|
||||||
USE_JP_LOCALE = u8"模拟日本区域设置?";
|
USE_JP_LOCALE = u8"模拟日本区域设置?";
|
||||||
FAILED_TO_CREATE_CONFIG_FILE = u8"无法创建配置文件 \"%1\"";
|
|
||||||
HOOK_SEARCH_UNSTABLE_WARNING = u8"搜索钩子的功能是不稳定的! 可能会导致你的游戏崩溃! ";
|
HOOK_SEARCH_UNSTABLE_WARNING = u8"搜索钩子的功能是不稳定的! 可能会导致你的游戏崩溃! ";
|
||||||
HOOK_SEARCH_STARTING_VIEW_CONSOLE = u8"正在初始化钩子搜索 - 请查看控制台以获取更多提示";
|
|
||||||
SEARCH_CJK = u8"搜索中文/日文/韩文";
|
SEARCH_CJK = u8"搜索中文/日文/韩文";
|
||||||
SEARCH_PATTERN = u8"搜索匹配特征 (hex byte array)";
|
SEARCH_PATTERN = u8"搜索匹配特征 (hex byte array)";
|
||||||
SEARCH_DURATION = u8"搜索持续时间 (ms)";
|
SEARCH_DURATION = u8"搜索持续时间 (ms)";
|
||||||
SEARCH_MODULE = u8"搜索指定模块";
|
SEARCH_MODULE = u8"搜索指定模块";
|
||||||
PATTERN_OFFSET = u8"相对于特征地址的偏移值";
|
PATTERN_OFFSET = u8"相对于特征地址的偏移值";
|
||||||
MAX_HOOK_SEARCH_RECORDS = u8"搜索结果达到上限";
|
MAX_HOOK_SEARCH_RECORDS = u8"搜索结果上限";
|
||||||
MIN_ADDRESS = u8"起始地址 (hex)";
|
MIN_ADDRESS = u8"起始地址 (hex)";
|
||||||
MAX_ADDRESS = u8"结束地址 (hex)";
|
MAX_ADDRESS = u8"结束地址 (hex)";
|
||||||
STRING_OFFSET = u8"字符串偏移值 (hex)";
|
STRING_OFFSET = u8"字符串偏移值 (hex)";
|
||||||
@ -391,7 +388,7 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
|||||||
DOUBLE_CLICK_TO_REMOVE_HOOK = u8"双击移除不需要的钩子";
|
DOUBLE_CLICK_TO_REMOVE_HOOK = u8"双击移除不需要的钩子";
|
||||||
FILTER_REPETITION = u8"过滤重复文本";
|
FILTER_REPETITION = u8"过滤重复文本";
|
||||||
AUTO_ATTACH = u8"自动附加";
|
AUTO_ATTACH = u8"自动附加";
|
||||||
ATTACH_SAVED_ONLY = u8"自动附加 (仅限保存过配置的游戏)";
|
ATTACH_SAVED_ONLY = u8"自动附加 (saved only)";
|
||||||
SHOW_SYSTEM_PROCESSES = u8"显示系统进程";
|
SHOW_SYSTEM_PROCESSES = u8"显示系统进程";
|
||||||
DEFAULT_CODEPAGE = u8"默认代码页";
|
DEFAULT_CODEPAGE = u8"默认代码页";
|
||||||
FLUSH_DELAY = u8"刷新延迟";
|
FLUSH_DELAY = u8"刷新延迟";
|
||||||
@ -404,7 +401,7 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
|||||||
项目主页: https://github.com/Artikash/Textractor
|
项目主页: https://github.com/Artikash/Textractor
|
||||||
教程视频: https://github.com/Artikash/Textractor/blob/master/docs/TUTORIAL.md
|
教程视频: https://github.com/Artikash/Textractor/blob/master/docs/TUTORIAL.md
|
||||||
如果有任何关于 Textractor 的困难,功能请求或问题,请联系我
|
如果有任何关于 Textractor 的困难,功能请求或问题,请联系我
|
||||||
可以通过项目主页 (Issues 页面) 或通过邮件来联系
|
可以通过项目主页 (问题区) 或通过邮件来联系
|
||||||
项目主页提供基于 GPLv3 协议的源代码)";
|
项目主页提供基于 GPLv3 协议的源代码)";
|
||||||
UPDATE_AVAILABLE = L"有可用的更新: 请从 https://github.com/Artikash/Textractor/releases 下载";
|
UPDATE_AVAILABLE = L"有可用的更新: 请从 https://github.com/Artikash/Textractor/releases 下载";
|
||||||
ALREADY_INJECTED = L"Textractor: 已经注入";
|
ALREADY_INJECTED = L"Textractor: 已经注入";
|
||||||
@ -420,8 +417,7 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
|||||||
HOOK_FAILED = u8"Textractor: 钩子注入失败";
|
HOOK_FAILED = u8"Textractor: 钩子注入失败";
|
||||||
TOO_MANY_HOOKS = u8"Textractor: 钩子数量已达上限: 无法注入";
|
TOO_MANY_HOOKS = u8"Textractor: 钩子数量已达上限: 无法注入";
|
||||||
HOOK_SEARCH_STARTING = u8"Textractor: 开始搜索钩子";
|
HOOK_SEARCH_STARTING = u8"Textractor: 开始搜索钩子";
|
||||||
HOOK_SEARCH_INITIALIZING = u8"Textractor: 初始化钩子搜索 (%f%%)";
|
NOT_ENOUGH_TEXT = u8"Textractor: 没有足够的文本用来精确搜索";
|
||||||
NOT_ENOUGH_TEXT = u8"Textractor: 文本长度不足, 无法精确搜索";
|
|
||||||
HOOK_SEARCH_INITIALIZED = u8"Textractor: 搜索初始化完成, 创建了 %zd 个钩子";
|
HOOK_SEARCH_INITIALIZED = u8"Textractor: 搜索初始化完成, 创建了 %zd 个钩子";
|
||||||
MAKE_GAME_PROCESS_TEXT = u8"Textractor: 请点击游戏区域, 在接下来的 %d 秒内使游戏强制处理文本";
|
MAKE_GAME_PROCESS_TEXT = u8"Textractor: 请点击游戏区域, 在接下来的 %d 秒内使游戏强制处理文本";
|
||||||
HOOK_SEARCH_FINISHED = u8"Textractor: 钩子搜索完毕, 找到了 %d 条结果";
|
HOOK_SEARCH_FINISHED = u8"Textractor: 钩子搜索完毕, 找到了 %d 条结果";
|
||||||
@ -434,65 +430,46 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
|||||||
HIJACK_ERROR = u8"Textractor: Hijack 错误";
|
HIJACK_ERROR = u8"Textractor: Hijack 错误";
|
||||||
COULD_NOT_FIND = u8"Textractor: 无法找到文本";
|
COULD_NOT_FIND = u8"Textractor: 无法找到文本";
|
||||||
TRANSLATE_TO = u8"翻译为";
|
TRANSLATE_TO = u8"翻译为";
|
||||||
TRANSLATE_FROM = u8"原文语言";
|
|
||||||
FILTER_GARBAGE = u8"过滤无意义字符";
|
|
||||||
TRANSLATE_SELECTED_THREAD_ONLY = u8"仅翻译当前选择的文本线程";
|
TRANSLATE_SELECTED_THREAD_ONLY = u8"仅翻译当前选择的文本线程";
|
||||||
RATE_LIMIT_ALL_THREADS = u8"限制请求频率";
|
RATE_LIMIT_ALL_THREADS = u8"限制所有文本线程的请求频率";
|
||||||
RATE_LIMIT_SELECTED_THREAD = u8"限制选中线程的请求频率";
|
RATE_LIMIT_SELECTED_THREAD = u8"限制当前选择线程的请求频率";
|
||||||
USE_TRANS_CACHE = u8"使用缓存的翻译结果";
|
USE_TRANS_CACHE = u8"使用缓存的翻译结果";
|
||||||
MAX_TRANSLATIONS_IN_TIMESPAN = u8"单位时间内最大请求次数";
|
MAX_TRANSLATIONS_IN_TIMESPAN = u8"限流器令牌数";
|
||||||
TIMESPAN = u8"单位时间长度 (ms)";
|
TIMESPAN = u8"限流器令牌重置时间 (ms)";
|
||||||
TOO_MANY_TRANS_REQUESTS = L"超出频率限制: 拒绝发出翻译请求";
|
TOO_MANY_TRANS_REQUESTS = L"太多翻译请求: 拒绝生成更多";
|
||||||
TRANSLATION_ERROR = L"翻译时出错";
|
TRANSLATION_ERROR = L"翻译时出错";
|
||||||
USE_PREV_SENTENCE_CONTEXT = u8"使用之前的句子作为上下文";
|
USE_PREV_SENTENCE_CONTEXT = u8"使用之前的句子作为上下文";
|
||||||
API_KEY = u8"API key";
|
API_KEY = u8"API key";
|
||||||
CHROME_LOCATION = u8"Google Chrome 安装位置";
|
EXTRA_WINDOW_INFO = u8R"(右键修改设置
|
||||||
START_DEVTOOLS = u8"启动 DevTools";
|
在窗口边缘点击并拖拽来移动,或在右下角点击并拖拽来调整大小)";
|
||||||
STOP_DEVTOOLS = u8"停止 DevTools";
|
|
||||||
HIDE_CHROME = u8"隐藏 Chrome 窗口";
|
|
||||||
DEVTOOLS_STATUS = u8"DevTools 状态";
|
|
||||||
AUTO_START = u8"自动启动";
|
|
||||||
ERROR_START_CHROME = L"无法启动或连接到 Chrome";
|
|
||||||
EXTRA_WINDOW_INFO = u8R"(在此点击右键以修改设置
|
|
||||||
在窗口边缘点击并拖拽来移动, 在窗口右下角点击并拖拽来调整大小)";
|
|
||||||
MAX_SENTENCE_SIZE = u8"最大文本长度";
|
MAX_SENTENCE_SIZE = u8"最大文本长度";
|
||||||
TOPMOST = u8"窗口总是置顶";
|
TOPMOST = u8"窗口总是置顶";
|
||||||
DICTIONARY = u8"字典";
|
DICTIONARY = u8"字典";
|
||||||
SHOW_ORIGINAL = u8"显示原文";
|
SHOW_ORIGINAL = u8"显示原文";
|
||||||
SHOW_ORIGINAL_INFO = u8R"(原文将被隐藏
|
SHOW_ORIGINAL_INFO = u8R"(将不显示原文
|
||||||
仅当此扩展位于翻译扩展之后使用时才有效)";
|
仅当此扩展置于翻译扩展之后使用时才有效)";
|
||||||
ORIGINAL_AFTER_TRANSLATION = u8"把原文显示在翻译文本的后面";
|
|
||||||
SIZE_LOCK = u8"锁定窗口大小";
|
|
||||||
POSITION_LOCK = u8"锁定窗口位置";
|
|
||||||
CENTERED_TEXT = u8"居中显示文本";
|
|
||||||
AUTO_RESIZE_WINDOW_HEIGHT = u8"自动改变窗口高度";
|
|
||||||
CLICK_THROUGH = u8"点击穿透\tAlt+X";
|
|
||||||
HIDE_MOUSEOVER = u8"鼠标经过时隐藏窗口";
|
|
||||||
OPACITY = u8"透明度";
|
OPACITY = u8"透明度";
|
||||||
|
SIZE_LOCK = u8"锁定窗口大小";
|
||||||
BG_COLOR = u8"背景颜色";
|
BG_COLOR = u8"背景颜色";
|
||||||
TEXT_COLOR = u8"文本颜色";
|
TEXT_COLOR = u8"文本颜色";
|
||||||
TEXT_OUTLINE = u8"文字描边";
|
TEXT_OUTLINE = u8"文字边框";
|
||||||
OUTLINE_COLOR = u8"文字描边颜色";
|
OUTLINE_COLOR = u8"边框颜色";
|
||||||
OUTLINE_SIZE = u8"文字描边大小";
|
OUTLINE_SIZE = u8"边框大小";
|
||||||
OUTLINE_SIZE_INFO = u8"描边的单位为px (建议保持在字体大小的20%以下)";
|
OUTLINE_SIZE_INFO = u8"以像素为单位的大小(建议保持在字体大小的20%以下)";
|
||||||
FONT = u8"字体";
|
FONT = u8"字体";
|
||||||
LUA_INTRO = u8R"(--[[
|
LUA_INTRO = u8R"(--[[
|
||||||
ProcessSentence 是Textractor每接收到一句文本时都会调用的函数.
|
ProcessSentence 是Textractor每接收到一句文本时都会调用的函数。
|
||||||
参数 sentence: Textractor接收到的文本 (UTF-8), 数据类型为 string.
|
参数 sentence: Textractor接收到的文本 (UTF-8)。
|
||||||
参数 sentenceInfo: 用于保存文本相关信息的表, 数据类型为 tabel.
|
参数 sentenceInfo: 用于保存文本相关信息的table。
|
||||||
|
如果你返回一个字符串,文本将被转换为该字符串。
|
||||||
如果你返回一个字符串,文本将被转换为该字符串.
|
如果返回 nil,该文本将不会被修改。
|
||||||
如果返回 nil, 该文本将不会被修改.
|
此扩展使用了几个Lua解释器的副本用于保证线程安全。
|
||||||
|
在ProcessSentence函数中对全局变量的修改可能不会生效。
|
||||||
此扩展使用了几个Lua解释器的副本用于保证线程安全.
|
sentenceInfo有以下成员:
|
||||||
在 ProcessSentence 函数中对全局变量的修改可能不会生效.
|
"current select": 除非文本属于用户当前选择的文本线程,否则为0。
|
||||||
|
"process id": 这句文本所属的进程id. 0 表示控制台与剪贴板线程。
|
||||||
sentenceInfo 表有以下关键字索引:
|
"text number": 当前选择的文本线程的id. 这是在创建文本线程时逐个递增的计数。 0 为控制台, 1 为剪贴板。
|
||||||
current select: 除非文本属于用户当前选择的文本线程, 否则为0. 数据类型为 number.
|
|
||||||
process id: 这句文本所属的进程ID. 0 表示控制台与剪贴板线程. 数据类型为 number.
|
|
||||||
text number: 当前选择的文本线程的ID. 这是在创建文本线程时自动递增的计数器. 0 为控制台, 1 为剪贴板. 数据类型为 number.
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
function ProcessSentence(sentence, sentenceInfo)
|
function ProcessSentence(sentence, sentenceInfo)
|
||||||
--在此处添加你的代码...
|
--在此处添加你的代码...
|
||||||
end)";
|
end)";
|
||||||
@ -504,28 +481,13 @@ end)";
|
|||||||
REPLACER_INSTRUCTIONS = LR"(使用"Replace"扩展时会使用此文件
|
REPLACER_INSTRUCTIONS = LR"(使用"Replace"扩展时会使用此文件
|
||||||
替换指令必须遵循以下格式:
|
替换指令必须遵循以下格式:
|
||||||
|ORIG|原文|BECOMES|替代文本|END|
|
|ORIG|原文|BECOMES|替代文本|END|
|
||||||
此文件中替换指令之外的所有文本都会被忽略.
|
替换指令之外的所有文本都会被忽略.
|
||||||
符号 ^ 可以代替任意一个字符.
|
|
||||||
原文中的空白字符将被忽略,但是替代文本可以包含空白字符、换行符等.
|
原文中的空白字符将被忽略,但是替代文本可以包含空白字符、换行符等.
|
||||||
此文件必须使用 Unicode 编码 (UTF-16 little endian).)";
|
此文件必须使用Unicode字符集(UTF-16 little endian).)";
|
||||||
REGEX_REPLACER_INSTRUCTIONS = LR"(使用"Regex Replace"扩展时会使用此文件
|
|
||||||
替换指令必须遵循以下格式:
|
|
||||||
|REGEX|正则表达式|BECOMES|替代文本|MODIFIER|修饰符|END|
|
|
||||||
替代文本可以通过 $[编号] 来引用捕获分组 (例如: $1 引用第1个捕获分组).
|
|
||||||
修饰符可以包含以下选项:
|
|
||||||
g 全局替换.
|
|
||||||
i 忽略大小写差异.
|
|
||||||
如果替代文本为空, 那么只会替换第1个匹配的到结果, 而且强制启用大小写敏感.
|
|
||||||
此文件中替换指令之外的所有文本都会被忽略.
|
|
||||||
此文件必须使用 Unicode 编码 (UTF-16 little endian).
|
|
||||||
你可以通过下列链接来学习编写和在线测试正则表达式:
|
|
||||||
https://www.runoob.com/regexp/regexp-intro.html
|
|
||||||
https://regexr.com/)";
|
|
||||||
THREAD_LINKER = u8"线程链接器";
|
THREAD_LINKER = u8"线程链接器";
|
||||||
LINK = u8"链接";
|
LINK = u8"链接";
|
||||||
UNLINK = u8"断开";
|
THREAD_LINK_FROM = u8"需要链接的线程id";
|
||||||
THREAD_LINK_FROM = u8"需要链接的线程ID";
|
THREAD_LINK_TO = u8"链接到的线程id";
|
||||||
THREAD_LINK_TO = u8"链接到的线程ID";
|
|
||||||
HEXADECIMAL = u8"十六进制";
|
HEXADECIMAL = u8"十六进制";
|
||||||
#endif // SIMPLIFIED_CHINESE
|
#endif // SIMPLIFIED_CHINESE
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
//#include <boost/foreach.hpp>
|
//#include <boost/foreach.hpp>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
// jichi 375/2014: Add offset of pusha/pushad
|
// jichi 375/2014: Add offset of pusha/pushad
|
||||||
// http://faydoc.tripod.com/cpu/pushad.htm
|
// http://faydoc.tripod.com/cpu/pushad.htm
|
||||||
@ -5731,21 +5730,21 @@ void SpecialHookShina2(DWORD esp_base, HookParam *, BYTE, DWORD *data, DWORD *sp
|
|||||||
// Used to merge correct text thread.
|
// Used to merge correct text thread.
|
||||||
// 1. Only keep threads with 0 and -1 split
|
// 1. Only keep threads with 0 and -1 split
|
||||||
// 2. Skip the thread withb 0 split and with minimum return address
|
// 2. Skip the thread withb 0 split and with minimum return address
|
||||||
//void SpecialHookShina1(DWORD esp_base, HookParam *hp, BYTE, DWORD *data, DWORD *split, DWORD *len)
|
void SpecialHookShina1(DWORD esp_base, HookParam *hp, BYTE, DWORD *data, DWORD *split, DWORD *len)
|
||||||
//{
|
{
|
||||||
// static DWORD min_retaddr = -1;
|
static DWORD min_retaddr = -1;
|
||||||
// DWORD s = *(DWORD *)(esp_base + hp->split);
|
DWORD s = *(DWORD *)(esp_base + hp->split);
|
||||||
// if (s == 0 || (s & 0xffff) == 0xffff) { // only keep threads with 0 and -1 split
|
if (s == 0 || (s & 0xffff) == 0xffff) { // only keep threads with 0 and -1 split
|
||||||
// if (s == 0 && retof(esp_base) <= min_retaddr) {
|
if (s == 0 && retof(esp_base) <= min_retaddr) {
|
||||||
// min_retaddr = retof(esp_base);
|
min_retaddr = retof(esp_base);
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
// *split = FIXED_SPLIT_VALUE;
|
*split = FIXED_SPLIT_VALUE;
|
||||||
// // Follow the same logic as the hook.
|
// Follow the same logic as the hook.
|
||||||
// *data = *(DWORD *)*data; // DATA_INDIRECT
|
*data = *(DWORD *)*data; // DATA_INDIRECT
|
||||||
// *len = LeadByteTable[*data & 0xff];
|
*len = LeadByteTable[*data & 0xff];
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
||||||
// jichi 8/27/2013
|
// jichi 8/27/2013
|
||||||
// Return ShinaRio version number
|
// Return ShinaRio version number
|
||||||
@ -5804,7 +5803,7 @@ bool InsertShinaHook()
|
|||||||
trigger_fun = [](LPVOID funcAddr, DWORD, DWORD stack)
|
trigger_fun = [](LPVOID funcAddr, DWORD, DWORD stack)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (funcAddr != GetGlyphOutlineA && funcAddr != GetTextExtentPoint32A) return false;
|
if (funcAddr != GetGlyphOutlineA) return false;
|
||||||
for (int i = 0; i < 100; ++i)
|
for (int i = 0; i < 100; ++i)
|
||||||
{
|
{
|
||||||
// Address of text is somewhere on stack in call to func. Search for it.
|
// Address of text is somewhere on stack in call to func. Search for it.
|
||||||
@ -5818,7 +5817,7 @@ bool InsertShinaHook()
|
|||||||
hp.type = DIRECT_READ;
|
hp.type = DIRECT_READ;
|
||||||
hp.address = addr;
|
hp.address = addr;
|
||||||
ConsoleOutput("Textractor: triggered: adding dynamic reader");
|
ConsoleOutput("Textractor: triggered: adding dynamic reader");
|
||||||
NewHook(hp, "ShinaRio READ");
|
NewHook(hp, "READ");
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -5826,8 +5825,9 @@ bool InsertShinaHook()
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
ConsoleOutput("Textractor: ShinaRio 2.50+: adding trigger");
|
ConsoleOutput("Textractor: ShinaRio 2.50+: adding trigger");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (ver >= 48) { // v2.48, v2.49
|
else if (ver >= 48) { // v2.48, v2.49
|
||||||
HookParam hp = {};
|
HookParam hp = {};
|
||||||
hp.address = (DWORD)::GetTextExtentPoint32A;
|
hp.address = (DWORD)::GetTextExtentPoint32A;
|
||||||
hp.text_fun = SpecialHookShina2;
|
hp.text_fun = SpecialHookShina2;
|
||||||
@ -6007,9 +6007,9 @@ bool InsertWaffleHook()
|
|||||||
0x50, //50 push eax
|
0x50, //50 push eax
|
||||||
0x8b, 0xce, //8BCE mov ecx,esi
|
0x8b, 0xce, //8BCE mov ecx,esi
|
||||||
0xc6, 0x45, 0xfc, XX, //C645 FC 01 move byte ptr ss:[ebp-4],?
|
0xc6, 0x45, 0xfc, XX, //C645 FC 01 move byte ptr ss:[ebp-4],?
|
||||||
0x89, 0x75, XX, //8975 D4 move dword ptr ss:[ebp-0x2c],esi
|
0x89, 0x75, 0xd4, //8975 D4 move dword ptr ss:[ebp-0x2c],esi
|
||||||
0xe8, XX4, //E8 ?? call ??
|
0xe8, XX4, //E8 ?? call ??
|
||||||
0x8d, 0x45, XX //8D45 DC lea eax,dword ptr ss:[ebp-0x24]
|
0x8d, 0x45, 0xdc //8D45 DC lea eax,dword ptr ss:[ebp-0x24]
|
||||||
};
|
};
|
||||||
if (DWORD addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress))
|
if (DWORD addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress))
|
||||||
{
|
{
|
||||||
@ -6352,267 +6352,9 @@ static bool InsertYuris2Hook()
|
|||||||
NewHook(hp, "YU-RIS2");
|
NewHook(hp, "YU-RIS2");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static bool Yuris3Filter(LPVOID data, DWORD* size, HookParam*, BYTE)
|
|
||||||
{
|
|
||||||
static wchar_t prev_text;
|
|
||||||
wchar_t* pText = reinterpret_cast<wchar_t*>(data);
|
|
||||||
|
|
||||||
if (prev_text == *pText)
|
|
||||||
{
|
|
||||||
prev_text = '\0';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
prev_text = *pText;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool InsertYuris3Hook()
|
|
||||||
{
|
|
||||||
//by Blu3train
|
|
||||||
HookParam hp = {};
|
|
||||||
wcsncpy_s(hp.module, L"kernel32.dll", MAX_MODULE_SIZE - 1);
|
|
||||||
strncpy_s(hp.function, "MultiByteToWideChar", MAX_MODULE_SIZE - 1);
|
|
||||||
hp.address = 6;
|
|
||||||
hp.offset = 0xC; //arg3
|
|
||||||
hp.index = 0;
|
|
||||||
hp.split = 0x1C;
|
|
||||||
hp.split_index = 0;
|
|
||||||
hp.filter_fun = Yuris3Filter;
|
|
||||||
hp.type = USING_STRING | USING_SPLIT | MODULE_OFFSET | FUNCTION_OFFSET;
|
|
||||||
hp.length_offset = 0x10 / (short)sizeof(void*); // arg4/arg_sz
|
|
||||||
ConsoleOutput("vnreng: INSERT YU-RIS 3");
|
|
||||||
NewHook(hp, "YU-RIS3");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InsertYuris4Hook()
|
|
||||||
{
|
|
||||||
//by Blu3train
|
|
||||||
/*
|
|
||||||
* Sample games:
|
|
||||||
* https://vndb.org/v6540
|
|
||||||
*/
|
|
||||||
bool found = false;
|
|
||||||
const BYTE pattern[] = {
|
|
||||||
0x52, // 52 push edx
|
|
||||||
0x68, 0x00, 0x42, 0x5C, 0x00, // 68 00425C00 push euphoria.exe+1C4200
|
|
||||||
0xFF, 0x15, 0x90, 0x44, 0x7E, 0x00, // FF 15 90447E00 call dword ptr [euphoria.exe+3E4490]
|
|
||||||
0x83, 0xC4, 0x0C, // 83 C4 0C add esp,0C
|
|
||||||
0xEB, 0x5F, // EB 5F jmp euphoria.exe+4F4C5
|
|
||||||
0xFF, 0x35, 0xA4, 0x19, 0x66, 0x00, // FF 35 A4196600 push [euphoria.exe+2619A4]
|
|
||||||
0x52 // 52 push edx
|
|
||||||
};
|
|
||||||
enum { addr_offset = 12 }; // distance to the beginning of the function, which is 0x83, 0xC4, 0x0C (add esp,0C)
|
|
||||||
|
|
||||||
for (auto addr : Util::SearchMemory(pattern, sizeof(pattern), PAGE_EXECUTE, processStartAddress, processStopAddress))
|
|
||||||
{
|
|
||||||
HookParam hp = {};
|
|
||||||
hp.address = addr + addr_offset;
|
|
||||||
hp.offset = pusha_edx_off - 4;
|
|
||||||
hp.type = USING_STRING;
|
|
||||||
ConsoleOutput("Textractor: INSERT YU-RIS 4");
|
|
||||||
NewHook(hp, "YU-RIS4");
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
if (!found) ConsoleOutput("Textractor:YU-RIS 4: pattern not found");
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InsertYuris5Hook()
|
|
||||||
{
|
|
||||||
//by Blu3train
|
|
||||||
/*
|
|
||||||
* Sample games:
|
|
||||||
* https://vndb.org/v4037
|
|
||||||
*/
|
|
||||||
const BYTE bytes[] = {
|
|
||||||
0x33, 0xD2, // xor edx,edx
|
|
||||||
0x88, 0x14, 0x0F, // mov [edi+ecx],dl
|
|
||||||
0xA1, XX4, // mov eax,[exe+2DE630]
|
|
||||||
0x8B, 0x78, 0x3C, // mov edi,[eax+3C]
|
|
||||||
0x8B, 0x58, 0x5C, // mov ebx,[eax+5C]
|
|
||||||
0x88, 0x14, 0x3B // mov [ebx+edi],dl
|
|
||||||
};
|
|
||||||
|
|
||||||
enum { addr_offset = 0 }; // distance to the beginning of the function, which is 0x55 (push ebp)
|
|
||||||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
|
||||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
|
||||||
if (!addr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
HookParam hp = {};
|
|
||||||
hp.address = addr + addr_offset;
|
|
||||||
hp.offset = pusha_ecx_off - 4;
|
|
||||||
hp.type = USING_STRING | NO_CONTEXT;
|
|
||||||
|
|
||||||
ConsoleOutput("Textractor: INSERT YU-RIS 5");
|
|
||||||
NewHook(hp, "YU-RIS5");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool Yuris6Filter(LPVOID data, DWORD* size, HookParam*, BYTE)
|
|
||||||
{
|
|
||||||
auto text = reinterpret_cast<LPSTR>(data);
|
|
||||||
auto len = reinterpret_cast<size_t*>(size);
|
|
||||||
static std::string prevText;
|
|
||||||
|
|
||||||
if (prevText.length() == *len && prevText.find(text, 0, *len) != std::string::npos) // Check if the string is present in the previous one
|
|
||||||
return false;
|
|
||||||
prevText.assign(text, *len);
|
|
||||||
|
|
||||||
// ruby <手水舎/ちょうずや>
|
|
||||||
if (cpp_strnstr(text, "\x81\x83", *len)) { // \x81\x83 -> '<'
|
|
||||||
StringFilterBetween(text, len, "\x81\x5E", 2, "\x81\x84", 2); // \x81\x5E -> '/' , \x81\x84 -> '>'
|
|
||||||
StringFilter(text, len, "\x81\x83", 2); // \x81\x83 -> '<'
|
|
||||||
}
|
|
||||||
// ruby ≪美桜/姉さん≫
|
|
||||||
else if (cpp_strnstr(text, "\x81\xE1", *len)) { // \x81\xE1 -> '≪'
|
|
||||||
StringFilterBetween(text, len, "\x81\x5E", 2, "\x81\xE2", 2); // \x81\x5E -> '/' , \x81\xE2 -> '≫'
|
|
||||||
StringFilter(text, len, "\x81\xE1", 2); // \x81\xE1 -> '≪'
|
|
||||||
}
|
|
||||||
|
|
||||||
CharReplacer(text, len, '=', '-');
|
|
||||||
StringCharReplacer(text, len, "\xEF\xF0", 2, ' ');
|
|
||||||
StringFilter(text, len, "\xEF\xF2", 2);
|
|
||||||
StringFilter(text, len, "\xEF\xF5", 2);
|
|
||||||
StringFilter(text, len, "\x81\x98", 2);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InsertYuris6Hook()
|
|
||||||
{
|
|
||||||
//by Blu3train
|
|
||||||
/*
|
|
||||||
* Sample games:
|
|
||||||
* https://vndb.org/v40058
|
|
||||||
* https://vndb.org/v42883
|
|
||||||
* https://vndb.org/v44092
|
|
||||||
* https://vndb.org/v21171
|
|
||||||
* https://vndb.org/r46910
|
|
||||||
*/
|
|
||||||
const BYTE bytes[] = {
|
|
||||||
0xE9, XX4, // jmp oshitona01.exe+1B629
|
|
||||||
0xBF, XX4, // mov edi,oshitona01.exe+24EEA0
|
|
||||||
0x8A, 0x17, // mov dl,[edi]
|
|
||||||
0x47, // inc edi
|
|
||||||
0x88, 0x16, // mov [esi],dl
|
|
||||||
0x46, // inc esi
|
|
||||||
0x84, 0xD2 // test dl,dl
|
|
||||||
};
|
|
||||||
|
|
||||||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
|
||||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
|
||||||
if (!addr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
HookParam hp = {};
|
|
||||||
hp.address = addr;
|
|
||||||
hp.offset = pusha_eax_off - 4;
|
|
||||||
hp.index = 0x38;
|
|
||||||
hp.codepage = 65001;
|
|
||||||
hp.filter_fun = Yuris6Filter;
|
|
||||||
hp.type = USING_STRING | NO_CONTEXT | DATA_INDIRECT;
|
|
||||||
|
|
||||||
ConsoleOutput("Textractor: INSERT YU-RIS 6");
|
|
||||||
NewHook(hp, "YU-RIS6");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InsertYuris7Hook()
|
|
||||||
{
|
|
||||||
//by Blu3train
|
|
||||||
/*
|
|
||||||
* Sample games:
|
|
||||||
* https://vndb.org/v45381
|
|
||||||
* https://vndb.org/v47458
|
|
||||||
* https://vndb.org/v21144
|
|
||||||
* https://vndb.org/v18681
|
|
||||||
*/
|
|
||||||
const BYTE bytes[] = {
|
|
||||||
0x03, 0xC1, // add eax,ecx
|
|
||||||
0x99, // cdq
|
|
||||||
0xE9, XX4 // jmp nekonin_spin.exe+55753 << hook here
|
|
||||||
};
|
|
||||||
enum { addr_offset = sizeof(bytes) - 5 };
|
|
||||||
|
|
||||||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
|
||||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
|
||||||
if (!addr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
HookParam hp = {};
|
|
||||||
hp.address = addr + addr_offset;
|
|
||||||
hp.offset = pusha_eax_off - 4;
|
|
||||||
hp.index = 0;
|
|
||||||
hp.length_offset = 1; // only 1 character
|
|
||||||
hp.text_fun = [](DWORD esp_base, HookParam*, BYTE, DWORD*, DWORD*, DWORD* len)
|
|
||||||
{
|
|
||||||
*len = (retof(esp_base) == 0) ? 2 : 0;
|
|
||||||
};
|
|
||||||
hp.type = BIG_ENDIAN;
|
|
||||||
ConsoleOutput("vnreng: INSERT YU-RIS7");
|
|
||||||
NewHook(hp, "YU-RIS7");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InsertYuris8Hook()
|
|
||||||
{
|
|
||||||
//by Blu3train
|
|
||||||
/*
|
|
||||||
* Sample games:
|
|
||||||
* https://vndb.org/v47458
|
|
||||||
* https://vndb.org/v45381
|
|
||||||
*/
|
|
||||||
const BYTE bytes[] = {
|
|
||||||
0x57, // push edi << hook here
|
|
||||||
0x56, // push esi
|
|
||||||
0x55, // push ebp
|
|
||||||
0x53, // push ebx
|
|
||||||
0x83, 0xEC, 0x10, // sub esp,10
|
|
||||||
0x8B, 0x5C, 0x24, 0x24, // mov ebx,[esp+24]
|
|
||||||
0x8B, 0x15, XX4, // mov edx,[hajiron.exe+47243C]
|
|
||||||
0x8B, 0x0C, 0x9A, // mov ecx,[edx+ebx*4]
|
|
||||||
0xC6, 0x41, 0x01, 0x03, // mov byte ptr [ecx+01],03
|
|
||||||
0x8B, 0xC3, // mov eax,ebx
|
|
||||||
0xE8,XX4 // call hajiron.exe+54EA4
|
|
||||||
};
|
|
||||||
|
|
||||||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
|
||||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
|
||||||
if (!addr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
HookParam hp = {};
|
|
||||||
hp.address = addr;
|
|
||||||
hp.offset = pusha_edx_off - 4;
|
|
||||||
hp.index = 0;
|
|
||||||
hp.text_fun = [](DWORD esp_base, HookParam*, BYTE, DWORD*, DWORD*, DWORD* len)
|
|
||||||
{
|
|
||||||
DWORD textLen = regof(eax, esp_base);
|
|
||||||
if (textLen > 2)
|
|
||||||
return;
|
|
||||||
*len = (regof(edi, esp_base) >= 0xFA && regof(edi, esp_base) <= 0xFE || regof(edi, esp_base) >= 0x1A0 && regof(edi, esp_base) <= 0x1C2) ? textLen : 0;
|
|
||||||
};
|
|
||||||
hp.type = USING_STRING;
|
|
||||||
ConsoleOutput("vnreng: INSERT YU-RIS8");
|
|
||||||
NewHook(hp, "YU-RIS8");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool InsertYurisHook()
|
bool InsertYurisHook()
|
||||||
{
|
{ return InsertYuris1Hook() || InsertYuris2Hook(); }
|
||||||
bool ok = InsertYuris1Hook();
|
|
||||||
ok = InsertYuris2Hook() || ok;
|
|
||||||
ok = InsertYuris3Hook() || ok;
|
|
||||||
ok = InsertYuris4Hook() || ok;
|
|
||||||
ok = InsertYuris5Hook() || ok;
|
|
||||||
ok = InsertYuris6Hook() || ok;
|
|
||||||
ok = InsertYuris7Hook() || ok;
|
|
||||||
ok = InsertYuris8Hook() || ok;
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InsertCotophaHook1()
|
bool InsertCotophaHook1()
|
||||||
{
|
{
|
||||||
@ -17260,7 +17002,7 @@ void InsertMonoHook(HMODULE h)
|
|||||||
if (!getDomain || !getName || !getJitInfo) goto failed;
|
if (!getDomain || !getName || !getJitInfo) goto failed;
|
||||||
static auto domain = getDomain();
|
static auto domain = getDomain();
|
||||||
if (!domain) goto failed;
|
if (!domain) goto failed;
|
||||||
ConsoleOutput("Textractor: Mono Dynamic ENTER (hooks = %s)", *loadedConfig ? loadedConfig : "brute force");
|
ConsoleOutput("Textractor: Mono Dynamic ENTER (hooks = %s)", loadedConfig ? loadedConfig : "brute force");
|
||||||
const BYTE prolog[] = { 0x55, 0x8b, 0xec };
|
const BYTE prolog[] = { 0x55, 0x8b, 0xec };
|
||||||
for (auto addr : Util::SearchMemory(prolog, sizeof(prolog), PAGE_EXECUTE_READWRITE))
|
for (auto addr : Util::SearchMemory(prolog, sizeof(prolog), PAGE_EXECUTE_READWRITE))
|
||||||
{
|
{
|
||||||
@ -17275,7 +17017,7 @@ void InsertMonoHook(HMODULE h)
|
|||||||
HookParam hp = {};
|
HookParam hp = {};
|
||||||
hp.address = addr;
|
hp.address = addr;
|
||||||
hp.type = USING_UNICODE | FULL_STRING;
|
hp.type = USING_UNICODE | FULL_STRING;
|
||||||
if (!*loadedConfig) hp.type |= KNOWN_UNSTABLE;
|
if (!loadedConfig) hp.type |= KNOWN_UNSTABLE;
|
||||||
hp.offset = 4;
|
hp.offset = 4;
|
||||||
char nameForUser[HOOK_NAME_SIZE] = {};
|
char nameForUser[HOOK_NAME_SIZE] = {};
|
||||||
strncpy_s(nameForUser, name + 1, HOOK_NAME_SIZE - 1);
|
strncpy_s(nameForUser, name + 1, HOOK_NAME_SIZE - 1);
|
||||||
@ -17293,7 +17035,7 @@ void InsertMonoHook(HMODULE h)
|
|||||||
__except (EXCEPTION_EXECUTE_HANDLER) {}
|
__except (EXCEPTION_EXECUTE_HANDLER) {}
|
||||||
}(addr);
|
}(addr);
|
||||||
}
|
}
|
||||||
if (!*loadedConfig) ConsoleOutput("Textractor: Mono Dynamic used brute force: if performance issues arise, please specify the correct hook in the game configuration");
|
if (!loadedConfig) ConsoleOutput("Textractor: Mono Dynamic used brute force: if performance issues arise, please specify the correct hook in the game configuration");
|
||||||
return true;
|
return true;
|
||||||
failed:
|
failed:
|
||||||
ConsoleOutput("Textractor: Mono Dynamic failed");
|
ConsoleOutput("Textractor: Mono Dynamic failed");
|
||||||
@ -17350,7 +17092,7 @@ bool InsertMonoHooks()
|
|||||||
if (FARPROC addr = ::GetProcAddress(h, func.functionName)) {
|
if (FARPROC addr = ::GetProcAddress(h, func.functionName)) {
|
||||||
hp.address = (DWORD)addr;
|
hp.address = (DWORD)addr;
|
||||||
hp.type = func.hookType;
|
hp.type = func.hookType;
|
||||||
if (*loadedConfig) hp.type |= HOOK_EMPTY;
|
if (loadedConfig) hp.type |= HOOK_EMPTY;
|
||||||
hp.filter_fun = NoAsciiFilter;
|
hp.filter_fun = NoAsciiFilter;
|
||||||
hp.offset = func.textIndex * 4;
|
hp.offset = func.textIndex * 4;
|
||||||
hp.length_offset = func.lengthIndex * 4;
|
hp.length_offset = func.lengthIndex * 4;
|
||||||
@ -21285,84 +21027,6 @@ bool InsertTecmoPSPHook()
|
|||||||
}
|
}
|
||||||
#endif // 0
|
#endif // 0
|
||||||
|
|
||||||
|
|
||||||
//for debug
|
|
||||||
void StringBlockProcessor(char* str, size_t* size, size_t fixlength)
|
|
||||||
{
|
|
||||||
size_t original_len = *size;
|
|
||||||
size_t new_len = 0;
|
|
||||||
char* new_str = new char[original_len + 1];
|
|
||||||
|
|
||||||
size_t i = 0;
|
|
||||||
while (i < original_len) {
|
|
||||||
size_t block_end = i + fixlength;
|
|
||||||
if (block_end > original_len) {
|
|
||||||
block_end = original_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t block_len = block_end - i;
|
|
||||||
char* block = str + i;
|
|
||||||
|
|
||||||
for (size_t j = 0; j < block_len; ++j) {
|
|
||||||
if (block[j] != 0) {
|
|
||||||
new_str[new_len++] = block[j];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i = block_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_str[new_len] = '\0';
|
|
||||||
|
|
||||||
std::memcpy(str, new_str, new_len + 1);
|
|
||||||
*size = new_len;
|
|
||||||
delete[] new_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DACFilter(LPVOID data, DWORD* size, HookParam*, BYTE)
|
|
||||||
{
|
|
||||||
auto text = reinterpret_cast<LPSTR>(data);
|
|
||||||
auto len = reinterpret_cast<size_t*>(size);
|
|
||||||
|
|
||||||
StringBlockProcessor(text, len, 0x3f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InsertDACHook()
|
|
||||||
{
|
|
||||||
const BYTE bytecodes[] = {
|
|
||||||
0x0F, 0xBF, 0x56, 0x34, // movsx edx, word ptr ds:[esi+34]
|
|
||||||
0x83, 0xC2, 0x05, // add edx, 5
|
|
||||||
0x8B, 0x8E, 0x00, 0x01, 0x00, 0x00, // mov ecx, dword ptr ds:[esi+100]
|
|
||||||
0x0F, 0xAF, 0xD3 // imul edx, ebx <--
|
|
||||||
};
|
|
||||||
|
|
||||||
ULONG addr = MemDbg::findBytes(bytecodes, sizeof(bytecodes), processStartAddress, processStopAddress);
|
|
||||||
if (addr == 0) {
|
|
||||||
ConsoleOutput("vnreng:DAC: pattern not found");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
enum { addr_offset = 13 };
|
|
||||||
|
|
||||||
HookParam hp = {};
|
|
||||||
hp.type = USING_STRING; //S
|
|
||||||
hp.address = addr + addr_offset;
|
|
||||||
hp.offset = pusha_ecx_off - 4; //-C
|
|
||||||
hp.index = 0x00;
|
|
||||||
hp.filter_fun = DACFilter;
|
|
||||||
hp.length_fun = [](uintptr_t, uintptr_t data)
|
|
||||||
{
|
|
||||||
int len = 0x3f;
|
|
||||||
return len * 4;
|
|
||||||
};
|
|
||||||
NewHook(hp, "DAC");
|
|
||||||
ConsoleOutput("vnreng: INSERT DAC");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** jichi 7/19/2014 PCSX2
|
/** jichi 7/19/2014 PCSX2
|
||||||
* Tested wit pcsx2-v1.2.1-328-gef0e3fe-windows-x86, built at http://buildbot.orphis.net/pcsx2
|
* Tested wit pcsx2-v1.2.1-328-gef0e3fe-windows-x86, built at http://buildbot.orphis.net/pcsx2
|
||||||
*/
|
*/
|
||||||
@ -21598,6 +21262,7 @@ bool InsertTypeMoonPS2Hook()
|
|||||||
ConsoleOutput("vnreng: TypeMoon PS2: leave");
|
ConsoleOutput("vnreng: TypeMoon PS2: leave");
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 8/3/2014 jichi
|
/** 8/3/2014 jichi
|
||||||
* Tested game: School Rumble ねる娘<EFBFBD>育つ
|
* Tested game: School Rumble ねる娘<EFBFBD>育つ
|
||||||
*
|
*
|
||||||
|
@ -14,7 +14,7 @@ namespace Engine {
|
|||||||
// Global variables
|
// Global variables
|
||||||
extern wchar_t *processName, // cached
|
extern wchar_t *processName, // cached
|
||||||
processPath[MAX_PATH]; // cached
|
processPath[MAX_PATH]; // cached
|
||||||
inline const char *requestedEngine = "", * loadedConfig = "";
|
inline const char *requestedEngine = nullptr, *loadedConfig = nullptr;
|
||||||
|
|
||||||
bool InsertMonoHooks(); // Mono
|
bool InsertMonoHooks(); // Mono
|
||||||
|
|
||||||
@ -96,7 +96,6 @@ bool InsertCandyHook(); // SystemC@CandySoft: *.fpk
|
|||||||
bool InsertCatSystemHook(); // CatSystem2: *.int
|
bool InsertCatSystemHook(); // CatSystem2: *.int
|
||||||
bool InsertCMVSHook(); // CMVS: data/pack/*.cpz; do not support the latest cmvs32.exe and cmvs64.exe
|
bool InsertCMVSHook(); // CMVS: data/pack/*.cpz; do not support the latest cmvs32.exe and cmvs64.exe
|
||||||
bool InsertCotophaHook(); // Cotopha: *.noa
|
bool InsertCotophaHook(); // Cotopha: *.noa
|
||||||
bool InsertDACHook(); // DAC
|
|
||||||
bool InsertDebonosuHook(); // Debonosu: bmp.bak and dsetup.dll
|
bool InsertDebonosuHook(); // Debonosu: bmp.bak and dsetup.dll
|
||||||
bool InsertEaglsHook(); // E.A.G.L.S: EAGLES.dll
|
bool InsertEaglsHook(); // E.A.G.L.S: EAGLES.dll
|
||||||
bool InsertEMEHook(); // EmonEngine: emecfg.ecf
|
bool InsertEMEHook(); // EmonEngine: emecfg.ecf
|
||||||
|
@ -45,13 +45,13 @@ namespace Engine
|
|||||||
if (AutoHandle<> configFile = CreateFileW(configFilename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))
|
if (AutoHandle<> configFile = CreateFileW(configFilename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))
|
||||||
{
|
{
|
||||||
ReadFile(configFile, configFileData, sizeof(configFileData) - 1, DUMMY, nullptr);
|
ReadFile(configFile, configFileData, sizeof(configFileData) - 1, DUMMY, nullptr);
|
||||||
if (strnicmp(configFileData, "engine:", 7) == 0)
|
if (strncmp(configFileData, "Engine:", 7) == 0)
|
||||||
{
|
{
|
||||||
if (const char* config = strchr(configFileData, '\n')) *(char*)(loadedConfig = config)++ = 0;
|
if (loadedConfig = strchr(configFileData, '\n')) *(char*)loadedConfig++ = 0;
|
||||||
ConsoleOutput("Textractor: Engine = %s", requestedEngine = strlwr(configFileData + 7));
|
ConsoleOutput("Textractor: Engine = %s", requestedEngine = configFileData + 7);
|
||||||
}
|
}
|
||||||
else loadedConfig = configFileData;
|
else loadedConfig = configFileData;
|
||||||
if (!*loadedConfig || strstr(configFileData, "https://")) loadedConfig = "";
|
if ((loadedConfig && !*loadedConfig) || strstr(configFileData, "https://")) loadedConfig = nullptr;
|
||||||
else ConsoleOutput("Textractor: game configuration loaded");
|
else ConsoleOutput("Textractor: game configuration loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,14 +67,14 @@ namespace Engine
|
|||||||
spDefault.maxAddress = processStopAddress;
|
spDefault.maxAddress = processStopAddress;
|
||||||
ConsoleOutput("Textractor: hijacking process located from 0x%p to 0x%p", processStartAddress, processStopAddress);
|
ConsoleOutput("Textractor: hijacking process located from 0x%p to 0x%p", processStartAddress, processStopAddress);
|
||||||
|
|
||||||
if (!strstr(requestedEngine, "none")) DetermineEngineType();
|
DetermineEngineType();
|
||||||
if (processStartAddress + 0x40000 > processStopAddress) ConsoleOutput("Textractor: WARNING injected process is very small, possibly a dummy!");
|
if (processStartAddress + 0x40000 > processStopAddress) ConsoleOutput("Textractor: WARNING injected process is very small, possibly a dummy!");
|
||||||
}(), 0);
|
}(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShouldMonoHook(const char* name)
|
bool ShouldMonoHook(const char* name)
|
||||||
{
|
{
|
||||||
if (!*loadedConfig) return strstr(name, "string:") && !strstr(name, "string:mem");
|
if (!loadedConfig) return strstr(name, "string:") && !strstr(name, "string:mem");
|
||||||
for (const char* hook = loadedConfig; hook; hook = strchr(hook + 1, '\t'))
|
for (const char* hook = loadedConfig; hook; hook = strchr(hook + 1, '\t'))
|
||||||
for (auto start = name; *start; ++start)
|
for (auto start = name; *start; ++start)
|
||||||
for (int i = 0; ; ++i)
|
for (int i = 0; ; ++i)
|
||||||
|
@ -54,11 +54,6 @@ bool DeterminePCEngine()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Util::CheckFile(L"script.dpk")) {
|
|
||||||
InsertDACHook();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 5/14/2015: Skip hijacking BALDRSKY ZEROs
|
// jichi 5/14/2015: Skip hijacking BALDRSKY ZEROs
|
||||||
//if (Util::CheckFile(L"bsz_Data\\Mono\\mono.dll") || Util::CheckFile(L"bsz2_Data\\Mono\\mono.dll")) {
|
//if (Util::CheckFile(L"bsz_Data\\Mono\\mono.dll") || Util::CheckFile(L"bsz2_Data\\Mono\\mono.dll")) {
|
||||||
// ConsoleOutput("vnreng: IGNORE BALDRSKY ZEROs");
|
// ConsoleOutput("vnreng: IGNORE BALDRSKY ZEROs");
|
||||||
@ -634,9 +629,10 @@ bool DetermineEngineAtLast()
|
|||||||
}
|
}
|
||||||
if (Util::CheckFile(L"MovieTexture.dll") && (InsertPensilHook() || Insert2RMHook())) // MovieTexture.dll also exists in 2RM games such as 母子愛2体験版, which is checked first
|
if (Util::CheckFile(L"MovieTexture.dll") && (InsertPensilHook() || Insert2RMHook())) // MovieTexture.dll also exists in 2RM games such as 母子愛2体験版, which is checked first
|
||||||
return true;
|
return true;
|
||||||
if ((Util::CheckFile(L"system") && Util::CheckFile(L"system.dat")) || Util::CheckFile(L"*01")) // jichi 7/31/2015 & Artikash 6/15/2018
|
if ((Util::CheckFile(L"system") && Util::CheckFile(L"system.dat")) || Util::CheckFile(L"*01")) { // jichi 7/31/2015 & Artikash 6/15/2018
|
||||||
if (InsertAbelHook())
|
InsertAbelHook();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
if (Util::CheckFile(L"data\\*.cpk")) { // jichi 12/2/2014
|
if (Util::CheckFile(L"data\\*.cpk")) { // jichi 12/2/2014
|
||||||
Insert5pbHook();
|
Insert5pbHook();
|
||||||
return true;
|
return true;
|
||||||
|
@ -80,7 +80,7 @@ namespace Engine
|
|||||||
if (!getDomain || !getName || !getJitInfo) goto failed;
|
if (!getDomain || !getName || !getJitInfo) goto failed;
|
||||||
static auto domain = getDomain();
|
static auto domain = getDomain();
|
||||||
if (!domain) goto failed;
|
if (!domain) goto failed;
|
||||||
ConsoleOutput("Textractor: Mono Dynamic ENTER (hooks = %s)", *loadedConfig ? loadedConfig : "brute force");
|
ConsoleOutput("Textractor: Mono Dynamic ENTER (hooks = %s)", loadedConfig ? loadedConfig : "brute force");
|
||||||
const BYTE prolog1[] = { 0x55, 0x48, 0x8b, 0xec };
|
const BYTE prolog1[] = { 0x55, 0x48, 0x8b, 0xec };
|
||||||
const BYTE prolog2[] = { 0x48, 0x83, 0xec };
|
const BYTE prolog2[] = { 0x48, 0x83, 0xec };
|
||||||
for (auto [prolog, size] : Array<const BYTE*, size_t>{ { prolog1, sizeof(prolog1) }, { prolog2, sizeof(prolog2) } })
|
for (auto [prolog, size] : Array<const BYTE*, size_t>{ { prolog1, sizeof(prolog1) }, { prolog2, sizeof(prolog2) } })
|
||||||
@ -97,7 +97,7 @@ namespace Engine
|
|||||||
HookParam hp = {};
|
HookParam hp = {};
|
||||||
hp.address = addr;
|
hp.address = addr;
|
||||||
hp.type = USING_STRING | USING_UNICODE | FULL_STRING;
|
hp.type = USING_STRING | USING_UNICODE | FULL_STRING;
|
||||||
if (!*loadedConfig) hp.type |= KNOWN_UNSTABLE;
|
if (!loadedConfig) hp.type |= KNOWN_UNSTABLE;
|
||||||
hp.offset = -0x20; // rcx
|
hp.offset = -0x20; // rcx
|
||||||
hp.padding = 20;
|
hp.padding = 20;
|
||||||
char nameForUser[HOOK_NAME_SIZE] = {};
|
char nameForUser[HOOK_NAME_SIZE] = {};
|
||||||
@ -119,7 +119,7 @@ namespace Engine
|
|||||||
}(addr);
|
}(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*loadedConfig) ConsoleOutput("Textractor: Mono Dynamic used brute force: if performance issues arise, please specify the correct hook in the game configuration");
|
if (!loadedConfig) ConsoleOutput("Textractor: Mono Dynamic used brute force: if performance issues arise, please specify the correct hook in the game configuration");
|
||||||
return true;
|
return true;
|
||||||
failed:
|
failed:
|
||||||
ConsoleOutput("Textractor: Mono Dynamic failed");
|
ConsoleOutput("Textractor: Mono Dynamic failed");
|
||||||
|
@ -193,7 +193,6 @@ void TextHook::Send(uintptr_t dwDataBase)
|
|||||||
|
|
||||||
TextOutput(tp, buffer, count);
|
TextOutput(tp, buffer, count);
|
||||||
#endif // _WIN64
|
#endif // _WIN64
|
||||||
++*pbData;
|
|
||||||
}
|
}
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user