49 Commits

Author SHA1 Message Date
55324bb5a8 v3.0.12 2023-12-27 00:40:43 +02:00
211f40ae53 SR 1.6.0: mark unverified 2023-12-27 00:37:12 +02:00
deddf93d3f SR 1.6.0: bump game version 2023-12-25 16:18:10 +02:00
c37d0e92f4 SR 1.6.0: updated checksums, patch address 2023-12-25 16:16:08 +02:00
fa3a3aa9cc Marked 3rd cn v7.2.0 as verified 2023-12-23 18:55:30 +02:00
186471508f Documented Wine 8.21+ fixing video playback 2023-12-23 18:54:41 +02:00
1f0a6bc016 Mark SR v1.5.0 as verified 2023-12-17 15:39:05 +02:00
da08b565f8 Mark 3rd glb/sea/tw/kr/jp v7.1.0 as verified 2023-12-08 00:10:05 +02:00
ead6489e63 Minor file structure reorganization 2023-11-16 22:58:31 +02:00
19d6139e13 v3.0.11 2023-11-15 18:50:56 +02:00
0047d7b64f Marked SR 1.5.0 as concerning 2023-11-13 23:08:53 +02:00
264cdc2528 Documentation update 2023-11-13 22:18:26 +02:00
ab4615dfe9 SR 1.5.0: updated checksums, patch address 2023-11-13 22:13:43 +02:00
cf34ac6e01 Mark 3rd cn v7.1.0 verified 2023-11-09 16:23:48 +02:00
6c7bbabced v3.0.10 2023-10-27 08:26:18 +03:00
81ddaeeda7 Marked 3rd 7.0.0 as verified 2023-10-27 08:25:58 +03:00
b9cae22212 Removed section name workaround for 3rd 2023-10-27 08:23:50 +03:00
8201e29e26 Remove misleading remark in readme 2023-10-11 17:55:48 +00:00
71144b4cd1 Mark HSR v1.4.0 as verified 2023-10-11 17:54:44 +00:00
5af8d2463a Set v3.0.9 in metadata.json 2023-10-10 22:02:36 +00:00
ea1d2f91f2 v3.0.9 2023-10-11 00:14:36 +03:00
f0ed718cf3 Document HSR 1.4.0 support 2023-10-09 19:27:24 +03:00
bc09349b8e Update checksums for HSR 1.4.0 2023-10-09 19:22:07 +03:00
66e51c6d9a Mark HI3 cn v7.0.0 verified 2023-10-01 11:04:01 +03:00
bc7b24f4d9 v3.0.8 2023-09-26 12:06:52 +03:00
9b55d4f160 Document HI3 forward compatibility 2023-09-26 12:06:24 +03:00
57b2423a8a Implement a better workaround for different HI3 editions having different section names 2023-09-26 12:05:53 +03:00
e96bf23a30 Document unexpected lack of change in HI3 v6.9.0 2023-09-15 23:18:02 +03:00
9296e00edd Document mfplat fix being unavailable 2023-09-11 19:30:52 +00:00
d22ded3d27 v3.0.7 2023-08-30 01:06:26 +03:00
15c403b0d1 Improve invalid checksum error message 2023-08-30 01:05:53 +03:00
1cc16ecbd9 Document HSR 1.3.0 support 2023-08-28 18:21:13 +03:00
ffe75e9de7 Update checksums to HSR 1.3.0 2023-08-28 18:19:36 +03:00
243e39d04b Optimized memory allocation in core 2023-08-26 21:24:56 +03:00
daa5585527 Update game version list in the readme 2023-08-17 23:11:46 +03:00
8bf5aac0ec v3.0.6 2023-08-17 22:57:32 +03:00
4c7dd302d5 Merged workaround for 3rd 2023-08-17 22:55:26 +03:00
63eed9d796 Handle missing txs section 2023-08-17 22:53:12 +03:00
671f9ba246 Add temporary workaround for 3rd 6.9.0 2023-08-17 22:51:43 +03:00
868b4e27be Reference 6.9.0 issue in readme 2023-08-17 18:23:54 +00:00
56eefd83d7 Mark 3rd cn 6.9.0 as broken 2023-08-17 19:10:52 +03:00
3b2d33ad24 v3.0.5 2023-08-12 17:22:34 +03:00
ba6a054ec3 Show executable path in failed to start game process messagebox 2023-08-12 17:20:58 +03:00
7693e63619 Update core.md 2023-08-12 17:16:05 +03:00
5d5d2117ec 3.0.4 2023-08-12 02:32:20 +03:00
ca65bbd70c Reformat invalid checksum messagebox 2023-08-12 02:29:27 +03:00
c17cf00409 Move LoadLibrary call into core 2023-08-12 02:16:19 +03:00
c80635fc71 Adapted utils_create_dir_recursively to general project style 2023-08-10 01:15:53 +03:00
e9d2130105 Minor game detect refactoring 2023-08-10 01:00:24 +03:00
14 changed files with 72 additions and 61 deletions

