forked from Popn_Tools/popnhax
Compare commits
3 Commits
d17bd63f3a
...
60f1b172ef
Author | SHA1 | Date | |
---|---|---|---|
60f1b172ef | |||
f5efc561c0 | |||
d23931f7f7 |
1
dist/popnhax/popnhax.xml
vendored
1
dist/popnhax/popnhax.xml
vendored
@ -99,7 +99,6 @@
|
||||
<!-- PLEASE USE OFFLINE ONLY -->
|
||||
<practice_mode __type="bool">0</practice_mode>
|
||||
<!-- Press 9 on option select screen to go back to song selection (requires quick_retire) -->
|
||||
<!-- Note: causes issues with sounds on song select -->
|
||||
<back_to_song_select __type="bool">0</back_to_song_select>
|
||||
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -986,6 +986,13 @@ uint8_t g_srambypass = 0;
|
||||
void (*real_option_screen_later)();
|
||||
void backtosongselect_option_screen()
|
||||
{
|
||||
/* cannot use backtosongselect when not in normal mode */
|
||||
__asm("push eax");
|
||||
__asm("call %0"::"a"(popn22_is_normal_mode));
|
||||
__asm("test al,al");
|
||||
__asm("pop eax");
|
||||
__asm("je exit_back_select");
|
||||
|
||||
__asm("push ecx\n");
|
||||
__asm("mov ecx, %0\n": :"m"(g_addr_icca));
|
||||
__asm("mov ebx, [ecx]\n");
|
||||
@ -1068,6 +1075,13 @@ void backtosongselect_option_screen_auto_leave()
|
||||
void (*real_option_screen_yellow)();
|
||||
void backtosongselect_option_yellow()
|
||||
{
|
||||
/* cannot use backtosongselect when not in normal mode */
|
||||
__asm("push eax");
|
||||
__asm("call %0"::"a"(popn22_is_normal_mode));
|
||||
__asm("test al,al");
|
||||
__asm("pop eax");
|
||||
__asm("je exit_back_select_yellow");
|
||||
|
||||
__asm("push ecx\n");
|
||||
__asm("mov ecx, %0\n": :"m"(g_addr_icca));
|
||||
__asm("mov ebx, [ecx]\n");
|
||||
@ -1412,7 +1426,7 @@ void quickexit_result_loop()
|
||||
__asm("push eax\n");
|
||||
__asm("push ecx\n");
|
||||
__asm("push edx\n");
|
||||
__asm("mov eax, 0x1F\n"); //"exit menu" sound fx
|
||||
__asm("mov eax, 0x16\n"); //"okay" sound fx
|
||||
__asm("push 0\n");
|
||||
__asm("call %0\n"::"D"(playsramsound_func));
|
||||
__asm("add esp, 4\n");
|
||||
@ -1435,7 +1449,7 @@ void quickexit_result_loop()
|
||||
__asm("push eax\n");
|
||||
__asm("push ecx\n");
|
||||
__asm("push edx\n");
|
||||
__asm("mov eax, 0x09\n"); //"bring menu" sound fx
|
||||
__asm("mov eax, 0x16\n"); //"okay" sound fx
|
||||
__asm("push 0\n");
|
||||
__asm("call %0\n"::"D"(playsramsound_func));
|
||||
__asm("add esp, 4\n");
|
||||
@ -3287,6 +3301,18 @@ static bool patch_quick_retire(bool pfree)
|
||||
(void **)&real_stage_increment);
|
||||
}
|
||||
|
||||
/* pfree already retrieves this function
|
||||
*/
|
||||
{
|
||||
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: quick retire: 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* instant retire with numpad 9 in song */
|
||||
|
@ -26,7 +26,7 @@ static void badCharHeuristic(const unsigned char *str, int size, int* badchar) {
|
||||
|
||||
#define DEBUG_SEARCH 0
|
||||
|
||||
int _search(unsigned char *haystack, size_t haystack_size, const unsigned char *needle, size_t needle_size, int orig_offset, int debug) {
|
||||
int _search(unsigned char *haystack, size_t haystack_size, const unsigned char *needle, size_t needle_size, int orig_offset, bool wildcards, int debug) {
|
||||
int badchar[NO_OF_CHARS];
|
||||
|
||||
badCharHeuristic(needle, needle_size, badchar);
|
||||
@ -46,12 +46,21 @@ int _search(unsigned char *haystack, size_t haystack_size, const unsigned char *
|
||||
LOG("pat...");
|
||||
for (size_t i = 0; i < needle_size; i++)
|
||||
{
|
||||
if (wildcards && needle[i] == '?')
|
||||
LOG("** ");
|
||||
else
|
||||
LOG("%02x ", needle[i]);
|
||||
}
|
||||
LOG("\n");
|
||||
}
|
||||
while (j >= 0 && needle[j] == haystack[orig_offset + s + j])
|
||||
if ( wildcards )
|
||||
{
|
||||
while (j >= 0 && ( needle[j] == '?' || needle[j] == haystack[orig_offset + s + j]) )
|
||||
j--;
|
||||
} else {
|
||||
while (j >= 0 && ( needle[j] == haystack[orig_offset + s + j]) )
|
||||
j--;
|
||||
}
|
||||
|
||||
if (j < 0) {
|
||||
if (debug)
|
||||
@ -70,11 +79,21 @@ int _search(unsigned char *haystack, size_t haystack_size, const unsigned char *
|
||||
}
|
||||
|
||||
int search(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset) {
|
||||
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, 0);
|
||||
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, false, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
int wildcard_search(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset) {
|
||||
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, true, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
int search_debug(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset) {
|
||||
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, 2);
|
||||
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, false, 2);
|
||||
return res;
|
||||
}
|
||||
|
||||
int wildcard_search_debug(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset) {
|
||||
int res = _search((unsigned char*) haystack, haystack_size, (const unsigned char *)needle, needle_size, orig_offset, true, 2);
|
||||
return res;
|
||||
}
|
@ -3,5 +3,7 @@
|
||||
|
||||
int search(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
||||
int search_debug(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
||||
int wildcard_search(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
||||
int wildcard_search_debug(char *haystack, size_t haystack_size, const char *needle, size_t needle_size, size_t orig_offset);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user