diff --git a/dist/popnhax/popnhax.xml b/dist/popnhax/popnhax.xml index 27731b6..854e416 100644 --- a/dist/popnhax/popnhax.xml +++ b/dist/popnhax/popnhax.xml @@ -50,6 +50,10 @@ 0 + + + 0 + 0 diff --git a/popnhax/config.h b/popnhax/config.h index b64642a..1b0fa17 100644 --- a/popnhax/config.h +++ b/popnhax/config.h @@ -6,6 +6,7 @@ struct popnhax_config { bool practice_mode; bool hidden_is_offset; + bool survival_gauge; bool show_offset; bool show_fast_slow; bool show_details; diff --git a/popnhax/dllmain.cc b/popnhax/dllmain.cc index 08273ff..9305223 100644 --- a/popnhax/dllmain.cc +++ b/popnhax/dllmain.cc @@ -90,6 +90,8 @@ struct popnhax_config config = {}; PSMAP_BEGIN(config_psmap, static) PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, hidden_is_offset, "/popnhax/hidden_is_offset") +PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, survival_gauge, + "/popnhax/survival_gauge") PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, show_fast_slow, "/popnhax/show_fast_slow") PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, show_details, @@ -4351,6 +4353,103 @@ bool patch_hispeed_auto(uint8_t mode, uint16_t default_bpm) return true; } +/* HARD GAUGE SURVIVAL*/ +uint8_t g_hard_gauge_selected = false; + +void (*real_survival_flag_hard_gauge)(); +void hook_survival_flag_hard_gauge() +{ + __asm("cmp bl, 0\n"); + __asm("jne no_hard_gauge\n"); + g_hard_gauge_selected = false; + __asm("cmp cl, 2\n"); + __asm("jne no_hard_gauge\n"); + g_hard_gauge_selected = true; + __asm("no_hard_gauge:\n"); + real_survival_flag_hard_gauge(); +} + +void (*real_survival_flag_hard_gauge_old)(); +void hook_survival_flag_hard_gauge_old() +{ + __asm("cmp bl, 0\n"); + __asm("jne no_hard_gauge_old\n"); + g_hard_gauge_selected = false; + __asm("cmp dl, 2\n"); + __asm("jne no_hard_gauge_old\n"); + g_hard_gauge_selected = true; + __asm("no_hard_gauge_old:\n"); + real_survival_flag_hard_gauge_old(); +} + +void (*real_check_survival_gauge)(); +void hook_check_survival_gauge() +{ + if ( g_hard_gauge_selected ) + { + __asm("mov al, 1\n"); + __asm("ret\n"); + } + real_check_survival_gauge(); +} + +bool patch_hard_gauge_survival() +{ + DWORD dllSize = 0; + char *data = getDllData(g_game_dll_fn, &dllSize); + + /* change is_survival_gauge function behavior */ + { + int64_t pattern_offset = search(data, dllSize, "\x33\xC9\x83\xF8\x04\x0F\x94\xC1\x8A\xC1", 10, 0); + if (pattern_offset == -1) { + LOG("popnhax: survival gauge: cannot find survival gauge check function\n"); + return false; + } + + uint64_t patch_addr = (int64_t)data + pattern_offset + 0x02; + + MH_CreateHook((LPVOID)(patch_addr), (LPVOID)hook_check_survival_gauge, + (void **)&real_check_survival_gauge); + } + + /* hook commit option to flag hard gauge being selected */ + { + /* find option commit function (unilab) */ + int64_t pattern_offset = search(data, dllSize, "\x89\x48\x0C\x8B\x56\x10\x89\x50\x10\x66\x8B\x4E\x14\x66\x89\x48\x14\x5B\xC3\xCC", 20, 0); + if (pattern_offset == -1) { + /* wasn't found, look for older function */ + int64_t first_loc = search(data, dllSize, "\x0F\xB6\xC3\x03\xCF\x8D", 6, 0); + + if (first_loc == -1) { + LOG("popnhax: survival gauge: cannot find option commit function (1)\n"); + return false; + } + + pattern_offset = search(data, 0x50, "\x89\x50\x0C", 3, first_loc); + + if (pattern_offset == -1) { + LOG("popnhax: survival gauge: cannot find option commit function (2)\n"); + return false; + } + + uint64_t patch_addr = (int64_t)data + pattern_offset; + MH_CreateHook((LPVOID)(patch_addr), (LPVOID)hook_survival_flag_hard_gauge_old, + (void **)&real_survival_flag_hard_gauge_old); + } + else + { + uint64_t patch_addr = (int64_t)data + pattern_offset; + MH_CreateHook((LPVOID)(patch_addr), (LPVOID)hook_survival_flag_hard_gauge, + (void **)&real_survival_flag_hard_gauge); + } + + } + + LOG("popnhax: hard gauge is survival gauge\n"); + + return true; +} + BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { @@ -4543,6 +4642,10 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv patch_hd_resolution(config.force_hd_resolution); } + if (config.survival_gauge) { + patch_hard_gauge_survival(); + } + if (config.hidden_is_offset){ patch_hidden_is_offset(); if (config.show_offset){