View File

@ -1,14 +1,12 @@
### Games and regions
- **3rd**: glb/sea/cn/tw/kr/jp **v6.8.0+**
- **SR**: os/cn **v1.2.0** (potentially unsafe, but no bans were reported since v1.1.0)
- **3rd**: glb/sea/tw/kr/jp **v7.1.0+**, cn **v7.2.0+**
- **SR**: os/cn **v1.6.0** (potentially unsafe, but no bans were reported since v1.1.0)
**You can expect newer versions of 3rd to work immediately after release with the same jadeite binary.** However, that is not the case for SR: you will have to update your jadeite binary to run newer versions.
You can expect newer versions to work immediately after release with the same jadeite binary if the version is specified with a + above.
### Information
The anticheat the games use is fundamentally incompatible with Wine in multiple ways. This tool launches the game without it (`injector`) and imitates it's behaviour (`game_payload`).
**SR-specific**: this tool disables the use of DirectX shared resources in a rather hacky way. It is required, as there is no (and most likely never will be) shared resources support in DirectX translation layers (WineD3D/DXVK). Refer to [configuration](#configuration) if you wish to run the game without the fix.
**Using third-party software (such as this tool) with the games violates their Terms of Service**. Therefore, **you may receive a ban**. No bans were ever reported with 3rd, however the legacy patch for SR did cause many. **Use at your own risk and only if you understand all the possible consequences**.
**This is not a cheating tool**. Using it with Windows is not possible, and Windows support is not planned or intended in any way. However, as it does not perform any on-disk file modifications, you may reuse the same game install for Windows if you have a dual-boot setup.
@ -18,7 +16,9 @@ The anticheat the games use is fundamentally incompatible with Wine in multiple
**Wine 8.0+ is recommended**, as lower versions leak "The Wine project" as the device identifier. Not critical, but taking a precaution never hurt anyone. **DXVK is strongly recommended.**
**3rd-specific**: In some cases, and if you're not using Proton GE, **a fix for Media Foundation may be required to play videos. The Game may crash without it.** You can download it from [here](https://github.com/z0z0z/mf-install). You might need to [limit the number of cores available to the game](https://github.com/z0z0z/mf-install/issues/44) if your CPU has more than 8. **IMPORTANT: do not run the mfplat fix under Proton GE. Doing so may irreparably damage your game installation!**
**3rd-specific**:
- **Wine 8.21+ or [Wine-GE-Proton](https://github.com/GloriousEggroll/wine-ge-custom) is required to play videos. The game may show a black screen or crash on lower versions.**
- You might need to [limit the number of cores available to the game](https://github.com/z0z0z/mf-install/issues/44) if your CPU has more than 8.
Manual usage instructions:
- Download the game you want to run
@ -36,9 +36,6 @@ These environment variables can be used to configure the behaviour of the tool.
- `WAIT_BEFORE_RESUME=1` - show a messagebox and wait for user input before resuming the game process. Useful on my side for debugging
**SR-exclusive**:
- `SRFIX_DISABLE=1` - disable shared resources fix. Not recommended. Doing so will most likely cause the game to not run at all
### Internals
This tool consists of three parts: the main injector (`injector/src/exe.c`), the launcher payload (`injector/src/dll.c`) and the game payload (`game_payload`).

Binary file not shown.

View File

@ -2,10 +2,12 @@
#include <stdint.h>
#define UTILS_COUNT(arr) (sizeof(arr) / sizeof(*arr))
int utils_path_exists(const wchar_t *filePath);
uint32_t utils_file_crc32c(const wchar_t *filePath);
void utils_create_dir_recursively(const wchar_t *path);
void utils_create_parent_dirs(const wchar_t *path);
void utils_save_to_file(const wchar_t *filePath, const void *buf, size_t length);

View File

@ -9,11 +9,13 @@ sources = [
'src/ace.c',
'src/pe.c',
'src/game.c',
'src/hi3.c',
'src/hsr.c',
'src/utils.c',
'src/msg.c',
'src/tx.c'
'src/tx.c',
'src/hi3/hi3.c',
'src/hsr/hsr.c'
]
if fs.exists('src/core.c')

View File

@ -23,6 +23,9 @@
### 3.0.1
- Fixed a bug that caused HI3 to crash
### branch/master
### 3.0.2
- Fixed multiple error messageboxes showing invalid characters
- Added handling for more error conditions
### 3.0.4
- Moved LoadLibrary call into core from main

View File

@ -1,32 +1,39 @@
#include <msg.h>
#include <utils.h>
#include <game.h>
typedef void (*fill_fn)(struct game_data *buf);
struct name_fn_pair {
const char *name;
const wchar_t *name;
fill_fn fill;
};
const struct name_fn_pair GAMES[] = {
{ "bh3.exe", &hi3_fill_data },
{ "starrail.exe", &hsr_fill_data }
{ L"BH3", &hi3_fill_data },
{ L"StarRail", &hsr_fill_data }
};
void game_detect(struct game_data *buf) {
char exePath[MAX_PATH];
GetModuleFileNameA(NULL, exePath, MAX_PATH);
wchar_t exePath[MAX_PATH];
GetModuleFileNameW(NULL, exePath, MAX_PATH);
char *exeName = strrchr(exePath, '\\') + 1;
strlwr(exeName);
// Leave only the basename
wchar_t *exeName = wcsrchr(exePath, L'\\') + 1;
for (size_t i = 0; i < sizeof(GAMES) / sizeof(struct name_fn_pair); i++) {
if (strcmp(exeName, GAMES[i].name) == 0) {
// Cut off extension (.exe)
wchar_t *extensionDot = wcsrchr(exeName, L'.');
if (extensionDot != NULL) {
*extensionDot = L'\0';
}
for (size_t i = 0; i < UTILS_COUNT(GAMES); i++) {
if (wcsicmp(exeName, GAMES[i].name) == 0) {
GAMES[i].fill(buf);
return;
}
}
msg_err_a("Unknown game: %s", exeName);
msg_err_w(L"Unknown game: %ls", exeName);
}

View File

@ -1,11 +1,13 @@
#include <utils.h>
#include <msg.h>
#include <pe.h>
#include <main.h>
#include <game.h>
const char *HI3_BASE_MODULE_NAME = "BH3Base.dll";
const char *HI3_ASSEMBLY_PATH = "BH3_Data\\Native\\UserAssembly.dll";
const char *HI3_TXS_SECTION_NAME = ".bh3";
const char *HI3_TXS_SECTION_NAME = ".ace";
const char *HI3_TVM_SECTION_NAME = ".tvm0";

View File

@ -9,6 +9,8 @@ const char *HSR_ASSEMBLY_PATH = "GameAssembly.dll";
const char *HSR_TXS_SECTION_NAME = ".ace";
const char *HSR_TVM_SECTION_NAME = ".tvm0";
#define HSR_VERSION "1.6.0"
enum hsr_region {
HSR_INVALID,
HSR_OS,
@ -21,15 +23,15 @@ struct crc_region_pair {
};
const struct crc_region_pair HSR_REGIONS[] = {
{ 0x9eb3084e, HSR_OS }, // os v1.2.0
{ 0x14be07e9, HSR_CN } // cn v1.2.0
{ 0x5741ce50, HSR_OS }, // os v1.6.0
{ 0xce891f97, HSR_CN } // cn v1.6.0
};
#define JUMP_SIZE (6 + sizeof(void*))
// Temporarily hardcoded offset
// v1.2.0, same for os and cn
#define WTSUD_PATCH_OFFSET 0x16430
// v1.6.0, same for os and cn
#define WTSUD_PATCH_OFFSET 0x16510
char wtsud_original_bytes[JUMP_SIZE];
char *wtsud_patch_addr;
@ -47,12 +49,12 @@ static void _wtsud_stub() {
}
static void _unityplayer_callback(HMODULE unityModule) {
if (utils_env_enabled("SRFIX_DISABLE")) {
msg_info_a("Shared resources fix disabled. The game may not work");
if (utils_env_enabled("CHECKSUM_PATCH_DISABLE")) {
msg_info_a("DirectX library verification patch disabled. The game will not work");
return;
}
// Remove dependency on shared resources by patching WriteTextureStatisticUserData
// Remove check by patching WriteTextureStatisticUserData
unload_ctr_inc();
wtsud_patch_addr = ((char*)unityModule) + WTSUD_PATCH_OFFSET;
@ -78,14 +80,15 @@ void hsr_fill_data(struct game_data *buf) {
uint32_t crc = utils_file_crc32c(L"UnityPlayer.dll");
enum hsr_region id = HSR_INVALID;
for (size_t i = 0; i < sizeof(HSR_REGIONS) / sizeof(struct crc_region_pair); i++) {
for (size_t i = 0; i < UTILS_COUNT(HSR_REGIONS); i++) {
if (HSR_REGIONS[i].crc == crc) {
id = HSR_REGIONS[i].id;
break;
}
}
if (id == HSR_INVALID) {
msg_err_a("Invalid UnityPlayer.dll checksum: %x", crc);
msg_err_a("Invalid UnityPlayer.dll checksum: 0x%08x. This patch is intended to be used with HSR v" HSR_VERSION, crc);
}
buf->base_module_name = HSR_BASE_MODULE_NAME;

View File

@ -51,18 +51,12 @@ static void _run_game(struct game_data *game, wchar_t *txFile) {
}
static void _run_tx(struct game_data *game, wchar_t *txFile) {
// Load unpatched base module
HMODULE baseModule = LoadLibraryA(game->base_module_name);
if (!baseModule) {
msg_err_a("Failed to load base module: %s", game->base_module_name);
}
// ...more magic
size_t tableSize;
void *table = core_perform_tx(game, &tableSize);
// Save to file
utils_create_dir_recursively(txFile);
utils_create_parent_dirs(txFile);
utils_save_to_file(txFile, table, tableSize);
// Cleanup

View File

@ -28,6 +28,10 @@ void tx_table_file(struct game_data *game, wchar_t *buf) {
// Checksum the TXS section
IMAGE_SECTION_HEADER *txsSection = pe_find_section(baseMap, game->txs_section_name);
if (!txsSection) {
msg_err_a("Could not find %s in %s. " ISSUE_SUFFIX, game->txs_section_name, game->base_module_name);
}
uint32_t txsChecksum = crc32c(0, baseMap + txsSection->PointerToRawData, txsSection->SizeOfRawData);
// Format the path

View File

@ -34,21 +34,18 @@ uint32_t utils_file_crc32c(const wchar_t *filePath) {
}
// https://stackoverflow.com/a/16719260
void utils_create_dir_recursively(const wchar_t *path) {
void utils_create_parent_dirs(const wchar_t *path) {
wchar_t dir[MAX_PATH];
ZeroMemory(dir, MAX_PATH * sizeof(wchar_t));
ZeroMemory(dir, sizeof(dir));
wchar_t *end = wcschr(path, L'\\');
const wchar_t *end = path - 1;
while(end != NULL)
{
while((end = wcschr(++end, L'\\')) != NULL) {
wcsncpy(dir, path, end - path + 1);
if (!utils_path_exists(dir) && !CreateDirectoryW(dir, NULL)) {
msg_err_w(L"Failed to create directory: %ls", dir);
}
end = wcschr(++end, L'\\');
}
}

View File

@ -88,7 +88,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
&pi
)) {
wchar_t message[1024];
wsprintfW(message, L"Failed to start game process: %ld", GetLastError());
wsprintfW(message, L"Failed to start game process: %ld\nGame executable path: '%ls'", GetLastError(), targetExe);
MessageBoxW(NULL, message, J_MB_TITLE, MB_OK | MB_ICONERROR);
exit(1);

View File

@ -1,4 +1,4 @@
project('jadeite', 'c', version: '3.0.3')
project('jadeite', 'c', version: '3.0.12')
nasm = find_program('nasm')
gen_res = find_program('gen_resources.sh')

View File

@ -1,42 +1,42 @@
{
"jadeite": {
"version": "3.0.3"
"version": "3.0.12"
},
"games": {
"hi3rd": {
"global": {
"status": "verified",
"version": "6.8.0"
"version": "7.1.0"
},
"sea": {
"status": "verified",
"version": "6.8.0"
"version": "7.1.0"
},
"china": {
"status": "verified",
"version": "6.8.0"
"version": "7.2.0"
},
"taiwan": {
"status": "verified",
"version": "6.8.0"
"version": "7.1.0"
},
"korea": {
"status": "verified",
"version": "6.8.0"
"version": "7.1.0"
},
"japan": {
"status": "verified",
"version": "6.8.0"
"version": "7.1.0"
}
},
"hsr": {
"global": {
"status": "verified",
"version": "1.2.0"
"status": "unverified",
"version": "1.6.0"
},
"china": {
"status": "verified",
"version": "1.2.0"
"status": "unverified",
"version": "1.6.0"
}
}
}