From e7484fad5e6c3ccc1c09c30da925943999872179 Mon Sep 17 00:00:00 2001 From: CrazyRedMachine Date: Wed, 2 Oct 2024 21:17:09 +0200 Subject: [PATCH] fix local favorites, tachi rivals, rework score challenge --- popnhax/custom_categs.cc | 27 +++++++++++++++++++++++---- popnhax/dllmain.cc | 20 ++++++++++++++++---- popnhax/tachi.cc | 22 +++++++++++++++++++--- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/popnhax/custom_categs.cc b/popnhax/custom_categs.cc index e4849e4..54c431f 100644 --- a/popnhax/custom_categs.cc +++ b/popnhax/custom_categs.cc @@ -27,7 +27,8 @@ typedef struct songlist_s { } songlist_t; uint8_t g_game_version; -uint32_t g_playerdata_ptr_addr; //pointer to the playerdata memory zone (offset 0x08 is popn friend ID as ascii (12 char long), offset 0x1A5 is "is logged in" flag) +uint32_t g_playerdata_ptr_addr; //pointer to the playerdata memory zone (offset 0x08 is popn friend ID as ascii (12 char long), offset g_loggedin_offset is "is logged in" flag) +uint32_t g_loggedin_offset; char *g_current_friendid; uint32_t g_current_songid; @@ -212,12 +213,13 @@ void categ_inject_favorites() __asm("mov ecx, dword ptr [_g_playerdata_ptr_addr]\n"); __asm("mov edx, [ecx]\n"); - __asm("add edx, 0x1A5\n"); //offset where result screen is checking to decide if the favorite option should be displayed/handled + __asm("add edx, [_g_loggedin_offset]\n"); //offset where result screen is checking to decide if the favorite option should be displayed/handled __asm("mov ecx, [edx]\n"); __asm("cmp ecx, 0\n"); __asm("jne skip_fake_login\n"); __asm("mov dword ptr [edx], 0xFF000001\n"); - __asm("sub edx, 0x19D\n"); //back to popn friendid offset + __asm("sub edx, [_g_loggedin_offset]\n"); + __asm("add edx, 8\n"); //back to popn friendid offset __asm("mov dword ptr [edx], 0x61666564\n"); // "defa" __asm("add edx, 0x04\n"); __asm("mov dword ptr [edx], 0x00746C75\n"); // "ult" @@ -728,7 +730,10 @@ void hook_remove_fake_login() __asm("jne skip_remove_login\n"); //fake login detected, cleanup - __asm("lea ecx, [eax+0x1A5]\n"); //login status offset + __asm("push ebx\n"); + __asm("mov ebx, [_g_loggedin_offset]\n"); + __asm("lea ecx, [eax+ebx]\n"); //login status offset + __asm("pop ebx\n"); __asm("mov dword ptr [ecx], 0x00000000\n"); __asm("skip_remove_login:\n"); @@ -753,6 +758,20 @@ static bool patch_favorite_categ(const char *game_dll_fn, bool with_numpad9_patc add_song_in_list = (void (*)())(data + pattern_offset - 0x12); } + //retrieve logged in status offset from playerdata + { + int64_t pattern_offset = _search(data, dllSize, "\xBF\x07\x00\x00\x00\xC6\x85", 7, 0); + if (pattern_offset == -1) { + LOG("popnhax: local_favorites: cannot find result screen function\n"); + return false; + } + uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x1D); + uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01)); + uint64_t function_addr = function_call_addr+5+function_offset; + g_loggedin_offset = *(uint32_t*)(function_addr+2); + //LOG("LOGGED IN OFFSET IS %x\n",g_loggedin_offset); // 0x1A5 for popn27-, 0x22D for popn28 + } + // patch category handling jumptable to add our processing { int64_t pattern_offset = _search(data, dllSize, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8, 0); diff --git a/popnhax/dllmain.cc b/popnhax/dllmain.cc index 7c8539b..5a8f6f5 100644 --- a/popnhax/dllmain.cc +++ b/popnhax/dllmain.cc @@ -4744,7 +4744,8 @@ void score_challenge_retrieve_addr() void (*score_challenge_prep_songdata)(); void (*score_challenge_song_inject)(); -void (*score_challenge_test_if_logged1)(); +void (*score_challenge_retrieve_player_data)(); +void (*score_challenge_is_logged_in)(); void (*score_challenge_test_if_normal_mode)(); void (*real_make_score_challenge_category)(); @@ -4756,8 +4757,8 @@ void make_score_challenge_category() if (g_course_id_ptr && *g_course_id_ptr != 0) { - score_challenge_test_if_logged1(); - __asm("mov al, byte ptr ds:[eax+0x1A5]\n"); /* or look for this function 8A 80 A5 01 00 00 C3 CC */ + score_challenge_retrieve_player_data(); + score_challenge_is_logged_in(); __asm("test al, al\n"); __asm("je leave_score_challenge\n"); @@ -4837,7 +4838,18 @@ static bool patch_score_challenge() uint64_t patch_addr = (int64_t)data + pattern_offset + 0x24; - score_challenge_test_if_logged1 = (void(*)())patch_addr; + score_challenge_retrieve_player_data = (void(*)())patch_addr; + } + { + int64_t pattern_offset = _search(data, dllSize, "\xE8\xDB\xFF\xFF\xFF\x33\xC9\x84\xC0\x0F\x94", 11, 0); + if (pattern_offset == -1) { + LOG("popnhax: score challenge: cannot find check if logged function\n"); + return false; + } + + uint64_t patch_addr = (int64_t)data + pattern_offset - 0x20; + + score_challenge_is_logged_in = (void(*)())patch_addr; } { int64_t pattern_offset = _search(data, dllSize, "\xF7\xD8\x1B\xC0\x40\xC3\xE8", 7, 0); diff --git a/popnhax/tachi.cc b/popnhax/tachi.cc index 63b41f5..868fa0f 100644 --- a/popnhax/tachi.cc +++ b/popnhax/tachi.cc @@ -204,7 +204,8 @@ struct MemoryStruct g_curl_data; score_info_t *g_score_info; song_info_t *g_song_info; uint32_t *g_song_info_zone; -uint32_t g_playerdata_zone_addr; //pointer to the playerdata memory zone (offset 0x08 is popn friend ID as ascii (12 char long), offset 0x44 is rival count, offset 0x1A5 is "is logged in" flag) +uint32_t g_playerdata_zone_addr; //pointer to the playerdata memory zone (offset 0x08 is popn friend ID as ascii (12 char long), offset 0x44 is rival count, g_tachi_loggedin_offset is "is logged in" flag) +uint32_t g_tachi_loggedin_offset; uint16_t g_stage_offset = 0x504; // 0x508 in later games, overwritten when setting up the patches uint32_t g_need_conf_load = 1; uint32_t g_hidden_is_offset = 0; // mask "hidden" value behavior in score send @@ -925,12 +926,13 @@ void hook_mode_select_rival_inject() /* fake login to prevent rival handling bypass */ __asm("mov ecx, dword ptr [_g_playerdata_zone_addr]\n"); __asm("mov edx, [ecx]\n"); - __asm("add edx, 0x1A5\n"); //offset where result screen is checking to decide if the favorite option should be displayed/handled + __asm("add edx, [_g_tachi_loggedin_offset]\n"); //offset where result screen is checking to decide if the favorite option should be displayed/handled __asm("mov ecx, [edx]\n"); __asm("cmp ecx, 0\n"); __asm("jne skip_fake_login_tachi\n"); __asm("mov dword ptr [edx], 0xFF000001\n"); - __asm("sub edx, 0x19D\n"); //back to popn friendid offset + __asm("sub edx, [_g_tachi_loggedin_offset]\n"); + __asm("add edx, 8\n"); //back to popn friendid offset __asm("mov dword ptr [edx], 0x61666564\n"); // "defa" __asm("add edx, 0x04\n"); __asm("mov dword ptr [edx], 0x00746C75\n"); // "ult" @@ -1138,6 +1140,20 @@ bool patch_tachi_rivals(const char *dllFilename, bool scorehook) } /* hook after mode select logged in check */ + + //retrieve logged in status offset from playerdata + { + int64_t pattern_offset = _search(data, dllSize, "\xBF\x07\x00\x00\x00\xC6\x85", 7, 0); + if (pattern_offset == -1) { + LOG("popnhax: tachi rivals: cannot find result screen function\n"); + return false; + } + uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x1D); + uint32_t function_offset = *((uint32_t*)(function_call_addr +0x01)); + uint64_t function_addr = function_call_addr+5+function_offset; + g_tachi_loggedin_offset = *(uint32_t*)(function_addr+2); + //LOG("LOGGED IN OFFSET IS %x\n",g_tachi_loggedin_offset); // 0x1A5 for popn27-, 0x22D for popn28 + } { int64_t pattern_offset = _search(data, dllSize, "\x8B\xE5\x5D\xC3\x8B\xC6\xE8", 7, 0);