3
0
mirror of https://github.com/CrazyRedMachine/popnhax.git synced 2024-11-23 22:00:57 +01:00

fix custom categ, quick retry

This commit is contained in:
CrazyRedMachine 2024-10-02 21:17:09 +02:00
parent f406794e07
commit 8f500c7dd0
5 changed files with 125 additions and 43 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -578,10 +578,11 @@ void hook_categ_title_printf()
real_categ_title_printf(); real_categ_title_printf();
} }
uint32_t g_max_categ_idx = 0;
void (*real_categ_listing)(); void (*real_categ_listing)();
void hook_categ_listing() void hook_categ_listing()
{ {
__asm("cmp eax, 0x11\n"); __asm("cmp eax, [_g_max_categ_idx]\n");
__asm("jne categ_listing_ok\n"); __asm("jne categ_listing_ok\n");
__asm("cmp byte ptr ds:[_g_subcategmode], 1\n"); __asm("cmp byte ptr ds:[_g_subcategmode], 1\n");
__asm("jne skip_push\n"); __asm("jne skip_push\n");
@ -761,8 +762,11 @@ static bool patch_favorite_categ(const char *game_dll_fn, bool with_numpad9_patc
{ {
int64_t pattern_offset = search(data, dllSize, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8, 0); int64_t pattern_offset = search(data, dllSize, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: local_favorites: cannot find category jump table\n"); pattern_offset = search(data, dllSize, "\x83\xF8\x11\x77\x7C\xFF\x24\x85", 8, 0); // jam&fizz
return false; if (pattern_offset == -1) {
LOG("popnhax: local_favorites: cannot find category jump table\n");
return false;
}
} }
uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x05 + 0x5A); uint64_t function_call_addr = (int64_t)(data + pattern_offset + 0x05 + 0x5A);
@ -876,6 +880,31 @@ local_favorite_ok:
return true; return true;
} }
void (*real_get_categ_name)();
void hook_get_categ_name()
{
//eax is index, needs to return pointer to categ name string in eax
__asm("cmp eax, [_g_max_categ_idx]\n");
__asm("jne skip_hook_categ_name\n");
__asm("mov eax, [_g_categname]\n");
__asm("ret");
__asm("skip_hook_categ_name:\n");
real_get_categ_name();
}
void (*real_get_icon_name)();
void hook_get_icon_name()
{
//eax is index, needs to return pointer to categ icon string in eax
__asm("cmp eax, [_g_max_categ_idx]\n");
__asm("jne skip_hook_categ_icon\n");
__asm("mov eax, [_g_categicon]\n");
__asm("ret");
__asm("skip_hook_categ_icon:\n");
real_get_icon_name();
}
static bool patch_custom_categ(const char *game_dll_fn, uint16_t min_id) { static bool patch_custom_categ(const char *game_dll_fn, uint16_t min_id) {
DWORD dllSize = 0; DWORD dllSize = 0;
@ -899,12 +928,17 @@ static bool patch_custom_categ(const char *game_dll_fn, uint16_t min_id) {
// patch category handling jumptable to add our processing // 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); int64_t pattern_offset = search(data, dllSize, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8, 0);
uint8_t jump_size = 0x75; //as seen in pattern
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: custom_categ: cannot find category jump table\n"); jump_size = 0x7C; //as seen in pattern
return false; pattern_offset = search(data, dllSize, "\x83\xF8\x11\x77\x7C\xFF\x24\x85", 8, 0); // jam&fizz
if (pattern_offset == -1) {
LOG("popnhax: custom_categ: cannot find category jump table\n");
return false;
}
} }
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x05 + 0x75; uint64_t patch_addr = (int64_t)data + pattern_offset + 0x05 + jump_size; //hook at the end of jump table
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_listing, MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_listing,
(void **)&real_categ_listing); (void **)&real_categ_listing);
@ -967,7 +1001,7 @@ static bool patch_custom_categ(const char *game_dll_fn, uint16_t min_id) {
//force rearm songlist creation so that it keeps working //force rearm songlist creation so that it keeps working
{ {
int64_t pattern_offset = search(data, dllSize, "\x33\xC9\xB8\x12\x00\x00\x00\xBA", 8, 0); int64_t pattern_offset = search(data, dllSize, "\xB8\x12\x00\x00\x00\xBA\x2B\x00\x00\x00\x89\x44\x24", 13, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: custom_categ: cannot find category generation function\n"); LOG("popnhax: custom_categ: cannot find category generation function\n");
return false; return false;
@ -976,51 +1010,80 @@ static bool patch_custom_categ(const char *game_dll_fn, uint16_t min_id) {
uint64_t patch_addr = (int64_t)data + pattern_offset; uint64_t patch_addr = (int64_t)data + pattern_offset;
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_reinit_songlist, MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_categ_reinit_songlist,
(void **)&real_categ_reinit_songlist); (void **)&real_categ_reinit_songlist);
} }
} }
//bump category count from 16 to 17 //bump category count from 16 to 17
g_max_categ_idx = 17;
if (!find_and_patch_hex(game_dll_fn, "\x83\xFE\x11\x0F\x82\x59\xFE\xFF\xFF", 9, 2, "\x12", 1)) if (!find_and_patch_hex(game_dll_fn, "\x83\xFE\x11\x0F\x82\x59\xFE\xFF\xFF", 9, 2, "\x12", 1))
{ {
return false; g_max_categ_idx++;
if (!find_and_patch_hex(game_dll_fn, "\x83\xFF\x12\x0F\x82\x71\xFE\xFF\xFF", 9, 2, "\x13", 1)) //jam&fizz
{
LOG("popnhax: custom_categ: cannot bump category count\n");
return false;
}
} }
//patch getCategName for a 17th entry //patch getCategName for a 17th entry
{ {
//make array one cell larger //make array one cell larger
if (!find_and_patch_hex(game_dll_fn, "\x83\xEC\x44\x98\xC7\x04\x24", 7, 2, "\x48", 1)) int64_t pattern_offset = find_and_patch_hex(game_dll_fn, "\x83\xEC\x44\x98\xC7\x04\x24", 7, 2, "\x48", 1);
if (!pattern_offset)
{ {
return false; pattern_offset = find_and_patch_hex(game_dll_fn, "\x83\xEC\x48\x98\xC7\x04\x24", 7, 2, "\x4C", 1);
if (!pattern_offset)
{
LOG("popnhax: custom_categ: cannot patch getCategName\n");
return false;
}
} }
if (!find_and_patch_hex(game_dll_fn, "\x8B\x04\x84\x83\xC4\x44\xC3\xCC", 8, 5, "\x48", 1))
{
if (!find_and_patch_hex(game_dll_fn, "\x8B\x04\x84\x83\xC4\x48\xC3\xCC", 8, 5, "\x4C", 1))
{
LOG("popnhax: custom_categ: cannot patch getCategName (2)\n");
return false;
}
}
//add the new name //add the new name
uint32_t categname_str_addr = (uint32_t)g_categname; uint64_t patch_addr = (int64_t)data + pattern_offset;
char categname_patch_string[] = "\xC7\x44\x24\x44\x20\x00\x28\x10\x8B\x04\x84\x83\xC4\x48\xC3";
memcpy(categname_patch_string+4, &categname_str_addr, 4); MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_get_categ_name,
if (!find_and_patch_hex(game_dll_fn, "\x8B\x04\x84\x83\xC4\x44\xC3\xCC", 8, 0, categname_patch_string, 15)) (void **)&real_get_categ_name);
{
return false;
}
} }
//patch getIconName for a 17th entry //patch getIconName for a 17th entry
{ {
if (!find_and_patch_hex(game_dll_fn, "\x83\xEC\x44\x98\xC7\x04\x24", 7, 2, "\x48", 1)) //2nd occurrence since first one just got patched int64_t pattern_offset = find_and_patch_hex(game_dll_fn, "\x83\xEC\x44\x98\xC7\x04\x24", 7, 2, "\x48", 1); //2nd occurrence since first one just got patched
if (!pattern_offset)
{ {
return false; pattern_offset = find_and_patch_hex(game_dll_fn, "\x83\xEC\x48\x98\xC7\x04\x24", 7, 2, "\x4C", 1);
if (!pattern_offset)
{
LOG("popnhax: custom_categ: cannot patch getIconName\n");
return false;
}
}
if (!find_and_patch_hex(game_dll_fn, "\x8B\x04\x84\x83\xC4\x44\xC3\xCC", 8, 5, "\x48", 1))
{
if (!find_and_patch_hex(game_dll_fn, "\x8B\x04\x84\x83\xC4\x48\xC3\xCC", 8, 5, "\x4C", 1))
{
LOG("popnhax: custom_categ: cannot patch getIconName (2)\n");
return false;
}
} }
//add the new icon name //add the new icon name
uint32_t categicon_str_addr = (uint32_t)g_categicon; uint64_t patch_addr = (int64_t)data + pattern_offset;
char categicon_patch_string[] = "\xC7\x44\x24\x44\xDC\x00\x28\x10\x8B\x04\x84\x83\xC4\x48\xC3";
memcpy(categicon_patch_string+4, &categicon_str_addr, 4); MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_get_icon_name,
if (!find_and_patch_hex(game_dll_fn, "\x8B\x04\x84\x83\xC4\x44\xC3\xCC", 8, 0, categicon_patch_string, 15)) (void **)&real_get_icon_name);
{
return false;
}
} }
char formatted_title[128]; char formatted_title[128];
sprintf(formatted_title, g_categformat, g_categname); sprintf(formatted_title, g_categformat, g_categname);
LOG("popnhax: custom %s \"%s\" injected", g_subcategmode? "subcategories":"category", formatted_title); LOG("popnhax: custom %s \"%s\" injected", g_subcategmode? "subcategories":"category", formatted_title);
if (min_id) if (min_id)
LOG(" (for songids >= %d)", min_id); LOG(" (for songids >= %d)", min_id);

