5 Commits

Author SHA1 Message Date
80aad703a0 根据 hash 寻找启动文件,启动前校验 system.arc 以确保是正确的游戏 2025-05-11 16:25:13 +08:00
a766ed930c Add more config settings 2025-03-25 14:38:06 +08:00
72163929a7 Fix 2025-03-21 13:03:56 +08:00
f7e25fb4fe Fix option 2025-03-21 12:42:41 +08:00
c50a56d76c Add more options 2025-03-21 12:21:00 +08:00
6 changed files with 95 additions and 9 deletions

View File

@@ -10,6 +10,11 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
option(USE_LIBMPV "Use libmpv." ON)
option(USE_PLAYER "Use player." OFF)
option(STATIC_CRT "Use static CRT" ON)
if (STATIC_CRT)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
if (USE_LIBMPV AND USE_PLAYER)
message(FATAL_ERROR "USE_LIBMPV and USE_PLAYER cannot be both enabled.")
@@ -66,3 +71,4 @@ target_link_libraries(jewena_patch utils)
target_link_libraries(jewena_patch zip)
add_executable(jewena-chs WIN32 main.cpp winres.rc jewena-chs.exe.manifest)
target_link_libraries(jewena-chs utils)

View File

@@ -42,6 +42,16 @@ bool Config::Load(std::string path) {
}
std::string key = l.substr(0, eq_pos);
std::string value = l.substr(eq_pos + 1);
#if HAVE_MPV
if (key.find("mpv-") == 0) {
key = key.substr(4);
if (str_util::tolower(key) == "wid") {
continue;
}
mpv.push_back(std::make_pair(key, value));
continue;
}
#endif
configs[key] = value;
}
free_file_reader(reader);
@@ -49,6 +59,8 @@ bool Config::Load(std::string path) {
return true;
}
#if HAVE_PLAYER
bool Config::IsAppendLogging() {
auto re = configs.find("appendLogging");
if (re == configs.end()) {
@@ -99,3 +111,5 @@ uint32_t Config::VideoBuffer() {
}
return std::stoul((*re).second);
}
#endif

View File

@@ -1,21 +1,31 @@
#include <unordered_map>
#include <string>
#include <list>
#include <utility>
#include "patch_config.h"
class Config {
public:
std::unordered_map<std::string, std::string> configs;
#if HAVE_MPV
std::list<std::pair<std::string, std::string>> mpv;
#endif
Config() {
configs["defaultFont"] = "微软雅黑";
configs["stringReplaceFile"] = "";
#if HAVE_PLAYER
configs["appendLogging"] = "false";
configs["loggingFile"] = "";
configs["loggingLevel"] = "info";
configs["audioBuffer"] = "0";
configs["videoBuffer"] = "0";
#endif
}
bool Load(std::string path);
#if HAVE_PLAYER
bool IsAppendLogging();
int LoggingLevel();
uint32_t AudioBuffer();
uint32_t VideoBuffer();
#endif
};

View File

@@ -202,10 +202,8 @@ int64_t HookedOpenMediaFileAndGetDuration(DWORD* duration, const char* arcName,
mpv_set_option_string(player, "input-default-bindings", "no");
mpv_set_option_string(player, "hwdec", "auto");
mpv_set_option_string(player, "auto-window-resize", "no");
mpv_set_option_string(player, "fullscreen", "no");
auto loggingFile = config.configs["loggingFile"];
if (!loggingFile.empty()) {
mpv_set_option_string(player, "log-file", loggingFile.c_str());
for (auto& i : config.mpv) {
mpv_set_option_string(player, i.first.c_str(), i.second.c_str());
}
const char* cmd[] = { "loadfile", videoName, nullptr };
err = mpv_command(player, cmd);
@@ -237,9 +235,9 @@ int64_t HookedOpenMediaFileAndGetDuration(DWORD* duration, const char* arcName,
Sleep(10);
}
int64_t dur = 0;
mpv_get_property(player, "duration", MPV_FORMAT_INT64, &dur);
mpv_get_property(player, "duration/full", MPV_FORMAT_INT64, &dur);
if (duration) {
*duration = dur / 1000;
*duration = dur;
}
return 1;
}

View File

@@ -1,5 +1,53 @@
#include <windows.h>
#include <stdio.h>
#include "hash_lib.h"
#include "wchar_util.h"
#include "str_util.h"
using namespace hash_lib;
static std::string dir;
std::wstring FindStartProcess() {
wchar_t path[MAX_PATH];
if (GetModuleFileNameW(NULL, path, MAX_PATH) == 0) {
return L"";
}
std::string tPath;
if (!wchar_util::wstr_to_str(tPath, path, CP_UTF8)) {
return L"";
}
dir = fileop::dirname(tPath);
dir = str_util::str_replace(dir, "/", "\\");
std::string name = fileop::join(dir, "*.exe");
std::wstring wName;
if (!wchar_util::str_to_wstr(wName, name, CP_UTF8)) {
return L"";
}
WIN32_FIND_DATAW data;
auto re = FindFirstFileW(wName.c_str(), &data);
if (re == INVALID_HANDLE_VALUE) {
return L"";
}
do {
std::string tmp;
if (!wchar_util::wstr_to_str(tmp, data.cFileName, CP_UTF8)) {
FindClose(re);
return L"";
}
if (hashHexFile<SHA512>(tmp) == "01bb9a1b072faa2e10e5489c624eb3b65a7304fd1e32f9015779c341102439e3ec229aa9cb4e1c1fe76e42803320a9c68cbf62cfaa8b145ac7f1481eb37185dc") {
FindClose(re);
return data.cFileName;
}
BOOL r = FindNextFileW(re, &data);
if (!r) {
FindClose(re);
if (GetLastError() == ERROR_NO_MORE_FILES) break;
return L"";
}
} while (1);
return L"";
}
void ShowErrorMsg(LPCWSTR text) {
wchar_t* buf[1024];
@@ -9,7 +57,7 @@ void ShowErrorMsg(LPCWSTR text) {
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// 要启动的进程名
const wchar_t* processName = L"jewena.exe";
auto processName = FindStartProcess();
// 要注入的 DLL 路径
const wchar_t* dllPath = L"jewena_patch.dll";
@@ -21,8 +69,18 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
si.cb = sizeof(si);
if (processName.empty()) {
MessageBoxW(nullptr, L"无法找到游戏的启动文件。", L"错误", MB_ICONERROR);
return 1;
}
if (hashHexFile<SHA512>(fileop::join(dir, "system.arc")) != "c69925d1016d1a4b327193bf97c6ac5d1940da0a5c5c28bd693d5655c33a6e0ea7c85e5fa057b98d9dde885f8bca320dee3e46f8b79913dc7a03cebddd1ac771") {
MessageBoxW(nullptr, L"system.arc 校验失败。请检查游戏是否正确。", L"错误", MB_ICONERROR);
return 1;
}
// 创建新进程
if (!CreateProcessW((LPCWSTR)processName, nullptr, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
if (!CreateProcessW(processName.c_str(), nullptr, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
ShowErrorMsg(L"CreateProcessW failed: ");
return 1;
}

2
utils

Submodule utils updated: 252c20d068...eeeedae697