2023-06-08 15:36:22 +00:00
|
|
|
#include <utils.h>
|
|
|
|
#include <err.h>
|
|
|
|
|
|
|
|
#include <game.h>
|
|
|
|
|
|
|
|
const char *HSR_NAME = "StarRail";
|
|
|
|
const char *HSR_ASSEMBLY_PATH = "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
|
|
|
|
|
|
|
|
{ 0x2df53005, GAME_HSR_OS }, // os v1.1.0
|
|
|
|
{ 0x3e644d26, GAME_HSR_CN } // cn v1.1.0
|
|
|
|
};
|
|
|
|
|
2023-06-08 17:13:21 +00:00
|
|
|
static void _unityplayer_callback(HMODULE unityModule) {
|
|
|
|
// Disable shared resources
|
|
|
|
|
|
|
|
// Temporarily hardcoded offset
|
|
|
|
// v1.1.0, same for os and cn
|
|
|
|
unsigned char *srAddr = ((unsigned char*)unityModule) + 0x16430;
|
|
|
|
|
|
|
|
DWORD oldProtect;
|
|
|
|
VirtualProtect(srAddr, 1, PAGE_EXECUTE_READWRITE, &oldProtect);
|
|
|
|
|
|
|
|
*srAddr = 0xC3; // ret
|
|
|
|
|
|
|
|
VirtualProtect(srAddr, 1, oldProtect, &oldProtect);
|
|
|
|
}
|
|
|
|
|
2023-06-08 15:36:22 +00:00
|
|
|
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) {
|
|
|
|
err_mb_a("Invalid UnityPlayer.dll checksum: %d", crc);
|
|
|
|
}
|
|
|
|
|
|
|
|
buf->id = id;
|
|
|
|
buf->name = HSR_NAME;
|
|
|
|
buf->assembly_path = HSR_ASSEMBLY_PATH;
|
|
|
|
buf->tp6_section_name = HSR_TP6_SECTION_NAME;
|
|
|
|
buf->tvm_section_name = HSR_TVM_SECTION_NAME;
|
2023-06-08 17:13:21 +00:00
|
|
|
|
|
|
|
buf->unityplayer_callback = &_unityplayer_callback;
|
2023-06-08 15:36:22 +00:00
|
|
|
}
|