View File

@ -1929,8 +1929,11 @@ static bool patch_normal0()
{ {
int64_t pattern_offset = search(data, dllSize, "\x83\xC4\x08\x8B\xF8\x89\x7C\x24\x3C", 9, 0); int64_t pattern_offset = search(data, dllSize, "\x83\xC4\x08\x8B\xF8\x89\x7C\x24\x3C", 9, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: Couldn't find song list display function\n"); pattern_offset = search(data, dllSize, "\x83\xC4\x08\x8B\xF8\x89\x7C\x24\x44", 9, 0);
return false; if (pattern_offset == -1) {
LOG("popnhax: normal0: Couldn't find song list display function\n");
return false;
}
} }
uint64_t patch_addr = (int64_t)data + pattern_offset; uint64_t patch_addr = (int64_t)data + pattern_offset;
@ -3536,12 +3539,18 @@ static bool patch_quick_retire(bool pfree)
/* retrieve songstart function pointer for quick retry */ /* retrieve songstart function pointer for quick retry */
{ {
int64_t pattern_offset = search(data, dllSize, "\xE9\x0C\x01\x00\x00\x8B\x85", 7, 0); int64_t pattern_offset = search(data, dllSize, "\xE9\x0C\x01\x00\x00\x8B\x85", 7, 0);
int delta = -4;
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: quick retry: cannot retrieve song start function\n"); delta = 18;
return false; pattern_offset = search(data, dllSize, "\x6A\x00\xB8\x17\x00\x00\x00\xE8", 8, 0);
if (pattern_offset == -1) {
LOG("popnhax: quick retry: cannot retrieve song start function\n");
return false;
}
} }
uint64_t patch_addr = (int64_t)data + pattern_offset - 4;
uint64_t patch_addr = (int64_t)data + pattern_offset + delta;
g_startsong_addr = *(uint32_t*)(patch_addr); g_startsong_addr = *(uint32_t*)(patch_addr);
} }
@ -4834,8 +4843,11 @@ static bool patch_score_challenge()
{ {
int64_t pattern_offset = search(data, dllSize, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8, 0); int64_t pattern_offset = search(data, dllSize, "\x83\xF8\x10\x77\x75\xFF\x24\x85", 8, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: score challenge: cannot find category building loop\n"); pattern_offset = search(data, dllSize, "\x83\xF8\x11\x77\x7C\xFF\x24\x85", 8, 0); // jam&fizz
return false; if (pattern_offset == -1) {
LOG("popnhax: score challenge: cannot find category building loop\n");
return false;
}
} }
uint64_t patch_addr = (int64_t)data + pattern_offset + 0x66; uint64_t patch_addr = (int64_t)data + pattern_offset + 0x66;
@ -6973,12 +6985,19 @@ static bool patch_record_mode(bool quickretire)
{ {
int64_t pattern_offset = search(data, dllSize, int64_t pattern_offset = search(data, dllSize,
"\xE9\x0C\x01\x00\x00\x8B\x85", 7, 0); "\xE9\x0C\x01\x00\x00\x8B\x85", 7, 0);
int delta = -4;
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: record reload: cannot retrieve song start function\n"); delta = 18;
return false; pattern_offset = search(data, dllSize,
"\x6A\x00\xB8\x17\x00\x00\x00\xE8", 8, 0);
if (pattern_offset == -1) {
LOG("popnhax: record reload: cannot retrieve song start function\n");
return false;
}
} }
uint64_t patch_addr = (int64_t)data + pattern_offset - 4; uint64_t patch_addr = (int64_t)data + pattern_offset + delta;
g_startsong_addr = *(uint32_t*)(patch_addr); g_startsong_addr = *(uint32_t*)(patch_addr);
} }
/* instant launch song with numpad 8 on option select (hold 8 during song for quick retry) */ /* instant launch song with numpad 8 on option select (hold 8 during song for quick retry) */

