diff --git a/game_payload/include/game.h b/game_payload/include/game.h index d8a1959..cfb8b66 100644 --- a/game_payload/include/game.h +++ b/game_payload/include/game.h @@ -5,7 +5,10 @@ enum game_id { GAME_INVALID, - GAME_HI3_GLB + GAME_HI3_GLB, + + GAME_HSR_OS, + GAME_HSR_CN }; struct game_data { @@ -19,3 +22,4 @@ struct game_data { void game_detect(struct game_data *buf); void hi3_fill_data(struct game_data *buf); +void hsr_fill_data(struct game_data *buf); diff --git a/game_payload/meson.build b/game_payload/meson.build index 29847d2..938d27c 100644 --- a/game_payload/meson.build +++ b/game_payload/meson.build @@ -6,6 +6,7 @@ sources = [ 'src/pe.c', 'src/game.c', 'src/hi3.c', + 'src/hsr.c', 'src/utils.c', 'src/err.c', diff --git a/game_payload/src/game.c b/game_payload/src/game.c index b32896b..e711f94 100644 --- a/game_payload/src/game.c +++ b/game_payload/src/game.c @@ -2,17 +2,31 @@ #include +typedef void (*fill_fn)(struct game_data *buf); + +struct name_fn_pair { + const char *name; + fill_fn fill; +}; + +const struct name_fn_pair GAMES[] = { + { "bh3.exe", &hi3_fill_data }, + { "starrail.exe", &hsr_fill_data } +}; + void game_detect(struct game_data *buf) { - wchar_t exePath[MAX_PATH]; - GetModuleFileNameW(NULL, exePath, MAX_PATH); + char exePath[MAX_PATH]; + GetModuleFileNameA(NULL, exePath, MAX_PATH); - wchar_t *exeName = wcsrchr(exePath, L'\\') + 1; - wcslwr(exeName); + char *exeName = strrchr(exePath, '\\') + 1; + strlwr(exeName); - // Only HI3 is supported for now - if (wcscmp(exeName, L"bh3.exe") == 0) { - hi3_fill_data(buf); - } else { - err_mb_w(L"Unknown game: %ls", exeName); + for (size_t i = 0; i < sizeof(GAMES) / sizeof(struct name_fn_pair); i++) { + if (strcmp(exeName, GAMES[i].name) == 0) { + GAMES[i].fill(buf); + return; + } } + + err_mb_a("Unknown game: %s", exeName); } diff --git a/game_payload/src/hi3.c b/game_payload/src/hi3.c index 3aaf55c..c00e9bf 100644 --- a/game_payload/src/hi3.c +++ b/game_payload/src/hi3.c @@ -3,10 +3,10 @@ #include -const char *HI3_NAME = "BH3"; -const char *HI3_ASSEMBLY_PATH = "BH3_Data/Native/UserAssembly.dll"; -const char *HI3_TP6_SECTION_NAME = ".bh3"; -const char *HI3_TVM_SECTION_NAME = ".tvm0"; +const char *HI3_NAME = "BH3"; +const char *HI3_ASSEMBLY_PATH = "BH3_Data/Native/UserAssembly.dll"; +const char *HI3_TP6_SECTION_NAME = ".bh3"; +const char *HI3_TVM_SECTION_NAME = ".tvm0"; struct crc_id_pair { uint32_t crc; diff --git a/game_payload/src/hsr.c b/game_payload/src/hsr.c new file mode 100644 index 0000000..5c54f8c --- /dev/null +++ b/game_payload/src/hsr.c @@ -0,0 +1,42 @@ +#include +#include + +#include + +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 +}; + +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; +}