95 lines
2.7 KiB
C
95 lines
2.7 KiB
C
#include <utils.h>
|
|
#include <msg.h>
|
|
#include <main.h>
|
|
|
|
#include <game.h>
|
|
|
|
const char *HSR_NAME = "StarRail";
|
|
const char *HSR_ASSEMBLY_NAME = "GameAssembly.dll";
|
|
const char *HSR_TP6_SECTION_NAME = ".ace";
|
|
const char *HSR_TVM_SECTION_NAME = ".tvm0";
|
|
|
|
struct crc_id_pair {
|
|
uint32_t crc;
|
|
enum game_id id;
|
|
};
|
|
|
|
const struct crc_id_pair HSR_REGIONS[] = {
|
|
// It may be possible to get rid of region-specific data altogether in the future
|
|
|
|
{ 0x9eb3084e, GAME_HSR_OS }, // os v1.2.0
|
|
{ 0x14be07e9, GAME_HSR_CN } // cn v1.2.0
|
|
};
|
|
|
|
#define JUMP_SIZE (6 + sizeof(void*))
|
|
|
|
// Temporarily hardcoded offset
|
|
// v1.2.0, same for os and cn
|
|
#define WTSUD_PATCH_OFFSET 0x16430
|
|
|
|
char wtsud_original_bytes[JUMP_SIZE];
|
|
char *wtsud_patch_addr;
|
|
|
|
static void _wtsud_stub() {
|
|
// Recover original bytes
|
|
DWORD oldProtect;
|
|
VirtualProtect(wtsud_patch_addr, JUMP_SIZE, PAGE_EXECUTE_READWRITE, &oldProtect);
|
|
|
|
memcpy(wtsud_patch_addr, wtsud_original_bytes, JUMP_SIZE);
|
|
|
|
VirtualProtect(wtsud_patch_addr, JUMP_SIZE, oldProtect, &oldProtect);
|
|
|
|
unload_ctr_dec();
|
|
}
|
|
|
|
static void _unityplayer_callback(HMODULE unityModule) {
|
|
if (utils_env_enabled("SRFIX_DISABLE")) {
|
|
msg_info_a("Shared resources fix disabled. The game may not work");
|
|
return;
|
|
}
|
|
|
|
// Remove dependency on shared resources by patching WriteTextureStatisticUserData
|
|
unload_ctr_inc();
|
|
|
|
wtsud_patch_addr = ((char*)unityModule) + WTSUD_PATCH_OFFSET;
|
|
|
|
DWORD oldProtect;
|
|
VirtualProtect(wtsud_patch_addr, JUMP_SIZE, PAGE_EXECUTE_READWRITE, &oldProtect);
|
|
|
|
// Save original bytes
|
|
memcpy(wtsud_original_bytes, wtsud_patch_addr, JUMP_SIZE);
|
|
|
|
// Write jump
|
|
const char JUMP_INST[] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00 }; // jmp [$ + 6]
|
|
memcpy(wtsud_patch_addr, JUMP_INST, sizeof(JUMP_INST));
|
|
|
|
// Write destination address
|
|
void *destAddr = &_wtsud_stub;
|
|
memcpy(wtsud_patch_addr + sizeof(JUMP_INST), &destAddr, sizeof(destAddr));
|
|
|
|
VirtualProtect(wtsud_patch_addr, JUMP_SIZE, oldProtect, &oldProtect);
|
|
}
|
|
|
|
void hsr_fill_data(struct game_data *buf) {
|
|
uint32_t crc = utils_file_crc32c("UnityPlayer.dll");
|
|
|
|
enum game_id id = GAME_INVALID;
|
|
for (size_t i = 0; i < sizeof(HSR_REGIONS) / sizeof(struct crc_id_pair); i++) {
|
|
if (HSR_REGIONS[i].crc == crc) {
|
|
id = HSR_REGIONS[i].id;
|
|
}
|
|
}
|
|
|
|
if (id == GAME_INVALID) {
|
|
msg_err_a("Invalid UnityPlayer.dll checksum: %x", crc);
|
|
}
|
|
|
|
buf->id = id;
|
|
buf->name = HSR_NAME;
|
|
buf->assembly_name = HSR_ASSEMBLY_NAME;
|
|
buf->tp6_section_name = HSR_TP6_SECTION_NAME;
|
|
buf->tvm_section_name = HSR_TVM_SECTION_NAME;
|
|
|
|
buf->unityplayer_callback = &_unityplayer_callback;
|
|
}
|