View File

@ -101,13 +101,13 @@ void find_and_patch_string(const char *dllFilename, const char *input_string, co
} }
} }
bool find_and_patch_hex(const char *dllFilename, const char *find, uint8_t find_size, int64_t shift, const char *replace, uint8_t replace_size) { int64_t find_and_patch_hex(const char *dllFilename, const char *find, uint8_t find_size, int64_t shift, const char *replace, uint8_t replace_size) {
DWORD dllSize = 0; DWORD dllSize = 0;
char *data = getDllData(dllFilename, &dllSize); char *data = getDllData(dllFilename, &dllSize);
int64_t pattern_offset = search(data, dllSize, find, find_size, 0); int64_t pattern_offset = search(data, dllSize, find, find_size, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
return false; return 0;
} }
#if DEBUG == 1 #if DEBUG == 1
@ -137,6 +137,6 @@ bool find_and_patch_hex(const char *dllFilename, const char *find, uint8_t find_
} }
#endif #endif
return true; return pattern_offset;
} }

View File

@ -14,7 +14,7 @@ bool offset_to_rva(const char *dllFilename, uint32_t offset, uint32_t *rva);
void patch_memory(uint64_t patch_addr, char *data, size_t len); void patch_memory(uint64_t patch_addr, char *data, size_t len);
bool find_and_patch_hex(const char *dllFilename, const char *find, uint8_t find_size, int64_t shift, const char *replace, uint8_t replace_size); int64_t find_and_patch_hex(const char *dllFilename, const char *find, uint8_t find_size, int64_t shift, const char *replace, uint8_t replace_size);
void find_and_patch_string(const char *dllFilename, const char *input_string, const char *new_string); void find_and_patch_string(const char *dllFilename, const char *input_string, const char *new_string);
#endif #endif