From d23931f7f7057a009a03290cd2a763c570295fea Mon Sep 17 00:00:00 2001 From: CrazyRedMachine Date: Thu, 6 Jun 2024 09:55:31 +0200 Subject: [PATCH] fix local favorite end of credit crash with guest --- dist/popnhax/popnhax.xml | 1 - popnhax/custom_categs.cc | 60 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/dist/popnhax/popnhax.xml b/dist/popnhax/popnhax.xml index 704fb4f..fbf369b 100644 --- a/dist/popnhax/popnhax.xml +++ b/dist/popnhax/popnhax.xml @@ -99,7 +99,6 @@ 0 - 0 diff --git a/popnhax/custom_categs.cc b/popnhax/custom_categs.cc index d508588..3990f76 100644 --- a/popnhax/custom_categs.cc +++ b/popnhax/custom_categs.cc @@ -197,6 +197,7 @@ void hook_remove_from_favorite() real_remove_from_favorite(); } +extern bool (*popn22_is_normal_mode)(); //this replaces the category handling function ( add_song_in_list is a subroutine called by the game ) void (*real_categ_favorite)(); void categ_inject_favorites() @@ -205,7 +206,13 @@ void categ_inject_favorites() __asm("push ecx\n"); __asm("push edx\n"); - //fake login if necessary + //fake login if necessary, only in normal mode + __asm("push eax"); + __asm("call %0"::"a"(popn22_is_normal_mode)); + __asm("test al,al"); + __asm("pop eax"); + __asm("je skip_fake_login"); + __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 @@ -680,6 +687,31 @@ static bool patch_custom_track_format(const char *game_dll_fn) { return true; } +void (*real_remove_fake_login)(); +void hook_remove_fake_login() +{ + //getPlayerDataAddr was just called so eax contains _playerdata_addr + __asm("push ecx\n"); + + __asm("lea ecx, [eax+0x08]\n"); //friendid offset + __asm("mov ecx, [ecx]\n"); + __asm("cmp ecx, 0x61666564\n"); //defa + __asm("jne skip_remove_login\n"); + __asm("lea ecx, [eax+0x0C]\n"); //friendid offset + __asm("mov ecx, [ecx]\n"); + __asm("cmp ecx, 0x00746C75\n"); //ult + __asm("jne skip_remove_login\n"); + + //fake login detected, cleanup + __asm("lea ecx, [eax+0x1A5]\n"); //login status offset + __asm("mov dword ptr [ecx], 0x00000000\n"); + + __asm("skip_remove_login:\n"); + + __asm("pop ecx\n"); + real_remove_fake_login(); +} + static bool patch_favorite_categ(const char *game_dll_fn) { DWORD dllSize = 0; @@ -711,6 +743,19 @@ static bool patch_favorite_categ(const char *game_dll_fn) { MH_CreateHook((LPVOID)function_addr, (LPVOID)categ_inject_favorites, (void **)&real_categ_favorite); } + + //only active in normal mode + { + int64_t pattern_offset = search(data, dllSize, "\x83\xC4\x0C\x33\xC0\xC3\xCC\xCC\xCC\xCC\xE8", 11, 0); + if (pattern_offset == -1) { + LOG("popnhax: local_favorites: cannot find is_normal_mode function, fallback to best effort (active in all modes)\n"); + } + else + { + popn22_is_normal_mode = (bool(*)()) (data + pattern_offset + 0x0A); + } + } + //categ_inject_favorites will need to force "logged in" status (for result screen) { //this is the same function used in score challenge patch, checking if we're logged in... but now we just directly retrieve the address @@ -722,6 +767,19 @@ static bool patch_favorite_categ(const char *game_dll_fn) { g_playerdata_ptr_addr = (*(uint32_t *)(data + pattern_offset + 0x25)); } + //and I need to remove the fake "logged in" status on credit end to prevent a crash + { + int64_t pattern_offset = search(data, dllSize, "\x84\xC0\x74\x07\xBB\x01\x00\x00\x00\xEB\x02\x33\xDB", 13, 0); + if (pattern_offset == -1) { + LOG("popnhax: local_favorites: cannot find end of credit check if logged function\n"); + return false; + } + + uint64_t patch_addr = (int64_t)data + pattern_offset - 0x05; + + MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_remove_fake_login, + (void **)&real_remove_fake_login); + } //hook result screen to replace 3 functions {