forked from Public-Mirror/Textractor
Compare commits
27 Commits
appveyor_t
...
x221Mod
Author | SHA1 | Date | |
---|---|---|---|
4335a4560a | |||
22946df452 | |||
3b22857d12 | |||
|
df5b830d17 | ||
|
f3fbe04409 | ||
|
5adeb1fab7 | ||
|
5c7b41dd84 | ||
|
92e2e85191 | ||
|
0bc23ba2c7 | ||
|
fd8a090e28 | ||
|
aa00d9e789 | ||
|
cfa11c5646 | ||
|
446f6d44e6 | ||
|
ff1a7a358c | ||
|
60a5d74eda | ||
|
4cebe9462f | ||
|
d97ebd4fbb | ||
|
233e75225c | ||
|
72ad51f039 | ||
|
39fcfaf644 | ||
|
5eb0440f01 | ||
|
c4ca84d39b | ||
|
c7b818aa75 | ||
|
2cb45ab9e3 | ||
|
72132239a5 | ||
|
5eaafbe81c | ||
|
97f2bc6304 |
@ -5,21 +5,21 @@ skip_branch_with_pr: false
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
arch: x64
|
||||
platform: x64
|
||||
qtbin: msvc2019_64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
qtbin: msvc2017_64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
arch: x86
|
||||
platform: Win32
|
||||
qtbin: msvc2019
|
||||
qtbin: msvc2017
|
||||
|
||||
before_build:
|
||||
- git submodule update --init
|
||||
- cd C:\
|
||||
- mkdir %arch%
|
||||
- cd %arch%
|
||||
- cmake -G "Visual Studio 16 2019" -A "%platform%" -DQt5_DIR="C:\Qt\5.15\%qtbin%\lib\cmake\Qt5" -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DVERSION="" ../Textractor
|
||||
- cmake -G "Visual Studio 15 2017" -A %platform% -DQt5_DIR="C:\Qt\5.13.2\%qtbin%\lib\cmake\Qt5" -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DVERSION="" ../Textractor
|
||||
|
||||
build:
|
||||
project: C:\%arch%\Textractor.sln
|
||||
|
@ -35,6 +35,10 @@ target_precompile_headers(pch PUBLIC include/common.h)
|
||||
file(GLOB ASSETS assets/*)
|
||||
file(COPY ${ASSETS} DESTINATION ${CMAKE_FINAL_OUTPUT_DIRECTORY})
|
||||
|
||||
include(QtUtils)
|
||||
msvc_registry_search()
|
||||
find_qt5(Core Widgets WinExtras WebSockets)
|
||||
|
||||
add_library(text text.cpp)
|
||||
target_compile_definitions(text PRIVATE ${TEXT_LANGUAGE})
|
||||
link_libraries(text)
|
||||
|
@ -4,25 +4,29 @@
|
||||
"name": "x86-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"cmakeCommandArgs": "-DQT_ROOT=/Qt",
|
||||
"inheritEnvironments": [ "msvc_x86" ]
|
||||
},
|
||||
{
|
||||
"name": "x86-RelWithDebInfo",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"cmakeCommandArgs": "-DQT_ROOT=/Qt",
|
||||
"inheritEnvironments": [ "msvc_x86" ]
|
||||
},
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"cmakeCommandArgs": "-DQT_ROOT=/Qt",
|
||||
"inheritEnvironments": [ "msvc_x64" ]
|
||||
},
|
||||
{
|
||||
"name": "x64-RelWithDebInfo",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"cmakeCommandArgs": "-DQT_ROOT=/Qt",
|
||||
"inheritEnvironments": [ "msvc_x64" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -1,7 +1,3 @@
|
||||
include(QtUtils)
|
||||
msvc_registry_search()
|
||||
find_qt5(Core Widgets WinExtras)
|
||||
|
||||
add_executable(Textractor WIN32
|
||||
main.cpp
|
||||
exception.cpp
|
||||
|
@ -88,6 +88,8 @@ namespace
|
||||
TextThread* current = nullptr;
|
||||
MainWindow* This = nullptr;
|
||||
|
||||
void FindHooks();
|
||||
|
||||
QString TextThreadString(TextThread& thread)
|
||||
{
|
||||
return QString("%1:%2:%3:%4:%5: %6").arg(
|
||||
@ -274,7 +276,8 @@ namespace
|
||||
void AddHook(QString hook)
|
||||
{
|
||||
if (QString hookCode = QInputDialog::getText(This, ADD_HOOK, CODE_INFODUMP, QLineEdit::Normal, hook, &ok, Qt::WindowCloseButtonHint); ok)
|
||||
if (auto hp = HookCode::Parse(S(hookCode))) try { Host::InsertHook(selectedProcessId, hp.value()); } catch (std::out_of_range) {}
|
||||
if (hookCode.startsWith("S") || hookCode.startsWith("/S")) FindHooks(); // backwards compatibility for old hook search UX
|
||||
else if (auto hp = HookCode::Parse(S(hookCode))) try { Host::InsertHook(selectedProcessId, hp.value()); } catch (std::out_of_range) {}
|
||||
else Host::AddConsoleOutput(INVALID_CODE);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
![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)
|
||||
[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.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.
|
||||
@ -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>
|
||||
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 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](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
|
||||
Before compiling Textractor, you need Qt version 5.13 and Visual Studio with CMake support.
|
||||
|
52
README_DE.md
Normal file
52
README_DE.md
Normal file
@ -0,0 +1,52 @@
|
||||
# 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
|
||||
|
||||
[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)
|
||||
[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)
|
||||
|
||||
## [Video tutorial](docs/TUTORIAL.md)
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
![À 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)
|
||||
[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.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.
|
||||
@ -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>
|
||||
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 ainsi que ce fichier README.
|
||||
Contribuer à une traduction est simple: il suffit de traduire les chaînes dans [text.cpp](text.cpp) ainsi que ce fichier README.
|
||||
|
||||
## Compilation
|
||||
|
||||
|
31
README_ID.md
31
README_ID.md
@ -2,9 +2,9 @@
|
||||
|
||||
![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)
|
||||
[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.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>
|
||||
**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>
|
||||
Lihat [video tutorial](docs/TUTORIAL.md) untuk mengetahui bagaimana cara menggunakannya.
|
||||
|
||||
## Pengunduhan
|
||||
@ -21,36 +21,33 @@ Rilisan Terakhir ITHVNR dapat diunduh [disini](https://drive.google.com/open?id=
|
||||
|
||||
## Dukungan
|
||||
|
||||
Please let me know of any bugs, games that Textractor has trouble hooking, feature requests, or other suggestions.<br>
|
||||
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/).
|
||||
Tolong beritahu saya jika kamu menemukan kutu, 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 mengunduh game tersebut, atau hadiahkan game tersebut di [Steam](https://steamcommunity.com/profiles/76561198097566313/).
|
||||
|
||||
## Ekstensi
|
||||
|
||||
Lihat [project sampel ekstensi saya](https://github.com/Artikash/ExampleExtension) untuk melihat bagaimana cara membuat ekstensi.<br>
|
||||
Lihat folder extensions untuk melihat sampel ekstensi.
|
||||
Lihat ekstensi folder untuk melihat sampel ekstensi.
|
||||
|
||||
## Kontribusi
|
||||
|
||||
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, 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 lalu terjemahkan README ini.
|
||||
Seluruh kontribusi diapresiasi! Tolong email saya di akashmozumdar@gmail.com jika kamu memiliki pertanyaan mengenai kode dasar nya.<br>
|
||||
Kamu harus menggunakan proses standar dalam membuat permintaan pull(fork, cabang, perubahan commit, membuat PR dari cabang kamu ke master saya).<br>
|
||||
Berkontribusi dalam penerjemahan dapat dilakukan dengan mudah : cukup terjemahkan string dari [text.cpp](text.cpp) lalu terjemahkan README ini.
|
||||
|
||||
## Compiling
|
||||
## Mengcompile
|
||||
|
||||
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. Run Textractor.exe.
|
||||
Lalu kamu dapat membuka folder di Visual Studio, dan build. Jalankan Textractor.exe.
|
||||
|
||||
|
||||
## Arsitektur Project
|
||||
|
||||
Host (lihat folder host) menginject texthook.dll (dibuat dari folder texthook) kedalam target process dan disambungkan lewat 2 file pipe.<br>
|
||||
Host (lihat folder host) menyuntikan texthook.dll (dibuat dari folder texthook) kedalam target proses dan disambungkan lewat 2 file pipe.<br>
|
||||
Host menulis ke hostPipe, texthook menulis ke hookPipe.<br>
|
||||
texthook menunggu pipe tersambung, lalu menginject beberapa instruksi ke teks yang menghasilkan fungsi (contoh: TextOut, GetGlyphOutline) yang membuat input dikirim melewati pipa.<br>
|
||||
texthook menunggu pipe tersambung, lalu menyuntikan 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>
|
||||
Text yang diterima host melewati pipe lalu diproses lagi sebelum dikembalikan ke GUI.<br>
|
||||
Dan pada akhirnya, GUI melepas text ke ekstensi sebelum menampilkan teks.
|
||||
Teks yang diterima host melewati pipe lalu diproses lagi sebelum dikembalikan ke GUI.<br>
|
||||
Dan pada akhirnya, GUI melepas teks ke ekstensi sebelum menampilkan teks.
|
||||
|
||||
## [Pengembang](docs/CREDITS.md)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
![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)
|
||||
[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.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.
|
||||
@ -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>
|
||||
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 cosi come questo README.
|
||||
Contribuire alla traduzione è semplice: traduci le stringhe in [text.cpp](text.cpp) cosi come questo README.
|
||||
|
||||
## Compiling
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# 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)
|
||||
[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** はビジュアルノベル文字抽出プログラム。
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
![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)
|
||||
[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.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) 를 참고하세요.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
![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)
|
||||
[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** (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.
|
||||
@ -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>
|
||||
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 assim como esse README.
|
||||
Contribuir com uma tradução é fácil: basta traduzir as linhas do [text.cpp](text.cpp) assim como esse README.
|
||||
|
||||
## Compilando
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
![Как это выглядит](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)
|
||||
[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.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) для быстрого ознакомления.
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
Любой вклад приветствуется! Пишите мне(автору) на akashmozumdar@gmail.com, если у вас есть любые вопросы о кодовой базе.<br>
|
||||
Используйте стандартные действия для создания pull request (fork, branch, commit changes, создайте PR из своей ветки branch на мой master).<br>
|
||||
Вклад в перевод совсем не сложен: просто переведите строки в text.cpp, также, как и этот README.
|
||||
Вклад в перевод совсем не сложен: просто переведите строки в [text.cpp](text.cpp), также, как и этот README.
|
||||
|
||||
## Компиляция
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# 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)
|
||||
[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)
|
||||
|
||||
## 概述
|
||||
|
||||
@ -30,7 +30,7 @@ Textractor 的发行版可以在[这里](https://github.com/Artikash/Textractor/
|
||||
|
||||
欢迎一切贡献!如有任何关于代码的疑问,请向 akashmozumdar@gmail.com 发邮件.<br>
|
||||
你应当使用创建 PR 的标准过程 (分岔 (fork), 分支 (branch), 提交变化, 创建从你的分支到我的 master 分支的 PR).<br>
|
||||
提供翻译贡献很简单: 只需翻译 text.cpp 中的字符串和这份 README 即可.
|
||||
提供翻译贡献很简单: 只需翻译 [text.cpp](text.cpp) 中的字符串和这份 README 即可.
|
||||
|
||||
## 编译
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
![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)
|
||||
[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**
|
||||
(หรือ 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,49 +1,24 @@
|
||||
macro(msvc_registry_search)
|
||||
if(NOT DEFINED Qt5_DIR)
|
||||
# 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)
|
||||
if (NOT EXISTS ${QT_ROOT})
|
||||
# look for user-registry pointing to qtcreator
|
||||
get_filename_component(QT_ROOT [HKEY_CURRENT_USER\\Software\\Classes\\Applications\\QtProject.QtCreator.pro\\shell\\Open\\Command] PATH)
|
||||
|
||||
# get root path so we can search for 5.3, 5.4, 5.5, etc
|
||||
string(REPLACE "/Tools" ";" QT_BIN "${QT_BIN}")
|
||||
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")
|
||||
# get root path
|
||||
string(REPLACE "/Tools" ";" QT_ROOT "${QT_ROOT}")
|
||||
list(GET QT_ROOT 0 QT_ROOT)
|
||||
endif()
|
||||
|
||||
set(QT_VERSION 5.13.2)
|
||||
set(QT_MSVC 2019)
|
||||
|
||||
if(QT_MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
SET(QT_SUFFIX "_64")
|
||||
else()
|
||||
set(QT_SUFFIX "")
|
||||
endif()
|
||||
|
||||
# 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()
|
||||
set(Qt5_DIR "${QT_VERSION}/msvc2017${QT_SUFFIX}/lib/cmake/Qt5")
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
@ -53,6 +28,11 @@ macro(find_qt5)
|
||||
#set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
#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})
|
||||
|
||||
if(Qt5_FOUND)
|
||||
|
@ -14,7 +14,7 @@
|
||||
- French translation by [Racky](mailto:maitrenoah@gmail.com) and [Gratusfr](https://github.com/Gratusfr)
|
||||
- Spanish translation by [scese250](https://github.com/scese250)
|
||||
- Turkish translation by [niisokusu](https://reddit.com/u/niisokusu)
|
||||
- Simplified Chinese translation by [tinyAdapter](https://github.com/tinyAdapter) and [lgztx96](https://github.com/lgztx96)
|
||||
- Simplified Chinese translation by [tinyAdapter](https://github.com/tinyAdapter), [lgztx96](https://github.com/lgztx96) and [chinanoahli](https://github.com/chinanoahli)
|
||||
- Russian translation by [TokcDK](https://github.com/TokcDK)
|
||||
- Indonesian translation by [Hawxone](https://github.com/Hawxone)
|
||||
- Portuguese translation by [TsumiHokiro](https://github.com/TsumiHokiro)
|
||||
|
@ -1,6 +1,3 @@
|
||||
include(QtUtils)
|
||||
msvc_registry_search()
|
||||
find_qt5(Core Widgets WebSockets)
|
||||
cmake_policy(SET CMP0037 OLD)
|
||||
|
||||
add_library(Bing\ Translate MODULE bingtranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
|
||||
|
@ -49,7 +49,7 @@ private:
|
||||
}
|
||||
|
||||
static constexpr C endImpl[5] = { '|', 'E', 'N', 'D', '|' };
|
||||
static constexpr std::basic_string_view end{ endImpl, 5 };
|
||||
static constexpr std::basic_string_view<C> end{ endImpl, 5 };
|
||||
|
||||
std::basic_streambuf<char>& streambuf;
|
||||
std::basic_string<C> buffer;
|
||||
|
@ -9,92 +9,119 @@ const char* TRANSLATION_PROVIDER = "DeepL Translate";
|
||||
const char* GET_API_KEY_FROM = "https://www.deepl.com/pro.html#developer";
|
||||
extern const QStringList languagesTo
|
||||
{
|
||||
"Arabic",
|
||||
"Bulgarian",
|
||||
"Chinese (Simplified)",
|
||||
"Czech",
|
||||
"Danish",
|
||||
"Dutch",
|
||||
"English (American)",
|
||||
"German",
|
||||
"Greek",
|
||||
"English (backward compatibility)",
|
||||
"English (British)",
|
||||
"English (American)",
|
||||
"Spanish",
|
||||
"Estonian",
|
||||
"Finnish",
|
||||
"French",
|
||||
"German",
|
||||
"Greek",
|
||||
"Hungarian",
|
||||
"Indonesian",
|
||||
"Italian",
|
||||
"Japanese",
|
||||
"Latvian",
|
||||
"Korean",
|
||||
"Lithuanian",
|
||||
"Latvian",
|
||||
"Norwegian Bokmål",
|
||||
"Dutch",
|
||||
"Polish",
|
||||
"Portuguese (Brazil)",
|
||||
"Portuguese (Portugal)",
|
||||
"Portuguese (backward compatibility)",
|
||||
"Portuguese (Brazilian)",
|
||||
"Portuguese (all Portuguese variants excluding Brazilian Portuguese)",
|
||||
"Romanian",
|
||||
"Russian",
|
||||
"Slovak",
|
||||
"Slovenian",
|
||||
"Spanish",
|
||||
"Swedish"
|
||||
"Swedish",
|
||||
"Turkish",
|
||||
"Ukrainian",
|
||||
"Chinese (backward compatibility)",
|
||||
"Chinese (simplified)",
|
||||
"Chinese (traditional)"
|
||||
},
|
||||
languagesFrom
|
||||
{
|
||||
"Arabic",
|
||||
"Bulgarian",
|
||||
"Chinese",
|
||||
"Chinese (all Chinese variants)",
|
||||
"Czech",
|
||||
"Danish",
|
||||
"Dutch",
|
||||
"English",
|
||||
"English (all English variants)",
|
||||
"Estonian",
|
||||
"Finnish",
|
||||
"French",
|
||||
"German",
|
||||
"Greek",
|
||||
"Hungarian",
|
||||
"Indonesian",
|
||||
"Italian",
|
||||
"Japanese",
|
||||
"Korean",
|
||||
"Latvian",
|
||||
"Lithuanian",
|
||||
"Norwegian Bokmål",
|
||||
"Polish",
|
||||
"Portuguese",
|
||||
"Portuguese (all Portuguese variants)",
|
||||
"Romanian",
|
||||
"Russian",
|
||||
"Slovak",
|
||||
"Slovenian",
|
||||
"Spanish",
|
||||
"Swedish"
|
||||
"Swedish",
|
||||
"Turkish",
|
||||
"Ukrainian"
|
||||
};
|
||||
extern const std::unordered_map<std::wstring, std::wstring> codes
|
||||
{
|
||||
{ { L"Arabic" }, { L"AR" } },
|
||||
{ { L"Bulgarian" }, { L"BG" } },
|
||||
{ { L"Chinese" }, { L"ZH" } },
|
||||
{ { L"Chinese (Simplified)" }, { L"ZH" } },
|
||||
{ { L"Czech" }, { L"CS" } },
|
||||
{ { L"Danish" }, { L"DA" } },
|
||||
{ { L"Dutch" }, { L"NL" } },
|
||||
{ { L"English" }, { L"EN" } },
|
||||
{ { L"English (American)" }, { L"EN-US" } },
|
||||
{ { L"German" }, { L"DE" } },
|
||||
{ { L"Greek" }, { L"EL" } },
|
||||
{ { 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"Spanish" }, { L"ES" } },
|
||||
{ { L"Estonian" }, { L"ET" } },
|
||||
{ { L"Finnish" }, { L"FI" } },
|
||||
{ { L"French" }, { L"FR" } },
|
||||
{ { L"German" }, { L"DE" } },
|
||||
{ { L"Greek" }, { L"EL" } },
|
||||
{ { L"Hungarian" }, { L"HU" } },
|
||||
{ { L"Indonesian" }, { L"ID" } },
|
||||
{ { L"Italian" }, { L"IT" } },
|
||||
{ { L"Japanese" }, { L"JA" } },
|
||||
{ { L"Latvian" }, { L"LV" } },
|
||||
{ { L"Korean" }, { L"KO" } },
|
||||
{ { L"Lithuanian" }, { L"LT" } },
|
||||
{ { L"Latvian" }, { L"LV" } },
|
||||
{ { L"Norwegian Bokmål" }, { L"NB" } },
|
||||
{ { L"Dutch" }, { L"NL" } },
|
||||
{ { L"Polish" }, { L"PL" } },
|
||||
{ { L"Portuguese" }, { L"PT" } },
|
||||
{ { L"Portuguese (Brazil)" }, { L"PT-BR" } },
|
||||
{ { L"Portuguese (Portugal)" }, { L"PT-PT" } },
|
||||
{ { L"Portuguese (all Portuguese variants)" }, { L"PT" } },
|
||||
{ { L"Portuguese (backward compatibility)" }, { L"PT" } },
|
||||
{ { L"Portuguese (Brazilian)" }, { L"PT-BR" } },
|
||||
{ { L"Portuguese (all Portuguese variants excluding Brazilian Portuguese)" }, { L"PT-PT" } },
|
||||
{ { L"Romanian" }, { L"RO" } },
|
||||
{ { L"Russian" }, { L"RU" } },
|
||||
{ { L"Slovak" }, { L"SK" } },
|
||||
{ { L"Slovenian" }, { L"SL" } },
|
||||
{ { L"Spanish" }, { L"ES" } },
|
||||
{ { 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" } }
|
||||
|
||||
};
|
||||
|
||||
bool translateSelectedOnly = true, useRateLimiter = true, rateLimitSelected = true, useCache = true, useFilter = true;
|
||||
|
@ -36,11 +36,11 @@ namespace
|
||||
if (process) DevTools::Close();
|
||||
|
||||
auto args = FormatString(
|
||||
L"%s --proxy-server=direct:// --disable-extensions --disable-gpu --user-data-dir=%s\\devtoolscache --remote-debugging-port=9222",
|
||||
L"%s --proxy-server=direct:// --disable-extensions --disable-gpu --no-first-run --user-data-dir=\"%s\\devtoolscache\" --remote-debugging-port=9222",
|
||||
chromePath,
|
||||
std::filesystem::current_path().wstring()
|
||||
);
|
||||
if (headless) args += L" --headless";
|
||||
args += headless ? L" --window-size=1920,1080 --headless" : L" --window-size=850,900";
|
||||
DWORD exitCode = 0;
|
||||
STARTUPINFOW DUMMY = { sizeof(DUMMY) };
|
||||
PROCESS_INFORMATION processInfo = {};
|
||||
@ -93,7 +93,7 @@ namespace DevTools
|
||||
if (chromePath.isEmpty())
|
||||
{
|
||||
for (auto [_, process] : GetAllProcesses())
|
||||
if (process && process->find(L"\\chrome.exe") != std::string::npos) chromePath = S(process.value());
|
||||
if (process && (process->find(L"\\chrome.exe") != std::string::npos || process->find(L"\\msedge.exe") != std::string::npos)) chromePath = S(process.value());
|
||||
wchar_t programFiles[MAX_PATH + 100] = {};
|
||||
for (auto folder : { CSIDL_PROGRAM_FILESX86, CSIDL_PROGRAM_FILES, CSIDL_LOCAL_APPDATA })
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "module.h"
|
||||
#include "blockmarkup.h"
|
||||
#include <fstream>
|
||||
#include <process.h>
|
||||
|
||||
extern const wchar_t* REGEX_REPLACER_INSTRUCTIONS;
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
extern const char* LOAD_SCRIPT;
|
||||
|
||||
constexpr auto STYLE_SAVE_FILE = u8"Textractor.css";
|
||||
constexpr auto STYLE_SAVE_FILE = u8"Textractor.qss";
|
||||
|
||||
class Window : public QDialog, Localizer
|
||||
{
|
||||
@ -13,7 +13,8 @@ public:
|
||||
{
|
||||
connect(&loadButton, &QPushButton::clicked, this, &Window::LoadScript);
|
||||
|
||||
if (scriptEditor.toPlainText().isEmpty()) scriptEditor.setPlainText("/*https://doc.qt.io/qt-5/stylesheet-syntax.html*/");
|
||||
if (scriptEditor.toPlainText().isEmpty())
|
||||
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(&loadButton);
|
||||
|
||||
|
@ -18,6 +18,8 @@ extern const char* MAX_TRANSLATIONS_IN_TIMESPAN;
|
||||
extern const char* TIMESPAN;
|
||||
extern const char* MAX_SENTENCE_SIZE;
|
||||
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 char* TRANSLATION_PROVIDER;
|
||||
@ -34,7 +36,6 @@ namespace
|
||||
{
|
||||
Synchronized<TranslationParam> tlp;
|
||||
Synchronized<std::unordered_map<std::wstring, std::wstring>> translationCache;
|
||||
int savedSize = 0;
|
||||
|
||||
std::string CacheFile()
|
||||
{
|
||||
@ -46,7 +47,6 @@ namespace
|
||||
for (const auto& [sentence, translation] : translationCache.Acquire().contents)
|
||||
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));
|
||||
savedSize = translationCache->size();
|
||||
}
|
||||
void LoadCache()
|
||||
{
|
||||
@ -59,7 +59,6 @@ namespace
|
||||
auto& [sentence, translation] = read.value();
|
||||
translationCache->try_emplace(std::move(sentence), std::move(translation));
|
||||
}
|
||||
savedSize = translationCache->size();
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +140,7 @@ public:
|
||||
private:
|
||||
void SaveTranslateTo(QString language)
|
||||
{
|
||||
if (translationCache->size() > savedSize) SaveCache();
|
||||
SaveCache();
|
||||
settings.setValue(TRANSLATE_TO, S(tlp->translateTo = S(language)));
|
||||
LoadCache();
|
||||
}
|
||||
@ -153,7 +152,7 @@ private:
|
||||
|
||||
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||
{
|
||||
if (sentenceInfo["text number"] == 0 || sentence.size() > maxSentenceSize) return false;
|
||||
if (sentenceInfo["text number"] == 0) return false;
|
||||
|
||||
static class
|
||||
{
|
||||
@ -175,12 +174,6 @@ bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||
concurrency::concurrent_priority_queue<DWORD64, std::greater<DWORD64>> tokens;
|
||||
} 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;
|
||||
std::wstring translation;
|
||||
if (useFilter)
|
||||
@ -189,6 +182,7 @@ 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());
|
||||
}
|
||||
if (sentence.empty()) return true;
|
||||
if (sentence.size() > maxSentenceSize) translation = SENTENCE_TOO_LARGE_TO_TRANS;
|
||||
if (useCache)
|
||||
{
|
||||
auto translationCache = ::translationCache.Acquire();
|
||||
@ -197,12 +191,12 @@ bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||
if (translation.empty() && (!translateSelectedOnly || sentenceInfo["current select"]))
|
||||
if (rateLimiter.Request() || !useRateLimiter || (!rateLimitSelected && sentenceInfo["current select"])) std::tie(cache, translation) = Translate(sentence, tlp.Copy());
|
||||
else translation = TOO_MANY_TRANS_REQUESTS;
|
||||
if (useFilter) Trim(translation);
|
||||
if (cache) translationCache->try_emplace(sentence, translation);
|
||||
if (cache && translationCache->size() > savedSize + 50) SaveCache();
|
||||
if (cache) translationCache->operator[](sentence) = translation;
|
||||
|
||||
if (useFilter) Trim(translation);
|
||||
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()) (sentence += L"\x200b \n") += translation;
|
||||
if (translation.empty()) translation = TRANSLATION_ERROR;
|
||||
(sentence += L"\x200b \n") += translation;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -276,7 +276,9 @@ namespace HookCode
|
||||
{
|
||||
std::optional<HookParam> Parse(std::wstring code)
|
||||
{
|
||||
if (code[0] == L'/') code.erase(0, 1); // legacy/AGTH compatibility
|
||||
if (code[0] == L'/') code.erase(0, 1);
|
||||
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));
|
||||
else if (code[0] == L'H') return ParseHCode(code.erase(0, 1));
|
||||
return {};
|
||||
@ -292,6 +294,7 @@ namespace HookCode
|
||||
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 /KF")),
|
||||
assert(Parse(L"HB4@0")),
|
||||
assert(Parse(L"/RS65001#@44")),
|
||||
assert(Parse(L"HQ@4")),
|
||||
|
@ -88,7 +88,7 @@ void SpawnThread(const F& f) // works in DllMain unlike std thread
|
||||
}, copy, 0, nullptr));
|
||||
}
|
||||
|
||||
static struct // should be inline but MSVC (linker) is bugged
|
||||
inline struct
|
||||
{
|
||||
inline static BYTE DUMMY[100];
|
||||
template <typename T> operator T*() { static_assert(sizeof(T) < sizeof(DUMMY)); return (T*)DUMMY; }
|
||||
@ -120,6 +120,12 @@ inline std::wstring FormatString(const wchar_t* format, const Args&... args)
|
||||
}
|
||||
#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)
|
||||
{
|
||||
std::vector<wchar_t> buffer(text.size() + 1);
|
||||
|
118
text.cpp
118
text.cpp
@ -143,6 +143,7 @@ const char* RATE_LIMIT_SELECTED_THREAD = u8"Rate limit selected text thread";
|
||||
const char* USE_TRANS_CACHE = u8"Use translation cache";
|
||||
const char* MAX_TRANSLATIONS_IN_TIMESPAN = u8"Max translation requests in timespan";
|
||||
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* TRANSLATION_ERROR = L"Error while translating";
|
||||
const char* USE_PREV_SENTENCE_CONTEXT = u8"Use previous sentence as context";
|
||||
@ -353,28 +354,30 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
||||
SETTINGS = u8"设置";
|
||||
EXTENSIONS = u8"扩展";
|
||||
SELECT_PROCESS = u8"选择进程";
|
||||
ATTACH_INFO = u8R"(如果没看见想要附加的进程,尝试使用管理员权限运行
|
||||
ATTACH_INFO = u8R"(如果没看见想要附加的进程,请尝试使用管理员权限运行Textractor
|
||||
也可以手动输入进程ID)";
|
||||
SELECT_PROCESS_INFO = u8"如果手动输入游戏名,请使用绝对路径";
|
||||
FROM_COMPUTER = u8"从计算机中选择";
|
||||
PROCESSES = u8"进程 (*.exe)";
|
||||
FROM_COMPUTER = u8"从资源管理器中选择";
|
||||
PROCESSES = u8"可执行文件 (*.exe)";
|
||||
SAVE_SETTINGS = u8"保存设置";
|
||||
EXTEN_WINDOW_INSTRUCTIONS = u8R"(从计算机拖拽扩展 (.dll) 文件到这里来添加
|
||||
(如果使用超级管理员运行,则无法工作)
|
||||
在列表中拖拽来重新排序
|
||||
使用 delete 键移除选中的扩展)";
|
||||
EXTEN_WINDOW_INSTRUCTIONS = u8R"(在列表中单击右键以添加或移除扩展
|
||||
在列表中拖拽扩展可以调整插件的执行顺序, 扩展会从上往下依次执行
|
||||
排在下方的扩展只能接收到由排在上方的扩展处理过后的文本)";
|
||||
ADD_EXTENSION = u8"添加扩展";
|
||||
REMOVE_EXTENSION = u8"移除扩展";
|
||||
INVALID_EXTENSION = u8"%1 是一个无效扩展";
|
||||
CONFIRM_EXTENSION_OVERWRITE = u8"此扩展的另一个版本已启用,是否删除并覆盖它?";
|
||||
EXTENSION_WRITE_ERROR = u8"保存扩展失败";
|
||||
USE_JP_LOCALE = u8"模拟日本区域设置?";
|
||||
FAILED_TO_CREATE_CONFIG_FILE = u8"无法创建配置文件 \"%1\"";
|
||||
HOOK_SEARCH_UNSTABLE_WARNING = u8"搜索钩子的功能是不稳定的! 可能会导致你的游戏崩溃! ";
|
||||
HOOK_SEARCH_STARTING_VIEW_CONSOLE = u8"正在初始化钩子搜索 - 请查看控制台以获取更多提示";
|
||||
SEARCH_CJK = u8"搜索中文/日文/韩文";
|
||||
SEARCH_PATTERN = u8"搜索匹配特征 (hex byte array)";
|
||||
SEARCH_DURATION = u8"搜索持续时间 (ms)";
|
||||
SEARCH_MODULE = u8"搜索指定模块";
|
||||
PATTERN_OFFSET = u8"相对于特征地址的偏移值";
|
||||
MAX_HOOK_SEARCH_RECORDS = u8"搜索结果上限";
|
||||
MAX_HOOK_SEARCH_RECORDS = u8"搜索结果达到上限";
|
||||
MIN_ADDRESS = u8"起始地址 (hex)";
|
||||
MAX_ADDRESS = u8"结束地址 (hex)";
|
||||
STRING_OFFSET = u8"字符串偏移值 (hex)";
|
||||
@ -388,7 +391,7 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
||||
DOUBLE_CLICK_TO_REMOVE_HOOK = u8"双击移除不需要的钩子";
|
||||
FILTER_REPETITION = u8"过滤重复文本";
|
||||
AUTO_ATTACH = u8"自动附加";
|
||||
ATTACH_SAVED_ONLY = u8"自动附加 (saved only)";
|
||||
ATTACH_SAVED_ONLY = u8"自动附加 (仅限保存过配置的游戏)";
|
||||
SHOW_SYSTEM_PROCESSES = u8"显示系统进程";
|
||||
DEFAULT_CODEPAGE = u8"默认代码页";
|
||||
FLUSH_DELAY = u8"刷新延迟";
|
||||
@ -401,7 +404,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/blob/master/docs/TUTORIAL.md
|
||||
如果有任何关于 Textractor 的困难,功能请求或问题,请联系我
|
||||
可以通过项目主页 (问题区) 或通过邮件来联系
|
||||
可以通过项目主页 (Issues 页面) 或通过邮件来联系
|
||||
项目主页提供基于 GPLv3 协议的源代码)";
|
||||
UPDATE_AVAILABLE = L"有可用的更新: 请从 https://github.com/Artikash/Textractor/releases 下载";
|
||||
ALREADY_INJECTED = L"Textractor: 已经注入";
|
||||
@ -417,7 +420,8 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
||||
HOOK_FAILED = u8"Textractor: 钩子注入失败";
|
||||
TOO_MANY_HOOKS = u8"Textractor: 钩子数量已达上限: 无法注入";
|
||||
HOOK_SEARCH_STARTING = u8"Textractor: 开始搜索钩子";
|
||||
NOT_ENOUGH_TEXT = u8"Textractor: 没有足够的文本用来精确搜索";
|
||||
HOOK_SEARCH_INITIALIZING = u8"Textractor: 初始化钩子搜索 (%f%%)";
|
||||
NOT_ENOUGH_TEXT = u8"Textractor: 文本长度不足, 无法精确搜索";
|
||||
HOOK_SEARCH_INITIALIZED = u8"Textractor: 搜索初始化完成, 创建了 %zd 个钩子";
|
||||
MAKE_GAME_PROCESS_TEXT = u8"Textractor: 请点击游戏区域, 在接下来的 %d 秒内使游戏强制处理文本";
|
||||
HOOK_SEARCH_FINISHED = u8"Textractor: 钩子搜索完毕, 找到了 %d 条结果";
|
||||
@ -430,46 +434,65 @@ Clic y arrastra los bordes de la ventana para moverla, o en la esquina inferior
|
||||
HIJACK_ERROR = u8"Textractor: Hijack 错误";
|
||||
COULD_NOT_FIND = u8"Textractor: 无法找到文本";
|
||||
TRANSLATE_TO = u8"翻译为";
|
||||
TRANSLATE_FROM = u8"原文语言";
|
||||
FILTER_GARBAGE = u8"过滤无意义字符";
|
||||
TRANSLATE_SELECTED_THREAD_ONLY = u8"仅翻译当前选择的文本线程";
|
||||
RATE_LIMIT_ALL_THREADS = u8"限制所有文本线程的请求频率";
|
||||
RATE_LIMIT_SELECTED_THREAD = u8"限制当前选择线程的请求频率";
|
||||
RATE_LIMIT_ALL_THREADS = u8"限制请求频率";
|
||||
RATE_LIMIT_SELECTED_THREAD = u8"限制选中线程的请求频率";
|
||||
USE_TRANS_CACHE = u8"使用缓存的翻译结果";
|
||||
MAX_TRANSLATIONS_IN_TIMESPAN = u8"限流器令牌数";
|
||||
TIMESPAN = u8"限流器令牌重置时间 (ms)";
|
||||
TOO_MANY_TRANS_REQUESTS = L"太多翻译请求: 拒绝生成更多";
|
||||
MAX_TRANSLATIONS_IN_TIMESPAN = u8"单位时间内最大请求次数";
|
||||
TIMESPAN = u8"单位时间长度 (ms)";
|
||||
TOO_MANY_TRANS_REQUESTS = L"超出频率限制: 拒绝发出翻译请求";
|
||||
TRANSLATION_ERROR = L"翻译时出错";
|
||||
USE_PREV_SENTENCE_CONTEXT = u8"使用之前的句子作为上下文";
|
||||
API_KEY = u8"API key";
|
||||
EXTRA_WINDOW_INFO = u8R"(右键修改设置
|
||||
在窗口边缘点击并拖拽来移动,或在右下角点击并拖拽来调整大小)";
|
||||
CHROME_LOCATION = u8"Google Chrome 安装位置";
|
||||
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"最大文本长度";
|
||||
TOPMOST = u8"窗口总是置顶";
|
||||
DICTIONARY = u8"字典";
|
||||
SHOW_ORIGINAL = u8"显示原文";
|
||||
SHOW_ORIGINAL_INFO = u8R"(将不显示原文
|
||||
仅当此扩展置于翻译扩展之后使用时才有效)";
|
||||
OPACITY = u8"透明度";
|
||||
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"透明度";
|
||||
BG_COLOR = u8"背景颜色";
|
||||
TEXT_COLOR = u8"文本颜色";
|
||||
TEXT_OUTLINE = u8"文字边框";
|
||||
OUTLINE_COLOR = u8"边框颜色";
|
||||
OUTLINE_SIZE = u8"边框大小";
|
||||
OUTLINE_SIZE_INFO = u8"以像素为单位的大小(建议保持在字体大小的20%以下)";
|
||||
TEXT_OUTLINE = u8"文字描边";
|
||||
OUTLINE_COLOR = u8"文字描边颜色";
|
||||
OUTLINE_SIZE = u8"文字描边大小";
|
||||
OUTLINE_SIZE_INFO = u8"描边的单位为px (建议保持在字体大小的20%以下)";
|
||||
FONT = u8"字体";
|
||||
LUA_INTRO = u8R"(--[[
|
||||
ProcessSentence 是Textractor每接收到一句文本时都会调用的函数。
|
||||
参数 sentence: Textractor接收到的文本 (UTF-8)。
|
||||
参数 sentenceInfo: 用于保存文本相关信息的table。
|
||||
如果你返回一个字符串,文本将被转换为该字符串。
|
||||
如果返回 nil,该文本将不会被修改。
|
||||
此扩展使用了几个Lua解释器的副本用于保证线程安全。
|
||||
在ProcessSentence函数中对全局变量的修改可能不会生效。
|
||||
sentenceInfo有以下成员:
|
||||
"current select": 除非文本属于用户当前选择的文本线程,否则为0。
|
||||
"process id": 这句文本所属的进程id. 0 表示控制台与剪贴板线程。
|
||||
"text number": 当前选择的文本线程的id. 这是在创建文本线程时逐个递增的计数。 0 为控制台, 1 为剪贴板。
|
||||
ProcessSentence 是Textractor每接收到一句文本时都会调用的函数.
|
||||
参数 sentence: Textractor接收到的文本 (UTF-8), 数据类型为 string.
|
||||
参数 sentenceInfo: 用于保存文本相关信息的表, 数据类型为 tabel.
|
||||
|
||||
如果你返回一个字符串,文本将被转换为该字符串.
|
||||
如果返回 nil, 该文本将不会被修改.
|
||||
|
||||
此扩展使用了几个Lua解释器的副本用于保证线程安全.
|
||||
在 ProcessSentence 函数中对全局变量的修改可能不会生效.
|
||||
|
||||
sentenceInfo 表有以下关键字索引:
|
||||
current select: 除非文本属于用户当前选择的文本线程, 否则为0. 数据类型为 number.
|
||||
process id: 这句文本所属的进程ID. 0 表示控制台与剪贴板线程. 数据类型为 number.
|
||||
text number: 当前选择的文本线程的ID. 这是在创建文本线程时自动递增的计数器. 0 为控制台, 1 为剪贴板. 数据类型为 number.
|
||||
--]]
|
||||
|
||||
function ProcessSentence(sentence, sentenceInfo)
|
||||
--在此处添加你的代码...
|
||||
end)";
|
||||
@ -481,13 +504,28 @@ end)";
|
||||
REPLACER_INSTRUCTIONS = LR"(使用"Replace"扩展时会使用此文件
|
||||
替换指令必须遵循以下格式:
|
||||
|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"线程链接器";
|
||||
LINK = u8"链接";
|
||||
THREAD_LINK_FROM = u8"需要链接的线程id";
|
||||
THREAD_LINK_TO = u8"链接到的线程id";
|
||||
UNLINK = u8"断开";
|
||||
THREAD_LINK_FROM = u8"需要链接的线程ID";
|
||||
THREAD_LINK_TO = u8"链接到的线程ID";
|
||||
HEXADECIMAL = u8"十六进制";
|
||||
#endif // SIMPLIFIED_CHINESE
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
//#include <boost/foreach.hpp>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
// jichi 375/2014: Add offset of pusha/pushad
|
||||
// http://faydoc.tripod.com/cpu/pushad.htm
|
||||
@ -5730,21 +5731,21 @@ void SpecialHookShina2(DWORD esp_base, HookParam *, BYTE, DWORD *data, DWORD *sp
|
||||
// Used to merge correct text thread.
|
||||
// 1. Only keep threads with 0 and -1 split
|
||||
// 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)
|
||||
{
|
||||
static DWORD min_retaddr = -1;
|
||||
DWORD s = *(DWORD *)(esp_base + hp->split);
|
||||
if (s == 0 || (s & 0xffff) == 0xffff) { // only keep threads with 0 and -1 split
|
||||
if (s == 0 && retof(esp_base) <= min_retaddr) {
|
||||
min_retaddr = retof(esp_base);
|
||||
return;
|
||||
}
|
||||
*split = FIXED_SPLIT_VALUE;
|
||||
// Follow the same logic as the hook.
|
||||
*data = *(DWORD *)*data; // DATA_INDIRECT
|
||||
*len = LeadByteTable[*data & 0xff];
|
||||
}
|
||||
}
|
||||
//void SpecialHookShina1(DWORD esp_base, HookParam *hp, BYTE, DWORD *data, DWORD *split, DWORD *len)
|
||||
//{
|
||||
// static DWORD min_retaddr = -1;
|
||||
// DWORD s = *(DWORD *)(esp_base + hp->split);
|
||||
// if (s == 0 || (s & 0xffff) == 0xffff) { // only keep threads with 0 and -1 split
|
||||
// if (s == 0 && retof(esp_base) <= min_retaddr) {
|
||||
// min_retaddr = retof(esp_base);
|
||||
// return;
|
||||
// }
|
||||
// *split = FIXED_SPLIT_VALUE;
|
||||
// // Follow the same logic as the hook.
|
||||
// *data = *(DWORD *)*data; // DATA_INDIRECT
|
||||
// *len = LeadByteTable[*data & 0xff];
|
||||
// }
|
||||
//}
|
||||
|
||||
// jichi 8/27/2013
|
||||
// Return ShinaRio version number
|
||||
@ -5803,7 +5804,7 @@ bool InsertShinaHook()
|
||||
trigger_fun = [](LPVOID funcAddr, DWORD, DWORD stack)
|
||||
{
|
||||
bool ret = false;
|
||||
if (funcAddr != GetGlyphOutlineA) return false;
|
||||
if (funcAddr != GetGlyphOutlineA && funcAddr != GetTextExtentPoint32A) return false;
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
// Address of text is somewhere on stack in call to func. Search for it.
|
||||
@ -5817,7 +5818,7 @@ bool InsertShinaHook()
|
||||
hp.type = DIRECT_READ;
|
||||
hp.address = addr;
|
||||
ConsoleOutput("Textractor: triggered: adding dynamic reader");
|
||||
NewHook(hp, "READ");
|
||||
NewHook(hp, "ShinaRio READ");
|
||||
ret = true;
|
||||
}
|
||||
};
|
||||
@ -5825,9 +5826,8 @@ bool InsertShinaHook()
|
||||
return ret;
|
||||
};
|
||||
ConsoleOutput("Textractor: ShinaRio 2.50+: adding trigger");
|
||||
return true;
|
||||
}
|
||||
else if (ver >= 48) { // v2.48, v2.49
|
||||
if (ver >= 48) { // v2.48, v2.49
|
||||
HookParam hp = {};
|
||||
hp.address = (DWORD)::GetTextExtentPoint32A;
|
||||
hp.text_fun = SpecialHookShina2;
|
||||
@ -6007,9 +6007,9 @@ bool InsertWaffleHook()
|
||||
0x50, //50 push eax
|
||||
0x8b, 0xce, //8BCE mov ecx,esi
|
||||
0xc6, 0x45, 0xfc, XX, //C645 FC 01 move byte ptr ss:[ebp-4],?
|
||||
0x89, 0x75, 0xd4, //8975 D4 move dword ptr ss:[ebp-0x2c],esi
|
||||
0x89, 0x75, XX, //8975 D4 move dword ptr ss:[ebp-0x2c],esi
|
||||
0xe8, XX4, //E8 ?? call ??
|
||||
0x8d, 0x45, 0xdc //8D45 DC lea eax,dword ptr ss:[ebp-0x24]
|
||||
0x8d, 0x45, XX //8D45 DC lea eax,dword ptr ss:[ebp-0x24]
|
||||
};
|
||||
if (DWORD addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress))
|
||||
{
|
||||
@ -6352,9 +6352,267 @@ static bool InsertYuris2Hook()
|
||||
NewHook(hp, "YU-RIS2");
|
||||
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()
|
||||
{ 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()
|
||||
{
|
||||
@ -17002,7 +17260,7 @@ void InsertMonoHook(HMODULE h)
|
||||
if (!getDomain || !getName || !getJitInfo) goto failed;
|
||||
static auto domain = getDomain();
|
||||
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 };
|
||||
for (auto addr : Util::SearchMemory(prolog, sizeof(prolog), PAGE_EXECUTE_READWRITE))
|
||||
{
|
||||
@ -17017,7 +17275,7 @@ void InsertMonoHook(HMODULE h)
|
||||
HookParam hp = {};
|
||||
hp.address = addr;
|
||||
hp.type = USING_UNICODE | FULL_STRING;
|
||||
if (!loadedConfig) hp.type |= KNOWN_UNSTABLE;
|
||||
if (!*loadedConfig) hp.type |= KNOWN_UNSTABLE;
|
||||
hp.offset = 4;
|
||||
char nameForUser[HOOK_NAME_SIZE] = {};
|
||||
strncpy_s(nameForUser, name + 1, HOOK_NAME_SIZE - 1);
|
||||
@ -17035,7 +17293,7 @@ void InsertMonoHook(HMODULE h)
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {}
|
||||
}(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;
|
||||
failed:
|
||||
ConsoleOutput("Textractor: Mono Dynamic failed");
|
||||
@ -17092,7 +17350,7 @@ bool InsertMonoHooks()
|
||||
if (FARPROC addr = ::GetProcAddress(h, func.functionName)) {
|
||||
hp.address = (DWORD)addr;
|
||||
hp.type = func.hookType;
|
||||
if (loadedConfig) hp.type |= HOOK_EMPTY;
|
||||
if (*loadedConfig) hp.type |= HOOK_EMPTY;
|
||||
hp.filter_fun = NoAsciiFilter;
|
||||
hp.offset = func.textIndex * 4;
|
||||
hp.length_offset = func.lengthIndex * 4;
|
||||
@ -21027,6 +21285,84 @@ bool InsertTecmoPSPHook()
|
||||
}
|
||||
#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
|
||||
* Tested wit pcsx2-v1.2.1-328-gef0e3fe-windows-x86, built at http://buildbot.orphis.net/pcsx2
|
||||
*/
|
||||
@ -21262,7 +21598,6 @@ bool InsertTypeMoonPS2Hook()
|
||||
ConsoleOutput("vnreng: TypeMoon PS2: leave");
|
||||
return addr;
|
||||
}
|
||||
|
||||
/** 8/3/2014 jichi
|
||||
* Tested game: School Rumble ねる娘<EFBFBD>育つ
|
||||
*
|
||||
|
@ -14,7 +14,7 @@ namespace Engine {
|
||||
// Global variables
|
||||
extern wchar_t *processName, // cached
|
||||
processPath[MAX_PATH]; // cached
|
||||
inline const char *requestedEngine = nullptr, *loadedConfig = nullptr;
|
||||
inline const char *requestedEngine = "", * loadedConfig = "";
|
||||
|
||||
bool InsertMonoHooks(); // Mono
|
||||
|
||||
@ -96,6 +96,7 @@ bool InsertCandyHook(); // SystemC@CandySoft: *.fpk
|
||||
bool InsertCatSystemHook(); // CatSystem2: *.int
|
||||
bool InsertCMVSHook(); // CMVS: data/pack/*.cpz; do not support the latest cmvs32.exe and cmvs64.exe
|
||||
bool InsertCotophaHook(); // Cotopha: *.noa
|
||||
bool InsertDACHook(); // DAC
|
||||
bool InsertDebonosuHook(); // Debonosu: bmp.bak and dsetup.dll
|
||||
bool InsertEaglsHook(); // E.A.G.L.S: EAGLES.dll
|
||||
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))
|
||||
{
|
||||
ReadFile(configFile, configFileData, sizeof(configFileData) - 1, DUMMY, nullptr);
|
||||
if (strncmp(configFileData, "Engine:", 7) == 0)
|
||||
if (strnicmp(configFileData, "engine:", 7) == 0)
|
||||
{
|
||||
if (loadedConfig = strchr(configFileData, '\n')) *(char*)loadedConfig++ = 0;
|
||||
ConsoleOutput("Textractor: Engine = %s", requestedEngine = configFileData + 7);
|
||||
if (const char* config = strchr(configFileData, '\n')) *(char*)(loadedConfig = config)++ = 0;
|
||||
ConsoleOutput("Textractor: Engine = %s", requestedEngine = strlwr(configFileData + 7));
|
||||
}
|
||||
else loadedConfig = configFileData;
|
||||
if ((loadedConfig && !*loadedConfig) || strstr(configFileData, "https://")) loadedConfig = nullptr;
|
||||
if (!*loadedConfig || strstr(configFileData, "https://")) loadedConfig = "";
|
||||
else ConsoleOutput("Textractor: game configuration loaded");
|
||||
}
|
||||
|
||||
@ -67,14 +67,14 @@ namespace Engine
|
||||
spDefault.maxAddress = processStopAddress;
|
||||
ConsoleOutput("Textractor: hijacking process located from 0x%p to 0x%p", processStartAddress, processStopAddress);
|
||||
|
||||
DetermineEngineType();
|
||||
if (!strstr(requestedEngine, "none")) DetermineEngineType();
|
||||
if (processStartAddress + 0x40000 > processStopAddress) ConsoleOutput("Textractor: WARNING injected process is very small, possibly a dummy!");
|
||||
}(), 0);
|
||||
}
|
||||
|
||||
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 (auto start = name; *start; ++start)
|
||||
for (int i = 0; ; ++i)
|
||||
|
@ -54,6 +54,11 @@ bool DeterminePCEngine()
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Util::CheckFile(L"script.dpk")) {
|
||||
InsertDACHook();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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")) {
|
||||
// ConsoleOutput("vnreng: IGNORE BALDRSKY ZEROs");
|
||||
@ -629,10 +634,9 @@ bool DetermineEngineAtLast()
|
||||
}
|
||||
if (Util::CheckFile(L"MovieTexture.dll") && (InsertPensilHook() || Insert2RMHook())) // MovieTexture.dll also exists in 2RM games such as 母子愛2体験版, which is checked first
|
||||
return true;
|
||||
if ((Util::CheckFile(L"system") && Util::CheckFile(L"system.dat")) || Util::CheckFile(L"*01")) { // jichi 7/31/2015 & Artikash 6/15/2018
|
||||
InsertAbelHook();
|
||||
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 (InsertAbelHook())
|
||||
return true;
|
||||
if (Util::CheckFile(L"data\\*.cpk")) { // jichi 12/2/2014
|
||||
Insert5pbHook();
|
||||
return true;
|
||||
|
@ -80,7 +80,7 @@ namespace Engine
|
||||
if (!getDomain || !getName || !getJitInfo) goto failed;
|
||||
static auto domain = getDomain();
|
||||
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 prolog2[] = { 0x48, 0x83, 0xec };
|
||||
for (auto [prolog, size] : Array<const BYTE*, size_t>{ { prolog1, sizeof(prolog1) }, { prolog2, sizeof(prolog2) } })
|
||||
@ -97,7 +97,7 @@ namespace Engine
|
||||
HookParam hp = {};
|
||||
hp.address = addr;
|
||||
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.padding = 20;
|
||||
char nameForUser[HOOK_NAME_SIZE] = {};
|
||||
@ -119,7 +119,7 @@ namespace Engine
|
||||
}(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;
|
||||
failed:
|
||||
ConsoleOutput("Textractor: Mono Dynamic failed");
|
||||
|
@ -193,6 +193,7 @@ void TextHook::Send(uintptr_t dwDataBase)
|
||||
|
||||
TextOutput(tp, buffer, count);
|
||||
#endif // _WIN64
|
||||
++*pbData;
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user